@atlashub/smartstack-cli 4.47.0 → 4.49.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.
Files changed (37) hide show
  1. package/.documentation/testing-ba-e2e.md +76 -24
  2. package/package.json +1 -1
  3. package/templates/agents/gitflow/init.md +26 -0
  4. package/templates/skills/apex/references/parallel-execution.md +22 -4
  5. package/templates/skills/apex/steps/step-00-init.md +38 -0
  6. package/templates/skills/apex/steps/step-03a-layer0-domain.md +21 -0
  7. package/templates/skills/apex/steps/step-03b-layer1-seed.md +60 -0
  8. package/templates/skills/apex/steps/step-03c-layer2-backend.md +124 -13
  9. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +32 -0
  10. package/templates/skills/application/references/backend-controller-hierarchy.md +14 -4
  11. package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +14 -0
  12. package/templates/skills/business-analyse-develop/references/compact-loop.md +15 -1
  13. package/templates/skills/business-analyse-develop/references/module-transition.md +10 -0
  14. package/templates/skills/business-analyse-develop/references/quality-gates.md +91 -1
  15. package/templates/skills/business-analyse-develop/steps/step-00-init.md +57 -0
  16. package/templates/skills/business-analyse-develop/steps/step-01-task.md +151 -2
  17. package/templates/skills/business-analyse-develop/steps/step-02-execute.md +14 -1
  18. package/templates/skills/business-analyse-develop/steps/step-02-v4-verify.md +22 -2
  19. package/templates/skills/business-analyse-develop/steps/step-03-commit.md +1 -1
  20. package/templates/skills/business-analyse-develop/steps/step-04-check.md +4 -1
  21. package/templates/skills/business-analyse-handoff/references/acceptance-criteria.md +53 -1
  22. package/templates/skills/business-analyse-handoff/references/handoff-file-templates.md +42 -0
  23. package/templates/skills/business-analyse-handoff/references/handoff-mappings.md +15 -1
  24. package/templates/skills/business-analyse-handoff/references/prd-generation.md +100 -0
  25. package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +27 -1
  26. package/templates/skills/business-analyse-handoff/steps/step-02-export.md +38 -8
  27. package/templates/skills/business-analyse-html/html/ba-interactive.html +64 -5
  28. package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +13 -1
  29. package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +10 -1
  30. package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +1 -1
  31. package/templates/skills/business-analyse-html/html/src/styles/03-navigation.css +2 -2
  32. package/templates/skills/business-analyse-html/html/src/styles/05-modules.css +38 -0
  33. package/templates/skills/business-analyse-html/steps/step-02-build-data.md +26 -5
  34. package/templates/skills/controller/references/mcp-scaffold-workflow.md +8 -4
  35. package/templates/skills/controller/steps/step-05-validate.md +2 -2
  36. package/templates/skills/controller/templates.md +4 -3
  37. package/templates/skills/feature-full/steps/step-01-implementation.md +18 -5
@@ -51,6 +51,12 @@ These verify data that `/business-analyse-handoff` step-01 generates:
51
51
  | AC-09 | BR-to-code mapping present | 1 | `handoff.brToCodeMapping[]` | YES |
52
52
  | AC-10 | API endpoint summary present | 1 | `handoff.apiEndpointSummary[]` | YES |
53
53
  | AC-11 | SeedData entries have category | ALL | `handoff.filesToCreate.seedData[].category` | YES |
54
+ | AC-12 | `specificationFiles` present with 5 paths | 5 | `handoff.specificationFiles` | YES |
55
+ | AC-13 | Companion entities file exists and count matches source | match | `.ralph/prd-{module}.entities.json` | YES |
56
+ | AC-14 | Companion rules file exists and count matches source | match | `.ralph/prd-{module}.rules.json` | YES |
57
+ | AC-15 | Companion usecases file exists and count matches source | match | `.ralph/prd-{module}.usecases.json` | YES |
58
+ | AC-16 | Companion screens file exists (if screens.json exists) | exists | `.ralph/prd-{module}.screens.json` | YES |
59
+ | AC-17 | Each `brToCodeMapping[].statement` non-empty | ALL | `handoff.brToCodeMapping[].statement` | YES |
54
60
 
55
61
  ---
56
62
 
@@ -240,11 +246,51 @@ if (noCat.length > 0) {
240
246
  console.error('FAIL: AC-11: ' + noCat.length + ' seedData entries missing category field');
241
247
  }
242
248
 
