@atlashub/smartstack-cli 4.17.1 → 4.18.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 (34) hide show
  1. package/package.json +1 -1
  2. package/templates/agents/ba-reader.md +9 -9
  3. package/templates/agents/ba-writer.md +13 -8
  4. package/templates/skills/business-analyse/SKILL.md +4 -4
  5. package/templates/skills/business-analyse/_rules.md +142 -0
  6. package/templates/skills/business-analyse/questionnaire/10-documentation.md +22 -7
  7. package/templates/skills/business-analyse/references/acceptance-criteria.md +4 -4
  8. package/templates/skills/business-analyse/references/agent-module-prompt.md +13 -9
  9. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +2 -2
  10. package/templates/skills/business-analyse/references/deploy-data-build.md +3 -2
  11. package/templates/skills/business-analyse/references/prd-generation.md +15 -10
  12. package/templates/skills/business-analyse/references/robustness-checks.md +12 -9
  13. package/templates/skills/business-analyse/references/team-orchestration.md +77 -6
  14. package/templates/skills/business-analyse/references/validation-checklist.md +7 -4
  15. package/templates/skills/business-analyse/schemas/shared/common-defs.json +2 -1
  16. package/templates/skills/business-analyse/steps/step-00-init.md +31 -63
  17. package/templates/skills/business-analyse/steps/step-01-cadrage.md +97 -7
  18. package/templates/skills/business-analyse/steps/step-03a1-setup.md +3 -23
  19. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +2 -3
  20. package/templates/skills/business-analyse/steps/step-03b-ui.md +2 -22
  21. package/templates/skills/business-analyse/steps/step-03c-compile.md +44 -139
  22. package/templates/skills/business-analyse/steps/step-03d-validate.md +198 -290
  23. package/templates/skills/business-analyse/steps/step-05a-handoff.md +117 -20
  24. package/templates/skills/ralph-loop/SKILL.md +8 -3
  25. package/templates/skills/ralph-loop/references/category-completeness.md +20 -4
  26. package/templates/skills/ralph-loop/references/compact-loop.md +80 -48
  27. package/templates/skills/ralph-loop/references/init-resume-recovery.md +3 -1
  28. package/templates/skills/ralph-loop/references/parallel-execution.md +27 -27
  29. package/templates/skills/ralph-loop/steps/step-00-init.md +19 -9
  30. package/templates/skills/ralph-loop/steps/step-01-task.md +10 -2
  31. package/templates/skills/ralph-loop/steps/step-02-execute.md +9 -4
  32. package/templates/skills/ralph-loop/steps/step-03-commit.md +1 -1
  33. package/templates/skills/ralph-loop/steps/step-04-check.md +5 -21
  34. package/templates/skills/ralph-loop/steps/step-05-report.md +6 -1
@@ -5,7 +5,7 @@ model: sonnet
5
5
  next_step: steps/step-03a1-setup.md OR steps/step-04a-collect.md (conditional)
6
6
  ---
7
7
 
8
- > **Context files:** `_shared.md` | `_module-loop.md`
8
+ > **Context files:** `_shared.md` | `_module-loop.md` | `_rules.md`
9
9
 
10
10
  # Step 3d: Validation & Loop
11
11
 
@@ -15,29 +15,24 @@ next_step: steps/step-03a1-setup.md OR steps/step-04a-collect.md (conditional)
15
15
  - This step VALIDATES the specification from step-03c, writes it to feature.json, and decides loop continuation
16
16
  - ALWAYS verify specification completeness before writing
17
17
  - ALL communication in `{language}`
18
+ - ALWAYS run the iteration safety guard BEFORE the loop decision (max 30 modules hard cap, 15 warning)
18
19
 
19
20
  ## MODE DETECTION (inherited from step-03a1)
20
21
 
21
22
  > **CRITICAL: Re-check your execution mode before proceeding.**
22
23
 
23
24
  **IF you are running as a TEAM AGENT** (your prompt contains `PROPOSE & REVIEW` or `team-lead` as recipient):
24
- → **NEVER** use `AskUserQuestion` in ANY section below (sections 9d, 10, 12)
25
- Section 9d: if validation fails, AUTO-CORRECT silently (no user options)
26
- Section 12: **SKIP ENTIRELY** — go directly to section 12-bis (Agent Mode)
25
+ → **NEVER** use `AskUserQuestion` in ANY phase below
26
+ Phase 3: if validation fails, AUTO-CORRECT silently (no user options)
27
+ Phase 6: **SKIP section 12** — go directly to section 12-bis (Agent Mode)
27
28
  → After writing feature.json, send `PROPOSAL_READY` to team lead via SendMessage
28
29
  → NEVER present options/menus to the user — you are an autonomous agent
29
30
 
30
31
  **IF you are running in the MAIN CONVERSATION** (classic inline mode):
31
32
  → Normal interactive mode — use `AskUserQuestion` as documented
32
33
  → Section 12-bis does NOT apply to you
33
- - **ID NAMING RULE (MANDATORY, NO EXCEPTION):**
34
- All IDs MUST include a module prefix to guarantee application-wide uniqueness.
35
- The prefix is derived from the module code initials (2-4 chars):
36
- UserManagement → UM | VehicleManagement → VM | PartsInventory → PI
37
- RepairManagement → RM | MaintenanceSchedule → MS | DataSync → DS
38
- Notifications → NT | Dashboard → DB | Orders → OR | Customers → CU
39
34
 
40
- NEVER use bare IDs (UC-001, BR-VAL-001) in multi-module mode.
35
+ - **Rules:** See `_rules.md` § "ID Naming Convention" (MANDATORY, NO EXCEPTION)
41
36
 
