@atlashub/smartstack-cli 3.24.0 → 3.26.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.
Files changed (33) hide show
  1. package/dist/index.js +5 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +51 -14
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/skills/apex/SKILL.md +26 -5
  7. package/templates/skills/apex/_shared.md +3 -3
  8. package/templates/skills/apex/references/agent-teams-protocol.md +8 -8
  9. package/templates/skills/apex/references/challenge-questions.md +165 -0
  10. package/templates/skills/apex/references/post-checks.md +457 -0
  11. package/templates/skills/apex/references/smartstack-api.md +234 -14
  12. package/templates/skills/apex/references/smartstack-frontend.md +20 -0
  13. package/templates/skills/apex/references/smartstack-layers.md +16 -4
  14. package/templates/skills/apex/steps/step-00-init.md +84 -56
  15. package/templates/skills/apex/steps/step-01-analyze.md +73 -87
  16. package/templates/skills/apex/steps/step-03-execute.md +6 -4
  17. package/templates/skills/apex/steps/step-04-examine.md +198 -0
  18. package/templates/skills/apex/steps/{step-05-examine.md → step-05-deep-review.md} +6 -6
  19. package/templates/skills/apex/steps/step-06-resolve.md +2 -2
  20. package/templates/skills/business-analyse/SKILL.md +28 -0
  21. package/templates/skills/business-analyse/references/agent-module-prompt.md +255 -0
  22. package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +26 -10
  23. package/templates/skills/business-analyse/references/team-orchestration.md +437 -0
  24. package/templates/skills/business-analyse/steps/step-02-decomposition.md +31 -4
  25. package/templates/skills/business-analyse/steps/step-03a1-setup.md +21 -0
  26. package/templates/skills/business-analyse/steps/step-03d-validate.md +84 -0
  27. package/templates/skills/efcore/steps/migration/step-02-create.md +14 -1
  28. package/templates/skills/ralph-loop/references/category-rules.md +26 -2
  29. package/templates/skills/ralph-loop/references/compact-loop.md +1 -1
  30. package/templates/skills/ralph-loop/references/core-seed-data.md +45 -10
  31. package/templates/skills/ralph-loop/steps/step-02-execute.md +128 -1
  32. package/templates/skills/validate-feature/steps/step-01-compile.md +4 -1
  33. package/templates/skills/apex/steps/step-04-validate.md +0 -448