249
+ // AC-12: specificationFiles present with 5 paths
250
+ const specFiles = handoff.specificationFiles || {};
251
+ const specKeys = ['entities', 'rules', 'usecases', 'screens', 'permissions'];
252
+ const missingSpecs = specKeys.filter(k => !specFiles[k]);
253
+ if (missingSpecs.length > 0) {
254
+ fails.push('AC-12: specificationFiles missing keys: ' + missingSpecs.join(', '));
255
+ console.error('FAIL: AC-12: specificationFiles missing keys: ' + missingSpecs.join(', '));
256
+ }
257
+
258
+ // AC-13 to AC-16: Companion files exist and counts match
259
+ const ralphDir = path.dirname(process.argv[1]);
260
+ const companionChecks = [
261
+ { ac: 'AC-13', key: 'entities', arrayKey: 'entities' },
262
+ { ac: 'AC-14', key: 'rules', arrayKey: 'rules' },
263
+ { ac: 'AC-15', key: 'usecases', arrayKey: 'useCases' },
264
+ { ac: 'AC-16', key: 'screens', arrayKey: 'screens' }
265
+ ];
266
+ for (const check of companionChecks) {
267
+ const companionPath = specFiles[check.key] ? path.join(ralphDir, specFiles[check.key]) : null;
268
+ if (companionPath && fs.existsSync(companionPath)) {
269
+ const companionData = JSON.parse(fs.readFileSync(companionPath, 'utf-8'));
270
+ const arr = companionData[check.arrayKey] || companionData[check.arrayKey.toLowerCase()] || [];
271
+ if (arr.length === 0 && check.ac !== 'AC-16') {
272
+ fails.push(check.ac + ': companion ' + check.key + ' file is empty');
273
+ console.error('FAIL: ' + check.ac + ': companion ' + check.key + ' file has 0 entries');
274
+ }
275
+ } else if (companionPath) {
276
+ fails.push(check.ac + ': companion file missing: ' + specFiles[check.key]);
277
+ console.error('FAIL: ' + check.ac + ': companion file not found: ' + specFiles[check.key]);
278
+ }
279
+ }
280
+
281
+ // AC-17: Each brToCodeMapping[].statement non-empty
282
+ const brMapping = handoff.brToCodeMapping || [];
283
+ const emptyStatements = brMapping.filter(br => !br.statement || br.statement.trim() === '');
284
+ if (emptyStatements.length > 0) {
285
+ fails.push('AC-17: ' + emptyStatements.length + ' BRs with empty statement');
286
+ console.error('FAIL: AC-17: ' + emptyStatements.length + ' brToCodeMapping entries have empty statement: ' + emptyStatements.slice(0, 3).map(b => b.ruleId).join(', '));
287
+ }
288
+
243
289
  if (fails.length > 0) {
244
290
  console.error('\\nBLOCKING: ' + fails.length + ' output acceptance criteria FAILED');
245
291
  process.exit(1);
246
292
  }
247
- console.log('PASS: All output acceptance criteria met (AC-08 to AC-11)');
293
+ console.log('PASS: All output acceptance criteria met (AC-08 to AC-17)');
248
294
  " "$MODULE_JSON"