42
37
  ## YOUR TASK
43
38
 
@@ -45,150 +40,126 @@ Validate the module specification for completeness and consistency, write to fea
45
40
 
46
41
  ---
47
42
 
48
- ### 9. Per-Module Validation
43
+ ## Phase 1: AUTO-FIX (silent — no output)
49
44
 
50
- #### 9a. Completeness Checks
45
+ > **Apply all auto-fix rules BEFORE validation. No user interaction, no display.**
46
+
47
+ **1a. Wireframe field names** — Apply `_rules.md` § "Auto-Fix: Wireframe Field Names":
48
+ - For each wireframe in `specification.uiWireframes` (or `specification.wireframes`):
49
+ - Rename `title` → `screen`, `name` → `screen`, `ascii` → `mockup`, `content` → `mockup` (only if canonical field absent)
50
+ - Store normalized wireframes under `specification.uiWireframes`
51
+
52
+ **1b. Entity attribute types** — Apply `_rules.md` § "Auto-Fix: Entity Attribute Type Inference":
53
+ - For each entity attribute missing a `type` field, infer from the name pattern table
54
+ - Normalize free-text `validation` into structured `maxLength` where applicable
55
+ - Default `required` to `true` if undefined
56
+ - Log count of auto-fixed attributes as a warning (defense-in-depth — step-03c should have caught these)
57
+
58
+ ---
59
+
60
+ ## Phase 2: VALIDATE (single pass)
51
61
 
52
62
  > **CRITICAL:** Checks MUST count ACTUAL elements in arrays, NOT declarative values.
53
63
  > A check that reports PASS when the array is empty is a LIE and BLOCKS downstream quality.
64
+ > **Minimums:** See `_rules.md` § "Minimum Counts (Authoritative)" for all thresholds.
65
+
66
+ Run ALL checks in a single pass. Each check has: name | minimum | blocking? | how to verify.
67
+
68
+ ### Completeness Checks
69
+
70
+ | Check | Min | Blocking | How to verify |
71
+ |-------|-----|----------|---------------|
72
+ | entities | ≥ 2 | YES | `analysis.entities.length >= 2` |
73
+ | entity attributes (each) | ≥ 3 | YES | Every entity has `attributes.length >= 3` |
74
+ | entitySchemaFormat | attributes[] not fields[] | YES | `analysis.entities.every(e => e.attributes?.length > 0)` — no `tableName` or `primaryKey` |
75
+ | entityAttributeTypes | ALL have `type` | YES | `analysis.entities.every(e => e.attributes.every(a => a.type))` |
76
+ | actors | ≥ 2 | YES | `specification.actors.length >= 2` |
77
+ | useCases | ≥ 6 | YES | `specification.useCases.length >= 6` |
78
+ | functionalRequirements | ≥ 4 | YES | `specification.functionalRequirements.length >= 4` |
79
+ | permissionMatrix | ≥ 5 perms, ≥ 2 roles | YES | `permissionMatrix.permissions.length >= 5 && permissionMatrix.roleAssignments.length >= 2` |
80
+ | sections | ≥ 2 | YES | `specification.sections.length >= 2` |
81
+ | wireframes | 1 per section | YES | `uiWireframes.length >= sections.length` (check BOTH key names) |
82
+ | wireframeSchema | All required fields | YES | Every wireframe has: `screen`, `section`, `mockupFormat`, `elements[]` (non-empty), `componentMapping[]`, `layout` (object), `permissionsRequired[]` |
83
+ | navigation | entries[] present | YES | `specification.navigation?.entries?.length >= 1` |
84
+ | seedDataCore | 9 arrays present | YES | See seedDataCore detail below |
85
+ | messages | ≥ 4 | YES | `specification.messages.length >= 4` |
86
+ | validations | ≥ 1 | YES | `specification.validations.length >= 1` |
87
+ | apiEndpoints | ≥ 5 | YES | `specification.apiEndpoints.length >= 5` |
88
+ | i18nKeys | ≥ 42 leaves, 4 langs | YES | All leaf keys have fr/en/it/de |
89
+ | gherkinScenarios | array, ≥ 1 entry | YES | `Array.isArray(gherkinScenarios) && gherkinScenarios.length >= 1` |
90
+ | gherkinCount | ≥ 2 scenarios | NO (WARN) | Total scenario count across all entries |
91
+ | lifeCycles | ≥ 1 (if entity has status) | YES | `specification.lifeCycles.length >= 1` if applicable |
92
+ | dataLifecycle | present | YES | `analysis.dataLifecycle !== undefined` |
93
+ | navigationIcons | non-null | YES | All navigation modules have non-null icon |
94
+
95
+ **seedDataCore detail:** Verify all 9 arrays per `_rules.md` § "Minimum Counts":
96
+
97
+ | Array | Min (1st module) | Min (2nd+ module) |
98
+ |---|---|---|
99
+ | navigationApplications | 1 | 0 |
100
+ | applicationRoles | 1 | 0 |
101
+ | navigationModules | 1 | 1 |
102
+ | navigationSections | 1 | 1 |
103
+ | navigationResources | 1 | 1 |
104
+ | navigationTranslations | 2 | 2 |
105
+ | permissions | 1 | 1 |
106
+ | rolePermissions | 1 | 1 |
107
+ | permissionConstants | 1 | 1 |
108
+
109
+ ### Consistency Checks
110
+
111
+ | Check | Blocking | Rule |
112
+ |-------|----------|------|
113
+ | UC-FR linkage | YES | Every UC has ≥ 1 linked FR |
114
+ | FR-BR linkage | NO (WARN) | Every FR has ≥ 1 linked BR |
115
+ | BR references valid | YES | All BR references exist in `analysis.businessRules` |
116
+ | Actors in permissions | YES | All actors appear in `permissionMatrix` |
117
+ | Permission path format | YES | Module-level `{app}.{module}.{action}` or section-level `{app}.{module}.{section}.{action}` |
118
+ | rolePermissions paths | YES | All paths match `permissions` paths |
119
+ | API route prefix | YES | Consistent prefix across endpoints |
120
+
121
+ ### Convention Checks
122
+
123
+ | Check | Blocking | Rule |
124
+ |-------|----------|------|
125
+ | UC ID format | YES | `UC-{PREFIX}-{NNN}` with module prefix |
126
+ | FR ID format | YES | `FR-{PREFIX}-{NNN}` |
127
+ | BR ID format | YES | `BR-{CAT}-{PREFIX}-{NNN}` |
128
+ | Entity names | YES | PascalCase |
129
+ | Field names | YES | camelCase |
130
+ | Permission paths | YES | Dot-separated lowercase |
131
+ | Navigation routes | YES | No `/list` or `/detail/:id` suffixes |
132
+
133
+ ### Format Checks
134
+
135
+ > See `_rules.md` § "Format Checks" for canonical rules.
136
+
137
+ | Check | Blocking | Rule |
138
+ |-------|----------|------|
139
+ | gherkinFormat | YES | Array `[{feature, scenarios}]`, not single object |
140
+ | gherkinContent | YES | Each entry has `feature` (string) + `scenarios` (array) |
141
+ | validationFormat | YES | `validations[].rules` is array, not singular string |
142
+ | messageFormat | YES | `messages[]` has `message` field |
143
+ | wireframeFields | YES | Uses `screen` (not `title`/`name`), `mockup` (not `ascii`/`content`) |
144
+
145
+ ### Failure Handling
146
+
147
+ IF any blocking check fails:
148
+ - **CONDITIONAL LOAD:** Read `references/validation-checklist.md` for detailed fix guidance
149
+ - Display table of failures with details and fix recommendations
150
+ - **BLOCKING ERROR:** Module specification incomplete → fix all failures before proceeding
151
+
152
+ IF all blocking checks pass:
153
+ - Display warning count (non-blocking)
154
+ - Proceed to Phase 3
54
155
 
