@atlashub/smartstack-cli 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.documentation/agents.html +1 -371
  2. package/.documentation/cli-commands.html +1 -1
  3. package/.documentation/commands.html +1 -1
  4. package/.documentation/efcore.html +1 -1
  5. package/.documentation/gitflow.html +1 -1
  6. package/.documentation/hooks.html +27 -66
  7. package/.documentation/index.html +166 -166
  8. package/.documentation/init.html +6 -7
  9. package/.documentation/installation.html +1 -1
  10. package/.documentation/prd-json-v2.0.0.md +396 -0
  11. package/.documentation/ralph-loop.html +1 -9
  12. package/.documentation/test-web.html +15 -39
  13. package/.documentation/testing-ba-e2e.md +462 -0
  14. package/dist/index.js +23 -16
  15. package/dist/index.js.map +1 -1
  16. package/package.json +6 -2
  17. package/templates/agents/gitflow/merge.md +56 -6
  18. package/templates/agents/gitflow/pr.md +70 -9
  19. package/templates/project/appsettings.json.template +8 -2
  20. package/templates/skills/business-analyse/SKILL.md +34 -17
  21. package/templates/skills/business-analyse/html/ba-interactive.html +147 -84
  22. package/templates/skills/business-analyse/questionnaire.md +20 -15
  23. package/templates/skills/business-analyse/steps/step-00-init.md +80 -57
  24. package/templates/skills/business-analyse/steps/step-03-specify.md +57 -0
  25. package/templates/skills/business-analyse/steps/step-05-handoff.md +480 -14
  26. package/templates/skills/business-analyse/steps/step-06-extract.md +131 -3
  27. package/templates/skills/gitflow/steps/step-pr.md +17 -5
  28. package/templates/skills/ralph-loop/SKILL.md +158 -33
  29. package/templates/skills/ralph-loop/steps/step-01-task.md +160 -18
  30. package/templates/skills/ralph-loop/steps/step-02-execute.md +408 -23
  31. package/templates/skills/ralph-loop/steps/step-03-commit.md +82 -0
  32. package/templates/skills/ralph-loop/steps/step-04-check.md +305 -9
  33. package/templates/skills/ralph-loop/steps/step-05-report.md +115 -0
@@ -1,14 +1,19 @@
1
1
  ---
2
2
  name: step-02-execute
3
- description: Execute ONE task with dependency checks and rich tracking
3
+ description: Execute task(s) with dependency checks and rich tracking
4
4
  next_step: steps/step-03-commit.md
5
5
  ---
6
6
 
7
7
  # Step 2: Execute Task
8
8
 
9
+ > **CONTEXT OPTIMIZATION:** This file is only read ONCE (first iteration).
10
+ > After the first full iteration, ALL subsequent iterations use the COMPACT LOOP
11
+ > in step-04-check.md section 5 which includes inline execution.
12
+ > **DO NOT re-read this file for iterations > 1.**
13
+
9
14
  ## YOUR TASK:
10
15
 
11
- Execute exactly ONE task from prd.json. Do NOT batch multiple tasks.
16
+ Execute the current task(s) from prd.json. For the first iteration, execute ONE task. After the first iteration, the compact loop in step-04 handles batch execution.
12
17
 
13
18
  **ULTRA THINK about the implementation.**
14
19
 
@@ -16,12 +21,11 @@ Execute exactly ONE task from prd.json. Do NOT batch multiple tasks.
16
21
 
17
22
  ## EXECUTION RULES:
18
23
 
19
- 1. **ONE TASK ONLY** - Execute only `{current_task_description}`
20
- 2. **ATOMIC CHANGES** - Changes should be complete and working
21
- 3. **USE MCP** - Validate with SmartStack MCP as needed
22
- 4. **DOCUMENT** - Track what you're doing
23
- 5. **CHECK DEPENDENCIES** - Verify all dependencies are met before starting
24
- 6. **TRACK FILES** - Record every file created or modified
24
+ 1. **ATOMIC CHANGES** - Changes should be complete and working
25
+ 2. **USE MCP** - Validate with SmartStack MCP (once per batch, not per task)
26
+ 3. **TRACK FILES** - Record every file created or modified
27
+ 4. **CHECK DEPENDENCIES** - Verify all dependencies are met before starting
28
+ 5. **BATCH ALLOWED** - Multiple tasks of the same category can be batched (max 5)
25
29
 
