@atlashub/smartstack-cli 3.34.0 → 3.36.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 (39) hide show
  1. package/.documentation/init.html +409 -0
  2. package/dist/index.js +35 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/mcp-entry.mjs +118 -70
  5. package/dist/mcp-entry.mjs.map +1 -1
  6. package/package.json +1 -2
  7. package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
  8. package/templates/skills/apex/SKILL.md +6 -3
  9. package/templates/skills/apex/references/post-checks.md +225 -0
  10. package/templates/skills/apex/references/smartstack-api.md +29 -1
  11. package/templates/skills/apex/references/smartstack-frontend.md +27 -0
  12. package/templates/skills/apex/references/smartstack-layers.md +18 -2
  13. package/templates/skills/apex/steps/step-00-init.md +77 -1
  14. package/templates/skills/apex/steps/step-01-analyze.md +21 -0
  15. package/templates/skills/apex/steps/step-03-execute.md +94 -5
  16. package/templates/skills/apex/steps/step-04-examine.md +7 -1
  17. package/templates/skills/business-analyse/SKILL.md +4 -3
  18. package/templates/skills/business-analyse/_shared.md +9 -0
  19. package/templates/skills/business-analyse/schemas/application-schema.json +13 -0
  20. package/templates/skills/business-analyse/steps/step-00-init.md +190 -34
  21. package/templates/skills/business-analyse/steps/step-01-cadrage.md +129 -10
  22. package/templates/skills/business-analyse/steps/step-01b-applications.md +184 -13
  23. package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
  24. package/templates/skills/business-analyse/steps/step-03d-validate.md +5 -1
  25. package/templates/skills/documentation/SKILL.md +175 -9
  26. package/templates/skills/efcore/steps/squash/step-03-create.md +6 -4
  27. package/templates/skills/gitflow/_shared.md +3 -1
  28. package/templates/skills/gitflow/steps/step-pr.md +34 -0
  29. package/templates/skills/ralph-loop/SKILL.md +31 -2
  30. package/templates/skills/ralph-loop/references/category-rules.md +29 -0
  31. package/templates/skills/ralph-loop/references/compact-loop.md +85 -2
  32. package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
  33. package/templates/skills/ralph-loop/references/team-orchestration.md +331 -14
  34. package/templates/skills/ralph-loop/steps/step-00-init.md +4 -0
  35. package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
  36. package/templates/skills/ralph-loop/steps/step-02-execute.md +206 -1
  37. package/templates/skills/ralph-loop/steps/step-05-report.md +19 -0
  38. package/scripts/health-check.sh +0 -168
  39. package/scripts/postinstall.js +0 -18
