@atlashub/smartstack-cli 3.9.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2544 -2461
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +479 -6185
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-writer.md +178 -0
- package/templates/agents/db-reader.md +149 -0
- package/templates/skills/application/references/application-roles-template.md +227 -0
- package/templates/skills/application/references/provider-template.md +30 -6
- package/templates/skills/application/steps/step-03-roles.md +45 -7
- package/templates/skills/application/steps/step-03b-provider.md +13 -6
- package/templates/skills/business-analyse/SKILL.md +56 -4
- package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +477 -0
- package/templates/skills/business-analyse/references/cache-warming-strategy.md +578 -0
- package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +9 -19
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +12 -2
- package/templates/skills/business-analyse/references/deploy-data-build.md +36 -25
- package/templates/skills/business-analyse/references/detection-strategies.md +424 -0
- package/templates/skills/business-analyse/references/html-data-mapping.md +4 -0
- package/templates/skills/business-analyse/references/prd-generation.md +258 -0
- package/templates/skills/business-analyse/references/robustness-checks.md +538 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +47 -4
- package/templates/skills/business-analyse/references/validation-checklist.md +281 -0
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +70 -75
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +8 -22
- package/templates/skills/business-analyse/steps/step-03a-data.md +20 -410
- package/templates/skills/business-analyse/steps/step-03a1-setup.md +356 -0
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +143 -0
- package/templates/skills/business-analyse/steps/step-03b-ui.md +3 -0
- package/templates/skills/business-analyse/steps/step-03c-compile.md +72 -3
- package/templates/skills/business-analyse/steps/step-03d-validate.md +36 -3
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +21 -440
- package/templates/skills/business-analyse/steps/step-04a-collect.md +304 -0
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +239 -0
- package/templates/skills/business-analyse/steps/step-04c-decide.md +186 -0
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +44 -0
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +42 -2
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +518 -0
- package/templates/skills/controller/steps/step-03-generate.md +184 -24
- package/templates/skills/controller/templates.md +11 -2
- package/templates/skills/debug/SKILL.md +156 -53
- package/templates/skills/debug/references/team-protocol.md +232 -0
- package/templates/skills/ralph-loop/references/category-rules.md +46 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +32 -2
- package/templates/skills/ralph-loop/references/core-seed-data.md +233 -21
- package/templates/skills/ralph-loop/steps/step-00-init.md +64 -1
- package/templates/skills/ralph-loop/steps/step-04-check.md +27 -2
|
@@ -75,40 +75,51 @@ const FEATURE_DATA = {
|
|
|
75
75
|
|
|
76
76
|
## EMBEDDED_ARTIFACTS Object
|
|
77
77
|
|
|
78
|
+
> **CRITICAL:** The wireframes object is keyed by moduleCode (NOT a flat array).
|
|
79
|
+
> Field names MUST be renamed from feature.json: `mockupFormat` → `format`, `mockup` → `content`.
|
|
80
|
+
> The HTML renderer reads `wf.format` and `wf.content` — using feature.json names will produce EMPTY mockups.
|
|
81
|
+
|
|
78
82
|
```javascript
|
|
79
83
|
const EMBEDDED_ARTIFACTS = {
|
|
80
|
-
wireframes:
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
screen:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
84
|
+
wireframes: {
|
|
85
|
+
// PER-MODULE keyed object (NOT a flat array)
|
|
86
|
+
// FOR EACH module: extract from specification.uiWireframes[]
|
|
87
|
+
[moduleCode]: moduleFeature.specification.uiWireframes.map(wf => ({
|
|
88
|
+
screen: wf.screen, // e.g. "employees-list"
|
|
89
|
+
section: wf.section, // e.g. "list"
|
|
90
|
+
format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
|
|
91
|
+
content: wf.mockup, // RENAME: mockup → content (ASCII art string)
|
|
92
|
+
description: wf.description || "",
|
|
93
|
+
elements: wf.elements || [], // ["DataGrid", "FilterBar", ...]
|
|
94
|
+
actions: wf.actions || [], // ["filter", "sort", "create", ...]
|
|
95
|
+
componentMapping: wf.componentMapping || [], // [{ wireframeElement, reactComponent }]
|
|
96
|
+
layout: wf.layout || null, // { type, regions: [...] }
|
|
97
|
+
permissionsRequired: wf.permissionsRequired || []
|
|
98
|
+
}))
|
|
99
|
+
},
|
|
100
|
+
e2eFlows: (master.consolidation?.e2eFlows || []).map(flow => ({
|
|
101
|
+
name: flow.name,
|
|
102
|
+
diagram: flow.steps.map(s => `${s.action}(${s.module})`).join(" ──→ "),
|
|
103
|
+
steps: flow.steps || [],
|
|
104
|
+
actors: [...new Set(flow.steps.map(s => s.permission?.split(".")[0]).filter(Boolean))].join(", "),
|
|
105
|
+
modules: [...new Set(flow.steps.map(s => s.module))].join(" → ")
|
|
106
|
+
})),
|
|
99
107
|
dependencyGraph: {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
nodes: (master.modules || []).map(m => ({
|
|
109
|
+
id: m.code, label: m.code, type: m.featureType || "data-centric"
|
|
110
|
+
})),
|
|
111
|
+
edges: (master.dependencyGraph?.edges || []).map(e => ({
|
|
112
|
+
from: e.from, to: e.to, description: e.description || ""
|
|
113
|
+
}))
|
|
103
114
|
}
|
|
104
115
|
};
|
|
105
116
|
```
|
|
106
117
|
|
|
107
118
|
### Artifact Gathering
|
|
108
119
|
|
|
109
|
-
1.
|
|
110
|
-
2. Read master's `consolidation.e2eFlows[]` and
|
|
111
|
-
3. Read master's `
|
|
120
|
+
1. For EACH module: read `specification.uiWireframes[]`, **rename fields** (`mockupFormat`→`format`, `mockup`→`content`), store under `wireframes[moduleCode]`
|
|
121
|
+
2. Read master's `consolidation.e2eFlows[]` and build e2eFlows array with diagram generation
|
|
122
|
+
3. Read master's `dependencyGraph` and build nodes/edges
|
|
112
123
|
4. Serialize as JSON with 2-space indentation
|
|
113
124
|
|
|
114
125
|
## Placeholder Replacement
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
# Detection Strategies - New vs Update vs Review
|
|
2
|
+
|
|
3
|
+
Source: business-analyse step-00-init.md
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Review Mode Detection
|
|
10
|
+
|
|
11
|
+
**Trigger:** `{feature_description}` starts with `-review` (with or without extra text)
|
|
12
|
+
|
|
13
|
+
### Algorithm
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
function detectReviewMode(feature_description) {
|
|
17
|
+
const isReviewMode = feature_description.trim().startsWith('-review');
|
|
18
|
+
|
|
19
|
+
if (!isReviewMode) {
|
|
20
|
+
return { mode: null };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Scan docs/business/ for most recent application
|
|
24
|
+
const applications = glob('docs/business/*/business-analyse/*/feature.json')
|
|
25
|
+
.map(path => ({
|
|
26
|
+
path,
|
|
27
|
+
metadata: readJSON(path).metadata,
|
|
28
|
+
updatedAt: readJSON(path).metadata.updatedAt
|
|
29
|
+
}))
|
|
30
|
+
.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
31
|
+
|
|
32
|
+
if (applications.length === 0) {
|
|
33
|
+
return {
|
|
34
|
+
mode: 'review',
|
|
35
|
+
error: 'NO_APPLICATIONS_FOUND',
|
|
36
|
+
fix: 'Create an application first using /business-analyse'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const latestApp = applications[0];
|
|
41
|
+
const versionDir = path.dirname(latestApp.path);
|
|
42
|
+
const reviewFilePath = path.join(versionDir, 'ba-review.json');
|
|
43
|
+
|
|
44
|
+
if (!fs.existsSync(reviewFilePath)) {
|
|
45
|
+
return {
|
|
46
|
+
mode: 'review',
|
|
47
|
+
error: 'NO_REVIEW_FILE',
|
|
48
|
+
applicationName: latestApp.metadata.application,
|
|
49
|
+
expectedPath: reviewFilePath,
|
|
50
|
+
fix: `
|
|
51
|
+
To create ba-review.json:
|
|
52
|
+
1. Open ba-interactive.html in your browser
|
|
53
|
+
2. Make your corrections
|
|
54
|
+
3. Click "Sauvegarder corrections" button
|
|
55
|
+
4. Save the downloaded ba-review.json in: ${versionDir}/
|
|
56
|
+
5. Run /business-analyse -review again
|
|
57
|
+
`
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
mode: 'review',
|
|
63
|
+
reviewJsonPath: reviewFilePath,
|
|
64
|
+
applicationName: latestApp.metadata.application,
|
|
65
|
+
docsDir: versionDir,
|
|
66
|
+
nextStep: 'step-06-review.md'
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Decision Matrix
|
|
72
|
+
|
|
73
|
+
| Condition | Action |
|
|
74
|
+
|-----------|--------|
|
|
75
|
+
| `{feature_description}` starts with `-review` | Activate review mode detection |
|
|
76
|
+
| ba-review.json found | Skip to step-06-review.md |
|
|
77
|
+
| ba-review.json NOT found | Display error with fix instructions, STOP |
|
|
78
|
+
| No applications exist | Display error, STOP |
|
|
79
|
+
|
|
80
|
+
### Error Messages
|
|
81
|
+
|
|
82
|
+
**Error 1: No Applications Found**
|
|
83
|
+
```
|
|
84
|
+
ERROR: No existing applications found in docs/business/
|
|
85
|
+
|
|
86
|
+
You must create an application first using:
|
|
87
|
+
/business-analyse
|
|
88
|
+
|
|
89
|
+
Then generate ba-interactive.html, make corrections, and export ba-review.json.
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Error 2: No Review File**
|
|
93
|
+
```
|
|
94
|
+
ERROR: No ba-review.json found in docs/business/{app}/business-analyse/v{version}/
|
|
95
|
+
|
|
96
|
+
To create one:
|
|
97
|
+
1. Open the ba-interactive.html in your browser
|
|
98
|
+
2. Make your corrections
|
|
99
|
+
3. Click "Sauvegarder corrections" button
|
|
100
|
+
4. Save the downloaded ba-review.json in the version folder
|
|
101
|
+
5. Run /business-analyse -review again
|
|
102
|
+
|
|
103
|
+
Expected path: {expectedPath}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 2. Existing Applications Scanner
|
|
109
|
+
|
|
110
|
+
**Objective:** Build a catalog of existing business analyses for comparison.
|
|
111
|
+
|
|
112
|
+
### Scan Algorithm
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
function scanExistingApplications() {
|
|
116
|
+
const featureFiles = glob('docs/business/*/business-analyse/*/feature.json');
|
|
117
|
+
|
|
118
|
+
const existingApps = featureFiles.map(path => {
|
|
119
|
+
const feature = readJSON(path);
|
|
120
|
+
return {
|
|
121
|
+
app: feature.metadata.application,
|
|
122
|
+
featureId: feature.id,
|
|
123
|
+
description: feature.metadata.featureDescription,
|
|
124
|
+
version: extractVersion(path), // e.g., "1.0" from "v1.0"
|
|
125
|
+
path: path,
|
|
126
|
+
updatedAt: feature.metadata.updatedAt,
|
|
127
|
+
modules: feature.modules?.map(m => m.code) || [],
|
|
128
|
+
status: feature.status
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Sort by most recent first
|
|
133
|
+
existingApps.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
134
|
+
|
|
135
|
+
return existingApps;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Output Schema
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
interface ExistingApp {
|
|
143
|
+
app: string; // "HumanResources"
|
|
144
|
+
featureId: string; // "FEAT-001"
|
|
145
|
+
description: string; // "Gestion des projets et absences"
|
|
146
|
+
version: string; // "1.0", "1.1", "2.0"
|
|
147
|
+
path: string; // "docs/business/HumanResources/..."
|
|
148
|
+
updatedAt: string; // ISO timestamp
|
|
149
|
+
modules: string[]; // ["Projects", "TimeTracking", "Reporting"]
|
|
150
|
+
status: string; // "draft", "consolidated", "handed-off"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Edge Cases
|
|
155
|
+
|
|
156
|
+
| Case | Handling |
|
|
157
|
+
|------|----------|
|
|
158
|
+
| No feature.json files found | Return empty array → triggers "new application" mode |
|
|
159
|
+
| Corrupted feature.json | Skip file, log warning, continue scan |
|
|
160
|
+
| Multiple versions of same app | Include all, sorted by updatedAt |
|
|
161
|
+
| Incomplete applications (status="draft") | Include but flag in description |
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 3. New vs Update Detection
|
|
166
|
+
|
|
167
|
+
**Objective:** Determine if user wants to create a new application or update an existing one.
|
|
168
|
+
|
|
169
|
+
### Similarity Analysis Algorithm
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
function analyzeSimilarity(feature_description, existingApps) {
|
|
173
|
+
const scores = existingApps.map(app => ({
|
|
174
|
+
app,
|
|
175
|
+
score: calculateSimilarityScore(feature_description, app)
|
|
176
|
+
}));
|
|
177
|
+
|
|
178
|
+
// Sort by highest score first
|
|
179
|
+
scores.sort((a, b) => b.score - a.score);
|
|
180
|
+
|
|
181
|
+
return scores;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function calculateSimilarityScore(description, existingApp) {
|
|
185
|
+
let score = 0;
|
|
186
|
+
|
|
187
|
+
// 1. Application name match (50 points)
|
|
188
|
+
if (description.toLowerCase().includes(existingApp.app.toLowerCase())) {
|
|
189
|
+
score += 50;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 2. Module name match (30 points)
|
|
193
|
+
for (const module of existingApp.modules) {
|
|
194
|
+
if (description.toLowerCase().includes(module.toLowerCase())) {
|
|
195
|
+
score += 30;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 3. Update keywords (40 points)
|
|
201
|
+
const updateKeywords = [
|
|
202
|
+
'ajouter', 'modifier', 'changer', 'enrichir', 'mettre à jour',
|
|
203
|
+
'add', 'modify', 'change', 'update', 'extend'
|
|
204
|
+
];
|
|
205
|
+
for (const keyword of updateKeywords) {
|
|
206
|
+
if (description.toLowerCase().includes(keyword)) {
|
|
207
|
+
score += 40;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 4. Domain overlap (20 points)
|
|
213
|
+
// Check if description and existing app share domain terms
|
|
214
|
+
const domainTerms = extractDomainTerms(existingApp.description);
|
|
215
|
+
for (const term of domainTerms) {
|
|
216
|
+
if (description.toLowerCase().includes(term.toLowerCase())) {
|
|
217
|
+
score += 5; // Up to 20 points (4 terms)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return score;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function extractDomainTerms(text) {
|
|
225
|
+
// Extract nouns/domain entities (simplified)
|
|
226
|
+
const words = text.toLowerCase().split(/\s+/);
|
|
227
|
+
return words.filter(w => w.length > 4); // Filter short words
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Decision Tree
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
┌─────────────────────────────────────┐
|
|
235
|
+
│ existing_apps.length === 0? │
|
|
236
|
+
└──┬─────────────────────────┬────────┘
|
|
237
|
+
│ YES │ NO
|
|
238
|
+
│ │
|
|
239
|
+
v v
|
|
240
|
+
┌──────────────┐ ┌──────────────────────┐
|
|
241
|
+
│ workflow_type │ │ Calculate similarity │
|
|
242
|
+
│ = "new" │ │ scores for all apps │
|
|
243
|
+
└──────────────┘ └──────┬───────────────┘
|
|
244
|
+
│
|
|
245
|
+
v
|
|
246
|
+
┌─────────────────────┐
|
|
247
|
+
│ Top score >= 80? │
|
|
248
|
+
└──┬─────────────┬────┘
|
|
249
|
+
│ YES │ NO
|
|
250
|
+
│ │
|
|
251
|
+
v v
|
|
252
|
+
┌──────────────┐ ┌──────────────┐
|
|
253
|
+
│ Suggest │ │ Show all │
|
|
254
|
+
│ update to │ │ options with │
|
|
255
|
+
│ matched app │ │ "New app" as │
|
|
256
|
+
│ as first │ │ first option │
|
|
257
|
+
│ option │ │ │
|
|
258
|
+
└───────────────┘ └──────────────┘
|
|
259
|
+
│ │
|
|
260
|
+
v v
|
|
261
|
+
┌────────────────────────┐
|
|
262
|
+
│ Ask via │
|
|
263
|
+
│ AskUserQuestion │
|
|
264
|
+
└─────────┬──────────────┘
|
|
265
|
+
│
|
|
266
|
+
┌──────────────┴──────────────┐
|
|
267
|
+
│ │
|
|
268
|
+
v v
|
|
269
|
+
┌──────────────────┐ ┌──────────────────┐
|
|
270
|
+
│ User selects │ │ User selects │
|
|
271
|
+
│ "Update {app}" │ │ "New app" │
|
|
272
|
+
└────────┬─────────┘ └────────┬─────────┘
|
|
273
|
+
│ │
|
|
274
|
+
v v
|
|
275
|
+
┌──────────────────┐ ┌──────────────────┐
|
|
276
|
+
│ workflow_type = │ │ workflow_type = │
|
|
277
|
+
│ "update" │ │ "new" │
|
|
278
|
+
│ existing_feature │ │ │
|
|
279
|
+
│ = app.featureId │ │ │
|
|
280
|
+
└──────────────────┘ └──────────────────┘
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### AskUserQuestion Format
|
|
284
|
+
|
|
285
|
+
**When similarity score >= 80 (strong match):**
|
|
286
|
+
```javascript
|
|
287
|
+
AskUserQuestion({
|
|
288
|
+
question: "J'ai trouvé une analyse existante similaire. Que souhaitez-vous faire ?",
|
|
289
|
+
header: "Mode",
|
|
290
|
+
options: [
|
|
291
|
+
{
|
|
292
|
+
label: `Mise à jour de ${matchedApp.app} (${matchedApp.featureId})`,
|
|
293
|
+
description: `Enrichir ou modifier l'application existante (crée v${nextVersion})`
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
label: "Nouvelle application",
|
|
297
|
+
description: "Créer une nouvelle analyse complète"
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
});
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**When multiple apps but no strong match:**
|
|
304
|
+
```javascript
|
|
305
|
+
AskUserQuestion({
|
|
306
|
+
question: "J'ai trouvé des analyses existantes. Que souhaitez-vous faire ?",
|
|
307
|
+
header: "Mode",
|
|
308
|
+
options: [
|
|
309
|
+
{
|
|
310
|
+
label: "Nouvelle application",
|
|
311
|
+
description: "Créer une nouvelle analyse complète"
|
|
312
|
+
},
|
|
313
|
+
...existingApps.slice(0, 3).map(app => ({
|
|
314
|
+
label: `Mise à jour de ${app.app} (${app.featureId})`,
|
|
315
|
+
description: `Enrichir ${app.app} — modules: ${app.modules.join(', ')}`
|
|
316
|
+
}))
|
|
317
|
+
]
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Update Mode Flow
|
|
322
|
+
|
|
323
|
+
When user selects an existing app for update:
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
function initiateUpdateMode(existingApp) {
|
|
327
|
+
// 1. Call ba-writer to create new version
|
|
328
|
+
const newVersion = ba_writer.createVersion(
|
|
329
|
+
existingApp.featureId,
|
|
330
|
+
feature_description
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
// 2. Copy previous version data as baseline
|
|
334
|
+
const previousFeature = readJSON(existingApp.path);
|
|
335
|
+
const newFeature = {
|
|
336
|
+
...previousFeature,
|
|
337
|
+
id: existingApp.featureId, // Keep same feature ID
|
|
338
|
+
version: newVersion.version, // Increment version (e.g., "1.0" → "1.1")
|
|
339
|
+
status: "draft",
|
|
340
|
+
metadata: {
|
|
341
|
+
...previousFeature.metadata,
|
|
342
|
+
featureDescription: feature_description, // New description
|
|
343
|
+
workflowType: "update",
|
|
344
|
+
previousVersion: extractVersion(existingApp.path),
|
|
345
|
+
updatedAt: new Date().toISOString()
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// 3. Write new version feature.json
|
|
350
|
+
const newPath = `docs/business/${existingApp.app}/business-analyse/v${newVersion.version}/feature.json`;
|
|
351
|
+
writeJSON(newPath, newFeature);
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
workflow_type: "update",
|
|
355
|
+
existing_feature_id: existingApp.featureId,
|
|
356
|
+
version: newVersion.version,
|
|
357
|
+
application_name: existingApp.app,
|
|
358
|
+
docs_dir: path.dirname(newPath)
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Similarity Scoring Reference
|
|
366
|
+
|
|
367
|
+
| Match Type | Score | Example |
|
|
368
|
+
|-----------|-------|---------|
|
|
369
|
+
| **Application name exact** | 50 | "HumanResources" in description → matches HumanResources app |
|
|
370
|
+
| **Module name exact** | 30 | "Projects" in description → matches app with Projects module |
|
|
371
|
+
| **Update keyword** | 40 | "ajouter", "modifier", "mettre à jour" |
|
|
372
|
+
| **Domain term overlap** | 5 per term (max 20) | "project", "absence", "employee" |
|
|
373
|
+
|
|
374
|
+
**Total possible:** 140 points
|
|
375
|
+
|
|
376
|
+
**Thresholds:**
|
|
377
|
+
- **>= 80:** Strong match → suggest update as first option
|
|
378
|
+
- **50-79:** Moderate match → show as option but list "New app" first
|
|
379
|
+
- **< 50:** Weak match → show in list but deprioritize
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## State Variables After Detection
|
|
384
|
+
|
|
385
|
+
After detection completes, these variables are set:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
interface DetectionResult {
|
|
389
|
+
workflow_type: "new" | "update" | "review";
|
|
390
|
+
existing_feature_id: string | null; // Set only if workflow_type = "update"
|
|
391
|
+
version: string; // "1.0" (new) or "1.1"+ (update)
|
|
392
|
+
application_name: string;
|
|
393
|
+
review_json_path?: string; // Set only if workflow_type = "review"
|
|
394
|
+
docs_dir: string;
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Testing Detection Logic
|
|
401
|
+
|
|
402
|
+
**Test Case 1: New Application (No Existing Apps)**
|
|
403
|
+
- Input: `"Créer une application de gestion des congés"`
|
|
404
|
+
- Expected: `workflow_type = "new"`, no prompt shown
|
|
405
|
+
|
|
406
|
+
**Test Case 2: Strong Match for Update**
|
|
407
|
+
- Input: `"Ajouter module de reporting à HumanResources"`
|
|
408
|
+
- Existing: `HumanResources (FEAT-001)` with modules `[Projects, TimeTracking]`
|
|
409
|
+
- Expected: Prompt with "Update HumanResources" as first option, score ~120
|
|
410
|
+
|
|
411
|
+
**Test Case 3: Ambiguous (Multiple Matches)**
|
|
412
|
+
- Input: `"Gérer les projets"`
|
|
413
|
+
- Existing: `HumanResources (FEAT-001)` with Projects module, `ProjectManagement (FEAT-002)`
|
|
414
|
+
- Expected: Prompt with "New app" first, both existing apps listed
|
|
415
|
+
|
|
416
|
+
**Test Case 4: Review Mode**
|
|
417
|
+
- Input: `"-review"`
|
|
418
|
+
- Existing: `HumanResources` with ba-review.json present
|
|
419
|
+
- Expected: Load ba-review.json, skip to step-06-review.md
|
|
420
|
+
|
|
421
|
+
**Test Case 5: Review Mode - File Missing**
|
|
422
|
+
- Input: `"-review"`
|
|
423
|
+
- Existing: `HumanResources` but no ba-review.json
|
|
424
|
+
- Expected: Display error with fix instructions, STOP
|
|
@@ -196,6 +196,10 @@ Default: "contributor"
|
|
|
196
196
|
|
|
197
197
|
## EMBEDDED_ARTIFACTS Mapping
|
|
198
198
|
|
|
199
|
+
> **FIELD RENAME WARNING:** feature.json stores wireframes with `mockupFormat` and `mockup` fields.
|
|
200
|
+
> The HTML renderer reads `format` and `content`. You MUST rename: `mockupFormat` → `format`, `mockup` → `content`.
|
|
201
|
+
> Failure to rename = empty mockup display in the browser.
|
|
202
|
+
|
|
199
203
|
Build a JSON object containing ALL visual artifacts from feature.json:
|
|
200
204
|
|
|
201
205
|
```javascript
|