26
30
  ---
27
31
 
@@ -81,6 +85,352 @@ writeJSON('.ralph/prd.json', prd);
81
85
  | `test` | `scaffold_tests`, `analyze_test_coverage` | xUnit, test naming conventions |
82
86
  | `validation` | `validate_conventions` | Build, test, lint checks |
83
87
 
88
+ **Test task guidance — TDD CYCLE (MANDATORY):**
89
+
90
+ > **CRITICAL:** Tests are NOT optional. Every feature MUST have tests that pass.
91
+ > The cycle is: Generate Code → Generate Tests → Run Tests → Fix Code → Re-run Tests → Pass.
92
+
93
+ When executing `test` category tasks, follow this EXACT sequence:
94
+
95
+ **1. ENSURE TEST PROJECT EXISTS (BLOCKING)**
96
+
97
+ ```bash
98
+ # Detect project name from solution
99
+ PROJECT_NAME=$(basename $(pwd))
100
+ TEST_PROJECT="tests/${PROJECT_NAME}.Tests.Unit"
101
+
102
+ if [ ! -d "$TEST_PROJECT" ]; then
103
+ echo "⚠️ Test project missing. Scaffolding now..."
104
+
105
+ # Create test project
106
+ dotnet new xunit -n "${PROJECT_NAME}.Tests.Unit" -o "$TEST_PROJECT"
107
+
108
+ # Add required packages
109
+ cd "$TEST_PROJECT"
110
+ dotnet add package Moq --version 4.20.72
111
+ dotnet add package FluentAssertions --version 8.3.0
112
+ dotnet add package Microsoft.Extensions.DependencyInjection --version 10.0.2
113
+ cd ../..
114
+
115
+ # Add project references to all src/ projects
116
+ for proj in src/*/*.csproj; do
117
+ dotnet add "$TEST_PROJECT" reference "$proj"
118
+ done
119
+
120
+ # Add test project to solution
121
+ dotnet sln add "$TEST_PROJECT/${PROJECT_NAME}.Tests.Unit.csproj"
122
+
123
+ echo "✅ Test project scaffolded at $TEST_PROJECT"
124
+ fi
125
+ ```
126
+
127
+ **2. GENERATE TESTS USING MCP (DO NOT WRITE MANUALLY)**
128
+
129
+ ```javascript
130
+ // Identify what to test based on task description
131
+ const task = prd.tasks.find(t => t.id === {current_task_id});
132
+ const testType = detectTestType(task.description); // "unit" | "integration" | "security"
133
+
134
+ // For domain tests
135
+ if (task.description.includes("domain entity") || task.description.includes("value object")) {
136
+ // Call MCP to scaffold domain tests
137
+ mcp__smartstack__scaffold_tests({
138
+ module: extractModuleName(task.description),
139
+ test_type: "unit",
140
+ target_layer: "domain",
141
+ target_file: identifyEntityFile(task.description)
142
+ });
143
+ }
144
+
145
+ // For service tests
146
+ if (task.description.includes("service")) {
147
+ mcp__smartstack__scaffold_tests({
148
+ module: extractModuleName(task.description),
149
+ test_type: "unit",
150
+ target_layer: "application",
151
+ target_file: identifyServiceFile(task.description)
152
+ });
153
+ }
154
+
155
+ // For controller tests
156
+ if (task.description.includes("controller") || task.description.includes("API")) {
157
+ mcp__smartstack__scaffold_tests({
158
+ module: extractModuleName(task.description),
159
+ test_type: "integration",
160
+ target_layer: "api",
161
+ target_file: identifyControllerFile(task.description)
162
+ });
163
+ }
164
+
165
+ // For security/permissions tests
166
+ if (task.description.includes("permission") || task.description.includes("security")) {
167
+ mcp__smartstack__scaffold_tests({
168
+ module: extractModuleName(task.description),
169
+ test_type: "security",
170
+ target_layer: "api",
171
+ target_file: identifyControllerFile(task.description)
172
+ });
173
+ }
174
+ ```
175
+
176
+ **3. RUN TESTS IMMEDIATELY (BLOCKING)**
177
+
178
+ ```bash
179
+ # Build test project first
180
+ dotnet build "$TEST_PROJECT" --no-restore
181
+
182
+ # Run tests with detailed output
183
+ dotnet test "$TEST_PROJECT" --no-build --verbosity normal
184
+
185
+ # Capture exit code
186
+ TEST_EXIT_CODE=$?
187
+ ```
188
+
189
+ **4. ANALYZE RESULTS AND IMPROVE (LOOP UNTIL GREEN)**
190
+
191
+ ```javascript
192
+ if (TEST_EXIT_CODE !== 0) {
193
+ echo "❌ Tests failed. Analyzing failures...";
194
+
195
+ // Parse test output to identify failures
196
+ const failures = parseTestFailures(testOutput);
197
+
198
+ // CRITICAL: DO NOT PROCEED. Fix the code.
199
+ for (const failure of failures) {
200
+ echo ` - ${failure.testName}: ${failure.reason}`;
201
+
202
+ // Identify what needs fixing
203
+ if (failure.reason.includes("NullReferenceException")) {
204
+ // Fix null handling in implementation
205
+ } else if (failure.reason.includes("Expected") && failure.reason.includes("Actual")) {
206
+ // Fix logic to match expected behavior
207
+ } else if (failure.reason.includes("NotImplementedException")) {
208
+ // Implement missing method
209
+ }
210
+ }
211
+
212
+ // After fixes, RE-RUN TESTS (step 3)
213
+ // LOOP until TEST_EXIT_CODE === 0
214
+
215
+ // If cannot fix after 3 attempts:
216
+ task.status = 'failed';
217
+ task.error = `Tests failed after 3 fix attempts: ${failures.map(f => f.testName).join(', ')}`;
218
+ // STOP - do not proceed to commit
219
+ }
220
+
221
+ if (TEST_EXIT_CODE === 0) {
222
+ echo "✅ All tests passed!";
223
+ {validation_result} = "passed";
224
+ }
225
+ ```
226
+
227
+ **5. VERIFY TEST COVERAGE (MANDATORY ≥80%)**
228
+
229
+ ```javascript
230
+ // Use MCP to analyze coverage
231
+ const coverage = mcp__smartstack__analyze_test_coverage({
232
+ project_path: process.cwd(),
233
+ module: extractModuleName(task.description)
234
+ });
235
+
236
+ if (coverage.percentage < 80) {
237
+ echo `⚠️ Test coverage ${coverage.percentage}% < 80% minimum`;
238
+ echo `Missing coverage for: ${coverage.uncovered_files.join(', ')}`;
239
+
240
+ // Generate additional tests for uncovered code
241
+ for (const file of coverage.uncovered_files) {
242
+ mcp__smartstack__scaffold_tests({
243
+ module: extractModuleName(task.description),
244
+ test_type: "unit",
245
+ target_file: file
246
+ });
247
+ }
248
+
249
+ // Re-run tests (go back to step 3)
250
+ }
251
+
252
+ echo `✅ Test coverage: ${coverage.percentage}% (${coverage.lines_covered}/${coverage.lines_total} lines)`;
253
+ ```
254
+
255
+ **6. TEST TASK COMPLETION CRITERIA**
256
+
257
+ A test task is ONLY complete when:
258
+ - ✅ Test project exists
259
+ - ✅ Tests generated via MCP (NOT manually written)
260
+ - ✅ `dotnet test` exits with code 0 (all tests pass)
261
+ - ✅ Test coverage ≥ 80%
262
+ - ✅ No `[Fact(Skip = "...")]` present (no skipped tests)
263
+
264
+ **If ANY criterion fails, task.status = 'failed' and DO NOT commit.**
265
+
266
+ **Validation task guidance — FINAL VERIFICATION (BLOCKING):**
267
+
268
+ > **CRITICAL:** The validation task is the LAST task in each module. It verifies the module is production-ready.
269
+
270
+ When executing `validation` category tasks, follow this EXACT sequence:
271
+
272
+ **1. CLEAN BUILD (MANDATORY)**
273
+
274
+ ```bash
275
+ echo "🔨 Running clean build..."
276
+
277
+ # Clean previous builds
278
+ dotnet clean --verbosity quiet
279
+
280
+ # Restore dependencies
281
+ dotnet restore --verbosity quiet
282
+
283
+ # Build entire solution
284
+ dotnet build --no-restore --verbosity normal
285
+
286
+ BUILD_EXIT_CODE=$?
287
+
288
+ if [ $BUILD_EXIT_CODE -ne 0 ]; then
289
+ echo "╔════════════════════════════════════════════════════════════╗"
290
+ echo "║ ❌ BUILD FAILED ║"
291
+ echo "╠════════════════════════════════════════════════════════════╣"
292
+ echo "║ The solution does not compile. ║"
293
+ echo "║ This indicates a critical error in the code. ║"
294
+ echo "╠════════════════════════════════════════════════════════════╣"
295
+ echo "║ CORRECTIVE ACTION: ║"
296
+ echo "║ 1. Review build errors above ║"
297
+ echo "║ 2. Fix compilation errors ║"
298
+ echo "║ 3. Re-run: dotnet build ║"
299
+ echo "║ 4. Once build succeeds, Ralph will continue ║"
300
+ echo "╚════════════════════════════════════════════════════════════╝"
301
+
302
+ task.status = 'failed';
303
+ task.error = 'Build failed. See build output for details.';
304
+ exit 1;
305
+ fi
306
+
307
+ echo "✅ Build succeeded";
308
+ ```
309
+
310
+ **2. RUN FULL TEST SUITE (MANDATORY)**
311
+
312
+ ```bash
313
+ echo "🧪 Running full test suite..."
314
+
315
+ PROJECT_NAME=$(basename $(pwd))
316
+ TEST_PROJECT="tests/${PROJECT_NAME}.Tests.Unit"
317
+
318
+ if [ ! -d "$TEST_PROJECT" ]; then
319
+ echo "⚠️ WARNING: No test project found at $TEST_PROJECT";
320
+ echo "This module has NO tests. This is NOT recommended.";
321
+ task.validation = "warning: no tests";
322
+ else
323
+ # Run ALL tests with detailed output
324
+ dotnet test "$TEST_PROJECT" --no-build --verbosity normal --logger "console;verbosity=detailed"
325
+
326
+ TEST_EXIT_CODE=$?
327
+
328
+ if [ $TEST_EXIT_CODE -ne 0 ]; then
329
+ echo "╔════════════════════════════════════════════════════════════╗"
330
+ echo "║ ❌ TESTS FAILED ║"
331
+ echo "╠════════════════════════════════════════════════════════════╣"
332
+ echo "║ One or more tests are failing. ║"
333
+ echo "║ The module is NOT production-ready. ║"
334
+ echo "╠════════════════════════════════════════════════════════════╣"
335
+ echo "║ CORRECTIVE ACTION: ║"
336
+ echo "║ 1. Review test failures above ║"
337
+ echo "║ 2. Fix the failing code or tests ║"
338
+ echo "║ 3. Re-run: dotnet test ║"
339
+ echo "║ 4. Once all tests pass, Ralph will continue ║"
340
+ echo "╚════════════════════════════════════════════════════════════╝"
341
+
342
+ task.status = 'failed';
343
+ task.error = 'Test suite failed. Module not production-ready.';
344
+ exit 1;
345
+ fi
346
+
347
+ echo "✅ All tests passed";
348
+ fi
349
+ ```
350
+
351
+ **3. MCP VALIDATION (MANDATORY)**
352
+
353
+ ```javascript
354
+ echo "🔍 Running MCP validation...";
355
+
356
+ // Validate SmartStack conventions
357
+ const validation = mcp__smartstack__validate_conventions({
358
+ checks: ["all"]
359
+ });
360
+
361
+ if (validation.status === "error" || validation.errors.length > 0) {
362
+ echo "❌ MCP validation failed:";
363
+ for (const error of validation.errors) {
364
+ echo ` - ${error.file}: ${error.message}`;
365
+ }
366
+
367
+ task.status = 'failed';
368
+ task.error = `MCP validation failed: ${validation.errors.length} error(s)`;
369
+ exit 1;
370
+ }
371
+
372
+ if (validation.warnings.length > 0) {
373
+ echo "⚠️ MCP validation warnings:";
374
+ for (const warning of validation.warnings) {
375
+ echo ` - ${warning.file}: ${warning.message}`;
376
+ }
377
+ task.validation = `passed with ${validation.warnings.length} warning(s)`;
378
+ } else {
379
+ task.validation = "passed";
380
+ }
381
+
382
+ echo "✅ MCP validation passed";
383
+ ```
384
+
385
+ **4. GENERATE VALIDATION REPORT**
386
+
387
+ ```javascript
388
+ const report = {
389
+ module: {current_module},
390
+ build: { status: "success", duration: buildDuration },
391
+ tests: {
392
+ status: TEST_EXIT_CODE === 0 ? "success" : "failed",
393
+ total: testStats.total,
394
+ passed: testStats.passed,
395
+ failed: testStats.failed,
396
+ skipped: testStats.skipped,
397
+ duration: testStats.duration,
398
+ coverage: coverage.percentage
399
+ },
400
+ mcp: {
401
+ status: validation.status,
402
+ errors: validation.errors.length,
403
+ warnings: validation.warnings.length
404
+ },
405
+ production_ready: (BUILD_EXIT_CODE === 0 && TEST_EXIT_CODE === 0 && validation.errors.length === 0)
406
+ };
407
+
408
+ // Append to progress.txt
409
+ const progressEntry = `
410
+ ╔═══════════════════════════════════════════════════════════════╗
411
+ ║ MODULE VALIDATION REPORT - ${current_module}
412
+ ╠═══════════════════════════════════════════════════════════════╣
413
+ ║ Build: ${report.build.status.toUpperCase()}
414
+ ║ Tests: ${report.tests.passed}/${report.tests.total} passed (${report.tests.coverage}% coverage)
415
+ ║ MCP: ${report.mcp.status.toUpperCase()} (${report.mcp.errors} errors, ${report.mcp.warnings} warnings)
416
+ ║ Production Ready: ${report.production_ready ? "YES ✅" : "NO ❌"}
417
+ ╚═══════════════════════════════════════════════════════════════╝
418
+ `;
419
+ appendToFile('.ralph/progress.txt', progressEntry);
420
+
421
+ echo progressEntry;
422
+ ```
423
+
424
+ **5. VALIDATION TASK COMPLETION CRITERIA**
425
+
426
+ A validation task is ONLY complete when:
427
+ - ✅ `dotnet build` exits with code 0
428
+ - ✅ `dotnet test` exits with code 0 (or no test project + warning logged)
429
+ - ✅ MCP `validate_conventions` has 0 errors
430
+ - ✅ Production ready = true
431
+
432
+ **If ANY criterion fails, task.status = 'failed', module is NOT production-ready, and Ralph STOPS.**
433
+
84
434
  **Infrastructure task guidance (MANDATORY directory conventions):**