55
- | Section | Minimum | How to verify | Status |
56
- |---------|---------|---------------|--------|
57
- | actors | 2 | `specification.actors.length >= 2` | PASS/FAIL |
58
- | useCases | 2 | `specification.useCases.length >= 2` | PASS/FAIL |
59
- | functionalRequirements | 4 | `specification.functionalRequirements.length >= 4` | PASS/FAIL |
60
- | permissionMatrix | 1 resource × 2 roles | `specification.permissionMatrix.permissions.length >= 1 && specification.permissionMatrix.roleAssignments.length >= 2` | PASS/FAIL |
61
- | entities | 1 | `analysis.entities.length >= 1` | PASS/FAIL |
62
- | entitySchemaFormat | attributes[] not fields[] (BLOCKING) | `analysis.entities.every(e => e.attributes?.length > 0)` | PASS/FAIL |
63
- | entityAttributeTypes | ALL attributes have `type` field (BLOCKING) | `analysis.entities.every(e => e.attributes.every(a => a.type))` — **NOTE:** Entities in analysis phase may NOT have `type`. Step-03c auto-fix MUST have run first. If types are missing, RE-RUN step-03c auto-fix algorithm. | PASS/FAIL |
64
- | navigation | entries[] present (BLOCKING) | `specification.navigation?.entries?.length >= 1` | PASS/FAIL |
65
- | dataLifecycle | present in analysis (BLOCKING) | `analysis.dataLifecycle !== undefined` | PASS/FAIL |
66
- | wireframes | 1 per section (BLOCKING) | `(specification.uiWireframes \|\| specification.wireframes \|\| []).length >= (specification.sections \|\| []).length` (count REAL elements, check BOTH key names) | PASS/FAIL |
67
- | wireframeSchema | All required fields present (BLOCKING) | `(specification.uiWireframes \|\| specification.wireframes \|\| []).every(w => (w.screen \|\| w.title) && w.section && (w.mockup \|\| w.ascii \|\| w.content))` | PASS/FAIL |
68
- | sections | 1 (BLOCKING) | `specification.sections.length >= 1` (EVERY module needs at least 1 section) | PASS/FAIL |
69
- | gherkinScenarios | 1 array entry | `Array.isArray(specification.gherkinScenarios) && specification.gherkinScenarios.length >= 1` | PASS/FAIL |
70
- | gherkinFormat | Array not object (BLOCKING) | `Array.isArray(specification.gherkinScenarios)` (NOT a single object) | PASS/FAIL |
71
- | validations | 1 | `specification.validations.length >= 1` | PASS/FAIL |
72
- | validationFormat | rules[] array (BLOCKING) | `specification.validations.every(v => Array.isArray(v.rules))` (NOT singular `rule`) | PASS/FAIL |
73
- | messages | 4 | `specification.messages.length >= 4` | PASS/FAIL |
74
- | messageFormat | `message` field present (BLOCKING) | `specification.messages.every(m => m.message)` | PASS/FAIL |
75
- | lifeCycles | 1 (if entity has status) | `specification.lifeCycles.length >= 1` (if any entity has status/state field) | PASS/FAIL |
76
- | seedDataCore | 9 arrays present with content | See detailed check below | PASS/FAIL (BLOCKING) |
77
- | apiEndpoints | 1 | `specification.apiEndpoints.length >= 1` | PASS/FAIL |
78
- | i18nKeys | present | `specification.i18nKeys !== undefined && specification.i18nKeys !== null` | PASS/FAIL |
79
- | navigationIcons | non-null | `specification.seedDataCore.navigationModules.every(m => m.icon !== null)` | PASS/FAIL |
80
-
81
- **seedDataCore detailed check (BLOCKING):**
82
- ```javascript
83
- const sdc = specification.seedDataCore;
84
- const currentModuleIndex = metadata.workflow?.currentModuleIndex || 0;
85
- const checks = [
86
- // navigationApplications and applicationRoles: required for first module (index 0), can be empty for subsequent modules
87
- { key: "navigationApplications", actual: sdc.navigationApplications?.length || 0, min: currentModuleIndex === 0 ? 1 : 0 },
88
- { key: "applicationRoles", actual: sdc.applicationRoles?.length || 0, min: currentModuleIndex === 0 ? 1 : 0 },
89
- { key: "navigationModules", actual: sdc.navigationModules?.length || 0, min: 1 },
90
- { key: "navigationSections", actual: sdc.navigationSections?.length || 0, min: 1 }, // EVERY module needs ≥1 section
91
- { key: "navigationResources", actual: sdc.navigationResources?.length || 0, min: 1 },
92
- { key: "navigationTranslations", actual: sdc.navigationTranslations?.length || 0, min: 2 }, // min fr+en
93
- { key: "permissions", actual: sdc.permissions?.length || 0, min: 1 },
94
- { key: "rolePermissions", actual: sdc.rolePermissions?.length || 0, min: 1 },
95
- { key: "permissionConstants", actual: sdc.permissionConstants?.length || 0, min: 1 }
96
- ];
97
- const failures = checks.filter(c => c.actual < c.min);
98
- IF failures.length > 0:
99
- BLOCKING ERROR: "seedDataCore incomplete — empty arrays: {failures.map(f => f.key).join(', ')}"
100
- → Fix: Ensure specification.sections[] has ≥1 entry, then re-run 8f-bis transform
101
- ```
102
-
103
- #### 9b. Consistency Checks
104
-
105
- - Every UC has ≥1 linked FR
106
- - Every FR has ≥1 linked BR
107
- - All BR references exist in analysis.businessRules
108
- - All actors appear in permissionMatrix
109
- - Permission paths use correct format: module-level `{app}.{module}.{action}` or section-level `{app}.{module}.{section}.{action}`
110
- - rolePermissions paths match permissions paths
111
- - API routes use consistent prefix
112
-
113
- #### 9c. Convention Checks
114
-
115
- - UC-NNN format
116
- - FR-NNN format
117
- - BR-{CATEGORY}-NNN format
118
- - Entity names PascalCase
119
- - Field names camelCase
120
- - Entity attribute format: `attributes[]` with {name, description}, NOT `fields[]` with {name, type} — entities must NOT have tableName or primaryKey
121
- - Wireframe structure: `screen` (not `name`/`title`), `mockup` (not `ascii`/`content`), `componentMapping` is array of {wireframeElement, reactComponent} (not plain key-value object), `layout` is object with regions (not string)
122
- - Wireframe field naming: uses `screen` (not `title`), `mockup` (not `ascii`) — auto-fix if wrong (see 9c-fix below)
123
- - Permission paths dot-separated lowercase
124
-
125
- #### 9c-fix. Auto-Fix Wireframe Field Names (MANDATORY before writing)
126
-
127
- > **CRITICAL:** The agent may use non-canonical field names (`title`, `ascii`, `name`, `content`).
128
- > These MUST be normalized to canonical names before writing to feature.json.
129
-
130
- ```javascript
131
- // AUTO-FIX: Normalize wireframe field names before writing
132
- const wireframes = specification.uiWireframes || specification.wireframes || [];
133
- for (const wf of wireframes) {
134
- if (wf.title && !wf.screen) { wf.screen = wf.title; delete wf.title; }
135
- if (wf.ascii && !wf.mockup) { wf.mockup = wf.ascii; delete wf.ascii; }
136
- if (wf.content && !wf.mockup) { wf.mockup = wf.content; delete wf.content; }
137
- if (wf.name && !wf.screen) { wf.screen = wf.name; delete wf.name; }
138
- }
139
- // Store normalized wireframes back under canonical key
140
- specification.uiWireframes = wireframes;
141
- ```
156
+ ---
142
157
 
