@atlashub/smartstack-cli 3.33.0 → 3.35.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 (65) hide show
  1. package/.documentation/agents.html +5 -1
  2. package/.documentation/apex.html +644 -0
  3. package/.documentation/business-analyse.html +81 -1
  4. package/.documentation/cli-commands.html +5 -1
  5. package/.documentation/commands.html +5 -1
  6. package/.documentation/efcore.html +5 -1
  7. package/.documentation/gitflow.html +5 -1
  8. package/.documentation/hooks.html +5 -1
  9. package/.documentation/index.html +60 -2
  10. package/.documentation/init.html +414 -1
  11. package/.documentation/installation.html +5 -1
  12. package/.documentation/ralph-loop.html +365 -216
  13. package/.documentation/test-web.html +5 -1
  14. package/dist/index.js +32 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/mcp-entry.mjs +7 -24
  17. package/dist/mcp-entry.mjs.map +1 -1
  18. package/package.json +1 -2
  19. package/templates/agents/ba-writer.md +142 -15
  20. package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
  21. package/templates/skills/apex/SKILL.md +9 -3
  22. package/templates/skills/apex/_shared.md +49 -4
  23. package/templates/skills/{ralph-loop → apex}/references/core-seed-data.md +20 -11
  24. package/templates/skills/{ralph-loop → apex}/references/error-classification.md +2 -1
  25. package/templates/skills/apex/references/post-checks.md +463 -3
  26. package/templates/skills/apex/references/smartstack-api.md +76 -8
  27. package/templates/skills/apex/references/smartstack-frontend.md +74 -1
  28. package/templates/skills/apex/references/smartstack-layers.md +21 -3
  29. package/templates/skills/apex/steps/step-00-init.md +121 -1
  30. package/templates/skills/apex/steps/step-01-analyze.md +58 -0
  31. package/templates/skills/apex/steps/step-02-plan.md +36 -0
  32. package/templates/skills/apex/steps/step-03-execute.md +114 -7
  33. package/templates/skills/apex/steps/step-04-examine.md +116 -2
  34. package/templates/skills/business-analyse/SKILL.md +31 -20
  35. package/templates/skills/business-analyse/_module-loop.md +68 -9
  36. package/templates/skills/business-analyse/_shared.md +80 -21
  37. package/templates/skills/business-analyse/questionnaire/00-application.md +4 -2
  38. package/templates/skills/business-analyse/questionnaire/00b-project.md +85 -0
  39. package/templates/skills/business-analyse/references/deploy-modes.md +69 -0
  40. package/templates/skills/business-analyse/references/team-orchestration.md +158 -7
  41. package/templates/skills/business-analyse/schemas/application-schema.json +15 -1
  42. package/templates/skills/business-analyse/schemas/project-schema.json +490 -0
  43. package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -1
  44. package/templates/skills/business-analyse/steps/step-00-init.md +220 -38
  45. package/templates/skills/business-analyse/steps/step-01-cadrage.md +184 -5
  46. package/templates/skills/business-analyse/steps/step-01b-applications.md +423 -0
  47. package/templates/skills/business-analyse/steps/step-02-decomposition.md +23 -6
  48. package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
  49. package/templates/skills/business-analyse/steps/step-03d-validate.md +32 -7
  50. package/templates/skills/business-analyse/steps/step-04a-collect.md +111 -0
  51. package/templates/skills/business-analyse/steps/step-05a-handoff.md +296 -103
  52. package/templates/skills/business-analyse/steps/step-05b-deploy.md +46 -14
  53. package/templates/skills/documentation/SKILL.md +92 -2
  54. package/templates/skills/ralph-loop/SKILL.md +14 -17
  55. package/templates/skills/ralph-loop/references/category-rules.md +63 -683
  56. package/templates/skills/ralph-loop/references/compact-loop.md +188 -428
  57. package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
  58. package/templates/skills/ralph-loop/references/team-orchestration.md +13 -14
  59. package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
  60. package/templates/skills/ralph-loop/steps/step-02-execute.md +80 -691
  61. package/templates/skills/ralph-loop/steps/step-03-commit.md +38 -79
  62. package/templates/skills/ralph-loop/steps/step-04-check.md +39 -58
  63. package/templates/skills/ralph-loop/steps/step-05-report.md +31 -123
  64. package/scripts/health-check.sh +0 -168
  65. package/scripts/postinstall.js +0 -18