@@ -22,6 +22,28 @@ All code goes through skills (/controller, /application, /ui-components, /efcore
22
22
 
23
23
  ---
24
24
 
25
+ ## Foundation Mode Detection
26
+
27
+ **IF `{foundation_mode}` == true:**
28
+
29
+ This is a foundation-only execution (called by ralph-loop Phase 0). Execute ONLY:
30
+ - Layer 0: Domain entities + EF configs + Migration
31
+
32
+ **SKIP ALL OTHER LAYERS:**
33
+ - Layer 1: Application + API + Seed Data → SKIP
34
+ - Layer 2: Frontend → SKIP
35
+ - Layer 3: Tests → SKIP
36
+
37
+ After Layer 0 completes and builds successfully:
38
+ - Commit with message: `chore(foundation): entities for {module_code}`
39
+ - Jump to step-04 for POST-CHECKs (domain + infrastructure only)
40
+ - End execution
41
+
42
+ **IF `{foundation_mode}` == false:**
43
+ Execute ALL layers normally (Layer 0 → Layer 1 → Layer 2 → Layer 3).
44
+
45
+ ---
46
+
25
47
  ## Layer 0 — Domain + Infrastructure (sequential, agent principal)
26
48
 
27
49
  ### Domain Entities
@@ -44,16 +66,26 @@ For each entity:
44
66
 
45
67
  ### Migration (BLOCKING)
46
68
 
69
+ > **CRITICAL — Migration must cover ALL entities, not just the first batch.**
70
+ > Root cause (test-apex-007): Migration was created once for 3 entities, then 4 more entities
71
+ > were added later without re-running migration → 4 entities had no database tables.
72
+ > **RULE:** Create/update migration AFTER ALL entities and EF configs are registered in DbContext.
73
+ > If entities are added incrementally, create a NEW migration for each batch.
74
+
47
75
  ```
48
- 1. MCP suggest_migration get standardized name
49
- 2. dotnet ef migrations add {Name} --project src/{Infra}.csproj --startup-project src/{Api}.csproj -o Persistence/Migrations
50
- 3. Cleanup corrupted EF Core artifacts:
76
+ 1. Verify ALL entities have been added as DbSet in ExtensionsDbContext
77
+ 2. Verify ALL EF configurations are registered (ApplyConfigurationsFromAssembly or individual)
78
+ 3. MCP suggest_migration get standardized name
79
+ 4. dotnet ef migrations add {Name} --project src/{Infra}.csproj --startup-project src/{Api}.csproj -o Persistence/Migrations
80
+ 5. Cleanup corrupted EF Core artifacts:
51
81
  for d in src/*/bin?Debug; do [ -d "$d" ] && rm -rf "$d"; done
52
- 4. dotnet ef database update (if local DB)
53
- 5. dotnet build → MUST PASS
82
+ 6. dotnet ef database update (if local DB)
83
+ 7. dotnet build → MUST PASS
84
+ 8. Verify: dotnet ef migrations has-pending-model-changes → MUST report "No pending model changes"
54
85
  ```
55
86
 
56
87
  **BLOCKING:** If build fails after migration, fix EF configs before proceeding.
88
+ **BLOCKING:** If `has-pending-model-changes` reports pending changes, entities are missing from the migration — create a new migration.
57
89
 
58
90
  ### Post-Layer 0 Build Gate
59
91
 
@@ -67,10 +99,66 @@ dotnet build
67
99
 
68
100
  ## Layer 1 — Application + API + Seed Data
69
101
 
102
+ ### NavRoute and Permission Kebab-Case (CRITICAL)
103
+
104
+ > **ALL NavRoute segments and permission codes MUST use kebab-case for multi-word identifiers.**
105
+ > Root cause (test-apex-007): Controllers had `[NavRoute("business.humanresources.employees")]`
106
+ > instead of `[NavRoute("business.human-resources.employees")]`. This mismatched seed data routes
107
+ > and permission codes, causing 404s and permission denials at runtime.
108
+
109
+ **Rules:**
110
+ - NavRoute: `business.human-resources.employees` (NEVER `business.humanresources.employees`)
111
+ - Permissions: `business.human-resources.employees.read` (segments MATCH NavRoute exactly)
112
+ - Seed data codes: `human-resources` (NEVER `humanresources`)
113
+ - C# class names stay PascalCase (`HumanResourcesController`) — only route/permission strings use kebab-case
114
+ - POST-CHECKs 41 + 48 validate this. Fix BEFORE committing.
115
+
116
+ ### Controller Route Attribute (BLOCKING)
117
+
118
+ > **Controllers with `[NavRoute]` must NOT have `[Route]` attribute.**
119
+ > Root cause (test-apex-007): ALL 7 controllers had BOTH `[Route("api/...")]` AND `[NavRoute("...")]`.
120
+ > In SmartStack, `[NavRoute]` resolves routes dynamically from Navigation entities in the database at startup.
121
+ > Having `[Route]` alongside causes route conflicts → all endpoints return 404.
122
+
123
+ **Rules:**
124
+ - `[NavRoute("context.app.module")]` is the ONLY route attribute needed on controllers
125
+ - **FORBIDDEN:** `[Route("api/business/human-resources/employees")]` alongside `[NavRoute]`
126
+ - **FORBIDDEN:** `[Route("api/[controller]")]` alongside `[NavRoute]`
127
+ - If generating via MCP `scaffold_extension` with `navRoute` option → output is correct (NavRoute only)
128
+ - If generating via `/controller` skill → verify NO `[Route]` is added
129
+ - POST-CHECK 50 validates this. Fix BEFORE committing.
130
+
131
+ ### Validators DI Registration (CRITICAL)
132
+
133
+ > After creating validators, they MUST be registered in DI. Without registration, `[FromBody]` DTOs are never validated.
134
+
135
+ ```
136
+ In DependencyInjection.cs (or ServiceCollectionExtensions.cs):
137
+ services.AddValidatorsFromAssemblyContaining<Create{Entity}DtoValidator>();
138
+ ```
139
+
140
+ POST-CHECK 46 validates this. If validators exist but no DI registration → BLOCKING.
141
+
70
142
  ### If economy_mode: Sequential execution
71
143
 
72
144
  Execute each item from the plan sequentially using skills and MCP.
73
145
 
146
+ ### Date Fields — Use DateOnly (CRITICAL)
147
+
148
+ > **ALL date-only fields in DTOs MUST use `DateOnly`, NEVER `string`.**
149
+ > Root cause (test-apex-007): WorkLog DTO had `string Date` instead of `DateOnly Date`.
150
+ > This causes: no date validation, inconsistent date formats, parsing errors.
151
+
152
+ **Type mapping for DTOs:**
153
+ | Domain type | DTO type | Example |
154
+ |-------------|----------|---------|
155
+ | `DateTime` | `DateTime` | `CreatedAt`, `UpdatedAt` |
156
+ | Date-only field | `DateOnly` | `Date`, `StartDate`, `EndDate`, `BirthDate` |
157
+ | `string` for date | **FORBIDDEN** | Never use `string` for dates |
158
+ | `DateTime` for date-only | **Avoid** | Use `DateOnly` when no time component needed |
159
+
160
+ POST-CHECK 47 validates this. If a DTO has `string` type for a property named `*Date*` → BLOCKING.
161
+
74
162
  ### Code Generation (if entities have codePattern != "manual")
75
163
 
76
164
  For each entity with auto-generated code pattern (from feature.json or step-02 decisions):
@@ -114,6 +202,7 @@ Code stays in CreateDto, user provides it, validator has regex rule.
114
202
  - A dead link (navigate to a route with no page) is a BLOCKING issue (POST-CHECK 42)
115
203
  - Read `references/smartstack-frontend.md` for mandatory patterns (sections 3b + 8)
116
204
  - Generate i18n JSON files for all 4 languages (fr, en, it, de) — `src/i18n/locales/{lang}/{module}.json`
205
+ - **I18n REGISTRATION (CRITICAL):** After creating i18n JSON files, register EACH new namespace in the i18n config file (config.ts/index.ts/i18n.ts). Unregistered namespaces → `useTranslation(['module'])` returns empty strings at runtime. POST-CHECK 45 validates this.
117
206
  - All pages must follow loading → error → content pattern with CSS variables
118
207
 
119
208
  ### If NOT economy_mode: Agent Teams (parallel)
@@ -262,7 +262,13 @@ AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
262
262
  | Security | TenantId filter, RequirePermission, no Guid.Empty, no !.Value | PASS / N/A |
263
263
  | Seed data | completeness, deterministic GUIDs, no ContextId/RoleId constants | PASS / N/A |
264
264
  | Code quality | PaginatedResult, EntityLookup (no FK select/input), CSS vars, search param | PASS / N/A |
265
- | POST-CHECKs | 43 checks from references/post-checks.md | PASS / N/A |
265
+ | Migration completeness | ModelSnapshot covers ALL DbSet entities (POST-CHECK 44, 49) | PASS / N/A |
266
+ | NavRoute kebab-case | NavRoute + permissions use kebab-case (POST-CHECK 48) | PASS / N/A |
267
+ | DateOnly DTOs | Date fields use DateOnly not string (POST-CHECK 47) | PASS / N/A |
268
+ | I18n registration | Namespaces registered in i18n config (POST-CHECK 45) | PASS / N/A |
269
+ | Validators DI | FluentValidation registered in DI (POST-CHECK 46) | PASS / N/A |
270
+ | Route/NavRoute conflict | No [Route] alongside [NavRoute] on controllers (POST-CHECK 50) | PASS / N/A |
271
+ | POST-CHECKs | 50 checks from references/post-checks.md | PASS / N/A |
266
272
  | Acceptance criteria | AC1..ACn | {X}/{Y} PASS |
267
273
  ```
268
274
 
@@ -43,6 +43,7 @@ The skill auto-detects which use case applies by scanning existing features in `
43
43
 
44
44
  Step-00 handles detection automatically:
45
45
  - **New vs Update**: scans `docs/business/` for existing applications
46
+ - **Single vs Multi-app**: multi-app detection in step-01, application identity confirmed in step-01b (always)
46
47
  - **Single vs Multi-module**: determined during step-02 decomposition
47
48
  - **Language**: detected from config or asked once
48
49
  - **Review mode**: if `-review` flag, routes directly to step-06
@@ -151,7 +152,7 @@ When step-00 detects that the description matches an existing application:
151
152
  **New application workflow (single or multi-app):**
152
153
  - **Step 00:** Detection, scan existing, create master feature.json (draft)
153
154
  - **Step 01:** Cadrage: context, stakeholders, scope, application roles (framed)
154
- - **Step 01b:** *(multi-app only)* Application decomposition: identify applications, contexts, prefixes, inter-app dependencies
155
+ - **Step 01b:** Application identity (always): confirm code, route, icon, seed data (lightweight single-app / full decomposition multi-app)
155
156
  - **Step 02:** Decomposition: modules, dependencies, client checkpoint (decomposed) — per application in multi-app mode
156
157
  - **Step 03a:** Per-module data: sections, entities, business rules, questionnaires
157
158
  - **Step 03b:** Per-module UI: state machines, wireframes, layouts, dashboards
@@ -207,12 +208,12 @@ When step-00 detects that the description matches an existing application:
207
208
  | ---- | --------------------------------- | ------ | ---------------------------------------------------- |
208
209
  | 00 | `steps/step-00-init.md` | Sonnet | Auto-detect new/update, scan existing, create master feature.json |
209
210
  | 01 | `steps/step-01-cadrage.md` | Opus | Framing: context, stakeholders, scope, application roles + multi-app detection |
210
- | 01b | `steps/step-01b-applications.md` | Opus | *(multi-app only)* Application decomposition, contexts, prefixes, inter-app dependencies |
211
+ | 01b | `steps/step-01b-applications.md` | Opus | Application identity: confirm code, route, icon, seedData (lightweight single-app, full decomposition multi-app) |
211
212
  | 02 | `steps/step-02-decomposition.md` | Opus | Module decomposition, dependency graph, client checkpoint (per application in multi-app) |
212
213
  | 03a1 | `steps/step-03a1-setup.md` | Opus | Per-module: setup, sections, questionnaires, cross-refs |
213
214
  | 03a2 | `steps/step-03a2-analysis.md` | Opus | Per-module: objectives, entities, BRs, process flow |
214
215
  | 03b | `steps/step-03b-ui.md` | Opus | Per-module: state machines, wireframes, layouts, dashboards |
215
- | 03c | `steps/step-03c-compile.md` | Opus | Per-module: actors, UCs, FRs, permissions, navigation, seedDataCore (7 arrays), i18n |
216
+ | 03c | `steps/step-03c-compile.md` | Opus | Per-module: actors, UCs, FRs, permissions, navigation, seedDataCore (9 arrays), i18n |
216
217
  | 03d | `steps/step-03d-validate.md` | Sonnet | Per-module: validation, write, incremental HTML, loop decision |
217
218
  | 04a | `steps/step-04a-collect.md` | Opus | Collect module summaries & cross-module interactions |
218
219
  | 04b | `steps/step-04b-analyze.md` | Opus | Analyze permission coherence, semantic validation, E2E flows |
@@ -98,6 +98,15 @@ Level 1: Context (business)
98
98
  Level 4: Section (approve) ← sidebar nav (workflow)
99
99
  ```
100
100
 
101
+ **CRITICAL — Application identification (Level 2):**
102
+ The application is formally identified in step-01b (ALWAYS, even for single-app mode):
103
+ - Code: PascalCase (e.g., "HumanResources")
104
+ - Route: kebab-case (e.g., "/business/human-resources")
105
+ - Icon: Lucide icon name
106
+ - Sort order: position in navigation
107
+ This creates the `seedDataCore.navigationApplications` entry that links modules to their parent application.
108
+ The `seedDataCore.applicationRoles` entries are also built from `cadrage.applicationRoles`.
109
+
101
110
  | BA Phase | Levels treated | What is defined |
102
111
  |----------|---------------|-----------------|
103
112
  | Cadrage (step-01) | Context + Application | Problem, stakeholders, scope, application-level roles |
@@ -54,6 +54,19 @@
54
54
  "pattern": "^[a-z]{2,5}_$",
55
55
  "description": "Application table prefix for database tables (e.g., rh_, fi_, crm_). Defined during cadrage, used by all entities in this application."
56
56
  },
57
+ "applicationCode": {
58
+ "type": "string",
59
+ "description": "PascalCase application code for navigation hierarchy (e.g., HumanResources). Confirmed in step-01b."
60
+ },
61
+ "applicationRoute": {
62
+ "type": "string",
63
+ "pattern": "^/[a-z-/]+$",
64
+ "description": "Kebab-case route path for navigation (e.g., /business/human-resources). Confirmed in step-01b."
65
+ },
66
+ "applicationIcon": {
67
+ "type": "string",
68
+ "description": "Lucide icon name for application navigation entry (e.g., users, shopping-cart). Confirmed in step-01b."
69
+ },
57
70
  "workflow": {
58
71
  "type": "object",
59
72
  "description": "Iterative module loop state",
@@ -129,10 +129,116 @@ existing_projects: array of { projectName, projectId, applications[], version }
129
129
 
130
130
  > **Project Resume Detection:** If a project-level feature.json is found at `docs/business-analyse/*/feature.json`, check its `metadata.workflow` to determine resume point. The project may have partially completed applications.
131
131
 
132
+ ## Step 3b: Early Multi-Application Detection from Prompt (NEW)
133
+
134
+ > **Detect multi-app structure BEFORE asking for a single application name.**
135
+ > When the user's prompt explicitly describes multiple applications, we must recognize this immediately
136
+ > and set `workflow.mode = "project"` to avoid doing cadrage for a single app.
137
+
138
+ **Detection patterns (ANY match = multi-app detected):**
139
+
140
+ ```javascript
141
+ const multiAppPatterns = [
142
+ // French patterns
143
+ /une\s+application\s+\w+.*une\s+application\s+\w+/is,
144
+ /application\s*\d?\s*[:]\s*\w+.*application\s*\d?\s*[:]\s*\w+/is,
145
+ /premier[e]?\s+application.*deuxième\s+application/is,
146
+ /app\s*1\s*[:.].*app\s*2\s*[:.]*/is,
147
+ // English patterns
148
+ /an?\s+application\s+(for\s+)?\w+.*an?\s+application\s+(for\s+)?\w+/is,
149
+ /application\s*#?\d\s*[:.].*application\s*#?\d\s*[:.]*/is,
150
+ /first\s+app.*second\s+app/is,
151
+ ];
152
+
153
+ const isMultiApp = multiAppPatterns.some(p => p.test(feature_description));
154
+ ```
155
+
156
+ **IF multi-app detected:**
157
+
158
+ 1. Extract candidate applications from the prompt:
159
+
160
+ ```javascript
161
+ // Parse the prompt to identify application boundaries
162
+ // Each "une application X" / "an application X" block = one candidate
163
+ const candidates = extractApplicationCandidates(feature_description);
164
+ // Result example:
165
+ // [
166
+ // { name: "RH", description: "gestion des employes, conges, temps", modules: ["Employes", "Conges", "Temps"] },
167
+ // { name: "Projet", description: "gestion des projets, saisie du temps", modules: ["Projets", "Temps"] }
168
+ // ]
169
+ ```
170
+
171
+ 2. Detect shared modules across candidates:
172
+
173
+ ```javascript
174
+ const allModules = candidates.flatMap(c => c.modules);
175
+ const sharedModules = allModules.filter((m, i) => allModules.indexOf(m) !== i);
176
+ // Example: sharedModules = ["Temps"] → appears in both RH and Projet
177
+ ```
178
+
179
+ 3. Display detection result and confirm:
180
+
181
+ ```
182
+ {language == "fr"
183
+ ? "### Détection multi-application\n\nJ'ai détecté **{candidates.length} applications** dans votre description :"
184
+ : "### Multi-application detection\n\nI detected **{candidates.length} applications** in your description:"}
185
+
186
+ | # | Application | Modules identifiés |
187
+ |---|-------------|-------------------|
188
+ {for each candidate: index | name | modules.join(", ")}
189
+
190
+ {sharedModules.length > 0
191
+ ? "⚠️ **Modules partagés détectés :** {sharedModules.join(', ')} — ces modules apparaissent dans plusieurs applications. Ils pourraient constituer une application transversale dédiée."
192
+ : ""}
193
+ ```
194
+
195
+ Ask via AskUserQuestion:
196
+ ```
197
+ question: "{language == 'fr' ? 'Confirmez-vous cette structure multi-application ?' : 'Do you confirm this multi-application structure?'}"
198
+ header: "Architecture"
199
+ options:
200
+ - label: "{language == 'fr' ? 'Oui, {candidates.length} applications' : 'Yes, {candidates.length} applications'}"
201
+ description: "{language == 'fr' ? 'Créer un projet avec les applications identifiées' : 'Create a project with the identified applications'}"
202
+ - label: "{language == 'fr' ? 'Extraire les modules partagés' : 'Extract shared modules'}" (only if sharedModules.length > 0)
203
+ description: "{language == 'fr' ? 'Créer une application dédiée pour {sharedModules.join(', ')} ({candidates.length + 1} applications au total)' : 'Create a dedicated app for {sharedModules.join(', ')} ({candidates.length + 1} total)'}"
204
+ - label: "{language == 'fr' ? 'Application unique' : 'Single application'}"
205
+ description: "{language == 'fr' ? 'Tout regrouper en une seule application avec plusieurs modules' : 'Group everything into one application with multiple modules'}"
206
+ ```
207
+
208
+ **IF "Oui, N applications" or "Extraire les modules partagés":**
209
+
210
+ ```yaml
211
+ workflow_mode: "project"
212
+ project_name: derived from feature_description
213
+ candidate_applications: [{ name, description, modules, context }]
214
+ shared_modules_extracted: boolean # true if user chose extraction
215
+ ```
216
+
217
+ → Skip step 4 (application name) — applications will be confirmed in step-01b
218
+ → Continue to step 5 (language selection)
219
+
220
+ **IF "Application unique":**
221
+
222
+ ```yaml
223
+ workflow_mode: "application"
224
+ ```
225
+
226
+ → Continue to step 4 normally
227
+
228
+ **IF no multi-app patterns detected:**
229
+ → Continue to step 4 normally
230
+
132
231
  ## Step 4: Determine Application Name
133
232
 
233
+ > **This step is SKIPPED if `workflow_mode = "project"` (multi-app detected in step 3b).**
234
+
134
235
  ```
