@atlashub/smartstack-cli 3.33.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/agents.html +5 -1
- package/.documentation/apex.html +644 -0
- package/.documentation/business-analyse.html +81 -1
- package/.documentation/cli-commands.html +5 -1
- package/.documentation/commands.html +5 -1
- package/.documentation/efcore.html +5 -1
- package/.documentation/gitflow.html +5 -1
- package/.documentation/hooks.html +5 -1
- package/.documentation/index.html +60 -2
- package/.documentation/init.html +414 -1
- package/.documentation/installation.html +5 -1
- package/.documentation/ralph-loop.html +365 -216
- package/.documentation/test-web.html +5 -1
- 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/agents/ba-writer.md +142 -15
- package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
- package/templates/skills/apex/SKILL.md +9 -3
- package/templates/skills/apex/_shared.md +49 -4
- package/templates/skills/{ralph-loop → apex}/references/core-seed-data.md +20 -11
- package/templates/skills/{ralph-loop → apex}/references/error-classification.md +2 -1
- package/templates/skills/apex/references/post-checks.md +463 -3
- package/templates/skills/apex/references/smartstack-api.md +76 -8
- package/templates/skills/apex/references/smartstack-frontend.md +74 -1
- package/templates/skills/apex/references/smartstack-layers.md +21 -3
- package/templates/skills/apex/steps/step-00-init.md +121 -1
- package/templates/skills/apex/steps/step-01-analyze.md +58 -0
- package/templates/skills/apex/steps/step-02-plan.md +36 -0
- package/templates/skills/apex/steps/step-03-execute.md +114 -7
- package/templates/skills/apex/steps/step-04-examine.md +116 -2
- package/templates/skills/business-analyse/SKILL.md +31 -20
- package/templates/skills/business-analyse/_module-loop.md +68 -9
- package/templates/skills/business-analyse/_shared.md +80 -21
- package/templates/skills/business-analyse/questionnaire/00-application.md +4 -2
- package/templates/skills/business-analyse/questionnaire/00b-project.md +85 -0
- package/templates/skills/business-analyse/references/deploy-modes.md +69 -0
- package/templates/skills/business-analyse/references/team-orchestration.md +158 -7
- package/templates/skills/business-analyse/schemas/application-schema.json +15 -1
- package/templates/skills/business-analyse/schemas/project-schema.json +490 -0
- package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +220 -38
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +184 -5
- package/templates/skills/business-analyse/steps/step-01b-applications.md +423 -0
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +23 -6
- package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +32 -7
- package/templates/skills/business-analyse/steps/step-04a-collect.md +111 -0
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +296 -103
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +46 -14
- package/templates/skills/documentation/SKILL.md +92 -2
- package/templates/skills/ralph-loop/SKILL.md +14 -17
- package/templates/skills/ralph-loop/references/category-rules.md +63 -683
- package/templates/skills/ralph-loop/references/compact-loop.md +188 -428
- package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +13 -14
- package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
- package/templates/skills/ralph-loop/steps/step-02-execute.md +80 -691
- package/templates/skills/ralph-loop/steps/step-03-commit.md +38 -79
- package/templates/skills/ralph-loop/steps/step-04-check.md +39 -58
- package/templates/skills/ralph-loop/steps/step-05-report.md +31 -123
- package/scripts/health-check.sh +0 -168
- package/scripts/postinstall.js +0 -18
|
@@ -85,7 +85,8 @@ mcp__smartstack__validate_conventions({ checks: ["tables"] })
|
|
|
85
85
|
|
|
86
86
|
Execute workflow detection algorithm:
|
|
87
87
|
1. **Review Mode Detection:** Check if `{feature_description}` starts with `-review`
|
|
88
|
-
2. **Existing
|
|
88
|
+
2. **Existing Projects Scanner:** Glob `docs/business-analyse/*/feature.json` (project-level)
|
|
89
|
+
2b. **Existing Applications Scanner:** Glob `docs/business/*/business-analyse/*/feature.json` + `docs/platform/*/business-analyse/*/feature.json` + `docs/personal/*/business-analyse/*/feature.json`
|
|
89
90
|
3. **Similarity Analysis:** Score user intent against existing apps (>= 80 = strong match)
|
|
90
91
|
4. **Decision Tree:** Prompt user with relevant options
|
|
91
92
|
|
|
@@ -119,15 +120,125 @@ ELSE:
|
|
|
119
120
|
```yaml
|
|
120
121
|
workflow_type: "new" | "update" | "review"
|
|
121
122
|
existing_feature_id: string | null
|
|
123
|
+
existing_project_id: string | null # PROJ-NNN if resuming a project
|
|
122
124
|
version: "1.0" (new) | "1.1"+ (update)
|
|
123
125
|
review_json_path: string | null (review only)
|
|
124
126
|
existing_apps: array of { app, featureId, description, version }
|
|
127
|
+
existing_projects: array of { projectName, projectId, applications[], version }
|
|
125
128
|
```
|
|
126
129
|
|
|
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
|
+
|
|
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
|
+
|
|
127
231
|
## Step 4: Determine Application Name
|
|
128
232
|
|
|
233
|
+
> **This step is SKIPPED if `workflow_mode = "project"` (multi-app detected in step 3b).**
|
|
234
|
+
|
|
129
235
|
```
|
|
130
|
-
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":
|
|
131
242
|
application_name = existing app name (from step 3)
|
|
132
243
|
ELSE:
|
|
133
244
|
Analyze {feature_description} to extract application name
|
|
@@ -144,12 +255,13 @@ ELSE:
|
|
|
144
255
|
**Validate business context:**
|
|
145
256
|
```
|
|
146
257
|
validate_business_context("business")
|
|
147
|
-
→ 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
|
|
148
260
|
```
|
|
149
261
|
|
|
150
262
|
**Store:**
|
|
151
263
|
```yaml
|
|
152
|
-
application_name: string
|
|
264
|
+
application_name: string # or project_name if project mode
|
|
153
265
|
context: "business"
|
|
154
266
|
```
|
|
155
267
|
|
|
@@ -211,15 +323,22 @@ feature_id: string
|
|
|
211
323
|
## Step 7: Create Output Directory Structure
|
|
212
324
|
|
|
213
325
|
```
|
|
214
|
-
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":
|
|
215
332
|
mkdir -p docs/business/{application_name}/business-analyse/v1.0
|
|
333
|
+
docs_dir = "docs/business/{app}/business-analyse/v{version}"
|
|
334
|
+
|
|
216
335
|
ELSE:
|
|
217
336
|
Directory already exists from ba-writer.createVersion()
|
|
218
337
|
```
|
|
219
338
|
|
|
220
339
|
**Store:**
|
|
221
340
|
```yaml
|
|
222
|
-
docs_dir:
|
|
341
|
+
docs_dir: string
|
|
223
342
|
```
|
|
224
343
|
|
|
225
344
|
## Step 8: Deploy JSON Schemas to Project (MANDATORY)
|
|
@@ -272,34 +391,67 @@ See [references/cache-warming-strategy.md](../references/cache-warming-strategy.
|
|
|
272
391
|
Create the master feature document using ba-writer agent.
|
|
273
392
|
|
|
274
393
|
```
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
+
}
|
|
294
416
|
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
Output path: docs/business-analyse/v{version}/feature.json
|
|
298
420
|
|
|
299
|
-
|
|
300
|
-
|
|
421
|
+
Store:
|
|
422
|
+
project_id: string // PROJ-NNN
|
|
423
|
+
feature_id: project_id // In project mode, feature_id = project_id for step-01
|
|
301
424
|
|
|
302
|
-
|
|
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.
|
|
303
455
|
|
|
304
456
|
## Step 10: Update Config
|
|
305
457
|
|
|
@@ -330,13 +482,18 @@ Update `.business-analyse/config.json` with new feature information.
|
|
|
330
482
|
|--------------------|----------------------------------------------|
|
|
331
483
|
| Feature ID | {feature_id} |
|
|
332
484
|
| Workflow | {workflow_type} |
|
|
333
|
-
|
|
|
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} |
|
|
334
487
|
| Output Path | {docs_dir}/feature.json |
|
|
335
488
|
| Language | {language} |
|
|
336
489
|
| Version | {version} |
|
|
337
490
|
| MCP Available | true |
|
|
338
491
|
| Analysis Mode | Interactive (always) |
|
|
339
492
|
|
|
493
|
+
{workflow_mode === "project"
|
|
494
|
+
? "Candidate applications: " + candidate_applications.map(a => a.name).join(", ")
|
|
495
|
+
: ""}
|
|
496
|
+
|
|
340
497
|
NEXT STEP: step-01-cadrage
|
|
341
498
|
═══════════════════════════════════════════════════════════════
|
|
342
499
|
```
|
|
@@ -347,14 +504,18 @@ After showing initialization summary, proceed to `./step-01-cadrage.md`
|
|
|
347
504
|
|
|
348
505
|
**Pass context variables:**
|
|
349
506
|
```yaml
|
|
350
|
-
feature_id: string
|
|
507
|
+
feature_id: string # FEAT-NNN (single-app) or PROJ-NNN (project)
|
|
351
508
|
feature_description: string
|
|
352
509
|
workflow_type: "new" | "update"
|
|
353
|
-
|
|
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
|
|
354
516
|
language: string
|
|
355
517
|
docs_dir: string
|
|
356
518
|
mcp_available: boolean
|
|
357
|
-
workflow_mode: "application"
|
|
358
519
|
analysisMode: "interactive"
|
|
359
520
|
version: string
|
|
360
521
|
```
|
|
@@ -372,9 +533,11 @@ version: string
|
|
|
372
533
|
|
|
373
534
|
If initialization was interrupted:
|
|
374
535
|
|
|
375
|
-
1. Check `.business-analyse/config.json` for currentFeature
|
|
376
|
-
2. If
|
|
377
|
-
|
|
536
|
+
1. Check `.business-analyse/config.json` for currentFeature or currentProject
|
|
537
|
+
2. If project ID exists, search for project feature.json in `docs/business-analyse/`
|
|
538
|
+
- If found with scope = "project": resume project mode (see Project Resume below)
|
|
539
|
+
3. If feature ID exists, search for feature.json in `docs/business/`, `docs/platform/`, `docs/personal/`
|
|
540
|
+
4. If found, check status and `metadata.workflow.lastCompletedStep`:
|
|
378
541
|
|
|
379
542
|
**Status-based resume routing (check in this order):**
|
|
380
543
|
|
|
@@ -401,3 +564,22 @@ If initialization was interrupted:
|
|
|
401
564
|
- Otherwise: offer to resume from last completed step
|
|
402
565
|
|
|
403
566
|
4. If not found, create fresh feature.json
|
|
567
|
+
|
|
568
|
+
**Project Resume (project mode):**
|
|
569
|
+
|
|
570
|
+
If a project-level feature.json is found (scope = "project"):
|
|
571
|
+
|
|
572
|
+
- If status = `"draft"` or `"framed"`:
|
|
573
|
+
→ Resume at `step-01-cadrage.md` or `step-01b-applications.md`
|
|
574
|
+
|
|
575
|
+
- If status = `"decomposed"`:
|
|
576
|
+
→ Check `metadata.workflow.currentApplicationIndex` and `completedApplications[]`
|
|
577
|
+
→ Resume module specification for current application (step-02 or step-03)
|
|
578
|
+
|
|
579
|
+
- If status = `"specified"`:
|
|
580
|
+
→ All applications specified → Resume at `step-04a-collect.md`
|
|
581
|
+
|
|
582
|
+
- If status = `"consolidated"`:
|
|
583
|
+
→ Resume at `step-05a-handoff.md`
|
|
584
|
+
|
|
585
|
+
Follow `_module-loop.md` "Project Mode (multi app)" resume logic for detailed routing.
|
|
@@ -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,7 +822,82 @@ ba-writer.enrichSection({
|
|
|
720
822
|
ba-writer.updateStatus({feature_id}, "framed")
|
|
721
823
|
```
|
|
722
824
|
|
|
723
|
-
### 9.
|
|
825
|
+
### 9. Multi-Application Detection
|
|
826
|
+
|
|
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):**
|
|
844
|
+
|
|
845
|
+
After coverage matrix is validated, check if the identified functional domains suggest multiple applications:
|
|
846
|
+
|
|
847
|
+
**Detection triggers (ANY of these = suggest multi-app):**
|
|
848
|
+
- Coverage matrix entries reference different navigation contexts (business + personal + platform)
|
|
849
|
+
- User mentioned "multiple applications", "several apps", "cross-platform"
|
|
850
|
+
- Functional domains form clearly independent applications with separate user bases
|
|
851
|
+
- Stakeholders only interact with specific domains (not shared across all)
|
|
852
|
+
|
|
853
|
+
**IF detection triggers matched:**
|
|
854
|
+
|
|
855
|
+
Display analysis as markdown:
|
|
856
|
+
```
|
|
857
|
+
{language == "fr"
|
|
858
|
+
? "### Analyse multi-application\n\nD'après mon analyse, ce projet couvre plusieurs domaines fonctionnels qui pourraient former des applications indépendantes :\n\n"
|
|
859
|
+
: "### Multi-Application Analysis\n\nBased on my analysis, this project spans multiple functional domains that could form independent applications:\n\n"}
|
|
860
|
+
|
|
861
|
+
| Domain | Suggested Context | Suggested Application | Key Modules |
|
|
862
|
+
|--------|-------------------|----------------------|-------------|
|
|
863
|
+
{for each identified domain: domain name | business/platform/personal | PascalCase name | top modules}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
Ask via AskUserQuestion:
|
|
867
|
+
```
|
|
868
|
+
question: "{language == 'fr' ? 'Ce projet constitue-t-il une seule application ou plusieurs applications distinctes ?' : 'Is this a single application or multiple independent applications?'}"
|
|
869
|
+
header: "Architecture"
|
|
870
|
+
options:
|
|
871
|
+
- label: "{language == 'fr' ? 'Application unique' : 'Single application'}"
|
|
872
|
+
description: "{language == 'fr' ? 'Tous les domaines forment une seule application avec plusieurs modules' : 'All domains form one application with multiple modules'}"
|
|
873
|
+
- label: "{language == 'fr' ? 'Applications multiples' : 'Multiple applications'}"
|
|
874
|
+
description: "{language == 'fr' ? 'Chaque domaine est une application indépendante (navigation, rôles et préfixe de table séparés)' : 'Each domain is an independent application (separate navigation, roles, and table prefix)'}"
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
**IF "Multiple applications":**
|
|
878
|
+
1. Create project-level feature.json:
|
|
879
|
+
```
|
|
880
|
+
ba-writer.createProjectFeature({
|
|
881
|
+
metadata: {
|
|
882
|
+
projectName: {project_name derived from feature_description},
|
|
883
|
+
language: {language},
|
|
884
|
+
featureDescription: {feature_description},
|
|
885
|
+
candidateApplications: [{detected candidates}]
|
|
886
|
+
},
|
|
887
|
+
cadrage: {cadrage data already collected in this step}
|
|
888
|
+
})
|
|
889
|
+
```
|
|
890
|
+
2. Set `workflow_mode = "project"` and `project_id = PROJ-NNN`
|
|
891
|
+
3. Load `questionnaire/00b-project.md` for additional project-level questions
|
|
892
|
+
4. Continue to section 10 and then step-01b
|
|
893
|
+
|
|
894
|
+
**IF "Single application":**
|
|
895
|
+
→ Continue to step 10 (display summary) and step-02 as usual.
|
|
896
|
+
|
|
897
|
+
**IF no detection triggers matched:**
|
|
898
|
+
→ Skip this section entirely — continue to step 10 (display summary).
|
|
899
|
+
|
|
900
|
+
### 10. Display Summary
|
|
724
901
|
|
|
725
902
|
```
|
|
726
903
|
## Cadrage Complete - {feature_id}
|
|
@@ -748,4 +925,6 @@ ba-writer.updateStatus({feature_id}, "framed")
|
|
|
748
925
|
|
|
749
926
|
## NEXT STEP
|
|
750
927
|
|
|
751
|
-
Load: `./step-
|
|
928
|
+
Load: `./step-01b-applications.md`
|
|
929
|
+
|
|
930
|
+
> step-01b handles both single-app (lightweight identity confirmation) and multi-app (full application decomposition).
|