@@ -1,116 +1,75 @@
1
1
  ---
2
2
  name: step-03-commit
3
- description: Commit changes, update prd.json v2 with full tracking
3
+ description: Commit PRD state after apex delegation
4
4
  next_step: steps/step-04-check.md
5
5
  ---
6
6
 
7
- # Step 3: Commit Changes
7
+ # Step 3: Commit PRD State
8
8
 
9
9
  > **CONTEXT OPTIMIZATION:** Read ONCE (first iteration). Subsequent iterations use compact-loop.md.
10
10
 
11
11
  ## YOUR TASK:
12
12
 
13
- Commit changes, finalize task tracking in prd.json, append to history.
13
+ Commit PRD state changes after apex delegation. Apex already committed code — ralph commits orchestration state only.
14
14
 
15
15
  ---
16
16
 
17
17
  ## EXECUTION SEQUENCE:
18
18
 
19
- ### 0. Pre-Commit Validation (BLOCKING)
20
-
21
- ```bash
22
- # Backend: build must pass
23
- if [ "{current_task_category}" != "frontend" ] && [ "{current_task_category}" != "i18n" ]; then
24
- dotnet build --no-restore --verbosity quiet
25
- fi
26
-
27
- # Frontend: typecheck + lint must pass
28
- if [ "{current_task_category}" = "frontend" ]; then
29
- npm run typecheck && npm run lint
30
- fi
31
-
32
- # Tests: full suite if test project exists
33
- TEST_PROJECT="tests/$(basename $(pwd)).Tests.Unit"
34
- if [ -d "$TEST_PROJECT" ]; then
35
- dotnet test "$TEST_PROJECT" --no-build --verbosity minimal
36
- if [ $? -ne 0 ]; then
37
- echo "COMMIT BLOCKED: tests failing. Fix before committing."
38
- STOP — return to step-02
39
- fi
40
- fi
41
- ```
42
-
43
- ### 1. Stage and Commit
44
-
45
- ```bash
46
- git add {files_created} {files_modified} .ralph/prd.json
47
- git commit -m "$(cat <<'EOF'
48
- {PREFIX}({scope}): {current_task_description}
49
-
50
- Task {current_task_id}/{tasks_total} - Iteration {current_iteration}
51
- Category: {current_task_category}
52
- {current_module ? "Module: " + current_module : ""}
53
-
54
- Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
55
- EOF
56
- )"
57
-
58
- COMMIT_HASH=$(git rev-parse --short HEAD)
59
- ```
60
-
61
- **Prefix mapping:**
62
-
63
- | Category | Prefix |
64
- |----------|--------|
65
- | domain, application, api, frontend | `feat` |
66
- | infrastructure | `db` |
67
- | i18n | `chore` |
68
- | test | `test` |
69
- | validation, other | `chore` |
70
-
71
- ### 2. Finalize Task in prd.json
19
+ ### 1. Finalize Task in prd.json
72
20
 
73
21
  ```javascript
74
22
  const prd = readJSON('.ralph/prd.json');
75
- const task = prd.tasks.find(t => t.id === {current_task_id});
76
23
  const now = new Date().toISOString();
77
24
 
78
- if (task.status !== 'failed') task.status = 'completed';
79
- task.completed_at = now;
80
- task.iteration = prd.config.current_iteration;
81
- task.commit_hash = COMMIT_HASH;
82
-
83
- prd.history.push({
84
- iteration: prd.config.current_iteration, task_id: task.id,
85
- action: task.status, timestamp: now, commit_hash: COMMIT_HASH,
86
- duration_seconds: Math.round((new Date(now) - new Date(task.started_at)) / 1000),
87
- notes: "{What was accomplished}"
88
- });
25
+ // Apex updates individual task statuses. Ralph updates overall PRD state.
26
+ const allDone = prd.tasks.every(t => t.status === 'completed' || t.status === 'skipped');
27
+ prd.status = allDone ? 'completed' : prd.tasks.some(t => t.status === 'failed' || t.status === 'blocked') ? 'partial' : 'in_progress';
89
28
 
90
29
  prd.config.current_iteration++;
91
30
  prd.updated_at = now;
92
31
 
93
- const allDone = prd.tasks.every(t => t.status === 'completed' || t.status === 'skipped');
94
- prd.status = allDone ? 'completed' : prd.tasks.some(t => t.status === 'failed' || t.status === 'blocked') ? 'partial' : 'in_progress';
95
-
96
32
  writeJSON('.ralph/prd.json', prd);
97
33
  ```