135
- IF workflow_type = "update":
236
+ IF workflow_mode = "project":
237
+ application_name = project_name // Project-level name, not a single app name
238
+ context = "business" // Default, each app can have its own context
239
+ → Skip to step 5
240
+
241
+ ELSE IF workflow_type = "update":
136
242
  application_name = existing app name (from step 3)
137
243
  ELSE:
138
244
  Analyze {feature_description} to extract application name
@@ -149,12 +255,13 @@ ELSE:
149
255
  **Validate business context:**
150
256
  ```
151
257
  validate_business_context("business")
152
- → BA restricted to 'business' context only
258
+ → BA restricted to 'business' context only (in standalone mode)
259
+ → In project mode, each application can target any context
153
260
  ```
154
261
 
155
262
  **Store:**
156
263
  ```yaml
157
- application_name: string
264
+ application_name: string # or project_name if project mode
158
265
  context: "business"
159
266
  ```
160
267
 
@@ -216,15 +323,22 @@ feature_id: string
216
323
  ## Step 7: Create Output Directory Structure
217
324
 
218
325
  ```
219
- IF workflow_type = "new":
326
+ IF workflow_mode = "project":
327
+ // Project mode: create project-level directory + per-app directories later (in step-01b)
328
+ mkdir -p docs/business-analyse/v1.0
329
+ docs_dir = "docs/business-analyse/v{version}"
330
+
331
+ ELSE IF workflow_type = "new":
220
332
  mkdir -p docs/business/{application_name}/business-analyse/v1.0
333
+ docs_dir = "docs/business/{app}/business-analyse/v{version}"
334
+
221
335
  ELSE:
222
336
  Directory already exists from ba-writer.createVersion()
223
337
  ```
