@atlashub/smartstack-cli 4.75.0 → 4.79.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 +87 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/project/claude-md/root.CLAUDE.md.template +1 -1
- package/templates/skills/ai-prompt/SKILL.md +64 -0
- package/templates/skills/ai-prompt/references/ai-agent-modes.md +89 -0
- package/templates/skills/ai-prompt/references/eval-framework.md +129 -0
- package/templates/skills/apex/SKILL.md +2 -2
- package/templates/skills/apex/references/checks/frontend-checks.sh +123 -11
- package/templates/skills/apex/references/checks/seed-checks.sh +81 -7
- package/templates/skills/apex/references/core-seed-data.md +27 -22
- package/templates/skills/apex/references/domain-events-pattern.md +45 -0
- package/templates/skills/apex/references/entity-hooks-pattern.md +68 -0
- package/templates/skills/apex/references/licensing-enforcement.md +52 -0
- package/templates/skills/apex/references/post-checks.md +18 -1
- package/templates/skills/apex/references/smartstack-api.md +116 -5
- package/templates/skills/apex/references/smartstack-frontend.md +1 -1
- package/templates/skills/apex/references/smartstack-layers.md +6 -6
- package/templates/skills/apex/steps/step-00-init.md +1 -1
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +26 -0
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +124 -2
- package/templates/skills/apex/steps/step-04-examine.md +163 -0
- package/templates/skills/apex-verify/SKILL.md +110 -0
- package/templates/skills/apex-verify/references/audit-rules.md +50 -0
- package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
- package/templates/skills/apex-verify/steps/step-01-nav-audit.md +96 -0
- package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
- package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
- package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
- package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
- package/templates/skills/application/references/contexts-cheatsheet.md +86 -0
- package/templates/skills/application/references/extensions-system.md +158 -0
- package/templates/skills/application/references/frontend-route-naming.md +7 -5
- package/templates/skills/application/references/frontend-verification.md +7 -5
- package/templates/skills/application/references/provider-template.md +4 -2
- package/templates/skills/application/references/smartstack-provider.md +118 -0
- package/templates/skills/application/references/themes-db-driven.md +484 -0
- package/templates/skills/application/templates-frontend.md +2 -2
- package/templates/skills/application/templates-seed.md +4 -2
- package/templates/skills/audit-route/references/routing-pattern.md +3 -1
- package/templates/skills/business-analyse/SKILL.md +3 -3
- package/templates/skills/business-analyse/_shared.md +37 -0
- package/templates/skills/business-analyse/react/components.md +30 -28
- package/templates/skills/business-analyse/references/03-json-schemas.md +11 -3
- package/templates/skills/business-analyse/references/03-post-check-validation.md +64 -0
- package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
- package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
- package/templates/skills/business-analyse/references/validation-checklist.md +5 -5
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +15 -4
- package/templates/skills/business-analyse/steps/step-03-specify.md +162 -4
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +211 -1
- package/templates/skills/business-analyse/templates-react.md +15 -15
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +3 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +198 -16
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +64 -0
- package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +6 -3
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +46 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +4 -2
- package/templates/skills/business-analyse-html/references/data-build.md +2 -0
- package/templates/skills/business-analyse-html/references/data-mapping.md +88 -21
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +6 -0
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
- package/templates/skills/business-analyse-quick/SKILL.md +807 -0
- package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
- package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
- package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
- package/templates/skills/cli-app-sync/SKILL.md +105 -4
- package/templates/skills/cli-app-sync/references/comparison-map.md +13 -0
- package/templates/skills/cli-app-sync/references/diff-entities.md +162 -0
- package/templates/skills/dev-start/SKILL.md +7 -7
- package/templates/skills/documentation/templates.md +16 -16
- package/templates/skills/migrate/SKILL.md +312 -0
- package/templates/skills/migrate/references/v3.34-to-v3.46.md +289 -0
- package/templates/skills/sketch/SKILL.md +15 -153
- package/templates/skills/smoke-generation/SKILL.md +313 -0
- package/templates/skills/ui-components/SKILL.md +11 -1
- package/templates/skills/ui-components/patterns/data-table.md +1 -1
- package/templates/skills/ui-components/references/component-catalog.md +82 -0
- package/templates/skills/workflow/SKILL.md +70 -1
|
@@ -41,6 +41,108 @@ if (delegate_mode && specification_loading_plan) {
|
|
|
41
41
|
> - **Dashboard pages**: use `screen.kpis[]` for KPI card and chart definitions
|
|
42
42
|
> - **Actions**: use `screen.actions[]` for action buttons (create, export, bulk operations)
|
|
43
43
|
|
|
44
|
+
### Build Per-Entity PRD Context Block (delegate mode)
|
|
45
|
+
|
|
46
|
+
> **CRITICAL:** This block builds the authoritative specification that MUST be passed to `/ui-components`.
|
|
47
|
+
> Without it, `/ui-components` infers columns from entity structure and misses PRD-specified fields
|
|
48
|
+
> (e.g., Person Extension Pattern display fields like DisplayFirstName, DisplayLastName).
|
|
49
|
+
|
|
50
|
+
When companion specs are loaded, build a `{prd_context}` map keyed by entity name:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const prdContextMap = {}; // entityName → structured PRD block
|
|
54
|
+
|
|
55
|
+
if (screensData?.sections) {
|
|
56
|
+
for (const section of screensData.sections) {
|
|
57
|
+
for (const resource of (section.resources || [])) {
|
|
58
|
+
if (!resource.entity) continue;
|
|
59
|
+
const entityName = resource.entity;
|
|
60
|
+
|
|
61
|
+
if (!prdContextMap[entityName]) {
|
|
62
|
+
prdContextMap[entityName] = { screens: [], labels: {}, permissions: [] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Collect screen resource specs
|
|
66
|
+
prdContextMap[entityName].screens.push({
|
|
67
|
+
sectionCode: section.code,
|
|
68
|
+
sectionType: section.sectionType,
|
|
69
|
+
resourceType: resource.type,
|
|
70
|
+
columns: resource.columns || null,
|
|
71
|
+
fields: resource.fields || null,
|
|
72
|
+
actions: resource.actions || [],
|
|
73
|
+
defaultSort: resource.defaultSort || null,
|
|
74
|
+
defaultPageSize: resource.defaultPageSize || 20
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Collect section labels (4 languages)
|
|
78
|
+
if (section.labels) {
|
|
79
|
+
prdContextMap[entityName].labels[section.code] = section.labels;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Collect permissions
|
|
83
|
+
if (section.permission) {
|
|
84
|
+
prdContextMap[entityName].permissions.push(section.permission);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then, for each entity, serialize the PRD context into a text block to inject into `/ui-components`:
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
function buildPrdBlock(entityName) {
|
|
95
|
+
const ctx = prdContextMap[entityName];
|
|
96
|
+
if (!ctx || ctx.screens.length === 0) return '';
|
|
97
|
+
|
|
98
|
+
let block = '\n--- PRD SPECIFICATION (AUTHORITATIVE — use these EXACT definitions) ---\n';
|
|
99
|
+
|
|
100
|
+
// SmartTable columns
|
|
101
|
+
const tableScreens = ctx.screens.filter(s => s.resourceType === 'SmartTable' && s.columns);
|
|
102
|
+
for (const screen of tableScreens) {
|
|
103
|
+
block += `\nCOLUMNS for DataTable (section: "${screen.sectionCode}") — use ALL, in this EXACT order:\n`;
|
|
104
|
+
for (const col of screen.columns) {
|
|
105
|
+
block += ` - key: "${col.field}", label_fr: "${col.label?.fr || col.field}", ` +
|
|
106
|
+
`label_en: "${col.label?.en || col.field}", format: "${col.format}", ` +
|
|
107
|
+
`sortable: ${col.sortable || false}\n`;
|
|
108
|
+
}
|
|
109
|
+
if (screen.actions.length > 0) {
|
|
110
|
+
block += `ACTIONS: ${screen.actions.join(', ')}\n`;
|
|
111
|
+
}
|
|
112
|
+
if (screen.defaultSort) {
|
|
113
|
+
block += `DEFAULT SORT: field="${screen.defaultSort.field}", direction="${screen.defaultSort.direction}"\n`;
|
|
114
|
+
}
|
|
115
|
+
block += `PAGE SIZE: ${screen.defaultPageSize}\n`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// SmartForm fields
|
|
119
|
+
const formScreens = ctx.screens.filter(s => s.resourceType === 'SmartForm' && s.fields);
|
|
120
|
+
for (const screen of formScreens) {
|
|
121
|
+
block += `\nFORM FIELDS (section: "${screen.sectionCode}"):\n`;
|
|
122
|
+
for (const field of screen.fields) {
|
|
123
|
+
block += ` - name: "${field.name}", type: "${field.type}", required: ${field.required || false}\n`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Labels
|
|
128
|
+
block += '\nSECTION LABELS (use for page titles, breadcrumbs, i18n — 4 languages):\n';
|
|
129
|
+
for (const [code, labels] of Object.entries(ctx.labels)) {
|
|
130
|
+
block += ` ${code}: fr="${labels.fr}" en="${labels.en}" it="${labels.it}" de="${labels.de}"\n`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Permissions
|
|
134
|
+
if (ctx.permissions.length > 0) {
|
|
135
|
+
block += `\nPERMISSIONS: ${ctx.permissions.join(', ')}\n`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
block += '--- END PRD SPECIFICATION ---\n';
|
|
139
|
+
return block;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Usage:** When invoking `Skill("ui-components")`, append `buildPrdBlock(entityName)` to the arguments.
|
|
144
|
+
The `/ui-components` skill reads free-text instructions — the structured block is parsed naturally.
|
|
145
|
+
|
|
44
146
|
### ⛔ HARD RULE — /ui-components is NON-NEGOTIABLE (read BEFORE any Layer 3 action)
|
|
45
147
|
|
|
46
148
|
> **VIOLATION CHECK:** If ANY .tsx page file was created by Write tool WITHOUT
|
|
@@ -130,6 +232,15 @@ For each module:
|
|
|
130
232
|
→ Create{Section}Page.tsx (/create route)
|
|
131
233
|
→ Edit{Section}Page.tsx (/:id/edit route)
|
|
132
234
|
"detail" is NEVER a separate section — it's the /:id route of the list section.
|
|
235
|
+
- **CRUD Page Completeness (MANDATORY for every entity section with a ListPage):**
|
|
236
|
+
1. ALL 4 page types MUST exist (List, Detail, Create/Form, Edit/Form)
|
|
237
|
+
2. **Create button on ListPage (MANDATORY):** Every ListPage MUST include a "New" / "Create" button
|
|
238
|
+
in the header that calls `navigate('create')`. Without this button, users cannot access the create form.
|
|
239
|
+
3. **componentRegistry registration:** ALL page types MUST be registered via `PageRegistry.register()`.
|
|
240
|
+
After `scaffold_routes`, verify the registry contains keys for ALL pages.
|
|
241
|
+
If form pages (create/edit) are missing from registry, add them manually.
|
|
242
|
+
4. **POST-CHECK Gate PG-2b:** Grep every `*ListPage.tsx` for `navigate.*create`.
|
|
243
|
+
If absent → BLOCKING error — add the create button before proceeding.
|
|
133
244
|
- Pages: **MANDATORY — INVOKE Skill("ui-components")** for ALL page generation.
|
|
134
245
|
⚠ BLOCKING REQUIREMENT: You MUST call Skill("ui-components") for EVERY page (.tsx).
|
|
135
246
|
NEVER generate .tsx page code directly. NEVER write page content in Agent prompts.
|
|
@@ -245,13 +356,17 @@ IF NOT economy_mode AND entities.length > 1:
|
|
|
245
356
|
# PHASE B — Sequential: pages via /ui-components (principal agent)
|
|
246
357
|
# Snipper agents cannot call Skill() — only the principal agent can.
|
|
247
358
|
For each entity (sequentially):
|
|
248
|
-
**INVOKE Skill("ui-components")** — pass entity context:
|
|
359
|
+
**INVOKE Skill("ui-components")** — pass entity context + PRD spec:
|
|
249
360
|
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
250
361
|
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
251
362
|
- "CSS: Use CSS variables ONLY — bg-[var(--bg-card)], text-[var(--text-primary)]"
|
|
252
363
|
- "Forms: Create/Edit are FULL PAGES with own routes (/create, /:id/edit)"
|
|
253
364
|
- "FK FIELDS: EntityLookup for ALL FK Guid fields"
|
|
254
365
|
- "I18n: ALL text uses t('namespace:key', 'Fallback')"
|
|
366
|
+
- {buildPrdBlock(EntityName)} — append the PRD specification block from companion specs
|
|
367
|
+
- "COLUMNS ARE AUTHORITATIVE: Do NOT infer columns from entity attributes. Use ALL columns from the PRD SPECIFICATION block above, in the EXACT order listed. Do NOT add, remove, or reorder columns."
|
|
368
|
+
- "LABELS ARE AUTHORITATIVE: Use PRD SECTION LABELS for i18n t() fallback text and page titles. Do NOT invent labels."
|
|
369
|
+
- "ACTIONS ARE AUTHORITATIVE: Implement ALL action buttons listed in the PRD SPECIFICATION (create, edit, delete, approve, reject, export, etc.)."
|
|
255
370
|
Generate form tests: co-located .test.tsx for Create and Edit pages
|
|
256
371
|
|
|
257
372
|
ELSE:
|
|
@@ -263,12 +378,16 @@ ELSE:
|
|
|
263
378
|
2. MCP scaffold_routes (outputFormat: 'componentRegistry')
|
|
264
379
|
3. Verify PageRegistry registration (componentRegistry.generated.ts)
|
|
265
380
|
No manual App.tsx wiring needed — DynamicRouter resolves at runtime
|
|
266
|
-
4. **INVOKE Skill("ui-components")** — pass entity context:
|
|
381
|
+
4. **INVOKE Skill("ui-components")** — pass entity context + PRD spec:
|
|
267
382
|
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
268
383
|
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
269
384
|
- "CSS: Use CSS variables ONLY — bg-[var(--bg-card)], text-[var(--text-primary)]"
|
|
270
385
|
- "Forms: Create/Edit are FULL PAGES with own routes (/create, /:id/edit)"
|
|
271
386
|
- "I18n: ALL text uses t('namespace:key', 'Fallback')"
|
|
387
|
+
- {buildPrdBlock(EntityName)} — append the PRD specification block from companion specs
|
|
388
|
+
- "COLUMNS ARE AUTHORITATIVE: Do NOT infer columns from entity attributes. Use ALL columns from the PRD SPECIFICATION block above, in the EXACT order listed."
|
|
389
|
+
- "LABELS ARE AUTHORITATIVE: Use PRD SECTION LABELS for i18n t() fallback text."
|
|
390
|
+
- "ACTIONS ARE AUTHORITATIVE: Implement ALL action buttons listed in the PRD SPECIFICATION."
|
|
272
391
|
5. I18n: 4 JSON files (fr, en, it, de) + register namespace in i18n config
|
|
273
392
|
6. Form tests: co-located .test.tsx for Create and Edit pages
|
|
274
393
|
```
|
|
@@ -300,6 +419,9 @@ When delegating to `/ui-components` skill, include explicit instructions:
|
|
|
300
419
|
- "Forms: Create/Edit forms are FULL PAGES with own routes (e.g., `/create`, `/:id/edit`)."
|
|
301
420
|
- "I18n: ALL text must use `t('namespace:key', 'Fallback')`. Generate JSON files in `src/i18n/locales/`."
|
|
302
421
|
- "Hooks: MUST use apiClient from @/services/api — NEVER raw fetch() or direct axios import."
|
|
422
|
+
- "PRD COLUMNS: If a `--- PRD SPECIFICATION ---` block is present, use its columns[] as the EXACT DataTable columns. Do NOT add, remove, or reorder. Do NOT infer columns from entity attributes — the PRD is the source of truth."
|
|
423
|
+
- "PRD LABELS: If a `--- PRD SPECIFICATION ---` block is present, use its SECTION LABELS for page titles and i18n fallback text in all 4 languages."
|
|
424
|
+
- "PRD ACTIONS: If a `--- PRD SPECIFICATION ---` block lists actions (approve, reject, export, etc.), generate the corresponding buttons and handlers."
|
|
303
425
|
|
|
304
426
|
### ⛔ POST-GENERATION VERIFICATION GATES (MANDATORY — run after ALL pages are created)
|
|
305
427
|
|
|
@@ -168,6 +168,168 @@ for (const providerFile of providerFiles) {
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
+
## 6d. PRD Compliance Verification (delegate mode only)
|
|
172
|
+
|
|
173
|
+
> **Run ONLY when `delegate_mode` is true AND companion spec files exist.**
|
|
174
|
+
> This checks that generated code matches PRD specifications — not just technical quality.
|
|
175
|
+
> The PRD companion files are the AUTHORITATIVE source for columns, actions, labels, and permissions.
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
if (delegate_mode) {
|
|
179
|
+
const specsDir = path.dirname(delegate_prd_path);
|
|
180
|
+
const prd = readJSON(delegate_prd_path);
|
|
181
|
+
|
|
182
|
+
const screensPath = path.join(specsDir, prd.specificationFiles?.screens);
|
|
183
|
+
const permsPath = path.join(specsDir, prd.specificationFiles?.permissions);
|
|
184
|
+
const screens = fileExists(screensPath) ? readJSON(screensPath) : null;
|
|
185
|
+
const perms = fileExists(permsPath) ? readJSON(permsPath) : null;
|
|
186
|
+
|
|
187
|
+
if (screens) {
|
|
188
|
+
// ──── PC-1 (BLOCKING): Column Completeness ────
|
|
189
|
+
// Every column defined in screens.json SmartTable resources MUST exist in the generated ListPage.
|
|
190
|
+
for (const section of screens.sections) {
|
|
191
|
+
for (const resource of (section.resources || [])) {
|
|
192
|
+
if (resource.type !== 'SmartTable' || !resource.columns) continue;
|
|
193
|
+
const entityName = resource.entity;
|
|
194
|
+
// Find the corresponding ListPage
|
|
195
|
+
const listPages = Glob(`src/pages/**/${entityName}*ListPage.tsx`);
|
|
196
|
+
if (listPages.length === 0) {
|
|
197
|
+
BLOCKING(`PC-1: No ListPage found for entity ${entityName} (section: ${section.code})`);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const pageContent = readFile(listPages[0]);
|
|
201
|
+
const missingCols = [];
|
|
202
|
+
for (const col of resource.columns) {
|
|
203
|
+
// Check for the column field name in the page content
|
|
204
|
+
if (!pageContent.includes(col.field)) {
|
|
205
|
+
missingCols.push(`${col.field} (${col.format})`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (missingCols.length > 0) {
|
|
209
|
+
BLOCKING(`PC-1: ${listPages[0]} missing ${missingCols.length}/${resource.columns.length} columns: ${missingCols.join(', ')}. ` +
|
|
210
|
+
`Fix: re-invoke Skill("ui-components") with the PRD SPECIFICATION block containing ALL columns.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ──── PC-2 (BLOCKING): Action Button Completeness ────
|
|
216
|
+
// Actions defined in screens.json MUST have corresponding handlers in the generated pages.
|
|
217
|
+
for (const section of screens.sections) {
|
|
218
|
+
for (const resource of (section.resources || [])) {
|
|
219
|
+
if (!resource.actions || resource.actions.length === 0) continue;
|
|
220
|
+
const entityName = resource.entity;
|
|
221
|
+
const pages = Glob(`src/pages/**/${entityName}*Page.tsx`);
|
|
222
|
+
const allContent = pages.map(p => readFile(p)).join('\n');
|
|
223
|
+
|
|
224
|
+
for (const action of resource.actions) {
|
|
225
|
+
let found = false;
|
|
226
|
+
switch (action) {
|
|
227
|
+
case 'create': found = allContent.includes('navigate') && allContent.includes('create'); break;
|
|
228
|
+
case 'edit': found = allContent.includes('edit') || allContent.includes('Edit'); break;
|
|
229
|
+
case 'delete': found = allContent.includes('delete') || allContent.includes('Delete'); break;
|
|
230
|
+
case 'approve': found = allContent.includes('approve') || allContent.includes('Approve'); break;
|
|
231
|
+
case 'reject': found = allContent.includes('reject') || allContent.includes('Reject'); break;
|
|
232
|
+
case 'export': found = allContent.includes('export') || allContent.includes('Export'); break;
|
|
233
|
+
default: found = allContent.toLowerCase().includes(action.toLowerCase());
|
|
234
|
+
}
|
|
235
|
+
if (!found) {
|
|
236
|
+
BLOCKING(`PC-2: ${entityName} pages missing action handler for '${action}' (section: ${section.code}). ` +
|
|
237
|
+
`Fix: add ${action} button/handler to the relevant page.`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ──── PC-3 (WARNING): I18n Label Accent Accuracy ────
|
|
244
|
+
// French/German/Italian labels MUST have proper UTF-8 accents.
|
|
245
|
+
const ACCENT_PATTERNS_FR = {
|
|
246
|
+
'Employes': 'Employés', 'Departement': 'Département', 'Departements': 'Départements',
|
|
247
|
+
'Prenom': 'Prénom', 'Numero': 'Numéro', 'Societe': 'Société',
|
|
248
|
+
'Categorie': 'Catégorie', 'Securite': 'Sécurité', 'Conge': 'Congé', 'Conges': 'Congés',
|
|
249
|
+
'Generalites': 'Généralités', 'Resume': 'Résumé', 'Echeance': 'Échéance'
|
|
250
|
+
};
|
|
251
|
+
const i18nFiles = Glob(`src/**/i18n/locales/fr/*.json`);
|
|
252
|
+
for (const file of i18nFiles) {
|
|
253
|
+
const content = readFile(file);
|
|
254
|
+
for (const [ascii, accented] of Object.entries(ACCENT_PATTERNS_FR)) {
|
|
255
|
+
if (content.includes(`"${ascii}"`) || content.includes(`"${ascii} `)) {
|
|
256
|
+
WARNING(`PC-3: ${file} contains ASCII-only '${ascii}' — should be '${accented}'. Fix the accent.`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ──── PC-5 (WARNING): Section Page Completeness ────
|
|
262
|
+
// Every primary/functional section in screens.json should have a corresponding page.
|
|
263
|
+
for (const section of screens.sections) {
|
|
264
|
+
if (!['primary', 'functional'].includes(section.sectionType)) continue;
|
|
265
|
+
const sectionCode = section.code;
|
|
266
|
+
const resources = section.resources || [];
|
|
267
|
+
const entityNames = resources.map(r => r.entity).filter(Boolean);
|
|
268
|
+
|
|
269
|
+
// Check if any page exists for this section's entities
|
|
270
|
+
let pageFound = false;
|
|
271
|
+
for (const entity of entityNames) {
|
|
272
|
+
const pages = Glob(`src/pages/**/${entity}*Page.tsx`);
|
|
273
|
+
if (pages.length > 0) { pageFound = true; break; }
|
|
274
|
+
}
|
|
275
|
+
// Also check by section code (e.g., CalendarPage, ApprovePage)
|
|
276
|
+
if (!pageFound) {
|
|
277
|
+
const sectionPages = Glob(`src/pages/**/*${sectionCode}*Page.tsx`);
|
|
278
|
+
pageFound = sectionPages.length > 0;
|
|
279
|
+
}
|
|
280
|
+
if (!pageFound) {
|
|
281
|
+
WARNING(`PC-5: Section '${sectionCode}' (${section.sectionType}) defined in screens.json ` +
|
|
282
|
+
`but no corresponding page found. Consider generating it.`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (perms) {
|
|
288
|
+
// ──── PC-4 (BLOCKING): Permission Seed Data Completeness ────
|
|
289
|
+
// All permissionPaths from permissions.json MUST be seeded in PermissionsSeedData.
|
|
290
|
+
const permSeedFiles = Glob(`**/PermissionsSeedData.cs`);
|
|
291
|
+
const permClassFiles = Glob(`**/Permissions.cs`);
|
|
292
|
+
const allPermContent = [...permSeedFiles, ...permClassFiles].map(f => readFile(f)).join('\n');
|
|
293
|
+
|
|
294
|
+
for (const path of perms.permissionPaths) {
|
|
295
|
+
// Check for the permission path (may be stored as kebab-case or segments)
|
|
296
|
+
const segments = path.split('.');
|
|
297
|
+
const lastSegment = segments[segments.length - 1].toLowerCase();
|
|
298
|
+
if (!allPermContent.toLowerCase().includes(lastSegment)) {
|
|
299
|
+
BLOCKING(`PC-4: Permission path '${path}' not found in seed data. ` +
|
|
300
|
+
`Fix: add to PermissionsSeedData.cs and Permissions.cs constants.`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Verify roles from permissions.json exist in RolesSeedData
|
|
305
|
+
const roleSeedFiles = Glob(`**/RolesSeedData.cs`);
|
|
306
|
+
const allRoleContent = roleSeedFiles.map(f => readFile(f)).join('\n');
|
|
307
|
+
for (const role of perms.roles) {
|
|
308
|
+
if (!allRoleContent.includes(role.role)) {
|
|
309
|
+
WARNING(`PC-4b: Role '${role.role}' from permissions.json not found in RolesSeedData.cs.`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ──── PC-6 (WARNING): I18n Namespace Registration ────
|
|
315
|
+
// This overlaps with GATE PG-4 but cross-checks against screens.json sections.
|
|
316
|
+
const i18nConfig = Glob(`src/**/i18n/config.ts`)[0] || Glob(`src/**/i18n/index.ts`)[0];
|
|
317
|
+
if (i18nConfig && screens) {
|
|
318
|
+
const configContent = readFile(i18nConfig);
|
|
319
|
+
const moduleCode = prd.project?.module;
|
|
320
|
+
if (moduleCode && !configContent.includes(moduleCode)) {
|
|
321
|
+
WARNING(`PC-6: Module namespace '${moduleCode}' not registered in ${i18nConfig}. ` +
|
|
322
|
+
`Translation keys will render as raw strings.`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
> **If ANY BLOCKING check fails:** Return to step-03d to fix the specific issue, then re-run section 6d.
|
|
329
|
+
> BLOCKING failures indicate the generated code does NOT match the PRD specification.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
171
333
|
## 7. Acceptance Criteria POST-CHECK
|
|
172
334
|
|
|
173
335
|
For each AC from step-01:
|
|
@@ -210,6 +372,7 @@ AC1: {criterion} → PASS / FAIL (evidence)
|
|
|
210
372
|
| Navigation translations (4 langs) | PASS / N/A |
|
|
211
373
|
| Inline tests | PASS / N/A |
|
|
212
374
|
| POST-CHECKs | PASS / N/A |
|
|
375
|
+
| PRD Compliance (delegate) | PASS / N/A |
|
|
213
376
|
| Acceptance criteria | {X}/{Y} PASS |
|
|
214
377
|
|
|
215
378
|
---
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apex-verify
|
|
3
|
+
description: |
|
|
4
|
+
Audit a generated SmartStack APEX application for common generation issues.
|
|
5
|
+
Use this skill when:
|
|
6
|
+
- Verifying a generated app has no missing CRUD pages or buttons
|
|
7
|
+
- Checking navigation seed data for reserved section codes in menu
|
|
8
|
+
- Auditing permission coverage (controllers vs Permissions.cs vs seed data)
|
|
9
|
+
- Validating route alignment (frontend vs backend vs seed)
|
|
10
|
+
- After /apex or /business-analyse-develop completes
|
|
11
|
+
argument-hint: "[--scope=all|nav|crud|perm|route] [--fix]"
|
|
12
|
+
model: sonnet
|
|
13
|
+
allowed-tools: "Read, Grep, Glob, Bash, ToolSearch"
|
|
14
|
+
entry_point: steps/step-00-init.md
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<objective>
|
|
18
|
+
Audit a SmartStack application generated by /apex or /business-analyse-develop for common post-generation issues:
|
|
19
|
+
|
|
20
|
+
1. **Navigation** — Reserved section codes (detail, create, edit) seeded as visible menu items
|
|
21
|
+
2. **CRUD** — Missing page types, missing "New" buttons on list pages, incomplete componentRegistry
|
|
22
|
+
3. **Permissions** — Cross-reference controllers, Permissions.cs, PermissionsSeedData, RolesSeedData
|
|
23
|
+
4. **Routes** — Alignment between seed data routes, PageRegistry keys, and controller NavRoutes
|
|
24
|
+
|
|
25
|
+
The audit is **read-only** by default. Use `--fix` to display actionable fix commands.
|
|
26
|
+
</objective>
|
|
27
|
+
|
|
28
|
+
<quick_start>
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
/apex-verify # Full audit (all 4 categories)
|
|
32
|
+
/apex-verify --scope=nav # Navigation menu audit only
|
|
33
|
+
/apex-verify --scope=crud # CRUD completeness audit only
|
|
34
|
+
/apex-verify --scope=perm # Permission cross-reference only
|
|
35
|
+
/apex-verify --scope=route # Route alignment only
|
|
36
|
+
/apex-verify --fix # Full audit + fix suggestions
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
</quick_start>
|
|
40
|
+
|
|
41
|
+
<parameters>
|
|
42
|
+
|
|
43
|
+
<flags>
|
|
44
|
+
| Flag | Description |
|
|
45
|
+
|------|-------------|
|
|
46
|
+
| `--scope=all` | Audit all 4 categories (default) |
|
|
47
|
+
| `--scope=nav` | Navigation audit only (reserved section codes) |
|
|
48
|
+
| `--scope=crud` | CRUD completeness only (pages, buttons, registry) |
|
|
49
|
+
| `--scope=perm` | Permission cross-reference only |
|
|
50
|
+
| `--scope=route` | Route alignment only |
|
|
51
|
+
| `--fix` | Display actionable fix commands for each finding |
|
|
52
|
+
</flags>
|
|
53
|
+
</parameters>
|
|
54
|
+
|
|
55
|
+
<workflow>
|
|
56
|
+
1. **Initialize** — Detect project structure, locate seed data, controllers, pages
|
|
57
|
+
2. **Navigation Audit** — Check for reserved section codes seeded as menu items
|
|
58
|
+
3. **CRUD Audit** — Verify 4 page types per section, create buttons, componentRegistry
|
|
59
|
+
4. **Permission Audit** — Cross-reference controllers, Permissions.cs, seed data, roles
|
|
60
|
+
5. **Route Audit** — Verify frontend/backend/seed alignment
|
|
61
|
+
6. **Report** — Consolidated findings with severity and fix suggestions
|
|
62
|
+
</workflow>
|
|
63
|
+
|
|
64
|
+
<state_variables>
|
|
65
|
+
| Variable | Type | Description |
|
|
66
|
+
|----------|------|-------------|
|
|
67
|
+
| `{scope}` | string | all, nav, crud, perm, route |
|
|
68
|
+
| `{fix_mode}` | boolean | Display fix commands |
|
|
69
|
+
| `{api_root}` | string | Path to backend src/ |
|
|
70
|
+
| `{web_root}` | string | Path to frontend web/ |
|
|
71
|
+
| `{seed_files}` | string[] | All *NavigationSeedData.cs files |
|
|
72
|
+
| `{controller_files}` | string[] | All *Controller.cs files |
|
|
73
|
+
| `{page_files}` | string[] | All *.tsx page files |
|
|
74
|
+
| `{registry_file}` | string | componentRegistry.generated.ts path |
|
|
75
|
+
| `{permissions_file}` | string | Permissions.cs path |
|
|
76
|
+
| `{findings}` | object[] | All findings with ID, severity, message, fix |
|
|
77
|
+
</state_variables>
|
|
78
|
+
|
|
79
|
+
<entry_point>
|
|
80
|
+
|
|
81
|
+
**FIRST ACTION:** Load `steps/step-00-init.md`
|
|
82
|
+
|
|
83
|
+
</entry_point>
|
|
84
|
+
|
|
85
|
+
<step_files>
|
|
86
|
+
| Step | File | Purpose |
|
|
87
|
+
|------|------|---------|
|
|
88
|
+
| 00 | `steps/step-00-init.md` | Parse flags, detect project structure, resolve paths |
|
|
89
|
+
| 01 | `steps/step-01-nav-audit.md` | Audit navigation seed data for reserved section codes |
|
|
90
|
+
| 02 | `steps/step-02-crud-audit.md` | Audit CRUD completeness (pages, buttons, registry) |
|
|
91
|
+
| 03 | `steps/step-03-perm-audit.md` | Audit permissions cross-reference |
|
|
92
|
+
| 04 | `steps/step-04-route-audit.md` | Audit route alignment |
|
|
93
|
+
| 05 | `steps/step-05-report.md` | Generate consolidated report |
|
|
94
|
+
</step_files>
|
|
95
|
+
|
|
96
|
+
<execution_rules>
|
|
97
|
+
- **Read-only** — This skill NEVER modifies code (unless --fix is used, and even then only displays commands)
|
|
98
|
+
- **Evidence-based** — Every finding must reference a specific file:line
|
|
99
|
+
- **Comprehensive** — Check ALL files, not a sample
|
|
100
|
+
- **Actionable** — Every finding must include a fix suggestion
|
|
101
|
+
- **Scoped** — Only run audits matching {scope}
|
|
102
|
+
- **SmartStack-aware** — Respect SmartStack conventions (PageRegistry, DynamicRouter, NavRoute, SeedData patterns)
|
|
103
|
+
</execution_rules>
|
|
104
|
+
|
|
105
|
+
<success_criteria>
|
|
106
|
+
- All applicable audits completed with zero false positives
|
|
107
|
+
- Each finding has: ID, severity (BLOCKING/CRITICAL/WARNING), file:line, description, fix
|
|
108
|
+
- Consolidated report with category totals
|
|
109
|
+
- Executive summary with pass/fail per category
|
|
110
|
+
</success_criteria>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Audit Rules Reference
|
|
2
|
+
|
|
3
|
+
> Complete codification of all audit rules used by /apex-verify.
|
|
4
|
+
> Each rule has a unique ID, severity, description, detection method, and fix pattern.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Navigation Rules (NAV-xxx)
|
|
9
|
+
|
|
10
|
+
| ID | Severity | Description | Detection | Fix |
|
|
11
|
+
|----|----------|-------------|-----------|-----|
|
|
12
|
+
| NAV-001 | BLOCKING | Reserved section code (detail/create/edit) seeded as visible menu item | Grep NavigationSeedData for `Code = "detail"` / `"create"` / `"edit"` without `IsActive = false` | Remove section from seed data, or set `IsActive = false` |
|
|
13
|
+
| NAV-002 | BLOCKING | Section code contains "-detail" seeded as menu item | Grep for codes matching `*-detail` pattern | Remove section entry — detail is resolved as /:id under parent section |
|
|
14
|
+
| NAV-003 | BLOCKING | Route contains forbidden segment (/detail/, /create/, /edit/) | Grep seed data routes for `/detail/`, `/create/`, `/edit/` segments | Use convention routes: /:id, /create, /:id/edit (no explicit segments) |
|
|
15
|
+
| NAV-004 | WARNING | Reserved section code with IsActive = false | Code is reserved but hidden from menu | Acceptable — remove if unnecessary |
|
|
16
|
+
| NAV-005 | WARNING | Section code not in kebab-case | Regex check: `^[a-z][a-z0-9]*(-[a-z0-9]+)*$` | Rename to kebab-case |
|
|
17
|
+
|
|
18
|
+
## CRUD Rules (CRUD-xxx)
|
|
19
|
+
|
|
20
|
+
| ID | Severity | Description | Detection | Fix |
|
|
21
|
+
|----|----------|-------------|-----------|-----|
|
|
22
|
+
| CRUD-001 | BLOCKING | ListPage missing for entity | Glob for `*ListPage.tsx` matching entity | Generate via `/ui-components` |
|
|
23
|
+
| CRUD-002 | BLOCKING | DetailPage missing for entity | Glob for `*DetailPage.tsx` matching entity | Generate via `/ui-components` |
|
|
24
|
+
| CRUD-003 | BLOCKING | Create/Edit page missing for entity | Glob for `*CreatePage.tsx`, `*EditPage.tsx`, `*FormPage.tsx` | Generate via `/ui-components` |
|
|
25
|
+
| CRUD-004 | BLOCKING | ListPage has no Create/New button | Grep for `navigate.*create` or `Link.*create` | Add navigate('create') button in page header |
|
|
26
|
+
| CRUD-005 | BLOCKING | Page exists but not registered in componentRegistry | Read registry, check for matching key | Add `PageRegistry.register()` call or run `scaffold_routes` |
|
|
27
|
+
| CRUD-006 | WARNING | Registry entry has no matching page file | Read registry, check file existence | Remove orphan registry entry or create the page |
|
|
28
|
+
| CRUD-007 | WARNING | Form page has no submit handler | Grep for `onSubmit`, `handleSubmit`, `api.create`, `api.post` | Implement form submission logic |
|
|
29
|
+
|
|
30
|
+
## Permission Rules (PERM-xxx)
|
|
31
|
+
|
|
32
|
+
| ID | Severity | Description | Detection | Fix |
|
|
33
|
+
|----|----------|-------------|-----------|-----|
|
|
34
|
+
| PERM-001 | BLOCKING | Controller uses permission not defined in Permissions.cs | Cross-ref `[RequirePermission]` vs `Permissions.cs` | Add missing constant to Permissions.cs |
|
|
35
|
+
| PERM-002 | BLOCKING | Permissions.cs constant not seeded in PermissionsSeedData | Cross-ref Permissions.cs paths vs seed data | Add `HasData()` entry in PermissionsSeedData |
|
|
36
|
+
| PERM-003 | CRITICAL | Seeded permission has no role mapping | Cross-ref seed data vs RolesSeedData | Add role-permission mapping in RolesSeedData |
|
|
37
|
+
| PERM-004 | CRITICAL | Admin role missing wildcard for module | Check admin role has `*.module.*` wildcard | Add wildcard permission for admin role |
|
|
38
|
+
| PERM-005 | WARNING | Permission path segments not in kebab-case | Regex check on permission paths | Rename to kebab-case |
|
|
39
|
+
| PERM-006 | WARNING | Viewer role has write permission | Check viewer role permissions | Remove write permissions from viewer role |
|
|
40
|
+
| PERM-007 | WARNING | Permission defined but unused by any controller | Cross-ref Permissions.cs vs controllers | Remove dead permission or add controller usage |
|
|
41
|
+
|
|
42
|
+
## Route Rules (ROUTE-xxx)
|
|
43
|
+
|
|
44
|
+
| ID | Severity | Description | Detection | Fix |
|
|
45
|
+
|----|----------|-------------|-----------|-----|
|
|
46
|
+
| ROUTE-001 | BLOCKING | Seed data route has no matching PageRegistry entry | Cross-ref seed routes vs registry keys | Add PageRegistry.register() or run scaffold_routes |
|
|
47
|
+
| ROUTE-002 | WARNING | Controller NavRoute has no matching seed data entry | Cross-ref NavRoute attrs vs seed routes | Add navigation seed data entry |
|
|
48
|
+
| ROUTE-003 | BLOCKING | PageRegistry references non-existent page file | Read registry imports, check file existence | Create page or fix import path |
|
|
49
|
+
| ROUTE-004 | WARNING | Orphan page — exists on disk but not registered | Cross-ref page files vs registry | Register page or delete orphan |
|
|
50
|
+
| ROUTE-005 | WARNING | Implicit route (detail/create/edit) not resolvable | Check registry + DynamicRouter conventions | Register in componentRegistry |
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-00-init
|
|
3
|
+
description: Parse flags, detect project structure, resolve paths for APEX verification
|
|
4
|
+
next_step: steps/step-01-nav-audit.md
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Step 0: Initialization
|
|
8
|
+
|
|
9
|
+
## MANDATORY EXECUTION RULES:
|
|
10
|
+
- NEVER skip project detection
|
|
11
|
+
- ALWAYS resolve actual filesystem paths before proceeding
|
|
12
|
+
- YOU ARE AN INITIALIZER, not a scanner
|
|
13
|
+
|
|
14
|
+
## YOUR TASK:
|
|
15
|
+
Parse the flags, detect the SmartStack project structure, and locate all files needed for auditing.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## EXECUTION SEQUENCE:
|
|
20
|
+
|
|
21
|
+
### 1. Parse Input
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Arguments from $ARGUMENTS:
|
|
25
|
+
--scope=nav -> {scope} = "nav"
|
|
26
|
+
--scope=crud -> {scope} = "crud"
|
|
27
|
+
--scope=perm -> {scope} = "perm"
|
|
28
|
+
--scope=route -> {scope} = "route"
|
|
29
|
+
--scope=all -> {scope} = "all" (default)
|
|
30
|
+
--fix -> {fix_mode} = true (default: false)
|
|
31
|
+
|
|
32
|
+
No arguments -> {scope} = "all", {fix_mode} = false
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 2. Detect Project Structure
|
|
36
|
+
|
|
37
|
+
Use Glob to locate all required files:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Backend paths:
|
|
41
|
+
{api_root} = src/*/Api/ or src/*.Api/
|
|
42
|
+
Verify: *.sln exists at project root
|
|
43
|
+
|
|
44
|
+
Frontend paths:
|
|
45
|
+
{web_root} = web/*/src/ or web/*-web/src/
|
|
46
|
+
Verify: package.json exists in web/*/
|
|
47
|
+
|
|
48
|
+
Key files to locate:
|
|
49
|
+
{seed_files}:
|
|
50
|
+
Glob "**/Seeding/Data/**/*NavigationSeedData.cs"
|
|
51
|
+
Glob "**/Seeding/Data/**/*NavigationModuleSeedData.cs"
|
|
52
|
+
|
|
53
|
+
{controller_files}:
|
|
54
|
+
Glob "**/Controllers/**/*Controller.cs"
|
|
55
|
+
|
|
56
|
+
{page_files}:
|
|
57
|
+
Glob "web/**/src/pages/**/*Page.tsx"
|
|
58
|
+
|
|
59
|
+
{registry_file}:
|
|
60
|
+
Glob "**/componentRegistry.generated.ts" or "**/componentRegistry*.ts"
|
|
61
|
+
|
|
62
|
+
{permissions_file}:
|
|
63
|
+
Glob "**/Authorization/Permissions.cs" or "**/Common/Authorization/Permissions.cs"
|
|
64
|
+
|
|
65
|
+
{perm_seed_files}:
|
|
66
|
+
Glob "**/Seeding/Data/**/*PermissionsSeedData.cs"
|
|
67
|
+
Glob "**/Seeding/Data/**/*SeedDataProvider.cs"
|
|
68
|
+
|
|
69
|
+
{role_seed_files}:
|
|
70
|
+
Glob "**/Seeding/Data/**/*RolesSeedData.cs"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. Validate Paths
|
|
74
|
+
|
|
75
|
+
For each required file set:
|
|
76
|
+
- If empty: record as CRITICAL warning (cannot audit that category)
|
|
77
|
+
- If found: record paths for next steps
|
|
78
|
+
|
|
79
|
+
### 4. Show Summary and Proceed
|
|
80
|
+
|
|
81
|
+
Display:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
APEX Verification — Initialization
|
|
85
|
+
====================================
|
|
86
|
+
|
|
87
|
+
| Setting | Value |
|
|
88
|
+
|---------|-------|
|
|
89
|
+
| Scope | {scope} |
|
|
90
|
+
| Fix mode | {fix_mode} |
|
|
91
|
+
|
|
92
|
+
Project Structure:
|
|
93
|
+
| Category | Files Found |
|
|
94
|
+
|----------|-------------|
|
|
95
|
+
| Navigation seed data | {count} files |
|
|
96
|
+
| Controllers | {count} files |
|
|
97
|
+
| Frontend pages | {count} files |
|
|
98
|
+
| Component registry | {found/MISSING} |
|
|
99
|
+
| Permissions.cs | {found/MISSING} |
|
|
100
|
+
| Permission seed data | {count} files |
|
|
101
|
+
| Role seed data | {count} files |
|
|
102
|
+
|
|
103
|
+
-> Proceeding to audits...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## SUCCESS METRICS:
|
|
109
|
+
- Scope and flags correctly parsed
|
|
110
|
+
- All filesystem paths resolved and validated
|
|
111
|
+
- Summary displayed with file counts
|
|
112
|
+
- Ready for audit steps
|
|
113
|
+
|
|
114
|
+
## NEXT STEP:
|
|
115
|
+
Based on {scope}:
|
|
116
|
+
- `all` or `nav` → proceed to `./step-01-nav-audit.md`
|
|
117
|
+
- `crud` → skip to `./step-02-crud-audit.md`
|
|
118
|
+
- `perm` → skip to `./step-03-perm-audit.md`
|
|
119
|
+
- `route` → skip to `./step-04-route-audit.md`
|