@atlashub/smartstack-cli 3.10.0 → 3.12.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 (35) hide show
  1. package/dist/index.js +2544 -2461
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +479 -6185
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/agents/db-reader.md +149 -0
  7. package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +9 -19
  8. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +12 -2
  9. package/templates/skills/business-analyse/references/deploy-data-build.md +36 -25
  10. package/templates/skills/business-analyse/references/detection-strategies.md +424 -0
  11. package/templates/skills/business-analyse/references/html-data-mapping.md +4 -0
  12. package/templates/skills/business-analyse/references/prd-generation.md +258 -0
  13. package/templates/skills/business-analyse/references/validate-incremental-html.md +47 -4
  14. package/templates/skills/business-analyse/references/validation-checklist.md +281 -0
  15. package/templates/skills/business-analyse/steps/step-00-init.md +50 -221
  16. package/templates/skills/business-analyse/steps/step-01-cadrage.md +8 -22
  17. package/templates/skills/business-analyse/steps/step-03a-data.md +20 -446
  18. package/templates/skills/business-analyse/steps/step-03a1-setup.md +356 -0
  19. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +143 -0
  20. package/templates/skills/business-analyse/steps/step-03b-ui.md +3 -0
  21. package/templates/skills/business-analyse/steps/step-03c-compile.md +1 -1
  22. package/templates/skills/business-analyse/steps/step-03d-validate.md +21 -262
  23. package/templates/skills/business-analyse/steps/step-04-consolidation.md +21 -606
  24. package/templates/skills/business-analyse/steps/step-04a-collect.md +304 -0
  25. package/templates/skills/business-analyse/steps/step-04b-analyze.md +239 -0
  26. package/templates/skills/business-analyse/steps/step-04c-decide.md +186 -0
  27. package/templates/skills/business-analyse/steps/step-05b-deploy.md +21 -0
  28. package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +27 -35
  29. package/templates/skills/debug/SKILL.md +156 -53
  30. package/templates/skills/debug/references/team-protocol.md +232 -0
  31. package/templates/skills/ralph-loop/references/category-rules.md +46 -0
  32. package/templates/skills/ralph-loop/references/compact-loop.md +32 -2
  33. package/templates/skills/ralph-loop/references/core-seed-data.md +60 -0
  34. package/templates/skills/ralph-loop/steps/step-00-init.md +64 -1
  35. package/templates/skills/ralph-loop/steps/step-04-check.md +27 -2