85
435
 
86
436
  When executing `infrastructure` category tasks, follow these rules strictly:
@@ -108,26 +458,61 @@ When executing `infrastructure` category tasks, follow these rules strictly:
108
458
  - Use `SqlObjectHelper.cs` for embedded resource loading
109
459
  - Use `CREATE OR ALTER` in SQL files for idempotency
110
460
 
111
- **Frontend task guidance (MANDATORY Layout wrapper):**
461
+ **Frontend task guidance — MCP-FIRST PROTOCOL (MANDATORY):**
462
+
463
+ > **CRITICAL:** Frontend code is generated via MCP tools, NOT written from scratch.
464
+ > Writing plain HTML tables, custom div cards, or hardcoded Tailwind is FORBIDDEN.
465
+ > The MCP tools produce SmartStack-compliant code automatically.
112
466
 
113
- When executing `frontend` category tasks, follow these rules strictly:
467
+ **Execution sequence for frontend tasks (follow IN ORDER):**
114
468
 
115
- 1. **Routes MUST be inside Layout wrapper** (CRITICAL - violating this breaks the entire UI shell)
116
- - All routes MUST be nested inside the appropriate context Layout component
117
- - `platform.*` `<Route path="/platform" element={<AdminLayout />}>` children
118
- - `business.*` → `<Route path="/business" element={<BusinessLayout />}>` children
119
- - `personal.*` → `<Route path="/personal/myspace" element={<UserLayout />}>` children
120
- - **If routes are placed OUTSIDE the layout wrapper: header, sidebar, and AvatarMenu will NOT render**
121
- - NEVER create flat routes at the top level of `<Routes>`
469
+ 1. **Call `mcp__smartstack__scaffold_api_client`** FIRST
470
+ - Generates: `{entity}Api.ts` with type-safe CRUD methods + React Query hook
471
+ - Uses `apiClient` (NOT axios), NavRoute integration, permission checking
472
+ - Output: `src/services/api/{module}Api.ts`
122
473
 
