# Detection Strategies - New vs Update vs Review

Source: business-analyse step-00-init.md

This document describes the algorithms used in step-00-init.md to automatically detect the workflow type (new application, update, or review mode) and match user intent against existing business analyses.

---

## 1. Review Mode Detection

**Trigger:** `{feature_description}` starts with `-review` (with or without extra text)

### Algorithm

```javascript
function detectReviewMode(feature_description) {
  const isReviewMode = feature_description.trim().startsWith('-review');

  if (!isReviewMode) {
    return { mode: null };
  }

  // Scan docs/ for most recent application
  const applications = glob('docs/*/business-analyse/*/index.json')
    .map(path => ({
      path,
      metadata: readJSON(path).metadata,
      updatedAt: readJSON(path).metadata.updatedAt
    }))
    .sort((a, b) => b.updatedAt - a.updatedAt);

  if (applications.length === 0) {
    return {
      mode: 'review',
      error: 'NO_APPLICATIONS_FOUND',
      fix: 'Create an application first using /business-analyse'
    };
  }

  const latestApp = applications[0];
  const versionDir = path.dirname(latestApp.path);
  const reviewFilePath = path.join(versionDir, 'ba-review.json');

  if (!fs.existsSync(reviewFilePath)) {
    return {
      mode: 'review',
      error: 'NO_REVIEW_FILE',
      applicationName: latestApp.metadata.application,
      expectedPath: reviewFilePath,
      fix: `
        To create ba-review.json:
        1. Open ba-interactive.html in your browser
        2. Make your corrections
        3. Click "Sauvegarder corrections" button
        4. Save the downloaded ba-review.json in: ${versionDir}/
        5. Run /business-analyse -review again
      `
    };
  }

  return {
    mode: 'review',
    reviewJsonPath: reviewFilePath,
    applicationName: latestApp.metadata.application,
    docsDir: versionDir,
    nextStep: 'redirect-to-ba-review'
  };
}
```

### Decision Matrix

| Condition | Action |
|-----------|--------|
| `{feature_description}` starts with `-review` | Activate review mode detection |
| ba-review.json found | Redirect user to `/business-analyse-review` skill |
| ba-review.json NOT found | Display error with fix instructions, STOP |
| No applications exist | Display error, STOP |

### Error Messages

**Error 1: No Applications Found**
```
ERROR: No existing applications found in docs/

You must create an application first using:
  /business-analyse

Then generate ba-interactive.html, make corrections, and export ba-review.json.
```

**Error 2: No Review File**
```
ERROR: No ba-review.json found in docs/{app}/business-analyse/v{version}/

To create one:
1. Open the ba-interactive.html in your browser
2. Make your corrections
3. Click "Sauvegarder corrections" button
4. Save the downloaded ba-review.json in the version folder
5. Run /business-analyse -review again

Expected path: {expectedPath}
```

---

## 2. Existing Applications Scanner

**Objective:** Build a catalog of existing business analyses for comparison.

### Scan Algorithm

```javascript
function scanExistingApplications() {
  const featureFiles = glob('docs/*/business-analyse/*/index.json');

  const existingApps = featureFiles.map(path => {
    const feature = readJSON(path);
    return {
      app: feature.metadata.application,
      featureId: feature.id,
      description: feature.metadata.featureDescription,
      version: extractVersion(path),  // e.g., "1.0" from "v1.0"
      path: path,
      updatedAt: feature.metadata.updatedAt,
      modules: feature.modules?.map(m => m.code) || [],
      status: feature.status
    };
  });

  // Sort by most recent first
  existingApps.sort((a, b) => b.updatedAt - a.updatedAt);

  return existingApps;
}
```

### Output Schema

```typescript
interface ExistingApp {
  app: string;              // "HumanResources"
  featureId: string;        // "FEAT-001"
  description: string;      // "Gestion des projets et absences"
  version: string;          // "1.0", "1.1", "2.0"
  path: string;             // "docs/HumanResources/..."
  updatedAt: string;        // ISO timestamp
  modules: string[];        // ["Projects", "TimeTracking", "Reporting"]
  status: string;           // "draft", "consolidated", "handed-off"
}
```

