@atlashub/smartstack-cli 4.50.0 → 4.52.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 (30) hide show
  1. package/dist/index.js +53 -1
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/skills/apex/SKILL.md +30 -0
  5. package/templates/skills/apex/references/core-seed-data.md +15 -0
  6. package/templates/skills/apex/references/error-classification.md +27 -3
  7. package/templates/skills/apex/references/post-checks.md +3 -1
  8. package/templates/skills/apex/steps/step-00-init.md +57 -0
  9. package/templates/skills/apex/steps/step-03-execute.md +40 -5
  10. package/templates/skills/apex/steps/step-03a-layer0-domain.md +4 -1
  11. package/templates/skills/apex/steps/step-03b-layer1-seed.md +22 -1
  12. package/templates/skills/apex/steps/step-03c-layer2-backend.md +4 -1
  13. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +7 -1
  14. package/templates/skills/apex/steps/step-04-examine.md +35 -0
  15. package/templates/skills/business-analyse-develop/references/init-resume-recovery.md +54 -0
  16. package/templates/skills/business-analyse-develop/steps/step-00-init.md +10 -3
  17. package/templates/skills/business-analyse-develop/steps/step-01-task.md +14 -2
  18. package/templates/skills/business-analyse-develop/steps/step-04-check.md +12 -2
  19. package/templates/skills/business-analyse-handoff/references/entity-canonicalization.md +158 -0
  20. package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +14 -0
  21. package/templates/skills/business-analyse-handoff/steps/step-02-export.md +14 -0
  22. package/templates/skills/business-analyse-html/SKILL.md +4 -0
  23. package/templates/skills/business-analyse-html/html/ba-interactive.html +7 -0
  24. package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +7 -0
  25. package/templates/skills/business-analyse-html/references/data-build.md +24 -17
  26. package/templates/skills/business-analyse-html/references/data-mapping.md +79 -35
  27. package/templates/skills/business-analyse-html/references/output-modes.md +2 -1
  28. package/templates/skills/business-analyse-html/steps/step-01-collect.md +7 -2
  29. package/templates/skills/business-analyse-html/steps/step-02-build-data.md +168 -40
  30. package/templates/skills/business-analyse-html/steps/step-04-verify.md +39 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "4.50.0",
3
+ "version": "4.52.0",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -171,6 +171,36 @@ Execute incremental SmartStack development using the APEX methodology. This skil
171
171
 
172
172
  </execution_rules>
173
173
 
174
+ <execution_guarantee>
175
+
176
+ ## Execution Guarantee (CRITICAL — read before ANY step)
177
+
178
+ > **The user is NOT watching. There is NOBODY to answer your questions. Stopping is a FAILURE.**
179
+
180
+ When APEX runs (especially in `-d` delegate mode or `-a` auto mode), the execution is **fully autonomous**. The user has launched the command and walked away. Any pause, question, or numbered option list is a **dead end** — nobody will respond.
181
+
182
+ **YOU MUST NOT:**
183
+ - Stop to ask the user a question between layers
184
+ - Present numbered options ("Would you like to: 1. Continue... 2. Generate... 3. Stop...")
185
+ - Pause between layers to summarize progress and wait for confirmation
186
+ - Stop because the work seems "large" or "complex" — that is expected
187
+ - Add "Let me know if you want me to continue" at any point
188
+
189
+ **YOU MUST:**
190
+ - After Layer N completes, **IMMEDIATELY** load the next sub-step file. No pause, no summary, no question.
191
+ - Execute the full pipeline: Layer 0 → Layer 1 → Layer 2 → Layer 3 → Layer 4 → step-04, with **ZERO pauses** between layers
192
+ - Treat each "Load `steps/step-03X-...md`" instruction as a **mandatory immediate action**, not a suggestion
193
+ - Continue even if a layer produced warnings (only a build gate failure after max retries is a valid stop)
194
+
195
+ **The ONLY valid reasons to stop:**
196
+ 1. A build gate fails after maximum retries (3 attempts)
197
+ 2. ALL layers are completed and step-04 (eXamine) is done
198
+ 3. The user presses Ctrl+C
199
+
200
+ **Anything else — including "being helpful" by asking — is a VIOLATION of the execution guarantee.**
201
+
202
+ </execution_guarantee>
203
+
174
204
  <error_handling>
175
205
 
176
206
  ## Error Handling Strategy