@@ -1,448 +0,0 @@
1
- ---
2
- name: step-04-validate
3
- description: MCP validation, build verification, seed data check, acceptance criteria
4
- model: opus
5
- prev_step: steps/step-03-execute.md
6
- next_step: steps/step-05-examine.md
7
- ---
8
-
9
- # Step 4: Validate
10
-
11
- **Goal:** Verify everything works. MCP conventions, build, seed data, acceptance criteria.
12
-
13
- ---
14
-
15
- ## 1. MCP Convention Validation
16
-
17
- ```
18
- Call: mcp__smartstack__validate_conventions
19
-
20
- Expected: 0 errors
21
- If errors found:
22
- → Fix each error (use appropriate skill/MCP)
23
- → Re-validate until 0 errors
24
- ```
25
-
26
- ---
27
-
28
- ## 2. EF Core Migration Check (if needs_migration)
29
-
30
- ```
31
- Call: mcp__smartstack__check_migrations
32
-
33
- Verify:
34
- - Migration exists and is applied
35
- - No pending model changes
36
- - ModelSnapshot matches
37
- ```
38
-
39
- ---
40
-
41
- ## 3. Frontend Route Validation (if frontend modified)
42
-
43
- ```
44
- Call: mcp__smartstack__validate_frontend_routes
45
-
46
- Verify:
47
- - Routes nested inside correct Layout wrapper
48
- - Route paths match controller patterns
49
- - No orphan routes
50
- ```
51
-
52
- ---
53
-
54
- ## 4. Build Verification
55
-
56
- ```bash
57
- # Backend
58
- dotnet clean && dotnet restore && dotnet build
59
-
60
- # Frontend (if applicable)
61
- npm run typecheck
62
- ```
63
-
64
- **BLOCKING:** Both must pass. If failure, fix and retry.
65
-
66
- ---
67
-
68
- ## 5. Database & Migration Validation (if needs_migration)
69
-
70
- ### 5a. Pending Model Changes Check
71
-
72
- ```bash
73
- INFRA_PROJECT=$(ls src/*Infrastructure*/*.csproj 2>/dev/null | head -1)
74
- API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)
75
-
76
- dotnet ef migrations has-pending-model-changes \
77
- --project "$INFRA_PROJECT" \
78
- --startup-project "$API_PROJECT"
79
- ```
80
-
81
- **BLOCKING** if pending changes detected → migration is missing.
82
-
83
- ### 5b. Migration Application Test (SQL Server LocalDB)
84
-
85
- ```bash
86
- DB_NAME="SmartStack_Apex_Validate_$(date +%s)"
87
- CONN_STRING="Server=(localdb)\\MSSQLLocalDB;Database=$DB_NAME;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=120;"
88
-
89
- dotnet ef database update \
90
- --connection "$CONN_STRING" \
91
- --project "$INFRA_PROJECT" \
92
- --startup-project "$API_PROJECT"
93
- ```
94
-
95
- **BLOCKING** if migration fails on SQL Server. Common issues:
96
- - SQLite-only syntax in migrations (fix: regenerate migration)
97
- - Column type mismatches (fix: update EF configuration)
98
- - Missing foreign key targets (fix: reorder migrations)
99
-
100
- ### 5c. Integration Tests on Real SQL Server
101
-
102
- ```bash
103
- # Integration tests use DatabaseFixture → real SQL Server LocalDB
104
- # This validates: LINQ→SQL, multi-tenant isolation, soft delete, EF configs
105
- INT_TEST_PROJECT=$(ls tests/*Tests.Integration*/*.csproj 2>/dev/null | head -1)
106
- if [ -n "$INT_TEST_PROJECT" ]; then
107
- dotnet test "$INT_TEST_PROJECT" --no-build --verbosity normal
108
- fi
109
- ```
110
-
111
- Tests running against SQL Server catch issues that SQLite misses:
112
- - Case sensitivity in string comparisons
113
- - Date/time function differences
114
- - IDENTITY vs AUTOINCREMENT behavior
115
- - Global query filter translation to T-SQL
116
-
117
- ### 5d. Cleanup
118
-
119
- ```bash
120
- 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
121
- ```
122
-
123
- ---
124
-
125
- ## 6. Seed Data Completeness Check (if needs_seed_data)
126
-
127
- | File | Checks |
128
- |------|--------|
129
- | NavigationApplicationSeedData | MUST be first, deterministic GUID, 4 lang translations |
130
- | NavigationModuleSeedData | Deterministic GUIDs (SHA256), 4 languages, GetModuleEntry + GetTranslationEntries |
131
- | PermissionsSeedData | MCP generate_permissions used, paths match Permissions.cs, wildcard + CRUD |
132
- | RolesSeedData | Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R |
133
- | IClientSeedDataProvider | 3 Seed methods, idempotent, factory methods, SaveChanges per group |
134
- | DI Registration | `services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()` |
135
-
136
- ---
137
-
138
- ## 6b. BLOCKING POST-CHECKs (bash verification on real files)
139
-
140
- > These checks run on the actual generated files. Model-interpreted checks are unreliable.
141
-
142
- ### POST-CHECK 1: Navigation routes must be full paths starting with /
143
-
144
- ```bash
145
- # Find all seed data files and check route values
146
- SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
147
- if [ -n "$SEED_FILES" ]; then
148
- # Check for short routes (no leading /) in Create() calls for navigation entities
149
- BAD_ROUTES=$(grep -Pn 'NavigationApplication\.Create\(|NavigationModule\.Create\(|NavigationSection\.Create\(|NavigationResource\.Create\(' $SEED_FILES | grep -v '"/[a-z]')
150
- if [ -n "$BAD_ROUTES" ]; then
151
- echo "BLOCKING: Navigation routes must be full paths starting with /"
152
- echo "$BAD_ROUTES"
153
- echo "Expected: \"/business/human-resources\" NOT \"humanresources\""
154
- exit 1
155
- fi
156
- fi
157
- ```
158
-
159
- ### POST-CHECK 2: All services must filter by TenantId (OWASP A01)
160
-
161
- ```bash
162
- # Find all service implementation files
163
- SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
164
- if [ -n "$SERVICE_FILES" ]; then
165
- # Check each service file has TenantId reference (either _currentUser.TenantId or TenantId filter)
166
- for f in $SERVICE_FILES; do
167
- if ! grep -q "TenantId" "$f"; then
168
- echo "BLOCKING (OWASP A01): Service missing TenantId filter: $f"
169
- echo "Every service query MUST filter by _currentUser.TenantId"
170
- exit 1
171
- fi
172
- if grep -q "Guid.Empty" "$f"; then
173
- echo "BLOCKING (OWASP A01): Service uses Guid.Empty instead of _currentUser.TenantId: $f"
174
- exit 1
175
- fi
176
- done
177
- fi
178
- ```
179
-
180
- ### POST-CHECK 3: Controllers must use [RequirePermission], not just [Authorize]
181
-
182
- ```bash
183
- # Find all controller files
184
- CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
185
- if [ -n "$CTRL_FILES" ]; then
186
- for f in $CTRL_FILES; do
187
- # Check controller has at least one RequirePermission attribute
188
- if grep -q "\[Authorize\]" "$f" && ! grep -q "\[RequirePermission" "$f"; then
189
- echo "WARNING: Controller uses [Authorize] without [RequirePermission]: $f"
190
- echo "Use [RequirePermission(Permissions.{Module}.{Action})] on each endpoint"
191
- fi
192
- done
193
- fi
194
- ```
195
-
196
- ### POST-CHECK 4: Seed data must not use Guid.NewGuid()
197
-
198
- ```bash
199
- SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
200
- if [ -n "$SEED_FILES" ]; then
201
- BAD_GUIDS=$(grep -n "Guid.NewGuid()" $SEED_FILES 2>/dev/null)
202
- if [ -n "$BAD_GUIDS" ]; then
203
- echo "BLOCKING: Seed data must use deterministic GUIDs (SHA256), not Guid.NewGuid()"
204
- echo "$BAD_GUIDS"
205
- exit 1
206
- fi
207
- fi
208
- ```
209
-
210
- ### POST-CHECK 5: Services must inject ICurrentUser
211
-
212
- ```bash
213
- SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
214
- if [ -n "$SERVICE_FILES" ]; then
215
- for f in $SERVICE_FILES; do
216
- if ! grep -q "ICurrentUser" "$f"; then
217
- echo "BLOCKING: Service missing ICurrentUser injection: $f"
218
- echo "All services MUST inject ICurrentUser for tenant isolation"
219
- exit 1
220
- fi
221
- done
222
- fi
223
- ```
224
-
225
- ### POST-CHECK 6: Translation files must exist for all 4 languages (if frontend)
226
-
227
- ```bash
228
- # Find all i18n namespaces used in tsx files
229
- TSX_FILES=$(find src/pages/ -name "*.tsx" 2>/dev/null)
230
- if [ -n "$TSX_FILES" ]; then
231
- NAMESPACES=$(grep -ohP "useTranslation\(\[?'([^']+)" $TSX_FILES | sed "s/.*'//" | sort -u)
232
- for NS in $NAMESPACES; do
233
- for LANG in fr en it de; do
234
- if [ ! -f "src/i18n/locales/$LANG/$NS.json" ]; then
235
- echo "BLOCKING: Missing translation file: src/i18n/locales/$LANG/$NS.json"
236
- exit 1
237
- fi
238
- done
239
- done
240
- fi
241
- ```
242
-
243
- ### POST-CHECK 7: Pages must use lazy loading (no static page imports in routes)
244
-
245
- ```bash
246
- ROUTE_FILES=$(find src/routes/ -name "*.tsx" -o -name "*.ts" 2>/dev/null)
247
- if [ -n "$ROUTE_FILES" ]; then
248
- STATIC_PAGE_IMPORTS=$(grep -Pn "^import .+ from '@/pages/" $ROUTE_FILES 2>/dev/null)
249
- if [ -n "$STATIC_PAGE_IMPORTS" ]; then
250
- echo "BLOCKING: Route files must use React.lazy() for page imports, not static imports"
251
- echo "$STATIC_PAGE_IMPORTS"
252
- echo "Fix: const Page = lazy(() => import('@/pages/...').then(m => ({ default: m.Page })));"
253
- exit 1
254
- fi
255
- fi
256
- ```
257
-
258
- ### POST-CHECK 8: Forms must be full pages with routes — ZERO modals/popups/drawers
259
-
260
- ```bash
261
- # Check for modal/dialog/drawer imports in page files (create/edit forms)
262
- PAGE_FILES=$(find src/pages/ -name "*.tsx" 2>/dev/null)
263
- if [ -n "$PAGE_FILES" ]; then
264
- MODAL_IMPORTS=$(grep -Pn "import.*(?:Modal|Dialog|Drawer|Popup|Sheet)" $PAGE_FILES 2>/dev/null)
265
- if [ -n "$MODAL_IMPORTS" ]; then
266
- echo "BLOCKING: Form pages must NOT use Modal/Dialog/Drawer/Popup components"
267
- echo "Create/Edit forms MUST be full pages with their own URL routes"
268
- echo "Found modal imports in page files:"
269
- echo "$MODAL_IMPORTS"
270
- echo "Fix: Create EntityCreatePage.tsx with route /create and EntityEditPage.tsx with route /:id/edit"
271
- exit 1
272
- fi
273
- fi
274
- ```
275
-
276
- ### POST-CHECK 9: Create/Edit pages must exist as separate route pages
277
-
278
- ```bash
279
- # For each module with a list page, verify create and edit pages exist
280
- LIST_PAGES=$(find src/pages/ -name "*ListPage.tsx" -o -name "*sPage.tsx" 2>/dev/null | grep -v test)
281
- if [ -n "$LIST_PAGES" ]; then
282
- for LIST_PAGE in $LIST_PAGES; do
283
- PAGE_DIR=$(dirname "$LIST_PAGE")
284
- MODULE_NAME=$(basename "$PAGE_DIR")
285
- # Check for create page
286
- CREATE_PAGE=$(find "$PAGE_DIR" -name "*CreatePage.tsx" 2>/dev/null)
287
- if [ -z "$CREATE_PAGE" ]; then
288
- echo "WARNING: Module $MODULE_NAME has a list page but no CreatePage — expected EntityCreatePage.tsx"
289
- fi
290
- # Check for edit page
291
- EDIT_PAGE=$(find "$PAGE_DIR" -name "*EditPage.tsx" 2>/dev/null)
292
- if [ -z "$EDIT_PAGE" ]; then
293
- echo "WARNING: Module $MODULE_NAME has a list page but no EditPage — expected EntityEditPage.tsx"
294
- fi
295
- done
296
- fi
297
- ```
298
-
299
- ### POST-CHECK 10: Form pages must have companion test files
300
-
301
- ```bash
302
- # Every CreatePage and EditPage must have a .test.tsx file
303
- FORM_PAGES=$(find src/pages/ -name "*CreatePage.tsx" -o -name "*EditPage.tsx" 2>/dev/null | grep -v test)
304
- if [ -n "$FORM_PAGES" ]; then
305
- for FORM_PAGE in $FORM_PAGES; do
306
- TEST_FILE="${FORM_PAGE%.tsx}.test.tsx"
307
- if [ ! -f "$TEST_FILE" ]; then
308
- echo "BLOCKING: Form page missing test file: $FORM_PAGE"
309
- echo "Expected: $TEST_FILE"
310
- echo "All form pages MUST have companion test files (rendering, validation, submit, navigation)"
311
- exit 1
312
- fi
313
- done
314
- fi
315
- ```
316
-
317
- ### POST-CHECK 11: FK fields must NOT be plain text inputs (EntityLookup required)
318
-
319
- ```bash
320
- # Check for FK fields rendered as plain text inputs in form pages
321
- FORM_PAGES=$(find src/pages/ -name "*CreatePage.tsx" -o -name "*EditPage.tsx" 2>/dev/null | grep -v test | grep -v node_modules)
322
- if [ -n "$FORM_PAGES" ]; then
323
- # Detect pattern: input with value containing "Id" (e.g., employeeId, departmentId)
324
- FK_TEXT_INPUTS=$(grep -Pn 'type=["\x27]text["\x27].*[a-z]+Id|value=\{[^}]*\.[a-z]+Id\}.*type=["\x27]text["\x27]' $FORM_PAGES 2>/dev/null)
325
- if [ -n "$FK_TEXT_INPUTS" ]; then
326
- echo "BLOCKING: FK fields rendered as plain text inputs — MUST use EntityLookup component"
327
- echo "Users cannot type GUIDs manually. Use <EntityLookup /> from @/components/ui/EntityLookup"
328
- echo "See smartstack-frontend.md section 6 for the EntityLookup pattern"
329
- echo "$FK_TEXT_INPUTS"
330
- exit 1
331
- fi
332
-
333
- # Check for input placeholders mentioning "ID" or "id" or "Enter...Id"
334
- FK_PLACEHOLDER=$(grep -Pn 'placeholder=["\x27].*[Ee]nter.*[Ii][Dd]|placeholder=["\x27].*[Gg][Uu][Ii][Dd]' $FORM_PAGES 2>/dev/null)
335
- if [ -n "$FK_PLACEHOLDER" ]; then
336
- echo "BLOCKING: Form has placeholder asking user to enter an ID/GUID — use EntityLookup instead"
337
- echo "$FK_PLACEHOLDER"
338
- exit 1
339
- fi
340
- fi
341
- ```
342
-
343
- ### POST-CHECK 12: Backend APIs must support search parameter for EntityLookup
344
-
345
- ```bash
346
- # Check that controller GetAll methods accept search parameter
347
- CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
348
- if [ -n "$CTRL_FILES" ]; then
349
- for f in $CTRL_FILES; do
350
- # Check if controller has GetAll but no search parameter
351
- if grep -q "\[HttpGet\]" "$f" && grep -q "GetAll" "$f"; then
352
- if ! grep -q "search" "$f"; then
353
- echo "WARNING: Controller missing search parameter on GetAll: $f"
354
- echo "GetAll endpoints MUST accept ?search= to enable EntityLookup on frontend"
355
- echo "Fix: Add [FromQuery] string? search parameter to GetAll action"
356
- fi
357
- fi
358
- done
359
- fi
360
- ```
361
-
362
- ### POST-CHECK 13: No hardcoded Tailwind colors in generated pages
363
-
364
- ```bash
365
- NEW_PAGES=$(git diff --name-only HEAD 2>/dev/null | grep "src/pages/.*\.tsx$")
366
- if [ -n "$NEW_PAGES" ]; then
367
- HARDCODED=$(grep -Pn '(bg|text|border)-(?!\[)(red|blue|green|gray|white|black|slate|zinc|neutral|stone)-' $NEW_PAGES 2>/dev/null)
368
- if [ -n "$HARDCODED" ]; then
369
- echo "WARNING: Pages should use CSS variables instead of hardcoded Tailwind colors"
370
- echo "Fix: bg-[var(--bg-card)] instead of bg-white, text-[var(--text-primary)] instead of text-gray-900"
371
- echo "$HARDCODED"
372
- fi
373
- fi
374
- ```
375
-
376
- **If ANY POST-CHECK fails → fix in step-03, re-validate.**
377
-
378
- ---
379
-
380
- ## 7. Acceptance Criteria POST-CHECK
381
-
382
- For each AC inferred in step-01:
383
-
384
- ```
385
- AC1: {criterion} → PASS / FAIL (evidence: {file:line or test})
386
- AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
387
- ...
388
- ```
389
-
390
- **All ACs must PASS. If any FAIL, go back to step-03 to fix.**
391
-
392
- ---
393
-
394
- ## 8. Validation Summary
395
-
396
- ```
397
- **APEX SmartStack - Validation Complete**
398
-
399
- | Check | Status |
400
- |-------|--------|
401
- | MCP validate_conventions | PASS (0 errors) |
402
- | EF Core migrations | PASS / N/A |
403
- | DB: Migrations apply (SQL Server) | PASS / N/A |
404
- | DB: Integration tests (SQL Server) | PASS / N/A |
405
- | Frontend routes | PASS / N/A |
406
- | dotnet build | PASS |
407
- | npm typecheck | PASS / N/A |
408
- | Seed data | PASS / N/A |
409
- | I18n: 4 languages per namespace | PASS / N/A |
410
- | Lazy loading: no static page imports | PASS / N/A |
411
- | Forms: full pages, zero modals | PASS / N/A |
412
- | Forms: create/edit pages exist | PASS / N/A |
413
- | Forms: test files exist | PASS / N/A |
414
- | FK fields: EntityLookup, no plain text | PASS / N/A |
415
- | APIs: search parameter on GetAll | PASS / N/A |
416
- | CSS variables: no hardcoded colors | PASS / N/A |
417
- | Acceptance criteria | {X}/{Y} PASS |
418
- ```
419
-
420
- ---
421
-
422
- ## 9. Save Output (if save_mode)
423
-
424
- Write to `{output_dir}/04-validate.md` with validation results.
425
-
426
- ---
427
-
428
- ## 10. Route to Next Step
429
-
430
- ```
431
- IF examine_mode = true:
432
- → Load steps/step-05-examine.md
433
-
434
- ELSE IF test_mode = true:
435
- → Load steps/step-07-tests.md
436
-
437
- ELSE IF pr_mode = true:
438
- → Create PR and show final summary
439
-
440
- ELSE:
441
- → Show final summary and exit
442
- ```
443
-
444
- ---
445
-
446
- ## FINAL SUMMARY (if no more steps)
447
-
448
- Display: task, context, files created/modified, validation status, commits count, next steps (git diff, dotnet test, deploy).