@atlashub/smartstack-cli 4.48.0 → 4.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.documentation/testing-ba-e2e.md +76 -24
- package/package.json +1 -1
- package/templates/agents/gitflow/init.md +26 -0
- package/templates/skills/apex/references/parallel-execution.md +22 -4
- package/templates/skills/apex/steps/step-00-init.md +38 -0
- package/templates/skills/apex/steps/step-03a-layer0-domain.md +21 -0
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +60 -0
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +124 -13
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +32 -0
- package/templates/skills/application/references/backend-controller-hierarchy.md +14 -4
- package/templates/skills/business-analyse-develop/references/quality-gates.md +91 -1
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +147 -1
- package/templates/skills/business-analyse-handoff/references/acceptance-criteria.md +53 -1
- package/templates/skills/business-analyse-handoff/references/handoff-file-templates.md +42 -0
- package/templates/skills/business-analyse-handoff/references/handoff-mappings.md +15 -1
- package/templates/skills/business-analyse-handoff/references/prd-generation.md +59 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +25 -1
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +32 -4
- package/templates/skills/business-analyse-html/html/ba-interactive.html +64 -5
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +13 -1
- package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +10 -1
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +1 -1
- package/templates/skills/business-analyse-html/html/src/styles/03-navigation.css +2 -2
- package/templates/skills/business-analyse-html/html/src/styles/05-modules.css +38 -0
- package/templates/skills/controller/references/mcp-scaffold-workflow.md +8 -4
- package/templates/skills/controller/steps/step-05-validate.md +2 -2
- package/templates/skills/controller/templates.md +4 -3
- package/templates/skills/feature-full/steps/step-01-implementation.md +18 -5
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Vue d'ensemble
|
|
4
4
|
|
|
5
|
-
Infrastructure de tests E2E pour valider le pipeline complet **Business Analyse → Handoff → PRD extraction →
|
|
5
|
+
Infrastructure de tests E2E pour valider le pipeline complet **Business Analyse → Handoff → PRD extraction → `/business-analyse-develop`**.
|
|
6
6
|
|
|
7
7
|
**Garanties :**
|
|
8
8
|
- ✅ Validation déterministe du handoff
|
|
@@ -25,11 +25,15 @@ tests/ba/
|
|
|
25
25
|
│ ├── Products/
|
|
26
26
|
│ └── Orders/
|
|
27
27
|
│
|
|
28
|
-
|
|
28
|
+
├── chain-integrity.test.ts # Intégrité chaîne BA → Handoff → PRD (55 tests)
|
|
29
|
+
│
|
|
30
|
+
└── e2e/ # Test suites E2E
|
|
29
31
|
├── handoff-validation.test.ts # Validation handoff section
|
|
30
32
|
├── prd-extraction-simple.test.ts # Extraction module simple
|
|
31
33
|
├── prd-extraction-medium.test.ts # Extraction module lifecycle
|
|
32
|
-
|
|
34
|
+
├── full-pipeline.test.ts # Pipeline complet BA → PRD → develop
|
|
35
|
+
├── task-generation.test.ts # Génération de tâches depuis PRD
|
|
36
|
+
└── unified-prd.test.ts # Extraction PRD unifié (dual-mode v2/v3)
|
|
33
37
|
```
|
|
34
38
|
|
|
35
39
|
---
|
|
@@ -140,7 +144,7 @@ tests/ba/
|
|
|
140
144
|
|
|
141
145
|
### 4. full-pipeline.test.ts
|
|
142
146
|
|
|
143
|
-
**Objectif:** Tester pipeline complet BA →
|
|
147
|
+
**Objectif:** Tester pipeline complet BA → Handoff → PRD → `/business-analyse-develop`.
|
|
144
148
|
|
|
145
149
|
**Scénarios:**
|
|
146
150
|
|
|
@@ -148,10 +152,10 @@ tests/ba/
|
|
|
148
152
|
1. Load feature.json (status = "handed-off")
|
|
149
153
|
2. Validate handoff section complet
|
|
150
154
|
3. Extract prd.json déterministe
|
|
151
|
-
4. Write prd.json to .
|
|
155
|
+
4. Write prd.json to .prd/
|
|
152
156
|
5. Read back prd.json (verify integrity)
|
|
153
|
-
6. Verify all required sections for
|
|
154
|
-
7. Verify prd.json meets
|
|
157
|
+
6. Verify all required sections for `/business-analyse-develop`
|
|
158
|
+
7. Verify prd.json meets requirements (8 categories incl. `documentation`, BR mappings, CORE seedData)
|
|
155
159
|
|
|
156
160
|
**Medium Module Pipeline with Lifecycle:**
|
|
157
161
|
1. Load medium feature with lifecycle
|
|
@@ -159,7 +163,7 @@ tests/ba/
|
|
|
159
163
|
3. Extract prd.json with lifecycle preserved
|
|
160
164
|
4. Verify lifecycle transitions mapped to BR
|
|
161
165
|
5. Verify lifecycle states match seedData
|
|
162
|
-
6. Write prd.json to .
|
|
166
|
+
6. Write prd.json to .prd/
|
|
163
167
|
|
|
164
168
|
**Reproducibility Test:**
|
|
165
169
|
- Multiple extractions = identical prd.json (sans timestamp)
|
|
@@ -168,11 +172,56 @@ tests/ba/
|
|
|
168
172
|
- Missing optional namespace handled gracefully
|
|
169
173
|
- Empty arrays handled gracefully
|
|
170
174
|
|
|
171
|
-
**Integration with
|
|
175
|
+
**Integration with `/business-analyse-develop`:**
|
|
172
176
|
- All required information present (entities, UCs, BRs, endpoints, permissions, filesToCreate, BR mappings, CORE seedData)
|
|
173
177
|
- Use cases linked to API endpoints
|
|
174
178
|
- Business rules linked to use cases
|
|
175
179
|
|
|
180
|
+
### 5. chain-integrity.test.ts
|
|
181
|
+
|
|
182
|
+
**Objectif:** Valider l'intégrité de la chaîne complète BA → Handoff → PRD.
|
|
183
|
+
|
|
184
|
+
**Scénarios (55 tests, 9 parties):**
|
|
185
|
+
- Part 1: Fichiers skill BA existent et sont structurés correctement
|
|
186
|
+
- Part 2: Fichiers skill handoff existent et sont structurés correctement
|
|
187
|
+
- Part 3: Cohérence des références inter-steps (next_step valides)
|
|
188
|
+
- Part 4: Schémas JSON valides et présents
|
|
189
|
+
- Part 5: POST-CHECKs exécutables dans les steps critiques
|
|
190
|
+
- Part 6: Références aux fonctions d'extraction (extractPrd, extractUnifiedPrd)
|
|
191
|
+
- Part 7: Cohérence fixtures ↔ schéma feature-json
|
|
192
|
+
- Part 8: Imports et exports du module prd-extractor
|
|
193
|
+
- Part 9: Silent failure guards (détection parse-error avant fallback)
|
|
194
|
+
|
|
195
|
+
### 6. task-generation.test.ts
|
|
196
|
+
|
|
197
|
+
**Objectif:** Tester la génération de tâches depuis le PRD.
|
|
198
|
+
|
|
199
|
+
**Scénarios (26 tests):**
|
|
200
|
+
- Génération de tâches depuis PRD simple (module Orders)
|
|
201
|
+
- Génération de tâches depuis PRD medium (module Invoices avec lifecycle)
|
|
202
|
+
- Validation intégrité des tâches (`validateTaskIntegrity()`)
|
|
203
|
+
- Tâches couvrent toutes les entités
|
|
204
|
+
- Tâches couvrent tous les use cases
|
|
205
|
+
- Tâches ont des dépendances valides (pas de cycles)
|
|
206
|
+
- Ordre topologique respecté
|
|
207
|
+
- Tâches lifecycle incluent les transitions
|
|
208
|
+
|
|
209
|
+
### 7. unified-prd.test.ts
|
|
210
|
+
|
|
211
|
+
**Objectif:** Tester `extractUnifiedPrd()` — extraction PRD dual-mode v2/v3.
|
|
212
|
+
|
|
213
|
+
**Scénarios (24 tests):**
|
|
214
|
+
- Extraction PRD v3.0 (task-oriented) depuis feature simple
|
|
215
|
+
- Extraction PRD v3.0 depuis feature medium avec lifecycle
|
|
216
|
+
- Structure v3.0 : `$version: "3.0.0"`, tâches intégrées
|
|
217
|
+
- `validatePrdCompleteness()` : PRD complet passe
|
|
218
|
+
- `validatePrdCompleteness()` : PRD incomplet signale erreurs
|
|
219
|
+
- `getPrdFileCounts()` : comptage correct par catégorie
|
|
220
|
+
- Fallback v2.0 quand extractPrd() appelé directement
|
|
221
|
+
- Cohérence entre v2 et v3 (mêmes données source)
|
|
222
|
+
- Metadata préservé (application, module, namespace)
|
|
223
|
+
- Traçabilité source (extractedAt, featureJsonPath)
|
|
224
|
+
|
|
176
225
|
---
|
|
177
226
|
|
|
178
227
|
## Exécution des Tests
|
|
@@ -302,7 +351,7 @@ describe('My Test Suite', () => {
|
|
|
302
351
|
const feature = await fs.readJson(join(fixturesDir, 'my-feature.json')) as ModuleFeatureJson;
|
|
303
352
|
const prd = extractPrd(feature, 'my-feature.json', 'MyCompany.MyApp');
|
|
304
353
|
|
|
305
|
-
expect(prd.version).
|
|
354
|
+
expect(prd.version).toBeDefined();
|
|
306
355
|
expect(prd.project.module).toBe('MyModule');
|
|
307
356
|
// ... more assertions
|
|
308
357
|
});
|
|
@@ -377,14 +426,18 @@ jobs:
|
|
|
377
426
|
|
|
378
427
|
| Fichier | Couverture Cible |
|
|
379
428
|
|---------|-----------------|
|
|
380
|
-
| `src/utils/prd-extractor.ts` | 100% |
|
|
381
|
-
| `src/
|
|
429
|
+
| `src/utils/prd-extractor.ts` — `extractPrd()` | 100% |
|
|
430
|
+
| `src/utils/prd-extractor.ts` — `extractUnifiedPrd()` | 100% |
|
|
431
|
+
| `src/utils/prd-extractor.ts` — `validatePrdCompleteness()` | 100% |
|
|
432
|
+
| `src/utils/prd-extractor.ts` — `validateTaskIntegrity()` | 100% |
|
|
433
|
+
| `src/utils/prd-extractor.ts` — `getPrdFileCounts()` | 100% |
|
|
434
|
+
| `src/commands/business-analyse-handoff.ts` | 90% |
|
|
382
435
|
| `templates/skills/business-analyse/**/*.md` | N/A (documentation) |
|
|
383
436
|
|
|
384
437
|
### KPIs Tests
|
|
385
438
|
|
|
386
|
-
- **Total tests:**
|
|
387
|
-
- **Temps d'exécution:** <
|
|
439
|
+
- **Total tests:** 168 scénarios (7 test suites)
|
|
440
|
+
- **Temps d'exécution:** < 2s
|
|
388
441
|
- **Fixtures:** 3 (simple/medium/complex)
|
|
389
442
|
- **Couverture code:** > 95% sur extraction pipeline
|
|
390
443
|
|
|
@@ -435,22 +488,20 @@ export default defineConfig({
|
|
|
435
488
|
### Phase 1 ✅ (Implémenté)
|
|
436
489
|
- Infrastructure Vitest
|
|
437
490
|
- 3 fixtures (simple/medium/complex)
|
|
438
|
-
-
|
|
491
|
+
- 7 test suites (handoff-validation, prd-extraction x2, full-pipeline, chain-integrity, task-generation, unified-prd)
|
|
439
492
|
- Scripts npm
|
|
440
493
|
- Documentation
|
|
441
494
|
|
|
442
|
-
### Phase 2 (
|
|
495
|
+
### Phase 2 (À planifier)
|
|
443
496
|
- Tests pour mode `--application` (extraction multi-modules)
|
|
444
|
-
- Tests pour
|
|
445
|
-
- Tests pour
|
|
497
|
+
- Tests pour flag `--v4` (PRD spec-oriented)
|
|
498
|
+
- Tests pour `extractUnifiedPrd()` edge cases
|
|
446
499
|
- Performance benchmarks (extraction < 100ms)
|
|
447
|
-
- Tests pour ba-interactive.html extraction
|
|
448
500
|
|
|
449
501
|
### Phase 3 (Futur)
|
|
450
|
-
- Tests E2E
|
|
451
|
-
- Tests pour
|
|
452
|
-
- Tests pour
|
|
453
|
-
- Tests pour validation schema (feature-schema.json)
|
|
502
|
+
- Tests E2E `/business-analyse-develop` integration (mock `/apex -d`)
|
|
503
|
+
- Tests pour `/business-analyse-handoff` CLI (end-to-end avec fs)
|
|
504
|
+
- Tests pour validation schema v5.0 (`feature-schema.json`)
|
|
454
505
|
|
|
455
506
|
---
|
|
456
507
|
|
|
@@ -459,4 +510,5 @@ export default defineConfig({
|
|
|
459
510
|
- [prd-json v2.0.0 Reference](./prd-json-v2.0.0.md)
|
|
460
511
|
- [Feature JSON Schema](../templates/skills/business-analyse/schemas/feature-schema.json)
|
|
461
512
|
- [Business Analyse Skill](../templates/skills/business-analyse/SKILL.md)
|
|
462
|
-
- [
|
|
513
|
+
- [Business Analyse Develop](../templates/skills/business-analyse-develop/SKILL.md)
|
|
514
|
+
- [Business Analyse Handoff](../templates/skills/business-analyse-handoff/SKILL.md)
|
package/package.json
CHANGED
|
@@ -240,6 +240,28 @@ Check the result. If FAIL, report to user and suggest manual intervention.
|
|
|
240
240
|
|
|
241
241
|
---
|
|
242
242
|
|
|
243
|
+
## STEP 3b: DETECT PROJECT VERSION
|
|
244
|
+
|
|
245
|
+
Read `references/init-version-detection.md` and execute the version detection script.
|
|
246
|
+
|
|
247
|
+
The script detects the project version with this priority:
|
|
248
|
+
1. `*.csproj` `<Version>` tag
|
|
249
|
+
2. `Directory.Build.props` `<Version>` tag
|
|
250
|
+
3. `package.json` `"version"` field
|
|
251
|
+
4. `VERSION` file
|
|
252
|
+
5. Latest git tag (stripped of `v` prefix)
|
|
253
|
+
6. Fallback: `0.0.0`
|
|
254
|
+
|
|
255
|
+
Store the result as `{VERSION}`.
|
|
256
|
+
|
|
257
|
+
**CRITICAL:** `{VERSION}` is the PROJECT version (e.g., "0.0.0", "1.2.3").
|
|
258
|
+
It is NOT the config schema version ("2.1.0" on line 1 of config.json).
|
|
259
|
+
These are two different things:
|
|
260
|
+
- `"version": "2.1.0"` = config file format version (FIXED, do not change)
|
|
261
|
+
- `"versioning.current": "{VERSION}"` = project semver version (DETECTED)
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
243
265
|
## STEP 4: WRITE CONFIG
|
|
244
266
|
|
|
245
267
|
Write `.claude/gitflow/config.json` in develop worktree using the Write tool.
|
|
@@ -257,6 +279,10 @@ MAIN_DIR = organized → "01-Main" | simple → "main" | disabled → "."
|
|
|
257
279
|
DEVELOP_DIR = organized → "02-Develop" | simple → "develop" | disabled → "."
|
|
258
280
|
```
|
|
259
281
|
|
|
282
|
+
> **TWO DIFFERENT VERSIONS:** `"version": "2.1.0"` below is the CONFIG SCHEMA version (always 2.1.0).
|
|
283
|
+
> `"versioning.current": "{VERSION}"` is the PROJECT version (detected in step 3b).
|
|
284
|
+
> Do NOT confuse them. Do NOT use "2.1.0" as the project version.
|
|
285
|
+
|
|
260
286
|
```json
|
|
261
287
|
{
|
|
262
288
|
"version": "2.1.0",
|
|
@@ -91,12 +91,28 @@ Agent principal aggregates all results after all agents complete.
|
|
|
91
91
|
|
|
92
92
|
```
|
|
93
93
|
Layer 2 (Backend) — if multiple entities:
|
|
94
|
+
# AGENT BOUNDARY: Snipper agents do NOT have access to MCP tools.
|
|
95
|
+
# Services, DTOs, controllers MUST be scaffolded by the principal agent via MCP.
|
|
96
|
+
# Snipper agents handle ONLY: business logic, validators, code-gen wiring.
|
|
97
|
+
|
|
98
|
+
# PHASE A — Sequential: MCP scaffolding (principal agent)
|
|
99
|
+
For each entity:
|
|
100
|
+
mcp__smartstack__scaffold_extension(type: "dto", name: "{Entity}", options: { navRoute: "..." })
|
|
101
|
+
mcp__smartstack__scaffold_extension(type: "controller", name: "{Entity}", options: { navRoute: "..." })
|
|
102
|
+
Verify NavRoute on generated controller (bash)
|
|
103
|
+
|
|
104
|
+
# PHASE B — Parallel: post-scaffold adjustments (Snipper agents)
|
|
94
105
|
Agent(subagent_type='Snipper', model='opus',
|
|
95
|
-
prompt='
|
|
106
|
+
prompt='Adjust Layer 2 backend for {Entity1}: service logic, validators, code-gen wiring.
|
|
107
|
+
DO NOT regenerate controller/DTO — already created by MCP.')
|
|
96
108
|
Agent(subagent_type='Snipper', model='opus',
|
|
97
|
-
prompt='
|
|
109
|
+
prompt='Adjust Layer 2 backend for {Entity2}: service logic, validators, code-gen wiring.
|
|
110
|
+
DO NOT regenerate controller/DTO — already created by MCP.')
|
|
98
111
|
# Launched in parallel in a single message
|
|
99
112
|
|
|
113
|
+
# PHASE C — Sequential: DI registration (principal agent)
|
|
114
|
+
# Register all services + validators in DependencyInjection.cs (single pass, no conflicts)
|
|
115
|
+
|
|
100
116
|
Layer 3 (Frontend) — if multiple entities:
|
|
101
117
|
# ⛔ AGENT BOUNDARY: Snipper agents do NOT have access to Skill().
|
|
102
118
|
# Pages (.tsx) MUST be generated by the principal agent via Skill("ui-components").
|
|
@@ -138,7 +154,9 @@ Each agent has an **isolated scope**: handles one entity end-to-end within the l
|
|
|
138
154
|
2. Build gate: dotnet build → MUST PASS
|
|
139
155
|
3. Layer 1: agent principal executes (seed data — sequential, no parallel agents)
|
|
140
156
|
4. Build gate: dotnet build → MUST PASS
|
|
141
|
-
5. Layer 2:
|
|
157
|
+
5. Layer 2 Phase A: principal scaffolds ALL entities via MCP (dto + controller per entity)
|
|
158
|
+
5b. Layer 2 Phase B: launch Snipper agents for post-scaffold adjustments (parallel)
|
|
159
|
+
5c. Layer 2 Phase C: principal registers all DI in DependencyInjection.cs (single pass)
|
|
142
160
|
6. Build gate: dotnet build → MUST PASS
|
|
143
161
|
7. Backend tests inline (scaffold + run + fix max 3)
|
|
144
162
|
8. Layer 3 Phase A: launch Snipper agents for infra (api-client, routes, i18n) — NOT pages
|
|
@@ -163,7 +181,7 @@ There is no idle state to manage — the agent principal simply waits for result
|
|
|
163
181
|
|-----------|--------|
|
|
164
182
|
| economy_mode = true | NO parallel agents, all sequential |
|
|
165
183
|
| Single entity (any layer) | NO parallel agents, agent principal handles all |
|
|
166
|
-
| Multiple entities, Layer 2 |
|
|
184
|
+
| Multiple entities, Layer 2 | Phase A: principal scaffolds via MCP (sequential). Phase B: Snipper for business logic (parallel). Phase C: principal DI registration (sequential) |
|
|
167
185
|
| Multiple entities, Layer 3 | Parallel: Snipper agents for infra (api-client, routes, i18n) — pages by principal via Skill("ui-components") |
|
|
168
186
|
| Layer 0, Layer 1, Layer 4 | NO parallel agents (sequential by nature) |
|
|
169
187
|
| Analysis phase (step-01) | Parallel: 2-3 Explore agents (backend + frontend + context) |
|
|
@@ -57,6 +57,43 @@ When `-d {prd_path}` is used, extract all context from PRD file and skip section
|
|
|
57
57
|
- `{needs_migration}` = any tasks with _migrationMeta
|
|
58
58
|
- `{has_dependencies}` = prd.tasks.some(t => t.dependencies.length > 0) ? "references" : "none"
|
|
59
59
|
|
|
60
|
+
**Fallback extraction (if prd.project is absent — e.g. PRD v3.0.0 with metadata format):**
|
|
61
|
+
- `{app_name}` = prd.metadata?.applicationCode || prd.project?.application
|
|
62
|
+
- `{module_code}` = prd.metadata?.moduleCode || prd.project?.module
|
|
63
|
+
- `{entities}` = prd.implementation?.filesToCreate?.domain?.filter(f => f.type === 'Entity').map(f => extractEntityName(f.path)) || domain tasks fallback
|
|
64
|
+
- `{sections}` = prd.implementation?.filesToCreate?.seedData?.filter(f => f.path.includes('NavigationSectionSeedData')).length > 0 ? extractSectionsFromSeedDataPaths(prd) : []
|
|
65
|
+
- `{needs_seed_data}` = (prd.implementation?.filesToCreate?.seedData?.length || 0) > 0
|
|
66
|
+
- `{needs_migration}` = (prd.implementation?.filesToCreate?.infrastructure?.length || 0) > 0
|
|
67
|
+
|
|
68
|
+
**Specification Files Loading (if prd.specificationFiles present):**
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
if (prd.specificationFiles) {
|
|
72
|
+
const specsDir = path.dirname(delegate_prd_path); // .ralph/
|
|
73
|
+
const specFiles = prd.specificationFiles;
|
|
74
|
+
|
|
75
|
+
// Store loading plan for layer-specific consumption
|
|
76
|
+
specification_loading_plan = {
|
|
77
|
+
layer0_domain: [specFiles.entities],
|
|
78
|
+
layer1_seed: [specFiles.entities, specFiles.permissions],
|
|
79
|
+
layer2_backend: [specFiles.rules, specFiles.usecases],
|
|
80
|
+
layer3_frontend: [specFiles.screens, specFiles.usecases]
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Verify all companion files exist
|
|
84
|
+
for (const [layer, files] of Object.entries(specification_loading_plan)) {
|
|
85
|
+
for (const file of files) {
|
|
86
|
+
const filePath = path.join(specsDir, file);
|
|
87
|
+
if (!fileExists(filePath)) {
|
|
88
|
+
console.warn(`WARNING: Companion file missing for ${layer}: ${filePath}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
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
|
+
|
|
60
97
|
**Jump to:** section 3 (MCP verify) → section 6 (determine needs) → section 9 (summary)
|
|
61
98
|
|
|
62
99
|
---
|
|
@@ -231,6 +268,7 @@ Hierarchy: {app_name} → {module_code} → {sections[].code}
|
|
|
231
268
|
Entities: {entities} | Complexity: {module_complexity} | Deps: {has_dependencies}
|
|
232
269
|
Code: {code_patterns summary} | PRD: {prd_path||none} | Feature: {feature_path||none}
|
|
233
270
|
Flags: {active_flags} | MCP: {available|degraded} | Needs: {migration/seed/workflow/notification}
|
|
271
|
+
Specs: {specification_loading_plan ? 'companion files available (layer-specific loading)' : 'none'}
|
|
234
272
|
NEXT STEP: step-01-analyze
|
|
235
273
|
```
|
|
236
274
|
|
|
@@ -9,6 +9,27 @@ parent_step: steps/step-03-execute.md
|
|
|
9
9
|
|
|
10
10
|
## Layer 0 — Domain + Infrastructure (sequential, agent principal)
|
|
11
11
|
|
|
12
|
+
### Companion Specs Loading (delegate mode)
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
if (delegate_mode && specification_loading_plan) {
|
|
16
|
+
const specsDir = path.dirname(delegate_prd_path);
|
|
17
|
+
// Layer 0 loads: entities companion
|
|
18
|
+
for (const file of specification_loading_plan.layer0_domain) {
|
|
19
|
+
const specPath = path.join(specsDir, file);
|
|
20
|
+
if (fileExists(specPath)) {
|
|
21
|
+
const specData = readJSON(specPath);
|
|
22
|
+
// specData.entities[] contains full attribute definitions:
|
|
23
|
+
// { name, type, required, validation, defaultValue, relationships[] }
|
|
24
|
+
// Use these for entity scaffolding instead of just entity names
|
|
25
|
+
console.log(`Loaded ${specPath}: ${(specData.entities || []).length} entities with full attributes`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
> When companion specs are loaded, use `specData.entities[].attributes[]` for entity property definitions (type, required, validation, defaultValue) instead of inferring from task descriptions. This ensures oneshot generation with correct types and constraints.
|
|
32
|
+
|
|
12
33
|
### Task Progress
|
|
13
34
|
TaskUpdate(taskId: layer0_task_id, status: "in_progress")
|
|
14
35
|
TaskUpdate(taskId: progress_tracker_id,
|
|
@@ -9,6 +9,31 @@ parent_step: steps/step-03-execute.md
|
|
|
9
9
|
|
|
10
10
|
## Layer 1 — Seed Data (DEDICATED LAYER — sequential, agent principal)
|
|
11
11
|
|
|
12
|
+
### Companion Specs Loading (delegate mode)
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
if (delegate_mode && specification_loading_plan) {
|
|
16
|
+
const specsDir = path.dirname(delegate_prd_path);
|
|
17
|
+
// Layer 1 loads: entities + permissions companions
|
|
18
|
+
for (const file of specification_loading_plan.layer1_seed) {
|
|
19
|
+
const specPath = path.join(specsDir, file);
|
|
20
|
+
if (fileExists(specPath)) {
|
|
21
|
+
const specData = readJSON(specPath);
|
|
22
|
+
if (specData.entities) {
|
|
23
|
+
// Use entities[].seedValues[] for business seed data generation
|
|
24
|
+
console.log(`Loaded entities: ${specData.entities.length} entities`);
|
|
25
|
+
}
|
|
26
|
+
if (specData.permissionPaths || specData.roles) {
|
|
27
|
+
// Use full permission structure for PermissionsSeedData and RolesSeedData
|
|
28
|
+
console.log(`Loaded permissions: ${(specData.permissionPaths || []).length} paths, ${(specData.roles || []).length} roles`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
> When companion specs are loaded, use `specData.permissionPaths[]` for exact permission paths and `specData.roles[]` for role definitions instead of generating from conventions. This ensures permission seed data matches BA specifications exactly.
|
|
36
|
+
|
|
12
37
|
### Task Progress
|
|
13
38
|
TaskUpdate(taskId: layer1_task_id, status: "in_progress")
|
|
14
39
|
TaskUpdate(taskId: progress_tracker_id,
|
|
@@ -157,6 +182,39 @@ Generate all files from scratch using `references/core-seed-data.md` templates:
|
|
|
157
182
|
|
|
158
183
|
---
|
|
159
184
|
|
|
185
|
+
### Startup Pipeline Wiring (ONCE per project)
|
|
186
|
+
|
|
187
|
+
> **CRITICAL:** Seed data files are useless without startup execution.
|
|
188
|
+
> Reference: SmartStack.app `SmartStackExtensions.cs` → `InitializeSmartStackAsync()` → `RunClientSeedDataProvidersAsync()`
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
Glob("**/Program.cs") → Read Program.cs
|
|
192
|
+
|
|
193
|
+
IF Program.cs calls `InitializeSmartStackAsync()`:
|
|
194
|
+
→ Seed data pipeline is already wired ✅
|
|
195
|
+
|
|
196
|
+
ELSE IF Program.cs ONLY calls `MigrateAsync()` without seed data execution:
|
|
197
|
+
→ Add seed data provider execution AFTER MigrateAsync():
|
|
198
|
+
|
|
199
|
+
After `await extDb.Database.MigrateAsync();`:
|
|
200
|
+
var seedProviders = scope.ServiceProvider
|
|
201
|
+
.GetServices<IClientSeedDataProvider>()
|
|
202
|
+
.OrderBy(s => s.Order).ToList();
|
|
203
|
+
foreach (var provider in seedProviders)
|
|
204
|
+
{
|
|
205
|
+
var coreDb = scope.ServiceProvider.GetRequiredService<ICoreDbContext>();
|
|
206
|
+
await provider.SeedNavigationAsync(coreDb, CancellationToken.None);
|
|
207
|
+
await provider.SeedRolesAsync(coreDb, CancellationToken.None);
|
|
208
|
+
await provider.SeedPermissionsAsync(coreDb, CancellationToken.None);
|
|
209
|
+
await provider.SeedRolePermissionsAsync(coreDb, CancellationToken.None);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
Add using: SmartStack.Application.Common.Interfaces.Seeding
|
|
213
|
+
→ ONE-TIME wiring. Future modules just add DI registrations.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
160
218
|
### Post-Layer 1 Verification Checklist
|
|
161
219
|
|
|
162
220
|
> **Before the build gate, verify ALL new scope elements are covered:**
|
|
@@ -169,6 +227,8 @@ For each section in {sections} from step-00:
|
|
|
169
227
|
✓ PermissionsSeedData has HasData() for each permission
|
|
170
228
|
✓ RolesSeedData maps all 4 roles to section permissions
|
|
171
229
|
✓ {App}SeedDataProvider references all seed data classes
|
|
230
|
+
✓ Program.cs executes seed data providers after MigrateAsync()
|
|
231
|
+
✓ DI registers: services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()
|
|
172
232
|
|
|
173
233
|
IF any check fails → fix BEFORE build gate
|
|
174
234
|
```
|
|
@@ -9,6 +9,37 @@ parent_step: steps/step-03-execute.md
|
|
|
9
9
|
|
|
10
10
|
## Layer 2 — Backend (Services + Controllers)
|
|
11
11
|
|
|
12
|
+
### Companion Specs Loading (delegate mode)
|
|
13
|
+
|
|
14
|
+
```javascript
|
|
15
|
+
if (delegate_mode && specification_loading_plan) {
|
|
16
|
+
const specsDir = path.dirname(delegate_prd_path);
|
|
17
|
+
// Layer 2 loads: rules + usecases companions
|
|
18
|
+
for (const file of specification_loading_plan.layer2_backend) {
|
|
19
|
+
const specPath = path.join(specsDir, file);
|
|
20
|
+
if (fileExists(specPath)) {
|
|
21
|
+
const specData = readJSON(specPath);
|
|
22
|
+
if (specData.rules) {
|
|
23
|
+
// Full rule definitions: statement, example, formula, conditions
|
|
24
|
+
// Use for: Validator rules (BR-VAL-*), calculation logic (BR-CALC-*), workflow guards (BR-WF-*)
|
|
25
|
+
console.log(`Loaded rules: ${specData.rules.length} business rules with full definitions`);
|
|
26
|
+
}
|
|
27
|
+
if (specData.useCases || specData.usecases) {
|
|
28
|
+
const ucs = specData.useCases || specData.usecases;
|
|
29
|
+
// Full UC definitions: steps[], preconditions[], result, alternativeFlows
|
|
30
|
+
// Use for: Service method implementation, controller actions, error handling
|
|
31
|
+
console.log(`Loaded usecases: ${ucs.length} use cases with steps and preconditions`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
> When companion specs are loaded:
|
|
39
|
+
> - **BR-VAL-*** rules: use `rule.statement` + `rule.conditions[]` to implement FluentValidation rules with exact business logic
|
|
40
|
+
> - **BR-CALC-*** rules: use `rule.formula` to implement calculation methods with the exact formula
|
|
41
|
+
> - **Use cases**: use `uc.steps[]` to implement service methods following the exact flow, and `uc.preconditions[]` for guard clauses
|
|
42
|
+
|
|
12
43
|
### Task Progress
|
|
13
44
|
TaskUpdate(taskId: layer2_task_id, status: "in_progress")
|
|
14
45
|
TaskUpdate(taskId: progress_tracker_id,
|
|
@@ -22,6 +53,28 @@ TaskUpdate(taskId: progress_tracker_id,
|
|
|
22
53
|
> - DateOnly vs string for DTO date fields
|
|
23
54
|
> - Code generation patterns (ICodeGenerator<T> registration, see references/code-generation.md)
|
|
24
55
|
|
|
56
|
+
### HARD RULE — MCP scaffold_extension is NON-NEGOTIABLE for backend generation
|
|
57
|
+
|
|
58
|
+
> **VIOLATION CHECK:** If ANY service, controller, or DTO file was created by Write tool
|
|
59
|
+
> WITHOUT a prior MCP scaffold_extension call in this execution, the backend layer is INVALID.
|
|
60
|
+
>
|
|
61
|
+
> **You MUST NOT:**
|
|
62
|
+
> - Generate service/controller/DTO code in Agent prompts and dispatch to Snipper agents
|
|
63
|
+
> - Write controller content directly via the Write tool
|
|
64
|
+
> - Copy-paste controller templates from your knowledge
|
|
65
|
+
>
|
|
66
|
+
> **You MUST:**
|
|
67
|
+
> - Call MCP scaffold_extension for each entity (service, DTO, controller)
|
|
68
|
+
> - Let MCP generate all files with correct NavRoute, permissions, conventions
|
|
69
|
+
>
|
|
70
|
+
> **Why this matters:** Without MCP, controllers get both [Route] and [NavRoute] (causes 404s),
|
|
71
|
+
> NavRoute typos, incorrect permission scoping, and missing convention compliance.
|
|
72
|
+
>
|
|
73
|
+
> **Agent boundary rule:** Snipper sub-agents DO NOT have access to MCP tools.
|
|
74
|
+
> Therefore, MCP scaffolding MUST NEVER be delegated to Snipper agents.
|
|
75
|
+
> MCP calls are ALWAYS executed by the principal agent.
|
|
76
|
+
> Snipper agents handle: DI registration, business logic adjustments, validator customization.
|
|
77
|
+
|
|
25
78
|
### Backend Tasks (sequential or parallel within layer)
|
|
26
79
|
|
|
27
80
|
- Services/DTOs: MCP scaffold_extension
|
|
@@ -63,32 +116,65 @@ For each entity where {code_patterns} defines strategy != "manual":
|
|
|
63
116
|
| /notification | In-app or email notifications | trigger, recipients, template |
|
|
64
117
|
| /workflow | Automated workflows | trigger, steps, conditions |
|
|
65
118
|
|
|
66
|
-
### If NOT economy_mode AND multiple entities:
|
|
119
|
+
### If NOT economy_mode AND multiple entities: Phased Execution
|
|
67
120
|
|
|
68
121
|
> **Protocol:** See `references/parallel-execution.md`
|
|
122
|
+
> **AGENT BOUNDARY:** Snipper agents do NOT have access to MCP tools or Bash.
|
|
123
|
+
> MCP scaffolding and bash validation MUST be executed by the principal agent.
|
|
124
|
+
|
|
125
|
+
#### Phase A — Sequential: MCP scaffolding (principal agent)
|
|
126
|
+
|
|
127
|
+
For each entity, the principal agent calls MCP directly:
|
|
69
128
|
|
|
70
129
|
```
|
|
71
130
|
IF NOT economy_mode AND entities.length > 1:
|
|
131
|
+
|
|
132
|
+
FOR EACH entity in entities:
|
|
133
|
+
1. mcp__smartstack__scaffold_extension(type: "dto", name: "{Entity}", options: { navRoute: "{navRoute}" })
|
|
134
|
+
2. mcp__smartstack__scaffold_extension(type: "controller", name: "{Entity}", options: { navRoute: "{navRoute}" })
|
|
135
|
+
|
|
136
|
+
# Immediate NavRoute verification (principal has Bash access)
|
|
137
|
+
3. Verify: [NavRoute] present, [Route] absent, segment count >= 2
|
|
138
|
+
If [Route] found alongside [NavRoute] → remove [Route] immediately
|
|
139
|
+
If [NavRoute] missing → add it with correct value
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Phase B — Parallel: post-scaffold adjustments (Snipper agents)
|
|
143
|
+
|
|
144
|
+
After ALL Phase A scaffolding completes, launch Snipper agents in parallel:
|
|
145
|
+
|
|
146
|
+
```
|
|
72
147
|
For each entity, launch in parallel (single message):
|
|
73
148
|
Agent(subagent_type='Snipper', model='opus',
|
|
74
|
-
prompt='
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
- IMPORTANT: GetAll endpoint MUST support ?search= parameter
|
|
78
|
-
- Validators: FluentValidation + DI registration
|
|
149
|
+
prompt='Adjust Layer 2 backend for {EntityName}:
|
|
150
|
+
- Service: implement business logic in {EntityName}Service (FK patterns, search, inline Select)
|
|
151
|
+
- Validator: customize FluentValidation rules for Create{EntityName}Dto and Update{EntityName}Dto
|
|
79
152
|
- CODE GENERATION: {code_patterns[EntityName] summary — e.g., "strategy: sequential, prefix: emp, digits: 5" or "manual"}
|
|
80
153
|
If strategy != "manual": read references/code-generation.md, then:
|
|
81
|
-
→
|
|
82
|
-
→
|
|
83
|
-
→ Remove Code from Create{EntityName}Dto
|
|
84
|
-
→ Keep Code in {EntityName}ResponseDto
|
|
154
|
+
→ Inject ICodeGenerator<{EntityName}> in {EntityName}Service constructor
|
|
155
|
+
→ Use _codeGenerator.NextCodeAsync(ct) in CreateAsync
|
|
156
|
+
→ Remove Code from Create{EntityName}Dto, keep in {EntityName}ResponseDto
|
|
85
157
|
→ Create{EntityName}Validator: NO Code rule. Update{EntityName}Validator: Code rule with regex ^[a-z0-9_-]+$
|
|
86
158
|
- Your task ID is {task_id}. Call TaskUpdate(status: "in_progress") before starting.
|
|
87
|
-
- Call TaskUpdate(status: "completed", metadata: { files_created: [...] }) when done.
|
|
159
|
+
- Call TaskUpdate(status: "completed", metadata: { files_created: [...] }) when done.
|
|
160
|
+
|
|
161
|
+
DO NOT regenerate controller or DTO files — already created by MCP in Phase A.
|
|
162
|
+
DO NOT add [Route] attribute — NavRoute is already set correctly.
|
|
163
|
+
Files already created: {list of paths from Phase A}')
|
|
88
164
|
# All agents launched in parallel
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Phase C — Sequential: shared file edits (principal agent)
|
|
168
|
+
|
|
169
|
+
After ALL Phase B agents complete, the principal agent handles shared-file edits:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
1. DependencyInjection.cs: register ALL services + validators in a single pass
|
|
173
|
+
→ Avoids concurrent edit conflicts on shared file
|
|
174
|
+
2. Code-generation DI: register ICodeGenerator<T> for each entity with strategy != "manual"
|
|
89
175
|
|
|
90
176
|
ELSE:
|
|
91
|
-
# Agent principal handles all entities sequentially
|
|
177
|
+
# Agent principal handles all entities sequentially (economy_mode or single entity)
|
|
92
178
|
```
|
|
93
179
|
|
|
94
180
|
### Parallel Agents + TaskCreate Integration
|
|
@@ -105,7 +191,7 @@ When launching agents for multi-entity layers:
|
|
|
105
191
|
|
|
106
192
|
After controller generation, verify `[NavRoute]` attribute is present on every controller:
|
|
107
193
|
- Expected: `[NavRoute("{app_name}.{module_code}.{section_code}")]` on the controller class
|
|
108
|
-
- If missing: Add it manually above `[Authorize]`
|
|
194
|
+
- If missing: Add it manually above `[Microsoft.AspNetCore.Authorization.Authorize]`
|
|
109
195
|
- When calling `scaffold_extension(type: "controller")`, always pass `navRoute` in options
|
|
110
196
|
- This is REQUIRED for `scaffold_routes` to auto-detect routes in Layer 3
|
|
111
197
|
|
|
@@ -121,6 +207,9 @@ After controller generation, verify `[NavRoute]` attribute is present on every c
|
|
|
121
207
|
- **If a controller is in a section subfolder** (e.g., `Controllers/{App}/Employees/ContractsController.cs`) **but has only 2 segments** → the API route will be wrong → 404. It MUST have 3 segments.
|
|
122
208
|
- 0 dots = INVALID → BLOCK
|
|
123
209
|
|
|
210
|
+
> **Execution context:** These bash scripts run from the PRINCIPAL AGENT after Phase C.
|
|
211
|
+
> Snipper agents cannot execute Bash. Do NOT include these checks in Snipper prompts.
|
|
212
|
+
|
|
124
213
|
```bash
|
|
125
214
|
# Quick validation
|
|
126
215
|
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
@@ -149,6 +238,9 @@ for f in $CTRL_FILES; do
|
|
|
149
238
|
if ! grep -q "\[NavRoute" "$f" && grep -q "\[Route" "$f"; then
|
|
150
239
|
echo "WARNING: $f has [Route] but no [NavRoute] — add [NavRoute] for route auto-detection"
|
|
151
240
|
fi
|
|
241
|
+
if grep -q "\[NavRoute" "$f" && grep -q "\[Route(" "$f"; then
|
|
242
|
+
echo "WARNING: $f has BOTH [Route] and [NavRoute] — remove [Route] (causes 404s)"
|
|
243
|
+
fi
|
|
152
244
|
done
|
|
153
245
|
```
|
|
154
246
|
|
|
@@ -181,6 +273,25 @@ for ENTITY in $ENTITIES; do
|
|
|
181
273
|
echo "BLOCKING: $CTRL has NO route attribute at all"
|
|
182
274
|
echo "Fix: Add [NavRoute(\"{app}.{module}.{section}\")] from naming rules"
|
|
183
275
|
fi
|
|
276
|
+
|
|
277
|
+
if [ "$HAS_NAVROUTE" -gt 0 ] && [ "$HAS_ROUTE" -gt 0 ]; then
|
|
278
|
+
echo "BLOCKING: $CTRL has BOTH [Route] and [NavRoute] — causes 404s"
|
|
279
|
+
echo "Fix: Remove [Route(\"...\")], keep only [NavRoute(\"...\")]"
|
|
280
|
+
fi
|
|
281
|
+
done
|
|
282
|
+
|
|
283
|
+
# Check NavRoute uniqueness across generated controllers
|
|
284
|
+
ALL_NAVROUTES=""
|
|
285
|
+
for ENTITY in $ENTITIES; do
|
|
286
|
+
CTRL=$(find src/ -path "*/Controllers/*" -name "${ENTITY}*Controller.cs" 2>/dev/null | head -1)
|
|
287
|
+
[ -z "$CTRL" ] && continue
|
|
288
|
+
NR=$(grep -oP '\[NavRoute\("\K[^"]+' "$CTRL" 2>/dev/null || true)
|
|
289
|
+
[ -z "$NR" ] && continue
|
|
290
|
+
if echo "$ALL_NAVROUTES" | grep -qx "$NR"; then
|
|
291
|
+
echo "BLOCKING: Duplicate NavRoute '$NR' on $CTRL — each controller needs a unique NavRoute"
|
|
292
|
+
fi
|
|
293
|
+
ALL_NAVROUTES="$ALL_NAVROUTES
|
|
294
|
+
$NR"
|
|
184
295
|
done
|
|
185
296
|
```
|
|
186
297
|
|