@@ -0,0 +1,232 @@
1
+ # Team Protocol — Debug Investigation
2
+
3
+ > **Loaded by:** SKILL.md phase 2 (EXPLORE)
4
+ > **Purpose:** Coordinate parallel investigation agents for bug diagnosis.
5
+ > **Pattern:** APEX-style (single session, parallel scan, aggregated results)
6
+
7
+ ---
8
+
9
+ ## 1. Team Creation
10
+
11
+ ```yaml
12
+ TeamCreate:
13
+ team_name: "debug-investigate"
14
+ description: "Parallel bug investigation team"
15
+ ```
16
+
17
+ ---
18
+
19
+ ## 2. Teammate Spawn
20
+
21
+ Spawn all teammates **in a single message** (parallel Task calls):
22
+
23
+ | Teammate | Model | Scope | Tools |
24
+ |----------|-------|-------|-------|
25
+ | `code-investigator` | haiku | Codebase search | Read, Glob, Grep, Bash |
26
+ | `doc-researcher` | haiku | Documentation + web | Read, Glob, Grep, WebSearch, WebFetch |
27
+ | `data-inspector` | haiku | Database READ-ONLY | Read, Glob, Grep, Bash |
28
+
29
+ **`data-inspector`**: spawn ONLY if the bug involves data, persistence, or database operations. Otherwise spawn only 2 teammates.
30
+
31
+ ```yaml
32
+ # For each teammate:
33
+ Task:
34
+ subagent_type: "general-purpose"
35
+ team_name: "debug-investigate"
36
+ name: "{teammate-name}"
37
+ model: "haiku"
38
+ mode: "bypassPermissions"
39
+ prompt: "{TEAMMATE_PROMPT}"
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 3. Communication Protocol
45
+
46
+ ### Messages from teammates → team-lead
47
+
48
+ | Message | When | Format |
49
+ |---------|------|--------|
50
+ | `FINDING` | Significant discovery | `FINDING: {description with file paths and line numbers}` |
51
+ | `INVESTIGATION_COMPLETE` | Agent finished all checks | `INVESTIGATION_COMPLETE: {summary of all findings}` |
52
+
53
+ **Rules:**
54
+ - Send `FINDING` as soon as a significant discovery is made (don't wait until the end)
55
+ - Always include **file paths with line numbers** in findings
56
+ - Send exactly ONE `INVESTIGATION_COMPLETE` when done
57
+
58
+ ### Messages from team-lead → teammates
59
+
60
+ | Message | When | Format |
61
+ |---------|------|--------|
62
+ | `LEAD_HINT` | Lead wants to orient a search | `LEAD_HINT: {new direction to investigate}` |
63
+
64
+ **Rules:**
65
+ - Lead sends hints based on cross-agent findings (e.g., code-investigator found a file, ask data-inspector to check related records)
66
+ - Hints are optional — only when findings from one agent inform another's search
67
+
68
+ ### Example Flow
69
+
70
+ ```
71
+ code-investigator → lead: FINDING: NullRef at OrderService.cs:45 — Customer lookup returns null
72
+ lead → data-inspector: LEAD_HINT: Check if Customer records exist for OrderId=123, verify FK integrity Orders→Customers
73
+ data-inspector → lead: FINDING: FK broken — Order.CustomerId=99 has no matching Customer record (deleted without cascade)
74
+ doc-researcher → lead: FINDING: EF Core docs warn about cascade delete config — OnDelete(DeleteBehavior.Restrict) may leave orphans
75
+ code-investigator → lead: INVESTIGATION_COMPLETE: Source at OrderService.cs:45, no null check before Customer access
76
+ data-inspector → lead: INVESTIGATION_COMPLETE: 3 orphaned Orders found, TenantId OK, audit fields present
77
+ doc-researcher → lead: INVESTIGATION_COMPLETE: EF Core cascade delete misconfiguration documented
78
+ ```
79
+
80
+ ---
81
+
82
+ ## 4. Teammate Prompts
83
+
84
+ ### code-investigator
85
+
86
+ ```
87
+ You are a code investigator on the debug team.
88
+
89
+ ## Bug Context
90
+ Error: {error_description}
91
+ Stack trace: {stack_trace}
92
+
93
+ ## Your Mission
94
+ 1. Locate the error source in code (from stack trace)
95
+ 2. Find related error handling patterns
96
+ 3. Identify similar code that works correctly (for comparison)
97
+ 4. Check recent commits on affected files (git log --oneline -10, git blame)
98
+ 5. Search for similar error patterns elsewhere in codebase
99
+
100
+ ## Communication Protocol
101
+ - Send FINDING messages to team-lead for each significant discovery:
102
+ SendMessage(type: "message", recipient: "team-lead", content: "FINDING: {description}", summary: "Found {short}")
103
+ - When done, send:
104
+ SendMessage(type: "message", recipient: "team-lead", content: "INVESTIGATION_COMPLETE: {summary}", summary: "Code investigation done")
105
+ - If team-lead sends a LEAD_HINT, follow that direction
106
+
107
+ ## Tools
108
+ - Read, Glob, Grep for code search
109
+ - Bash ONLY for: git log, git blame, git diff (NEVER for code modification)
110
+
111
+ ## Output
112
+ Report file paths with line numbers. Be precise and factual.
113
+ ```
114
+
115
+ ### doc-researcher
116
+
117
+ ```
118
+ You are a documentation researcher on the debug team.
119
+
120
+ ## Bug Context
121
+ Error: {error_description}
122
+ Libraries/frameworks in stack trace: {libraries_in_stacktrace}
123
+
124
+ ## Your Mission
125
+ 1. Research documentation for libraries in the stack trace
126
+ 2. Find known issues or breaking changes
127
+ 3. Find correct usage patterns
128
+ 4. Search for similar issues reported by others online
129
+ 5. Look for migration guides if version issues suspected
130
+
131
+ ## Communication Protocol
132
+ - Send FINDING messages to team-lead for each discovery:
133
+ SendMessage(type: "message", recipient: "team-lead", content: "FINDING: {description}", summary: "Found {short}")
134
+ - When done, send:
135
+ SendMessage(type: "message", recipient: "team-lead", content: "INVESTIGATION_COMPLETE: {summary}", summary: "Doc research done")
136
+ - If team-lead sends a LEAD_HINT, follow that direction
137
+
138
+ ## Tools
139
+ - Read, Glob, Grep for local documentation search
140
+ - WebSearch, WebFetch for online documentation and issue trackers
141
+ ```
142
+
143
+ ### data-inspector
144
+
145
+ ```
146
+ You are a READ-ONLY database inspector on the debug team.
147
+
148
+ ## Bug Context
149
+ Error: {error_description}
150
+
151
+ ## ABSOLUTE RESTRICTIONS — READ BEFORE EVERY BASH COMMAND
152
+ YOU MUST NEVER EXECUTE:
153
+ - INSERT, UPDATE, DELETE, MERGE, TRUNCATE
154
+ - DROP, ALTER, CREATE, RENAME
155
+ - EXEC, EXECUTE (stored procedures)
156
+ - dotnet ef database update, dotnet ef migrations
157
+ - ANY command that writes, modifies, or deletes data or schema
158
+
159
+ YOU MAY ONLY EXECUTE:
160
+ - SELECT queries
161
+ - INFORMATION_SCHEMA queries
162
+ - sys.* catalog views
163
+ - sp_help, sp_helptext, sp_columns
164
+
165
+ ## Your Mission
166
+ 1. Find the connection string (appsettings.json, appsettings.Development.json)
167
+ 2. Check record existence and field values for affected entities
168
+ 3. Verify foreign key integrity (orphaned records)
169
+ 4. Check tenant isolation (TenantId present on all records)
170
+ 5. Verify soft delete and audit field consistency
171
+ 6. Compare actual schema vs expected EF Core model
172
+
173
+ ## Communication Protocol
174
+ - Send FINDING messages to team-lead for each data anomaly:
175
+ SendMessage(type: "message", recipient: "team-lead", content: "FINDING: {description}", summary: "Data issue {short}")
176
+ - When done, send:
177
+ SendMessage(type: "message", recipient: "team-lead", content: "INVESTIGATION_COMPLETE: {summary}", summary: "DB inspection done")
178
+ - If team-lead sends a LEAD_HINT, follow that direction
179
+
180
+ ## Tools
181
+ - Read, Glob, Grep for connection string and config discovery
182
+ - Bash ONLY for SELECT queries (NEVER modify data)
183
+
184
+ ## Output
185
+ - Use markdown tables for query results
186
+ - Mask sensitive data (passwords, tokens, PII)
187
+ - Limit results with TOP/LIMIT to avoid overwhelming output
188
+ - If a data fix is needed, DESCRIBE it — NEVER execute it
189
+ ```
190
+
191
+ ---
192
+
193
+ ## 5. Team Lead Aggregation
194
+
195
+ After receiving all `INVESTIGATION_COMPLETE` messages:
196
+
197
+ ```
198
+ 1. Collect all FINDING messages from each agent
199
+ 2. Cross-reference findings (code issues ↔ data anomalies ↔ documentation)
200
+ 3. Build the root cause chain: symptom → immediate cause → root cause
201
+ 4. Shutdown teammates
202
+ 5. Proceed to ULTRA-THINK phase (inline)
203
+ ```
204
+
205
+ ---
206
+
207
+ ## 6. Graceful Shutdown
208
+
209
+ After aggregation (or if investigation is sufficient before all complete):
210
+
211
+ ```yaml
212
+ # For each teammate:
213
+ SendMessage:
214
+ type: "shutdown_request"
215
+ recipient: "{teammate-name}"
216
+ content: "Investigation complete, shutting down"
217
+
218
+ # Wait for shutdown_response from each, then:
219
+ TeamDelete
220
+ ```
221
+
222
+ ---
223
+
224
+ ## 7. Decision Matrix
225
+
226
+ | Condition | Action |
227
+ |-----------|--------|
228
+ | Simple error, obvious from stack trace | NO team — inline investigation |
229
+ | Error involves code + data | Team: code-investigator + data-inspector |
230
+ | Error involves unknown library | Team: code-investigator + doc-researcher |
231
+ | Complex bug, multiple suspects | Full team: all 3 agents |
232
+ | Performance issue (no error) | code-investigator only (profiling inline) |
@@ -75,10 +75,17 @@ Execution sequence:
75
75
  - IClientSeedDataProvider: SeedNavigationAsync + SeedPermissionsAsync + SeedRolePermissionsAsync
76
76
  - DI: `services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>()`
77
77
 
78
+ **Business seed data (DevDataSeeder):**
79
+ - ALL seeded business entities MUST include `TenantId = {tenantGuid}`
80
+ - Reference entities (types, categories, statuses) MUST set TenantId
81
+ - Use deterministic TenantId from SeedConstants (NEVER hardcoded inline)
82
+ - DevDataSeeder MUST implement `IDevDataSeeder` with idempotent `SeedAsync()` method
83
+
78
84
  **FORBIDDEN:**
79
85
  - `Guid.NewGuid()` → use deterministic GUIDs
80
86
  - Empty seed data classes with only GUIDs and no seeding methods
81
87
  - Missing translations (must have all 4 languages)
88
+ - Seeding business entities WITHOUT `TenantId`
82
89
 
83
90
  ---
84
91
 
@@ -118,6 +125,24 @@ Rules:
118
125
  - DTOs separate from domain entities
119
126
  - Service interfaces in Application, implementations in Infrastructure
120
127
 
128
+ **Lifecycle-aware services:**
129
+ - Services operating on entities with a `lifeCycle` (status field) MUST validate entity state before mutations
130
+ - Example: `if (entity.Status == EmployeeStatus.Terminated) throw new BusinessException("Cannot update terminated employee")`
131
+ - Guard checks MUST match the `allowedTransitions` from the entity's lifecycle definition
132
+ - Delete/archive operations MUST respect terminal states (`isTerminal: true`)
133
+
134
+ **Validator completeness (BLOCKING):**
135
+ - For EVERY `Create{Entity}Validator`, a matching `Update{Entity}Validator` MUST exist
136
+ - ALL validators MUST be registered in `Application/DependencyInjection.cs`:
137
+ `services.AddValidatorsFromAssemblyContaining<Create{Entity}Validator>()`
138
+ - DependencyInjection.cs MUST NOT be empty or contain only TODO comments
139
+ - After writing validators, VERIFY DI registration exists — if missing, add it immediately
140
+
141
+ **FORBIDDEN:**
142
+ - Empty DependencyInjection.cs with `// TODO` placeholder
143
+ - CreateValidator without matching UpdateValidator
144
+ - Validators not registered in DI container
145
+
121
146
  ---