249
295
  ```
250
296
 
@@ -264,3 +310,9 @@ console.log('PASS: All output acceptance criteria met (AC-08 to AC-11)');
264
310
  | AC-09 | Re-run `/business-analyse-handoff` step-01 transform (BR mapping) |
265
311
  | AC-10 | Re-run `/business-analyse-handoff` step-01 transform (API endpoints) |
266
312
  | AC-11 | Re-run `/business-analyse-handoff` step-01 transform (seedData categories) |
313
+ | AC-12 | Re-run `/business-analyse-handoff` step-01 transform (specificationFiles missing) |
314
+ | AC-13 | Re-run `/business-analyse-handoff` step-01 transform (entities companion missing/empty) |
315
+ | AC-14 | Re-run `/business-analyse-handoff` step-01 transform (rules companion missing/empty) |
316
+ | AC-15 | Re-run `/business-analyse-handoff` step-01 transform (usecases companion missing/empty) |
317
+ | AC-16 | Re-run `/business-analyse-handoff` step-01 transform (screens companion missing) |
318
+ | AC-17 | Re-run `/business-analyse-handoff` step-01 transform (BR statements empty — copy from rules.json) |
@@ -153,3 +153,45 @@ From `screens.json > screens[]` and `usecases.json > useCases[]`:
153
153
 
154
154
  Include: Technical documentation data, API specification files, user guides.
155
155
  This category can be an empty array `[]` if no documentation is planned at this stage. It will be populated by the `/documentation` skill after `/business-analyse-develop` completes.
156
+
157
+ ## 4.9 Specification Files (Companion Files)
158
+
159
+ > **Purpose:** Enable `/apex` and `/business-analyse-develop` to load full BA specifications per layer, avoiding monolithic context loading.
160
+
161
+ Each PRD MUST include a `specificationFiles` object referencing 5 companion files:
162
+
163
+ ```json
164
+ "specificationFiles": {
165
+ "entities": "prd-{moduleCode}.entities.json",
166
+ "rules": "prd-{moduleCode}.rules.json",
167
+ "usecases": "prd-{moduleCode}.usecases.json",
168
+ "screens": "prd-{moduleCode}.screens.json",
169
+ "permissions": "prd-{moduleCode}.permissions.json"
170
+ }
171
+ ```
172
+
173
+ ### Naming Convention
174
+
175
+ `prd-{moduleCode}.{section}.json` — all files colocated in `.ralph/` alongside the PRD.
176
+
177
+ | File | Source | Content |
178
+ |------|--------|---------|
179
+ | `prd-{moduleCode}.entities.json` | `{moduleDir}/entities.json` | VERBATIM copy |
180
+ | `prd-{moduleCode}.rules.json` | `{moduleDir}/rules.json` | VERBATIM copy |
181
+ | `prd-{moduleCode}.usecases.json` | `{moduleDir}/usecases.json` | VERBATIM copy |
182
+ | `prd-{moduleCode}.screens.json` | `{moduleDir}/screens.json` | VERBATIM copy |
183
+ | `prd-{moduleCode}.permissions.json` | `{moduleDir}/permissions.json` | VERBATIM copy |
184
+
185
+ ### Rules
186
+
187
+ - **VERBATIM copy:** Each companion file is a 1:1 copy of the BA source file. Zero transformation, zero filtering.
188
+ - **Colocated:** All companion files live in `.ralph/` alongside the PRD file.
189
+ - **Mandatory:** All 5 companion files MUST be generated for every module PRD.
190
+ - **Layer loading:** `/apex` loads only the companion files needed per layer (see loading plan below).
191
+
192
+ | Layer | Files loaded | Estimated context |
193
+ |-------|-------------|-------------------|
194
+ | Layer 0 (domain) | `entities.json` | ~200-400 lines |
195
+ | Layer 1 (seed) | `entities.json` + `permissions.json` | ~300-500 lines |
196
+ | Layer 2 (backend) | `rules.json` + `usecases.json` | ~300-600 lines |
197
+ | Layer 3 (frontend) | `screens.json` + `usecases.json` | ~300-500 lines |
@@ -12,6 +12,13 @@ Generate complete mapping for each BR:
12
12
  {
13
13
  "ruleId": "BR-VAL-001",
14
14
  "title": "Order total must equal sum of item prices",
15
+ "statement": "The order total amount must equal the sum of all order item prices multiplied by their quantities",
16
+ "example": "Order with 3 items at $10, $20, $30 → total must be $60. If total = $50 → validation error",
17
+ "formula": null,
18
+ "conditions": [],
19
+ "entities": ["Order", "OrderItem"],
20
+ "category": "validation",
21
+ "sectionCode": "orders",
15
22
  "module": "{moduleCode}",
16
23
  "severity": "critical",
17
24
  "implementationPoints": [
@@ -27,7 +34,14 @@ Generate complete mapping for each BR:
27
34
 
28
35
  For each BR include:
29
36
  - **ruleId**: Reference to `rules.json > rules[].id`
30
- - **title**: The rule statement
37
+ - **title**: Short descriptive title
38
+ - **statement**: VERBATIM copy of `rules.json > rules[].statement` — the full rule text, NOT a paraphrase
39
+ - **example**: VERBATIM copy of `rules.json > rules[].example` — concrete example illustrating the rule (null if absent)
40
+ - **formula**: VERBATIM copy of `rules.json > rules[].formula` — formula for BR-CALC-* rules (null if absent)
41
+ - **conditions**: VERBATIM copy of `rules.json > rules[].conditions[]` — conditions of applicability (empty array if absent)
42
+ - **entities**: Array of entity names this rule applies to (from `rules.json > rules[].entities[]` or inferred from rule context)
43
+ - **category**: Rule category from `rules.json > rules[].category` — one of: validation, calculation, workflow, security, data
44
+ - **sectionCode**: Section this rule belongs to (from `rules.json > rules[].sectionCode` or inferred)
31
45
  - **module**: Which module it belongs to
32
46
  - **severity**: From `rule.severity` (blocking, info, etc.) mapped to "critical", "high", "medium", "low"
33
47
  - **implementationPoints**: Array of {layer, component, method, implementation}
@@ -80,6 +80,47 @@ ss business-analyse-handoff --feature {path} --output .ralph/prd-{moduleCode}.js
80
80
 
81
81
  ---
82
82
 
83
+ ### 2b. PRD v4.0 Structure (spec-oriented)
84
+
85
+ > **v4 PRDs are generated with `--v4` flag.** They use `expectedFiles` instead of `implementation.filesToCreate`.
86
+
87
+ ```json
88
+ {
89
+ "$version": "4.0.0",
90
+ "objectives": [
91
+ { "description": "...", "acceptanceCriteria": ["..."] }
92
+ ],
93
+ "expectedFiles": {
94
+ "domain": [...],
95
+ "application": [...],
96
+ "infrastructure": [...],
97
+ "api": [...],
98
+ "frontend": [...],
99
+ "seedData": [...],
100
+ "tests": [...],
101
+ "documentation": [...]
102
+ },
103
+ "gates": { /* declarative quality gate definitions */ }
104
+ }
105
+ ```
106
+
107
+ **Key differences from v3:**
108
+
109
+ | Aspect | v3 (`$version: "3.0.0"`) | v4 (`$version: "4.0.0"`) |
110
+ |--------|--------------------------|--------------------------|
111
+ | File manifest | `implementation.filesToCreate` | `expectedFiles` (root level) |
112
+ | Task model | `tasks[]` (pre-computed) | `objectives[]` (goal-oriented) |
113
+ | Execution | Batch iterations (compact-loop) | Continuous (compaction-enabled) |
114
+
115
+ **Consumer code must handle both:**
116
+ ```javascript
117
+ const fileManifest = prd.$version === '4.0.0'
118
+ ? prd.expectedFiles
119
+ : prd.implementation?.filesToCreate;
120
+ ```
121
+
122
+ ---
123
+
83
124
  ### 3. Eight Categories (MANDATORY)
84
125
 
85
126
  All PRD files MUST include these 8 categories under `implementation.filesToCreate`:
@@ -167,6 +208,64 @@ Each file entry in a category array must have:
167
208
 
168
209
  ---
169
210
 
211
+ ### 6. Specification Files (MANDATORY)
212
+
213
+ Each PRD MUST include a `specificationFiles` object and 5 companion files in `.ralph/`:
214
+
215
+ ```json
216
+ {
217
+ "$version": "3.0.0",
218
+ "implementation": { "filesToCreate": { /* 8 categories */ } },
219
+ "brToCodeMapping": [ /* enriched with statement, example, formula */ ],
220
+ "apiEndpointSummary": [ /* ... */ ],
221
+ "specificationFiles": {
222
+ "entities": "prd-{moduleCode}.entities.json",
223
+ "rules": "prd-{moduleCode}.rules.json",
224
+ "usecases": "prd-{moduleCode}.usecases.json",
225
+ "screens": "prd-{moduleCode}.screens.json",
226
+ "permissions": "prd-{moduleCode}.permissions.json"
227
+ }
228
+ }
229
+ ```
230
+
231
+ **Companion files** are VERBATIM copies of BA source files, colocated in `.ralph/`:
232
+
233
+ ```
234
+ .ralph/
235
+ prd-Employees.json # PRD manifest (compact)
236
+ prd-Employees.entities.json # VERBATIM copy of entities.json
237
+ prd-Employees.rules.json # VERBATIM copy of rules.json
238
+ prd-Employees.usecases.json # VERBATIM copy of usecases.json
239
+ prd-Employees.screens.json # VERBATIM copy of screens.json
240
+ prd-Employees.permissions.json # VERBATIM copy of permissions.json
241
+ ```
242
+
243
+ **Validation:**
244
+ ```javascript
245
+ const specFiles = prd.specificationFiles;
246
+ if (!specFiles) {
247
+ BLOCKING_ERROR('specificationFiles missing from PRD');
248
+ }
249
+ const specKeys = ['entities', 'rules', 'usecases', 'screens', 'permissions'];
250
+ for (const key of specKeys) {
251
+ if (!specFiles[key]) {
252
+ BLOCKING_ERROR(`specificationFiles.${key} missing`);
253
+ }
254
+ const filePath = path.join('.ralph', specFiles[key]);
255
+ if (!fs.existsSync(filePath)) {
256
+ BLOCKING_ERROR(`Companion file not found: ${filePath}`);
257
+ }
258
+ }
259
+ ```
260
+
261
+ **Why companion files matter:**
262
+ - `/apex` loads only the specs needed per layer (entities for L0, rules+usecases for L2, screens for L3)
263
+ - Context per layer is ~200-500 lines instead of ~2000 lines monolithic
264
+ - Zero risk of specs being lost at the bottom of a large context window
265
+ - Full BA detail available for oneshot generation (attributes, formulas, screen columns)
266
+
267
+ ---
268
+
170
269
  ## Validation Checklist
171
270
 
172
271
  Use this checklist when validating PRD files:
@@ -178,6 +277,7 @@ Use this checklist when validating PRD files:
178
277
  | **Categories** | All 8 categories present | PASS/FAIL |
179
278
  | **File Counts** | PRD counts match index.json handoff.filesToCreate | PASS/FAIL |
180
279
  | **File Schemas** | All files have path, type, module | PASS/FAIL |
280
+ | **Spec Files** | `specificationFiles` present with 5 paths, all companion files exist | PASS/FAIL |
181
281
 
182
282
  **All checks must PASS before proceeding to /business-analyse-develop**
183
283
 
@@ -151,13 +151,39 @@ Write via ba-writer.enrichModuleHandoff with the complete handoff payload:
151
151
  - totalFiles, totalTasks, handedOffAt (ISO timestamp)
152
152
  - featureDescription: {featureDescription}
153
153
 
154
+ ### Specification Files (MANDATORY)
155
+ After writing the handoff data, ALSO write 5 companion files:
156
+ 1. `.ralph/prd-{moduleCode}.entities.json` = VERBATIM copy of `{moduleDir}/entities.json`
157
+ 2. `.ralph/prd-{moduleCode}.rules.json` = VERBATIM copy of `{moduleDir}/rules.json`
158
+ 3. `.ralph/prd-{moduleCode}.usecases.json` = VERBATIM copy of `{moduleDir}/usecases.json`
159
+ 4. `.ralph/prd-{moduleCode}.screens.json` = VERBATIM copy of `{moduleDir}/screens.json`
160
+ 5. `.ralph/prd-{moduleCode}.permissions.json` = VERBATIM copy of `{moduleDir}/permissions.json`
161
+
162
+ Add `specificationFiles` to the PRD referencing these files (relative names, all in `.ralph/`):
163
+ ```json
164
+ "specificationFiles": {
165
+ "entities": "prd-{moduleCode}.entities.json",
166
+ "rules": "prd-{moduleCode}.rules.json",
167
+ "usecases": "prd-{moduleCode}.usecases.json",
168
+ "screens": "prd-{moduleCode}.screens.json",
169
+ "permissions": "prd-{moduleCode}.permissions.json"
170
+ }
171
+ ```
172
+
154
173
  ### POST-CHECK (BLOCKING)
155
174
  After writing, verify:
156
175
  1. Handoff not empty
157
176
  2. All 8 categories present
158
177
  3. brToCodeMapping non-empty
159
178
  4. Section resources have entity field
160
- Display: "POST-CHECK PASS: {moduleCode} -- 8 categories, {brCount} BRs mapped"
179
+ 5. SeedData contains CORE entries (NavigationModuleSeedData, NavigationSectionSeedData if sections exist, PermissionsSeedData, RolesSeedData)
180
+ 6. For FIRST module only: SeedData contains APP-LEVEL CORE entries (NavigationApplicationSeedData, ApplicationRolesSeedData)
181
+ 7. All 5 companion files exist in `.ralph/` and are non-empty
182
+ 8. `specificationFiles` present in the PRD with all 5 paths
183
+ 9. Entity count in companion matches source: `prd-{moduleCode}.entities.json` entities[] count = `{moduleDir}/entities.json` entities[] count
184
+ 10. BR count in companion matches source: `prd-{moduleCode}.rules.json` rules[] count = `{moduleDir}/rules.json` rules[] count
185
+ 11. Each `brToCodeMapping[].statement` is non-empty (not just a title paraphrase)
186
+ Display: "POST-CHECK PASS: {moduleCode} -- 8 categories, {brCount} BRs mapped, {coreCount} core seeds, 5 companion files"
161
187
  ```