@@ -1003,6 +1003,21 @@ public class RolePermissionSeedEntry
1003
1003
 
1004
1004
  ## 6. IClientSeedDataProvider Implementation
1005
1005
 
1006
+ > **IMPORTANT — HasData vs Seed*Async: TWO DIFFERENT MECHANISMS**
1007
+ >
1008
+ > | Mechanism | Where | When | Purpose |
1009
+ > |-----------|-------|------|---------|
1010
+ > | **EF Core `HasData()`** | `*Configuration.cs` (Infrastructure) | At migration time | Seeds static reference data into tables via `INSERT` in migration SQL. Data is part of the migration — no runtime code needed. |
1011
+ > | **`IClientSeedDataProvider.Seed*Async()`** | `*SeedDataProvider.cs` (Infrastructure) | At runtime startup | Seeds navigation, roles, permissions, role-permissions into the **Core** schema. Runs AFTER `MigrateAsync()` in `Program.cs`. |
1012
+ >
1013
+ > **Common mistake:** Generating `HasData()` calls for navigation/permissions instead of `Seed*Async()` methods.
1014
+ > Navigation and permission data goes into the **Core** schema (`core.nav_*`, `core.auth_*`) which is managed
1015
+ > by SmartStack, not by the client's migration. Only `IClientSeedDataProvider` can write to Core tables at runtime.
1016
+ >
1017
+ > **ANTI-STUB WARNING:** Each of the 4 Seed methods MUST contain real `context.{DbSet}.Add()` calls.
1018
+ > If ANY method is just `return Task.CompletedTask;`, the module will be **invisible** in the UI (empty menu).
1019
+ > This happens when this reference file is evicted from context by compression — see step-03b safeguard.
1020
+
1006
1021
  **File:** `Infrastructure/Persistence/Seeding/{AppPascalName}SeedDataProvider.cs`
1007
1022
 
1008
1023
  ### Critical Rules
@@ -100,6 +100,28 @@
100
100
 
101
101
  ---
102
102
 
103
+ ### Category G: PRD Quality Error (FIX = fix PRD or re-run handoff)
104
+
105
+ > **These errors are NOT caused by code generation — they originate from invalid PRD data.**
106
+ > The handoff generated file paths with illegal characters (spaces, apostrophes, accents in entity names).
107
+ > Code generation faithfully reproduced the invalid paths → build failure.
108
+
109
+ | Error Pattern | Example | Fix |
110
+ |--------------|---------|-----|
111
+ | `error CS1001: Identifier expected` with file name containing spaces | `Type d'absence.cs` → CS1001 | Re-run `/business-analyse-handoff` with entity canonicalization |
112
+ | `error CS1513/CS1514` with file name containing apostrophes | `Congé.cs` → accent in identifier | Fix entity name in BA or re-run handoff |
113
+ | Path contains non-ASCII characters in `.cs` file names | `Département.cs` | Canonicalize: strip diacritics, PascalCase |
114
+
115
+ **Detection heuristic:** If the error file path contains spaces, apostrophes, or accented characters, it is a PRD quality error, not a code error. Do NOT attempt to fix the generated code — fix the PRD source.
116
+
117
+ **Fix procedure:**
118
+ 1. Identify the invalid entity name from the error file path
119
+ 2. Report to user: "PRD quality error — entity name '{name}' is not a valid C# identifier"
120
+ 3. Either: manually canonicalize in the PRD file, or re-run `/business-analyse-handoff` (which now includes canonicalization)
121
+ 4. Re-run `/apex -d` with the corrected PRD
122
+
123
+ ---
124
+
103
125
  ## Decision Tree
104
126
 
105
127
  When a build or runtime error occurs, follow this tree:
@@ -123,9 +145,11 @@ BUILD/RUNTIME ERROR
123
145
  | YES -> Category E (edit config files)
124
146
  |
125
147
  +-- error CS#### (C# compiler error) ?
126
- | YES -> Is the missing type in ANY project file?
127
- | NO -> Category A (missing package)
128
- | YES -> Category F (fix source code)
148
+ | YES -> Does the error file path contain spaces, apostrophes, or accents?
149
+ | YES -> Category G (PRD quality error — fix handoff, not code)
150
+ | NO -> Is the missing type in ANY project file?
151
+ | NO -> Category A (missing package)
152
+ | YES -> Category F (fix source code)
129
153
  |
130
154
  +-- Test failure (Assert/Expected) ?