122
147
 
123
148
  ## API
@@ -140,9 +165,15 @@ Rules:
140
165
  - Consistent route patterns: `api/{context}/{app}/{module}`
141
166
  - Return DTOs, never domain entities
142
167
 
168
+ **Controller coverage (BLOCKING):**
169
+ - EVERY entity in the module MUST have a controller with CRUD endpoints (GET list, GET by id, POST, PUT, DELETE)
170
+ - Reference/lookup entities (types, categories, statuses) MUST also have controllers — they are needed for dropdowns and configuration
171
+ - Count: `controllers created >= entities in module`. If fewer → FAIL
172
+
143
173
  **FORBIDDEN:**
144
174
  - `[Authorize]` without specific permission → use `[RequirePermission]`
145
175
  - Returning domain entities directly
176
+ - Skipping controllers for reference/lookup entities
146
177
 
147
178
  ---
148
179
 
@@ -178,6 +209,18 @@ Rules:
178
209
 
179
210
  **CSS:** Variables ONLY → `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`
180
211
 
212
+ **Form error handling (MANDATORY):**
213
+ - ALL SmartForm components MUST include `onError` callback for API errors
214
+ - Validation errors MUST be displayed inline next to the relevant field
215
+ - API errors (4xx, 5xx) MUST show a user-friendly error notification (toast/banner)
216
+ - Forms MUST preserve user input on error (no data loss on failed submit)
217
+
218
+ **Dependency verification (BLOCKING):**
219
+ - BEFORE writing any import, verify the package exists in `package.json`
220
+ - If package not present: run `npm install {package}` BEFORE writing the import
221
+ - Common missing packages: @tanstack/react-query, recharts, date-fns, react-router-dom
222
+ - After ALL frontend tasks: run `npm ls --depth=0` to detect any MISSING dependencies
223
+
181
224
  **FORBIDDEN patterns (any = FAIL):**
