@atlashub/smartstack-cli 3.31.0 → 3.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.documentation/installation.html +7 -2
- package/README.md +7 -1
- package/dist/index.js +33 -37
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +547 -97
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/scripts/health-check.sh +2 -1
- package/templates/mcp-scaffolding/controller.cs.hbs +10 -7
- package/templates/mcp-scaffolding/entity-extension.cs.hbs +132 -124
- package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +4 -4
- package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +38 -15
- package/templates/mcp-scaffolding/tests/service.test.cs.hbs +20 -8
- package/templates/skills/apex/SKILL.md +7 -9
- package/templates/skills/apex/_shared.md +9 -2
- package/templates/skills/apex/references/code-generation.md +412 -0
- package/templates/skills/apex/references/post-checks.md +377 -37
- package/templates/skills/apex/references/smartstack-api.md +229 -5
- package/templates/skills/apex/references/smartstack-frontend.md +368 -11
- package/templates/skills/apex/references/smartstack-layers.md +54 -7
- package/templates/skills/apex/steps/step-00-init.md +1 -2
- package/templates/skills/apex/steps/step-01-analyze.md +45 -2
- package/templates/skills/apex/steps/step-02-plan.md +23 -2
- package/templates/skills/apex/steps/step-03-execute.md +195 -5
- package/templates/skills/apex/steps/step-04-examine.md +18 -5
- package/templates/skills/apex/steps/step-05-deep-review.md +9 -11
- package/templates/skills/apex/steps/step-06-resolve.md +5 -9
- package/templates/skills/apex/steps/step-07-tests.md +66 -1
- package/templates/skills/apex/steps/step-08-run-tests.md +12 -3
- package/templates/skills/application/references/provider-template.md +62 -39
- package/templates/skills/application/templates-backend.md +3 -3
- package/templates/skills/application/templates-frontend.md +12 -12
- package/templates/skills/application/templates-seed.md +14 -4
- package/templates/skills/business-analyse/SKILL.md +9 -6
- package/templates/skills/business-analyse/questionnaire/04-data.md +8 -0
- package/templates/skills/business-analyse/references/agent-module-prompt.md +84 -5
- package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +83 -19
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +6 -2
- package/templates/skills/business-analyse/references/team-orchestration.md +443 -110
- package/templates/skills/business-analyse/references/validation-checklist.md +5 -4
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +44 -0
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +72 -1
- package/templates/skills/business-analyse/steps/step-03c-compile.md +93 -7
- package/templates/skills/business-analyse/steps/step-03d-validate.md +34 -2
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +40 -0
- package/templates/skills/controller/references/controller-code-templates.md +2 -2
- package/templates/skills/controller/templates.md +12 -12
- package/templates/skills/feature-full/steps/step-01-implementation.md +4 -4
- package/templates/skills/ralph-loop/references/category-rules.md +44 -2
- package/templates/skills/ralph-loop/references/compact-loop.md +37 -0
- package/templates/skills/ralph-loop/references/core-seed-data.md +51 -20
- package/templates/skills/review-code/references/owasp-api-top10.md +1 -1
|
@@ -6,7 +6,7 @@ prev_step: steps/step-07-tests.md
|
|
|
6
6
|
next_step: COMPLETE
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
# Step 8: Run Tests
|
|
9
|
+
# Step 8: Run Tests
|
|
10
10
|
|
|
11
11
|
**CRITICAL:** Fix the CODE, not the tests. Tests represent expected behavior.
|
|
12
12
|
100% pass required for Sonar quality gate.
|
|
@@ -85,13 +85,22 @@ questions:
|
|
|
85
85
|
|
|
86
86
|
---
|
|
87
87
|
|
|
88
|
-
## 5. Frontend Typecheck (if applicable)
|
|
88
|
+
## 5. Frontend Tests + Typecheck (if applicable)
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
|
+
# Run frontend tests first
|
|
92
|
+
WEB_DIR=$(find . -name "vitest.config.ts" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
|
|
93
|
+
if [ -n "$WEB_DIR" ]; then
|
|
94
|
+
cd "$WEB_DIR"
|
|
95
|
+
npm run test
|
|
96
|
+
cd -
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# Then typecheck
|
|
91
100
|
npm run typecheck
|
|
92
101
|
```
|
|
93
102
|
|
|
94
|
-
**MUST PASS.**
|
|
103
|
+
**BOTH MUST PASS.** If frontend tests fail, apply the same fix loop as backend (fix CODE, not tests, max 5 iterations).
|
|
95
104
|
|
|
96
105
|
---
|
|
97
106
|
|
|
@@ -30,49 +30,71 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
|
30
30
|
|
|
31
31
|
public async Task SeedNavigationAsync(ICoreDbContext context, CancellationToken ct)
|
|
32
32
|
{
|
|
33
|
-
//
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// 1. Retrieve the parent context ("business", "platform", etc.)
|
|
39
|
-
var parentContext = await context.NavigationContexts
|
|
40
|
-
.FirstAsync(c => c.Code == "{context_code}", ct);
|
|
41
|
-
|
|
42
|
-
// 2. Create the application
|
|
43
|
-
var app = NavigationApplication.Create(
|
|
44
|
-
parentContext.Id,
|
|
45
|
-
"{app_code}",
|
|
46
|
-
"{app_label_en}",
|
|
47
|
-
"{app_desc_en}",
|
|
48
|
-
"{app_icon}",
|
|
49
|
-
IconType.Lucide,
|
|
50
|
-
"/{context_code}/{app_code}",
|
|
51
|
-
{display_order});
|
|
52
|
-
context.NavigationApplications.Add(app);
|
|
53
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
33
|
+
// --- Application (idempotent — reuse if already exists) ---
|
|
34
|
+
var appEntry = NavigationApplicationSeedData.GetApplicationEntry(Guid.Empty);
|
|
35
|
+
var existingApp = await context.NavigationApplications
|
|
36
|
+
.FirstOrDefaultAsync(a => a.Code == appEntry.Code, ct);
|
|
54
37
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
38
|
+
NavigationApplication app;
|
|
39
|
+
if (existingApp != null)
|
|
40
|
+
{
|
|
41
|
+
app = existingApp; // Reuse existing for module seeding below
|
|
42
|
+
}
|
|
43
|
+
else
|
|
58
44
|
{
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
context.
|
|
45
|
+
var parentContext = await context.NavigationContexts
|
|
46
|
+
.FirstAsync(c => c.Code == "{context_code}", ct);
|
|
47
|
+
|
|
48
|
+
appEntry = NavigationApplicationSeedData.GetApplicationEntry(parentContext.Id);
|
|
49
|
+
app = NavigationApplication.Create(
|
|
50
|
+
appEntry.ContextId, appEntry.Code, appEntry.Label,
|
|
51
|
+
appEntry.Description, appEntry.Icon, appEntry.IconType,
|
|
52
|
+
appEntry.Route, appEntry.DisplayOrder);
|
|
53
|
+
context.NavigationApplications.Add(app);
|
|
54
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
55
|
+
|
|
56
|
+
// Application translations (only when creating new application)
|
|
57
|
+
foreach (var t in NavigationApplicationSeedData.GetTranslationEntries())
|
|
58
|
+
{
|
|
59
|
+
context.NavigationTranslations.Add(
|
|
60
|
+
NavigationTranslation.Create(t.EntityType, t.EntityId, t.LanguageCode, t.Label, t.Description));
|
|
61
|
+
}
|
|
62
|
+
await ((DbContext)context).SaveChangesAsync(ct);
|
|
69
63
|
}
|
|
64
|
+
|
|
65
|
+
// --- Modules (idempotent per-module) ---
|
|
66
|
+
// var mod1Exists = await context.NavigationModules.AnyAsync(
|
|
67
|
+
// m => m.Code == "{module_code}" && m.ApplicationId == app.Id, ct);
|
|
68
|
+
// if (!mod1Exists) { context.NavigationModules.Add(NavigationModule.Create(...)); }
|
|
69
|
+
// Repeat per module...
|
|
70
70
|
await ((DbContext)context).SaveChangesAsync(ct);
|
|
71
71
|
|
|
72
|
-
//
|
|
73
|
-
//
|
|
74
|
-
//
|
|
72
|
+
// Resolve module entities
|
|
73
|
+
// var mod1Entity = await context.NavigationModules.FirstAsync(
|
|
74
|
+
// m => m.Code == "{module_code}" && m.ApplicationId == app.Id, ct);
|
|
75
|
+
|
|
76
|
+
// --- Module translations (IDEMPOTENT — check before inserting) ---
|
|
77
|
+
// CRITICAL: nav_Translations has unique index IX_nav_Translations_EntityType_EntityId_LanguageCode
|
|
78
|
+
// Always guard with AnyAsync to prevent duplicate key errors on re-runs.
|
|
79
|
+
// if (!await context.NavigationTranslations.AnyAsync(
|
|
80
|
+
// t => t.EntityId == {Module}NavigationSeedData.{Module}ModuleId
|
|
81
|
+
// && t.EntityType == NavigationEntityType.Module, ct))
|
|
82
|
+
// { foreach (var t in {Module}NavigationSeedData.GetTranslationEntries()) { ... } }
|
|
75
83
|
await ((DbContext)context).SaveChangesAsync(ct);
|
|
84
|
+
|
|
85
|
+
// --- Sections (idempotent per-section) ---
|
|
86
|
+
// Check each section before inserting: AnyAsync(s => s.Code == secEntry.Code && s.ModuleId == ...)
|
|
87
|
+
|
|
88
|
+
// --- Section translations (IDEMPOTENT — same guard pattern as module translations) ---
|
|
89
|
+
// if (!await context.NavigationTranslations.AnyAsync(
|
|
90
|
+
// t => t.EntityId == secEntry.Id && t.EntityType == NavigationEntityType.Section, ct))
|
|
91
|
+
|
|
92
|
+
// --- Resources (idempotent — use ACTUAL section IDs from DB) ---
|
|
93
|
+
// CRITICAL: NavigationSection.Create() generates its own ID. Deterministic seed GUIDs
|
|
94
|
+
// do NOT match actual SectionId in DB → FK_nav_Resources_nav_Sections_SectionId violation.
|
|
95
|
+
// MUST query actual section: var actualSection = await context.NavigationSections
|
|
96
|
+
// .FirstAsync(s => s.Code == secEntry.Code && s.ModuleId == modEntity.Id, ct);
|
|
97
|
+
// Then use actualSection.Id (NOT secEntry.Id) for NavigationResource.Create() and AnyAsync
|
|
76
98
|
}
|
|
77
99
|
|
|
78
100
|
public async Task SeedRolesAsync(ICoreDbContext context, CancellationToken ct)
|
|
@@ -150,8 +172,9 @@ services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>();
|
|
|
150
172
|
## Critical Rules
|
|
151
173
|
|
|
152
174
|
1. **Factory methods mandatory**: `NavigationModule.Create(...)`, `Role.Create(...)`, `Permission.CreateForModule(...)`, `RolePermission.Create(...)` — NEVER `new Entity()`
|
|
153
|
-
2. **Idempotence**: Each Seed method checks existence before inserting
|
|
154
|
-
3. **
|
|
175
|
+
2. **Idempotence**: Each Seed method checks existence before inserting. **Translations require explicit `AnyAsync` guard** — unique index `IX_nav_Translations_EntityType_EntityId_LanguageCode` causes crashes on duplicate inserts
|
|
176
|
+
3. **Translation guard pattern**: `if (!await context.NavigationTranslations.AnyAsync(t => t.EntityId == {id} && t.EntityType == ..., ct))` — MANDATORY before every translation batch insert
|
|
177
|
+
4. **SaveChangesAsync per group**: Navigation → save → Roles → save → Permissions → save → RolePermissions → save
|
|
155
178
|
4. **Execution order**: `SeedRolesAsync()` MUST be called BEFORE `SeedRolePermissionsAsync()` (roles must exist before mapping)
|
|
156
179
|
5. **Deterministic GUIDs**: Use IDs from SeedData classes (not `Guid.NewGuid()`)
|
|
157
180
|
6. **Resolve FK by Code**: Parent modules and roles are found by `Code`, not hardcoded GUID
|
|
@@ -55,7 +55,7 @@ namespace SmartStack.Application.Common.Interfaces;
|
|
|
55
55
|
|
|
56
56
|
public interface I$MODULE_PASCALService
|
|
57
57
|
{
|
|
58
|
-
Task<
|
|
58
|
+
Task<PaginatedResult<$ENTITY_PASCALDto>> GetAllAsync(
|
|
59
59
|
$ENTITY_PASCALQueryParameters parameters,
|
|
60
60
|
CancellationToken cancellationToken = default);
|
|
61
61
|
|
|
@@ -115,7 +115,7 @@ public class $MODULE_PASCALService : I$MODULE_PASCALService
|
|
|
115
115
|
_logger = logger;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
public async Task<
|
|
118
|
+
public async Task<PaginatedResult<$ENTITY_PASCALDto>> GetAllAsync(
|
|
119
119
|
$ENTITY_PASCALQueryParameters parameters,
|
|
120
120
|
CancellationToken cancellationToken = default)
|
|
121
121
|
{
|
|
@@ -159,7 +159,7 @@ public class $MODULE_PASCALService : I$MODULE_PASCALService
|
|
|
159
159
|
})
|
|
160
160
|
.ToListAsync(cancellationToken);
|
|
161
161
|
|
|
162
|
-
return new
|
|
162
|
+
return new PaginatedResult<$ENTITY_PASCALDto>
|
|
163
163
|
{
|
|
164
164
|
Items = items,
|
|
165
165
|
TotalCount = totalCount,
|
|
@@ -100,7 +100,7 @@ interface $ENTITY_PASCALDto {
|
|
|
100
100
|
updatedAt: string | null;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
interface
|
|
103
|
+
interface PaginatedResult {
|
|
104
104
|
items: $ENTITY_PASCALDto[];
|
|
105
105
|
totalCount: number;
|
|
106
106
|
page: number;
|
|
@@ -135,15 +135,15 @@ export function $MODULE_PASCALListView({
|
|
|
135
135
|
setViewMode,
|
|
136
136
|
} = use$MODULE_PASCALPreferences();
|
|
137
137
|
|
|
138
|
-
const [data, setData] = useState<
|
|
138
|
+
const [data, setData] = useState<PaginatedResult | null>(null);
|
|
139
139
|
const [loading, setLoading] = useState(true);
|
|
140
140
|
const [error, setError] = useState<string | null>(null);
|
|
141
141
|
const [page, setPage] = useState(1);
|
|
142
|
-
const [
|
|
142
|
+
const [search, setSearchTerm] = useState('');
|
|
143
143
|
|
|
144
144
|
useEffect(() => {
|
|
145
145
|
loadData();
|
|
146
|
-
}, [page, pageSize, sortColumn, sortDirection,
|
|
146
|
+
}, [page, pageSize, sortColumn, sortDirection, search]);
|
|
147
147
|
|
|
148
148
|
const loadData = async () => {
|
|
149
149
|
try {
|
|
@@ -154,9 +154,9 @@ export function $MODULE_PASCALListView({
|
|
|
154
154
|
pageSize: pageSize.toString(),
|
|
155
155
|
sortColumn,
|
|
156
156
|
sortDirection,
|
|
157
|
-
...(
|
|
157
|
+
...(search && { search }),
|
|
158
158
|
});
|
|
159
|
-
const result = await api.get<
|
|
159
|
+
const result = await api.get<PaginatedResult>(`/api/$module?${params}`);
|
|
160
160
|
setData(result);
|
|
161
161
|
} catch (err) {
|
|
162
162
|
setError(t('common:errors.loadFailed'));
|
|
@@ -222,7 +222,7 @@ export function $MODULE_PASCALListView({
|
|
|
222
222
|
<input
|
|
223
223
|
type="text"
|
|
224
224
|
placeholder={t('common:search.placeholder')}
|
|
225
|
-
value={
|
|
225
|
+
value={search}
|
|
226
226
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
227
227
|
className="w-full pl-10 pr-4 py-2 bg-[var(--bg-primary)] border border-[var(--border-color)] text-sm focus:outline-none focus:border-[var(--color-accent-500)]"
|
|
228
228
|
style={{ borderRadius: 'var(--radius-input)' }}
|
|
@@ -456,27 +456,27 @@ export interface Update$ENTITY_PASCALRequest {
|
|
|
456
456
|
description?: string;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
export interface
|
|
459
|
+
export interface PaginatedResult<T> {
|
|
460
460
|
items: T[];
|
|
461
461
|
totalCount: number;
|
|
462
462
|
page: number;
|
|
463
463
|
pageSize: number;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
export interface
|
|
466
|
+
export interface PaginationParams {
|
|
467
467
|
page?: number;
|
|
468
468
|
pageSize?: number;
|
|
469
|
-
|
|
469
|
+
search?: string;
|
|
470
470
|
sortColumn?: string;
|
|
471
471
|
sortDirection?: 'asc' | 'desc';
|
|
472
472
|
}
|
|
473
473
|
|
|
474
474
|
export const $moduleApi = {
|
|
475
|
-
getAll: async (params:
|
|
475
|
+
getAll: async (params: PaginationParams = {}): Promise<PaginatedResult<$ENTITY_PASCALDto>> => {
|
|
476
476
|
const queryParams = new URLSearchParams();
|
|
477
477
|
if (params.page) queryParams.set('page', params.page.toString());
|
|
478
478
|
if (params.pageSize) queryParams.set('pageSize', params.pageSize.toString());
|
|
479
|
-
if (params.
|
|
479
|
+
if (params.search) queryParams.set('search', params.search);
|
|
480
480
|
if (params.sortColumn) queryParams.set('sortColumn', params.sortColumn);
|
|
481
481
|
if (params.sortDirection) queryParams.set('sortDirection', params.sortDirection);
|
|
482
482
|
|
|
@@ -895,13 +895,23 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
|
895
895
|
// Create modules (idempotent per-module — check each before inserting)
|
|
896
896
|
// var mod1Exists = await context.NavigationModules.AnyAsync(m => m.Code == "{module_code}" && m.ApplicationId == app.Id, ct);
|
|
897
897
|
// if (!mod1Exists) { var mod1 = NavigationModule.Create(...); context.NavigationModules.Add(mod1); }
|
|
898
|
-
// Create module translations from {Module}NavigationSeedData.GetTranslationEntries()
|
|
899
898
|
|
|
900
|
-
//
|
|
899
|
+
// Module translations — IDEMPOTENT (unique index IX_nav_Translations_EntityType_EntityId_LanguageCode)
|
|
900
|
+
// CRITICAL: Always check before inserting to avoid duplicate key errors on re-runs
|
|
901
|
+
// if (!await context.NavigationTranslations.AnyAsync(
|
|
902
|
+
// t => t.EntityId == {Module}NavigationSeedData.{Module}ModuleId && t.EntityType == NavigationEntityType.Module, ct))
|
|
903
|
+
// { foreach (var t in {Module}NavigationSeedData.GetTranslationEntries()) { ... } }
|
|
904
|
+
|
|
905
|
+
// Sections (idempotent per-section — check each before inserting)
|
|
906
|
+
// var secExists = await context.NavigationSections.AnyAsync(s => s.Code == secEntry.Code && s.ModuleId == ..., ct);
|
|
901
907
|
// Use NavigationSection.Create(moduleId, code, label, description, icon, iconType, route, displayOrder)
|
|
902
|
-
// Create section translations from {Module}NavigationSeedData.GetSectionTranslationEntries()
|
|
903
908
|
|
|
904
|
-
//
|
|
909
|
+
// Section translations — IDEMPOTENT (same guard pattern as module translations)
|
|
910
|
+
// if (!await context.NavigationTranslations.AnyAsync(
|
|
911
|
+
// t => t.EntityId == secEntry.Id && t.EntityType == NavigationEntityType.Section, ct))
|
|
912
|
+
|
|
913
|
+
// Resources (idempotent per-resource — check each before inserting)
|
|
914
|
+
// var resExists = await context.NavigationResources.AnyAsync(r => r.Code == resEntry.Code && r.SectionId == ..., ct);
|
|
905
915
|
// Use NavigationResource.Create(sectionId, code, label, entityType, route, displayOrder)
|
|
906
916
|
}
|
|
907
917
|
|
|
@@ -285,19 +285,22 @@ Load ONLY relevant categories based on feature type:
|
|
|
285
285
|
| 1 module | Inline (classic, no team) |
|
|
286
286
|
| 2+ modules | Team mode (Propose & Review) |
|
|
287
287
|
|
|
288
|
-
**Team mode workflow (Propose & Review):**
|
|
288
|
+
**Team mode workflow (Parallel Propose & Review):**
|
|
289
289
|
1. Steps 00-02 execute inline in the main conversation (interactive with user)
|
|
290
290
|
2. After step-02 decomposition: clean up old team data (§1a), then `TeamCreate({ team_name: "ba-{appName}" })` — **CRITICAL: capture the RETURNED team name** (may differ from requested)
|
|
291
|
-
3. For each
|
|
292
|
-
4.
|
|
293
|
-
5. After
|
|
294
|
-
6.
|
|
291
|
+
3. For each dependency layer: pre-analyze cross-module touchpoints, then spawn autonomous agents **IN PARALLEL** (all modules in the same layer run simultaneously). Team lead pre-injects coordination notes into each agent's prompt, handles runtime cross-module queries between agents, then presents cross-module interaction analysis + individual module reviews to user.
|
|
292
|
+
4. Between layers: shutdown all layer agents, rebuild completedModulesSummary, spawn next layer
|
|
293
|
+
5. After all modules specified: spawn consolidation agent (steps 04a + 04b), present report for user approval (04c)
|
|
294
|
+
6. After consolidation approved: spawn handoff agent (steps 05a + 05b + 05c)
|
|
295
|
+
7. `TeamDelete()` cleanup
|
|
295
296
|
|
|
296
297
|
**Why team mode:**
|
|
297
298
|
- Each module agent gets a **fresh context window** (zero accumulation)
|
|
298
299
|
- The team lead stays lightweight (< 30% context even with 10+ modules)
|
|
299
300
|
- Module agents work **autonomously** (no AskUserQuestion — they PROPOSE, user REVIEWS)
|
|
300
|
-
-
|
|
301
|
+
- **Parallel execution**: modules in the same dependency layer run simultaneously (~50-66% wall-clock reduction)
|
|
302
|
+
- **Cross-module coordination**: team lead pre-injects known touchpoints + relays runtime queries between parallel agents
|
|
303
|
+
- Error recovery: if an agent crashes, other agents in the layer continue; crashed module retried independently
|
|
301
304
|
|
|
302
305
|
**Reference:** `references/team-orchestration.md` (loaded by step-02 after decomposition)
|
|
303
306
|
**Agent prompt template:** `references/agent-module-prompt.md`
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
| Q4.2 | For each entity: important attributes? | Per entity |
|
|
14
14
|
| Q4.3 | What relationships exist between entities? | Text schema |
|
|
15
15
|
| Q4.4 | Expected data volume? | Estimation |
|
|
16
|
+
| Q4.4b | For each entity: should the Code be auto-generated or user-provided? | Per entity |
|
|
17
|
+
| Q4.4c | If auto-generated: what strategy? (sequential, daily timestamp, yearly, UUID short) | Per entity |
|
|
18
|
+
| Q4.4d | What prefix represents this entity? (2-6 lowercase letters, e.g., emp, inv) | Per entity |
|
|
16
19
|
|
|
17
20
|
## 4.2 Data Rules
|
|
18
21
|
|
|
@@ -34,6 +37,8 @@
|
|
|
34
37
|
| Unique attribute | `HasIndex().IsUnique()` |
|
|
35
38
|
| 1:N relationship | Navigation property |
|
|
36
39
|
| Sensitive data | Encryption + audit |
|
|
40
|
+
| Code auto-generation | `ICodeGenerator<T>.NextCodeAsync()` with retry — see `apex/references/code-generation.md` |
|
|
41
|
+
| Code pattern config | `analysis.entities[].codePattern` in feature.json |
|
|
37
42
|
|
|
38
43
|
> **⚠️ RBAC EXCLUSION: The following concepts are handled by the platform's RBAC system
|
|
39
44
|
> and MUST NOT be modeled as entity attributes or separate entities:**
|
|
@@ -58,6 +63,9 @@
|
|
|
58
63
|
| Q4.2 (attributes) | Liste de champs techniques (ID, CreatedDate) | "Les champs techniques (Id, TenantId, audit) sont auto-gérés. Quels sont les attributs MÉTIER ?" |
|
|
59
64
|
| Q4.3 (relationships) | "1:N" without detail | "Un {Parent} peut avoir combien de {Children} max ? Un {Child} peut-il exister sans {Parent} ?" |
|
|
60
65
|
| Q4.4 (volume) | "Beaucoup" | "Ordre de grandeur : dizaines, centaines, milliers, millions ? Croissance par mois ?" |
|
|
66
|
+
| Q4.4b (code pattern) | "User enters the code" or no answer | "Le code doit-il suivre un format spécifique ? (numéro séquentiel, date, combinaison ?)" |
|
|
67
|
+
| Q4.4c (code strategy) | No answer | Propose strategy based on entity type: invoices/orders → timestamp-daily, employees/customers → sequential, references/categories → uuid-short, contracts → year-sequential, tickets → timestamp-minute |
|
|
68
|
+
| Q4.4d (code prefix) | Too long or ambiguous | "Le préfixe est limité à 2-6 lettres minuscules. Exemple : 'emp' pour Employee, 'inv' pour Invoice, 'ctr' pour Contract." |
|
|
61
69
|
| Q4.5 (validations) | Validations basiques seulement | "Y a-t-il des règles inter-champs ? (date fin > date début, montant selon statut)" |
|
|
62
70
|
| Q4.8 (sensitive) | "Non" | "Pas de données personnelles (nom, email, téléphone) ? Pas de données financières ?" |
|
|
63
71
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Module Specifier Agent — Prompt Template
|
|
2
2
|
|
|
3
|
-
> **Used by:** team-orchestration.md §
|
|
3
|
+
> **Used by:** team-orchestration.md § 2c
|
|
4
4
|
> **Purpose:** Self-contained prompt for autonomous module specification agents.
|
|
5
5
|
> **Placeholders:** All `{...}` tokens are replaced at spawn time by the team lead.
|
|
6
|
+
> **New in v3.32:** `{coordinationNotes}` for parallel same-layer execution.
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
@@ -52,12 +53,23 @@ You work WITHOUT user interaction:
|
|
|
52
53
|
**Dependencies on other modules:** {dependencies}
|
|
53
54
|
**Detail tabs:** {detailTabs}
|
|
54
55
|
|
|
55
|
-
## Completed Modules Context
|
|
56
|
+
## Completed Modules Context (from previous layers)
|
|
56
57
|
|
|
57
|
-
These modules are already specified
|
|
58
|
+
These modules are already specified (from completed dependency layers).
|
|
59
|
+
Reference their entities for FK relationships:
|
|
58
60
|
|
|
59
61
|
{completedModulesSummary}
|
|
60
62
|
|
|
63
|
+
## Same-Layer Coordination (Parallel Execution)
|
|
64
|
+
|
|
65
|
+
{coordinationNotes}
|
|
66
|
+
|
|
67
|
+
> **Parallel execution note:** You may be running simultaneously with other module agents
|
|
68
|
+
> in the same dependency layer. The `completedModulesSummary` above covers COMPLETED LAYERS only.
|
|
69
|
+
> For information about modules in your SAME layer, use the CROSS_MODULE_QUERY protocol
|
|
70
|
+
> described in the Communication Protocol section below.
|
|
71
|
+
> If `coordinationNotes` is empty, you are the only module in this layer — no coordination needed.
|
|
72
|
+
|
|
61
73
|
## Project Context
|
|
62
74
|
|
|
63
75
|
- Language: {language}
|
|
@@ -204,6 +216,55 @@ SendMessage({
|
|
|
204
216
|
- {section}: {1-line description of layout}
|
|
205
217
|
```
|
|
206
218
|
|
|
219
|
+
### Cross-Module Queries (for same-layer modules)
|
|
220
|
+
|
|
221
|
+
If you need information about another module being specified in parallel
|
|
222
|
+
(e.g., entity attribute structure for FK references, shared enum values, naming conventions):
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
SendMessage({
|
|
226
|
+
type: "message",
|
|
227
|
+
recipient: "team-lead",
|
|
228
|
+
content: "CROSS_MODULE_QUERY:{targetModuleCode}\nQuestion: {your specific question}\nContext: {why you need this information}",
|
|
229
|
+
summary: "Query about {targetModuleCode}"
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Then **WAIT** for the team lead to respond with `CROSS_MODULE_ANSWER` before proceeding.
|
|
234
|
+
Do NOT guess or assume — **always query** when unsure about a same-layer module's design.
|
|
235
|
+
|
|
236
|
+
**When to use CROSS_MODULE_QUERY:**
|
|
237
|
+
- You need the exact attribute list of an entity owned by another same-layer module
|
|
238
|
+
- You want to verify a naming convention with a parallel module
|
|
239
|
+
- You need to know if a shared concept (e.g., Status enum) is already defined elsewhere
|
|
240
|
+
- You're defining a FK that references an entity from a same-layer module
|
|
241
|
+
|
|
242
|
+
**When NOT to use CROSS_MODULE_QUERY:**
|
|
243
|
+
- For modules in completed layers → use `completedModulesSummary` (already in your context)
|
|
244
|
+
- For general SmartStack conventions → use ULTRATHINK + step file instructions
|
|
245
|
+
- For your own module's entities → you define them yourself
|
|
246
|
+
|
|
247
|
+
### Responding to Cross-Module Queries (relay from team lead)
|
|
248
|
+
|
|
249
|
+
The team lead may relay a question from another same-layer agent:
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
"CROSS_MODULE_QUERY_RELAY:{requestingModule}\nQuestion: {their question}"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Respond with your current specification data:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
SendMessage({
|
|
259
|
+
type: "message",
|
|
260
|
+
recipient: "team-lead",
|
|
261
|
+
content: "CROSS_MODULE_ANSWER_RELAY:{requestingModule}\nAnswer: {your answer based on your current specification state}",
|
|
262
|
+
summary: "Answer for {requestingModule}"
|
|
263
|
+
})
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Then **continue your work** — don't wait for anything after answering a relay query.
|
|
267
|
+
|
|
207
268
|
### After receiving feedback:
|
|
208
269
|
|
|
209
270
|
If team lead sends "REVISION:{moduleCode}\n{feedback}":
|
|
@@ -268,17 +329,35 @@ OBJ-{PREFIX}-{NNN} → OBJ-TM-001
|
|
|
268
329
|
|
|
269
330
|
NEVER use bare IDs (UC-001, BR-VAL-001) — always prefixed.
|
|
270
331
|
|
|
332
|
+
## MANDATORY SECTIONS (your feature.json MUST contain ALL of these)
|
|
333
|
+
|
|
334
|
+
> **CRITICAL — Missing any of these sections causes BLOCKING validation errors.**
|
|
335
|
+
|
|
336
|
+
- `analysis.dataLifecycle` — Even for simple modules. Use standard defaults if no specific GDPR requirements:
|
|
337
|
+
```json
|
|
338
|
+
{ "retentionPeriod": "Standard (as per company policy)", "archiveStrategy": "Soft-delete with audit trail", "gdprCompliance": "N/A — no PII or standard audit trail only" }
|
|
339
|
+
```
|
|
340
|
+
- `specification.navigation.entries[]` — Module + section entries with labels in **4 languages (fr, en, it, de)**
|
|
341
|
+
- `validation` — completeness/consistency/convention/semantic checks + decision (recording step-03d results)
|
|
342
|
+
|
|
343
|
+
**i18n RULE:** ALL i18n keys MUST have **4 languages (fr, en, it, de)**. IT/DE can use shorter translations but MUST exist. Missing IT/DE is a common failure — use EN as fallback if unsure.
|
|
344
|
+
|
|
345
|
+
**Wireframe RULE:** For each data-centric section with a create form, a wireframe `{section}-create` MUST exist. For modifiable entities, a `{section}-edit` wireframe SHOULD also exist. These are action-page wireframes, NOT navigation sections.
|
|
346
|
+
|
|
271
347
|
## Quality Checklist (self-verify before PROPOSAL_READY)
|
|
272
348
|
|
|
273
349
|
- [ ] All entities have attributes with type + required + validation
|
|
274
350
|
- [ ] All FK fields are Guid type with navigation property
|
|
275
351
|
- [ ] All sections have at least 1 resource
|
|
276
|
-
- [ ] All sections have a wireframe
|
|
352
|
+
- [ ] All sections have a wireframe (+ create/edit wireframes for data-centric sections)
|
|
277
353
|
- [ ] seedDataCore has all 7 arrays with content
|
|
278
354
|
- [ ] Permissions follow {context}.{app}.{module}.{entity}.{action} pattern
|
|
279
|
-
- [ ] i18n has all
|
|
355
|
+
- [ ] i18n has all keys in **4 languages (fr, en, it, de)** — not just fr/en
|
|
280
356
|
- [ ] At least 2 actors, 2 use cases, 4 functional requirements
|
|
281
357
|
- [ ] Gherkin scenarios are arrays (not objects)
|
|
282
358
|
- [ ] Messages have `message` field (not `text`)
|
|
283
359
|
- [ ] Validations have `rules[]` arrays (not singular `rule`)
|
|
360
|
+
- [ ] `analysis.dataLifecycle` section present
|
|
361
|
+
- [ ] `specification.navigation.entries[]` non-empty with 4-language labels
|
|
362
|
+
- [ ] `validation` section with decision recorded
|
|
284
363
|
```
|
|
@@ -212,6 +212,57 @@ Spawn agent-consolidate
|
|
|
212
212
|
|
|
213
213
|
---
|
|
214
214
|
|
|
215
|
+
### Pattern 4: Layer-Based Parallel Spawn (RECOMMENDED for Step 03)
|
|
216
|
+
|
|
217
|
+
**Scenario:** Step 03 - Specify modules across dependency layers
|
|
218
|
+
|
|
219
|
+
**Recommended:**
|
|
220
|
+
```
|
|
221
|
+
FOR each layer in dependencyGraph.layers:
|
|
222
|
+
|
|
223
|
+
1. Pre-analyze: Identify cross-module touchpoints between modules in this layer
|
|
224
|
+
→ Shared entities, FK overlaps, naming conventions, shared lookups
|
|
225
|
+
→ Build coordinationNotes per module
|
|
226
|
+
|
|
227
|
+
2. Spawn ALL layer agents in parallel (1 Task per module, ALL in ONE message)
|
|
228
|
+
→ Each agent receives: module context + completedModulesSummary + coordinationNotes
|
|
229
|
+
|
|
230
|
+
3. Handle cross-module queries during execution (team lead relays)
|
|
231
|
+
→ Agent sends CROSS_MODULE_QUERY → team lead routes → answer forwarded
|
|
232
|
+
|
|
233
|
+
4. Wait for ALL PROPOSAL_READY from this layer
|
|
234
|
+
|
|
235
|
+
5. Display cross-module interaction analysis (bird's-eye view)
|
|
236
|
+
→ Detected interactions, resolved queries, attention points
|
|
237
|
+
|
|
238
|
+
6. Review each module individually with user (quality-first)
|
|
239
|
+
→ Approve, revise, or see detail per module
|
|
240
|
+
|
|
241
|
+
7. Layer consistency check (FK names, permissions, i18n, seed data IDs)
|
|
242
|
+
→ Auto-fix if inconsistency found
|
|
243
|
+
|
|
244
|
+
8. Shutdown ALL layer agents
|
|
245
|
+
|
|
246
|
+
9. Rebuild completedModulesSummary for next layer
|
|
247
|
+
|
|
248
|
+
10. Proceed to next layer
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Result:**
|
|
252
|
+
- 4 agents for 4 modules (same count as sequential)
|
|
253
|
+
- But wall-clock reduced by ~50-66% for apps with parallel layers
|
|
254
|
+
- Cross-module consistency guaranteed by pre-injection + relay + consistency check
|
|
255
|
+
- Each agent has fresh context (zero accumulation)
|
|
256
|
+
|
|
257
|
+
**Why this pattern works:**
|
|
258
|
+
- Dependency layers already computed by step-02 topological sort
|
|
259
|
+
- Modules in the same layer have NO direct dependencies (by definition)
|
|
260
|
+
- Pre-injection prevents most cross-module issues before they happen
|
|
261
|
+
- Runtime relay catches unexpected edge cases
|
|
262
|
+
- Consistency check catches anything missed by both mechanisms
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
215
266
|
## Metrics & Monitoring
|
|
216
267
|
|
|
217
268
|
### Target Metrics (per BA session)
|
|
@@ -282,19 +333,23 @@ Otherwise → inline or reuse.
|
|
|
282
333
|
### Step 03: Module Specification (BIGGEST IMPACT)
|
|
283
334
|
|
|
284
335
|
**Current:** 4-5 agents PER module × 5 modules = 20-25 agents
|
|
285
|
-
**Target:** 1 agent per module
|
|
286
|
-
|
|
287
|
-
**Changes:**
|
|
288
|
-
- **Option A:** ONE agent for ALL modules (sequential)
|
|
289
|
-
- Agent loops through modules
|
|
290
|
-
- Executes 03a → 03b → 03c → 03d internally
|
|
291
|
-
- Displays progress checkpoints
|
|
336
|
+
**Target:** 1 agent per module, parallel within dependency layers
|
|
292
337
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
338
|
+
**Implementation (team mode with parallel layers):**
|
|
339
|
+
- ONE agent PER module, each executing 03a → 03b → 03c → 03d autonomously
|
|
340
|
+
- Modules in the same dependency layer spawn **simultaneously** (parallel)
|
|
341
|
+
- Modules in different layers spawn **sequentially** (dependency order)
|
|
342
|
+
- Team lead pre-injects cross-module coordination notes before spawning
|
|
343
|
+
- Runtime cross-module queries relayed by team lead between parallel agents
|
|
344
|
+
- Layer consistency check after all modules in a layer are approved
|
|
296
345
|
|
|
297
|
-
**
|
|
346
|
+
**Example (4 modules, 3 layers):**
|
|
347
|
+
```
|
|
348
|
+
Layer 0: [Customers, Products] → 2 agents in parallel
|
|
349
|
+
Layer 1: [Orders] → 1 agent (after layer 0 complete)
|
|
350
|
+
Layer 2: [Invoices] → 1 agent (after layer 1 complete)
|
|
351
|
+
Total: 4 agents, but wall-clock = 3 layers (not 4 sequential)
|
|
352
|
+
```
|
|
298
353
|
|
|
299
354
|
---
|
|
300
355
|
|
|
@@ -433,17 +488,19 @@ Session: Business-analyse for HumanResources application
|
|
|
433
488
|
- Cache efficiency: 50-60% read (optimal)
|
|
434
489
|
```
|
|
435
490
|
|
|
436
|
-
### After Optimization — Team Mode (Target, RECOMMENDED)
|
|
491
|
+
### After Optimization — Team Mode with Parallel Layers (Target, RECOMMENDED)
|
|
437
492
|
|
|
438
493
|
```
|
|
439
|
-
Session: Business-analyse for HumanResources application (4 modules)
|
|
494
|
+
Session: Business-analyse for HumanResources application (4 modules, 3 layers)
|
|
440
495
|
- Team lead context: <50% (never exhausted)
|
|
441
|
-
- Module agents: 4 (1 per module, each ~40-60% context)
|
|
496
|
+
- Module agents: 4 (1 per module, parallel within layers, each ~40-60% context)
|
|
442
497
|
- Consolidation agent: 1 (~30-40% context)
|
|
443
498
|
- Handoff agent: 1 (~40-50% context)
|
|
444
499
|
- Total agents: 6
|
|
445
500
|
- Context exhaustion: ZERO (each agent has fresh context window)
|
|
446
501
|
- User interaction: Propose & Review (user validates complete proposals)
|
|
502
|
+
- Wall-clock: ~50% reduction vs sequential (layer 0 runs 2 modules in parallel)
|
|
503
|
+
- Cross-module quality: pre-injection + relay + consistency check
|
|
447
504
|
```
|
|
448
505
|
|
|
449
506
|
### Success Metrics
|
|
@@ -452,8 +509,10 @@ Session: Business-analyse for HumanResources application (4 modules)
|
|
|
452
509
|
- ✅ Ultra-short agents eliminated
|
|
453
510
|
- ✅ JSONL complexity reduced by 68-81%
|
|
454
511
|
- ✅ **Context exhaustion eliminated** (team mode)
|
|
455
|
-
- ✅ Token usage
|
|
456
|
-
- ✅
|
|
512
|
+
- ✅ Token usage distributed across parallel agents (team mode)
|
|
513
|
+
- ✅ **Wall-clock time reduced by ~50-66%** (parallel layer execution)
|
|
514
|
+
- ✅ **Cross-module consistency guaranteed** (pre-injection + relay + consistency check)
|
|
515
|
+
- ✅ Same or better output quality (cross-module coordination improves integration)
|
|
457
516
|
|
|
458
517
|
---
|
|
459
518
|
|
|
@@ -472,6 +531,10 @@ Session: Business-analyse for HumanResources application (4 modules)
|
|
|
472
531
|
|
|
473
532
|
- Reuse agents for sequential operations
|
|
474
533
|
- Spawn 1 agent per logical phase (not per sub-step)
|
|
534
|
+
- Spawn ALL same-layer agents in parallel (one message, multiple Task calls)
|
|
535
|
+
- Pre-inject coordination notes for parallel agents
|
|
536
|
+
- Handle cross-module queries via relay protocol
|
|
537
|
+
- Run layer consistency check after parallel approvals
|
|
475
538
|
- Do summaries/formatting inline
|
|
476
539
|
- Pre-load context at phase start
|
|
477
540
|
- Display progress checkpoints
|
|
@@ -482,12 +545,13 @@ Session: Business-analyse for HumanResources application (4 modules)
|
|
|
482
545
|
- Spawn agents for trivial tasks (<20 lines output)
|
|
483
546
|
- Spawn new agent for each step transition
|
|
484
547
|
- Spawn agents for sequential dependencies
|
|
548
|
+
- Spawn agents from different dependency layers in parallel
|
|
485
549
|
- Re-read same files multiple times
|
|
486
550
|
- Create summary-only agents
|
|
487
|
-
- Spawn more than
|
|
551
|
+
- Spawn more than N+2 agents per BA session (N modules + consolidation + handoff)
|
|
488
552
|
|
|
489
553
|
---
|
|
490
554
|
|
|
491
|
-
**Last Updated:** 2026-02-
|
|
492
|
-
**Version:**
|
|
555
|
+
**Last Updated:** 2026-02-15
|
|
556
|
+
**Version:** 2.0 (parallel layer execution)
|
|
493
557
|
**Author:** SmartStack CLI Team
|