@atlashub/smartstack-cli 3.34.0 → 3.35.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/init.html +409 -0
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +7 -24
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -2
- package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
- package/templates/skills/apex/SKILL.md +3 -3
- package/templates/skills/apex/references/post-checks.md +225 -0
- package/templates/skills/apex/references/smartstack-api.md +29 -1
- package/templates/skills/apex/references/smartstack-frontend.md +27 -0
- package/templates/skills/apex/references/smartstack-layers.md +18 -2
- package/templates/skills/apex/steps/step-00-init.md +73 -0
- package/templates/skills/apex/steps/step-01-analyze.md +21 -0
- package/templates/skills/apex/steps/step-03-execute.md +72 -5
- package/templates/skills/apex/steps/step-04-examine.md +7 -1
- package/templates/skills/business-analyse/SKILL.md +4 -3
- package/templates/skills/business-analyse/_shared.md +9 -0
- package/templates/skills/business-analyse/schemas/application-schema.json +13 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +190 -34
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +129 -10
- package/templates/skills/business-analyse/steps/step-01b-applications.md +184 -13
- package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +5 -1
- package/templates/skills/ralph-loop/SKILL.md +5 -0
- package/templates/skills/ralph-loop/references/category-rules.md +29 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +85 -2
- package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
- package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
- package/templates/skills/ralph-loop/steps/step-02-execute.md +45 -1
- package/templates/skills/ralph-loop/steps/step-05-report.md +19 -0
- package/scripts/health-check.sh +0 -168
- package/scripts/postinstall.js +0 -18
|
@@ -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
|
-
|
|
|
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:**
|
|
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 |
|
|
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 (
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
|
|
305
|
-
`docs/business/{app}/business-analyse/v{version}/feature.json`
|
|
419
|
+
Output path: docs/business-analyse/v{version}/feature.json
|
|
306
420
|
|
|
307
|
-
|
|
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
|
-
|
|
|
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
|
-
|
|
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
|
```
|
|
@@ -41,14 +41,31 @@ Phase 5: PERIMETRE → Bound scope with roles, coverage matrix (sections
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
+
## PROJECT vs APPLICATION MODE
|
|
45
|
+
|
|
46
|
+
> **When `workflow_mode = "project"` (detected in step-00 from prompt structure):**
|
|
47
|
+
> The cadrage operates at the **PROJECT level**, not at a single application level.
|
|
48
|
+
> - Phase 1-3: Gather requirements for the ENTIRE project (all applications combined)
|
|
49
|
+
> - Phase 4: ANTICIPATION analyzes cross-application shared modules and suggests extracting them as dedicated applications
|
|
50
|
+
> - Phase 5: Coverage matrix maps requirements to APPLICATIONS first, then modules within each application
|
|
51
|
+
> - `candidate_applications` from step-00 are used as starting structure (can be modified during cadrage)
|
|
52
|
+
>
|
|
53
|
+
> **When `workflow_mode = "application"` (single-app):**
|
|
54
|
+
> The cadrage operates at the application level as before.
|
|
55
|
+
|
|
44
56
|
## PHASE 1: ECOUTE (Listen)
|
|
45
57
|
|
|
46
58
|
### 1. Read Current State
|
|
47
59
|
|
|
48
60
|
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
→ Read
|
|
61
|
+
IF workflow_mode === "project":
|
|
62
|
+
ba-reader.findProjectFeature({project_id})
|
|
63
|
+
→ Read metadata: projectName, language, candidateApplications
|
|
64
|
+
→ Read cadrage section (if resuming)
|
|
65
|
+
ELSE:
|
|
66
|
+
ba-reader.findFeature({feature_id})
|
|
67
|
+
→ Read metadata: application, language, workflow.mode, useCase
|
|
68
|
+
→ Read cadrage section (if resuming)
|
|
52
69
|
```
|
|
53
70
|
|
|
54
71
|
IF cadrage already completed (status = "framed"):
|
|
@@ -507,6 +524,91 @@ options:
|
|
|
507
524
|
|
|
508
525
|
6. Accepted suggestions enrich `coverageMatrix` and `globalScope`.
|
|
509
526
|
|
|
527
|
+
### 5b. Cross-Application Shared Module Detection (PROJECT MODE ONLY)
|
|
528
|
+
|
|
529
|
+
> **When `workflow_mode = "project"`, analyze candidate applications for shared modules.**
|
|
530
|
+
> A module that appears in 2+ applications should be extracted as a dedicated transversal application.
|
|
531
|
+
|
|
532
|
+
**This section is SKIPPED if `workflow_mode !== "project"`.**
|
|
533
|
+
|
|
534
|
+
**Process:**
|
|
535
|
+
|
|
536
|
+
1. Build module inventory per candidate application:
|
|
537
|
+
|
|
538
|
+
```javascript
|
|
539
|
+
// From candidateApplications (step-00) + enriched by cadrage phases 1-4
|
|
540
|
+
const modulesByApp = {};
|
|
541
|
+
for (const app of candidate_applications) {
|
|
542
|
+
modulesByApp[app.name] = app.modules; // e.g., { "RH": ["Employes", "Conges", "Temps"], "Projet": ["Projets", "Temps"] }
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
2. Detect modules appearing in 2+ applications:
|
|
547
|
+
|
|
548
|
+
```javascript
|
|
549
|
+
const allModules = Object.values(modulesByApp).flat();
|
|
550
|
+
const moduleCounts = {};
|
|
551
|
+
for (const mod of allModules) {
|
|
552
|
+
const normalized = normalizeModuleName(mod); // "Temps", "Saisie du temps", "Time Tracking" → same concept
|
|
553
|
+
moduleCounts[normalized] = (moduleCounts[normalized] || 0) + 1;
|
|
554
|
+
}
|
|
555
|
+
const sharedModules = Object.entries(moduleCounts)
|
|
556
|
+
.filter(([_, count]) => count >= 2)
|
|
557
|
+
.map(([name, count]) => ({ name, appearsIn: count, applications: findAppsContaining(name) }));
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
3. IF shared modules found, propose extraction:
|
|
561
|
+
|
|
562
|
+
```
|
|
563
|
+
{language == "fr"
|
|
564
|
+
? "### Modules partagés détectés\n\nCertains modules apparaissent dans plusieurs applications. Les extraire en application(s) dédiée(s) améliore la réutilisabilité et évite la duplication :"
|
|
565
|
+
: "### Shared modules detected\n\nSome modules appear in multiple applications. Extracting them as dedicated application(s) improves reusability and avoids duplication:"}
|
|
566
|
+
|
|
567
|
+
| Module | Présent dans | Suggestion |
|
|
568
|
+
|--------|-------------|-----------|
|
|
569
|
+
{for each shared: name | apps.join(", ") | "Extraire en application '{name}'" }
|
|
570
|
+
|
|
571
|
+
{language == "fr"
|
|
572
|
+
? "**Exemple :** Si 'Gestion du temps' est dans RH et Projet, créer une application 'Temps' dédiée que les deux autres consomment."
|
|
573
|
+
: "**Example:** If 'Time Management' is in HR and Project, create a dedicated 'Time' application that the other two consume."}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
Ask via AskUserQuestion:
|
|
577
|
+
```
|
|
578
|
+
question: "{language == 'fr' ? 'Souhaitez-vous extraire les modules partagés en application(s) dédiée(s) ?' : 'Do you want to extract shared modules as dedicated application(s)?'}"
|
|
579
|
+
header: "Extraction"
|
|
580
|
+
options:
|
|
581
|
+
- label: "{language == 'fr' ? 'Oui, extraire' : 'Yes, extract'}"
|
|
582
|
+
description: "{language == 'fr' ? 'Créer {sharedModules.length} application(s) transversale(s) supplémentaire(s)' : 'Create {sharedModules.length} additional cross-cutting application(s)'}"
|
|
583
|
+
- label: "{language == 'fr' ? 'Non, garder en l\'état' : 'No, keep as-is'}"
|
|
584
|
+
description: "{language == 'fr' ? 'Chaque application garde sa propre version du module' : 'Each application keeps its own version of the module'}"
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**IF "Oui, extraire":**
|
|
588
|
+
```javascript
|
|
589
|
+
for (const shared of sharedModules) {
|
|
590
|
+
// Create new candidate application
|
|
591
|
+
candidate_applications.push({
|
|
592
|
+
name: shared.name,
|
|
593
|
+
description: `Application transversale pour ${shared.name}`,
|
|
594
|
+
modules: [shared.name],
|
|
595
|
+
context: "business",
|
|
596
|
+
isTransversal: true,
|
|
597
|
+
consumedBy: shared.applications
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
// Remove the shared module from original applications
|
|
601
|
+
for (const appName of shared.applications) {
|
|
602
|
+
const app = candidate_applications.find(a => a.name === appName);
|
|
603
|
+
app.modules = app.modules.filter(m => normalizeModuleName(m) !== shared.name);
|
|
604
|
+
app.dependencies = app.dependencies || [];
|
|
605
|
+
app.dependencies.push({ target: shared.name, type: "data-dependency" });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Update `candidate_applications` in the project feature.json.
|
|
611
|
+
|
|
510
612
|
---
|
|
511
613
|
|
|
512
614
|
## PHASE 5: PERIMETRE (Bound Scope)
|
|
@@ -720,9 +822,25 @@ ba-writer.enrichSection({
|
|
|
720
822
|
ba-writer.updateStatus({feature_id}, "framed")
|
|
721
823
|
```
|
|
722
824
|
|
|
723
|
-
### 9. Multi-Application Detection
|
|
825
|
+
### 9. Multi-Application Detection
|
|
724
826
|
|
|
725
827
|
> **Analyze whether the project spans multiple independent applications.**
|
|
828
|
+
> **SKIP this section entirely if `workflow_mode = "project"`** — multi-app was already detected in step-00
|
|
829
|
+
> and cross-app analysis was done in section 5b above.
|
|
830
|
+
|
|
831
|
+
**IF `workflow_mode === "project"`:**
|
|
832
|
+
→ SKIP section 9 entirely. Candidate applications are already identified and enriched.
|
|
833
|
+
→ Write cadrage data to project-level feature.json:
|
|
834
|
+
```
|
|
835
|
+
ba-writer.enrichSection({
|
|
836
|
+
projectId: {project_id},
|
|
837
|
+
section: "cadrage",
|
|
838
|
+
data: {cadrage data collected in phases 1-5 above}
|
|
839
|
+
})
|
|
840
|
+
```
|
|
841
|
+
→ Continue to section 10 (summary).
|
|
842
|
+
|
|
843
|
+
**IF `workflow_mode === "application"` (single-app mode):**
|
|
726
844
|
|
|
727
845
|
After coverage matrix is validated, check if the identified functional domains suggest multiple applications:
|
|
728
846
|
|
|
@@ -763,15 +881,15 @@ ba-writer.createProjectFeature({
|
|
|
763
881
|
metadata: {
|
|
764
882
|
projectName: {project_name derived from feature_description},
|
|
765
883
|
language: {language},
|
|
766
|
-
featureDescription: {feature_description}
|
|
884
|
+
featureDescription: {feature_description},
|
|
885
|
+
candidateApplications: [{detected candidates}]
|
|
767
886
|
},
|
|
768
887
|
cadrage: {cadrage data already collected in this step}
|
|
769
888
|
})
|
|
770
889
|
```
|
|
771
|
-
2. Set `
|
|
890
|
+
2. Set `workflow_mode = "project"` and `project_id = PROJ-NNN`
|
|
772
891
|
3. Load `questionnaire/00b-project.md` for additional project-level questions
|
|
773
|
-
4.
|
|
774
|
-
5. **STOP — DO NOT load step-02**
|
|
892
|
+
4. Continue to section 10 and then step-01b
|
|
775
893
|
|
|
776
894
|
**IF "Single application":**
|
|
777
895
|
→ Continue to step 10 (display summary) and step-02 as usual.
|
|
@@ -807,5 +925,6 @@ ba-writer.createProjectFeature({
|
|
|
807
925
|
|
|
808
926
|
## NEXT STEP
|
|
809
927
|
|
|
810
|
-
|
|
811
|
-
|
|
928
|
+
Load: `./step-01b-applications.md`
|
|
929
|
+
|
|
930
|
+
> step-01b handles both single-app (lightweight identity confirmation) and multi-app (full application decomposition).
|