224
338
 
225
339
  **Store:**
226
340
  ```yaml
227
- docs_dir: "docs/business/{app}/business-analyse/v{version}"
341
+ docs_dir: string
228
342
  ```
229
343
 
230
344
  ## Step 8: Deploy JSON Schemas to Project (MANDATORY)
@@ -277,34 +391,67 @@ See [references/cache-warming-strategy.md](../references/cache-warming-strategy.
277
391
  Create the master feature document using ba-writer agent.
278
392
 
279
393
  ```
280
- ba-writer.createApplicationFeature({
281
- id: {feature_id},
282
- version: {version},
283
- scope: "application",
284
- status: "draft",
285
- metadata: {
286
- application: {application_name},
287
- context: "business",
288
- language: {language},
289
- featureDescription: {feature_description},
290
- workflowType: {workflow_type},
291
- analysisMode: "interactive",
292
- mcpAvailable: true,
293
- workflow: {
294
- mode: "application",
295
- moduleOrder: [],
296
- currentModuleIndex: 0,
297
- completedModules: [],
298
- currentModule: null
394
+ IF workflow_mode = "project":
395
+ // PROJECT MODE: Create project-level feature.json
396
+ ba-writer.createProjectFeature({
397
+ id: generate_project_id(), // PROJ-NNN
398
+ version: {version},
399
+ scope: "project",
400
+ status: "draft",
401
+ metadata: {
402
+ projectName: {project_name},
403
+ language: {language},
404
+ featureDescription: {feature_description},
405
+ workflowType: {workflow_type},
406
+ analysisMode: "interactive",
407
+ mcpAvailable: true,
408
+ candidateApplications: {candidate_applications}, // From step 3b detection
409
+ sharedModulesExtracted: {shared_modules_extracted},
410
+ workflow: {
411
+ mode: "project",
412
+ applicationOrder: [],
413
+ currentApplicationIndex: 0,
414
+ completedApplications: []
415
+ }
299
416
  }
300
- }
301
- })
302
- ```
417
+ })
303
418
 
