@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.
- package/.documentation/agents.html +5 -1
- package/.documentation/apex.html +644 -0
- package/.documentation/business-analyse.html +81 -1
- package/.documentation/cli-commands.html +5 -1
- package/.documentation/commands.html +5 -1
- package/.documentation/efcore.html +5 -1
- package/.documentation/gitflow.html +5 -1
- package/.documentation/hooks.html +5 -1
- package/.documentation/index.html +60 -2
- package/.documentation/init.html +414 -1
- package/.documentation/installation.html +5 -1
- package/.documentation/ralph-loop.html +365 -216
- package/.documentation/test-web.html +5 -1
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +7 -24
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -2
- package/templates/agents/ba-writer.md +142 -15
- package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
- package/templates/skills/apex/SKILL.md +9 -3
- package/templates/skills/apex/_shared.md +49 -4
- package/templates/skills/{ralph-loop → apex}/references/core-seed-data.md +20 -11
- package/templates/skills/{ralph-loop → apex}/references/error-classification.md +2 -1
- package/templates/skills/apex/references/post-checks.md +463 -3
- package/templates/skills/apex/references/smartstack-api.md +76 -8
- package/templates/skills/apex/references/smartstack-frontend.md +74 -1
- package/templates/skills/apex/references/smartstack-layers.md +21 -3
- package/templates/skills/apex/steps/step-00-init.md +121 -1
- package/templates/skills/apex/steps/step-01-analyze.md +58 -0
- package/templates/skills/apex/steps/step-02-plan.md +36 -0
- package/templates/skills/apex/steps/step-03-execute.md +114 -7
- package/templates/skills/apex/steps/step-04-examine.md +116 -2
- package/templates/skills/business-analyse/SKILL.md +31 -20
- package/templates/skills/business-analyse/_module-loop.md +68 -9
- package/templates/skills/business-analyse/_shared.md +80 -21
- package/templates/skills/business-analyse/questionnaire/00-application.md +4 -2
- package/templates/skills/business-analyse/questionnaire/00b-project.md +85 -0
- package/templates/skills/business-analyse/references/deploy-modes.md +69 -0
- package/templates/skills/business-analyse/references/team-orchestration.md +158 -7
- package/templates/skills/business-analyse/schemas/application-schema.json +15 -1
- package/templates/skills/business-analyse/schemas/project-schema.json +490 -0
- package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +220 -38
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +184 -5
- package/templates/skills/business-analyse/steps/step-01b-applications.md +423 -0
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +23 -6
- package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +32 -7
- package/templates/skills/business-analyse/steps/step-04a-collect.md +111 -0
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +296 -103
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +46 -14
- package/templates/skills/documentation/SKILL.md +92 -2
- package/templates/skills/ralph-loop/SKILL.md +14 -17
- package/templates/skills/ralph-loop/references/category-rules.md +63 -683
- package/templates/skills/ralph-loop/references/compact-loop.md +188 -428
- package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +13 -14
- package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
- package/templates/skills/ralph-loop/steps/step-02-execute.md +80 -691
- package/templates/skills/ralph-loop/steps/step-03-commit.md +38 -79
- package/templates/skills/ralph-loop/steps/step-04-check.md +39 -58
- package/templates/skills/ralph-loop/steps/step-05-report.md +31 -123
- package/scripts/health-check.sh +0 -168
- package/scripts/postinstall.js +0 -18
|
@@ -1,116 +1,75 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: step-03-commit
|
|
3
|
-
description: Commit
|
|
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
|
|
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
|
|
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
|
-
###
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
###
|
|
35
|
+
### 2. Update progress.txt
|
|
100
36
|
|
|
101
|
-
Append iteration
|
|
37
|
+
Append iteration summary (compact):
|
|
102
38
|
```markdown
|
|
103
|
-
## Iteration {iteration} —
|
|
104
|
-
Status: {status} |
|
|
105
|
-
|
|
39
|
+
## Iteration {iteration} — Delegated to /apex
|
|
40
|
+
Status: {status} | Completed: {completed}/{total}
|
|
41
|
+
Module: {current_module}
|
|
106
42
|
```
|
|
107
43
|
|
|
108
|
-
###
|
|
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
|
-
|
|
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
|
|
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.
|
|
28
|
+
### 1.5. Lightweight Sanity Check
|
|
29
29
|
|
|
30
|
-
**
|
|
31
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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(
|
|
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
|
|
105
|
-
cat === 'test' ? 'Unit + integration
|
|
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(`
|
|
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
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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 →
|
|
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
|
|
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.
|
|
56
|
+
### 1c. Test Metrics (from PRD)
|
|
57
57
|
|
|
58
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
|
214
|
-
|
|
|
215
|
-
|
|
|
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
|
```
|