@atlashub/smartstack-cli 4.32.0 → 4.34.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/index.html +2 -2
- package/.documentation/init.html +358 -174
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +271 -44
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/mcp-scaffolding/controller.cs.hbs +54 -128
- package/templates/project/README.md +19 -0
- package/templates/project/claude-md/api.CLAUDE.md.template +315 -0
- package/templates/project/claude-md/application.CLAUDE.md.template +181 -0
- package/templates/project/claude-md/domain.CLAUDE.md.template +125 -0
- package/templates/project/claude-md/infrastructure.CLAUDE.md.template +168 -0
- package/templates/project/claude-md/root.CLAUDE.md.template +339 -0
- package/templates/project/claude-md/web.CLAUDE.md.template +339 -0
- package/templates/skills/apex/SKILL.md +16 -10
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/architecture-checks.sh +154 -0
- package/templates/skills/apex/references/checks/backend-checks.sh +194 -0
- package/templates/skills/apex/references/checks/frontend-checks.sh +448 -0
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +255 -0
- package/templates/skills/apex/references/checks/security-checks.sh +153 -0
- package/templates/skills/apex/references/checks/seed-checks.sh +536 -0
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +49 -192
- package/templates/skills/apex/references/post-checks.md +124 -2156
- package/templates/skills/apex/references/smartstack-api.md +160 -957
- package/templates/skills/apex/references/smartstack-frontend.md +134 -1022
- package/templates/skills/apex/references/smartstack-layers.md +12 -6
- package/templates/skills/apex/steps/step-00-init.md +81 -238
- package/templates/skills/apex/steps/step-03-execute.md +25 -752
- package/templates/skills/apex/steps/step-03a-layer0-domain.md +118 -0
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +91 -0
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +240 -0
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +300 -0
- package/templates/skills/apex/steps/step-03e-layer4-devdata.md +44 -0
- package/templates/skills/apex/steps/step-04-examine.md +70 -150
- package/templates/skills/application/references/frontend-i18n-and-output.md +2 -2
- package/templates/skills/application/references/frontend-route-naming.md +5 -1
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +49 -198
- package/templates/skills/application/references/frontend-verification.md +11 -11
- package/templates/skills/application/steps/step-05-frontend.md +26 -15
- package/templates/skills/application/templates-frontend.md +4 -0
- package/templates/skills/cli-app-sync/SKILL.md +2 -2
- package/templates/skills/cli-app-sync/references/comparison-map.md +1 -1
- package/templates/skills/controller/references/controller-code-templates.md +70 -67
- package/templates/skills/controller/references/mcp-scaffold-workflow.md +5 -1
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-03d-layer3-frontend
|
|
3
|
+
description: "Layer 3: Frontend pages, i18n, routes, documentation, and tests"
|
|
4
|
+
model: opus
|
|
5
|
+
parent_step: steps/step-03-execute.md
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Layer 3 — Frontend (Pages + I18n + Documentation)
|
|
9
|
+
|
|
10
|
+
### ⛔ HARD RULE — /ui-components is NON-NEGOTIABLE (read BEFORE any Layer 3 action)
|
|
11
|
+
|
|
12
|
+
> **VIOLATION CHECK:** If ANY .tsx page file was created by Write tool WITHOUT
|
|
13
|
+
> a prior Skill("ui-components") call in this execution, the frontend layer is INVALID.
|
|
14
|
+
>
|
|
15
|
+
> **You MUST NOT:**
|
|
16
|
+
> - Generate .tsx page code in Agent prompts and dispatch to Snipper agents
|
|
17
|
+
> - Write page content directly via the Write tool
|
|
18
|
+
> - Copy-paste page templates from your knowledge
|
|
19
|
+
>
|
|
20
|
+
> **You MUST:**
|
|
21
|
+
> - Call Skill("ui-components") which loads the style guide, responsive guidelines,
|
|
22
|
+
> accessibility rules, and pattern files (entity-card, data-table, dashboard-chart, grid-layout, kanban)
|
|
23
|
+
> - Let /ui-components generate all pages with correct conventions
|
|
24
|
+
>
|
|
25
|
+
> **Why this matters:** Without the skill, pages miss CSS variables, DataTable/EntityCard,
|
|
26
|
+
> memo()/useCallback, responsive mobile-first design, and accessibility patterns.
|
|
27
|
+
>
|
|
28
|
+
> **Agent boundary rule:** Snipper sub-agents DO NOT have access to the Skill tool.
|
|
29
|
+
> Therefore, .tsx page generation MUST NEVER be delegated to Snipper agents.
|
|
30
|
+
> Pages are ALWAYS generated by the principal agent via Skill("ui-components").
|
|
31
|
+
> Snipper agents handle: API clients, routes, wiring, i18n, tests — NOT pages.
|
|
32
|
+
|
|
33
|
+
### Load Frontend References (deferred from top of step)
|
|
34
|
+
|
|
35
|
+
- Read `references/smartstack-frontend.md` now — lazy loading, i18n, page structure, CSS variables, EntityLookup (sections 1-6)
|
|
36
|
+
- Read `references/smartstack-frontend-compliance.md` now — documentation, form testing, compliance gates (sections 7-9)
|
|
37
|
+
|
|
38
|
+
### Pre-flight: Shared component existence check
|
|
39
|
+
|
|
40
|
+
Before generating any page, verify shared components exist:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Glob("src/components/ui/DataTable.*")
|
|
44
|
+
Glob("src/components/ui/EntityCard.*")
|
|
45
|
+
Glob("src/components/ui/PageLoader.*")
|
|
46
|
+
Glob("src/components/ui/EntityLookup.*")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If ANY shared component is MISSING:
|
|
50
|
+
→ Log warning: "Shared component {Component} not found — will be generated locally"
|
|
51
|
+
→ When invoking Skill("ui-components"), add instruction:
|
|
52
|
+
"MISSING SHARED COMPONENTS: {list}. Generate these locally in src/components/ui/"
|
|
53
|
+
|
|
54
|
+
**EntityLookup special handling (FK fields):**
|
|
55
|
+
If ANY entity has FK Guid fields (e.g., EmployeeId, DepartmentId) AND EntityLookup is missing:
|
|
56
|
+
→ Include EntityLookup generation in the Skill("ui-components") invocation
|
|
57
|
+
→ Add to the skill prompt: "MISSING SHARED COMPONENT: EntityLookup. Generate EntityLookup in src/components/ui/EntityLookup.tsx"
|
|
58
|
+
→ The /ui-components skill has the EntityLookup pattern in smartstack-frontend.md section 6
|
|
59
|
+
→ Critical requirement for the skill: response parsing MUST use `(res.data.items || res.data).map(mapOption)`
|
|
60
|
+
→ Verify after generation: the component MUST contain `(res.data.items || res.data).map(mapOption)` — if not, fix it
|
|
61
|
+
→ Do NOT generate EntityLookup manually via Write tool — always via Skill("ui-components")
|
|
62
|
+
|
|
63
|
+
### Task Progress
|
|
64
|
+
TaskUpdate(taskId: layer3_task_id, status: "in_progress")
|
|
65
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
66
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 3",
|
|
67
|
+
activeForm: "Executing Layer 3")
|
|
68
|
+
|
|
69
|
+
> **Frontend patterns** are in `references/smartstack-frontend.md` (already loaded above):
|
|
70
|
+
> - API client generation (MCP scaffold_api_client)
|
|
71
|
+
> - Route scaffolding (MCP scaffold_routes) — section 1 + 3b
|
|
72
|
+
> - Page types (ListPage, DetailPage, CreatePage, EditPage) — section 3
|
|
73
|
+
> - FK field handling (EntityLookup component) — section 6
|
|
74
|
+
> - Form structure (no modals — all full pages) — section 3b
|
|
75
|
+
> - Detail page tabs (local state only) — section 3 "Tab Behavior Rules"
|
|
76
|
+
> - Testing patterns (co-located form tests) — section 8
|
|
77
|
+
> - Section-level routes and permissions — section 3b
|
|
78
|
+
> - I18n JSON structure and registration — section 2
|
|
79
|
+
> - Compliance gates (5 mandatory checks) — section 9
|
|
80
|
+
|
|
81
|
+
### Frontend Tasks (sequential or parallel within layer)
|
|
82
|
+
|
|
83
|
+
For each module:
|
|
84
|
+
- API client: MCP scaffold_api_client
|
|
85
|
+
- Routes — TWO mandatory steps:
|
|
86
|
+
1. Generate registry: MCP scaffold_routes (source: 'controllers', outputFormat: 'componentRegistry', dryRun: false)
|
|
87
|
+
→ Creates/updates componentRegistry.generated.ts + navRoutes.generated.ts
|
|
88
|
+
2. Verify PageRegistry registration (see below)
|
|
89
|
+
- Pages per section: When a section exists (e.g., "list"), generate ALL 4 page types:
|
|
90
|
+
→ {Section}ListPage.tsx (index route)
|
|
91
|
+
→ {Section}DetailPage.tsx (/:id route) — click on list item navigates here
|
|
92
|
+
→ Create{Section}Page.tsx (/create route)
|
|
93
|
+
→ Edit{Section}Page.tsx (/:id/edit route)
|
|
94
|
+
"detail" is NEVER a separate section — it's the /:id route of the list section.
|
|
95
|
+
- Pages: **MANDATORY — INVOKE Skill("ui-components")** for ALL page generation.
|
|
96
|
+
⚠ BLOCKING REQUIREMENT: You MUST call Skill("ui-components") for EVERY page (.tsx).
|
|
97
|
+
NEVER generate .tsx page code directly. NEVER write page content in Agent prompts.
|
|
98
|
+
NEVER use Write tool to create pages without first calling Skill("ui-components").
|
|
99
|
+
The skill loads the full style guide + patterns (entity-card, data-table, dashboard-chart, grid-layout).
|
|
100
|
+
Follow smartstack-frontend.md patterns:
|
|
101
|
+
→ React.lazy() for all page imports (named export wrapping)
|
|
102
|
+
→ `<Suspense fallback={<PageLoader />}>` around all lazy components
|
|
103
|
+
→ Page structure: hooks → useEffect(load) → loading → error → content
|
|
104
|
+
→ CSS variables only: bg-[var(--bg-card)], text-[var(--text-primary)]
|
|
105
|
+
→ DataTable/EntityCard (not raw HTML `<table>`)
|
|
106
|
+
→ If entity has FK Guid fields: generate EntityLookup component in @/components/ui/EntityLookup (see smartstack-frontend.md section 6)
|
|
107
|
+
→ Dashboard pages: generate StatCard + ChartCard locally (see ui-components patterns/dashboard-chart.md)
|
|
108
|
+
- Form pages: Create/Edit forms are full pages with own routes:
|
|
109
|
+
→ EntityCreatePage.tsx with route /{module}/create
|
|
110
|
+
→ EntityEditPage.tsx with route /{module}/:id/edit
|
|
111
|
+
→ Zero modals/popups/drawers/dialogs for forms
|
|
112
|
+
→ Back button with navigate(-1) on every form page
|
|
113
|
+
→ See smartstack-frontend.md section 3b for templates
|
|
114
|
+
- Tabs on detail pages: Tabs must switch content locally:
|
|
115
|
+
→ Tab click handler: setActiveTab(tabKey) only — do not navigate() to another page
|
|
116
|
+
→ Tab content: render inline with {activeTab === 'tabKey' && <TabContent />}
|
|
117
|
+
→ Sub-resource data: fetch via API filtered by parent ID, display in tab panel
|
|
118
|
+
→ Do not use navigate('../leaves?employee=${id}') in tab handler
|
|
119
|
+
→ See smartstack-frontend.md section 3 'Tab Behavior Rules'
|
|
120
|
+
- FK fields: Foreign key Guid fields (e.g., EmployeeId) must use EntityLookup:
|
|
121
|
+
→ Do not render FK fields as `<input>` — users cannot type GUIDs
|
|
122
|
+
→ Do not render FK fields as `<select>` — even with API-loaded options, `<select>` is not acceptable
|
|
123
|
+
→ Only use `<EntityLookup />` from @/components/ui/EntityLookup for searchable selection
|
|
124
|
+
→ Each FK field needs: apiEndpoint, mapOption (display name), search support on backend
|
|
125
|
+
→ Do not use `<select value={formData.departmentId}>`, `<option value={dept.id}>`, `e.target.value` for FK fields
|
|
126
|
+
→ See smartstack-frontend.md section 6 for the full EntityLookup pattern
|
|
127
|
+
<!-- TODO A12: Replace direct i18n generation with MCP scaffold_i18n when B4 is ready -->
|
|
128
|
+
- I18n: Generate 4 JSON files per module namespace (fr, en, it, de)
|
|
129
|
+
→ Follow JSON template from smartstack-frontend.md
|
|
130
|
+
→ Keys: actions, labels, errors, validation, columns, form, messages, empty
|
|
131
|
+
→ All t() calls must use namespace prefix + fallback: t('ns:key', 'Default text')
|
|
132
|
+
→ **Register namespace in i18n config** (critical — POST-CHECK C39 catches this, but fix it now):
|
|
133
|
+
1. Find i18n config: `Glob("src/**/i18n/config.ts")` or `index.ts` or `i18n.ts`
|
|
134
|
+
2. Read the config → find the resources/ns registration pattern
|
|
135
|
+
3. Add the new namespace import + registration for all 4 languages
|
|
136
|
+
4. If config uses dynamic imports: add namespace to the `ns` array
|
|
137
|
+
5. Verify: `grep -q "{module_namespace}" src/**/i18n/config.ts` → must match
|
|
138
|
+
- Permissions: Call MCP generate_permissions for the module permission root (2 segments: {app}.{module}),
|
|
139
|
+
then also call MCP generate_permissions for each section (3 segments: {app}.{module}.{section}).
|
|
140
|
+
- Section routes: Ensure navigation seed data has ComponentKey matching PageRegistry keys.
|
|
141
|
+
ComponentKey convention: `{app_code}.{module_code}.{section_code}` (dot-separated, lowercase).
|
|
142
|
+
DynamicRouter generates the URL paths from seed data Route field.
|
|
143
|
+
- MUST use src/pages/{App}/{Module}/ hierarchy (NOT flat)
|
|
144
|
+
|
|
145
|
+
### Documentation (after frontend pages exist)
|
|
146
|
+
|
|
147
|
+
> **After frontend pages are created, generate module documentation via `/documentation` skill.**
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
Invoke /documentation {module_code} --type user
|
|
151
|
+
|
|
152
|
+
This generates:
|
|
153
|
+
- src/pages/docs/business/{app}/{module}/doc-data.ts (data file)
|
|
154
|
+
- src/pages/docs/business/{app}/{module}/index.tsx (page wrapper)
|
|
155
|
+
- src/i18n/locales/fr/docs-{app}-{module}.json (French doc translations)
|
|
156
|
+
- Updates App.tsx routing for doc page
|
|
157
|
+
- Updates docs-manifest.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Verify DocToggleButton presence in list/detail pages:**
|
|
161
|
+
- Every `*ListPage.tsx` and `*DetailPage.tsx` MUST import and render `DocToggleButton` in their header
|
|
162
|
+
- Import: `import { DocToggleButton } from '@/components/docs/DocToggleButton';`
|
|
163
|
+
- Placement: inside the header actions area (see `smartstack-frontend.md` section 7)
|
|
164
|
+
|
|
165
|
+
### If NOT economy_mode AND multiple entities: Parallel Agents (within layer)
|
|
166
|
+
|
|
167
|
+
> **Protocol:** See `references/parallel-execution.md`
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
IF NOT economy_mode AND entities.length > 1:
|
|
171
|
+
# PHASE A — Parallel: infrastructure frontend (NO page generation)
|
|
172
|
+
# Snipper agents DO NOT have access to the Skill tool, so they CANNOT call /ui-components.
|
|
173
|
+
# Pages MUST be generated by the principal agent in Phase B.
|
|
174
|
+
For each entity, launch in parallel (single message):
|
|
175
|
+
Agent(subagent_type='Snipper', model='opus',
|
|
176
|
+
prompt='Execute Layer 3 INFRASTRUCTURE for {EntityName}:
|
|
177
|
+
**MANDATORY: Read references/smartstack-frontend.md FIRST**
|
|
178
|
+
- API client: MCP scaffold_api_client
|
|
179
|
+
- Routes: MCP scaffold_routes (outputFormat: "componentRegistry", dryRun: false)
|
|
180
|
+
→ MUST generate componentRegistry.generated.ts + navRoutes.generated.ts
|
|
181
|
+
- Verify: componentRegistry.generated.ts has PageRegistry.register() for new pages
|
|
182
|
+
- Verify: main.tsx imports componentRegistry.generated (one-time check)
|
|
183
|
+
- NO manual App.tsx wiring needed — DynamicRouter handles routing
|
|
184
|
+
- I18n: 4 JSON files (fr, en, it, de) + REGISTER namespace in i18n config
|
|
185
|
+
- DO NOT generate any .tsx page files — pages are handled by the principal agent
|
|
186
|
+
- Your task ID is {task_id}. Call TaskUpdate(status: "in_progress") before starting.
|
|
187
|
+
- Call TaskUpdate(status: "completed", metadata: { files_created: [...] }) when done.')
|
|
188
|
+
# Wait for all agents to complete
|
|
189
|
+
|
|
190
|
+
# PHASE B — Sequential: pages via /ui-components (principal agent)
|
|
191
|
+
# Snipper agents cannot call Skill() — only the principal agent can.
|
|
192
|
+
For each entity (sequentially):
|
|
193
|
+
**INVOKE Skill("ui-components")** — pass entity context:
|
|
194
|
+
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
195
|
+
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
196
|
+
- "CSS: Use CSS variables ONLY — bg-[var(--bg-card)], text-[var(--text-primary)]"
|
|
197
|
+
- "Forms: Create/Edit are FULL PAGES with own routes (/create, /:id/edit)"
|
|
198
|
+
- "FK FIELDS: EntityLookup for ALL FK Guid fields"
|
|
199
|
+
- "I18n: ALL text uses t('namespace:key', 'Fallback')"
|
|
200
|
+
Generate form tests: co-located .test.tsx for Create and Edit pages
|
|
201
|
+
|
|
202
|
+
ELSE:
|
|
203
|
+
# Economy mode: Agent principal handles all entities SEQUENTIALLY.
|
|
204
|
+
# MANDATORY: You MUST still call Skill("ui-components") for page generation.
|
|
205
|
+
# economy_mode only disables parallel agents — it does NOT skip /ui-components.
|
|
206
|
+
For each entity (sequentially):
|
|
207
|
+
1. MCP scaffold_api_client
|
|
208
|
+
2. MCP scaffold_routes (outputFormat: 'componentRegistry')
|
|
209
|
+
3. Verify PageRegistry registration (componentRegistry.generated.ts)
|
|
210
|
+
No manual App.tsx wiring needed — DynamicRouter resolves at runtime
|
|
211
|
+
4. **INVOKE Skill("ui-components")** — pass entity context:
|
|
212
|
+
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
213
|
+
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
214
|
+
- "CSS: Use CSS variables ONLY — bg-[var(--bg-card)], text-[var(--text-primary)]"
|
|
215
|
+
- "Forms: Create/Edit are FULL PAGES with own routes (/create, /:id/edit)"
|
|
216
|
+
- "I18n: ALL text uses t('namespace:key', 'Fallback')"
|
|
217
|
+
5. I18n: 4 JSON files (fr, en, it, de) + register namespace in i18n config
|
|
218
|
+
6. Form tests: co-located .test.tsx for Create and Edit pages
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Parallel Agents + TaskCreate Integration
|
|
222
|
+
|
|
223
|
+
When launching agents for multi-entity layers:
|
|
224
|
+
- Each agent receives its task ID and metadata context in the prompt
|
|
225
|
+
- Agent must call TaskUpdate(status: "in_progress") before starting
|
|
226
|
+
- Agent must call TaskUpdate(status: "completed", metadata: { files_created: [...] }) when done
|
|
227
|
+
- Agent principal monitors via TaskList() after all agents complete
|
|
228
|
+
- Agent principal updates activeForm after each entity completion:
|
|
229
|
+
`TaskUpdate(taskId: layer3_task_id, activeForm: "Building {EntityName} frontend (2/5 entities)")`
|
|
230
|
+
|
|
231
|
+
### Frontend Compliance Gate
|
|
232
|
+
|
|
233
|
+
> See `references/smartstack-frontend-compliance.md` section 9 "Compliance Gates" for all 6 required checks:
|
|
234
|
+
> 1. CSS Variables (theme system)
|
|
235
|
+
> 2. Forms as Pages (zero modals/drawers/slide-overs)
|
|
236
|
+
> 3. I18n File Structure (4 languages, separate JSON files)
|
|
237
|
+
> 4. Lazy Loading (React.lazy() — no static imports)
|
|
238
|
+
> 5. useTranslation in Pages (all text translated)
|
|
239
|
+
> 6. SmartStack Components (no raw HTML tables — DataTable/EntityCard required)
|
|
240
|
+
|
|
241
|
+
Do not commit frontend changes until all 6 gates pass.
|
|
242
|
+
|
|
243
|
+
When delegating to `/ui-components` skill, include explicit instructions:
|
|
244
|
+
- "CSS: Use CSS variables ONLY — `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`."
|
|
245
|
+
- "Forms: Create/Edit forms are FULL PAGES with own routes (e.g., `/create`, `/:id/edit`)."
|
|
246
|
+
- "I18n: ALL text must use `t('namespace:key', 'Fallback')`. Generate JSON files in `src/i18n/locales/`."
|
|
247
|
+
|
|
248
|
+
### Frontend Tests Inline
|
|
249
|
+
|
|
250
|
+
> **Tests are scaffolded and run WITHIN Layer 3, not deferred to step-07.**
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
1. Scaffold frontend tests:
|
|
254
|
+
→ For each module with create/edit pages:
|
|
255
|
+
→ Generate EntityCreatePage.test.tsx and EntityEditPage.test.tsx
|
|
256
|
+
→ Co-located next to the page component (NOT in __tests__/ folder)
|
|
257
|
+
→ Cover: rendering, validation, submit, pre-fill, navigation, errors
|
|
258
|
+
→ Tools: Vitest + React Testing Library + @testing-library/user-event
|
|
259
|
+
→ Mock API: vi.mock() or MSW — NEVER real API calls
|
|
260
|
+
|
|
261
|
+
2. Run tests:
|
|
262
|
+
WEB_DIR=$(find . -name "vitest.config.ts" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
|
|
263
|
+
if [ -n "$WEB_DIR" ]; then
|
|
264
|
+
(cd "$WEB_DIR" && npm run test)
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
3. Fix loop (max 3 iterations):
|
|
268
|
+
IF tests fail:
|
|
269
|
+
→ Identify root cause (ALWAYS code bug, not test bug)
|
|
270
|
+
→ Fix production CODE
|
|
271
|
+
→ Re-run tests
|
|
272
|
+
→ Repeat until pass or max 3
|
|
273
|
+
|
|
274
|
+
4. If still failing after 3 iterations: note failures, continue.
|
|
275
|
+
Step-07 "Final Test Sweep" will handle remaining failures.
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Typecheck Gate
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npm run typecheck
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Must pass before commit.
|
|
285
|
+
|
|
286
|
+
TaskUpdate(taskId: layer3_task_id, status: "completed",
|
|
287
|
+
metadata: { build_gate: "pass" })
|
|
288
|
+
|
|
289
|
+
### Layer 3 Commits
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
feat({module}): [frontend] pages, routes, i18n, documentation
|
|
293
|
+
test({module}): frontend form tests
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## NEXT SUB-STEP
|
|
299
|
+
|
|
300
|
+
Load `steps/step-03e-layer4-devdata.md`
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-03e-layer4-devdata
|
|
3
|
+
description: "Layer 4: Development test data (optional)"
|
|
4
|
+
model: opus
|
|
5
|
+
parent_step: steps/step-03-execute.md
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Layer 4 — DevData (optional)
|
|
9
|
+
|
|
10
|
+
### Task Progress
|
|
11
|
+
IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "in_progress")
|
|
12
|
+
IF layer4 task exists: TaskUpdate(taskId: progress_tracker_id,
|
|
13
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 4",
|
|
14
|
+
activeForm: "Executing Layer 4")
|
|
15
|
+
|
|
16
|
+
> **Business test data for development/demo environments.**
|
|
17
|
+
> Skip this layer if no meaningful test data is needed.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
1. Create DevDataSeeder:
|
|
21
|
+
→ Infrastructure/Persistence/Seeding/DevData/{Module}DevDataSeeder.cs
|
|
22
|
+
→ ALL entities MUST include TenantId
|
|
23
|
+
→ Realistic business data for demo purposes
|
|
24
|
+
|
|
25
|
+
2. Build gate:
|
|
26
|
+
dotnet build → MUST PASS
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<!-- TODO A13: Replace with MCP scaffold_extension(type: "devdata") when B5 is ready -->
|
|
30
|
+
|
|
31
|
+
IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "completed",
|
|
32
|
+
metadata: { build_gate: "pass" })
|
|
33
|
+
|
|
34
|
+
### Layer 4 Commit (if applicable)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
feat({module}): [devdata] test data for development
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## SUB-STEPS COMPLETE
|
|
43
|
+
|
|
44
|
+
Return to `steps/step-03-execute.md` for PRD State Update, State Auto-Save, and routing to step-04.
|
|
@@ -16,15 +16,8 @@ next_step: steps/step-05-deep-review.md
|
|
|
16
16
|
|
|
17
17
|
## 0. Task Progress
|
|
18
18
|
|
|
19
|
-
### Progress Tracker Update
|
|
20
|
-
```
|
|
21
|
-
TaskUpdate(taskId: progress_tracker_id,
|
|
22
|
-
description: "Module: {module_code}. Current: step-04 (eXamine)",
|
|
23
|
-
activeForm: "Validating conventions")
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### eXamine Task Lifecycle
|
|
27
19
|
```
|
|
20
|
+
TaskUpdate(taskId: progress_tracker_id, description: "Module: {module_code}. Current: step-04 (eXamine)", activeForm: "Validating conventions")
|
|
28
21
|
TaskUpdate(taskId: examine_task_id, status: "in_progress")
|
|
29
22
|
```
|
|
30
23
|
|
|
@@ -34,64 +27,41 @@ TaskUpdate(taskId: examine_task_id, status: "in_progress")
|
|
|
34
27
|
|
|
35
28
|
```
|
|
36
29
|
Call: mcp__smartstack__validate_conventions
|
|
37
|
-
|
|
38
|
-
Expected: 0 errors
|
|
39
|
-
If errors found:
|
|
40
|
-
→ Fix each error (use appropriate skill/MCP)
|
|
41
|
-
→ Re-validate until 0 errors
|
|
30
|
+
Expected: 0 errors. Fix and re-validate if any found.
|
|
42
31
|
```
|
|
43
32
|
|
|
44
|
-
---
|
|
45
|
-
|
|
46
33
|
## 2. EF Core Migration Check (if needs_migration)
|
|
47
34
|
|
|
48
35
|
```
|
|
49
36
|
Call: mcp__smartstack__check_migrations
|
|
50
|
-
|
|
51
|
-
Verify:
|
|
52
|
-
- Migration exists and is applied
|
|
53
|
-
- No pending model changes
|
|
54
|
-
- ModelSnapshot matches
|
|
37
|
+
Verify: Migration exists, no pending changes, ModelSnapshot matches.
|
|
55
38
|
```
|
|
56
39
|
|
|
57
|
-
---
|
|
58
|
-
|
|
59
40
|
## 3. Frontend Route Validation (if frontend modified)
|
|
60
41
|
|
|
61
42
|
```
|
|
62
43
|
Call: mcp__smartstack__validate_frontend_routes
|
|
63
44
|
|
|
64
45
|
Verify:
|
|
65
|
-
- Routes nested
|
|
66
|
-
- Route paths match controller patterns
|
|
46
|
+
- Routes nested in correct Layout wrapper
|
|
47
|
+
- Route paths match controller patterns, include module segment
|
|
67
48
|
- No orphan routes
|
|
68
|
-
-
|
|
69
|
-
→ Compare frontend route paths in App.tsx against backend NavigationSeedData routes
|
|
70
|
-
→ If backend defines route /app/module/section, frontend must use module/section (relative)
|
|
49
|
+
- Compare frontend routes (componentRegistry.generated.ts or App.tsx) against backend NavigationSeedData routes
|
|
71
50
|
```
|
|
72
51
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
> POST-CHECKs C4, C5, and C6 in `references/post-checks.md` cover this verification (dead navigation links, missing Create/Edit pages, missing test files). Executed in section 6b below.
|
|
76
|
-
>
|
|
77
|
-
> ROOT CAUSE (test-v4-015): Frontend generation created List + Detail pages but SKIPPED Create + Edit pages → white screen / 404.
|
|
78
|
-
|
|
79
|
-
**If ANY check fails → return to step-03 to generate the missing pages, tests, or routes.**
|
|
52
|
+
> **Page completeness:** POST-CHECKs C4, C5, C6 (dead links, missing Create/Edit, missing tests) executed in section 6b.
|
|
53
|
+
> **If ANY check fails → return to step-03.**
|
|
80
54
|
|
|
81
55
|
---
|
|
82
56
|
|
|
83
57
|
## 4. Build Verification
|
|
84
58
|
|
|
85
59
|
```bash
|
|
86
|
-
# Backend
|
|
87
60
|
dotnet clean && dotnet restore && dotnet build
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# Frontend (if applicable)
|
|
91
|
-
npm run typecheck
|
|
61
|
+
npm run typecheck # if applicable
|
|
92
62
|
```
|
|
93
63
|
|
|
94
|
-
Both must pass.
|
|
64
|
+
Both must pass. Classify errors per `references/error-classification.md` (A-F).
|
|
95
65
|
|
|
96
66
|
---
|
|
97
67
|
|
|
@@ -101,30 +71,22 @@ Both must pass. If failure, classify error per `references/error-classification.
|
|
|
101
71
|
INFRA_PROJECT=$(ls src/*Infrastructure*/*.csproj 2>/dev/null | head -1)
|
|
102
72
|
API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)
|
|
103
73
|
|
|
104
|
-
#
|
|
105
|
-
dotnet ef migrations has-pending-model-changes
|
|
106
|
-
--project "$INFRA_PROJECT" \
|
|
107
|
-
--startup-project "$API_PROJECT"
|
|
74
|
+
# Check pending model changes
|
|
75
|
+
dotnet ef migrations has-pending-model-changes --project "$INFRA_PROJECT" --startup-project "$API_PROJECT"
|
|
108
76
|
|
|
109
|
-
#
|
|
77
|
+
# Apply to SQL Server LocalDB
|
|
110
78
|
DB_NAME="SmartStack_Apex_Examine_$(date +%s)"
|
|
111
|
-
|
|
112
|
-
dotnet ef database update \
|
|
113
|
-
--connection "$CONN_STRING" \
|
|
114
|
-
--project "$INFRA_PROJECT" \
|
|
115
|
-
--startup-project "$API_PROJECT"
|
|
79
|
+
dotnet ef database update --connection "Server=(localdb)\\MSSQLLocalDB;Database=$DB_NAME;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=120;" --project "$INFRA_PROJECT" --startup-project "$API_PROJECT"
|
|
116
80
|
|
|
117
|
-
#
|
|
81
|
+
# Run integration tests if present
|
|
118
82
|
INT_TEST_PROJECT=$(ls tests/*Tests.Integration*/*.csproj 2>/dev/null | head -1)
|
|
119
|
-
|
|
120
|
-
dotnet test "$INT_TEST_PROJECT" --no-build --verbosity normal
|
|
121
|
-
fi
|
|
83
|
+
[ -n "$INT_TEST_PROJECT" ] && dotnet test "$INT_TEST_PROJECT" --no-build --verbosity normal
|
|
122
84
|
|
|
123
85
|
# Cleanup
|
|
124
86
|
sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "IF DB_ID('$DB_NAME') IS NOT NULL BEGIN ALTER DATABASE [$DB_NAME] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [$DB_NAME]; END" 2>/dev/null
|
|
125
87
|
```
|
|
126
88
|
|
|
127
|
-
If migration fails
|
|
89
|
+
If migration fails (SQLite-only syntax, type mismatches, missing FK targets), fix the DbContext or migration first.
|
|
128
90
|
|
|
129
91
|
---
|
|
130
92
|
|
|
@@ -132,137 +94,95 @@ If migration fails on SQL Server (common: SQLite-only syntax, column type mismat
|
|
|
132
94
|
|
|
133
95
|
| File | Checks |
|
|
134
96
|
|------|--------|
|
|
135
|
-
| NavigationApplicationSeedData |
|
|
136
|
-
| ApplicationRolesSeedData | 4 roles
|
|
137
|
-
| NavigationModuleSeedData | 4 languages
|
|
138
|
-
| ↳ Section methods
|
|
139
|
-
| ↳ Resource methods
|
|
140
|
-
| Permissions.cs | Static
|
|
141
|
-
| PermissionsSeedData | MCP generate_permissions
|
|
142
|
-
| RolesSeedData | Admin=wildcard(*), Manager=CRU, Contributor=CR, Viewer=R
|
|
143
|
-
| IClientSeedDataProvider | 4 Seed methods
|
|
97
|
+
| NavigationApplicationSeedData | 4 lang translations |
|
|
98
|
+
| ApplicationRolesSeedData | 4 roles, references NavigationApplicationSeedData.ApplicationId |
|
|
99
|
+
| NavigationModuleSeedData | 4 languages, GetModuleEntry + translations |
|
|
100
|
+
| ↳ Section methods | GetSectionEntries + translations, 4 languages, random GUIDs |
|
|
101
|
+
| ↳ Resource methods | GetResourceEntries + translations, 4 languages, random GUIDs |
|
|
102
|
+
| Permissions.cs | Static class with Read/Create/Update/Delete constants, match PermissionsSeedData |
|
|
103
|
+
| PermissionsSeedData | MCP generate_permissions, paths match Permissions.cs |
|
|
104
|
+
| RolesSeedData | Admin=wildcard(*), Manager=CRU, Contributor=CR, Viewer=R |
|
|
105
|
+
| IClientSeedDataProvider | 4 Seed methods, idempotent, SaveChanges per group |
|
|
144
106
|
| DI Registration | `services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()` |
|
|
145
107
|
|
|
146
108
|
---
|
|
147
109
|
|
|
148
110
|
## 6b. POST-CHECKs
|
|
149
111
|
|
|
150
|
-
|
|
151
|
-
> These 3 MCP tools cover ~10 additional checks automatically.
|
|
152
|
-
|
|
153
|
-
Load and execute all checks from `references/post-checks.md` (security + convention + architecture checks).
|
|
112
|
+
**MCP FIRST:** Run `validate_conventions`, `validate_security`, `validate_frontend_routes` (covers ~10 checks).
|
|
154
113
|
|
|
155
|
-
If any
|
|
114
|
+
Execute all checks from `references/post-checks.md`. If any fails, fix in step-03 and re-validate.
|
|
156
115
|
|
|
157
116
|
---
|
|
158
117
|
|
|
159
118
|
## 7. Acceptance Criteria POST-CHECK
|
|
160
119
|
|
|
161
|
-
For each AC
|
|
162
|
-
|
|
120
|
+
For each AC from step-01:
|
|
163
121
|
```
|
|
164
|
-
AC1: {criterion} → PASS / FAIL (evidence
|
|
165
|
-
AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
|
|
122
|
+
AC1: {criterion} → PASS / FAIL (evidence)
|
|
166
123
|
...
|
|
167
124
|
```
|
|
168
|
-
|
|
169
|
-
**All ACs must PASS. If any FAIL, go back to step-03 to fix.**
|
|
125
|
+
**All ACs must PASS. If any FAIL, return to step-03.**
|
|
170
126
|
|
|
171
127
|
---
|
|
172
128
|
|
|
173
129
|
## 8. eXamine Summary
|
|
174
130
|
|
|
175
|
-
```
|
|
176
131
|
**APEX SmartStack - eXamine Complete**
|
|
177
132
|
|
|
178
|
-
| Layer | Status |
|
|
179
|
-
|
|
180
|
-
| Layer 0 — Domain + Infrastructure | PASS / N/A |
|
|
181
|
-
| Layer 1 — Seed Data | PASS / N/A |
|
|
182
|
-
| Layer 2 — Backend | PASS / N/A |
|
|
183
|
-
| Layer 3 — Frontend | PASS / N/A |
|
|
184
|
-
| Layer 4 — DevData | PASS / N/A / SKIPPED |
|
|
185
|
-
|
|
186
|
-
| Category |
|
|
187
|
-
|
|
188
|
-
| MCP conventions |
|
|
189
|
-
| Build
|
|
190
|
-
| EF Core
|
|
191
|
-
|
|
|
192
|
-
| Frontend
|
|
193
|
-
| Security
|
|
194
|
-
| Seed data
|
|
195
|
-
| Code quality |
|
|
196
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
|
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
205
|
-
|
|
|
206
|
-
| Inline tests (Layer 2) | Backend unit + integration tests | PASS / N/A |
|
|
207
|
-
| Inline tests (Layer 3) | Frontend form tests | PASS / N/A |
|
|
208
|
-
| POST-CHECKs | 3 MCP tools + bash checks (security + convention + architecture) | PASS / N/A |
|
|
209
|
-
| Acceptance criteria | AC1..ACn | {X}/{Y} PASS |
|
|
210
|
-
```
|
|
133
|
+
| Layer | Status |
|
|
134
|
+
|-------|--------|
|
|
135
|
+
| Layer 0 — Domain + Infrastructure | PASS / N/A |
|
|
136
|
+
| Layer 1 — Seed Data | PASS / N/A |
|
|
137
|
+
| Layer 2 — Backend | PASS / N/A |
|
|
138
|
+
| Layer 3 — Frontend | PASS / N/A |
|
|
139
|
+
| Layer 4 — DevData | PASS / N/A / SKIPPED |
|
|
140
|
+
|
|
141
|
+
| Category | Status |
|
|
142
|
+
|----------|--------|
|
|
143
|
+
| MCP conventions | PASS (0 errors) |
|
|
144
|
+
| Build (dotnet + npm) | PASS |
|
|
145
|
+
| EF Core (migrations, SQL Server) | PASS / N/A |
|
|
146
|
+
| Integration tests | PASS / N/A |
|
|
147
|
+
| Frontend routes + i18n | PASS / N/A |
|
|
148
|
+
| Security checks | PASS / N/A |
|
|
149
|
+
| Seed data completeness | PASS / N/A |
|
|
150
|
+
| Code quality | PASS / N/A |
|
|
151
|
+
| NavRoute kebab-case | PASS / N/A |
|
|
152
|
+
| DateOnly DTOs | PASS / N/A |
|
|
153
|
+
| I18n registration | PASS / N/A |
|
|
154
|
+
| FluentValidation DI | PASS / N/A |
|
|
155
|
+
| Route/NavRoute conflict | PASS / N/A |
|
|
156
|
+
| Role-permission matrix | PASS / N/A |
|
|
157
|
+
| Navigation translations (4 langs) | PASS / N/A |
|
|
158
|
+
| Inline tests | PASS / N/A |
|
|
159
|
+
| POST-CHECKs | PASS / N/A |
|
|
160
|
+
| Acceptance criteria | {X}/{Y} PASS |
|
|
211
161
|
|
|
212
162
|
---
|
|
213
163
|
|
|
214
|
-
##
|
|
164
|
+
## 8b. Runtime Validation
|
|
215
165
|
|
|
216
|
-
|
|
166
|
+
For runtime validation (if NOT foundation/economy mode): Run `/validate-feature {EntityName}` (OPTIONAL but RECOMMENDED).
|
|
217
167
|
|
|
218
168
|
---
|
|
219
169
|
|
|
220
|
-
##
|
|
221
|
-
|
|
222
|
-
> **Note:** Backend tests (Layer 2) and frontend tests (Layer 3) have already been scaffolded and run inline.
|
|
223
|
-
> Step-07 "Final Test Sweep" handles: security tests, coverage analysis, cross-layer scenarios, and remaining failures.
|
|
170
|
+
## 9. Route to Next Step
|
|
224
171
|
|
|
225
172
|
```
|
|
226
|
-
IF examine_mode
|
|
227
|
-
|
|
228
|
-
→ Then step-06 (resolve) if findings need fixing
|
|
229
|
-
→ Then step-07 (Final Test Sweep) — ALWAYS
|
|
173
|
+
IF examine_mode: Load step-05 → step-06 → step-07
|
|
174
|
+
ELSE: Load step-07-tests.md
|
|
230
175
|
|
|
231
|
-
ELSE:
|
|
232
|
-
→ Load steps/step-07-tests.md — IMMEDIATELY after eXamine completes
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
**RULE:** The APEX workflow is NOT complete until steps 07-08 execute.
|
|
236
|
-
The success criteria require: "Tests: 100% pass, >= 80% coverage" — step-07 verifies coverage and adds security tests.
|
|
237
|
-
|
|
238
|
-
### eXamine Task Lifecycle — Completion
|
|
239
|
-
```
|
|
240
176
|
TaskUpdate(taskId: examine_task_id, status: "completed")
|
|
241
177
|
```
|
|
242
178
|
|
|
243
|
-
**
|
|
179
|
+
**RULE:** APEX requires steps 07-08 (100% tests, >= 80% coverage).
|
|
244
180
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
## 11. PRD Final Reconciliation (delegate mode only)
|
|
248
|
-
|
|
249
|
-
> **After all validation passes**, ensure the PRD file reflects the completed state.
|
|
181
|
+
## 10. PRD Reconciliation (delegate mode)
|
|
250
182
|
|
|
251
183
|
```
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
IF task was executed by apex AND all checks passed:
|
|
257
|
-
Verify task.status == 'completed'
|
|
258
|
-
IF task was NOT in scope (different module):
|
|
259
|
-
Leave unchanged
|
|
260
|
-
|
|
261
|
-
Set prd.updated_at = new Date().toISOString()
|
|
262
|
-
|
|
263
|
-
If ALL module tasks completed:
|
|
264
|
-
Set prd.status = 'completed' (if single module)
|
|
265
|
-
OR leave prd.status = 'in_progress' (if multi-module, other modules remain)
|
|
266
|
-
|
|
267
|
-
Write back to {delegate_prd_path}
|
|
184
|
+
For all tasks in module:
|
|
185
|
+
IF executed AND checks passed: Set task.status = 'completed'
|
|
186
|
+
Set prd.updated_at = now
|
|
187
|
+
If all done: Set prd.status = 'completed' (single) or 'in_progress' (multi)
|
|
268
188
|
```
|