@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.
Files changed (52) hide show
  1. package/.documentation/installation.html +7 -2
  2. package/README.md +7 -1
  3. package/dist/index.js +33 -37
  4. package/dist/index.js.map +1 -1
  5. package/dist/mcp-entry.mjs +547 -97
  6. package/dist/mcp-entry.mjs.map +1 -1
  7. package/package.json +1 -1
  8. package/scripts/health-check.sh +2 -1
  9. package/templates/mcp-scaffolding/controller.cs.hbs +10 -7
  10. package/templates/mcp-scaffolding/entity-extension.cs.hbs +132 -124
  11. package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +4 -4
  12. package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +38 -15
  13. package/templates/mcp-scaffolding/tests/service.test.cs.hbs +20 -8
  14. package/templates/skills/apex/SKILL.md +7 -9
  15. package/templates/skills/apex/_shared.md +9 -2
  16. package/templates/skills/apex/references/code-generation.md +412 -0
  17. package/templates/skills/apex/references/post-checks.md +377 -37
  18. package/templates/skills/apex/references/smartstack-api.md +229 -5
  19. package/templates/skills/apex/references/smartstack-frontend.md +368 -11
  20. package/templates/skills/apex/references/smartstack-layers.md +54 -7
  21. package/templates/skills/apex/steps/step-00-init.md +1 -2
  22. package/templates/skills/apex/steps/step-01-analyze.md +45 -2
  23. package/templates/skills/apex/steps/step-02-plan.md +23 -2
  24. package/templates/skills/apex/steps/step-03-execute.md +195 -5
  25. package/templates/skills/apex/steps/step-04-examine.md +18 -5
  26. package/templates/skills/apex/steps/step-05-deep-review.md +9 -11
  27. package/templates/skills/apex/steps/step-06-resolve.md +5 -9
  28. package/templates/skills/apex/steps/step-07-tests.md +66 -1
  29. package/templates/skills/apex/steps/step-08-run-tests.md +12 -3
  30. package/templates/skills/application/references/provider-template.md +62 -39
  31. package/templates/skills/application/templates-backend.md +3 -3
  32. package/templates/skills/application/templates-frontend.md +12 -12
  33. package/templates/skills/application/templates-seed.md +14 -4
  34. package/templates/skills/business-analyse/SKILL.md +9 -6
  35. package/templates/skills/business-analyse/questionnaire/04-data.md +8 -0
  36. package/templates/skills/business-analyse/references/agent-module-prompt.md +84 -5
  37. package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +83 -19
  38. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +6 -2
  39. package/templates/skills/business-analyse/references/team-orchestration.md +443 -110
  40. package/templates/skills/business-analyse/references/validation-checklist.md +5 -4
  41. package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +44 -0
  42. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +72 -1
  43. package/templates/skills/business-analyse/steps/step-03c-compile.md +93 -7
  44. package/templates/skills/business-analyse/steps/step-03d-validate.md +34 -2
  45. package/templates/skills/business-analyse/steps/step-04b-analyze.md +40 -0
  46. package/templates/skills/controller/references/controller-code-templates.md +2 -2
  47. package/templates/skills/controller/templates.md +12 -12
  48. package/templates/skills/feature-full/steps/step-01-implementation.md +4 -4
  49. package/templates/skills/ralph-loop/references/category-rules.md +44 -2
  50. package/templates/skills/ralph-loop/references/compact-loop.md +37 -0
  51. package/templates/skills/ralph-loop/references/core-seed-data.md +51 -20
  52. 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 (if -t)
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
- // Check idempotence
34
- var exists = await context.NavigationApplications
35
- .AnyAsync(a => a.Code == "{app_code}", ct);
36
- if (exists) return;
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
- // 3. Create modules
56
- // Use GUIDs and data from {Module}NavigationSeedData.cs
57
- foreach (var moduleData in GetModuleSeedEntries(app.Id))
38
+ NavigationApplication app;
39
+ if (existingApp != null)
40
+ {
41
+ app = existingApp; // Reuse existing for module seeding below
42
+ }
43
+ else
58
44
  {
59
- var module = NavigationModule.Create(
60
- moduleData.ApplicationId,
61
- moduleData.Code,
62
- moduleData.Label,
63
- moduleData.Description,
64
- moduleData.Icon,
65
- IconType.Lucide,
66
- moduleData.Route,
67
- moduleData.DisplayOrder);
68
- context.NavigationModules.Add(module);
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
- // 4. Create translations (4 languages per entity)
73
- // Use data from {Module}NavigationTranslationSeedData.cs
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. **SaveChangesAsync per group**: Navigation save Roles save Permissions save RolePermissions save
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<PagedResult<$ENTITY_PASCALDto>> GetAllAsync(
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<PagedResult<$ENTITY_PASCALDto>> GetAllAsync(
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 PagedResult<$ENTITY_PASCALDto>
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 PagedResult {
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<PagedResult | null>(null);
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 [searchTerm, setSearchTerm] = useState('');
142
+ const [search, setSearchTerm] = useState('');
143
143
 
144
144
  useEffect(() => {
145
145
  loadData();
146
- }, [page, pageSize, sortColumn, sortDirection, searchTerm]);
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
- ...(searchTerm && { searchTerm }),
157
+ ...(search && { search }),
158
158
  });
159
- const result = await api.get<PagedResult>(`/api/$module?${params}`);
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={searchTerm}
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 PagedResult<T> {
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 QueryParameters {
466
+ export interface PaginationParams {
467
467
  page?: number;
468
468
  pageSize?: number;
469
- searchTerm?: string;
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: QueryParameters = {}): Promise<PagedResult<$ENTITY_PASCALDto>> => {
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.searchTerm) queryParams.set('searchTerm', params.searchTerm);
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
- // Create sections from {Module}NavigationSeedData.GetSectionEntries(moduleId)
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
- // Create resources from {Module}NavigationSeedData.GetResourceEntries(sectionId)
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 module: spawn autonomous agent using the **returned** team name, agent proposes complete specification, team lead presents to user for validation
292
- 4. After all modules specified: spawn consolidation agent (steps 04a + 04b), present report for user approval (04c)
293
- 5. After consolidation approved: spawn handoff agent (steps 05a + 05b + 05c)
294
- 6. `TeamDelete()` cleanup
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
- - Error recovery: if an agent crashes, respawn with same module context from feature.json
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 § 2b
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. Reference their entities for FK relationships:
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 8 required keys (actions, columns, empty, errors, form, labels, messages, validation)
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 (5 total) OR 1 agent for all modules (1 total)
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
- - **Option B:** ONE agent PER module (if parallel possible)
294
- - Max 2-3 modules in parallel
295
- - Each agent handles 1 module end-to-end
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
- **Recommended:** Option A (sequential) for most cases, Option B only if modules truly independent
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 reduced by 15-20% (agent pooling) or distributed across agents (team mode)
456
- - ✅ Same output quality (no regressions)
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 7 agents per BA session
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-08
492
- **Version:** 1.0
555
+ **Last Updated:** 2026-02-15
556
+ **Version:** 2.0 (parallel layer execution)
493
557
  **Author:** SmartStack CLI Team