304
- **Output path:**
305
- `docs/business/{app}/business-analyse/v{version}/feature.json`
419
+ Output path: docs/business-analyse/v{version}/feature.json
306
420
 
307
- > **Note:** Always create the master feature.json first. Step-02 (decomposition) determines if it's single or multi-module.
421
+ Store:
422
+ project_id: string // PROJ-NNN
423
+ feature_id: project_id // In project mode, feature_id = project_id for step-01
424
+
425
+ ELSE:
426
+ // SINGLE-APP MODE: Create application-level feature.json
427
+ ba-writer.createApplicationFeature({
428
+ id: {feature_id},
429
+ version: {version},
430
+ scope: "application",
431
+ status: "draft",
432
+ metadata: {
433
+ application: {application_name},
434
+ context: "business",
435
+ language: {language},
436
+ featureDescription: {feature_description},
437
+ workflowType: {workflow_type},
438
+ analysisMode: "interactive",
439
+ mcpAvailable: true,
440
+ workflow: {
441
+ mode: "application",
442
+ moduleOrder: [],
443
+ currentModuleIndex: 0,
444
+ completedModules: [],
445
+ currentModule: null
446
+ }
447
+ }
448
+ })
449
+
450
+ Output path: docs/business/{app}/business-analyse/v{version}/feature.json
451
+ ```
452
+
453
+ > **Note:** In project mode, per-application feature.json files are created later in step-01b.
454
+ > In single-app mode, step-02 (decomposition) determines if it's single or multi-module.
308
455
 
309
456
  ## Step 10: Update Config
310
457
 
@@ -335,13 +482,18 @@ Update `.business-analyse/config.json` with new feature information.
335
482
  |--------------------|----------------------------------------------|
336
483
  | Feature ID | {feature_id} |
337
484
  | Workflow | {workflow_type} |
338
- | Application | business/{application_name} |
485
+ | Mode | {workflow_mode === "project" ? "Multi-application project" : "Single application"} |
486
+ | Application/Project| {workflow_mode === "project" ? project_name + " (" + candidate_applications.length + " apps)" : "business/" + application_name} |
339
487
  | Output Path | {docs_dir}/feature.json |
340
488
  | Language | {language} |
341
489
  | Version | {version} |
342
490
  | MCP Available | true |
343
491
  | Analysis Mode | Interactive (always) |
344
492
 
493
+ {workflow_mode === "project"
494
+ ? "Candidate applications: " + candidate_applications.map(a => a.name).join(", ")
495
+ : ""}
496
+
345
497
  NEXT STEP: step-01-cadrage
346
498
  ═══════════════════════════════════════════════════════════════
347
499
  ```
@@ -352,14 +504,18 @@ After showing initialization summary, proceed to `./step-01-cadrage.md`
352
504
 
353
505
  **Pass context variables:**
354
506
  ```yaml
355
- feature_id: string
507
+ feature_id: string # FEAT-NNN (single-app) or PROJ-NNN (project)
356
508
  feature_description: string
357
509
  workflow_type: "new" | "update"
358
- application_name: string
510
+ workflow_mode: "application" | "project"
511
+ application_name: string # Single-app: app name. Project: project name.
512
+ applicationCode: string # PascalCase derived from application_name (preliminary, confirmed in step-01b)
513
+ project_id: string | null # PROJ-NNN if project mode, null if single-app
514
+ candidate_applications: array | null # Pre-identified apps from prompt (project mode only)
515
+ shared_modules_extracted: boolean # True if user chose to extract shared modules as new app
359
516
  language: string
360
517
  docs_dir: string
361
518
  mcp_available: boolean
362
- workflow_mode: "application"
363
519
  analysisMode: "interactive"
364
520
  version: string
365
521
  ```