143
- #### 9c-fix-entities. Auto-Fix Entity Attribute Types (MANDATORY before writing)
144
-
145
- > **DEFENSE-IN-DEPTH:** step-03c POST-CHECK should catch attributes without `type`,
146
- > but if any slip through to step-03d, auto-fix them here before writing to feature.json.
147
- > Uses the same type inference algorithm as step-03c POST-CHECK.
148
-
149
- ```javascript
150
- // AUTO-FIX: Ensure all entity attributes have structured type
151
- const entities = analysis.entities || [];
152
- let entityAutoFixCount = 0;
153
- for (const entity of entities) {
154
- for (const attr of entity.attributes || []) {
155
- if (!attr.type) {
156
- // Infer type from attribute name pattern
157
- if (attr.validation?.match(/max\s*\d+/i) || attr.name.match(/name|title|code|description|label|email|phone|address/i)) {
158
- attr.type = "string";
159
- const maxMatch = attr.validation?.match(/max\s*(\d+)/i);
160
- if (maxMatch) attr.maxLength = parseInt(maxMatch[1]);
161
- } else if (attr.name.match(/id$/i)) {
162
- attr.type = "Guid";
163
- } else if (attr.name.match(/date|At$/i)) {
164
- attr.type = "DateTime";
165
- } else if (attr.name.match(/is[A-Z]|has[A-Z]|active|enabled/)) {
166
- attr.type = "bool";
167
- } else if (attr.name.match(/amount|salary|rate|price|total/i)) {
168
- attr.type = "decimal";
169
- } else if (attr.name.match(/count|number|order|sort|index/i)) {
170
- attr.type = "int";
171
- } else {
172
- attr.type = "string"; // safe default
173
- }
174
- // Normalize free-text maxLength
175
- if (typeof attr.validation === 'string' && !attr.maxLength) {
176
- const m = attr.validation.match(/max\s*(\d+)/i);
177
- if (m) attr.maxLength = parseInt(m[1]);
178
- }
179
- if (attr.required === undefined) attr.required = true;
180
- entityAutoFixCount++;
181
- }
182
- }
183
- }
184
- if (entityAutoFixCount > 0) {
185
- console.warn(`DEFENSE-IN-DEPTH: auto-fixed ${entityAutoFixCount} attributes without type in step-03d`);
186
- }
187
- ```
158
+ ## Phase 3: DECIDE + WRITE VALIDATION
188
159
 