98
34
 
99
- ### 3. Update progress.txt
35
+ ### 2. Update progress.txt
100
36
 
101
- Append iteration learnings (compact):
37
+ Append iteration summary (compact):
102
38
  ```markdown
103
- ## Iteration {iteration} — [{id}] {description}
104
- Status: {status} | Commit: {hash} | Files: {count}
105
- Learnings: {what was learned}
39
+ ## Iteration {iteration} — Delegated to /apex
40
+ Status: {status} | Completed: {completed}/{total}
41
+ Module: {current_module}
106
42
  ```
107
43
 
108
- ### 4. Commit Progress Files
44
+ ### 3. Stage and Commit (PRD state only)
109
45
 
110
46
  ```bash
111
47
  git add .ralph/prd.json .ralph/progress.txt
112
48
  [ -f .ralph/modules-queue.json ] && git add .ralph/modules-queue.json
113
- git commit -m "chore(ralph): progress — task {id}/{total}"
49
+
50
+ git commit -m "$(cat <<'EOF'
51
+ chore(ralph): PRD state — iteration {iteration}, {completed}/{total} tasks
52
+
53
+ Module: {current_module}
54
+
55
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
56
+ EOF
57
+ )"
58
+
59
+ COMMIT_HASH=$(git rev-parse --short HEAD)
60
+ ```
61
+
62
+ ### 4. Record Commit in History
63
+
64
+ ```javascript
65
+ prd.history.push({
66
+ iteration: prd.config.current_iteration - 1,
67
+ action: 'iteration-completed',
68
+ timestamp: now,
69
+ commit_hash: COMMIT_HASH,
70
+ notes: "Delegated to /apex"
71
+ });
72
+ writeJSON('.ralph/prd.json', prd);
114
73
  ```
115
74
 
116
75
  ### 5. Verify
@@ -124,7 +83,7 @@ git log -2 --oneline
124
83
  ## ERROR HANDLING:
125
84
 
