@atlashub/smartstack-cli 3.10.0 → 3.13.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 +2 -2
- package/templates/agents/db-reader.md +149 -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/validate-incremental-html.md +47 -4
- package/templates/skills/business-analyse/references/validation-checklist.md +281 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +50 -221
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +8 -22
- package/templates/skills/business-analyse/steps/step-03a-data.md +20 -446
- 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 +1 -1
- package/templates/skills/business-analyse/steps/step-03d-validate.md +21 -262
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +21 -606
- 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-05b-deploy.md +21 -0
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +27 -35
- 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 +60 -0
- package/templates/skills/ralph-loop/steps/step-00-init.md +64 -1
- package/templates/skills/ralph-loop/steps/step-04-check.md +27 -2
|
@@ -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
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# PRD v3.0 Structure & Validation Rules
|
|
2
|
+
|
|
3
|
+
Source: business-analyse step-05c-ralph-readiness.md
|
|
4
|
+
|
|
5
|
+
## PRD File Format v3.0
|
|
6
|
+
|
|
7
|
+
### File Location
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
.ralph/prd-{moduleCode}.json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Example: `.ralph/prd-Projects.json`, `.ralph/prd-TimeTracking.json`
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Structure Requirements
|
|
18
|
+
|
|
19
|
+
### 1. Version Field (MANDATORY)
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"$version": "3.0.0"
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Validation:**
|
|
28
|
+
- MUST be exactly `"3.0.0"`
|
|
29
|
+
- BLOCKING if missing or wrong version
|
|
30
|
+
|
|
31
|
+
**Common Error:**
|
|
32
|
+
```
|
|
33
|
+
BLOCKING_ERROR: PRD version must be 3.0.0, got: 2.1.0
|
|
34
|
+
Fix: Re-run ss derive-prd with latest version
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### 2. Implementation Section (MANDATORY)
|
|
40
|
+
|
|
41
|
+
**CRITICAL:** `filesToCreate` MUST be under `implementation`, NOT at root level.
|
|
42
|
+
|
|
43
|
+
**Correct Structure:**
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"$version": "3.0.0",
|
|
47
|
+
"implementation": {
|
|
48
|
+
"filesToCreate": {
|
|
49
|
+
"domain": [...],
|
|
50
|
+
"application": [...],
|
|
51
|
+
"infrastructure": [...],
|
|
52
|
+
"api": [...],
|
|
53
|
+
"frontend": [...],
|
|
54
|
+
"seedData": [...],
|
|
55
|
+
"tests": [...]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Wrong Structure (v2.x legacy):**
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"$version": "3.0.0",
|
|
65
|
+
"filesToCreate": { // ❌ WRONG - at root level
|
|
66
|
+
"domain": [...]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Validation:**
|
|
72
|
+
- IF `prd.filesToCreate` exists at root level → BLOCKING ERROR
|
|
73
|
+
- IF `prd.implementation.filesToCreate` missing → BLOCKING ERROR
|
|
74
|
+
|
|
75
|
+
**Fix Command:**
|
|
76
|
+
```bash
|
|
77
|
+
ss derive-prd --feature {path} --output .ralph/prd-{moduleCode}.json
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### 3. Seven Categories (MANDATORY)
|
|
83
|
+
|
|
84
|
+
All PRD files MUST include these 7 categories under `implementation.filesToCreate`:
|
|
85
|
+
|
|
86
|
+
| Category | Description | Examples |
|
|
87
|
+
|----------|-------------|----------|
|
|
88
|
+
| **domain** | Domain entities, value objects, domain services | `Project.cs`, `ProjectStatus.cs` |
|
|
89
|
+
| **application** | Application services, DTOs, interfaces | `ProjectService.cs`, `CreateProjectDto.cs` |
|
|
90
|
+
| **infrastructure** | Data access, repositories, EF Core config | `ProjectRepository.cs`, `ProjectConfiguration.cs` |
|
|
91
|
+
| **api** | Controllers, API endpoints | `ProjectsController.cs` |
|
|
92
|
+
| **frontend** | React pages, components, hooks | `ProjectsPage.tsx`, `useProjects.ts` |
|
|
93
|
+
| **seedData** | Seed data classes | `ProjectSeedData.cs` |
|
|
94
|
+
| **tests** | Unit tests, integration tests | `ProjectServiceTests.cs`, `ProjectsControllerTests.cs` |
|
|
95
|
+
|
|
96
|
+
**Validation:**
|
|
97
|
+
```javascript
|
|
98
|
+
const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests'];
|
|
99
|
+
const missingCategories = categories.filter(cat => !prd.implementation.filesToCreate[cat]);
|
|
100
|
+
|
|
101
|
+
if (missingCategories.length > 0) {
|
|
102
|
+
BLOCKING_ERROR(`Missing categories: ${missingCategories.join(', ')}`);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Common Errors:**
|
|
107
|
+
- Missing `tests` category → often forgotten
|
|
108
|
+
- Missing `seedData` category → sometimes omitted for modules without seed data
|
|
109
|
+
- Empty arrays allowed (e.g., `"seedData": []`) if genuinely no files needed
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### 4. File Count Consistency (MANDATORY)
|
|
114
|
+
|
|
115
|
+
**Validation:** PRD file counts MUST match feature.json handoff counts.
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
const featureHandoff = moduleFeature.handoff.filesToCreate;
|
|
119
|
+
const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests'];
|
|
120
|
+
|
|
121
|
+
for (const cat of categories) {
|
|
122
|
+
const prdCount = prd.implementation.filesToCreate[cat]?.length ?? 0;
|
|
123
|
+
const featureCount = featureHandoff[cat]?.length ?? 0;
|
|
124
|
+
|
|
125
|
+
if (prdCount !== featureCount) {
|
|
126
|
+
BLOCKING_ERROR(`${cat}: prd has ${prdCount} files but feature.json has ${featureCount}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Why this matters:**
|
|
132
|
+
- Ensures PRD was derived from the correct feature.json
|
|
133
|
+
- Catches stale PRD files (derived from old version)
|
|
134
|
+
- Validates handoff integrity before ralph-loop
|
|
135
|
+
|
|
136
|
+
**Fix:**
|
|
137
|
+
- Re-derive PRD from latest feature.json
|
|
138
|
+
- Check that feature.json handoff section is complete
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 5. File Entry Schema
|
|
143
|
+
|
|
144
|
+
Each file entry in a category array must have:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"path": "src/SmartStack.HumanResources.Domain/Projects/Project.cs",
|
|
149
|
+
"type": "Entity",
|
|
150
|
+
"module": "Projects"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Required Fields:**
|
|
155
|
+
- `path` (string): Absolute or relative path where file will be created
|
|
156
|
+
- `type` (string): File type hint (Entity, Service, Controller, Page, Test, etc.)
|
|
157
|
+
- `module` (string): Module code this file belongs to
|
|
158
|
+
|
|
159
|
+
**Optional Fields:**
|
|
160
|
+
- `description` (string): Brief description of what the file does
|
|
161
|
+
- `dependencies` (array): Other files this depends on
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Validation Checklist
|
|
166
|
+
|
|
167
|
+
Use this checklist when validating PRD files:
|
|
168
|
+
|
|
169
|
+
| Check | Validation | Status |
|
|
170
|
+
|-------|-----------|--------|
|
|
171
|
+
| **Version** | `$version === "3.0.0"` | PASS/FAIL |
|
|
172
|
+
| **Structure** | `implementation.filesToCreate` exists (not root) | PASS/FAIL |
|
|
173
|
+
| **Categories** | All 7 categories present | PASS/FAIL |
|
|
174
|
+
| **File Counts** | PRD counts match feature.json handoff | PASS/FAIL |
|
|
175
|
+
| **File Schemas** | All files have path, type, module | PASS/FAIL |
|
|
176
|
+
|
|
177
|
+
**All checks must PASS before proceeding to /ralph-loop**
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Common Errors & Fixes
|
|
182
|
+
|
|
183
|
+
### Error 1: Wrong Version
|
|
184
|
+
```
|
|
185
|
+
BLOCKING_ERROR: PRD version must be 3.0.0, got: 2.1.0
|
|
186
|
+
```
|
|
187
|
+
**Fix:** Re-run `ss derive-prd` with latest SmartStack.mcp version
|
|
188
|
+
|
|
189
|
+
### Error 2: filesToCreate at Root Level
|
|
190
|
+
```
|
|
191
|
+
BLOCKING_ERROR: filesToCreate is at ROOT level (wrong structure)
|
|
192
|
+
```
|
|
193
|
+
**Fix:** Re-run `ss derive-prd --feature {path} --output .ralph/prd-{moduleCode}.json`
|
|
194
|
+
|
|
195
|
+
### Error 3: Missing Categories
|
|
196
|
+
```
|
|
197
|
+
BLOCKING_ERROR: Missing categories: seedData, tests
|
|
198
|
+
```
|
|
199
|
+
**Fix:**
|
|
200
|
+
- Check feature.json handoff.filesToCreate has all 7 categories
|
|
201
|
+
- Re-derive PRD after fixing feature.json
|
|
202
|
+
- If genuinely no files needed, use empty array: `"seedData": []`
|
|
203
|
+
|
|
204
|
+
### Error 4: File Count Mismatch
|
|
205
|
+
```
|
|
206
|
+
BLOCKING_ERROR: api: prd has 8 files but feature.json has 12
|
|
207
|
+
```
|
|
208
|
+
**Fix:**
|
|
209
|
+
- PRD is stale (derived from old feature.json)
|
|
210
|
+
- Re-derive PRD from latest feature.json: `ss derive-prd --feature {path} --output .ralph/prd-{moduleCode}.json`
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Generation Command Reference
|
|
215
|
+
|
|
216
|
+
**Derive PRD from feature.json:**
|
|
217
|
+
```bash
|
|
218
|
+
ss derive-prd \
|
|
219
|
+
--feature docs/business/{App}/{Module}/business-analyse/v1.0/feature.json \
|
|
220
|
+
--output .ralph/prd-{ModuleCode}.json
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Example:**
|
|
224
|
+
```bash
|
|
225
|
+
ss derive-prd \
|
|
226
|
+
--feature docs/business/HumanResources/Projects/business-analyse/v1.0/feature.json \
|
|
227
|
+
--output .ralph/prd-Projects.json
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Batch generation for all modules:**
|
|
231
|
+
```bash
|
|
232
|
+
# Typically done in step-05a-handoff.md
|
|
233
|
+
for module in $(modules); do
|
|
234
|
+
ss derive-prd --feature {module_feature_path} --output .ralph/prd-${module}.json
|
|
235
|
+
done
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Why PRD Validation Matters
|
|
241
|
+
|
|
242
|
+
| Risk | Without Validation | With Validation |
|
|
243
|
+
|------|-------------------|-----------------|
|
|
244
|
+
| **Wrong structure** | ralph-loop fails mid-execution | Caught before development starts |
|
|
245
|
+
| **Stale PRD** | Generates code from old spec | Detects version mismatch |
|
|
246
|
+
| **Missing files** | Incomplete implementation | Ensures all layers covered |
|
|
247
|
+
| **Count mismatch** | Silent data loss | Guarantees integrity |
|
|
248
|
+
|
|
249
|
+
**Bottom line:** Ralph-loop depends on correct PRD structure. Validating upfront saves hours of debugging.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Related Files
|
|
254
|
+
|
|
255
|
+
- `step-05a-handoff.md`: Generates PRD files via `ss derive-prd`
|
|
256
|
+
- `step-05c-ralph-readiness.md`: Validates PRD structure before ralph-loop
|
|
257
|
+
- `feature-schema.json`: Schema for feature.json (source of PRD)
|
|
258
|
+
- `/ralph-loop` skill: Consumes PRD files for implementation
|