131
155
  YES -> Category F (fix source code, NOT tests)
@@ -90,7 +90,7 @@ bash references/checks/infrastructure-checks.sh
90
90
  | C20 | WARNING | Section route completeness (NavigationSection → frontend route + permissions) | seed-checks.sh |
91
91
  | C21 | WARNING | FORBIDDEN route patterns — /list and /detail/:id | seed-checks.sh |
92
92
  | C22 | WARNING | Permission path segment count (2-4 dots expected) | seed-checks.sh |
93
- | C23 | BLOCKING | IClientSeedDataProvider must have 4 methods + DI registration | seed-checks.sh |
93
+ | C23 | BLOCKING | IClientSeedDataProvider must have 4 methods with real implementation (not stubs) + DI registration | seed-checks.sh |
94
94
  | C32 | CRITICAL | Translation seed data must have idempotency guard | seed-checks.sh |
95
95
  | C33 | CRITICAL | Resource seed data must use actual section IDs from DB | seed-checks.sh |
96
96
  | C34 | BLOCKING | NavRoute segments must use kebab-case for multi-word codes — MCP overlap | seed-checks.sh |
@@ -101,6 +101,8 @@ bash references/checks/infrastructure-checks.sh
101
101
  | C47 | WARNING | Person Extension entities must not duplicate User fields | seed-checks.sh |
102
102
  | C48 | CRITICAL | Person Extension service must Include(User) | seed-checks.sh |
103
103
  | C53 | BLOCKING | Enum serialization — JsonStringEnumConverter required | seed-checks.sh |
104
+ | C57 | BLOCKING | SeedDataProvider Seed*Async methods must NOT be `return Task.CompletedTask` or empty body — stubs cause empty menu | seed-checks.sh |
105
+ | C58 | BLOCKING | File paths in filesToCreate must be valid C# identifiers — no spaces, apostrophes, or accents | seed-checks.sh |
104
106
 
105
107
  ### Architecture — Clean Architecture Layer Isolation (A1-A8)
106
108
 