123
- 2. **Nested routes, NOT flat routes**
124
- - Use `<Route path="application"><Route path="module" element={...} /></Route>` pattern
125
- - NEVER use `<Route path="/context/application/module" element={...} />` (flat)
126
- - Use `<Route index element={<Navigate to="default" replace />} />` for default redirects
474
+ 2. **Call `mcp__smartstack__scaffold_routes`** (source: "controllers", scope: "all")
475
+ - Updates: `navRoutes.generated.ts` + route config in App.tsx
476
+ - Generates: Nested routes INSIDE correct Layout wrapper
477
+ - Context mapping: `business.*` `BusinessLayout`, `platform.*` `AdminLayout`
127
478
 
128
- 3. **Tenant-prefixed routes** - If `/t/:slug/` block exists, add routes there too
479
+ 3. **Create pages using SmartStack components** (reference: `templates-frontend.md`)
480
+ - **List pages**: Use `SmartTable` (NOT HTML `<table>`), `SmartFilter`, `EntityCard` for grid view
481
+ - **Detail pages**: Use `EntityDetailCard`, `StatusBadge`, tab layout
482
+ - **Create/Edit pages**: Use `SmartForm` with `FluentValidation`-backed fields, tab layout
483
+ - **Dashboard pages**: Use `StatCard`, Recharts components
484
+ - Match wireframes from feature.json `specification.uiWireframes[]`
485
+
486
+ 4. **Create preferences hook**: `use{Module}Preferences.ts`
487
+ - pageSize, sortColumn, sortDirection, visibleColumns, viewMode, filters
488
+
489
+ 5. **Generate i18n** (4 languages: fr, en, it, de)
490
+ - All UI labels, validation messages, button text, empty states
491
+
492
+ 6. **Post-generation validation (BLOCKING)**:
493
+ - `npm run typecheck` MUST pass
494
+ - NO hardcoded colors (scan for `bg-blue-`, `text-gray-`, etc.)
495
+ - CSS variables ONLY: `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`
496
+ - Routes are NESTED and INSIDE Layout wrapper
497
+ - All pages have loading/error/empty states
498
+ - API client uses `@/services/api/apiClient` (NOT `import axios`)
499
+ - `EntityCard` for grid views (NOT custom `<div>` cards)
500
+
501
+ **FORBIDDEN patterns (any of these = FAIL the task):**
502
+ ```
503
+ import axios from 'axios' → use @/services/api/apiClient
504
+ <table>...</table> → use SmartTable component
505
+ <div className="bg-blue-600"> → use bg-[var(--color-accent-600)]
506
+ <Route path="/business/app/mod" /> → MUST be nested inside BusinessLayout
507
+ Only fr/en translations → MUST have 4 languages (fr, en, it, de)
508
+ ```
129
509
 