### Edge Cases

| Case | Handling |
|------|----------|
| No index.json files found | Return empty array → triggers "new application" mode |
| Corrupted index.json | Skip file, log warning, continue scan |
| Multiple versions of same app | Include all, sorted by updatedAt |
| Incomplete applications (status="draft") | Include but flag in description |

---

## 3. New vs Update Detection

**Objective:** Determine if user wants to create a new application or update an existing one.

### Similarity Analysis Algorithm

```javascript
function analyzeSimilarity(feature_description, existingApps) {
  const scores = existingApps.map(app => ({
    app,
    score: calculateSimilarityScore(feature_description, app)
  }));

  // Sort by highest score first
  scores.sort((a, b) => b.score - a.score);

  return scores;
}

function calculateSimilarityScore(description, existingApp) {
  let score = 0;

  // 1. Application name match (50 points)
  if (description.toLowerCase().includes(existingApp.app.toLowerCase())) {
    score += 50;
  }

  // 2. Module name match (30 points)
  for (const module of existingApp.modules) {
    if (description.toLowerCase().includes(module.toLowerCase())) {
      score += 30;
      break;
    }
  }

  // 3. Update keywords (40 points)
  const updateKeywords = [
    'ajouter', 'modifier', 'changer', 'enrichir', 'mettre à jour',
    'add', 'modify', 'change', 'update', 'extend'
  ];
  for (const keyword of updateKeywords) {
    if (description.toLowerCase().includes(keyword)) {
      score += 40;
      break;
    }
  }

  // 4. Domain overlap (20 points)
  // Check if description and existing app share domain terms
  const domainTerms = extractDomainTerms(existingApp.description);
  for (const term of domainTerms) {
    if (description.toLowerCase().includes(term.toLowerCase())) {
      score += 5;  // Up to 20 points (4 terms)
    }
  }

  return score;
}

function extractDomainTerms(text) {
  // Extract nouns/domain entities (simplified)
  const words = text.toLowerCase().split(/\s+/);
  return words.filter(w => w.length > 4);  // Filter short words
}
```

### Decision Tree

```
┌─────────────────────────────────────┐
│ existing_apps.length === 0?         │
└──┬─────────────────────────┬────────┘
   │ YES                     │ NO
   │                         │
   v                         v
┌──────────────┐      ┌──────────────────────┐
│ workflow_type │      │ Calculate similarity  │
│ = "new"       │      │ scores for all apps   │
└──────────────┘      └──────┬───────────────┘
                              │
                              v
                     ┌─────────────────────┐
                     │ Top score >= 80?    │
                     └──┬─────────────┬────┘
                        │ YES         │ NO
                        │             │
                        v             v
              ┌──────────────┐  ┌──────────────┐
              │ Suggest       │  │ Show all     │
              │ update to     │  │ options with │
              │ matched app   │  │ "New app" as │
              │ as first      │  │ first option │
              │ option        │  │              │
              └───────────────┘  └──────────────┘
                        │             │
                        v             v
                   ┌────────────────────────┐
                   │ Ask via                │
                   │ AskUserQuestion        │
                   └─────────┬──────────────┘
                             │
              ┌──────────────┴──────────────┐
              │                             │
              v                             v
    ┌──────────────────┐        ┌──────────────────┐
    │ User selects     │        │ User selects     │
    │ "Update {app}"   │        │ "New app"        │
    └────────┬─────────┘        └────────┬─────────┘
             │                            │
             v                            v
    ┌──────────────────┐        ┌──────────────────┐
    │ workflow_type =  │        │ workflow_type =  │
    │ "update"         │        │ "new"            │
    │ existing_feature │        │                  │
    │ = app.featureId  │        │                  │
    └──────────────────┘        └──────────────────┘
```

### AskUserQuestion Format