126
85
  - **Commit fails (pre-commit hook):** Fix issue, stage, create NEW commit (don't amend)
127
- - **Task failed in step-02:** Still commit partial progress, status stays "failed"
86
+ - **Task failed in apex:** PRD already reflects failure status commit as-is
128
87
 
129
88
  ---
130
89
 
@@ -25,49 +25,21 @@ const tasksTotal = prd.tasks.length;
25
25
  const allDone = (tasksCompleted + tasksSkipped) === tasksTotal;
26
26
  ```
27
27
 
28
- ### 1.5. Regression Check (BLOCKING)
28
+ ### 1.5. Lightweight Sanity Check
29
29
 
30
- **Backend build + tests:**
31
- ```bash
32
- dotnet build --no-restore
33
- if [ $? -ne 0 ]; then
34
- echo "BUILD REGRESSION — creating fix task"
35
- # Inject fix task, category: validation, acceptance: "dotnet build passes"
36
- fi
37
-
38
- TEST_PROJECT="tests/$(basename $(pwd)).Tests.Unit"
39
- if [ -d "$TEST_PROJECT" ]; then
40
- dotnet test "$TEST_PROJECT" --no-build --verbosity normal
41
- if [ $? -ne 0 ]; then
42
- echo "TEST REGRESSION — creating fix task"
43
- prd.tasks.push({ id: maxId+1, description: "Fix test regression — all tests must pass",
44
- status: "pending", category: "validation", dependencies: [],
45
- acceptance_criteria: "dotnet test exits 0, all tests pass" });
46
- writeJSON('.ralph/prd.json', prd);
47
- fi
48
- else
49
- # CRITICAL: Test project MUST exist if test tasks are marked completed
50
- const testTasksDone = prd.tasks.filter(t => t.category === 'test' && t.status === 'completed');
51
- if (testTasksDone.length > 0) {
52
- echo "ARTIFACT MISSING — test tasks marked completed but no test project exists"
53
- // Reset test tasks to pending and inject guardrail
54
- testTasksDone.forEach(t => { t.status = 'pending'; t.error = null; t.completed_at = null; });
55
- writeJSON('.ralph/prd.json', prd);
56
- fi
57
- fi
58
- ```
30
+ > **Note:** Full build verification, POST-CHECKs, and test runs are handled by apex.
31
+ > Ralph only does a lightweight sanity check to detect regressions between apex invocations.
59
32
 
60
- **Frontend — typecheck + lint:**
61
33
  ```bash
62
- if [ -f "web/package.json" ] || [ -f "package.json" ]; then
63
- npm run typecheck
64
- if [ $? -ne 0 ]; then
65
- echo "FRONTEND REGRESSION creating fix task"
66
- prd.tasks.push({ id: maxId+1, description: "Fix frontend typecheck errors",
67
- status: "pending", category: "frontend", dependencies: [],
68
- acceptance_criteria: "npm run typecheck exits 0" });
69
- writeJSON('.ralph/prd.json', prd);
70
- fi
34
+ # Quick build check (quiet mode)
35
+ dotnet build --no-restore --verbosity quiet
36
+ if [ $? -ne 0 ]; then
37
+ echo "BUILD REGRESSION detected between apex invocations"
38
+ # Inject fix task apex will handle the actual fix
39
+ prd.tasks.push({ id: maxId+1, description: "Fix build regression",
40
+ status: "pending", category: "validation", dependencies: [],
41
+ acceptance_criteria: "dotnet build passes" });
42
+ writeJSON('.ralph/prd.json', prd);
71
43
  fi
72
44
  ```
73
45
 
@@ -84,7 +56,7 @@ const REQUIRED_CATEGORIES = ['domain', 'infrastructure', 'application', 'api', '
84
56
  const missingFromPrd = REQUIRED_CATEGORIES.filter(c => !presentCategories.has(c));
85
57
 
86
58
  if (missingFromPrd.length > 0) {
87
- console.warn(`⚠ PRD MISSING CATEGORIES: ${missingFromPrd.join(', ')}`);
59
+ console.warn(`PRD MISSING CATEGORIES: ${missingFromPrd.join(', ')}`);
88
60
 
89
61
  // Inject guardrail tasks for missing categories
90
62
  let maxIdNum = Math.max(...prd.tasks.map(t => parseInt(t.id.replace(/[^0-9]/g, ''), 10) || 0));
@@ -101,14 +73,14 @@ if (missingFromPrd.length > 0) {
101
73
  status: 'pending', category: cat,
102
74
  dependencies: lastSeedDataTask ? [lastSeedDataTask] : (lastApiTask ? [lastApiTask] : []),
103
75
  acceptance_criteria: [
104
- cat === 'frontend' ? 'React pages + routes wired to App.tsx (standard + tenant blocks)' :
105
- cat === 'test' ? 'Unit + integration test projects with passing dotnet test' :
76
+ cat === 'frontend' ? 'React pages + routes wired to App.tsx' :
77
+ cat === 'test' ? 'Unit + integration tests passing' :
106
78
  `${cat} layer complete`
107
79
  ],
108
80
  started_at: null, completed_at: null, iteration: null,
109
81
  commit_hash: null, files_changed: [], validation: null, error: null
110
82
  });
111
- console.log(` Injected [${taskId}] ${cat} guardrail`);
83
+ console.log(` Injected [${taskId}] ${cat} guardrail`);
112
84
  }
113
85
  writeJSON('.ralph/prd.json', prd);
114
86
 
@@ -158,13 +130,11 @@ If `allDone`:
158
130
 
159
131
  ```javascript
160
132
  if ({team_active}) {
161
- // Signal team lead that this module is done
162
133
  SendMessage({
163
134
  type: "message", recipient: "team-lead",
164
135
  content: `MODULE_COMPLETE:${current_module}`,
165
136
  summary: `${current_module} complete`
166
137
  });
167
- // STOP — team lead manages next module
168
138
  return;
169
139
  }
170
140
  ```
@@ -177,14 +147,12 @@ if (fileExists(queuePath)) {
177
147
  const queue = readJSON(queuePath);
178
148
  const currentModule = queue.modules[queue.currentIndex];
179
149
 
180
- // MODULE COMPLETENESS CHECK (lightweight — heavy check already done in section 1.7)
181
- // Verify all expected layers have completed tasks
150
+ // MODULE COMPLETENESS CHECK
182
151
  const completedCats = new Set(prd.tasks.filter(t => t.status === 'completed').map(t => t.category));
183
152
  const expected = ['domain', 'infrastructure', 'application', 'api', 'seedData', 'frontend', 'test'];
184
153
  const missing = expected.filter(c => !completedCats.has(c));
185
154
 
186
155
  if (missing.length > 0) {
187
- // Section 1.7 should have injected guardrails already — fall through to compact loop
188
156
  console.log(`Module ${currentModule.code}: missing categories ${missing.join(', ')} — continuing loop`);
189
157
  // Fall through to section 5 (compact loop)
190
158
  } else {
@@ -198,13 +166,11 @@ if (fileExists(queuePath)) {
198
166
  queue.modules[nextIndex].status = 'in-progress';
199
167
  writeJSON(queuePath, queue);
200
168
 
201
- // Create transition marker
202
169
  writeJSON('.ralph/module-changed.json', {
203
170
  fromModule: currentModule.code, toModule: queue.modules[nextIndex].code,
204
171
  timestamp: new Date().toISOString()
205
172
  });
206
173
 
207
- // Load next module PRD
208
174
  prd.status = 'completed';
209
175
  writeJSON('.ralph/prd.json', prd);
210
176
  const nextPrd = readJSON(queue.modules[nextIndex].prdFile);
@@ -235,11 +201,27 @@ Set `prd.status = 'completed'` → step-05.
235
201
 
236
202
  ## 4. Dead-End Check
237
203
 
238
- If `!hasPending && !allDone`: all remaining blocked/failed, no progress possible.
239
- ```
240
- DEAD-END: {completed} done, {failed} failed, {blocked} blocked
204
+ ```javascript
205
+ const hasPending = prd.tasks.some(t => t.status === 'pending');
206
+ const MAX_RETRIES = 3;
207
+
208
+ // Before declaring dead-end, check if any failed tasks have retries left
209
+ const retriableCount = prd.tasks.filter(t =>
210
+ t.status === 'failed' && (t._retryCount || 0) < MAX_RETRIES
211
+ ).length;
212
+
213
+ if (!hasPending && !allDone && retriableCount > 0) {
214
+ // NOT a dead-end — compact loop will reset failed tasks to pending
215
+ console.log(`${retriableCount} failed tasks have retries remaining — entering compact loop`);
216
+ // Fall through to section 5
217
+ } else if (!hasPending && !allDone && retriableCount === 0) {
218
+ // TRUE dead-end: all retries exhausted
219
+ console.log(`DEAD-END: ${tasksCompletedNow} done, ${tasksFailed} failed (retries exhausted), ${tasksBlocked} blocked`);
220
+ prd.status = 'failed';
221
+ writeJSON('.ralph/prd.json', prd);
222
+ // → step-05
223
+ }
241
224
  ```
242
- Set `prd.status = 'failed'` → step-05.
243
225
 
244
226
  ## 5. Compact Loop (MANDATORY — EXECUTE IMMEDIATELY)
245
227
 
@@ -251,7 +233,7 @@ Set `prd.status = 'failed'` → step-05.
251
233
  If `hasPending && iteration < max`:
252
234
 
253
235
  1. Read `references/compact-loop.md`
254
- 2. Execute sections A → B → C → D inline (find tasks → execute batch → commit → loop back)
236
+ 2. Execute sections A → B → C → D inline (find tasks → delegate to apex → commit PRD → loop back)
255
237
  3. **IMMEDIATELY** return to section 1 of THIS step (do NOT pause)
256
238
  4. Repeat until ALL tasks are complete, max iterations reached, or dead-end
257
239
 
@@ -260,14 +242,13 @@ If `hasPending && iteration < max`:
260
242
  ## CRITICAL RULES — EXECUTION GUARANTEE:
261
243
 
262
244
  - **NEVER** output completion promise unless ALL tasks done (all modules if multi)
263
- - **NEVER** delegate the loop to sub-agents (except team mode for multi-module)
264
245
  - **NEVER** stop between iterations — this is the CORE PROMISE of ralph-loop
265
246
  - **NEVER** ask the user "should I continue?" or "is this OK?" — JUST CONTINUE
266
247
  - **NEVER** pause to show intermediate results and wait for feedback
248
+ - **NEVER** generate code directly — ALWAYS delegate to /apex
267
249
  - **BATCH** same-category tasks (max 5)
268
250
  - **MODULE COMPLETENESS:** All layers must have completed tasks before advancing
269
251
  - **Only valid stop conditions:** all complete, max iterations, dead-end, or user Ctrl+C
270
- - **If you stop for any other reason, you have VIOLATED the execution guarantee.**
271
252
 
272
253
  ---
273
254
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: step-05-report
3
- description: Generate final report from prd.json structured data (v3 unified or v2 legacy)
3
+ description: Generate final report from prd.json structured data
4
4
  next_step: null
5
5
  ---
6
6
 
@@ -27,7 +27,7 @@ const stats = {
27
27
  }
28
28
  };
29
29
 
30
- // Aggregate files from all tasks
30
+ // Aggregate files from all tasks (populated by apex during execution)
31
31
  const filesCreated = [...new Set(prd.tasks.flatMap(t => t.files_changed?.created || []))];
32
32
  const filesModified = [...new Set(prd.tasks.flatMap(t => t.files_changed?.modified || []))];
33
33
  const totalDuration = prd.history.reduce((sum, h) => sum + (h.duration_seconds || 0), 0);
@@ -53,125 +53,14 @@ if (fileExists(queuePath)) {
53
53
  }
54
54
  ```
55
55
 
56
- ### 1c. Team Results Aggregation
56
+ ### 1c. Test Metrics (from PRD)
57
57
 
58
- ```javascript
59
- // If Agent Teams were used, results are already in per-module PRDs
60
- // Aggregate from moduleStats (same as 1b)
61
- ```
62
-
63
- ### 1d. Test Metrics
64
-
65
- ```bash
66
- TEST_PROJECT="tests/$(basename $(pwd)).Tests.Unit"
67
- if [ -d "$TEST_PROJECT" ]; then
68
- dotnet test "$TEST_PROJECT" --no-build --verbosity minimal
69
- # Parse total/passed/failed/skipped from output
70
- fi
71
- ```
72
-
73
- ### 1e. Frontend Quality Metrics (if frontend tasks were executed)
74
-
75
- ```bash
76
- WEB_SRC=$(find . -name "App.tsx" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
77
- if [ -n "$WEB_SRC" ]; then
78
- PAGE_DIR="$WEB_SRC/pages"
79
- HOOK_DIR="$WEB_SRC/hooks"
80
- COMP_DIR="$WEB_SRC/components"
81
- I18N_DIR="$WEB_SRC/i18n/locales"
82
-
83
- # Count metrics
84
- PAGE_COUNT=$(find "$PAGE_DIR" -name "*.tsx" ! -name "*.test.tsx" 2>/dev/null | wc -l)
85
- TEST_COUNT=$(find "$PAGE_DIR" -name "*.test.tsx" 2>/dev/null | wc -l)
86
- HOOK_COUNT=$(find "$HOOK_DIR" -name "*.ts" -o -name "*.tsx" 2>/dev/null | wc -l)
87
-
88
- # Quality checks
89
- RAW_TABLES=$(grep -rl '<table[\s>]' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | wc -l)
90
- HARDCODED_COLORS=$(grep -rl '(?:bg|text|border)-(?:red|blue|green|gray|slate)-\d{2,3}' "$PAGE_DIR" "$COMP_DIR" --include="*.tsx" 2>/dev/null | wc -l)
91
- CSS_VARS=$(grep -rl 'var(--' "$PAGE_DIR" "$COMP_DIR" --include="*.tsx" 2>/dev/null | wc -l)
92
- WINDOW_CONFIRM=$(grep -rl 'window\.confirm' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | wc -l)
93
- HARDCODED_TEXT=$(grep -rl '>\s*\(Create\|Edit\|Delete\|Save\|Cancel\)\s*<' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | wc -l)
94
- USE_TRANSLATION=$(grep -rl 'useTranslation' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | wc -l)
95
- SMART_TABLE=$(grep -rl 'SmartTable\|DataTable' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | wc -l)
96
-
97
- # i18n coverage
98
- I18N_LANGS=0
99
- for LANG in fr en it de; do
100
- [ -d "$I18N_DIR/$LANG" ] && I18N_LANGS=$((I18N_LANGS + 1))
101
- done
102
- fi
103
- ```
104
-
105
- Include frontend metrics in report section:
106
- ```markdown
107
- ## Frontend Quality
108
- | Metric | Value | Target |
109
- |--------|-------|--------|
110
- | Pages | {PAGE_COUNT} | — |
111
- | Tests | {TEST_COUNT} | ≥ {PAGE_COUNT/3} |
112
- | Hooks | {HOOK_COUNT} | — |
113
- | SmartTable/DataTable usage | {SMART_TABLE} files | All list pages |
114
- | Raw HTML tables | {RAW_TABLES} files | 0 |
115
- | CSS variable usage | {CSS_VARS} files | All TSX files |
116
- | Hardcoded colors | {HARDCODED_COLORS} files | 0 |
117
- | useTranslation() usage | {USE_TRANSLATION} files | All page files |
118
- | Hardcoded English text | {HARDCODED_TEXT} files | 0 |
119
- | window.confirm() usage | {WINDOW_CONFIRM} files | 0 |
120
- | i18n languages | {I18N_LANGS}/4 | 4 |
121
- ```
58
+ > **Note:** Apex already ran tests and recorded results. Source metrics from PRD task data.
122
59
 
123
- ### 1f. Final DB Validation (if infrastructure/migration tasks were executed)
124
-
125
- ```bash
126
- INFRA_PROJECT=$(ls src/*Infrastructure*/*.csproj 2>/dev/null | head -1)
127
- API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)
128
-
129
- if [ -n "$INFRA_PROJECT" ] && [ -n "$API_PROJECT" ]; then
130
- echo "FINAL DB VALIDATION: Applying all migrations on fresh SQL Server LocalDB..."
131
-
132
- # 1. Check no pending model changes
133
- dotnet ef migrations has-pending-model-changes \
134
- --project "$INFRA_PROJECT" \
135
- --startup-project "$API_PROJECT"
136
- PENDING_RESULT=$?
137
-
138
- # 2. Apply all migrations on temp database
139
- DB_NAME="SmartStack_FinalCheck_$(date +%s)"
140
- CONN_STRING="Server=(localdb)\\MSSQLLocalDB;Database=$DB_NAME;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=120;"
141
- dotnet ef database update \
142
- --connection "$CONN_STRING" \
143
- --project "$INFRA_PROJECT" \
144
- --startup-project "$API_PROJECT"
145
- MIGRATION_RESULT=$?
146
-
147
- # 3. Run integration tests against real SQL Server
148
- INT_TEST_PROJECT=$(ls tests/*Tests.Integration*/*.csproj 2>/dev/null | head -1)
149
- INT_TEST_RESULT=0
150
- if [ -n "$INT_TEST_PROJECT" ]; then
151
- dotnet test "$INT_TEST_PROJECT" --no-build --verbosity minimal
152
- INT_TEST_RESULT=$?
153
- fi
154
-
155
- # 4. Cleanup
156
- 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
157
-
158
- # Record results
159
- DB_VALIDATION="PASS"
160
- [ $PENDING_RESULT -ne 0 ] && DB_VALIDATION="FAIL (pending model changes)"
161
- [ $MIGRATION_RESULT -ne 0 ] && DB_VALIDATION="FAIL (migration apply failed)"
162
- [ $INT_TEST_RESULT -ne 0 ] && DB_VALIDATION="FAIL (integration tests failed on SQL Server)"
163
- fi
164
- ```
165
-
166
- Include DB validation results in report section:
167
- ```markdown
168
- ## DB Validation (SQL Server LocalDB)
169
- | Check | Result |
170
- |-------|--------|
171
- | Pending model changes | {PENDING_RESULT == 0 ? "PASS" : "FAIL"} |
172
- | Migrations apply cleanly | {MIGRATION_RESULT == 0 ? "PASS" : "FAIL"} |
173
- | Integration tests (real SQL Server) | {INT_TEST_RESULT == 0 ? "PASS" : "N/A"} |
174
- | Overall | {DB_VALIDATION} |
60
+ ```javascript
61
+ const testTasks = prd.tasks.filter(t => t.category === 'test');
62
+ const testsPassed = testTasks.filter(t => t.status === 'completed').length;
63
+ const testsFailed = testTasks.filter(t => t.status === 'failed').length;
175
64
  ```
176
65
 
177
66
  ## 2. Generate Report
@@ -188,6 +77,7 @@ Write to `.ralph/reports/{feature-slug}.md`:
188
77
  | Iterations | {iterations_used} / {max} |
189
78
  | Branch | {branch} |
190
79
  | Duration | {totalDuration}s ({min} min) |
80
+ | Execution | Delegated to /apex |
191
81
 
192
82
  ## Tasks
193
83
  | # | Task | Category | Status | Commit |
@@ -207,13 +97,21 @@ Write to `.ralph/reports/{feature-slug}.md`:
207
97
  **{completedModules}/{totalModules} modules completed**
208
98
  {end if}
209
99
 
100
+ {if prd._sectionSplit?.enabled:}
101
+ ## Section Split Execution
102
+ | Phase | Type | Section | Entities | Status |
103
+ |-------|------|---------|----------|--------|
104
+ {for each phase:}
105
+ | {phase} | {type} | {sectionCode || '-'} | {entities.length} | {status} |
106
+
107
+ {end if}
108
+
210
109
  ## Test Metrics
211
110
  | Metric | Value |
212
111
  |--------|-------|
213
- | Tests Executed | {yes/no} |
214
- | Status | {passed/failed} |
215
- | Total | {n} | Passed | {n} | Failed | {n} |
216
- | Coverage | {n}% |
112
+ | Test Tasks | {testTasks.length} |
113
+ | Passed | {testsPassed} |
114
+ | Failed | {testsFailed} |
217
115
 
218
116
  ## Failed Tasks
219
117
  {table of failed tasks with error messages, or "None"}
@@ -232,6 +130,16 @@ Write to `.ralph/reports/{feature-slug}.md`:
232
130
  ## 3. Finalize
233
131
 
234
132
  ```javascript
133
+ // Clean up section-split temporary files
134
+ if (prd._sectionSplit?.enabled) {
135
+ for (const phase of prd._sectionSplit.phases) {
136
+ if (fileExists(phase.prdFile) && phase.prdFile !== '.ralph/prd.json') {
137
+ deleteFile(phase.prdFile);
138
+ }
139
+ }
140
+ delete prd._sectionSplit;
141
+ }
142
+
235
143
  prd.updated_at = new Date().toISOString();
236
144
  writeJSON('.ralph/prd.json', prd);
237
145
  ```