@atlashub/smartstack-cli 4.26.0 → 4.27.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/mcp-entry.mjs +33 -11
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-writer.md +46 -46
- package/templates/project/appsettings.json.template +4 -6
- package/templates/skills/apex/SKILL.md +1 -0
- package/templates/skills/apex/references/challenge-questions.md +17 -0
- package/templates/skills/apex/references/post-checks.md +48 -0
- package/templates/skills/apex/steps/step-03-execute.md +63 -2
- package/templates/skills/business-analyse/steps/step-00-init.md +19 -9
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +2 -14
- package/templates/skills/ralph-loop/references/compact-loop.md +34 -3
package/package.json
CHANGED
|
@@ -18,17 +18,18 @@ Write and update granular JSON files for project-level (multi-app), application-
|
|
|
18
18
|
- Module-level: `docs/{app}/{module}/business-analyse/v{X.Y}/index.json` + thematic files
|
|
19
19
|
|
|
20
20
|
**Thematic files (v2 granular architecture):**
|
|
21
|
-
- `index.json` — metadata, version, hash manifest, module registry
|
|
22
|
-
- `cadrage.json` — stakeholders, problem/vision, risks, acceptance criteria
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
29
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
21
|
+
- `index.json` — metadata, version, hash manifest, module registry (ALL scopes)
|
|
22
|
+
- `cadrage.json` — stakeholders, problem/vision, risks, acceptance criteria (ALL scopes)
|
|
23
|
+
- `validation.json` — validation rules and consistency checks (ALL scopes)
|
|
24
|
+
- `consolidation.json` — cross-module interactions and E2E flows (application/project ONLY)
|
|
25
|
+
- `navigation.json` — navigation tree (application/project ONLY, created by ba-design-ui)
|
|
26
|
+
- `entities.json` — entity definitions with attributes and relationships (**MODULE ONLY**)
|
|
27
|
+
- `rules.json` — business rules with categories and conditions (**MODULE ONLY**)
|
|
28
|
+
- `usecases.json` — use cases and functional requirements (**MODULE ONLY**)
|
|
29
|
+
- `permissions.json` — permission matrix and role assignments (**MODULE ONLY**)
|
|
30
|
+
- `screens.json` — UI wireframes and navigation (**MODULE ONLY**)
|
|
31
|
+
- `handoff.json` — complexity, file catalog, BR-to-code mapping (**MODULE ONLY**)
|
|
32
|
+
- `review.json` — preserved review comments and change summary (ALL scopes)
|
|
32
33
|
|
|
33
34
|
> **Backward compatibility:** If only 1 application, the project level is NOT created. The application-level index.json remains the master.
|
|
34
35
|
|
|
@@ -62,12 +63,12 @@ Create initial index.json and empty thematic files with metadata and draft statu
|
|
|
62
63
|
- For project scope: modules: []
|
|
63
64
|
- For application scope: modules: []
|
|
64
65
|
- For module scope: (no modules array)
|
|
65
|
-
5. Create empty thematic files
|
|
66
|
-
- Project
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
5. Create empty thematic files — ONLY the files listed for the scope. Creating ANY unlisted file is a **BLOCKING ERROR**.
|
|
67
|
+
- Project: cadrage.json, validation.json, consolidation.json — **EXACTLY 3 files, NO OTHERS**
|
|
68
|
+
- Application: cadrage.json, validation.json, consolidation.json — **EXACTLY 3 files, NO OTHERS**
|
|
69
|
+
- Module: entities.json, rules.json, usecases.json, permissions.json, screens.json, validation.json, handoff.json — **EXACTLY 7 files**
|
|
70
|
+
|
|
71
|
+
**FORBIDDEN at project/application level:** entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json — these exist ONLY at module level.
|
|
71
72
|
6. Update `.business-analyse/config.json` with new lastFeatureId
|
|
72
73
|
7. IF scope = "module" AND applicationRef provided AND moduleCode provided:
|
|
73
74
|
a. Read master index.json (via applicationRef FEAT-NNN)
|
|
@@ -110,8 +111,8 @@ Create a project-level index.json for multi-application analysis. Only used when
|
|
|
110
111
|
- fileHashes: {}
|
|
111
112
|
- applications: []
|
|
112
113
|
- applicationDependencyGraph: {}
|
|
113
|
-
5. Create thematic files
|
|
114
|
-
|
|
114
|
+
5. Create thematic files — **EXACTLY 3 files, NO OTHERS:** cadrage.json, validation.json, consolidation.json
|
|
115
|
+
**FORBIDDEN at project level:** entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json — these exist ONLY at module level.
|
|
115
116
|
6. Update `.business-analyse/config.json` with new lastProjectId
|
|
116
117
|
7. Deploy schemas to `docs/business-analyse/schemas/` (including project-schema.json)
|
|
117
118
|
8. Return project ID (PROJ-NNN) and path
|
|
@@ -178,6 +179,10 @@ Write a complete thematic file and update its hash in index.json.
|
|
|
178
179
|
|
|
179
180
|
**Process:**
|
|
180
181
|
1. Find and read index.json (use findFeature if given ID)
|
|
182
|
+
1b. **SCOPE GUARD (BLOCKING):** If index.json scope is "project" or "application", verify themeName is ALLOWED:
|
|
183
|
+
- Allowed: [cadrage, validation, consolidation, navigation, review]
|
|
184
|
+
- FORBIDDEN: [entities, rules, usecases, permissions, screens, handoff]
|
|
185
|
+
If themeName is FORBIDDEN → **REJECT with BLOCKING ERROR.** Do NOT create the file.
|
|
181
186
|
2. Determine thematic filename: `{themeName}.json`
|
|
182
187
|
3. Create full path: `{version_dir}/{themeName}.json`
|
|
183
188
|
4. Write thematic file with pretty-print (2-space indent)
|
|
@@ -335,6 +340,20 @@ Increment the module loop counter in the master index.json.
|
|
|
335
340
|
9. Write back index.json
|
|
336
341
|
10. Return new index and whether loop is complete
|
|
337
342
|
|
|
343
|
+
### cleanupAppLevelFiles
|
|
344
|
+
Remove forbidden thematic files at project/application level and clean their entries from fileHashes.
|
|
345
|
+
|
|
346
|
+
**Input:** featureId: FEAT-NNN
|
|
347
|
+
|
|
348
|
+
**Process:**
|
|
349
|
+
1. Read index.json (verify scope is "project" or "application")
|
|
350
|
+
2. FORBIDDEN = [entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json]
|
|
351
|
+
3. For each FORBIDDEN file: if file exists in version directory → DELETE it
|
|
352
|
+
4. For each FORBIDDEN file: if referenced in fileHashes → REMOVE entry
|
|
353
|
+
5. If `files` property exists in index.json: remove entries for forbidden files
|
|
354
|
+
6. Update metadata.updatedAt, write index.json
|
|
355
|
+
7. Return list of cleaned files
|
|
356
|
+
|
|
338
357
|
### createVersion
|
|
339
358
|
Create a new version for refactoring or major changes.
|
|
340
359
|
|
|
@@ -470,43 +489,29 @@ docs/business-analyse/
|
|
|
470
489
|
v1.0/
|
|
471
490
|
index.json ← PROJECT metadata
|
|
472
491
|
cadrage.json
|
|
473
|
-
entities.json
|
|
474
|
-
rules.json
|
|
475
|
-
usecases.json
|
|
476
|
-
permissions.json
|
|
477
|
-
screens.json
|
|
478
492
|
validation.json
|
|
479
493
|
consolidation.json
|
|
494
|
+
# NO entities/rules/usecases/permissions/screens/handoff — MODULE ONLY
|
|
480
495
|
|
|
481
496
|
docs/{app}/business-analyse/
|
|
482
497
|
v1.0/
|
|
483
498
|
index.json ← APPLICATION metadata
|
|
484
499
|
cadrage.json
|
|
485
|
-
entities.json
|
|
486
|
-
rules.json
|
|
487
|
-
usecases.json
|
|
488
|
-
permissions.json
|
|
489
|
-
screens.json
|
|
490
500
|
validation.json
|
|
491
501
|
consolidation.json
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
cadrage.json
|
|
495
|
-
entities.json
|
|
496
|
-
...
|
|
502
|
+
navigation.json ← (created by ba-design-ui)
|
|
503
|
+
# NO entities/rules/usecases/permissions/screens/handoff — MODULE ONLY
|
|
497
504
|
|
|
498
505
|
docs/{app}/{module}/business-analyse/
|
|
499
506
|
v1.0/
|
|
500
507
|
index.json ← MODULE metadata
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
508
|
+
entities.json
|
|
509
|
+
rules.json
|
|
510
|
+
usecases.json
|
|
511
|
+
permissions.json
|
|
512
|
+
screens.json
|
|
504
513
|
validation.json
|
|
505
514
|
handoff.json
|
|
506
|
-
v1.1/
|
|
507
|
-
index.json
|
|
508
|
-
discovery.json
|
|
509
|
-
...
|
|
510
515
|
```
|
|
511
516
|
|
|
512
517
|
Versions are stored as separate directories. Each directory contains index.json + thematic files.
|
|
@@ -726,11 +731,6 @@ if (estimatedNewSize > 500 * 1024) { // 500KB
|
|
|
726
731
|
"fileHashes": {
|
|
727
732
|
"index.json": "pqr678...",
|
|
728
733
|
"cadrage.json": "stu901...",
|
|
729
|
-
"entities.json": "vwx234...",
|
|
730
|
-
"rules.json": "yza567...",
|
|
731
|
-
"usecases.json": "bcd890...",
|
|
732
|
-
"permissions.json": "efg123...",
|
|
733
|
-
"screens.json": "hij456...",
|
|
734
734
|
"validation.json": "klm789...",
|
|
735
735
|
"consolidation.json": "nop012..."
|
|
736
736
|
},
|
|
@@ -7,10 +7,8 @@
|
|
|
7
7
|
"FailOnMigrationError": true,
|
|
8
8
|
"EnableDevSeeding": false,
|
|
9
9
|
"CorsOrigins": [
|
|
10
|
-
"http://localhost:
|
|
11
|
-
"http://localhost:
|
|
12
|
-
"http://localhost:5175",
|
|
13
|
-
"http://localhost:6173"
|
|
10
|
+
"http://localhost:3000",
|
|
11
|
+
"http://localhost:5173"
|
|
14
12
|
]
|
|
15
13
|
},
|
|
16
14
|
"Jwt": {
|
|
@@ -34,7 +32,7 @@
|
|
|
34
32
|
"SecretExpiresAt": "",
|
|
35
33
|
"CallbackPath": "/api/auth/google/callback"
|
|
36
34
|
},
|
|
37
|
-
"FrontendUrl": "http://localhost:
|
|
35
|
+
"FrontendUrl": "http://localhost:3000"
|
|
38
36
|
},
|
|
39
37
|
"Session": {
|
|
40
38
|
"IdleTimeoutMinutes": 20,
|
|
@@ -125,7 +123,7 @@
|
|
|
125
123
|
"Provider": "Development",
|
|
126
124
|
"FromEmail": "noreply@{{ProjectDomain}}",
|
|
127
125
|
"FromName": "{{ProjectName}}",
|
|
128
|
-
"BaseUrl": "http://localhost:
|
|
126
|
+
"BaseUrl": "http://localhost:3000",
|
|
129
127
|
"TokenExpiration": {
|
|
130
128
|
"EmailConfirmation": "24:00:00",
|
|
131
129
|
"PasswordReset": "01:00:00"
|
|
@@ -149,6 +149,7 @@ Execute incremental SmartStack development using the APEX methodology. This skil
|
|
|
149
149
|
- **Parallel Agent tool** - Parallel execution for scan (step-01) and within Layer 2/3 (step-03) for multi-entity, unless economy_mode
|
|
150
150
|
- **Tests inline** - Backend tests run after Layer 2, frontend tests run after Layer 3 (max 3 fix iterations each). Step-07 = final sweep (security + coverage).
|
|
151
151
|
- **Exception: seed data** — The templates in core-seed-data.md and person-extension-pattern.md are generated directly because no MCP tool covers seed data creation. This is a documented exception to the "orchestrate, never generate" rule.
|
|
152
|
+
- **Frontend pages: ALWAYS via Skill("ui-components")** — economy_mode affects parallelization only, NOT whether /ui-components is called. NEVER generate .tsx pages directly, even in delegate or economy mode.
|
|
152
153
|
- **Save outputs** if `{save_mode}` = true
|
|
153
154
|
- **Commits per layer** - Atomic commits after each execution layer
|
|
154
155
|
- **Delegate mode** (`-d`): Read PRD context, skip challenge questions, auto+economy mode implied. Used when `/ralph-loop` delegates code generation to `/apex`.
|
|
@@ -82,8 +82,25 @@ questions:
|
|
|
82
82
|
multiSelect: true
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
**Reserved codes (NOT valid sections):**
|
|
86
|
+
- `detail` — auto-generated as `/:id` route when "list" section exists
|
|
87
|
+
- `create` — auto-generated as `/create` route when "list" section exists
|
|
88
|
+
- `edit` — auto-generated as `/:id/edit` route when "list" section exists
|
|
89
|
+
|
|
90
|
+
These are **view modes**, not sections. A "list" section automatically generates 4 pages: ListPage (index), DetailPage (/:id), CreatePage (/create), EditPage (/:id/edit).
|
|
91
|
+
|
|
85
92
|
**Validation:**
|
|
86
93
|
```
|
|
94
|
+
RESERVED_SECTION_CODES = ["detail", "create", "edit"]
|
|
95
|
+
|
|
96
|
+
IF any section.code IN RESERVED_SECTION_CODES:
|
|
97
|
+
DISPLAY: "'{section.code}' is a view mode, not a section.
|
|
98
|
+
The 'list' section automatically includes detail (/:id), create (/create),
|
|
99
|
+
and edit (/:id/edit) pages. Remove '{section.code}' from your sections."
|
|
100
|
+
→ Remove the offending section(s) from the list
|
|
101
|
+
→ Re-ask the sections question if {sections}.length == 0
|
|
102
|
+
→ DO NOT proceed
|
|
103
|
+
|
|
87
104
|
IF {sections}.length == 0:
|
|
88
105
|
DISPLAY: "Every module must have at least one section. Please select or define at least one."
|
|
89
106
|
→ Re-ask the sections question
|
|
@@ -117,6 +117,21 @@ if [ -n "$APP_TSX" ]; then
|
|
|
117
117
|
fi
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
### POST-CHECK S7: Controllers must NOT use Guid.Empty for tenantId/userId (OWASP A01)
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
124
|
+
if [ -n "$CTRL_FILES" ]; then
|
|
125
|
+
BAD_GUID=$(grep -Pn 'Guid\.Empty' $CTRL_FILES 2>/dev/null)
|
|
126
|
+
if [ -n "$BAD_GUID" ]; then
|
|
127
|
+
echo "BLOCKING (OWASP A01): Controller uses Guid.Empty — tenant isolation bypassed"
|
|
128
|
+
echo "$BAD_GUID"
|
|
129
|
+
echo "Fix: Use _currentTenant.TenantId from ICurrentTenantService"
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
|
132
|
+
fi
|
|
133
|
+
```
|
|
134
|
+
|
|
120
135
|
---
|
|
121
136
|
|
|
122
137
|
## Backend — Entity, Service & Controller Checks
|
|
@@ -154,6 +169,39 @@ fi
|
|
|
154
169
|
|
|
155
170
|
## Frontend — CSS, Forms, Components, I18n
|
|
156
171
|
|
|
172
|
+
### POST-CHECK C3a: Frontend must not be empty if Layer 3 was planned (BLOCKING)
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# If foundation_mode is false AND App.tsx exists, verify frontend was generated
|
|
176
|
+
APP_TSX=$(find web/ src/ -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
|
|
177
|
+
if [ -n "$APP_TSX" ]; then
|
|
178
|
+
# Check if applicationRoutes is an empty object
|
|
179
|
+
EMPTY_ROUTES=$(grep -P "applicationRoutes.*=\s*\{[\s/]*\}" "$APP_TSX" 2>/dev/null)
|
|
180
|
+
if [ -n "$EMPTY_ROUTES" ]; then
|
|
181
|
+
echo "BLOCKING: applicationRoutes in App.tsx is empty — Layer 3 frontend was NOT executed"
|
|
182
|
+
echo "Expected: at least one application key with route definitions"
|
|
183
|
+
echo "Fix: Run Layer 3 (scaffold_routes + scaffold_extension + route wiring)"
|
|
184
|
+
exit 1
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Check pages/ directory is not empty
|
|
188
|
+
PAGE_COUNT=$(find web/ src/ -path "*/pages/*" -name "*.tsx" -not -path "*/node_modules/*" 2>/dev/null | wc -l)
|
|
189
|
+
if [ "$PAGE_COUNT" -eq 0 ]; then
|
|
190
|
+
echo "BLOCKING: No page components found in pages/ directory"
|
|
191
|
+
echo "Fix: Generate pages via scaffold_extension or /ui-components"
|
|
192
|
+
exit 1
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Check navRoutes.generated.ts exists
|
|
196
|
+
NAV_ROUTES=$(find web/ src/ -name "navRoutes.generated.ts" -not -path "*/node_modules/*" 2>/dev/null | head -1)
|
|
197
|
+
if [ -z "$NAV_ROUTES" ]; then
|
|
198
|
+
echo "BLOCKING: navRoutes.generated.ts not found — scaffold_routes was never called"
|
|
199
|
+
echo "Fix: Run scaffold_routes(source: 'controllers', outputFormat: 'applicationRoutes')"
|
|
200
|
+
exit 1
|
|
201
|
+
fi
|
|
202
|
+
fi
|
|
203
|
+
```
|
|
204
|
+
|
|
157
205
|
### POST-CHECK C3: Translation files must exist for all 4 languages (if frontend)
|
|
158
206
|
|
|
159
207
|
```bash
|
|
@@ -290,6 +290,24 @@ When launching agents for multi-entity layers:
|
|
|
290
290
|
- Agent principal updates activeForm after each entity completion:
|
|
291
291
|
`TaskUpdate(taskId: layer2_task_id, activeForm: "Building {EntityName} backend (2/5 entities)")`
|
|
292
292
|
|
|
293
|
+
### Controller NavRoute Attribute (MANDATORY)
|
|
294
|
+
|
|
295
|
+
After controller generation, verify `[NavRoute]` attribute is present on every controller:
|
|
296
|
+
- Expected: `[NavRoute("{app_name}.{module_code}.{section_code}")]` on the controller class
|
|
297
|
+
- If missing: Add it manually above `[Authorize]`
|
|
298
|
+
- When calling `scaffold_extension(type: "controller")`, always pass `navRoute` in options
|
|
299
|
+
- This is REQUIRED for `scaffold_routes` to auto-detect routes in Layer 3
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
# Quick check: all controllers must have [NavRoute] (not just [Route])
|
|
303
|
+
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
304
|
+
for f in $CTRL_FILES; do
|
|
305
|
+
if ! grep -q "\[NavRoute" "$f" && grep -q "\[Route" "$f"; then
|
|
306
|
+
echo "WARNING: $f has [Route] but no [NavRoute] — add [NavRoute] for route auto-detection"
|
|
307
|
+
fi
|
|
308
|
+
done
|
|
309
|
+
```
|
|
310
|
+
|
|
293
311
|
### Post-Layer 2 Build Gate
|
|
294
312
|
|
|
295
313
|
```bash
|
|
@@ -377,7 +395,18 @@ For each module:
|
|
|
377
395
|
→ All business applications use `<AppLayout />` as layout wrapper
|
|
378
396
|
→ See `references/frontend-route-wiring-app-tsx.md` for full Pattern A/B detection and examples
|
|
379
397
|
→ Verify: `mcp__smartstack__validate_frontend_routes (scope: 'routes')`
|
|
380
|
-
- Pages:
|
|
398
|
+
- Pages per section: When a section exists (e.g., "list"), generate ALL 4 page types:
|
|
399
|
+
→ {Section}ListPage.tsx (index route)
|
|
400
|
+
→ {Section}DetailPage.tsx (/:id route) — click on list item navigates here
|
|
401
|
+
→ Create{Section}Page.tsx (/create route)
|
|
402
|
+
→ Edit{Section}Page.tsx (/:id/edit route)
|
|
403
|
+
"detail" is NEVER a separate section — it's the /:id route of the list section.
|
|
404
|
+
- Pages: **MANDATORY — INVOKE Skill("ui-components")** for ALL page generation.
|
|
405
|
+
⚠ BLOCKING REQUIREMENT: You MUST call Skill("ui-components") for EVERY page (.tsx).
|
|
406
|
+
NEVER generate .tsx page code directly. NEVER write page content in Agent prompts.
|
|
407
|
+
NEVER use Write tool to create pages without first calling Skill("ui-components").
|
|
408
|
+
The skill loads the full style guide + patterns (entity-card, data-table, dashboard-chart, grid-layout).
|
|
409
|
+
Follow smartstack-frontend.md patterns:
|
|
381
410
|
→ React.lazy() for all page imports (named export wrapping)
|
|
382
411
|
→ `<Suspense fallback={<PageLoader />}>` around all lazy components
|
|
383
412
|
→ Page structure: hooks → useEffect(load) → loading → error → content
|
|
@@ -466,7 +495,21 @@ IF NOT economy_mode AND entities.length > 1:
|
|
|
466
495
|
# All agents launched in parallel
|
|
467
496
|
|
|
468
497
|
ELSE:
|
|
469
|
-
# Agent principal handles all entities
|
|
498
|
+
# Economy mode: Agent principal handles all entities SEQUENTIALLY.
|
|
499
|
+
# MANDATORY: You MUST still call Skill("ui-components") for page generation.
|
|
500
|
+
# economy_mode only disables parallel agents — it does NOT skip /ui-components.
|
|
501
|
+
For each entity (sequentially):
|
|
502
|
+
1. MCP scaffold_api_client
|
|
503
|
+
2. MCP scaffold_routes (outputFormat: 'applicationRoutes')
|
|
504
|
+
3. Wire routes to App.tsx (Pattern A/B — see references/frontend-route-wiring-app-tsx.md)
|
|
505
|
+
4. **INVOKE Skill("ui-components")** — pass entity context:
|
|
506
|
+
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
507
|
+
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
508
|
+
- "CSS: Use CSS variables ONLY — bg-[var(--bg-card)], text-[var(--text-primary)]"
|
|
509
|
+
- "Forms: Create/Edit are FULL PAGES with own routes (/create, /:id/edit)"
|
|
510
|
+
- "I18n: ALL text uses t('namespace:key', 'Fallback')"
|
|
511
|
+
5. I18n: 4 JSON files (fr, en, it, de) + register namespace in i18n config
|
|
512
|
+
6. Form tests: co-located .test.tsx for Create and Edit pages
|
|
470
513
|
```
|
|
471
514
|
|
|
472
515
|
### Parallel Agents + TaskCreate Integration
|
|
@@ -495,6 +538,24 @@ When delegating to `/ui-components` skill, include explicit instructions:
|
|
|
495
538
|
- "Forms: Create/Edit forms are FULL PAGES with own routes (e.g., `/create`, `/:id/edit`)."
|
|
496
539
|
- "I18n: ALL text must use `t('namespace:key', 'Fallback')`. Generate JSON files in `src/i18n/locales/`."
|
|
497
540
|
|
|
541
|
+
### HARD RULE — /ui-components is NON-NEGOTIABLE
|
|
542
|
+
|
|
543
|
+
> **VIOLATION CHECK:** If ANY .tsx page file was created by Write tool WITHOUT
|
|
544
|
+
> a prior Skill("ui-components") call in this execution, the frontend layer is INVALID.
|
|
545
|
+
>
|
|
546
|
+
> **You MUST NOT:**
|
|
547
|
+
> - Generate .tsx page code in Agent prompts and dispatch to Snipper agents
|
|
548
|
+
> - Write page content directly via the Write tool
|
|
549
|
+
> - Copy-paste page templates from your knowledge
|
|
550
|
+
>
|
|
551
|
+
> **You MUST:**
|
|
552
|
+
> - Call Skill("ui-components") which loads the style guide, responsive guidelines,
|
|
553
|
+
> accessibility rules, and pattern files (entity-card, data-table, dashboard-chart, grid-layout, kanban)
|
|
554
|
+
> - Let /ui-components generate all pages with correct conventions
|
|
555
|
+
>
|
|
556
|
+
> **Why this matters:** Without the skill, pages miss CSS variables, DataTable/EntityCard,
|
|
557
|
+
> memo()/useCallback, responsive mobile-first design, and accessibility patterns.
|
|
558
|
+
|
|
498
559
|
### Frontend Tests Inline
|
|
499
560
|
|
|
500
561
|
> **Tests are scaffolded and run WITHIN Layer 3, not deferred to step-07.**
|
|
@@ -357,13 +357,12 @@ IF workflow_mode = "project":
|
|
|
357
357
|
})
|
|
358
358
|
|
|
359
359
|
Output path: docs/business-analyse/v{version}/index.json
|
|
360
|
-
Thematic files
|
|
360
|
+
Thematic files — EXACTLY these 3, NO OTHERS:
|
|
361
361
|
- cadrage.json
|
|
362
362
|
- validation.json
|
|
363
363
|
- consolidation.json
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
// Do NOT create them at project/app level — empty files mislead downstream tools.
|
|
364
|
+
FORBIDDEN: entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json
|
|
365
|
+
Creating any FORBIDDEN file at project level is a BLOCKING ERROR.
|
|
367
366
|
|
|
368
367
|
Store:
|
|
369
368
|
project_id: string // PROJ-NNN
|
|
@@ -394,18 +393,29 @@ ELSE:
|
|
|
394
393
|
})
|
|
395
394
|
|
|
396
395
|
Output path: docs/{app}/business-analyse/v{version}/index.json
|
|
397
|
-
Thematic files
|
|
396
|
+
Thematic files — EXACTLY these 3, NO OTHERS:
|
|
398
397
|
- cadrage.json
|
|
399
398
|
- validation.json
|
|
400
|
-
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
// Do NOT create them at app level — empty files mislead derive-prd and ralph-loop.
|
|
399
|
+
- consolidation.json
|
|
400
|
+
FORBIDDEN: entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json
|
|
401
|
+
Creating any FORBIDDEN file at application level is a BLOCKING ERROR.
|
|
404
402
|
```
|
|
405
403
|
|
|
406
404
|
> **Note:** In project mode, per-application index.json files are created later in step-01-cadrage.
|
|
407
405
|
> In single-app mode, step-02 (structure) determines if it's single or multi-module.
|
|
408
406
|
|
|
407
|
+
### POST-CREATE VERIFICATION (MANDATORY)
|
|
408
|
+
|
|
409
|
+
After creating thematic files, verify no forbidden files were created:
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
List all *.json files in {docs_dir}/
|
|
413
|
+
Expected (project/application): [index.json, cadrage.json, validation.json, consolidation.json]
|
|
414
|
+
If any file NOT in expected list is found → DELETE it immediately + log WARNING
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
This guard catches any accidental creation of module-only files at the wrong scope.
|
|
418
|
+
|
|
409
419
|
## Step 10: Update Config
|
|
410
420
|
|
|
411
421
|
Update `.business-analyse/config.json` with new feature information.
|
|
@@ -423,20 +423,8 @@ ba-writer.enrichSection({
|
|
|
423
423
|
// Update status
|
|
424
424
|
ba-writer.updateStatus({feature_id}, "consolidated");
|
|
425
425
|
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
// Module-level data lives in module directories — do NOT declare empty app-level files.
|
|
429
|
-
ba-writer.enrichSection({
|
|
430
|
-
featureId: {feature_id},
|
|
431
|
-
section: "files",
|
|
432
|
-
data: {
|
|
433
|
-
// Keep only files that exist and have content at app level
|
|
434
|
-
cadrage: { path: "cadrage.json", hash: "framed", lastModified: now() },
|
|
435
|
-
validation: { path: "validation.json", hash: "consolidated", lastModified: now() }
|
|
436
|
-
// REMOVED: entities, rules, usecases, permissions, screens, handoff
|
|
437
|
-
// These exist only at module level (flat-file architecture)
|
|
438
|
-
}
|
|
439
|
-
});
|
|
426
|
+
// Clean up any forbidden files that may have been created at app level
|
|
427
|
+
ba-writer.cleanupAppLevelFiles({ featureId: {feature_id} });
|
|
440
428
|
|
|
441
429
|
// Save workflow state for resume support
|
|
442
430
|
ba-writer.enrichSection({
|
|
@@ -306,7 +306,38 @@ appendFile('.ralph/progress.txt',
|
|
|
306
306
|
);
|
|
307
307
|
```
|
|
308
308
|
|
|
309
|
-
### C2.
|
|
309
|
+
### C2. Skipped Task Audit
|
|
310
|
+
|
|
311
|
+
After apex returns, check for newly skipped tasks:
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
const newlySkipped = prdCheck.tasks.filter(t =>
|
|
315
|
+
batchIds.includes(t.id) && t.status === 'skipped'
|
|
316
|
+
);
|
|
317
|
+
if (newlySkipped.length > 0) {
|
|
318
|
+
console.warn(`⚠ ${newlySkipped.length} tasks were SKIPPED by apex:`);
|
|
319
|
+
newlySkipped.forEach(t => console.warn(` - ${t.id}: ${t.description}`));
|
|
320
|
+
|
|
321
|
+
// If ALL tasks in a category were skipped → BLOCKING, reset for retry
|
|
322
|
+
const skippedCategories = [...new Set(newlySkipped.map(t => t.category))];
|
|
323
|
+
for (const cat of skippedCategories) {
|
|
324
|
+
const allInCat = prdCheck.tasks.filter(t => t.category === cat);
|
|
325
|
+
const allSkipped = allInCat.every(t => t.status === 'skipped');
|
|
326
|
+
if (allSkipped) {
|
|
327
|
+
console.error(`BLOCKING: ALL tasks in category "${cat}" were skipped — investigate root cause`);
|
|
328
|
+
// Reset to pending for retry
|
|
329
|
+
allInCat.forEach(t => {
|
|
330
|
+
t.status = 'pending';
|
|
331
|
+
t._retryCount = (t._retryCount || 0) + 1;
|
|
332
|
+
t.error = `All tasks in category "${cat}" skipped — auto-retry`;
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
writeJSON(currentPrdPath, prdCheck);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### C3. Increment Iteration
|
|
310
341
|
|
|
311
342
|
```javascript
|
|
312
343
|
prdCheck.config.current_iteration++;
|
|
@@ -314,7 +345,7 @@ prdCheck.updated_at = new Date().toISOString();
|
|
|
314
345
|
writeJSON(currentPrdPath, prdCheck);
|
|
315
346
|
```
|
|
316
347
|
|
|
317
|
-
###
|
|
348
|
+
### C4. Git Commit (PRD state only — apex already committed code)
|
|
318
349
|
|
|
319
350
|
```bash
|
|
320
351
|
git add {currentPrdPath} .ralph/progress.txt
|
|
@@ -331,7 +362,7 @@ EOF
|
|
|
331
362
|
)"
|
|
332
363
|
```
|
|
333
364
|
|
|
334
|
-
###
|
|
365
|
+
### C5. PRD Sync Verification (HARD CHECK)
|
|
335
366
|
|
|
336
367
|
> **Note:** `prdCheck` (read in C1) is the authoritative post-apex snapshot.
|
|
337
368
|
> `completed` (from B3) was computed on a DIFFERENT read — do NOT mix the two.
|