**When similarity score >= 80 (strong match):**
```javascript
AskUserQuestion({
  question: "J'ai trouvé une analyse existante similaire. Que souhaitez-vous faire ?",
  header: "Mode",
  options: [
    {
      label: `Mise à jour de ${matchedApp.app} (${matchedApp.featureId})`,
      description: `Enrichir ou modifier l'application existante (crée v${nextVersion})`
    },
    {
      label: "Nouvelle application",
      description: "Créer une nouvelle analyse complète"
    }
  ]
});
```

**When multiple apps but no strong match:**
```javascript
AskUserQuestion({
  question: "J'ai trouvé des analyses existantes. Que souhaitez-vous faire ?",
  header: "Mode",
  options: [
    {
      label: "Nouvelle application",
      description: "Créer une nouvelle analyse complète"
    },
    ...existingApps.slice(0, 3).map(app => ({
      label: `Mise à jour de ${app.app} (${app.featureId})`,
      description: `Enrichir ${app.app} — modules: ${app.modules.join(', ')}`
    }))
  ]
});
```

### Update Mode Flow

When user selects an existing app for update:

```javascript
function initiateUpdateMode(existingApp) {
  // 1. Call ba-writer to create new version
  const newVersion = ba_writer.createVersion(
    existingApp.featureId,
    feature_description
  );

  // 2. Copy previous version data as baseline
  const previousFeature = readJSON(existingApp.path);
  const newFeature = {
    ...previousFeature,
    id: existingApp.featureId,  // Keep same feature ID
    version: newVersion.version,  // Increment version (e.g., "1.0" → "1.1")
    status: "draft",
    metadata: {
      ...previousFeature.metadata,
      featureDescription: feature_description,  // New description
      workflowType: "update",
      previousVersion: extractVersion(existingApp.path),
      updatedAt: new Date().toISOString()
    }
  };

  // 3. Write new version index.json
  const newPath = `docs/${existingApp.app}/business-analyse/v${newVersion.version}/index.json`;
  writeJSON(newPath, newFeature);

  return {
    workflow_type: "update",
    existing_feature_id: existingApp.featureId,
    version: newVersion.version,
    application_name: existingApp.app,
    docs_dir: path.dirname(newPath)
  };
}
```

---

## Similarity Scoring Reference

| Match Type | Score | Example |
|-----------|-------|---------|
| **Application name exact** | 50 | "HumanResources" in description → matches HumanResources app |
| **Module name exact** | 30 | "Projects" in description → matches app with Projects module |
| **Update keyword** | 40 | "ajouter", "modifier", "mettre à jour" |
| **Domain term overlap** | 5 per term (max 20) | "project", "absence", "employee" |

**Total possible:** 140 points

**Thresholds:**
- **>= 80:** Strong match → suggest update as first option
- **50-79:** Moderate match → show as option but list "New app" first
- **< 50:** Weak match → show in list but deprioritize

---

## State Variables After Detection

After detection completes, these variables are set:

```typescript
interface DetectionResult {
  workflow_type: "new" | "update" | "review";
  existing_feature_id: string | null;        // Set only if workflow_type = "update"
  version: string;                           // "1.0" (new) or "1.1"+ (update)
  application_name: string;
  review_json_path?: string;                 // Set only if workflow_type = "review"
  docs_dir: string;
}
```

---

## Testing Detection Logic

**Test Case 1: New Application (No Existing Apps)**
- Input: `"Créer une application de gestion des congés"`
- Expected: `workflow_type = "new"`, no prompt shown

**Test Case 2: Strong Match for Update**
- Input: `"Ajouter module de reporting à HumanResources"`
- Existing: `HumanResources (FEAT-001)` with modules `[Projects, TimeTracking]`
- Expected: Prompt with "Update HumanResources" as first option, score ~120

**Test Case 3: Ambiguous (Multiple Matches)**
- Input: `"Gérer les projets"`
- Existing: `HumanResources (FEAT-001)` with Projects module, `ProjectManagement (FEAT-002)`
- Expected: Prompt with "New app" first, both existing apps listed

**Test Case 4: Review Mode**
- Input: `"-review"`
- Existing: `HumanResources` with ba-review.json present
- Expected: Redirect user to `/business-analyse-review` skill

**Test Case 5: Review Mode - File Missing**
- Input: `"-review"`
- Existing: `HumanResources` but no ba-review.json
- Expected: Display error with fix instructions, STOP