162
188
 
163
189
  ### 3. Display Progress
@@ -91,6 +91,26 @@ for (const cat of categories) {
91
91
  BLOCKING_ERROR(`${cat}: prd=${prdCount} but feature=${featureCount}`);
92
92
  }
93
93
  }
94
+
95
+ // Check 5: Specification files (companion files)
96
+ const specFiles = prd.specificationFiles;
97
+ if (!specFiles) {
98
+ BLOCKING_ERROR("specificationFiles missing from PRD");
99
+ }
100
+ const specKeys = ['entities', 'rules', 'usecases', 'screens', 'permissions'];
101
+ for (const key of specKeys) {
102
+ if (!specFiles[key]) {
103
+ BLOCKING_ERROR(`specificationFiles.${key} path missing`);
104
+ }
105
+ const companionPath = `.ralph/${specFiles[key]}`;
106
+ if (!fileExists(companionPath)) {
107
+ BLOCKING_ERROR(`Companion file not found: ${companionPath}`);
108
+ }
109
+ const companionSize = fileSize(companionPath);
110
+ if (companionSize < 10) {
111
+ BLOCKING_ERROR(`Companion file empty or too small: ${companionPath} (${companionSize} bytes)`);
112
+ }
113
+ }
94
114
  ```
95
115
 
96
116
  Display verification table showing all 8 categories match between module JSON files and prd.json.
@@ -99,11 +119,13 @@ Display verification table showing all 8 categories match between module JSON fi
99
119
 
100
120
  ```json