189
- #### 9d. Decision
160
+ ### 3a. Decision
190
161
 
191
- > **TEAM AGENT MODE:** If running as team agent, SKIP AskUserQuestion. On FAIL → auto-correct silently. On PASS → proceed directly to section 11 (write). NEVER present options to the user.
162
+ > **TEAM AGENT MODE:** If running as team agent, SKIP AskUserQuestion. On FAIL → auto-correct silently. On PASS → proceed directly. NEVER present options to the user.
192
163
 
193
164
  **INLINE MODE ONLY (main conversation):**
194
165
 
@@ -207,9 +178,9 @@ IF validation FAIL:
207
178
  description: "Accepter malgré les erreurs (risqué)"
208
179
  ```
209
180
 
210
- #### 9e. Write Module Validation Section (MANDATORY)
181
+ ### 3b. Write Module Validation Section (MANDATORY)
211
182
 
212
- > **The module feature.json MUST have a `validation` section recording the results of steps 9a-9d.**
183
+ > **The module feature.json MUST have a `validation` section recording the results of Phase 2.**
213
184
 
214
185
  ```
215
186
  ba-writer.enrichSection({
@@ -218,10 +189,10 @@ ba-writer.enrichSection({
218
189
  data: {
219
190
  validatedAt: "{ISO timestamp}",
220
191
  completenessChecks: [
221
- { "section": "useCases", "count": {count}, "minimum": 2, "status": "PASS|FAIL" },
192
+ { "section": "useCases", "count": {count}, "minimum": 6, "status": "PASS|FAIL" },
222
193
  { "section": "functionalRequirements", "count": {count}, "minimum": 4, "status": "PASS|FAIL" },
223
194
  { "section": "wireframes", "count": {count}, "minimum": {section_count}, "status": "PASS|FAIL" },
224
- { "section": "seedDataCore", "count": 7, "minimum": 7, "status": "PASS|FAIL" }
195
+ { "section": "seedDataCore", "count": 9, "minimum": 9, "status": "PASS|FAIL" }
225
196
  ],
226
197
  consistencyChecks: [
227
198
  { "check": "UC-FR linkage", "passed": {n}, "warnings": {n}, "errors": {n}, "status": "PASS|FAIL" },
@@ -249,73 +220,11 @@ ba-writer.enrichSection({
249
220
  })
250
221
  ```
251
222
 
252
- #### 9e-POST-CHECK: Validation Section Persistence (BLOCKING)
253
-
254
- > **CRITICAL:** The `validation` section MUST be persisted to feature.json. Without it, consolidation checks fail.
255
-
256
- ```bash
257
- MODULE_JSON="{module_feature_json_path}"
258
- node -e "const d=JSON.parse(require('fs').readFileSync(process.argv[1],'utf-8'));
259
- if(!d.validation||!d.validation.decision) { console.error('FAIL: validation section missing or incomplete'); process.exit(1); }
260
- console.log('PASS: validation section present with decision');" "$MODULE_JSON"
261
- ```
262
-
263
- IF this check FAILS → re-execute section 9e write and re-run this check.
264
-
265
- #### 9f. Module Specification Checklist (BLOCKING)
266
-
267
- > **CRITICAL:** This checklist MUST be FULLY COMPLETED before marking module status = "specified".
268
-
269
- **Execute the comprehensive validation checklist:**
270
-
271
- Run the 29-check validation process across 10 categories:
272
- - Data Model (4 checks) | Business Rules (3 checks) | Use Cases & FRs (4 checks)
273
- - Permissions (3 checks) | UI & Navigation (4 checks) | I18N & Messages (3 checks)
274
- - Seed Data (2 checks) | API Endpoints (2 checks) | Validations (1 check) | Gherkin (3 checks)
275
-
276
- ```javascript
277
- const blockingFailures = checks.filter(c => c.blocking && c.status === "FAIL");
278
-
279
- IF blockingFailures.length > 0:
280
- // CONDITIONAL LOAD: Only load detailed checklist on validation failure
281
- Read references/validation-checklist.md
282
- Display:
283
- - Full validation logic for FAILED checks
284
- - Exact requirements (minimums, patterns, formats)
285
- - Fix recommendations for each failure
286
-
287
- BLOCKING ERROR: Module specification incomplete
288
- → Fix all failures before proceeding
289
-
290
- ELSE:
291
- All blocking checks passed ✓
292
- Display: "{warnings_count} warnings (non-blocking)"
293
- → Proceed to mark module as "specified"
294
- ```
295
-
296
- **Optimization:** The detailed 280-line validation-checklist.md is loaded **only when validation fails** (saves ~10,000 tokens on success path).
297
-
298
223
  ---
299
224
 
300
- ### 9g. Anti-Premature-Completion Guard (MANDATORY)
301
-
302
- > **CRITICAL — NEVER say "the analysis is complete" or "ready for /ralph-loop" at this point.**
303
- > Step-03d is the END of SPECIFICATION, NOT the end of the BA workflow.
304
- > Steps 04a → 04b → 04c (consolidation) + 05a → 05b → 05c (handoff) are STILL REQUIRED.
305
- > Without handoff, /ralph-loop will generate an INCOMPLETE PRD (no frontend, no tests).
306
-
307
- **FORBIDDEN phrases in step-03d output:**
308
- - "L'analyse métier est complète" / "The business analysis is complete"
309
- - "Prêt pour /ralph-loop" / "Ready for /ralph-loop"
310
- - "Vous pouvez maintenant lancer /ralph-loop"
311
- - Any variation suggesting the BA is finished or /ralph-loop can be invoked
312
-
313
- **REQUIRED phrasing:**
314
- - "Module {name} spécifié. {Remaining} modules restants." (if more modules)
315
- - "Tous les modules spécifiés. Passage à la consolidation (étapes 04a-04c)..." (if last module)
316
- - NEVER mention /ralph-loop — only step-05c (ralph readiness) validates the handoff
225
+ ## Phase 4: SUMMARY + WRITE FEATURE.JSON
317
226
 
318
- ### 10. Module Summary with Roles & Permissions
227
+ ### 4a. Module Summary with Roles & Permissions
319
228
 
320
229
  Display comprehensive summary:
321
230
 
@@ -349,15 +258,19 @@ Display comprehensive summary:
349
258
 
350
259
  {IF validation PASS}:
351
260
  → Module validé automatiquement
352
- → Passage automatique au module suivant (section 12)
261
+ → Passage automatique au module suivant (Phase 6)
353
262
 
354
263
  {IF validation FAIL}:
355
- → Afficher les erreurs et offrir les options de correction (section 9d)
264
+ → Afficher les erreurs et offrir les options de correction (Phase 3)
356
265
  ```
357
266
 
358
- ---
267
+ > **Anti-Premature-Completion Guard:** NEVER say "the analysis is complete" or "ready for /ralph-loop" at this point.
268
+ > Step-03d is the END of SPECIFICATION, NOT the end of the BA workflow.
269
+ > Steps 04a → 04b → 04c (consolidation) + 05a → 05b → 05c (handoff) are STILL REQUIRED.
270
+ > **FORBIDDEN phrases:** "L'analyse métier est complète", "Prêt pour /ralph-loop", "Vous pouvez maintenant lancer /ralph-loop"
271
+ > **REQUIRED phrasing:** "Module {name} spécifié. {Remaining} modules restants." or "Tous les modules spécifiés. Passage à la consolidation (étapes 04a-04c)..."
359
272
 
360
- ### 11. Write Module Feature.json
273
+ ### 4b. Write Module Feature.json
361
274
 
362
275
  ```
363
276
  // Write analysis section with ALL subsections
@@ -383,7 +296,7 @@ ba-writer.enrichSection({
383
296
  functionalRequirements: [{id, statement, priority, linkedRules, linkedUseCases, acceptanceCriteria}], // 8c
384
297
  permissionMatrix: {permissions: [], roleAssignments: []}, // 8d
385
298
  navigation: {entries: []}, // 8e
386
- seedDataCore: {navigationModules, navigationSections, navigationResources, navigationTranslations, permissions, rolePermissions, permissionConstants}, // 8f (7 arrays)
299
+ seedDataCore: {navigationApplications, applicationRoles, navigationModules, navigationSections, navigationResources, navigationTranslations, permissions, rolePermissions, permissionConstants}, // 8f (9 arrays)
387
300
  gherkinScenarios: [{feature, scenarios: [{name, tags, given, when, then}]}], // 8g
388
301
  validations: [{entity, field, rules, errorMessageKey}], // 8h
389
302
  messages: [{code, type, title, message, i18nKey}], // 8i
@@ -396,8 +309,8 @@ ba-writer.enrichSection({
396
309
  }
397
310
  })
398
311
 
399
- // Write validation results from step 9
400
- // (Already written in step 9e above)
312
+ // Write validation results from Phase 3
313
+ // (Already written in Phase 3b above)
401
314
 
402
315
  ba-writer.updateStatus({module_feature_id}, "specified")
403
316
 
@@ -405,52 +318,21 @@ ba-writer.updateStatus({module_feature_id}, "specified")
405
318
  ba-writer.updateModuleStatus({feature_id}, {currentModule.code}, "specified")
406
319
  ```
407
320
 
408
- #### 11-POST-CHECK: Verify Written Data (BLOCKING)
409
-
410
- > **CRITICAL — Data loss prevention.** After writing, READ BACK the module feature.json and verify the following arrays are **non-empty**:
411
-
412
- ```javascript
413
- // READ BACK the written feature.json
414
- const written = ba-reader.read({module_feature_id});
415
-
416
- // BLOCKING checks — if ANY fails, the write was incomplete
417
- const checks = [
418
- { key: "specification.actors", actual: written.specification?.actors?.length, min: 2 },
419
- { key: "specification.useCases", actual: written.specification?.useCases?.length, min: 2 },
420
- { key: "specification.wireframes", actual: (written.specification?.uiWireframes?.length || written.specification?.wireframes?.length || 0), min: 1 },
421
- { key: "specification.sections", actual: written.specification?.sections?.length, min: 1 },
422
- { key: "specification.seedDataCore", actual: Object.keys(written.specification?.seedDataCore || {}).length, min: 7 },
423
- { key: "specification.lifeCycles", actual: written.specification?.lifeCycles?.length, min: 0 },
424
- { key: "specification.gherkinScenarios",actual: written.specification?.gherkinScenarios?.length,min: 1 },
425
- { key: "specification.apiEndpoints", actual: written.specification?.apiEndpoints?.length, min: 1 }
426
- ];
427
-
428
- const failures = checks.filter(c => (c.actual || 0) < c.min);
429
-
430
- IF failures.length > 0:
431
- BLOCKING ERROR: "Feature.json write INCOMPLETE — missing data in: {failures.map(f => f.key).join(', ')}"
432
- → Re-execute section 11 write with ALL specification data
433
- → DO NOT proceed to next module until ALL checks pass
434
-
435
- // SPECIAL CHECK: wireframes content verification (check BOTH key names)
436
- const wireframes = written.specification?.uiWireframes || written.specification?.wireframes || [];
437
- IF wireframes.length > 0:
438
- const emptyMockups = wireframes.filter(wf => !wf.mockup && !wf.ascii && !wf.content);
439
- IF emptyMockups.length > 0:
440
- WARNING: "{emptyMockups.length} wireframes have empty mockup content — verify step-03b data"
441
-
442
- // SPECIAL CHECK: wireframes >= sections
443
- const sectionCount = written.specification?.sections?.length || 0;
444
- IF wireframes.length < sectionCount:
445
- BLOCKING ERROR: "{wireframes.length} wireframes < {sectionCount} sections — wireframes MISSING for some sections"
446
- → Re-read wireframes from conversation context and re-write to feature.json
447
- ```
321
+ ---
448
322
 
449
- #### 11-POST-CHECK-BASH: Acceptance Criteria Verification (BLOCKING)
323
+ ## Phase 5: VERIFY (bash)
450
324
 
451
- > **CRITICAL:** The pseudocode checks above are interpreted by the model — they can be "passed" incorrectly.
325
+ > **CRITICAL:** The validation checks in Phase 2 are interpreted by the model — they can be "passed" incorrectly.
452
326
  > This bash check reads the REAL file on disk and provides an objective verification.
453
- > See [references/acceptance-criteria.md](../references/acceptance-criteria.md) for the full acceptance criteria definition.
327
+ >
328
+ > **Canonical acceptance criteria (AC-01 to AC-17):** See [references/acceptance-criteria.md](../references/acceptance-criteria.md).
329
+ > The script below EXTENDS those criteria with step-03d-specific checks:
330
+ > - Navigation entries present (`specification.navigation.entries`)
331
+ > - `analysis.dataLifecycle` section present
332
+ > - `validation` section recorded
333
+ > - i18n 4-language completeness (AC-18)
334
+ >
335
+ > If you need the standalone script (for debugging or handoff gate), use the one in `acceptance-criteria.md`.
454
336
 
455
337
  ```bash
456
338
  MODULE_JSON="{module_feature_json_path}"
@@ -462,13 +344,15 @@ const analysis = data.analysis || {};
462
344
  const wf = spec.uiWireframes || spec.wireframes || [];
463
345
  const sections = spec.sections || [];
464
346
  const checks = [
465
- ['entities >= 1', (analysis.entities||[]).length, 1],
347
+ ['entities >= 2', (analysis.entities||[]).length, 2],
466
348
  ['useCases >= 2', (spec.useCases||[]).length, 2],
467
349
  ['FRs >= 4', (spec.functionalRequirements||[]).length,4],
468
350
  ['wireframes >= 1', wf.length, 1],
469
351
  ['wireframes >= sections', wf.length, sections.length],
470
352
  ['sections >= 1', sections.length, 1],
471
- ['seedDataCore 7 arrays', Object.keys(spec.seedDataCore||{}).filter(k=>(spec.seedDataCore||{})[k]&&(spec.seedDataCore||{})[k].length>0).length, 7],
353
+ // CP-02: modules 2+ may have navigationApplications=[] and applicationRoles=[] (correct per _rules.md)
354
+ // Minimum = 9 for first module, 7 for subsequent modules
355
+ ['seedDataCore arrays', (() => { const sdc=spec.seedDataCore||{}; return Object.keys(sdc).filter(k=>Array.isArray(sdc[k])&&sdc[k].length>0).length; })(), (() => { const sdc=spec.seedDataCore||{}; const hasApp=(sdc.navigationApplications||[]).length>0||(sdc.applicationRoles||[]).length>0; return hasApp?9:7; })()],
472
356
  ['gherkin is array', Array.isArray(spec.gherkinScenarios)?1:0, 1],
473
357
  ['apiEndpoints >= 1', (spec.apiEndpoints||[]).length, 1],
474
358
  ['messages >= 4', (spec.messages||[]).length, 4],
@@ -516,15 +400,13 @@ IF this check FAILS:
516
400
  - Identify which criteria failed from the output
517
401
  - Fix the corresponding data (re-read from conversation context, re-generate, or re-run the step that produces it)
518
402
  - Re-write to feature.json
519
- - Re-run the POST-CHECK until PASS
520
-
521
- > **WHY:** Step-03b now writes wireframes intermediately (since fix), but step-03d section 11 does the FULL write.
522
- > This bash POST-CHECK is the ultimate safety net — it reads the REAL file and verifies ALL acceptance criteria.
523
- > The pseudocode checks (section 9a) catch issues early; this bash check catches anything the model missed.
403
+ - Re-run this check until PASS
524
404
 
525
405
  ---
526
406
 
527
- ### 11-bis. Deploy Incremental Interactive HTML (MANDATORY)
407
+ ## Phase 6: DEPLOY + ROUTE
408
+
409
+ ### 6a. Deploy Incremental Interactive HTML (MANDATORY)
528
410
 
529
411
  > **After each module is specified, deploy/update the interactive HTML document with all available data.**
530
412
  > The client can review completed modules while the next module is being specified.
@@ -535,7 +417,46 @@ Uses the **same mapping** as step-05b-deploy.md — only difference is `moduleSp
535
417
 
536
418
  ---
537
419
 
538
- ### 12. Loop Decision
420
+ ### 6b. Iteration Safety Guard (MAX MODULES CHECK)
421
+
422
+ > **DEFENSIVE CHECK — Run BEFORE loop decision to prevent infinite loops.**
423
+
424
+ ```
425
+ // Read loop state from feature.json
426
+ const moduleOrder = metadata.workflow.moduleOrder || [];
427
+ const completedModules = metadata.workflow.completedModules || [];
428
+ const currentModuleIndex = metadata.workflow.currentModuleIndex || 0;
429
+ const totalModules = moduleOrder.length;
430
+
431
+ // Guard thresholds
432
+ const MAX_MODULES_WARN = 15;
433
+ const MAX_MODULES_BLOCK = 30;
434
+
435
+ IF totalModules > MAX_MODULES_BLOCK:
436
+ BLOCKING ERROR:
437
+ "Module count ({totalModules}) exceeds maximum allowed ({MAX_MODULES_BLOCK}).
438
+ This is likely a decomposition error. Return to step-02-decomposition.md
439
+ and consolidate or split into multiple applications."
440
+ STOP — do not continue loop
441
+
442
+ IF totalModules > MAX_MODULES_WARN:
443
+ WARNING (non-blocking):
444
+ "Module count ({totalModules}) is high. Consider whether some modules
445
+ could be grouped or split into separate applications.
446
+ Continuing with {totalModules - completedModules.length} modules remaining."
447
+
448
+ // Sanity check: currentModuleIndex should never exceed totalModules
449
+ IF currentModuleIndex >= totalModules AND completedModules.length < totalModules:
450
+ BLOCKING ERROR:
451
+ "Loop state inconsistency: currentModuleIndex ({currentModuleIndex}) >= totalModules ({totalModules})
452
+ but only {completedModules.length} modules are marked complete.
453
+ Fix: Check metadata.workflow in feature.json and correct the state manually."
454
+ STOP
455
+ ```
456
+
457
+ ---
458
+
459
+ ### 6c. Loop Decision (section 12)
539
460
 
540
461
  > **TEAM AGENT MODE: SKIP THIS ENTIRE SECTION.** If you are a team agent (your prompt contains `PROPOSE & REVIEW`), go directly to **section 12-bis** below. Section 12 is for inline mode ONLY. You MUST NOT load the next step or advance the module loop — the team lead handles orchestration.
541
462
 
@@ -654,7 +575,7 @@ SendMessage({
654
575
  - **`REVISION:{moduleCode}\n{feedback}`** → Apply changes:
655
576
  1. Read the feedback
656
577
  2. Update the relevant sections in feature.json via ba-writer
657
- 3. Re-run validation checks (section 9)
578
+ 3. Re-run validation checks (Phase 2)
658
579
  4. Re-build summary and send new `PROPOSAL_READY`
659
580
  5. Max **3 revision cycles** — after 3, send `ERROR:{moduleCode}:Max revisions reached` and stop
660
581
 
@@ -696,19 +617,6 @@ This terminates your process. Do NOT output any text after `shutdown_response`.
696
617
 
697
618
  ---
698
619
 
699
- ## SELF-VERIFICATION (MANDATORY before loading next step)
700
-
701
- Before proceeding to step-03a (next module) or step-04 (consolidation), VERIFY:
702
-
703
- 1. **Module feature.json has specification section** with ALL sub-sections (actors, useCases, functionalRequirements, permissionMatrix, navigation, seedDataCore, gherkinScenarios, validations, messages, lifeCycles, apiEndpoints, i18nKeys, sections, uiWireframes)
704
- 2. **Module feature.json status** = "specified" (set by section 11)
705
- 3. **Master modules[].status** for this module = "specified" (set by section 11)
706
- 4. **ba-interactive.html exists** and includes data for this module (set by section 11-bis)
707
-
708
- **IF any check fails → FIX before proceeding.** Do NOT advance the module loop with incomplete data.
709
-
710
- ---
711
-
712
620
  ## SINGLE-MODULE MODE
713
621
 
714
622
  When only 1 module in moduleOrder:
@@ -737,8 +645,8 @@ Read metadata.workflow.currentModule
737
645
  | Loaded | Not Loaded |
738
646
  |--------|------------|
739
647
  | _shared.md | Other module feature.json (full) |
740
- | feature-schema.json | Questionnaires not needed |
741
- | Questionnaires for this module | Templates |
648
+ | _rules.md | Questionnaires not needed |
649
+ | feature-schema.json | Templates |
742
650
  | Completed modules summary (100 lines max) | React viewer files |
743
651
 
744
652
  ---