@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.
- package/dist/index.js +2544 -2461
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +479 -6185
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/db-reader.md +149 -0
- package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +9 -19
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +12 -2
- package/templates/skills/business-analyse/references/deploy-data-build.md +36 -25
- package/templates/skills/business-analyse/references/detection-strategies.md +424 -0
- package/templates/skills/business-analyse/references/html-data-mapping.md +4 -0
- package/templates/skills/business-analyse/references/prd-generation.md +258 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +47 -4
- package/templates/skills/business-analyse/references/validation-checklist.md +281 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +50 -221
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +8 -22
- package/templates/skills/business-analyse/steps/step-03a-data.md +20 -446
- package/templates/skills/business-analyse/steps/step-03a1-setup.md +356 -0
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +143 -0
- package/templates/skills/business-analyse/steps/step-03b-ui.md +3 -0
- package/templates/skills/business-analyse/steps/step-03c-compile.md +1 -1
- package/templates/skills/business-analyse/steps/step-03d-validate.md +21 -262
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +21 -606
- package/templates/skills/business-analyse/steps/step-04a-collect.md +304 -0
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +239 -0
- package/templates/skills/business-analyse/steps/step-04c-decide.md +186 -0
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +21 -0
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +27 -35
- package/templates/skills/debug/SKILL.md +156 -53
- package/templates/skills/debug/references/team-protocol.md +232 -0
- package/templates/skills/ralph-loop/references/category-rules.md +46 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +32 -2
- package/templates/skills/ralph-loop/references/core-seed-data.md +60 -0
- package/templates/skills/ralph-loop/steps/step-00-init.md +64 -1
- 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.
|
|
75
|
-
|
|
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.
|
|
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));
|