182
225
  ```
183
226
  import axios from 'axios' → use @/services/api/apiClient
@@ -186,6 +229,9 @@ import axios from 'axios' → use @/services/api/apiClient
186
229
  <Route path="/business/app/mod" /> → MUST be nested inside Layout
187
230
  Only fr/en translations → MUST have 4 languages
188
231
  src/pages/{Module}/ → MUST be src/pages/{Context}/{App}/{Module}/
232
+ '00000000-0000-0000-0000-000000000000' → use dynamic ID from auth context or route params
233
+ const api = axios.create(...) → use @/services/api/apiClient (single instance)
234
+ useXxx with raw axios inside hooks → hooks MUST use the shared apiClient from @/services/api
189
235
  ```
190
236
 
191
237
  ---
@@ -71,8 +71,25 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
71
71
  - Backend (domain/infra/app/api): `dotnet build --no-restore` → MUST exit 0
72
72
  - Frontend: `npm run typecheck` → MUST exit 0
73
73
  3. If build fails → read FULL error output → fix source code → rebuild → loop until pass
74
- 4. Verify acceptance criteria
75
- 5. If failed after 3 attempts: `task.status = 'failed'`, `task.error = reason`, continue to next in batch
74
+ 4. **ARTIFACT verification (BLOCKING per task):**
75
+ - `files_created` MUST NOT be empty for code-generating tasks
76
+ - Category-specific checks (see below)
77
+ - IF no artifacts produced → task.status = 'failed', task.error = 'No artifacts created'
78
+ 5. Verify acceptance criteria from task description
79
+ 6. If failed after 3 attempts: `task.status = 'failed'`, `task.error = reason`, continue to next in batch
80
+
81
+ **Category-specific artifact checks (step 4 above):**
82
+
83
+ | Category | Artifact Check | FAIL if |
84
+ |----------|---------------|---------|
85
+ | `domain` | Entity .cs files exist in Domain/ | 0 files created |
86
+ | `infrastructure` with migration | `Migrations/` folder has .cs files | No migration files |
87
+ | `infrastructure` with seed data | Seed data .cs files exist | 0 files created |
88
+ | `application` | Service + DTO + Validator files exist | 0 files created |
89
+ | `api` | Controller .cs files exist | 0 files created |
90
+ | `frontend` | .tsx page files exist | 0 files created |
91
+ | `test` | Test project dir exists AND contains test .cs files | No test project or 0 test files |
92
+ | `validation` | `dotnet test` exit 0 AND `dotnet build` exit 0 | Either command fails |
76
93
 