101
121
  {
102
- "queue": [
103
- { "moduleCode": "{code}", "order": 1, "dependencies": [], "complexity": "simple" },
104
- { "moduleCode": "{code}", "order": 2, "dependencies": ["{dep}"], "complexity": "medium" }
122
+ "modules": [
123
+ { "code": "{code}", "prdFile": ".ralph/prd-{code}.json", "status": "pending", "order": 1, "dependencies": [], "complexity": "simple" },
124
+ { "code": "{code}", "prdFile": ".ralph/prd-{code}.json", "status": "pending", "order": 2, "dependencies": ["{dep}"], "complexity": "medium" }
105
125
  ],
106
- "totalModules": {count},
126
+ "currentIndex": 0,
127
+ "totalModules": "{count}",
128
+ "completedModules": 0,
107
129
  "strategy": "topological"
108
130
  }
109
131
  ```
@@ -185,10 +207,15 @@ Readiness Scores:
185
207
  └──────────────┴────────────┴──────────────┘
186
208
 
187
209
  Artifacts generated:
188
- .ralph/prd-{module}.json — Task breakdown per module
189
- .ralph/progress.txt Progression tracker
190
- .ralph/modules-queue.json Module execution order (if multi-module)
191
- docs/index.json BA manifest (status: handed-off)
210
+ .ralph/prd-{module}.json — Task breakdown per module
211
+ .ralph/prd-{module}.entities.json Entity specifications (companion)
212
+ .ralph/prd-{module}.rules.json Business rules (companion)
213
+ .ralph/prd-{module}.usecases.json Use cases (companion)
214
+ .ralph/prd-{module}.screens.json — Screen specifications (companion)
215
+ .ralph/prd-{module}.permissions.json — Permissions (companion)
216
+ .ralph/progress.txt — Progression tracker
217
+ .ralph/modules-queue.json — Module execution order (if multi-module)
218
+ docs/index.json — BA manifest (status: handed-off)
192
219
 
193
220
  [NEXT] Development:
194
221
  1. Run /business-analyse-develop to begin implementation
@@ -208,5 +235,8 @@ Artifacts generated:
208
235
  4. `docs/index.json` updated with correct entry count and status "handed-off"
209
236
  5. All PRD files have $version=3.0.0 or 4.0.0, file manifest present, 8 categories
210
237
  6. File counts match between PRD and handoff for all categories
238
+ 7. For EACH module: 5 companion files exist in `.ralph/` (entities, rules, usecases, screens, permissions)
239
+ 8. Each PRD contains `specificationFiles` with all 5 paths
240
+ 9. Each companion file is non-empty (>10 bytes)
211
241
 
212
242
  **IF any check fails -> fix before completing.**
@@ -378,13 +378,13 @@ body {
378
378
  .nav-icon-section { font-size: 0.5rem; color: var(--accent); }
379
379
  .nav-icon-resource { font-size: 0.7rem; color: var(--border-light); }
380
380
  .nav-resource-link {
381
- cursor: default;
381
+ cursor: pointer;
382
382
  font-size: 0.72rem;
383
383
  color: var(--text-muted);
384
384
  padding-top: 0.2rem;
385
385
  padding-bottom: 0.2rem;
386
386
  }
387
- .nav-resource-link:hover { background: transparent; color: var(--text-muted); }
387
+ .nav-resource-link:hover { background: var(--bg-hover); color: var(--accent); }
388
388
  .nav-resources { margin-left: 0.5rem; }
389
389
 
390
390
 
@@ -1031,6 +1031,44 @@ body {
1031
1031
  color: var(--text-muted);
1032
1032
  }
1033
1033
 
1034
+ /* ============================================
1035
+ STRUCTURE LEGEND
1036
+ ============================================ */
1037
+ .struct-legend {
1038
+ background: var(--bg-card);
1039
+ border: 1px solid var(--border);
1040
+ border-radius: 10px;
1041
+ padding: 0.75rem 1rem;
1042
+ margin-bottom: 1.25rem;
1043
+ }
1044
+ .struct-legend-title {
1045
+ font-size: 0.8rem;
1046
+ font-weight: 600;
1047
+ color: var(--text-muted);
1048
+ margin-bottom: 0.5rem;
1049
+ }
1050
+ .struct-legend-grid {
1051
+ display: grid;
1052
+ grid-template-columns: 1fr 1fr;
1053
+ gap: 0.4rem 1.5rem;
1054
+ }
1055
+ .struct-legend-item {
1056
+ font-size: 0.78rem;
1057
+ color: var(--text-muted);
1058
+ line-height: 1.4;
1059
+ }
1060
+ .struct-legend-code {
1061
+ display: inline-block;
1062
+ font-weight: 600;
1063
+ color: var(--accent);
1064
+ background: rgba(6,182,212,0.1);
1065
+ padding: 0.05rem 0.4rem;
1066
+ border-radius: 3px;
1067
+ font-size: 0.72rem;
1068
+ margin-right: 0.3rem;
1069
+ font-family: monospace;
1070
+ }
1071
+
1034
1072
  /* ============================================
1035
1073
  SECTION GROUPS (Hierarchical Mode)
1036
1074
  ============================================ */
@@ -2762,7 +2800,7 @@ function renderModuleNavItem(mod) {
2762
2800
  html += '<div class="nav-children nav-resources">';
2763
2801
  resources.forEach(function(res) {
2764
2802
  var resName = typeof res === 'string' ? res : (res.code || res.name || '');
2765
- html += '<a class="nav-item nav-resource-link">';
2803
+ html += '<a class="nav-item nav-resource-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'mock\');scrollToMockup(\'' + code + '\',\'' + section.code + '\')">';
2766
2804
  html += '<span class="nav-icon nav-icon-resource">&#8226;</span> ' + escapeHtml(resName);
2767
2805
  html += '</a>';
2768
2806
  });
@@ -2785,6 +2823,18 @@ function renderModuleTabNavItem(code, tabId, label, badge) {
2785
2823
  '</a>';
2786
2824
  }
2787
2825
 
2826
+ function scrollToMockup(moduleCode, sectionCode) {
2827
+ setTimeout(function() {
2828
+ var el = document.getElementById('screen-' + moduleCode + '-' + sectionCode);
2829
+ if (el) {
2830
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' });
2831
+ el.style.outline = '2px solid var(--accent)';
2832
+ el.style.borderRadius = '10px';
2833
+ setTimeout(function() { el.style.outline = ''; el.style.borderRadius = ''; }, 2000);
2834
+ }
2835
+ }, 150);
2836
+ }
2837
+
2788
2838
  /* ---------- Collapse/Expand ---------- */
2789
2839
 
2790
2840
  function toggleNavGroup(groupId) {
@@ -3916,7 +3966,16 @@ function renderModuleStructure(code) {
3916
3966
  '</div>';
3917
3967
  }
3918
3968
 
3919
- return sections.map(function(section) {
3969
+ var legend = '<div class="struct-legend">' +
3970
+ '<div class="struct-legend-title">&#9432; Types de sections</div>' +
3971
+ '<div class="struct-legend-grid">' +
3972
+ '<div class="struct-legend-item"><span class="struct-legend-code">list</span> Page principale — grille de données avec filtres, tri et actions (créer, exporter)</div>' +
3973
+ '<div class="struct-legend-item"><span class="struct-legend-code">detail</span> Fiche détaillée — affichée au clic sur une ligne, avec onglets (infos, relations, historique)</div>' +
3974
+ '<div class="struct-legend-item"><span class="struct-legend-code">dashboard</span> Tableau de bord — KPIs, graphiques et métriques du module</div>' +
3975
+ '<div class="struct-legend-item"><span class="struct-legend-code">approve</span> Workflow — file de validation avec actions (approuver, rejeter, mettre en attente)</div>' +
3976
+ '</div></div>';
3977
+
3978
+ return legend + sections.map(function(section) {
3920
3979
  var resources = section.resources || [];
3921
3980
  var sectionUCs = section.useCases || [];
3922
3981
  var sectionBRs = section.businessRules || [];
@@ -4295,7 +4354,7 @@ function renderScreenMockups(code) {
4295
4354
 
4296
4355
  return screens.map(function(screen, si) {
4297
4356
  var resources = screen.resources || [];
4298
- return '<div class="screen-section" style="margin-bottom:2rem;">' +
4357
+ return '<div class="screen-section" id="screen-' + code + '-' + screen.sectionCode + '" style="margin-bottom:2rem;">' +
4299
4358
  '<h3 style="color:var(--text-bright);font-size:1rem;margin-bottom:1rem;">' +
4300
4359
  '<span style="color:var(--accent);">&#9656;</span> ' + escapeHtml(screen.sectionLabel || screen.sectionCode) +
4301
4360
  '</h3>' +
@@ -182,7 +182,7 @@ function renderModuleNavItem(mod) {
182
182
  html += '<div class="nav-children nav-resources">';
183
183
  resources.forEach(function(res) {
184
184
  var resName = typeof res === 'string' ? res : (res.code || res.name || '');
185
- html += '<a class="nav-item nav-resource-link">';
185
+ html += '<a class="nav-item nav-resource-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'mock\');scrollToMockup(\'' + code + '\',\'' + section.code + '\')">';
186
186
  html += '<span class="nav-icon nav-icon-resource">&#8226;</span> ' + escapeHtml(resName);
187
187
  html += '</a>';
188
188
  });
@@ -205,6 +205,18 @@ function renderModuleTabNavItem(code, tabId, label, badge) {
205
205
  '</a>';
206
206
  }
207
207
 
208
+ function scrollToMockup(moduleCode, sectionCode) {
209
+ setTimeout(function() {
210
+ var el = document.getElementById('screen-' + moduleCode + '-' + sectionCode);
211
+ if (el) {
212
+ el.scrollIntoView({ behavior: 'smooth', block: 'start' });
213
+ el.style.outline = '2px solid var(--accent)';
214
+ el.style.borderRadius = '10px';
215
+ setTimeout(function() { el.style.outline = ''; el.style.borderRadius = ''; }, 2000);
216
+ }
217
+ }, 150);
218
+ }
219
+
208
220
  /* ---------- Collapse/Expand ---------- */
209
221
 
210
222
  function toggleNavGroup(groupId) {
@@ -620,7 +620,16 @@ function renderModuleStructure(code) {
620
620
  '</div>';
621
621
  }
622
622
 
623
- return sections.map(function(section) {
623
+ var legend = '<div class="struct-legend">' +
624
+ '<div class="struct-legend-title">&#9432; Types de sections</div>' +
625
+ '<div class="struct-legend-grid">' +
626
+ '<div class="struct-legend-item"><span class="struct-legend-code">list</span> Page principale — grille de données avec filtres, tri et actions (créer, exporter)</div>' +
627
+ '<div class="struct-legend-item"><span class="struct-legend-code">detail</span> Fiche détaillée — affichée au clic sur une ligne, avec onglets (infos, relations, historique)</div>' +
628
+ '<div class="struct-legend-item"><span class="struct-legend-code">dashboard</span> Tableau de bord — KPIs, graphiques et métriques du module</div>' +
629
+ '<div class="struct-legend-item"><span class="struct-legend-code">approve</span> Workflow — file de validation avec actions (approuver, rejeter, mettre en attente)</div>' +
630
+ '</div></div>';
631
+
632
+ return legend + sections.map(function(section) {
624
633
  var resources = section.resources || [];
625
634
  var sectionUCs = section.useCases || [];
626
635
  var sectionBRs = section.businessRules || [];
@@ -11,7 +11,7 @@ function renderScreenMockups(code) {
11
11
 
12
12
  return screens.map(function(screen, si) {
13
13
  var resources = screen.resources || [];
14
- return '<div class="screen-section" style="margin-bottom:2rem;">' +
14
+ return '<div class="screen-section" id="screen-' + code + '-' + screen.sectionCode + '" style="margin-bottom:2rem;">' +
15
15
  '<h3 style="color:var(--text-bright);font-size:1rem;margin-bottom:1rem;">' +
16
16
  '<span style="color:var(--accent);">&#9656;</span> ' + escapeHtml(screen.sectionLabel || screen.sectionCode) +
17
17
  '</h3>' +
@@ -110,11 +110,11 @@
110
110
  .nav-icon-section { font-size: 0.5rem; color: var(--accent); }
111
111
  .nav-icon-resource { font-size: 0.7rem; color: var(--border-light); }
112
112
  .nav-resource-link {
113
- cursor: default;
113
+ cursor: pointer;
114
114
  font-size: 0.72rem;
115
115
  color: var(--text-muted);
116
116
  padding-top: 0.2rem;
117
117
  padding-bottom: 0.2rem;
118
118
  }
119
- .nav-resource-link:hover { background: transparent; color: var(--text-muted); }
119
+ .nav-resource-link:hover { background: var(--bg-hover); color: var(--accent); }
120
120
  .nav-resources { margin-left: 0.5rem; }
@@ -443,6 +443,44 @@
443
443
  color: var(--text-muted);
444
444
  }
445
445
 
446
+ /* ============================================
447
+ STRUCTURE LEGEND
448
+ ============================================ */
449
+ .struct-legend {
450
+ background: var(--bg-card);
451
+ border: 1px solid var(--border);
452
+ border-radius: 10px;
453
+ padding: 0.75rem 1rem;
454
+ margin-bottom: 1.25rem;
455
+ }
456
+ .struct-legend-title {
457
+ font-size: 0.8rem;
458
+ font-weight: 600;
459
+ color: var(--text-muted);
460
+ margin-bottom: 0.5rem;
461
+ }
462
+ .struct-legend-grid {
463
+ display: grid;
464
+ grid-template-columns: 1fr 1fr;
465
+ gap: 0.4rem 1.5rem;
466
+ }
467
+ .struct-legend-item {
468
+ font-size: 0.78rem;
469
+ color: var(--text-muted);
470
+ line-height: 1.4;
471
+ }
472
+ .struct-legend-code {
473
+ display: inline-block;
474
+ font-weight: 600;
475
+ color: var(--accent);
476
+ background: rgba(6,182,212,0.1);
477
+ padding: 0.05rem 0.4rem;
478
+ border-radius: 3px;
479
+ font-size: 0.72rem;
480
+ margin-right: 0.3rem;
481
+ font-family: monospace;
482
+ }
483
+
446
484
  /* ============================================
447
485
  SECTION GROUPS (Hierarchical Mode)
448
486
  ============================================ */