@atlashub/smartstack-cli 4.23.0 → 4.25.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/package.json +1 -1
- package/templates/skills/ba-generate-html/html/ba-interactive.html +950 -1055
- package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +1 -2
- package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +0 -39
- package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +133 -135
- package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +199 -199
- package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +165 -166
- package/templates/skills/ba-generate-html/html/src/styles/05-modules.css +444 -454
- package/templates/skills/ba-generate-html/html/src/template.html +0 -49
- package/templates/skills/ba-generate-html/references/data-build.md +176 -182
- package/templates/skills/ba-generate-html/references/data-mapping.md +295 -301
- package/templates/skills/ba-generate-html/steps/step-01-collect.md +1 -1
- package/templates/skills/ba-generate-html/steps/step-02-build-data.md +0 -9
- package/templates/skills/derive-prd/SKILL.md +9 -9
- package/templates/skills/derive-prd/references/acceptance-criteria.md +166 -116
- package/templates/skills/derive-prd/references/entity-domain-mapping.md +5 -5
- package/templates/skills/derive-prd/references/handoff-file-templates.md +12 -12
- package/templates/skills/derive-prd/references/handoff-mappings.md +13 -14
- package/templates/skills/derive-prd/references/handoff-seeddata-generation.md +1 -1
- package/templates/skills/derive-prd/references/readiness-scoring.md +41 -50
- package/templates/skills/derive-prd/schemas/handoff-schema.json +2 -2
- package/templates/skills/derive-prd/steps/step-00-validate.md +73 -52
- package/templates/skills/derive-prd/steps/step-01-transform.md +86 -43
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-risks.html +0 -48
|
@@ -15,7 +15,6 @@ data.specComments = data.specComments || {};
|
|
|
15
15
|
data.customRoles = data.customRoles || [];
|
|
16
16
|
data.customActions = data.customActions || [];
|
|
17
17
|
data.cadrage.criteria = data.cadrage.criteria || [];
|
|
18
|
-
data.cadrage.risks = data.cadrage.risks || [];
|
|
19
18
|
data.consolidation = data.consolidation || {};
|
|
20
19
|
data.consolidation.e2eFlows = data.consolidation.e2eFlows || [];
|
|
21
20
|
|
|
@@ -151,7 +150,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
151
150
|
}
|
|
152
151
|
renderStakeholders();
|
|
153
152
|
renderScope();
|
|
154
|
-
renderRisks();
|
|
155
153
|
renderCriteria();
|
|
156
154
|
renderModules();
|
|
157
155
|
renderDependencies();
|
|
@@ -163,4 +161,5 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
163
161
|
updateDepSelects();
|
|
164
162
|
initInlineComments();
|
|
165
163
|
renderReviewPanel();
|
|
164
|
+
showSection(currentSectionId);
|
|
166
165
|
});
|
|
@@ -113,7 +113,6 @@ function buildCadrageItems() {
|
|
|
113
113
|
return renderNavItem('cadrage-context', 'Contexte') +
|
|
114
114
|
renderNavItem('cadrage-stakeholders', 'Parties prenantes', data.cadrage.stakeholders.length) +
|
|
115
115
|
renderNavItem('cadrage-scope', 'Perimetre fonctionnel') +
|
|
116
|
-
(isVibeCoding ? '' : renderNavItem('cadrage-risks', 'Risques et hypotheses', data.cadrage.risks.length)) +
|
|
117
116
|
renderNavItem('cadrage-success', 'Criteres de reussite');
|
|
118
117
|
}
|
|
119
118
|
|
|
@@ -144,45 +144,6 @@ function renderCriteria() {
|
|
|
144
144
|
`).join('');
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
/* ============================================
|
|
148
|
-
RISKS
|
|
149
|
-
============================================ */
|
|
150
|
-
function addRisk() {
|
|
151
|
-
const desc = document.getElementById('risk-desc').value.trim();
|
|
152
|
-
if (!desc) return;
|
|
153
|
-
|
|
154
|
-
data.cadrage.risks.push({
|
|
155
|
-
description: desc,
|
|
156
|
-
probability: document.getElementById('risk-probability').value,
|
|
157
|
-
impact: document.getElementById('risk-impact').value,
|
|
158
|
-
mitigation: document.getElementById('risk-mitigation').value.trim()
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
renderRisks();
|
|
162
|
-
toggleForm('addRiskForm');
|
|
163
|
-
clearForm('addRiskForm');
|
|
164
|
-
autoSave();
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function renderRisks() {
|
|
168
|
-
const list = document.getElementById('risksList');
|
|
169
|
-
list.innerHTML = data.cadrage.risks.map((r, i) => {
|
|
170
|
-
const level = (r.probability === 'high' && r.impact === 'high') ? 'critical'
|
|
171
|
-
: (r.probability === 'low' && r.impact === 'low') ? 'low' : 'medium';
|
|
172
|
-
return `
|
|
173
|
-
<div class="risk-item">
|
|
174
|
-
<div class="risk-level risk-${level}"></div>
|
|
175
|
-
<div>
|
|
176
|
-
<div class="risk-text">${r.description}</div>
|
|
177
|
-
${r.mitigation ? '<div style="font-size:0.75rem;color:var(--text-muted);margin-top:0.25rem;">Prevention : ' + r.mitigation + '</div>' : ''}
|
|
178
|
-
</div>
|
|
179
|
-
<div class="risk-probability">${formatLevel(r.probability)}</div>
|
|
180
|
-
<div class="risk-impact">${formatLevel(r.impact)}</div>
|
|
181
|
-
</div>
|
|
182
|
-
`;
|
|
183
|
-
}).join('');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
147
|
/* ============================================
|
|
187
148
|
CONTEXT RENDERING (merged problem/current/vision)
|
|
188
149
|
============================================ */
|
|
@@ -24,7 +24,6 @@ function renderHandoffStats() {
|
|
|
24
24
|
<div class="stat-card"><div class="stat-value">${totalStakeholders}</div><div class="stat-label">Profils utilisateurs</div></div>
|
|
25
25
|
<div class="stat-card"><div class="stat-value">${data.dependencies.length}</div><div class="stat-label">Dependances</div></div>
|
|
26
26
|
<div class="stat-card"><div class="stat-value">${data.consolidation.e2eFlows.length}</div><div class="stat-label">Parcours bout en bout</div></div>
|
|
27
|
-
${isVibeCoding ? '' : `<div class="stat-card"><div class="stat-value">${data.cadrage.risks.length}</div><div class="stat-label">Risques identifies</div></div>`}
|
|
28
27
|
`;
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -1,135 +1,133 @@
|
|
|
1
|
-
/* ============================================
|
|
2
|
-
PERSISTENCE
|
|
3
|
-
============================================ */
|
|
4
|
-
function autoSave() {
|
|
5
|
-
data.metadata.lastModified = new Date().toISOString();
|
|
6
|
-
localStorage.setItem(APP_KEY, JSON.stringify(data));
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function saveToLocalStorage() {
|
|
10
|
-
autoSave();
|
|
11
|
-
showNotification('Modifications sauvegardees');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function resetToEmbedded() {
|
|
15
|
-
if (!confirm('Reinitialiser toutes les donnees depuis la version d\'origine ? Vos modifications locales (commentaires, notes) seront perdues.')) return;
|
|
16
|
-
localStorage.removeItem(APP_KEY);
|
|
17
|
-
// Restore data from ORIGINAL_DATA
|
|
18
|
-
Object.keys(data).forEach(k => delete data[k]);
|
|
19
|
-
Object.assign(data, JSON.parse(JSON.stringify(ORIGINAL_DATA)));
|
|
20
|
-
// Re-render everything
|
|
21
|
-
initEditableFields();
|
|
22
|
-
renderStakeholders();
|
|
23
|
-
renderScope();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
+ '|' +
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
data.
|
|
62
|
-
data.
|
|
63
|
-
data.
|
|
64
|
-
data.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// Preserve user
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
data.
|
|
119
|
-
data.
|
|
120
|
-
data.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
} catch (e) { console.error('Error loading saved data:', e); }
|
|
135
|
-
}
|
|
1
|
+
/* ============================================
|
|
2
|
+
PERSISTENCE
|
|
3
|
+
============================================ */
|
|
4
|
+
function autoSave() {
|
|
5
|
+
data.metadata.lastModified = new Date().toISOString();
|
|
6
|
+
localStorage.setItem(APP_KEY, JSON.stringify(data));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function saveToLocalStorage() {
|
|
10
|
+
autoSave();
|
|
11
|
+
showNotification('Modifications sauvegardees');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function resetToEmbedded() {
|
|
15
|
+
if (!confirm('Reinitialiser toutes les donnees depuis la version d\'origine ? Vos modifications locales (commentaires, notes) seront perdues.')) return;
|
|
16
|
+
localStorage.removeItem(APP_KEY);
|
|
17
|
+
// Restore data from ORIGINAL_DATA
|
|
18
|
+
Object.keys(data).forEach(k => delete data[k]);
|
|
19
|
+
Object.assign(data, JSON.parse(JSON.stringify(ORIGINAL_DATA)));
|
|
20
|
+
// Re-render everything
|
|
21
|
+
initEditableFields();
|
|
22
|
+
renderStakeholders();
|
|
23
|
+
renderScope();
|
|
24
|
+
renderCriteria();
|
|
25
|
+
renderModules();
|
|
26
|
+
renderDependencies();
|
|
27
|
+
renderAllModuleSpecs();
|
|
28
|
+
renderConsolidation();
|
|
29
|
+
renderHandoff();
|
|
30
|
+
renderE2EFlows();
|
|
31
|
+
updateCounts();
|
|
32
|
+
renderReviewPanel();
|
|
33
|
+
showNotification('Donnees reinitialisees depuis la version d\'origine');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function loadFromLocalStorage() {
|
|
37
|
+
const saved = localStorage.getItem(APP_KEY);
|
|
38
|
+
if (!saved) return;
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(saved);
|
|
42
|
+
|
|
43
|
+
// Build fingerprint of embedded structural data to detect HTML regeneration
|
|
44
|
+
const embeddedFingerprint = ORIGINAL_DATA.modules.map(m => m.code).sort().join(',')
|
|
45
|
+
+ '|' + (ORIGINAL_DATA.metadata?.createdAt || '')
|
|
46
|
+
+ '|' + ORIGINAL_DATA.modules.length;
|
|
47
|
+
const cachedFingerprint = parsed._structureFingerprint || '';
|
|
48
|
+
|
|
49
|
+
const structureChanged = embeddedFingerprint !== cachedFingerprint;
|
|
50
|
+
const embeddedModuleCount = ORIGINAL_DATA.modules?.length || 0;
|
|
51
|
+
const cachedModuleCount = (parsed.modules || []).length;
|
|
52
|
+
const hasNewModules = embeddedModuleCount > cachedModuleCount;
|
|
53
|
+
const embeddedModuleCodes = new Set(ORIGINAL_DATA.modules.map(m => m.code));
|
|
54
|
+
const cachedModuleCodes = new Set((parsed.modules || []).map(m => m.code));
|
|
55
|
+
const missingModules = [...embeddedModuleCodes].filter(c => !cachedModuleCodes.has(c));
|
|
56
|
+
|
|
57
|
+
if (structureChanged || hasNewModules || missingModules.length > 0) {
|
|
58
|
+
// HTML was regenerated or has new modules — keep embedded structural data
|
|
59
|
+
// Only restore user-specific edits (comments, custom roles, notes)
|
|
60
|
+
data.wireframeComments = parsed.wireframeComments || {};
|
|
61
|
+
data.specComments = parsed.specComments || {};
|
|
62
|
+
data.customRoles = parsed.customRoles || [];
|
|
63
|
+
data.customActions = parsed.customActions || [];
|
|
64
|
+
data.comments = parsed.comments || [];
|
|
65
|
+
|
|
66
|
+
// Merge user-added notes per module (preserve existing module notes)
|
|
67
|
+
for (const code of Object.keys(parsed.moduleSpecs || {})) {
|
|
68
|
+
if (data.moduleSpecs[code] && parsed.moduleSpecs[code]?.notes) {
|
|
69
|
+
data.moduleSpecs[code].notes = parsed.moduleSpecs[code].notes;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Save fresh embedded data with fingerprint
|
|
74
|
+
data._structureFingerprint = embeddedFingerprint;
|
|
75
|
+
autoSave();
|
|
76
|
+
} else {
|
|
77
|
+
// Cache matches current structure — safe to restore user edits on cadrage/notes
|
|
78
|
+
// IMPORTANT: Always keep embedded modules and moduleSpecs as structural source of truth
|
|
79
|
+
// Only merge cadrage user-editable fields and notes
|
|
80
|
+
if (parsed.cadrage) {
|
|
81
|
+
// Merge cadrage context (user may have edited text fields)
|
|
82
|
+
if (parsed.cadrage.context) {
|
|
83
|
+
data.cadrage.context = { ...data.cadrage.context, ...parsed.cadrage.context };
|
|
84
|
+
}
|
|
85
|
+
// Merge scope only if user added items interactively
|
|
86
|
+
if (parsed.cadrage.scope) {
|
|
87
|
+
data.cadrage.scope = { ...data.cadrage.scope, ...parsed.cadrage.scope };
|
|
88
|
+
}
|
|
89
|
+
// Merge stakeholders if user edited them
|
|
90
|
+
if (parsed.cadrage.stakeholders) data.cadrage.stakeholders = parsed.cadrage.stakeholders;
|
|
91
|
+
}
|
|
92
|
+
data.dependencies = parsed.dependencies || data.dependencies;
|
|
93
|
+
data.consolidation = { ...data.consolidation, ...(parsed.consolidation || {}) };
|
|
94
|
+
|
|
95
|
+
// Merge moduleSpecs: keep embedded structure, overlay user-editable fields (notes, custom permissions)
|
|
96
|
+
for (const code of Object.keys(data.moduleSpecs)) {
|
|
97
|
+
const cached = parsed.moduleSpecs?.[code];
|
|
98
|
+
if (cached) {
|
|
99
|
+
// Preserve user notes
|
|
100
|
+
if (cached.notes) data.moduleSpecs[code].notes = cached.notes;
|
|
101
|
+
// Preserve user-added use cases/rules/entities (merged with embedded)
|
|
102
|
+
// Only add items that don't exist in embedded (by name match)
|
|
103
|
+
const embeddedUcNames = new Set((data.moduleSpecs[code].useCases || []).map(uc => uc.name));
|
|
104
|
+
(cached.useCases || []).forEach(uc => {
|
|
105
|
+
if (!embeddedUcNames.has(uc.name)) data.moduleSpecs[code].useCases.push(uc);
|
|
106
|
+
});
|
|
107
|
+
const embeddedBrNames = new Set((data.moduleSpecs[code].businessRules || []).map(br => br.name));
|
|
108
|
+
(cached.businessRules || []).forEach(br => {
|
|
109
|
+
if (!embeddedBrNames.has(br.name)) data.moduleSpecs[code].businessRules.push(br);
|
|
110
|
+
});
|
|
111
|
+
// Preserve user permissions edits
|
|
112
|
+
if (cached.permissions) data.moduleSpecs[code].permissions = cached.permissions;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
data.wireframeComments = parsed.wireframeComments || {};
|
|
117
|
+
data.specComments = parsed.specComments || {};
|
|
118
|
+
data.customRoles = parsed.customRoles || [];
|
|
119
|
+
data.customActions = parsed.customActions || [];
|
|
120
|
+
data.comments = parsed.comments || [];
|
|
121
|
+
|
|
122
|
+
// Update fingerprint
|
|
123
|
+
data._structureFingerprint = embeddedFingerprint;
|
|
124
|
+
autoSave();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Restore editable fields
|
|
128
|
+
document.querySelectorAll('.editable[data-field]').forEach(el => {
|
|
129
|
+
const value = getNestedValue(data, 'cadrage.' + el.dataset.field);
|
|
130
|
+
if (value) el.textContent = value;
|
|
131
|
+
});
|
|
132
|
+
} catch (e) { console.error('Error loading saved data:', e); }
|
|
133
|
+
}
|