@atlashub/smartstack-cli 3.19.0 → 3.21.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/dist/index.js +53 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +1 -0
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/gitflow/cleanup.md +5 -1
- package/templates/agents/gitflow/finish.md +2 -0
- package/templates/agents/gitflow/init-clone.md +13 -0
- package/templates/agents/gitflow/init-validate.md +14 -0
- package/templates/agents/gitflow/status.md +6 -0
- package/templates/project/api.ts.template +8 -29
- package/templates/project/appsettings.json.template +1 -0
- package/templates/skills/business-analyse/html/ba-interactive.html +562 -150
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +11 -6
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +209 -4
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +2 -8
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +57 -2
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +3 -1
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +112 -22
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +7 -0
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +1 -1
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +89 -31
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +64 -0
- package/templates/skills/business-analyse/html/src/template.html +8 -76
- package/templates/skills/business-analyse/references/deploy-data-build.md +9 -7
- package/templates/skills/business-analyse/references/html-data-mapping.md +20 -28
- package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -1
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +16 -3
- package/templates/skills/business-analyse/steps/step-03c-compile.md +55 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +82 -15
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +77 -3
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +27 -0
- package/templates/skills/gitflow/_shared.md +65 -17
- package/templates/skills/gitflow/phases/status.md +8 -3
- package/templates/skills/gitflow/steps/step-start.md +3 -0
|
@@ -1,62 +1,120 @@
|
|
|
1
1
|
/* ============================================
|
|
2
|
-
SIDEBAR -
|
|
2
|
+
SIDEBAR - Hierarchical Tree Navigation
|
|
3
3
|
============================================ */
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
/* Sidebar header */
|
|
6
|
+
.sidebar-header {
|
|
7
|
+
padding: 0.75rem 1rem;
|
|
8
|
+
border-bottom: 1px solid var(--border);
|
|
9
|
+
background: var(--bg-hover);
|
|
10
|
+
}
|
|
11
|
+
.sidebar-app-name {
|
|
12
|
+
font-size: 0.95rem;
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
color: var(--primary-light);
|
|
15
|
+
display: block;
|
|
16
|
+
white-space: nowrap;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
text-overflow: ellipsis;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Nav groups (top-level: Cadrage, Modules, Consolidation, Synthese) */
|
|
22
|
+
.nav-group { padding: 0.4rem 0; }
|
|
5
23
|
.nav-group + .nav-group { border-top: 1px solid var(--border); }
|
|
6
24
|
|
|
7
25
|
.nav-group-title {
|
|
8
|
-
font-size: 0.
|
|
26
|
+
font-size: 0.7rem;
|
|
9
27
|
text-transform: uppercase;
|
|
10
28
|
letter-spacing: 0.1em;
|
|
11
29
|
color: var(--text-muted);
|
|
12
|
-
padding: 0 1rem;
|
|
13
|
-
margin-bottom: 0.
|
|
30
|
+
padding: 0.4rem 1rem;
|
|
31
|
+
margin-bottom: 0.15rem;
|
|
14
32
|
font-weight: 600;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
gap: 0.3rem;
|
|
37
|
+
user-select: none;
|
|
38
|
+
transition: color var(--transition-fast);
|
|
39
|
+
}
|
|
40
|
+
.nav-group-title:hover { color: var(--text-bright); }
|
|
41
|
+
|
|
42
|
+
/* Chevron icon for expand/collapse */
|
|
43
|
+
.nav-chevron {
|
|
44
|
+
font-size: 0.6rem;
|
|
45
|
+
display: inline-block;
|
|
46
|
+
transition: transform var(--transition-fast);
|
|
47
|
+
color: var(--text-muted);
|
|
48
|
+
width: 12px;
|
|
49
|
+
text-align: center;
|
|
50
|
+
flex-shrink: 0;
|
|
15
51
|
}
|
|
52
|
+
.nav-chevron.expanded { transform: rotate(90deg); }
|
|
16
53
|
|
|
54
|
+
/* Nav items (leaf nodes) */
|
|
17
55
|
.nav-item {
|
|
18
56
|
display: flex;
|
|
19
57
|
align-items: center;
|
|
20
|
-
gap: 0.
|
|
21
|
-
padding: 0.
|
|
58
|
+
gap: 0.4rem;
|
|
59
|
+
padding: 0.35rem 1rem;
|
|
22
60
|
color: var(--text);
|
|
23
61
|
text-decoration: none;
|
|
24
|
-
font-size: 0.
|
|
62
|
+
font-size: 0.82rem;
|
|
25
63
|
cursor: pointer;
|
|
26
64
|
transition: all var(--transition-fast);
|
|
27
65
|
border-left: 3px solid transparent;
|
|
28
66
|
}
|
|
29
67
|
.nav-item:hover { background: var(--bg-hover); color: var(--text-bright); }
|
|
30
|
-
.nav-item.active {
|
|
68
|
+
.nav-item.active {
|
|
69
|
+
background: rgba(99,102,241,0.1);
|
|
70
|
+
border-left-color: var(--primary);
|
|
71
|
+
color: var(--primary-light);
|
|
72
|
+
font-weight: 500;
|
|
73
|
+
}
|
|
31
74
|
|
|
32
|
-
.nav-item .nav-icon {
|
|
75
|
+
.nav-item .nav-icon {
|
|
76
|
+
font-size: 0.45rem;
|
|
77
|
+
width: 12px;
|
|
78
|
+
text-align: center;
|
|
79
|
+
color: var(--border-light);
|
|
80
|
+
flex-shrink: 0;
|
|
81
|
+
}
|
|
33
82
|
.nav-item .nav-badge {
|
|
34
83
|
margin-left: auto;
|
|
35
|
-
font-size: 0.
|
|
84
|
+
font-size: 0.6rem;
|
|
36
85
|
background: var(--bg-hover);
|
|
37
|
-
padding: 0.1rem 0.
|
|
86
|
+
padding: 0.1rem 0.35rem;
|
|
38
87
|
border-radius: 10px;
|
|
39
88
|
color: var(--text-muted);
|
|
89
|
+
min-width: 16px;
|
|
90
|
+
text-align: center;
|
|
40
91
|
}
|
|
41
92
|
|
|
42
|
-
|
|
43
|
-
.nav-children
|
|
93
|
+
/* Nested children (indented) */
|
|
94
|
+
.nav-children { margin-left: 0; }
|
|
95
|
+
.nav-children .nav-item { padding-left: 1.6rem; font-size: 0.8rem; }
|
|
96
|
+
.nav-children .nav-children .nav-item { padding-left: 2.4rem; font-size: 0.78rem; }
|
|
97
|
+
.nav-children .nav-children .nav-children .nav-item { padding-left: 3rem; font-size: 0.75rem; }
|
|
44
98
|
|
|
45
|
-
/*
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
99
|
+
/* Module header in nav (collapsible) */
|
|
100
|
+
.nav-module-header {
|
|
101
|
+
font-weight: 500;
|
|
102
|
+
color: var(--text-bright);
|
|
103
|
+
font-size: 0.85rem;
|
|
104
|
+
}
|
|
105
|
+
.nav-module-header:hover { color: var(--primary-light); }
|
|
106
|
+
|
|
107
|
+
/* Section/Resource items in nav */
|
|
108
|
+
.nav-section-item { margin-top: 0.1rem; }
|
|
109
|
+
.nav-section-link { font-style: italic; }
|
|
110
|
+
.nav-icon-section { font-size: 0.5rem; color: var(--accent); }
|
|
111
|
+
.nav-icon-resource { font-size: 0.7rem; color: var(--border-light); }
|
|
112
|
+
.nav-resource-link {
|
|
113
|
+
cursor: default;
|
|
114
|
+
font-size: 0.72rem;
|
|
115
|
+
color: var(--text-muted);
|
|
116
|
+
padding-top: 0.2rem;
|
|
117
|
+
padding-bottom: 0.2rem;
|
|
58
118
|
}
|
|
59
|
-
.
|
|
60
|
-
.
|
|
61
|
-
.phase-line { flex: 1; height: 2px; background: var(--border); }
|
|
62
|
-
.phase-line.completed { background: var(--success); }
|
|
119
|
+
.nav-resource-link:hover { background: transparent; color: var(--text-muted); }
|
|
120
|
+
.nav-resources { margin-left: 0.5rem; }
|
|
@@ -388,3 +388,67 @@
|
|
|
388
388
|
padding-left: 0.75rem; border-left: 2px solid var(--accent);
|
|
389
389
|
margin-bottom: 0.2rem;
|
|
390
390
|
}
|
|
391
|
+
|
|
392
|
+
/* ============================================
|
|
393
|
+
STRUCTURE TAB (Sections/Resources)
|
|
394
|
+
============================================ */
|
|
395
|
+
.struct-section {
|
|
396
|
+
background: var(--bg-card);
|
|
397
|
+
border: 1px solid var(--border);
|
|
398
|
+
border-radius: 10px;
|
|
399
|
+
margin-bottom: 1rem;
|
|
400
|
+
overflow: hidden;
|
|
401
|
+
}
|
|
402
|
+
.struct-section-header {
|
|
403
|
+
display: flex;
|
|
404
|
+
align-items: center;
|
|
405
|
+
gap: 0.75rem;
|
|
406
|
+
padding: 0.75rem 1rem;
|
|
407
|
+
background: var(--bg-hover);
|
|
408
|
+
border-bottom: 1px solid var(--border);
|
|
409
|
+
}
|
|
410
|
+
.struct-section-code {
|
|
411
|
+
font-weight: 600;
|
|
412
|
+
color: var(--text-bright);
|
|
413
|
+
font-size: 0.95rem;
|
|
414
|
+
}
|
|
415
|
+
.struct-section-desc {
|
|
416
|
+
flex: 1;
|
|
417
|
+
font-size: 0.8rem;
|
|
418
|
+
color: var(--text-muted);
|
|
419
|
+
}
|
|
420
|
+
.struct-section-badge {
|
|
421
|
+
font-size: 0.65rem;
|
|
422
|
+
color: var(--text-muted);
|
|
423
|
+
background: rgba(99,102,241,0.1);
|
|
424
|
+
padding: 0.1rem 0.5rem;
|
|
425
|
+
border-radius: 4px;
|
|
426
|
+
white-space: nowrap;
|
|
427
|
+
}
|
|
428
|
+
.struct-resources {
|
|
429
|
+
padding: 0.5rem 0;
|
|
430
|
+
}
|
|
431
|
+
.struct-resource {
|
|
432
|
+
display: flex;
|
|
433
|
+
align-items: baseline;
|
|
434
|
+
gap: 0.5rem;
|
|
435
|
+
padding: 0.35rem 1rem 0.35rem 1.5rem;
|
|
436
|
+
font-size: 0.85rem;
|
|
437
|
+
transition: background var(--transition-fast);
|
|
438
|
+
}
|
|
439
|
+
.struct-resource:hover {
|
|
440
|
+
background: var(--bg-hover);
|
|
441
|
+
}
|
|
442
|
+
.struct-resource-icon {
|
|
443
|
+
color: var(--primary-light);
|
|
444
|
+
font-size: 0.7rem;
|
|
445
|
+
flex-shrink: 0;
|
|
446
|
+
}
|
|
447
|
+
.struct-resource-name {
|
|
448
|
+
font-weight: 500;
|
|
449
|
+
color: var(--text-bright);
|
|
450
|
+
}
|
|
451
|
+
.struct-resource-desc {
|
|
452
|
+
font-size: 0.8rem;
|
|
453
|
+
color: var(--text-muted);
|
|
454
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
<span class="header-app-name" id="appName">{{APPLICATION_NAME}}</span>
|
|
21
21
|
<div class="header-spacer"></div>
|
|
22
22
|
<div class="header-actions">
|
|
23
|
+
<button class="btn btn-sm" onclick="resetToEmbedded()" title="Reinitialiser depuis les donnees d'origine (supprime les modifications locales)">Reset</button>
|
|
23
24
|
<button class="btn btn-sm" onclick="saveToLocalStorage()" title="Sauvegarder les modifications dans le navigateur">Sauvegarder</button>
|
|
24
25
|
<button class="btn btn-sm btn-review" onclick="saveReviewJSON()" title="Sauvegarder les corrections pour creer une nouvelle version">Sauvegarder corrections</button>
|
|
25
26
|
<button class="btn btn-sm btn-primary" onclick="exportJSON()" title="Exporter les donnees au format JSON pour l'extraction">Exporter JSON</button>
|
|
@@ -32,85 +33,16 @@
|
|
|
32
33
|
|
|
33
34
|
<div class="body" id="appBody">
|
|
34
35
|
<!-- ============================================
|
|
35
|
-
SIDEBAR - Navigation
|
|
36
|
+
SIDEBAR - Navigation hierarchique
|
|
36
37
|
============================================ -->
|
|
37
38
|
<aside class="sidebar">
|
|
38
|
-
<!--
|
|
39
|
-
<div class="
|
|
40
|
-
<
|
|
41
|
-
<div class="phase-line" id="pline-1"></div>
|
|
42
|
-
<div class="phase-dot" id="phase-2" title="Decomposition">2</div>
|
|
43
|
-
<div class="phase-line" id="pline-2"></div>
|
|
44
|
-
<div class="phase-dot" id="phase-3" title="Specification">3</div>
|
|
45
|
-
<div class="phase-line" id="pline-3"></div>
|
|
46
|
-
<div class="phase-dot" id="phase-4" title="Consolidation">4</div>
|
|
47
|
-
<div class="phase-line" id="pline-4"></div>
|
|
48
|
-
<div class="phase-dot" id="phase-5" title="Synthese">5</div>
|
|
39
|
+
<!-- Application Name -->
|
|
40
|
+
<div class="sidebar-header">
|
|
41
|
+
<span class="sidebar-app-name" id="sidebarAppName">{{APPLICATION_NAME}}</span>
|
|
49
42
|
</div>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<div class="nav-group-title">1. Cadrage</div>
|
|
54
|
-
<a class="nav-item active" onclick="showSection('cadrage-context')" data-section="cadrage-context">
|
|
55
|
-
<span class="nav-icon">●</span> Contexte
|
|
56
|
-
</a>
|
|
57
|
-
<a class="nav-item" onclick="showSection('cadrage-stakeholders')" data-section="cadrage-stakeholders">
|
|
58
|
-
<span class="nav-icon">●</span> Parties prenantes
|
|
59
|
-
<span class="nav-badge" id="stakeholderCount">0</span>
|
|
60
|
-
</a>
|
|
61
|
-
<a class="nav-item" onclick="showSection('cadrage-scope')" data-section="cadrage-scope">
|
|
62
|
-
<span class="nav-icon">●</span> Perimetre fonctionnel
|
|
63
|
-
</a>
|
|
64
|
-
<a class="nav-item" onclick="showSection('cadrage-risks')" data-section="cadrage-risks">
|
|
65
|
-
<span class="nav-icon">●</span> Risques et hypotheses
|
|
66
|
-
</a>
|
|
67
|
-
<a class="nav-item" onclick="showSection('cadrage-success')" data-section="cadrage-success">
|
|
68
|
-
<span class="nav-icon">●</span> Criteres de reussite
|
|
69
|
-
</a>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<!-- Phase 2 : Decomposition -->
|
|
73
|
-
<div class="nav-group">
|
|
74
|
-
<div class="nav-group-title">2. Decomposition</div>
|
|
75
|
-
<a class="nav-item" onclick="showSection('decomp-modules')" data-section="decomp-modules">
|
|
76
|
-
<span class="nav-icon">●</span> Domaines fonctionnels
|
|
77
|
-
<span class="nav-badge" id="moduleCount">0</span>
|
|
78
|
-
</a>
|
|
79
|
-
<a class="nav-item" onclick="showSection('decomp-dependencies')" data-section="decomp-dependencies">
|
|
80
|
-
<span class="nav-icon">●</span> Dependances
|
|
81
|
-
</a>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
<!-- Phase 3 : Specification par module -->
|
|
85
|
-
<div class="nav-group" id="modulesNav">
|
|
86
|
-
<div class="nav-group-title">3. Specification</div>
|
|
87
|
-
<!-- Populated dynamically per module -->
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
<!-- Phase 4 : Consolidation -->
|
|
91
|
-
<div class="nav-group">
|
|
92
|
-
<div class="nav-group-title">4. Consolidation</div>
|
|
93
|
-
<a class="nav-item" onclick="showSection('consol-datamodel')" data-section="consol-datamodel">
|
|
94
|
-
<span class="nav-icon">●</span> Modele de donnees
|
|
95
|
-
<span class="nav-badge" id="entityCount">0</span>
|
|
96
|
-
</a>
|
|
97
|
-
<a class="nav-item" onclick="showSection('consol-interactions')" data-section="consol-interactions">
|
|
98
|
-
<span class="nav-icon">●</span> Interactions
|
|
99
|
-
</a>
|
|
100
|
-
<a class="nav-item" onclick="showSection('consol-permissions')" data-section="consol-permissions">
|
|
101
|
-
<span class="nav-icon">●</span> Coherence des acces
|
|
102
|
-
</a>
|
|
103
|
-
<a class="nav-item" onclick="showSection('consol-flows')" data-section="consol-flows">
|
|
104
|
-
<span class="nav-icon">●</span> Parcours bout en bout
|
|
105
|
-
</a>
|
|
106
|
-
</div>
|
|
107
|
-
|
|
108
|
-
<!-- Phase 5 : Synthese -->
|
|
109
|
-
<div class="nav-group">
|
|
110
|
-
<div class="nav-group-title">5. Synthese</div>
|
|
111
|
-
<a class="nav-item" onclick="showSection('handoff-summary')" data-section="handoff-summary">
|
|
112
|
-
<span class="nav-icon">●</span> Vue d'ensemble
|
|
113
|
-
</a>
|
|
43
|
+
<!-- Dynamic Tree Navigation -->
|
|
44
|
+
<div id="sidebarNav">
|
|
45
|
+
<!-- Populated by buildNavTree() -->
|
|
114
46
|
</div>
|
|
115
47
|
</aside>
|
|
116
48
|
|
|
@@ -26,14 +26,15 @@ const FEATURE_DATA = {
|
|
|
26
26
|
scope: {
|
|
27
27
|
// CONVERT feature.json keys to HTML keys:
|
|
28
28
|
// mustHave → vital, shouldHave → important, couldHave → optional, outOfScope → excluded
|
|
29
|
+
// CRITICAL: Preserve per-item `module` assignment from coverageMatrix (NOT modules[0])
|
|
29
30
|
vital: (master.cadrage.globalScope?.mustHave || master.cadrage.coverageMatrix?.filter(i => i.category === "mustHave") || [])
|
|
30
|
-
.map(item => typeof item === 'string' ? { name: item, description: "" } : { name: item.item || item, description: item.notes || "" }),
|
|
31
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
31
32
|
important: (master.cadrage.globalScope?.shouldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "shouldHave") || [])
|
|
32
|
-
.map(item => typeof item === 'string' ? { name: item, description: "" } : { name: item.item || item, description: item.notes || "" }),
|
|
33
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
33
34
|
optional: (master.cadrage.globalScope?.couldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "couldHave") || [])
|
|
34
|
-
.map(item => typeof item === 'string' ? { name: item, description: "" } : { name: item.item || item, description: item.notes || "" }),
|
|
35
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
35
36
|
excluded: (master.cadrage.globalScope?.outOfScope || master.cadrage.coverageMatrix?.filter(i => i.category === "outOfScope") || [])
|
|
36
|
-
.map(item => typeof item === 'string' ? { name: item, description: "" } : { name: item.item || item, description: item.notes || "" })
|
|
37
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null })
|
|
37
38
|
},
|
|
38
39
|
risks: (master.cadrage.risks || []).map(r => ({
|
|
39
40
|
description: r.description,
|
|
@@ -123,8 +124,9 @@ const FEATURE_DATA = {
|
|
|
123
124
|
const EMBEDDED_ARTIFACTS = {
|
|
124
125
|
wireframes: {
|
|
125
126
|
// PER-MODULE keyed object (NOT a flat array)
|
|
126
|
-
// FOR EACH module: extract from specification.uiWireframes[]
|
|
127
|
-
|
|
127
|
+
// FOR EACH module: extract from specification.uiWireframes[] OR specification.wireframes[] (SAFETY NET)
|
|
128
|
+
// IMPORTANT: The agent may write wireframes under either key name — always check BOTH
|
|
129
|
+
[moduleCode]: (moduleFeature.specification.uiWireframes || moduleFeature.specification.wireframes || []).map(wf => ({
|
|
128
130
|
screen: wf.screen || wf.name || wf.id || "", // SAFETY NET: fallback name/id → screen
|
|
129
131
|
section: wf.section || "", // e.g. "list"
|
|
130
132
|
format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
|
|
@@ -161,7 +163,7 @@ const EMBEDDED_ARTIFACTS = {
|
|
|
161
163
|
|
|
162
164
|
### Artifact Gathering
|
|
163
165
|
|
|
164
|
-
1. For EACH module: read `specification.uiWireframes[]
|
|
166
|
+
1. For EACH module: read `specification.uiWireframes[]` OR `specification.wireframes[]` (check BOTH keys — agent may use either), **rename fields** (`mockupFormat`→`format`, `mockup`→`content`), store under `wireframes[moduleCode]`
|
|
165
167
|
2. Read master's `consolidation.e2eFlows[]` and build e2eFlows array with diagram generation
|
|
166
168
|
3. Read master's `dependencyGraph` and build nodes/edges
|
|
167
169
|
4. Serialize as JSON with 2-space indentation
|
|
@@ -20,25 +20,17 @@ Build a JSON object following this **exact mapping** from feature.json to the HT
|
|
|
20
20
|
analysisMode: master.metadata.analysisMode || "interactive" // always "interactive"
|
|
21
21
|
},
|
|
22
22
|
cadrage: {
|
|
23
|
-
problem
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.flatMap(s => s.painPoints || []).join("\n"), // aggregate all painPoints
|
|
35
|
-
errors: ""
|
|
36
|
-
},
|
|
37
|
-
vision: {
|
|
38
|
-
changes: master.cadrage.toBe, // string → vision.changes
|
|
39
|
-
results: master.cadrage.acceptanceCriteria
|
|
40
|
-
.map(ac => ac.criterion).join("\n"), // AC → results (one per line)
|
|
41
|
-
successSign: ""
|
|
23
|
+
// CONTEXT SECTION — lean format (merged from problem/asIs/toBe)
|
|
24
|
+
// NOTE: 01-data-init.js has backward compat for old problem/current/vision format
|
|
25
|
+
context: {
|
|
26
|
+
problem: master.cadrage.problem || "", // flat string from feature.json
|
|
27
|
+
trigger: master.cadrage.trigger || "", // flat string from feature.json
|
|
28
|
+
currentSituation: master.cadrage.asIs || "", // flat string from feature.json
|
|
29
|
+
desiredSituation: master.cadrage.toBe || "", // flat string from feature.json
|
|
30
|
+
painPoints: (master.cadrage.stakeholders || [])
|
|
31
|
+
.flatMap(s => s.painPoints || []).join("\n"), // aggregate all painPoints
|
|
32
|
+
acceptanceCriteria: (master.cadrage.acceptanceCriteria || [])
|
|
33
|
+
.map(ac => ac.criterion).join("\n") // AC → newline-separated string
|
|
42
34
|
},
|
|
43
35
|
stakeholders: master.cadrage.stakeholders.map(s => ({
|
|
44
36
|
role: s.role,
|
|
@@ -64,22 +56,22 @@ Build a JSON object following this **exact mapping** from feature.json to the HT
|
|
|
64
56
|
impact: r.impact,
|
|
65
57
|
mitigation: r.mitigation || ""
|
|
66
58
|
})),
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
metrics: "",
|
|
72
|
-
timeline: "",
|
|
73
|
-
minimumConditions: ""
|
|
74
|
-
}
|
|
59
|
+
criteria: (master.cadrage.acceptanceCriteria || []).map(ac => ({
|
|
60
|
+
text: ac.criterion,
|
|
61
|
+
validated: ac.validated || false
|
|
62
|
+
}))
|
|
75
63
|
},
|
|
76
64
|
modules: master.modules.map(m => ({
|
|
77
65
|
code: m.code,
|
|
78
|
-
name: m.code,
|
|
66
|
+
name: m.name || m.code, // display name (MANDATORY, separate from code)
|
|
79
67
|
description: m.description || "",
|
|
80
68
|
featureType: m.featureType || "data-centric",
|
|
81
69
|
priority: m.priority || "must",
|
|
82
70
|
entities: m.entities || [],
|
|
71
|
+
anticipatedSections: m.anticipatedSections || [], // [{code, description, resources[]}]
|
|
72
|
+
dependencies: m.dependencies || [],
|
|
73
|
+
dependents: m.dependents || [],
|
|
74
|
+
estimatedComplexity: m.estimatedComplexity || "medium",
|
|
83
75
|
status: m.status || "handed-off"
|
|
84
76
|
})),
|
|
85
77
|
dependencies: (master.dependencyGraph?.edges || []).map(e => ({
|
|
@@ -44,7 +44,8 @@ Build EMBEDDED_ARTIFACTS with wireframes for completed modules only:
|
|
|
44
44
|
const EMBEDDED_ARTIFACTS = {
|
|
45
45
|
wireframes: {
|
|
46
46
|
// FOR EACH completed module: extract wireframes with RENAMED fields
|
|
47
|
-
|
|
47
|
+
// SAFETY NET: check BOTH key names (agent may use either)
|
|
48
|
+
[moduleCode]: (moduleFeature.specification.uiWireframes || moduleFeature.specification.wireframes || []).map(wf => ({
|
|
48
49
|
screen: wf.screen,
|
|
49
50
|
section: wf.section,
|
|
50
51
|
format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
|
|
@@ -293,10 +293,12 @@ Create: docs/business/{app}/{module_code}/business-analyse/v1.0/
|
|
|
293
293
|
|
|
294
294
|
> Module feature.json files will be created by step-03 when each module is processed.
|
|
295
295
|
|
|
296
|
-
### 9. Display Summary
|
|
296
|
+
### 9. Display Summary & AUTOCHAIN
|
|
297
297
|
|
|
298
298
|
```
|
|
299
|
-
|
|
299
|
+
═══════════════════════════════════════════════════════════
|
|
300
|
+
DECOMPOSITION COMPLETE - {feature_id}
|
|
301
|
+
═══════════════════════════════════════════════════════════
|
|
300
302
|
|
|
301
303
|
| Aspect | Value |
|
|
302
304
|
|--------|-------|
|
|
@@ -309,8 +311,16 @@ Create: docs/business/{app}/{module_code}/business-analyse/v1.0/
|
|
|
309
311
|
{numbered list of modules}
|
|
310
312
|
|
|
311
313
|
→ Starting iterative specification with {first_module}...
|
|
314
|
+
═══════════════════════════════════════════════════════════
|
|
312
315
|
```
|
|
313
316
|
|
|
317
|
+
**AUTOCHAIN — DO NOT STOP HERE:**
|
|
318
|
+
- Do NOT ask "shall I continue?" or "voulez-vous que je continue?"
|
|
319
|
+
- Do NOT summarize what's coming next
|
|
320
|
+
- Do NOT wait for user input
|
|
321
|
+
- The user ALREADY validated at step 6 — that was the checkpoint
|
|
322
|
+
- IMMEDIATELY load step-03a1-setup.md
|
|
323
|
+
|
|
314
324
|
---
|
|
315
325
|
|
|
316
326
|
## SINGLE-MODULE MODE
|
|
@@ -325,6 +335,9 @@ When `workflow.mode = "module"` or only 1 scope item identified:
|
|
|
325
335
|
|
|
326
336
|
---
|
|
327
337
|
|
|
328
|
-
## NEXT STEP
|
|
338
|
+
## NEXT STEP (MANDATORY — NO PAUSE)
|
|
329
339
|
|
|
330
340
|
Load: `./step-03a1-setup.md`
|
|
341
|
+
|
|
342
|
+
> **FORBIDDEN:** Asking any question between decomposition summary and step-03 load.
|
|
343
|
+
> The client checkpoint was at step 6. Do NOT add another one.
|
|
@@ -48,6 +48,45 @@ Compile all data collected in step-03a (data) and step-03b (UI) into the module
|
|
|
48
48
|
|
|
49
49
|
Generate the complete specification for this module. **Each subsection below includes a STRUCTURE CARD showing the EXACT JSON format. Follow them precisely.**
|
|
50
50
|
|
|
51
|
+
#### ENTITY ATTRIBUTE SCHEMA (MANDATORY — applies to ALL entities in section 6b of step-03a)
|
|
52
|
+
|
|
53
|
+
> **CRITICAL:** Entity attributes MUST use STRUCTURED properties, not free-text validation strings.
|
|
54
|
+
> The ralph-loop needs parseable types to generate correct C# code.
|
|
55
|
+
|
|
56
|
+
> **STRUCTURE CARD: analysis.entities[].attributes[]**
|
|
57
|
+
> ```json
|
|
58
|
+
> {
|
|
59
|
+
> "name": "occupancyRate",
|
|
60
|
+
> "description": "Employee occupancy percentage",
|
|
61
|
+
> "type": "decimal",
|
|
62
|
+
> "maxLength": null,
|
|
63
|
+
> "nullable": true,
|
|
64
|
+
> "required": false,
|
|
65
|
+
> "unique": false,
|
|
66
|
+
> "indexed": false,
|
|
67
|
+
> "defaultValue": "100",
|
|
68
|
+
> "validation": "min:0, max:100, step:0.01",
|
|
69
|
+
> "foreignKey": null
|
|
70
|
+
> }
|
|
71
|
+
> ```
|
|
72
|
+
> **MANDATORY fields:** `name`, `type`
|
|
73
|
+
> **type values:** `string`, `int`, `long`, `decimal`, `double`, `bool`, `DateTime`, `DateOnly`, `TimeOnly`, `Guid`, `enum:{EnumName}`, `byte[]`
|
|
74
|
+
> **For FK attributes:**
|
|
75
|
+
> ```json
|
|
76
|
+
> {
|
|
77
|
+
> "name": "departmentId",
|
|
78
|
+
> "description": "FK to Department",
|
|
79
|
+
> "type": "Guid",
|
|
80
|
+
> "required": true,
|
|
81
|
+
> "foreignKey": { "targetEntity": "Department", "targetField": "Id", "onDelete": "restrict" }
|
|
82
|
+
> }
|
|
83
|
+
> ```
|
|
84
|
+
> **FORBIDDEN:** Free-text-only validation like `"FK vers Employee"` or `"Max 100 caractères"` without corresponding structured properties.
|
|
85
|
+
>
|
|
86
|
+
> **BaseEntity inheritance:** All entities inherit `tenantId`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` from SmartStack.BaseEntity. Do NOT redeclare these. Document this once at the top of the entities section.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
51
90
|
#### 8a. Actors
|
|
52
91
|
|
|
53
92
|
Inherited from application roles → mapped to module permissions.
|
|
@@ -234,7 +273,7 @@ const navigationResources = specification.sections.flatMap(section =>
|
|
|
234
273
|
);
|
|
235
274
|
```
|
|
236
275
|
|
|
237
|
-
**Write to
|
|
276
|
+
**Write seedDataCore to specification:**
|
|
238
277
|
|
|
239
278
|
```
|
|
240
279
|
ba-writer.enrichSection({
|
|
@@ -254,6 +293,9 @@ ba-writer.enrichSection({
|
|
|
254
293
|
})
|
|
255
294
|
```
|
|
256
295
|
|
|
296
|
+
> **NOTE:** This step writes ONLY seedDataCore. The FULL specification write (actors, useCases, wireframes, sections, etc.) happens in step-03d section 11.
|
|
297
|
+
> ALL data from 8a-8l MUST be carried forward to step-03d. Do NOT discard in-memory data.
|
|
298
|
+
|
|
257
299
|
**Validation:**
|
|
258
300
|
|
|
259
301
|
- EVERY section in `specification.sections[]` MUST appear in `navigationSections`
|
|
@@ -280,8 +322,9 @@ BDD acceptance tests per UC.
|
|
|
280
322
|
> ]
|
|
281
323
|
> }
|
|
282
324
|
> ```
|
|
283
|
-
> **STRUCTURE:**
|
|
325
|
+
> **STRUCTURE:** MUST be an ARRAY of objects (NOT a single object). Each object has `feature` string + `scenarios[]` array. Each scenario has `given`, `when`, `then` as ARRAYS of strings.
|
|
284
326
|
> **FORBIDDEN:** Do NOT use flat arrays of `{uc, scenario, given, when, then}` where given/when/then are single strings.
|
|
327
|
+
> **FORBIDDEN:** Do NOT use a single object `{feature, scenarios}` — MUST be an ARRAY `[{feature, scenarios}]` even with one feature.
|
|
285
328
|
|
|
286
329
|
#### 8h. Validations
|
|
287
330
|
|
|
@@ -405,6 +448,16 @@ Before loading step-03d-validate, verify all 12 subsections (8a-8l) are populate
|
|
|
405
448
|
|
|
406
449
|
**IF any subsection is missing → STOP and request the missing data before proceeding.**
|
|
407
450
|
|
|
451
|
+
**SCHEMA UNIFORMITY CHECK (multi-module mode):**
|
|
452
|
+
IF this is NOT the first module in moduleOrder:
|
|
453
|
+
Compare THIS module's specification structure against the FIRST specified module:
|
|
454
|
+
- `gherkinScenarios` MUST be array (not object) in ALL modules
|
|
455
|
+
- `validations[].rules` MUST be array (not singular `rule`) in ALL modules
|
|
456
|
+
- `messages[]` MUST have `message` field in ALL modules
|
|
457
|
+
- `specification.apiEndpoints[]` MUST be present in ALL modules
|
|
458
|
+
- `specification.i18nKeys` MUST be present in ALL modules
|
|
459
|
+
IF any structural divergence detected → AUTO-FIX to match the canonical format before proceeding.
|
|
460
|
+
|
|
408
461
|
---
|
|
409
462
|
|
|
410
463
|
## NEXT STEP
|