77
94
  **Category-specific triggers:**
78
95
 
@@ -99,12 +116,25 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
99
116
  ```
100
117
  If FAIL → fix source code (NOT tests) → rebuild → retest → loop until 100% pass
101
118
 
119
+ 2bis. **DI completeness (if application tasks in batch):**
120
+ Verify `Application/DependencyInjection.cs` registers all validators and services:
121
+ - Count validators in `Validators/` folder
122
+ - Verify `AddValidatorsFromAssemblyContaining` is present
123
+ - If empty/TODO → FAIL → fix DI registration → rebuild
124
+
102
125
  3. **Frontend (if frontend/i18n tasks in batch):**
103
126
  ```bash
104
127
  npm run typecheck && npm run lint
105
128
  ```
106
129
  If FAIL → fix → re-check → loop until pass
107
130
 
131
+ 3bis. **Dependency audit (if frontend tasks in batch):**
132
+ ```bash
133
+ cd {frontend_dir}
134
+ npm ls --depth=0 2>&1 | grep "MISSING" && echo "FAIL: missing deps" && exit 1
135
+ ```
136
+ If FAIL → `npm install {missing_packages}` → re-check → loop until pass
137
+
108
138
  4. **MCP validation:**
109
139
  `mcp__smartstack__validate_conventions` ONCE for the whole batch
110
140
 
@@ -688,3 +688,63 @@ Before marking the task as completed, verify ALL:
688
688
  - [ ] `dotnet build` passes after generation
689
689
 
690
690
  **If ANY check fails, the task status = 'failed'.**
691
+
692
+ ---
693
+
694
+ ## 9. Business Seed Data (DevDataSeeder) — TenantId Rules
695
+
696
+ > **Applies to:** Seed data for business entities (reference types, categories, statuses).
697
+ > **NOT the same as** core seed data above (navigation, permissions, roles).
698
+
699
+ ### Rules
700
+
701
+ | Rule | Description |
702
+ |------|-------------|
703
+ | TenantId MANDATORY | ALL business seed entities MUST set `TenantId` |
704
+ | Deterministic TenantId | Use `SeedConstants.DefaultTenantId` (NEVER inline GUID) |
705
+ | DevDataSeeder pattern | Implement `IDevDataSeeder` with `SeedAsync()` method |
706
+ | Idempotency | Each seeder MUST check `AnyAsync()` before inserting |
707
+ | Order | DevDataSeeder `Order >= 200` (after core seed data at Order 100) |
708
+
709
+ ### Template (Reference Types)
710
+
711
+ ```csharp
712
+ public class {Module}DevDataSeeder : IDevDataSeeder
713
+ {
714
+ public int Order => 200; // After core seed data (Order 100)
715
+
716
+ public async Task SeedAsync(ExtensionsDbContext context, CancellationToken ct)
717
+ {
718
+ if (await context.Set<{EntityType}>().AnyAsync(ct)) return;
719
+
720
+ var items = new[]
721
+ {
722
+ new {EntityType}
723
+ {
724
+ Id = GenerateDeterministicGuid("{entity-type}-{code}"),
725
+ Code = "{code}",
726
+ Name = "{name}",
727
+ TenantId = SeedConstants.DefaultTenantId, // MANDATORY
728
+ IsActive = true
729
+ }
730
+ };
731
+
732
+ context.Set<{EntityType}>().AddRange(items);
733
+ await context.SaveChangesAsync(ct);
734
+ }
735
+
736
+ private static Guid GenerateDeterministicGuid(string seed)
737
+ {
738
+ using var sha256 = System.Security.Cryptography.SHA256.Create();
739
+ var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(seed));
740
+ return new Guid(hash.Take(16).ToArray());
741
+ }
742
+ }
743
+ ```
744
+
745
+ ### FORBIDDEN
746
+
747
+ - Seeding business entities WITHOUT `TenantId`
748
+ - Using `Guid.NewGuid()` for TenantId
749
+ - Omitting idempotency check (`AnyAsync`)
750
+ - Hardcoding TenantId inline (use `SeedConstants.DefaultTenantId`)
@@ -48,7 +48,70 @@ mcp__context7__resolve-library-id: libraryName: "test" → {mcp_context7} = tru
48
48
 
49
49
  If ANY fails: show error, suggest `smartstack check-mcp`, STOP.
50
50
 
51
- ## 3. Resume Mode
51
+ ## 3. Human-in-the-Loop Checkpoint (RECOMMENDED)
52
+
53
+ > **Best Practice:** Commencer en mode supervisé avant le mode autonome complet.
54
+
55
+ ### Why HITL First?
56
+
57
+ Ralph-loop est puissant mais peut diverger si :
58
+ - Les requirements sont ambigus
59
+ - Les tests sont lents (>30s)
60
+ - Le code généré ne compile pas immédiatement
61
+
62
+ **Stratégie recommandée :**
63
+
64
+ 1. **Première itération supervisée** - Lancer manuellement la première tâche pour vérifier :
65
+ - La qualité du code généré
66
+ - Le temps d'exécution des tests
67
+ - La clarté des messages d'erreur
68
+
69
+ 2. **Mode autonome limité** - Si première itération OK, relancer avec `--max-iterations 5-10`
70
+
71
+ 3. **Mode autonome complet** - Une fois confiant, augmenter à `--max-iterations 50`
72
+
73
+ ### Checkpoint Prompt (Optional)
74
+
75
+ Si vous détectez que c'est la première utilisation de ralph-loop sur ce projet (pas de `.ralph/logs/`), proposer :
76
+
77
+ ```javascript
78
+ if (!dirExists('.ralph/logs') && !resume_mode) {
79
+ AskUserQuestion({
80
+ questions: [{
81
+ question: "Premier usage de ralph-loop détecté. Démarrer en mode supervisé ou autonome ?",
82
+ header: "Mode",
83
+ multiSelect: false,
84
+ options: [
85
+ { label: "Supervisé (recommandé)", description: "Exécuter 1 tâche, puis demander confirmation" },
86
+ { label: "Autonome limité", description: "Max 10 itérations automatiques" },
87
+ { label: "Autonome complet", description: "Jusqu'à 50 itérations (mode AFK)" }
88
+ ]
89
+ }]
90
+ });
91
+
92
+ if (answer === "Supervisé") {
93
+ max_iterations = 1;
94
+ console.log("Mode supervisé : 1 tâche sera exécutée. Relancez avec -r pour continuer.");
95
+ } else if (answer === "Autonome limité") {
96
+ max_iterations = Math.min(max_iterations, 10);
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Feedback Speed Warning
102
+
103
+ ⚠️ **IMPORTANT :** Si vos tests prennent >30 secondes, ralph-loop peut devenir inefficace.
104
+
105
+ ```
106
+ Temps test recommandés :
107
+ - Unitaires : <5s
108
+ - Intégration : <15s
109
+ - E2E : <30s (à exécuter en dehors du loop)
110
+ ```
111
+
112
+ Si tests lents détectés (via logs), avertir l'utilisateur et suggérer de désactiver tests E2E pendant le loop.
113
+
114
+ ## 4. Resume Mode
52
115
 
53
116
  If `{resume_mode} = true`:
54
117
 
@@ -40,12 +40,20 @@ if [ -d "$TEST_PROJECT" ]; then
40
40
  dotnet test "$TEST_PROJECT" --no-build --verbosity normal
41
41
  if [ $? -ne 0 ]; then
42
42
  echo "TEST REGRESSION — creating fix task"
43
- # Inject fix task into prd.json:
44
43
  prd.tasks.push({ id: maxId+1, description: "Fix test regression — all tests must pass",
45
44
  status: "pending", category: "validation", dependencies: [],
46
45
  acceptance_criteria: "dotnet test exits 0, all tests pass" });
47
46
  writeJSON('.ralph/prd.json', prd);
48
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
49
57
  fi
50
58
  ```
51
59
 
@@ -99,11 +107,28 @@ if (fileExists(queuePath)) {
99
107
  const queue = readJSON(queuePath);
100
108
  const currentModule = queue.modules[queue.currentIndex];
101
109
 
102
- // MODULE COMPLETENESS CHECK: verify all expected layers
110
+ // MODULE COMPLETENESS CHECK: verify all expected layers AND their artifacts
103
111
  const completedCats = new Set(prd.tasks.filter(t => t.status === 'completed').map(t => t.category));
104
112
  const expected = ['domain', 'infrastructure', 'application', 'api', 'frontend', 'test'];
105
113
  const missing = expected.filter(c => !completedCats.has(c));
106
114
 
115
+ // ARTIFACT EXISTENCE CHECK: categories with completed tasks must have real files
116
+ const artifactChecks = {
117
+ 'infrastructure': () => fs.existsSync('src/*/Persistence/Migrations') && fs.readdirSync('src/*/Persistence/Migrations').length > 0,
118
+ 'test': () => fs.existsSync(`tests/${projectName}.Tests.Unit`) && glob.sync('tests/**/*Tests.cs').length > 0,
119
+ 'api': () => glob.sync('src/*/Controllers/**/*Controller.cs').length > 0,
120
+ 'frontend': () => glob.sync('**/src/pages/**/*.tsx').length > 0
121
+ };
122
+ for (const [cat, check] of Object.entries(artifactChecks)) {
123
+ if (completedCats.has(cat) && !check()) {
124
+ // Tasks marked completed but artifacts missing — reset to pending
125
+ prd.tasks.filter(t => t.category === cat && t.status === 'completed')
126
+ .forEach(t => { t.status = 'pending'; t.error = 'Artifacts missing — re-execute'; t.completed_at = null; });
127
+ missing.push(cat);
128
+ console.log(`ARTIFACT RESET: ${cat} tasks reset to pending (no files found)`);
129
+ }
130
+ }
131
+
107
132
  if (missing.length > 0) {
108
133
  // Inject guardrail tasks for missing layers
109
134
  let maxId = Math.max(...prd.tasks.map(t => t.id));