130
- 4. **See `/application` skill templates-frontend.md** for full template patterns
510
+ **Layout wrapper mapping:**
511
+ | Context | Layout | Route path |
512
+ |---------|--------|------------|
513
+ | `platform.*` | `AdminLayout` | `/platform` |
514
+ | `business.*` | `BusinessLayout` | `/business` |
515
+ | `personal.*` | `UserLayout` | `/personal/myspace` |
131
516
 
132
517
  **API/Controller task guidance (MANDATORY folder hierarchy):**
133
518
 
@@ -6,6 +6,11 @@ next_step: steps/step-04-check.md
6
6
 
7
7
  # Step 3: Commit Changes
8
8
 
9
+ > **CONTEXT OPTIMIZATION:** This file is only read ONCE (first iteration).
10
+ > After the first full iteration, ALL subsequent iterations use the COMPACT LOOP
11
+ > in step-04-check.md section 5 which includes inline commit logic.
12
+ > **DO NOT re-read this file for iterations > 1.**
13
+
9
14
  ## YOUR TASK:
10
15
 
11
16
  Commit the changes from the executed task, finalize task tracking in prd.json, and append to history.
@@ -14,6 +19,83 @@ Commit the changes from the executed task, finalize task tracking in prd.json, a
14
19
 
15
20
  ## EXECUTION SEQUENCE:
16
21
 
22
+ ### 0. PRE-COMMIT VALIDATION (BLOCKING)
23
+
24
+ **CRITICAL: Before ANY commit, verify all tests pass.**
25
+
26
+ ```bash
27
+ # Check if test project exists
28
+ PROJECT_NAME=$(basename $(pwd))
29
+ TEST_PROJECT="tests/${PROJECT_NAME}.Tests.Unit"
30
+
31
+ if [ -d "$TEST_PROJECT" ]; then
32
+ echo "Running full test suite before commit..."
33
+
34
+ # Run ALL tests (not just current task's tests)
35
+ dotnet test "$TEST_PROJECT" --no-build --verbosity minimal
36
+
37
+ TEST_EXIT_CODE=$?
38
+
39
+ if [ $TEST_EXIT_CODE -ne 0 ]; then
40
+ echo "╔════════════════════════════════════════════════════════════╗"
41
+ echo "║ ❌ COMMIT BLOCKED: TESTS FAILED ║"
42
+ echo "╠════════════════════════════════════════════════════════════╣"
43
+ echo "║ Cannot commit code when tests are failing. ║"
44
+ echo "║ This prevents broken code from entering the repository. ║"
45
+ echo "╠════════════════════════════════════════════════════════════╣"
46
+ echo "║ ACTION REQUIRED: ║"
47
+ echo "║ 1. Review test failures above ║"
48
+ echo "║ 2. Fix the failing code ║"
49
+ echo "║ 3. Re-run: dotnet test ║"
50
+ echo "║ 4. Once tests pass, Ralph will commit automatically ║"
51
+ echo "╚════════════════════════════════════════════════════════════╝"
52
+
53
+ # Mark task as failed (do not complete)
54
+ # Update prd.json
55
+ const prd = readJSON('.ralph/prd.json');
56
+ const task = prd.tasks.find(t => t.id === {current_task_id});
57
+ task.status = 'failed';
58
+ task.error = 'Pre-commit test suite failed. Cannot commit broken code.';
59
+ writeJSON('.ralph/prd.json', prd);
60
+
61
+ # STOP - return to step-02 to fix
62
+ exit 1;
63
+ fi
64
+
65
+ echo "✅ All tests passed. Proceeding with commit..."
66
+ fi
67
+ ```
68
+
69
+ **Additional validation for specific categories:**
70
+
71
+ ```javascript
72
+ const task = prd.tasks.find(t => t.id === {current_task_id});
73
+
74
+ // For backend changes: ensure build succeeds
75
+ if (['domain', 'application', 'infrastructure', 'api'].includes(task.category)) {
76
+ dotnet build --no-restore --verbosity quiet
77
+ if ($? !== 0) {
78
+ echo "❌ Build failed. Cannot commit broken code.";
79
+ task.status = 'failed';
80
+ task.error = 'Build failed';
81
+ exit 1;
82
+ }
83
+ }
84
+
85
+ // For frontend changes: ensure typecheck passes
86
+ if (task.category === 'frontend') {
87
+ npm run typecheck
88
+ if ($? !== 0) {
89
+ echo "❌ TypeScript errors. Cannot commit broken code.";
90
+ task.status = 'failed';
91
+ task.error = 'TypeScript compilation failed';
92
+ exit 1;
93
+ }
94
+ }
95
+ ```
96
+
97
+ **If ALL validations pass, proceed to staging.**
98
+
17
99
  ### 1. Stage Changes
18
100
 
19
101
  **Add modified files:**