@atlashub/smartstack-cli 4.14.0 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +256 -101
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +1 -0
- package/templates/skills/apex/references/agent-teams-protocol.md +28 -5
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +1 -1
- package/templates/skills/apex/steps/step-02-plan.md +132 -0
- package/templates/skills/apex/steps/step-03-execute.md +71 -0
- package/templates/skills/apex/steps/step-04-examine.md +21 -0
- package/templates/skills/apex/steps/step-05-deep-review.md +11 -0
- package/templates/skills/apex/steps/step-06-resolve.md +24 -5
- package/templates/skills/apex/steps/step-07-tests.md +11 -0
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +36 -4
- package/templates/skills/application/references/nav-fallback-procedure.md +6 -4
- package/templates/skills/application/templates-frontend.md +3 -3
- package/templates/skills/controller/steps/step-01-analyze.md +8 -2
- package/templates/skills/documentation/steps/step-03-validate.md +47 -16
- package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +0 -133
- package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +0 -126
package/package.json
CHANGED
|
@@ -43,13 +43,36 @@ Task:
|
|
|
43
43
|
|
|
44
44
|
## Task List Coordination (T10)
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
### Task Creation (by team lead, BEFORE spawning teammates)
|
|
47
|
+
|
|
48
|
+
Tasks MUST be created upfront for the full layer scope:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
FOR EACH entity in layer:
|
|
52
|
+
TaskCreate(
|
|
53
|
+
subject: "Layer {N}: {Entity} {layer_type}",
|
|
54
|
+
description: "{detailed scope: files, skills, MCP tools}",
|
|
55
|
+
activeForm: "{Building/Creating} {Entity} {layer_type}"
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Task Assignment (by team lead, WHEN spawning)
|
|
60
|
+
|
|
61
|
+
Include task ID and metadata context in teammate prompt:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
"Your assigned task ID is {task_id}.
|
|
65
|
+
Your metadata context: entities={entities}, layer={layer}, tools={tools}.
|
|
66
|
+
Call TaskUpdate(taskId: '{task_id}', status: 'in_progress') before starting.
|
|
67
|
+
Call TaskUpdate(taskId: '{task_id}', status: 'completed', metadata: { files_created: [...] }) after ENTITY_COMPLETE message."
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Task Monitoring (by team lead)
|
|
47
71
|
|
|
48
72
|
```
|
|
49
|
-
1.
|
|
50
|
-
2.
|
|
51
|
-
3.
|
|
52
|
-
4. Lead: TaskList to monitor progress
|
|
73
|
+
1. TaskList() — check progress after each teammate message
|
|
74
|
+
2. All tasks completed → proceed to build gate
|
|
75
|
+
3. Any task stuck → investigate, reassign if needed
|
|
53
76
|
```
|
|
54
77
|
|
|
55
78
|
---
|
|
@@ -56,7 +56,7 @@ const applicationRoutes: ApplicationRouteExtensions = {
|
|
|
56
56
|
'human-resources': [
|
|
57
57
|
// existing routes...
|
|
58
58
|
{ path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
|
|
59
|
-
{ path: '{module_kebab}/{section_kebab}/
|
|
59
|
+
{ path: '{module_kebab}/{section_kebab}/create', element: <Create{EntityName}Page /> },
|
|
60
60
|
{ path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
61
61
|
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },
|
|
62
62
|
|
|
@@ -155,6 +155,138 @@ Write to `{output_dir}/02-plan.md` with the complete plan.
|
|
|
155
155
|
|
|
156
156
|
---
|
|
157
157
|
|
|
158
|
+
## 8. Create Task List (MANDATORY)
|
|
159
|
+
|
|
160
|
+
> **Visibility:** TaskCreate generates the grouped progress UI with checkboxes.
|
|
161
|
+
> This makes APEX execution trackable and predictable for the user.
|
|
162
|
+
|
|
163
|
+
After plan is finalized (auto_mode or user approved):
|
|
164
|
+
|
|
165
|
+
### Task Creation Rules
|
|
166
|
+
|
|
167
|
+
1. Create ONE task per layer (Layer 0-4)
|
|
168
|
+
2. For multi-entity layers (2, 3): create ONE sub-task per entity within the layer
|
|
169
|
+
3. Add build/test gate tasks after each layer
|
|
170
|
+
4. Set dependencies via `addBlockedBy` to enforce layer ordering
|
|
171
|
+
|
|
172
|
+
### Metadata Schema
|
|
173
|
+
|
|
174
|
+
> **All APEX tasks use this metadata schema for context recovery after compression:**
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Schema for ALL APEX tasks
|
|
178
|
+
{
|
|
179
|
+
layer?: number, // 0-4, absent for meta/examine/finding tasks
|
|
180
|
+
apex_step?: string, // "02-plan", "03-execute", etc (meta task only)
|
|
181
|
+
entities?: string[], // entities concerned
|
|
182
|
+
tools?: string[], // MCP tools/skills used
|
|
183
|
+
build_gate?: "pending" | "pass" | "fail",
|
|
184
|
+
files_created?: string[], // updated via TaskUpdate after creation
|
|
185
|
+
module?: string, // module code (meta task only)
|
|
186
|
+
app?: string, // app name (meta task only)
|
|
187
|
+
flags?: object // APEX flags (meta task only)
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Task Template
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
# APEX Progress Tracker (recovery anchor)
|
|
195
|
+
TaskCreate(subject: "APEX Progress",
|
|
196
|
+
description: "Module: {module_code}, App: {app_name}, Entities: {entities list}. Current: step-02 (Plan)",
|
|
197
|
+
activeForm: "Planning execution",
|
|
198
|
+
metadata: {
|
|
199
|
+
apex_step: "02-plan",
|
|
200
|
+
module: "{module_code}",
|
|
201
|
+
app: "{app_name}",
|
|
202
|
+
entities: ["{entity1}", "{entity2}"],
|
|
203
|
+
flags: { auto: {auto_mode}, economy: {economy_mode}, examine: {examine_mode} }
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
# Layer 0 — Domain + Infrastructure
|
|
207
|
+
TaskCreate(subject: "Layer 0: Domain + Infrastructure",
|
|
208
|
+
description: "Entities: {entity1} ({tenantMode}), {entity2} ({tenantMode}).
|
|
209
|
+
Files: Domain/Entities/*.cs, Infrastructure/Persistence/Configs/*.cs, Migration.
|
|
210
|
+
Tools: MCP scaffold_extension (type: entity, configuration). MCP suggest_migration.
|
|
211
|
+
Gate: dotnet build --no-restore. ACs: {relevant ACs}.",
|
|
212
|
+
activeForm: "Creating domain entities",
|
|
213
|
+
metadata: { layer: 0, entities: [...], tools: ["scaffold_extension", "suggest_migration"], build_gate: "pending", files_created: [] })
|
|
214
|
+
|
|
215
|
+
# Layer 1 — Seed Data
|
|
216
|
+
TaskCreate(subject: "Layer 1: Seed Data",
|
|
217
|
+
description: "Navigation, permissions, roles, provider for {module_code}.
|
|
218
|
+
Files: Seeding/Data/{Module}/*.cs, {App}SeedDataProvider.cs.
|
|
219
|
+
Tools: MCP generate_permissions. Ref: core-seed-data.md.
|
|
220
|
+
Gate: dotnet build. ACs: {relevant ACs}.",
|
|
221
|
+
activeForm: "Generating seed data",
|
|
222
|
+
metadata: { layer: 1, entities: [...], tools: ["generate_permissions"], build_gate: "pending", files_created: [] })
|
|
223
|
+
TaskUpdate(taskId: layer1_id, addBlockedBy: [layer0_id])
|
|
224
|
+
|
|
225
|
+
# Layer 2 — Backend (1 task per entity if multi-entity, 1 task if single)
|
|
226
|
+
IF multi-entity:
|
|
227
|
+
FOR EACH entity:
|
|
228
|
+
TaskCreate(subject: "Layer 2: {Entity} backend",
|
|
229
|
+
description: "Service + DTO + Controller + Validator for {Entity}.
|
|
230
|
+
Files: Application/Services/{Entity}Service.cs, Application/DTOs/{Entity}*.cs, Api/Controllers/{Entity}Controller.cs.
|
|
231
|
+
Tools: MCP scaffold_extension, /controller skill. Gate: dotnet build.
|
|
232
|
+
ACs: {relevant ACs for this entity}.",
|
|
233
|
+
activeForm: "Building {Entity} backend",
|
|
234
|
+
metadata: { layer: 2, entities: ["{Entity}"], tools: ["scaffold_extension", "controller"], build_gate: "pending", files_created: [] })
|
|
235
|
+
TaskUpdate(taskId: entity_task_id, addBlockedBy: [layer1_id])
|
|
236
|
+
|
|
237
|
+
# Layer 2 Tests
|
|
238
|
+
TaskCreate(subject: "Layer 2: Backend tests",
|
|
239
|
+
description: "Unit + integration tests for all entities.
|
|
240
|
+
Tools: MCP scaffold_tests (unit + integration). Gate: dotnet test.",
|
|
241
|
+
activeForm: "Running backend tests",
|
|
242
|
+
metadata: { layer: 2, tools: ["scaffold_tests"], build_gate: "pending" })
|
|
243
|
+
|
|
244
|
+
# Layer 3 — Frontend (1 task per entity if multi-entity)
|
|
245
|
+
IF multi-entity:
|
|
246
|
+
FOR EACH entity:
|
|
247
|
+
TaskCreate(subject: "Layer 3: {Entity} frontend",
|
|
248
|
+
description: "API client, pages (List/Detail/Create/Edit), i18n (4 langs), routes for {Entity}.
|
|
249
|
+
Files: src/pages/{App}/{Module}/{Entity}*.tsx, src/i18n/locales/*/{module}.json.
|
|
250
|
+
Tools: MCP scaffold_api_client, MCP scaffold_routes, /ui-components skill.
|
|
251
|
+
Gate: npm run typecheck + 5 compliance gates. ACs: {relevant ACs}.",
|
|
252
|
+
activeForm: "Building {Entity} frontend",
|
|
253
|
+
metadata: { layer: 3, entities: ["{Entity}"], tools: ["scaffold_api_client", "scaffold_routes", "ui-components"], build_gate: "pending", files_created: [] })
|
|
254
|
+
TaskUpdate(taskId: entity_task_id, addBlockedBy: [layer2_tests_id])
|
|
255
|
+
|
|
256
|
+
# Layer 3 Tests + Compliance
|
|
257
|
+
TaskCreate(subject: "Layer 3: Frontend tests + compliance",
|
|
258
|
+
description: "Form tests (Create/Edit .test.tsx), typecheck, 5 compliance gates.
|
|
259
|
+
Tools: Vitest + React Testing Library. Gate: npm run test + typecheck.",
|
|
260
|
+
activeForm: "Running frontend tests",
|
|
261
|
+
metadata: { layer: 3, tools: ["vitest"], build_gate: "pending" })
|
|
262
|
+
|
|
263
|
+
# Layer 4 (if applicable)
|
|
264
|
+
IF NOT foundation_mode AND devdata needed:
|
|
265
|
+
TaskCreate(subject: "Layer 4: DevData",
|
|
266
|
+
description: "Development test data seeder.
|
|
267
|
+
Files: Infrastructure/Persistence/Seeding/DevData/{Module}DevDataSeeder.cs.
|
|
268
|
+
Gate: dotnet build.",
|
|
269
|
+
activeForm: "Creating dev data",
|
|
270
|
+
metadata: { layer: 4, tools: [], build_gate: "pending", files_created: [] })
|
|
271
|
+
|
|
272
|
+
# Post-execution
|
|
273
|
+
TaskCreate(subject: "eXamine: Validation + POST-CHECKs",
|
|
274
|
+
description: "MCP validate_conventions, build, 50 POST-CHECKs, acceptance criteria.
|
|
275
|
+
Tools: MCP validate_conventions, validate_security, validate_frontend_routes.",
|
|
276
|
+
activeForm: "Validating conventions",
|
|
277
|
+
metadata: { tools: ["validate_conventions", "validate_security", "validate_frontend_routes"] })
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Economy Mode
|
|
281
|
+
|
|
282
|
+
IF economy_mode: Create the SAME tasks (for visibility), but no Agent Teams — agent principal executes sequentially.
|
|
283
|
+
|
|
284
|
+
### Delegate Mode
|
|
285
|
+
|
|
286
|
+
IF delegate_mode: Create tasks from PRD task list, mapped to layers.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
158
290
|
## NEXT STEP
|
|
159
291
|
|
|
160
292
|
Load `steps/step-03-execute.md`
|
|
@@ -47,6 +47,12 @@ Execute ALL layers normally (Layer 0 → Layer 1 → Layer 2 → Layer 3 → Lay
|
|
|
47
47
|
|
|
48
48
|
## Layer 0 — Domain + Infrastructure (sequential, agent principal)
|
|
49
49
|
|
|
50
|
+
### Task Progress
|
|
51
|
+
TaskUpdate(taskId: layer0_task_id, status: "in_progress")
|
|
52
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
53
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 0",
|
|
54
|
+
activeForm: "Executing Layer 0")
|
|
55
|
+
|
|
50
56
|
### Domain Entities
|
|
51
57
|
|
|
52
58
|
```
|
|
@@ -108,6 +114,9 @@ dotnet build
|
|
|
108
114
|
|
|
109
115
|
**MUST PASS before Layer 1. If NuGet error, run `dotnet restore` first. If file lock (MSB3021), use `--output /tmp/{project}_build`.**
|
|
110
116
|
|
|
117
|
+
TaskUpdate(taskId: layer0_task_id, status: "completed",
|
|
118
|
+
metadata: { build_gate: "pass" })
|
|
119
|
+
|
|
111
120
|
### Layer 0 Commit
|
|
112
121
|
|
|
113
122
|
```
|
|
@@ -118,6 +127,12 @@ feat({module}): [domain+infra] {short description}
|
|
|
118
127
|
|
|
119
128
|
## Layer 1 — Seed Data (DEDICATED LAYER — sequential, agent principal)
|
|
120
129
|
|
|
130
|
+
### Task Progress
|
|
131
|
+
TaskUpdate(taskId: layer1_task_id, status: "in_progress")
|
|
132
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
133
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 1",
|
|
134
|
+
activeForm: "Executing Layer 1")
|
|
135
|
+
|
|
121
136
|
> **This layer is DEDICATED and MANDATORY.** Seed data makes modules visible in the UI.
|
|
122
137
|
> Without seed data, the module exists in code but is invisible to users.
|
|
123
138
|
> Reference: `references/core-seed-data.md` (loaded above) for complete C# templates.
|
|
@@ -181,6 +196,9 @@ dotnet build
|
|
|
181
196
|
|
|
182
197
|
**MUST PASS before Layer 2.**
|
|
183
198
|
|
|
199
|
+
TaskUpdate(taskId: layer1_task_id, status: "completed",
|
|
200
|
+
metadata: { build_gate: "pass" })
|
|
201
|
+
|
|
184
202
|
### Layer 1 Commit
|
|
185
203
|
|
|
186
204
|
```
|
|
@@ -191,6 +209,12 @@ feat({module}): [seed] navigation, permissions, roles
|
|
|
191
209
|
|
|
192
210
|
## Layer 2 — Backend (Services + Controllers)
|
|
193
211
|
|
|
212
|
+
### Task Progress
|
|
213
|
+
TaskUpdate(taskId: layer2_task_id, status: "in_progress")
|
|
214
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
215
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 2",
|
|
216
|
+
activeForm: "Executing Layer 2")
|
|
217
|
+
|
|
194
218
|
> **Layer 2 rules** are in `references/smartstack-layers.md` (already in context from step-02):
|
|
195
219
|
> - NavRoute and permission kebab-case (Layer 2 - API section)
|
|
196
220
|
> - Controller route attributes (FORBIDDEN: [Route] alongside [NavRoute])
|
|
@@ -238,6 +262,18 @@ Wait for all teammates to report completion.
|
|
|
238
262
|
shutdown_request → shutdown_response → TeamDelete("apex-layer2")
|
|
239
263
|
```
|
|
240
264
|
|
|
265
|
+
### Agent Teams + TaskCreate Integration
|
|
266
|
+
|
|
267
|
+
When spawning teammates for multi-entity layers:
|
|
268
|
+
- Each teammate receives its task ID and metadata context in the prompt
|
|
269
|
+
- Teammate MUST call TaskUpdate(status: "in_progress") before starting
|
|
270
|
+
- Teammate MUST call TaskUpdate(status: "completed", metadata: { files_created: [...] }) after SendMessage("ENTITY_COMPLETE")
|
|
271
|
+
- Lead monitors via TaskList() between teammate completions
|
|
272
|
+
- Lead updates activeForm after each entity completion:
|
|
273
|
+
`TaskUpdate(taskId: layer2_task_id, activeForm: "Building {EntityName} backend (2/5 entities)")`
|
|
274
|
+
- Lead updates metadata after each MCP scaffold:
|
|
275
|
+
`TaskUpdate(taskId: layer_task_id, metadata: { files_created: [...previous, "new_file.cs"] })`
|
|
276
|
+
|
|
241
277
|
### Post-Layer 2 Build Gate
|
|
242
278
|
|
|
243
279
|
```bash
|
|
@@ -246,6 +282,11 @@ dotnet build
|
|
|
246
282
|
|
|
247
283
|
**MUST PASS before backend tests.**
|
|
248
284
|
|
|
285
|
+
TaskUpdate(taskId: layer2_task_id, status: "completed",
|
|
286
|
+
metadata: { build_gate: "pass" })
|
|
287
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
288
|
+
activeForm: "Running build gate (Layer 2)")
|
|
289
|
+
|
|
249
290
|
### Backend Tests Inline
|
|
250
291
|
|
|
251
292
|
> **Tests are scaffolded and run WITHIN Layer 2, not deferred to step-07.**
|
|
@@ -282,6 +323,12 @@ test({module}): backend unit and integration tests
|
|
|
282
323
|
|
|
283
324
|
## Layer 3 — Frontend (Pages + I18n + Documentation)
|
|
284
325
|
|
|
326
|
+
### Task Progress
|
|
327
|
+
TaskUpdate(taskId: layer3_task_id, status: "in_progress")
|
|
328
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
329
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 3",
|
|
330
|
+
activeForm: "Executing Layer 3")
|
|
331
|
+
|
|
285
332
|
> **Frontend patterns** are in `references/smartstack-frontend.md` (already loaded above):
|
|
286
333
|
> - API client generation (MCP scaffold_api_client)
|
|
287
334
|
> - Route scaffolding (MCP scaffold_routes) — section 1 + 3b
|
|
@@ -399,6 +446,18 @@ Wait for all teammates to report completion.
|
|
|
399
446
|
shutdown_request → shutdown_response → TeamDelete("apex-layer3")
|
|
400
447
|
```
|
|
401
448
|
|
|
449
|
+
### Agent Teams + TaskCreate Integration
|
|
450
|
+
|
|
451
|
+
When spawning teammates for multi-entity layers:
|
|
452
|
+
- Each teammate receives its task ID and metadata context in the prompt
|
|
453
|
+
- Teammate MUST call TaskUpdate(status: "in_progress") before starting
|
|
454
|
+
- Teammate MUST call TaskUpdate(status: "completed", metadata: { files_created: [...] }) after SendMessage("ENTITY_COMPLETE")
|
|
455
|
+
- Lead monitors via TaskList() between teammate completions
|
|
456
|
+
- Lead updates activeForm after each entity completion:
|
|
457
|
+
`TaskUpdate(taskId: layer3_task_id, activeForm: "Building {EntityName} frontend (2/5 entities)")`
|
|
458
|
+
- Lead updates metadata after each MCP scaffold:
|
|
459
|
+
`TaskUpdate(taskId: layer_task_id, metadata: { files_created: [...previous, "NewPage.tsx"] })`
|
|
460
|
+
|
|
402
461
|
### FRONTEND COMPLIANCE GATE (MANDATORY before commit)
|
|
403
462
|
|
|
404
463
|
> **Reference:** See `references/smartstack-frontend.md` section 9 "Compliance Gates" for all 5 mandatory checks:
|
|
@@ -453,6 +512,9 @@ npm run typecheck
|
|
|
453
512
|
|
|
454
513
|
**MUST PASS before commit.**
|
|
455
514
|
|
|
515
|
+
TaskUpdate(taskId: layer3_task_id, status: "completed",
|
|
516
|
+
metadata: { build_gate: "pass" })
|
|
517
|
+
|
|
456
518
|
### Layer 3 Commits
|
|
457
519
|
|
|
458
520
|
```
|
|
@@ -464,6 +526,12 @@ test({module}): frontend form tests
|
|
|
464
526
|
|
|
465
527
|
## Layer 4 — DevData (optional)
|
|
466
528
|
|
|
529
|
+
### Task Progress
|
|
530
|
+
IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "in_progress")
|
|
531
|
+
IF layer4 task exists: TaskUpdate(taskId: progress_tracker_id,
|
|
532
|
+
description: "Module: {module_code}. Current: step-03 (Execute), Layer 4",
|
|
533
|
+
activeForm: "Executing Layer 4")
|
|
534
|
+
|
|
467
535
|
> **Business test data for development/demo environments.**
|
|
468
536
|
> Skip this layer if no meaningful test data is needed.
|
|
469
537
|
|
|
@@ -477,6 +545,9 @@ test({module}): frontend form tests
|
|
|
477
545
|
dotnet build → MUST PASS
|
|
478
546
|
```
|
|
479
547
|
|
|
548
|
+
IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "completed",
|
|
549
|
+
metadata: { build_gate: "pass" })
|
|
550
|
+
|
|
480
551
|
### Layer 4 Commit (if applicable)
|
|
481
552
|
|
|
482
553
|
```
|
|
@@ -14,6 +14,22 @@ next_step: steps/step-05-deep-review.md
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## 0. Task Progress
|
|
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
|
+
```
|
|
28
|
+
TaskUpdate(taskId: examine_task_id, status: "in_progress")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
17
33
|
## 1. MCP Convention Validation
|
|
18
34
|
|
|
19
35
|
```
|
|
@@ -284,6 +300,11 @@ ELSE:
|
|
|
284
300
|
**BLOCKING RULE:** The APEX workflow is NOT complete until steps 07-08 execute.
|
|
285
301
|
The success criteria require: "Tests: 100% pass, >= 80% coverage" — step-07 verifies coverage and adds security tests.
|
|
286
302
|
|
|
303
|
+
### eXamine Task Lifecycle — Completion
|
|
304
|
+
```
|
|
305
|
+
TaskUpdate(taskId: examine_task_id, status: "completed")
|
|
306
|
+
```
|
|
307
|
+
|
|
287
308
|
**NEXT ACTION:** Load `steps/step-07-tests.md` now.
|
|
288
309
|
|
|
289
310
|
---
|
|
@@ -12,6 +12,17 @@ next_step: steps/step-06-resolve.md
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## 0. Task Progress
|
|
16
|
+
|
|
17
|
+
### Progress Tracker Update
|
|
18
|
+
```
|
|
19
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
20
|
+
description: "Module: {module_code}. Current: step-05 (Deep Review)",
|
|
21
|
+
activeForm: "Reviewing code")
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
15
26
|
## 1. Gather Changed Files
|
|
16
27
|
|
|
17
28
|
```bash
|
|
@@ -12,15 +12,34 @@ next_step: steps/step-07-tests.md
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## 0. Task Progress
|
|
16
|
+
|
|
17
|
+
### Progress Tracker Update
|
|
18
|
+
```
|
|
19
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
20
|
+
description: "Module: {module_code}. Current: step-06 (Resolve)",
|
|
21
|
+
activeForm: "Fixing findings")
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 1. Create Finding Tasks
|
|
16
27
|
|
|
17
28
|
For each BLOCKING finding from step-05:
|
|
18
29
|
|
|
19
30
|
```
|
|
20
|
-
|
|
21
|
-
File: {path}
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
TaskCreate(subject: "Fix: {F01} — {short description}",
|
|
32
|
+
description: "File: {path}:{line}\nIssue: {description}\nFix: {approach}",
|
|
33
|
+
activeForm: "Fixing {F01}",
|
|
34
|
+
metadata: { finding_id: "F01", severity: "BLOCKING", source_file: "{path}" })
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then process each finding by updating task status:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
TaskUpdate(taskId: finding_task_id, status: "in_progress")
|
|
41
|
+
... apply fix ...
|
|
42
|
+
TaskUpdate(taskId: finding_task_id, status: "completed")
|
|
24
43
|
```
|
|
25
44
|
|
|
26
45
|
**Fixing rules:**
|
|
@@ -16,6 +16,17 @@ next_step: steps/step-08-run-tests.md
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## Task Progress
|
|
20
|
+
|
|
21
|
+
### Progress Tracker Update
|
|
22
|
+
```
|
|
23
|
+
TaskUpdate(taskId: progress_tracker_id,
|
|
24
|
+
description: "Module: {module_code}. Current: step-07 (Final Test Sweep)",
|
|
25
|
+
activeForm: "Running test sweep")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
19
30
|
## 0. Ensure Test Infrastructure Exists
|
|
20
31
|
|
|
21
32
|
### 0a. Frontend Test Tooling (if frontend was generated)
|
|
@@ -55,10 +55,14 @@ Read App.tsx and detect which pattern is used:
|
|
|
55
55
|
const applicationRoutes: ApplicationRouteExtensions = {
|
|
56
56
|
'human-resources': [
|
|
57
57
|
// existing routes...
|
|
58
|
-
{ path: '{module_kebab}', element: <{EntityName}ListPage /> },
|
|
59
|
-
{ path: '{module_kebab}/
|
|
60
|
-
{ path: '{module_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
61
|
-
{ path: '{module_kebab}/:id/edit', element: <Create{EntityName}Page /> },
|
|
58
|
+
{ path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
|
|
59
|
+
{ path: '{module_kebab}/{section_kebab}/create', element: <Create{EntityName}Page /> },
|
|
60
|
+
{ path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
61
|
+
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },
|
|
62
|
+
|
|
63
|
+
// Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
|
|
64
|
+
{ path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
|
|
65
|
+
{ path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
|
|
62
66
|
],
|
|
63
67
|
};
|
|
64
68
|
```
|
|
@@ -137,6 +141,34 @@ If `appWiring.issues` is not empty, fix the wiring before proceeding.
|
|
|
137
141
|
|
|
138
142
|
---
|
|
139
143
|
|
|
144
|
+
## Step 4e: Parent Redirect Routes (MANDATORY)
|
|
145
|
+
|
|
146
|
+
**CRITICAL:** Without parent redirects, navigating to an application or module URL (e.g., `/human-resources` or `/human-resources/employees`) will cause a redirect to `/login` because no route matches.
|
|
147
|
+
|
|
148
|
+
For each application, you MUST add:
|
|
149
|
+
|
|
150
|
+
1. **Application root redirect** — redirects `/{application}` to the first module/section:
|
|
151
|
+
```tsx
|
|
152
|
+
{ path: '', element: <Navigate to="{first_module}/{first_section}" replace /> }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
2. **Module redirect** (if modules have sections) — redirects `/{application}/{module}` to first section:
|
|
156
|
+
```tsx
|
|
157
|
+
{ path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Example:** For NavRoutes `human-resources.employees.management` and `human-resources.employees.departments`:
|
|
161
|
+
```tsx
|
|
162
|
+
{ path: 'employees', element: <Navigate to="employees/management" replace /> },
|
|
163
|
+
{ path: '', element: <Navigate to="employees/management" replace /> },
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.
|
|
167
|
+
|
|
168
|
+
> Note: `scaffold_routes` with `outputFormat: "applicationRoutes"` generates these redirects automatically.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
140
172
|
## Forbidden Patterns (BOTH patterns)
|
|
141
173
|
|
|
142
174
|
- Adding application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is ONLY for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
|
|
@@ -53,13 +53,15 @@ Read the parent SeedData class and find the GUID matching `{parent_path}`.
|
|
|
53
53
|
Generate a random GUID for the new navigation entity:
|
|
54
54
|
|
|
55
55
|
```csharp
|
|
56
|
-
//
|
|
57
|
-
|
|
56
|
+
// IMPORTANT: Use a stable GUID. Never change after the first seed.
|
|
57
|
+
// Generate once with Guid.NewGuid(), then hardcode the result as a static field.
|
|
58
|
+
public static readonly Guid MyEntityId = Guid.Parse("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
58
59
|
```
|
|
59
60
|
|
|
60
61
|
**Rules:**
|
|
61
|
-
-
|
|
62
|
-
-
|
|
62
|
+
- Generate a GUID once with `Guid.NewGuid()`, then **hardcode it as a static readonly field**
|
|
63
|
+
- NEVER call `Guid.NewGuid()` at runtime in seed data — each migration run would generate different IDs, breaking foreign keys
|
|
64
|
+
- Idempotence is handled by EF Core HasData matching on the `Id` primary key
|
|
63
65
|
- Store result as `{navigation_guid}`
|
|
64
66
|
|
|
65
67
|
## F4. Write Navigation Entity Seed
|
|
@@ -67,7 +67,7 @@ export function $MODULE_PASCALPage() {
|
|
|
67
67
|
<$MODULE_PASCALListView
|
|
68
68
|
title={t('$module:title')}
|
|
69
69
|
subtitle={t('$module:subtitle')}
|
|
70
|
-
createPath="
|
|
70
|
+
createPath="create"
|
|
71
71
|
/>
|
|
72
72
|
);
|
|
73
73
|
}
|
|
@@ -530,7 +530,7 @@ const applicationRoutes: ApplicationRouteExtensions = {
|
|
|
530
530
|
'$APPLICATION_KEBAB': [
|
|
531
531
|
// ... existing routes ...
|
|
532
532
|
{ path: '$MODULE_KEBAB', element: <$MODULE_PASCALPage /> },
|
|
533
|
-
{ path: '$MODULE_KEBAB/
|
|
533
|
+
{ path: '$MODULE_KEBAB/create', element: <Create$MODULE_PASCALPage /> },
|
|
534
534
|
{ path: '$MODULE_KEBAB/:id', element: <$MODULE_PASCALDetailPage /> },
|
|
535
535
|
{ path: '$MODULE_KEBAB/:id/edit', element: <Create$MODULE_PASCALPage /> },
|
|
536
536
|
],
|
|
@@ -580,7 +580,7 @@ import { Create$MODULE_PASCALPage } from '@/pages/$APPLICATION/$MODULE/Create$MO
|
|
|
580
580
|
<Route path="$MODULE_KEBAB">
|
|
581
581
|
<Route index element={<Navigate to="." replace />} />
|
|
582
582
|
<Route index element={<$MODULE_PASCALPage />} />
|
|
583
|
-
<Route path="
|
|
583
|
+
<Route path="create" element={<Create$MODULE_PASCALPage />} />
|
|
584
584
|
<Route path=":id" element={<$MODULE_PASCALDetailPage />} />
|
|
585
585
|
<Route path=":id/edit" element={<Create$MODULE_PASCALPage />} />
|
|
586
586
|
</Route>
|
|
@@ -20,9 +20,15 @@ Gather all context needed to generate the controller. Find the Entity, check DbC
|
|
|
20
20
|
|
|
21
21
|
**Search for entity file:**
|
|
22
22
|
|
|
23
|
+
1. Read `.smartstack/config.json` → use `paths.domain` if available
|
|
24
|
+
2. Otherwise, use wildcard on project name:
|
|
23
25
|
```
|
|
24
|
-
Glob: "src
|
|
25
|
-
Glob: "src
|
|
26
|
+
Glob: "src/*Domain*/**/{entity}.cs"
|
|
27
|
+
Glob: "src/*Domain*/**/{entity}s.cs"
|
|
28
|
+
```
|
|
29
|
+
3. Fallback (if no match):
|
|
30
|
+
```
|
|
31
|
+
Glob: "src/**/{entity}.cs" with ignore "**/obj/**,**/bin/**,**/Tests/**"
|
|
26
32
|
```
|
|
27
33
|
|
|
28
34
|
**Extract from Entity:**
|