@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.
- package/dist/index.js +53 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/skills/apex/SKILL.md +30 -0
- package/templates/skills/apex/references/core-seed-data.md +15 -0
- package/templates/skills/apex/references/error-classification.md +27 -3
- package/templates/skills/apex/references/post-checks.md +3 -1
- package/templates/skills/apex/steps/step-00-init.md +57 -0
- package/templates/skills/apex/steps/step-03-execute.md +40 -5
- package/templates/skills/apex/steps/step-03a-layer0-domain.md +4 -1
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +22 -1
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +4 -1
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +7 -1
- package/templates/skills/apex/steps/step-04-examine.md +35 -0
- package/templates/skills/business-analyse-develop/references/init-resume-recovery.md +54 -0
- package/templates/skills/business-analyse-develop/steps/step-00-init.md +10 -3
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +14 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +12 -2
- package/templates/skills/business-analyse-handoff/references/entity-canonicalization.md +158 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +14 -0
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +14 -0
- package/templates/skills/business-analyse-html/SKILL.md +4 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +7 -0
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +7 -0
- package/templates/skills/business-analyse-html/references/data-build.md +24 -17
- package/templates/skills/business-analyse-html/references/data-mapping.md +79 -35
- package/templates/skills/business-analyse-html/references/output-modes.md +2 -1
- package/templates/skills/business-analyse-html/steps/step-01-collect.md +7 -2
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +168 -40
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +39 -3
package/package.json
CHANGED
|
@@ -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 ->
|
|
127
|
-
|
|
|
128
|
-
|
|
|
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
|
|
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
|
-
|
|
59
|
-
|
|
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
|
|
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
|
-
**
|
|
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
|
|
10
|
-
|
|
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
|
|
10
|
-
|
|
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
|
|