@@ -94,6 +94,46 @@ if (prd.specificationFiles) {
94
94
 
95
95
  Each layer step (step-03a through step-03d) will load its companion files at the start. This provides full BA specifications (entity attributes, BR formulas, UC steps, screen columns) without loading the entire spec corpus.
96
96
 
97
+ **PRD Quality Gate (delegate mode — BLOCKING):**
98
+
99
+ > Validate that PRD file paths are valid C# identifiers BEFORE starting execution.
100
+ > Invalid entity names (French with spaces/apostrophes/accents) cause CS1001 build errors
101
+ > that waste 3+ retry iterations before being correctly classified.
102
+
103
+ ```javascript
104
+ // Extract all file paths from PRD
105
+ const filesToCreate = prd.$version === '4.0.0' ? prd.expectedFiles : prd.implementation?.filesToCreate;
106
+ if (filesToCreate) {
107
+ const invalidPaths = [];
108
+ for (const [category, files] of Object.entries(filesToCreate)) {
109
+ for (const file of (files || [])) {
110
+ const filePath = file.path || file;
111
+ // Extract filename (without extension) from path
112
+ const fileName = filePath.split('/').pop().replace(/\.(cs|tsx|ts|json)$/, '');
113
+ // Check for illegal characters in C# identifiers
114
+ if (/[\s'àâäéèêëïîôùûüçÀÂÄÉÈÊËÏÎÔÙÛÜÇ]/.test(fileName)) {
115
+ invalidPaths.push({ category, path: filePath, fileName });
116
+ }
117
+ }
118
+ }
119
+
120
+ if (invalidPaths.length > 0) {
121
+ console.error('BLOCKING — PRD QUALITY ERROR (not a code error):');
122
+ console.error('The following file paths contain illegal C# identifier characters:');
123
+ for (const p of invalidPaths) {
124
+ console.error(` ${p.category}: ${p.path} (invalid name: "${p.fileName}")`);
125
+ }
126
+ console.error('');
127
+ console.error('FIX: Re-run /business-analyse-handoff which now includes entity name canonicalization.');
128
+ console.error(' Or manually fix entity names in the PRD (strip accents, remove spaces/apostrophes, PascalCase).');
129
+ console.error('');
130
+ console.error('This is a PRD quality error (Category G), NOT a code generation error.');
131
+ console.error('Do NOT attempt to generate code from this PRD — it will fail with CS1001.');
132
+ STOP; // Do not proceed with invalid PRD
133
+ }
134
+ }
135
+ ```
136
+
97
137
  **Jump to:** section 3 (MCP verify) → section 6 (determine needs) → section 9 (summary)
98
138
 
99
139
  ---
@@ -248,6 +288,23 @@ needs_notification = {module_complexity} in ["crud-workflow","complex"] OR menti
248
288
 
249
289
  Read latest task directory in `.claude/output/apex/`:
250
290
  - **If state.json exists:** resume step-03 at next uncompleted layer (skip completed)
291
+ - **Delegate context recovery:** If `state.delegate_mode === true`:
292
+ 1. Restore `{delegate_prd_path}` from `state.delegate_prd_path`
293
+ 2. Restore `{app_name}`, `{module_code}`, `{sections}`, `{entities}` from state
294
+ 3. Re-read PRD at `{delegate_prd_path}` to rebuild `{specification_loading_plan}`:
295
+ ```javascript
296
+ const prd = readJSON(state.delegate_prd_path);
297
+ if (prd.specificationFiles) {
298
+ const sf = prd.specificationFiles;
299
+ specification_loading_plan = {
300
+ layer0_domain: [sf.entities],
301
+ layer1_seed: [sf.entities, sf.permissions],
302
+ layer2_backend: [sf.rules, sf.usecases],
303
+ layer3_frontend: [sf.screens, sf.usecases]
304
+ };
305
+ }
306
+ ```
307
+ 4. Set `{delegate_mode} = true` — companion spec loading will work in remaining layers
251
308
  - **Else if 00-context.md exists:** restore step-00 state, re-derive post-step-00 from git + files
252
309
  - **Else:** full re-derive from git history + files
253
310
 
@@ -46,25 +46,48 @@ Execute all layers (Layer 0 → Layer 1 → Layer 2 → Layer 3 → Layer 4).
46
46
  BEFORE starting Layer N:
47
47
  Verify these variables are still accessible:
48
48
  {app_name}, {module_code}, {sections}, {entities}, {code_patterns}
49
+ IF delegate_mode: also verify {delegate_prd_path}, {specification_loading_plan}
49
50
 
50
51
  IF any variable is missing or empty:
51
52
  1. Read .claude/output/apex/{task_id}/state.json (if exists)
52
- 2. IF state.json missing re-derive from filesystem:
53
+ 2. IF state.json has delegate context:
54
+ - {delegate_prd_path} = state.delegate_prd_path
55
+ - {delegate_mode} = state.delegate_mode
56
+ - Re-read PRD at {delegate_prd_path} to rebuild specification_loading_plan:
57
+ const prd = readJSON(delegate_prd_path);
58
+ if (prd.specificationFiles) {
59
+ specification_loading_plan = {
60
+ layer0_domain: [prd.specificationFiles.entities],
61
+ layer1_seed: [prd.specificationFiles.entities, prd.specificationFiles.permissions],
62
+ layer2_backend: [prd.specificationFiles.rules, prd.specificationFiles.usecases],
63
+ layer3_frontend: [prd.specificationFiles.screens, prd.specificationFiles.usecases]
64
+ };
65
+ }
66
+ - {app_name} = state.app_name || prd.project?.application || prd.metadata?.applicationCode
67
+ - {module_code} = state.module_code || prd.project?.module || prd.metadata?.moduleCode
68
+ 3. IF state.json missing OR no delegate context → re-derive from filesystem:
53
69
  - {app_name}: Glob("docs/business/*/") → first directory name
54
70
  - {module_code}: Glob("src/**/Domain/Entities/*/") → target module directory
55
71
  - {entities}: Glob("src/**/Domain/Entities/{module_code}/*.cs") → entity names
56
72
  - {sections}: Glob("src/**/Seeding/Data/{module_code}/*NavigationSeedData.cs") → parse
57
73
  - {code_patterns}: Read state.json or re-derive from DependencyInjection.cs
58
- 3. IF recovered: verify consistency with naming derivation rules (step-00 §4f)
59
- 4. IF Layer N-1 already completed: skip to Layer N directly
74
+ 4. IF recovered: verify consistency with naming derivation rules (step-00 §4f)
75
+ 5. IF Layer N-1 already completed: skip to Layer N directly
60
76
 
61
- Cost: ~5 tool calls. Only triggered if context was compressed.
77
+ Cost: ~5-8 tool calls. Only triggered if context was compressed.
62
78
  ```
63
79
 
64
80
  ---
65
81
 
66
82
  ## Layer Dispatch
67
83
 
84
+ > **CRITICAL RULES — LAYER EXECUTION GUARANTEE**
85
+ >
86
+ > - **NEVER** stop between layers. NEVER ask the user. NEVER present numbered options between layers.
87
+ > - The pipeline is sequential and mandatory: **0 → 1 → 2 → 3 → 4 → step-04**, with **ZERO pauses**.
88
+ > - After each sub-step completes, IMMEDIATELY load the next one. No summary, no confirmation request.
89
+ > - Stopping between layers is a **VIOLATION** of the execution guarantee defined in SKILL.md.
90
+
68
91
  Load each sub-step sequentially:
69
92
 
70
93
  | Layer | Sub-step | Content |
@@ -119,6 +142,7 @@ Layer 4: feat({module}): [devdata] test data for development # if applicable
119
142
  ## State Auto-Save (after each layer)
120
143
 
121
144
  > **Automatic** — not dependent on `-s` flag. Enables reliable resume after context loss.
145
+ > **CRITICAL (audit ba-003):** Delegate context MUST be persisted for resume to work in delegate mode.
122
146
 
123
147
  After each layer's build gate passes, write state to `.claude/output/apex/{task_id}/state.json`:
124
148
 
@@ -130,10 +154,21 @@ After each layer's build gate passes, write state to `.claude/output/apex/{task_
130
154
  "files_created": ["Employee.cs", "EmployeeConfiguration.cs", "..."],
131
155
  "build_gates": { "layer0": "pass", "layer1": "pass", "layer2": "pass" },
132
156
  "commits": ["abc1234", "def5678", "ghi9012"],
133
- "timestamp": "2026-03-06T14:30:00Z"
157
+ "timestamp": "2026-03-06T14:30:00Z",
158
+ "delegate_mode": true,
159
+ "delegate_prd_path": ".ralph/prd-employees.json",
160
+ "app_name": "HumanResources",
161
+ "module_code": "employee-management",
162
+ "sections": ["employees", "departments"],
163
+ "entities": ["Employee", "Department"]
134
164
  }
135
165
  ```
136
166
 
167
+ > **Fields `delegate_mode`, `delegate_prd_path`, `app_name`, `module_code`, `sections`, `entities`**
168
+ > are persisted so that Context Recovery Protocol (above) can restore the full execution context
169
+ > after context compression or resume (`-r`). The `specification_loading_plan` is rebuilt from the
170
+ > PRD file at `delegate_prd_path` — no need to serialize it directly.
171
+
137
172
  ---
138
173
 
139
174
  ## Save Output (if save_mode)
@@ -136,6 +136,9 @@ feat({module}): [domain+infra] {short description}
136
136
 
137
137
  ---
138
138
 
139
- ## NEXT SUB-STEP
139
+ ## NEXT SUB-STEP (MANDATORY — IMMEDIATE)
140
+
141
+ > **DO NOT STOP.** DO NOT ask the user. DO NOT present options. IMMEDIATELY load the next sub-step.
142
+ > Stopping here is a VIOLATION of the execution guarantee.
140
143
 
141
144
  Load `steps/step-03b-layer1-seed.md`
@@ -42,6 +42,24 @@ TaskUpdate(taskId: progress_tracker_id,
42
42
 
43
43
  > This layer is required. Seed data makes modules visible in the UI. Without it, the module exists in code but is invisible to users. Reference: `references/core-seed-data.md` (loaded above) for complete C# templates.
44
44
 
45
+ > **CONTEXT COMPRESSION SAFEGUARD (delegate mode):**
46
+ > In delegate mode (`-d`), `references/core-seed-data.md` may have been evicted from context by compression
47
+ > before Layer 1 begins (it was loaded at step-03 entry but is ~1464 lines).
48
+ >
49
+ > **CHECK:** Can you see Section 6 "IClientSeedDataProvider Implementation" from `core-seed-data.md` in your context?
50
+ > - **YES** → Proceed normally using the templates from that section.
51
+ > - **NO** → **Re-read** `references/core-seed-data.md` lines 1004-1296 NOW (the IClientSeedDataProvider template).
52
+ > This section contains the complete C# template for the provider class with all 4 Seed methods.
53
+ >
54
+ > **WARNING — ANTI-STUB RULE:**
55
+ > The SeedDataProvider MUST contain real implementation code. Each of the 4 methods
56
+ > (`SeedNavigationAsync`, `SeedRolesAsync`, `SeedPermissionsAsync`, `SeedRolePermissionsAsync`)
57
+ > MUST have actual entity creation logic with `context.{DbSet}.Add()` calls.
58
+ >
59
+ > **BLOCKING:** If ANY Seed method body is just `return Task.CompletedTask;` or `{ }` (empty),
60
+ > the seed data layer is INVALID. The module will be invisible in the UI (menu vide / empty menu).
61
+ > Re-read the template from `references/core-seed-data.md` Section 6 and generate proper implementation.
62
+
45
63
  ---
46
64
 
47
65
  ### Mode Detection: CREATE vs UPDATE
@@ -254,6 +272,9 @@ feat({module}): [seed] navigation, permissions, roles
254
272
 
255
273
  ---
256
274
 
257
- ## NEXT SUB-STEP
275
+ ## NEXT SUB-STEP (MANDATORY — IMMEDIATE)
276
+
277
+ > **DO NOT STOP.** DO NOT ask the user. DO NOT present options. IMMEDIATELY load the next sub-step.
278
+ > Stopping here is a VIOLATION of the execution guarantee.
258
279
 
259
280
  Load `steps/step-03c-layer2-backend.md`
@@ -348,6 +348,9 @@ test({module}): backend unit and integration tests
348
348
 
349
349
  ---
350
350
 
351
- ## NEXT SUB-STEP
351
+ ## NEXT SUB-STEP (MANDATORY — IMMEDIATE)
352
+
353
+ > **DO NOT STOP.** DO NOT ask the user. DO NOT present options. IMMEDIATELY load the next sub-step.
354
+ > Stopping here is a VIOLATION of the execution guarantee.
352
355
 
353
356
  Load `steps/step-03d-layer3-frontend.md`
@@ -169,6 +169,9 @@ For each module:
169
169
  3. Add the new namespace import + registration for all 4 languages
170
170
  4. If config uses dynamic imports: add namespace to the `ns` array
171
171
  5. Verify: `grep -q "{module_namespace}" src/**/i18n/config.ts` → must match
172
+ 6. **I18n File/Import Alignment Check:** Verify that every locale JSON file on disk for this module
173
+ has a corresponding import in the i18n config index.ts. Glob `src/**/i18n/locales/*/` for module files,
174
+ then verify each is imported. Missing imports cause silent translation failures (keys show as raw strings).
172
175
  - Permissions: Call MCP generate_permissions for the module permission root (2 segments: {app}.{module}),
173
176
  then also call MCP generate_permissions for each section (3 segments: {app}.{module}.{section}).
174
177
  - Section routes: Ensure navigation seed data has ComponentKey matching PageRegistry keys.
@@ -329,6 +332,9 @@ test({module}): frontend form tests
329
332
 
330
333
  ---
331
334
 
332
- ## NEXT SUB-STEP
335
+ ## NEXT SUB-STEP (MANDATORY — IMMEDIATE)
336
+
337
+ > **DO NOT STOP.** DO NOT ask the user. DO NOT present options. IMMEDIATELY load the next sub-step.
338
+ > Stopping here is a VIOLATION of the execution guarantee.
333
339
 
334
340
  Load `steps/step-03e-layer4-devdata.md`
@@ -131,6 +131,41 @@ IF ANY cell = NO → BLOCKING — return to step-03b to fix
131
131
 
132
132
  Execute all checks from `references/post-checks.md`. If any fails, fix in step-03 and re-validate.
133
133
 
134
+ ### 6c. SeedDataProvider Content Verification (BLOCKING)
135
+
136
+ > **LESSON LEARNED (audit ba-003):** SeedDataProvider existed and had 4 methods (passed C23),
137
+ > but all methods were `return Task.CompletedTask` — stubs generated when `core-seed-data.md`
138
+ > was evicted from context by compression. Result: empty menu, 0 applications visible.
139
+
140
+ ```javascript
141
+ // Find the SeedDataProvider file
142
+ const providerFiles = Glob("**/Seeding/*SeedDataProvider.cs");
143
+ for (const providerFile of providerFiles) {
144
+ const content = readFile(providerFile);
145
+
146
+ // Check 1: No stub methods — each Seed*Async must have real implementation
147
+ const methods = ['SeedNavigationAsync', 'SeedRolesAsync', 'SeedPermissionsAsync', 'SeedRolePermissionsAsync'];
148
+ for (const method of methods) {
149
+ const methodRegex = new RegExp(`${method}[^{]*\\{([^}]*)\\}`, 's');
150
+ const match = content.match(methodRegex);
151
+ if (match) {
152
+ const body = match[1].trim();
153
+ if (body === 'return Task.CompletedTask;' || body === '' || body === 'return;') {
154
+ BLOCKING_ERROR(`${providerFile}: ${method} is a STUB (${body || 'empty body'}). ` +
155
+ `Re-read references/core-seed-data.md Section 6 and generate real implementation. ` +
156
+ `Stub seed methods cause EMPTY MENU — 0 applications visible in UI.`);
157
+ }
158
+ }
159
+ }
160
+
161
+ // Check 2: Must contain actual entity creation calls
162
+ if (!content.includes('.Add(') && !content.includes('.AddRange(')) {
163
+ BLOCKING_ERROR(`${providerFile}: No .Add() or .AddRange() calls found. ` +
164
+ `SeedDataProvider must actually insert seed data, not just return.`);
165
+ }
166
+ }
167
+ ```
168
+
134
169
  ---
135
170
 
136
171
  ## 7. Acceptance Criteria POST-CHECK
@@ -65,6 +65,60 @@ if (resumeValid) {
65
65
  }
66
66
  ```
67
67
 
68
+ ### Ralph State Recovery (context compression defense)
69
+
70
+ > **When context compression occurs mid-execution**, conversation variables are lost.
71
+ > `ralph-state.json` tracks the current position and is written before each major transition.
72
+ > This section reads it back to recover position.
73
+
74
+ ```javascript
75
+ // ALWAYS attempt to read ralph-state.json on resume — regardless of -r flag
76
+ // This file is written by: step-00 init, step-02 execute, compact-loop, module-transition
77
+ const statePath = '.ralph/ralph-state.json';
78
+ if (fileExists(statePath)) {
79
+ const state = readJSON(statePath);
80
+
81
+ console.log(`Ralph state recovered: step=${state.currentStep}, module=${state.currentModule}, ` +
82
+ `iteration=${state.iteration || '?'}, reason=${state.reason || 'normal'}`);
83
+
84
+ // Restore conversation variables from state
85
+ if (state.currentModule) {
86
+ {current_module} = state.currentModule;
87
+ }
88
+ if (state.iteration) {
89
+ {current_iteration} = state.iteration;
90
+ }
91
+ if (state.prdVersion) {
92
+ {prd_version} = state.prdVersion;
93
+ }
94
+
95
+ // Route to the correct step based on saved state
96
+ // This replaces the default "always go to step-01" behavior
97
+ const stepRouting = {
98
+ 'step-01-task': 'steps/step-01-task.md',
99
+ 'step-02-execute': 'steps/step-02-execute.md',
100
+ 'step-03-commit': 'steps/step-03-commit.md',
101
+ 'step-04-check': 'steps/step-04-check.md',
102
+ 'compact-loop': 'steps/step-04-check.md', // compact-loop re-enters via step-04
103
+ 'step-05-report': 'steps/step-05-report.md'
104
+ };
105
+
106
+ const targetStep = stepRouting[state.currentStep] || 'steps/step-01-task.md';
107
+
108
+ // Special case: module transition — go to step-01 to detect module-changed.json
109
+ if (state.reason === 'module-transition') {
110
+ console.log(`Module transition recovery: ${state.fromModule} → ${state.currentModule}`);
111
+ console.log('Routing to step-01-task.md to detect module-changed.json');
112
+ // targetStep stays 'steps/step-01-task.md'
113
+ }
114
+
115
+ console.log(`Recovery routing: → ${targetStep}`);
116
+ // The calling code (step-00) should load targetStep instead of the default step-01
117
+ }
118
+ ```
119
+
120
+ **IMPORTANT:** This recovery is triggered BEFORE the default "Proceed to step-01" routing in step-00-init.md. If ralph-state.json provides a different target step, that step should be loaded instead.
121
+
68
122
  ---
69
123
 
70
124
  ## Auto-Recovery: BA Artifacts Without PRD
@@ -76,10 +76,11 @@ If tests are slow (>30s in logs), display warning but **continue execution**:
76
76
 
77
77
  ## 4. Resume or Initialize
78
78
 
79
- See `references/init-resume-recovery.md` for complete Resume Mode and Auto-Recovery logic.
79
+ See `references/init-resume-recovery.md` for complete Resume Mode, Auto-Recovery, and Ralph State Recovery logic.
80
80
 
81
81
  **Quick:**
82
- - If `-r` flag: restore state from .ralph/prd.json
82
+ - If `-r` flag: restore state from .ralph/prd.json + .ralph/ralph-state.json
83
+ - Else if `.ralph/ralph-state.json` exists: recover position (step, module, iteration) — see init-resume-recovery.md "Ralph State Recovery"
83
84
  - Else if BA artifacts exist: auto-recover PRDs via `ss business-analyse-handoff`
84
85
  - Else: fresh start
85
86
 
@@ -222,14 +223,20 @@ MCP: Ready | Branch: {branch} | PRD: v{prd_version}
222
223
 
223
224
  ### 7b. Initialize State File (context compression defense)
224
225
 
226
+ > **ralph-state.json is written here AND updated by step-02, compact-loop, and module-transition.**
227
+ > On resume or after context compression, `init-resume-recovery.md` reads it back to route
228
+ > to the correct step instead of always restarting from step-01.
229
+
225
230
  ```javascript
226
231
  writeJSON('.ralph/ralph-state.json', {
227
232
  currentStep: 'step-01-task',
228
233
  currentModule: {current_module},
229
234
  iteration: 1,
230
235
  prdVersion: {prd_version},
236
+ modulesQueuePath: fileExists('.ralph/modules-queue.json') ? '.ralph/modules-queue.json' : null,
231
237
  timestamp: new Date().toISOString()
232
238
  });
233
239
  ```
234
240
 
235
- **Proceed directly to step-01-task.md**
241
+ **Step routing:** If ralph-state recovery (section 4) provided a different target step, load THAT step.
242
+ Otherwise, proceed to step-01-task.md.
@@ -6,8 +6,20 @@ next_step: steps/step-02-execute.md
6
6
 
7
7
  # Step 1: Load Task
8
8
 
9
- > **STATE RECOVERY:** If you are unsure which step you are executing (e.g., after context compression),
10
- > read `.ralph/ralph-state.json` to recover your position.
9
+ > **STATE RECOVERY (executable):** If context was compressed and you are unsure of your position:
10
+ ```javascript
11
+ if (fileExists('.ralph/ralph-state.json')) {
12
+ const state = readJSON('.ralph/ralph-state.json');
13
+ if (state.currentStep && state.currentStep !== 'step-01-task') {
14
+ console.warn(`RECOVERY: ralph-state.json says currentStep="${state.currentStep}" but we are in step-01.`);
15
+ console.warn(`This may indicate context compression routed to the wrong step.`);
16
+ console.warn(`Current module: ${state.currentModule}, iteration: ${state.iteration}`);
17
+ }
18
+ // Restore module context
19
+ if (state.currentModule) { {current_module} = state.currentModule; }
20
+ if (state.iteration) { {current_iteration} = state.iteration; }
21
+ }
22
+ ```
11
23
 
12
24
  > **MODULE TRANSITION CHECK:** Before "Only Read Once" rule, check for module transition:
13
25
 
@@ -6,8 +6,18 @@ next_step: steps/step-05-report.md OR steps/step-01-task.md
6
6
 
7
7
  # Step 4: Check Completion
8
8
 
9
- > **STATE RECOVERY:** If you are unsure which step you are executing (e.g., after context compression),
10
- > read `.ralph/ralph-state.json` to recover your position.
9
+ > **STATE RECOVERY (executable):** If context was compressed:
10
+ ```javascript
11
+ if (fileExists('.ralph/ralph-state.json')) {
12
+ const state = readJSON('.ralph/ralph-state.json');
13
+ if (state.currentStep && state.currentStep !== 'step-04-check' && state.currentStep !== 'compact-loop') {
14
+ console.warn(`RECOVERY: ralph-state.json says currentStep="${state.currentStep}" but we are in step-04.`);
15
+ }
16
+ // Restore module context if lost
17
+ if (state.currentModule) { {current_module} = state.currentModule; }
18
+ if (state.iteration) { {current_iteration} = state.iteration; }
19
+ }
20
+ ```
11
21
 
12
22
  ## YOUR TASK:
13
23