@atlashub/smartstack-cli 3.7.0 → 3.9.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 +365 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/templates/agents/action.md +1 -0
- package/templates/agents/ba-writer.md +33 -0
- package/templates/agents/explore-codebase.md +1 -0
- package/templates/agents/explore-docs.md +1 -0
- package/templates/agents/fix-grammar.md +1 -0
- package/templates/agents/snipper.md +1 -0
- package/templates/skills/admin/SKILL.md +6 -0
- package/templates/skills/ai-prompt/SKILL.md +32 -136
- package/templates/skills/ai-prompt/steps/step-01-implementation.md +122 -0
- package/templates/skills/apex/SKILL.md +120 -0
- package/templates/skills/apex/_shared.md +86 -0
- package/templates/skills/apex/references/agent-teams-protocol.md +164 -0
- package/templates/skills/apex/references/smartstack-layers.md +173 -0
- package/templates/skills/apex/steps/step-00-init.md +156 -0
- package/templates/skills/apex/steps/step-01-analyze.md +169 -0
- package/templates/skills/apex/steps/step-02-plan.md +160 -0
- package/templates/skills/apex/steps/step-03-execute.md +166 -0
- package/templates/skills/apex/steps/step-04-validate.md +138 -0
- package/templates/skills/apex/steps/step-05-examine.md +124 -0
- package/templates/skills/apex/steps/step-06-resolve.md +105 -0
- package/templates/skills/apex/steps/step-07-tests.md +130 -0
- package/templates/skills/apex/steps/step-08-run-tests.md +115 -0
- package/templates/skills/application/SKILL.md +10 -0
- package/templates/skills/application/references/backend-controller-hierarchy.md +58 -0
- package/templates/skills/application/references/backend-entity-seeding.md +72 -0
- package/templates/skills/application/references/backend-verification.md +88 -0
- package/templates/skills/application/references/frontend-verification.md +111 -0
- package/templates/skills/application/references/nav-fallback-procedure.md +200 -0
- package/templates/skills/application/references/provider-template.md +134 -0
- package/templates/skills/application/references/test-frontend.md +73 -0
- package/templates/skills/application/references/test-prerequisites.md +72 -0
- package/templates/skills/application/steps/step-01-navigation.md +7 -198
- package/templates/skills/application/steps/step-03b-provider.md +4 -128
- package/templates/skills/application/steps/step-04-backend.md +20 -350
- package/templates/skills/application/steps/step-05-frontend.md +12 -101
- package/templates/skills/application/steps/step-07-tests.md +12 -132
- package/templates/skills/business-analyse/SKILL.md +11 -2
- package/templates/skills/business-analyse/html/ba-interactive.html +3214 -2246
- package/templates/skills/business-analyse/html/build-html.js +77 -0
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +130 -0
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +22 -0
- package/templates/skills/business-analyse/html/src/scripts/03-render-cadrage.js +208 -0
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +211 -0
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +554 -0
- package/templates/skills/business-analyse/html/src/scripts/06-render-consolidation.js +110 -0
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +90 -0
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +45 -0
- package/templates/skills/business-analyse/html/src/scripts/09-export.js +168 -0
- package/templates/skills/business-analyse/html/src/scripts/10-comments.js +171 -0
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +161 -0
- package/templates/skills/business-analyse/html/src/styles/01-variables.css +38 -0
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +101 -0
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +62 -0
- package/templates/skills/business-analyse/html/src/styles/04-cards.css +196 -0
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +325 -0
- package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +230 -0
- package/templates/skills/business-analyse/html/src/styles/07-comments.css +184 -0
- package/templates/skills/business-analyse/html/src/styles/08-review-panel.css +241 -0
- package/templates/skills/business-analyse/html/src/template.html +623 -0
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +78 -0
- package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +97 -0
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +92 -0
- package/templates/skills/business-analyse/references/deploy-data-build.md +121 -0
- package/templates/skills/business-analyse/references/deploy-modes.md +49 -0
- package/templates/skills/business-analyse/references/handoff-file-templates.md +119 -0
- package/templates/skills/business-analyse/references/handoff-mappings.md +81 -0
- package/templates/skills/business-analyse/references/html-data-mapping.md +10 -2
- package/templates/skills/business-analyse/references/init-schema-deployment.md +65 -0
- package/templates/skills/business-analyse/references/review-data-mapping.md +363 -0
- package/templates/skills/business-analyse/references/spec-auto-inference.md +57 -0
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +85 -0
- package/templates/skills/business-analyse/references/ui-resource-cards.md +110 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +55 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +35 -68
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +5 -194
- package/templates/skills/business-analyse/steps/step-03a-data.md +6 -49
- package/templates/skills/business-analyse/steps/step-03b-ui.md +12 -178
- package/templates/skills/business-analyse/steps/step-03d-validate.md +3 -48
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +9 -104
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +25 -441
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +19 -187
- package/templates/skills/business-analyse/steps/step-06-review.md +277 -0
- package/templates/skills/cc-agent/references/agent-behavior-patterns.md +95 -0
- package/templates/skills/cc-agent/steps/step-02-generate.md +5 -78
- package/templates/skills/check-version/SKILL.md +7 -0
- package/templates/skills/controller/references/controller-code-templates.md +159 -0
- package/templates/skills/controller/references/permission-sync-templates.md +152 -0
- package/templates/skills/controller/steps/step-03-generate.md +6 -158
- package/templates/skills/controller/steps/step-04-perms.md +5 -144
- package/templates/skills/debug/SKILL.md +7 -0
- package/templates/skills/explore/SKILL.md +6 -0
- package/templates/skills/feature-full/SKILL.md +39 -142
- package/templates/skills/feature-full/steps/step-01-implementation.md +120 -0
- package/templates/skills/gitflow/references/init-config-template.md +135 -0
- package/templates/skills/gitflow/references/init-name-normalization.md +103 -0
- package/templates/skills/gitflow/references/plan-template.md +69 -0
- package/templates/skills/gitflow/references/start-efcore-preflight.md +70 -0
- package/templates/skills/gitflow/references/start-local-config.md +110 -0
- package/templates/skills/gitflow/steps/step-init.md +18 -289
- package/templates/skills/gitflow/steps/step-plan.md +6 -63
- package/templates/skills/gitflow/steps/step-start.md +16 -126
- package/templates/skills/mcp/SKILL.md +9 -213
- package/templates/skills/mcp/steps/step-01-healthcheck.md +108 -0
- package/templates/skills/mcp/steps/step-02-tools.md +73 -0
- package/templates/skills/notification/SKILL.md +7 -0
- package/templates/skills/quick-search/SKILL.md +5 -0
- package/templates/skills/ralph-loop/SKILL.md +99 -381
- package/templates/skills/ralph-loop/references/category-rules.md +259 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +182 -0
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +259 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +189 -0
- package/templates/skills/ralph-loop/steps/step-00-init.md +111 -383
- package/templates/skills/ralph-loop/steps/step-01-task.md +79 -896
- package/templates/skills/ralph-loop/steps/step-02-execute.md +68 -680
- package/templates/skills/ralph-loop/steps/step-03-commit.md +47 -277
- package/templates/skills/ralph-loop/steps/step-04-check.md +124 -607
- package/templates/skills/ralph-loop/steps/step-05-report.md +68 -367
- package/templates/skills/refactor/SKILL.md +12 -176
- package/templates/skills/refactor/steps/step-01-discover.md +60 -0
- package/templates/skills/refactor/steps/step-02-execute.md +67 -0
- package/templates/skills/review-code/SKILL.md +19 -257
- package/templates/skills/review-code/steps/step-01-smartstack.md +96 -0
- package/templates/skills/review-code/steps/step-02-detailed-review.md +80 -0
- package/templates/skills/review-code/steps/step-03-react.md +44 -0
- package/templates/skills/ui-components/SKILL.md +7 -0
- package/templates/skills/utils/SKILL.md +6 -0
- package/templates/skills/validate/SKILL.md +6 -0
- package/templates/skills/validate-feature/SKILL.md +8 -0
- package/templates/skills/workflow/SKILL.md +40 -118
- package/templates/skills/workflow/steps/step-01-implementation.md +84 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Task Transform: Legacy PrdJson → Ralph v2 (DEPRECATED)
|
|
2
|
+
|
|
3
|
+
> Reference for step-01-task.md — fallback transformation for old FORMAT A PRDs (pre-v3.9.0).
|
|
4
|
+
> New PRDs generated by `ss derive-prd` use unified v3 format (`$version: "3.0.0"`)
|
|
5
|
+
> with pre-computed tasks. The v3 fast path in sections 0 and 1 bypasses this entirely.
|
|
6
|
+
> This function will be removed in a future release.
|
|
7
|
+
|
|
8
|
+
## FORMAT A Input Structure
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
{ version, source, project, requirements, businessRules, architecture, implementation, seedData }
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## transformPrdJsonToRalphV2(prdJson, moduleCode)
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
function transformPrdJsonToRalphV2(prdJson, moduleCode) {
|
|
18
|
+
const tasks = [];
|
|
19
|
+
let taskId = 1;
|
|
20
|
+
|
|
21
|
+
const layerOrder = [
|
|
22
|
+
{ key: "domain", category: "domain" },
|
|
23
|
+
{ key: "infrastructure", category: "infrastructure" },
|
|
24
|
+
{ key: "application", category: "application" },
|
|
25
|
+
{ key: "api", category: "api" },
|
|
26
|
+
{ key: "frontend", category: "frontend" },
|
|
27
|
+
{ key: "seedData", category: "infrastructure" },
|
|
28
|
+
{ key: "tests", category: "test" }
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const filesToCreate = prdJson.implementation?.filesToCreate || prdJson.filesToCreate || {};
|
|
32
|
+
const lastIdByCategory = {};
|
|
33
|
+
const frontendFiles = [];
|
|
34
|
+
const i18nFiles = [];
|
|
35
|
+
|
|
36
|
+
// --- Generate tasks from filesToCreate ---
|
|
37
|
+
for (const layer of layerOrder) {
|
|
38
|
+
const files = filesToCreate[layer.key] || [];
|
|
39
|
+
if (layer.category === "frontend") { frontendFiles.push(...files); continue; }
|
|
40
|
+
|
|
41
|
+
for (const fileSpec of files) {
|
|
42
|
+
if (fileSpec.path?.includes('i18n/') || fileSpec.path?.includes('/locales/')) {
|
|
43
|
+
i18nFiles.push(fileSpec); continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const depIds = [];
|
|
47
|
+
if (lastIdByCategory[layer.category]) depIds.push(lastIdByCategory[layer.category]);
|
|
48
|
+
if (layer.category === "api" && lastIdByCategory["application"]) depIds.push(lastIdByCategory["application"]);
|
|
49
|
+
if (layer.category === "test" && lastIdByCategory["api"]) depIds.push(lastIdByCategory["api"]);
|
|
50
|
+
|
|
51
|
+
const allFRs = prdJson.requirements?.functionalRequirements || prdJson.functionalRequirements || [];
|
|
52
|
+
const linkedFRs = (fileSpec.linkedFRs || []).map(frId => allFRs.find(f => f.id === frId)?.statement || frId);
|
|
53
|
+
let criteria = linkedFRs.length > 0 ? `Implements: ${linkedFRs.join("; ")}` : `File ${fileSpec.path} created and compiles`;
|
|
54
|
+
|
|
55
|
+
const permMatrix = prdJson.architecture?.permissionMatrix || prdJson.permissionMatrix;
|
|
56
|
+
if (layer.category === "api" && permMatrix?.permissions?.length > 0) {
|
|
57
|
+
criteria += "; MANDATORY: [RequirePermission] on every endpoint (NOT [Authorize])";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
tasks.push({
|
|
61
|
+
id: taskId, description: fileSpec.description ? `[${layer.category}] ${fileSpec.description} → ${fileSpec.path}` : `[${layer.category}] Create ${fileSpec.type}: ${fileSpec.path}`,
|
|
62
|
+
status: "pending", category: layer.category, dependencies: [...new Set(depIds)],
|
|
63
|
+
acceptance_criteria: criteria, started_at: null, completed_at: null, iteration: null,
|
|
64
|
+
commit_hash: null, files_changed: { created: [fileSpec.path], modified: [] },
|
|
65
|
+
validation: null, error: null, module: moduleCode
|
|
66
|
+
});
|
|
67
|
+
lastIdByCategory[layer.category] = taskId;
|
|
68
|
+
taskId++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// --- 1b. Consolidated frontend task ---
|
|
73
|
+
if (frontendFiles.length > 0) {
|
|
74
|
+
const apiDepId = lastIdByCategory["api"] || lastIdByCategory["application"];
|
|
75
|
+
const ctx = (prdJson.project?.context || 'Business').replace(/^./, c => c.toUpperCase());
|
|
76
|
+
const app = prdJson.project?.application || moduleCode;
|
|
77
|
+
tasks.push({
|
|
78
|
+
id: taskId,
|
|
79
|
+
description: `[frontend] Generate COMPLETE frontend for module ${moduleCode} via MCP (${frontendFiles.length} files)`,
|
|
80
|
+
status: "pending", category: "frontend", dependencies: apiDepId ? [apiDepId] : [],
|
|
81
|
+
acceptance_criteria: `Pages in src/pages/${ctx}/${app}/${moduleCode}/; MCP scaffold_api_client + scaffold_routes; SmartTable for lists; CSS variables ONLY; 4-language i18n; npm run typecheck passes`,
|
|
82
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
83
|
+
files_changed: { created: frontendFiles.map(f => f.path), modified: [] },
|
|
84
|
+
validation: null, error: null, module: moduleCode,
|
|
85
|
+
_frontendMeta: { wireframes: [...new Set(frontendFiles.flatMap(f => f.linkedWireframes || []))], filesToCreate: frontendFiles }
|
|
86
|
+
});
|
|
87
|
+
lastIdByCategory["frontend"] = taskId; taskId++;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// --- 1c. Consolidated i18n task ---
|
|
91
|
+
if (i18nFiles.length > 0) {
|
|
92
|
+
tasks.push({
|
|
93
|
+
id: taskId, description: `[i18n] Generate i18n for module ${moduleCode} (4 languages)`,
|
|
94
|
+
status: "pending", category: "i18n", dependencies: lastIdByCategory["frontend"] ? [lastIdByCategory["frontend"]] : [],
|
|
95
|
+
acceptance_criteria: "4 JSON files (fr, en, it, de) with identical keys",
|
|
96
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
97
|
+
files_changed: { created: i18nFiles.map(f => f.path), modified: [] },
|
|
98
|
+
validation: null, error: null, module: moduleCode
|
|
99
|
+
});
|
|
100
|
+
lastIdByCategory["i18n"] = taskId; taskId++;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// --- GUARDRAILS: Inject missing layers ---
|
|
104
|
+
const entities = prdJson.architecture?.entities || prdJson.entities || [];
|
|
105
|
+
const apiEndpoints = prdJson.architecture?.apiEndpoints || prdJson.apiEndpoints || [];
|
|
106
|
+
const sections = prdJson.architecture?.sections || prdJson.sections || [];
|
|
107
|
+
const wireframes = prdJson.specification?.uiWireframes || prdJson.uiWireframes || [];
|
|
108
|
+
const dashboards = prdJson.specification?.dashboards || prdJson.dashboards || [];
|
|
109
|
+
|
|
110
|
+
// 1d. INJECT missing infrastructure
|
|
111
|
+
if (!tasks.some(t => t.category === 'infrastructure') && entities.length > 0) {
|
|
112
|
+
tasks.push({ id: taskId, description: `[infrastructure] Create EF Core configs and seed data for ${moduleCode} (${entities.length} entities)`,
|
|
113
|
+
status: "pending", category: "infrastructure", dependencies: lastIdByCategory["domain"] ? [lastIdByCategory["domain"]] : [],
|
|
114
|
+
acceptance_criteria: `EF configs for ${entities.length} entities; DbSet in ExtensionsDbContext; DI registration`,
|
|
115
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
116
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode });
|
|
117
|
+
lastIdByCategory["infrastructure"] = taskId; taskId++;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 1e. INJECT missing API
|
|
121
|
+
if (!tasks.some(t => t.category === 'api') && apiEndpoints.length > 0) {
|
|
122
|
+
const permMatrix = prdJson.architecture?.permissionMatrix || prdJson.permissionMatrix;
|
|
123
|
+
tasks.push({ id: taskId, description: `[api] Create controllers for ${moduleCode} (${apiEndpoints.length} endpoints)`,
|
|
124
|
+
status: "pending", category: "api", dependencies: [lastIdByCategory["application"] || lastIdByCategory["infrastructure"]].filter(Boolean),
|
|
125
|
+
acceptance_criteria: `${apiEndpoints.length} endpoints; ${permMatrix?.permissions?.length > 0 ? "[RequirePermission] on every endpoint" : "Authorization"}; Swagger`,
|
|
126
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
127
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode });
|
|
128
|
+
lastIdByCategory["api"] = taskId; taskId++;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 1f. INJECT missing frontend
|
|
132
|
+
if (frontendFiles.length === 0 && (sections.length > 0 || wireframes.length > 0 || apiEndpoints.length > 0)) {
|
|
133
|
+
const ctx = (prdJson.project?.context || 'Business').replace(/^./, c => c.toUpperCase());
|
|
134
|
+
const app = prdJson.project?.application || moduleCode;
|
|
135
|
+
const derivedFiles = wireframes.map(wf => ({ path: `web/src/pages/${ctx}/${app}/${moduleCode}/${wf.screen || wf.id}.tsx`, type: 'Page' }));
|
|
136
|
+
if (apiEndpoints.length > 0) derivedFiles.push({ path: `web/src/services/api/${moduleCode}Api.ts`, type: 'ApiService' });
|
|
137
|
+
|
|
138
|
+
tasks.push({ id: taskId,
|
|
139
|
+
description: `[frontend] Generate COMPLETE frontend for ${moduleCode} via MCP (${derivedFiles.length} files)`,
|
|
140
|
+
status: "pending", category: "frontend", dependencies: [lastIdByCategory["api"] || lastIdByCategory["application"]].filter(Boolean),
|
|
141
|
+
acceptance_criteria: `Pages in src/pages/${ctx}/${app}/${moduleCode}/; SmartTable for lists; CSS variables ONLY; 4-language i18n; npm run typecheck passes`,
|
|
142
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
143
|
+
files_changed: { created: derivedFiles.map(f => f.path), modified: [] },
|
|
144
|
+
validation: null, error: null, module: moduleCode,
|
|
145
|
+
_frontendMeta: { wireframes: wireframes.map(w => w.screen || w.id), filesToCreate: derivedFiles, source: "guardrail-derived" }
|
|
146
|
+
});
|
|
147
|
+
lastIdByCategory["frontend"] = taskId; taskId++;
|
|
148
|
+
|
|
149
|
+
// Also inject i18n
|
|
150
|
+
if (i18nFiles.length === 0) {
|
|
151
|
+
tasks.push({ id: taskId, description: `[i18n] Generate i18n for ${moduleCode} (4 languages)`,
|
|
152
|
+
status: "pending", category: "i18n", dependencies: [lastIdByCategory["frontend"]],
|
|
153
|
+
acceptance_criteria: "4 JSON files (fr, en, it, de) with identical keys",
|
|
154
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
155
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode });
|
|
156
|
+
lastIdByCategory["i18n"] = taskId; taskId++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 1g. INJECT missing tests
|
|
161
|
+
if (!tasks.some(t => t.category === 'test') && entities.length > 0) {
|
|
162
|
+
const migDepId = lastIdByCategory["migration"] || lastIdByCategory["api"] || lastIdByCategory["application"];
|
|
163
|
+
tasks.push({ id: taskId, description: `[test] Create unit and integration tests for ${moduleCode}`,
|
|
164
|
+
status: "pending", category: "test", dependencies: migDepId ? [migDepId] : [],
|
|
165
|
+
acceptance_criteria: "Domain + service + controller tests; dotnet test passes; coverage >= 80%",
|
|
166
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
167
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode });
|
|
168
|
+
lastIdByCategory["test"] = taskId; taskId++;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 1h. GUARDRAIL: Core seed data (navigation, permissions, roles)
|
|
172
|
+
const coreSeedData = prdJson.seedData?.core || prdJson.seedDataCore || prdJson.specification?.seedDataCore;
|
|
173
|
+
const hasSeedDataInTasks = tasks.some(t => t.description?.includes("SeedData") || t.description?.includes("seed data"));
|
|
174
|
+
if (coreSeedData && !hasSeedDataInTasks) {
|
|
175
|
+
const infraDepId = lastIdByCategory["infrastructure"] || lastIdByCategory["domain"];
|
|
176
|
+
const navModules = coreSeedData.navigationModules || coreSeedData.navigation || [];
|
|
177
|
+
const permissions = coreSeedData.permissions || [];
|
|
178
|
+
const rolePerms = coreSeedData.rolePermissions || [];
|
|
179
|
+
tasks.push({
|
|
180
|
+
id: taskId, description: `[infrastructure] Create core seed data for ${moduleCode}: NavigationModuleSeedData, PermissionsSeedData, RolesSeedData`,
|
|
181
|
+
status: "pending", category: "infrastructure", dependencies: infraDepId ? [infraDepId] : [],
|
|
182
|
+
acceptance_criteria: `NavigationModuleSeedData (${navModules.length} nav); PermissionsSeedData (${permissions.length} perms); RolesSeedData (${rolePerms.length} roles); SeedConstants; dotnet build passes`,
|
|
183
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
184
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode,
|
|
185
|
+
_seedDataMeta: {
|
|
186
|
+
source: "guardrail-derived", coreSeedData,
|
|
187
|
+
navRoute: prdJson.project?.navRoute || `business.${prdJson.project?.application || 'app'}.${moduleCode}`,
|
|
188
|
+
contextCode: prdJson.project?.context || 'business',
|
|
189
|
+
appCode: prdJson.project?.application, appLabels: prdJson.project?.labels || null
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
lastIdByCategory["infrastructure"] = taskId; taskId++;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 1i. GUARDRAIL: IClientSeedDataProvider
|
|
196
|
+
const hasProvider = tasks.some(t => t.description?.includes("IClientSeedDataProvider") || t.description?.includes("SeedDataProvider"));
|
|
197
|
+
if (!hasProvider && (filesToCreate["seedData"]?.length > 0 || coreSeedData)) {
|
|
198
|
+
tasks.push({
|
|
199
|
+
id: taskId, description: `[infrastructure] Create IClientSeedDataProvider for core seed data injection`,
|
|
200
|
+
status: "pending", category: "infrastructure",
|
|
201
|
+
dependencies: [lastIdByCategory["infrastructure"] || lastIdByCategory["domain"]].filter(Boolean),
|
|
202
|
+
acceptance_criteria: "SeedNavigationAsync + SeedPermissionsAsync + SeedRolePermissionsAsync; DI registered; idempotent",
|
|
203
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
204
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode,
|
|
205
|
+
_providerMeta: {
|
|
206
|
+
navRoute: prdJson.project?.navRoute || `business.${prdJson.project?.application || 'app'}.${moduleCode}`,
|
|
207
|
+
contextCode: prdJson.project?.context || 'business', appCode: prdJson.project?.application
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
lastIdByCategory["infrastructure"] = taskId; taskId++;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 1j. GUARDRAIL: EF Core migration (CRITICAL — without this, no DB schema, no tests)
|
|
214
|
+
const hasEntities = entities.length > 0 || tasks.some(t => t.category === 'domain');
|
|
215
|
+
const hasMigration = tasks.some(t => t.description?.toLowerCase().includes('migration'));
|
|
216
|
+
if (hasEntities && !hasMigration) {
|
|
217
|
+
tasks.push({
|
|
218
|
+
id: taskId, description: `[infrastructure] Create EF Core migration for ${moduleCode}`,
|
|
219
|
+
status: "pending", category: "infrastructure",
|
|
220
|
+
dependencies: [lastIdByCategory["infrastructure"]].filter(Boolean),
|
|
221
|
+
acceptance_criteria: "MCP suggest_migration → name; dotnet ef migrations add; dotnet ef database update; dotnet build passes",
|
|
222
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
223
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode,
|
|
224
|
+
_migrationMeta: { entities: entities.map(e => e.name || e.code), moduleCode }
|
|
225
|
+
});
|
|
226
|
+
lastIdByCategory["migration"] = taskId; taskId++;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Final validation task
|
|
230
|
+
tasks.push({
|
|
231
|
+
id: taskId, description: `[validation] Build, test, and MCP validate module ${moduleCode}`,
|
|
232
|
+
status: "pending", category: "validation", dependencies: Object.values(lastIdByCategory),
|
|
233
|
+
acceptance_criteria: "dotnet build succeeds; dotnet test passes; MCP validate_conventions clean",
|
|
234
|
+
started_at: null, completed_at: null, iteration: null, commit_hash: null,
|
|
235
|
+
files_changed: { created: [], modified: [] }, validation: null, error: null, module: moduleCode
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
$version: "2.0.0", feature: `${prdJson.project?.module || moduleCode} (${prdJson.project?.application || "app"})`,
|
|
240
|
+
status: "in_progress", created: new Date().toISOString(), updated_at: new Date().toISOString(),
|
|
241
|
+
metadata: { cli_version: "unknown", branch: getCurrentBranch(), project_path: process.cwd(), mcp_servers: { smartstack: true, context7: true }, moduleCode },
|
|
242
|
+
config: { max_iterations: {max_iterations}, completion_promise: "{completion_promise}", current_iteration: 1 },
|
|
243
|
+
source: { type: "ba-handoff", handoff_path: null, feature_json_path: prdJson.source?.featureJson || null, module: moduleCode },
|
|
244
|
+
tasks, history: []
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Guardrails Summary
|
|
250
|
+
|
|
251
|
+
| ID | Guardrail | Condition | Injection |
|
|
252
|
+
|----|-----------|-----------|-----------|
|
|
253
|
+
| 1d | Missing infrastructure | entities exist, no infra tasks | EF Core configs + seed data |
|
|
254
|
+
| 1e | Missing API | apiEndpoints exist, no api tasks | Controllers |
|
|
255
|
+
| 1f | Missing frontend | sections/wireframes exist, no frontend tasks | Pages + API service |
|
|
256
|
+
| 1g | Missing tests | entities exist, no test tasks | Unit + integration tests |
|
|
257
|
+
| 1h | Core seed data | coreSeedData exists, no seed tasks | Navigation + Permissions + Roles |
|
|
258
|
+
| 1i | IClientSeedDataProvider | seedData files or coreSeedData, no provider task | Provider class |
|
|
259
|
+
| 1j | EF Core migration | entities exist, no migration task | Migration (CRITICAL) |
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Team Orchestration — Multi-Module Parallel Execution
|
|
2
|
+
|
|
3
|
+
> **Loaded by:** step-00 when multi-module detected (PRD_COUNT > 1)
|
|
4
|
+
> **Purpose:** Parallelize independent modules via Agent Teams.
|
|
5
|
+
> **Rule:** Single module = NO team. Only create team for 2+ modules.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Layer Detection
|
|
10
|
+
|
|
11
|
+
Read dependency graph from master feature.json:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
const master = readJSON(MASTER_FEATURE);
|
|
15
|
+
const layers = master.metadata?.workflow?.dependencyGraph?.layers
|
|
16
|
+
|| master.dependencyGraph?.layers;
|
|
17
|
+
|
|
18
|
+
// Example layers:
|
|
19
|
+
// [
|
|
20
|
+
// { layer: 0, modules: ["employees"], reason: "foundation" },
|
|
21
|
+
// { layer: 1, modules: ["timetracking", "leavemanagement"], reason: "depends on employees" },
|
|
22
|
+
// { layer: 2, modules: ["reporting"], reason: "depends on all" }
|
|
23
|
+
// ]
|
|
24
|
+
|
|
25
|
+
// Fallback: if no layers, treat all modules as sequential (layer 0, 1, 2...)
|
|
26
|
+
if (!layers) {
|
|
27
|
+
const modules = queue.modules.map((m, i) => ({
|
|
28
|
+
layer: i, modules: [m.code], reason: "sequential"
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 2. Team Setup
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
// Create team
|
|
39
|
+
TeamCreate({ team_name: `ralph-${appName}` });
|
|
40
|
+
|
|
41
|
+
// Store team context
|
|
42
|
+
const teamContext = {
|
|
43
|
+
teamName: `ralph-${appName}`,
|
|
44
|
+
layers: layers,
|
|
45
|
+
currentLayer: 0,
|
|
46
|
+
teammates: {} // name → agentId mapping (populated after spawn)
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 3. Teammate Spawn — Per Layer
|
|
53
|
+
|
|
54
|
+
For each layer, spawn teammates IN PARALLEL (single message, multiple Task calls):
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
for (const layer of layers) {
|
|
58
|
+
// Wait for previous layer to complete (except layer 0)
|
|
59
|
+
if (layer.layer > 0) {
|
|
60
|
+
// WAIT: check for MODULE_COMPLETE messages from all previous layer teammates
|
|
61
|
+
// Messages are automatically delivered via SendMessage
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Spawn all modules in this layer in parallel
|
|
65
|
+
for (const moduleCode of layer.modules) {
|
|
66
|
+
const prdFile = `.ralph/prd-${moduleCode}.json`;
|
|
67
|
+
const prdContent = readJSON(prdFile);
|
|
68
|
+
|
|
69
|
+
Task({
|
|
70
|
+
subagent_type: "general-purpose",
|
|
71
|
+
team_name: `ralph-${appName}`,
|
|
72
|
+
name: `mod-${moduleCode}`,
|
|
73
|
+
mode: "bypassPermissions",
|
|
74
|
+
prompt: TEAMMATE_PROMPT(moduleCode, prdContent),
|
|
75
|
+
description: `Module ${moduleCode}`
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 4. Teammate Prompt Template
|
|
84
|
+
|
|
85
|
+
Each teammate receives a self-contained prompt with all context:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
You are a Ralph Loop module worker for module "${moduleCode}".
|
|
89
|
+
|
|
90
|
+
## Your Mission
|
|
91
|
+
Implement ALL tasks in the PRD below, following SmartStack conventions.
|
|
92
|
+
Execute autonomously: domain → infrastructure → MIGRATION → seed data → application → api → frontend → i18n → tests → validation.
|
|
93
|
+
|
|
94
|
+
## PRD (your task list)
|
|
95
|
+
${JSON.stringify(prdContent, null, 2)}
|
|
96
|
+
|
|
97
|
+
## Execution Rules
|
|
98
|
+
1. Read the skill file at: templates/skills/ralph-loop/references/category-rules.md
|
|
99
|
+
2. For seed data tasks, also read: templates/skills/ralph-loop/references/core-seed-data.md
|
|
100
|
+
3. Follow SmartStack conventions (MCP validation after each batch)
|
|
101
|
+
4. MIGRATION is MANDATORY after EF configs: mcp suggest_migration → dotnet ef migrations add → database update
|
|
102
|
+
5. Tests MUST pass before proceeding (dotnet test = 0 failures)
|
|
103
|
+
6. Frontend in src/pages/{Context}/{App}/{Module}/ (NOT flat)
|
|
104
|
+
7. Commit after each batch: git add + git commit
|
|
105
|
+
|
|
106
|
+
## Communication Protocol
|
|
107
|
+
- After domain + infrastructure + migration are done and build passes:
|
|
108
|
+
SendMessage({ type: "message", recipient: "team-lead", content: "LAYER_READY:${moduleCode}", summary: "${moduleCode} foundation ready" })
|
|
109
|
+
- When ALL tasks complete:
|
|
110
|
+
SendMessage({ type: "message", recipient: "team-lead", content: "MODULE_COMPLETE:${moduleCode}", summary: "${moduleCode} complete" })
|
|
111
|
+
- On blocking error:
|
|
112
|
+
SendMessage({ type: "message", recipient: "team-lead", content: "ERROR:${moduleCode}:{error}", summary: "${moduleCode} blocked" })
|
|
113
|
+
|
|
114
|
+
## Project Context
|
|
115
|
+
- Project path: ${projectPath}
|
|
116
|
+
- Branch: ${branch}
|
|
117
|
+
- Application: ${appName}
|
|
118
|
+
- Context: ${contextCode}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 5. Team Lead Wait Logic
|
|
124
|
+
|
|
125
|
+
After spawning a layer, the team lead waits for completion:
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
// Track expected messages
|
|
129
|
+
const expectedMessages = layer.modules.length;
|
|
130
|
+
let receivedComplete = 0;
|
|
131
|
+
let receivedReady = 0;
|
|
132
|
+
let errors = [];
|
|
133
|
+
|
|
134
|
+
// Messages arrive automatically via SendMessage
|
|
135
|
+
// When a teammate sends "MODULE_COMPLETE:xxx", increment counter
|
|
136
|
+
// When a teammate sends "ERROR:xxx:yyy", record error
|
|
137
|
+
|
|
138
|
+
// For LAYER_READY: wait until all layer 0 modules signal before spawning layer 1
|
|
139
|
+
// For MODULE_COMPLETE: wait until all layer N modules complete before spawning layer N+1
|
|
140
|
+
|
|
141
|
+
// If error received:
|
|
142
|
+
// - Log to progress.txt
|
|
143
|
+
// - Decide: retry module or mark as partial
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 6. Cross-Module Verification
|
|
149
|
+
|
|
150
|
+
After all layers complete, team lead runs:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Full solution build
|
|
154
|
+
dotnet build --no-restore
|
|
155
|
+
|
|
156
|
+
# Full test suite
|
|
157
|
+
dotnet test --no-build
|
|
158
|
+
|
|
159
|
+
# MCP validation
|
|
160
|
+
mcp__smartstack__validate_conventions checks=["all"]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 7. Cleanup
|
|
166
|
+
|
|
167
|
+
After all modules done and report generated:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
// Shutdown all teammates
|
|
171
|
+
for (const [name, _] of Object.entries(teamContext.teammates)) {
|
|
172
|
+
SendMessage({ type: "shutdown_request", recipient: name, content: "All modules complete" });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Wait for shutdown confirmations, then:
|
|
176
|
+
TeamDelete();
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Decision Matrix
|
|
182
|
+
|
|
183
|
+
| Condition | Action |
|
|
184
|
+
|-----------|--------|
|
|
185
|
+
| 1 module | NO team, classic compact loop |
|
|
186
|
+
| 2+ modules, no dependency graph | Sequential layers (one at a time) |
|
|
187
|
+
| 2+ modules, with layers | Parallel within each layer |
|
|
188
|
+
| Teammate error | Log, try to continue other modules |
|
|
189
|
+
| All modules done | Cross-module verify → step-05 → TeamDelete |
|