feat(ms-ai-architect): add v1→v2 MIGRATIONS handler with snapshot fixture and idempotency test
This commit is contained in:
parent
1fe40fe886
commit
502faa97d5
3 changed files with 354 additions and 0 deletions
|
|
@ -502,6 +502,10 @@
|
|||
const loaded = await persistence.load();
|
||||
// Sørg for at schemaVersion finnes (cold start kan returnere uten).
|
||||
if (!loaded.schemaVersion) loaded.schemaVersion = SCHEMA_VERSION;
|
||||
// Data-version migrasjon (v1.9.0 -> v1.10.0): utled verdict/keyStats
|
||||
// for eksisterende parser-output. Idempotent via state.dataVersion-guard.
|
||||
try { migrateDataVersion(loaded, defaultArchetypeFor); }
|
||||
catch (e) { console.warn('[playground v3] migrateDataVersion failed:', e); }
|
||||
store = createStore(loaded, sharedBus);
|
||||
scheduleWrite = makeThrottledWriter(function () {
|
||||
return persistence.save(store.raw);
|
||||
|
|
@ -625,12 +629,17 @@
|
|||
// Migrer envelope opp til gjeldende SCHEMA_VERSION før vi commit-er.
|
||||
const migrated = migrateState({
|
||||
schemaVersion: envelope.schemaVersion,
|
||||
dataVersion: envelope.dataVersion,
|
||||
shared: envelope.shared || INITIAL_STATE.shared,
|
||||
projects: envelope.projects || [],
|
||||
activeProjectId: envelope.activeProjectId || null,
|
||||
activeSurface: envelope.activeSurface || 'home',
|
||||
preferences: envelope.preferences || INITIAL_STATE.preferences
|
||||
});
|
||||
// Data-version migrasjon (additive — verdict/keyStats utledes for
|
||||
// pre-v1.10.0 envelope-er). Idempotent via dataVersion=2 guard.
|
||||
try { migrateDataVersion(migrated, defaultArchetypeFor); }
|
||||
catch (e) { console.warn('[playground v3] migrateDataVersion (import) failed:', e); }
|
||||
// Skriv direkte til persistens for å unngå at debounce-vinduet
|
||||
// svelger import-en ved en samtidig page-unload.
|
||||
if (persistence) {
|
||||
|
|
@ -640,6 +649,7 @@
|
|||
// sin referanse fordi Proxy-en er bundet til den; muter feltvis.
|
||||
const target = store.raw;
|
||||
target.schemaVersion = migrated.schemaVersion;
|
||||
if (migrated.dataVersion != null) target.dataVersion = migrated.dataVersion;
|
||||
target.shared = migrated.shared;
|
||||
target.projects = migrated.projects;
|
||||
target.activeProjectId = migrated.activeProjectId;
|
||||
|
|
@ -3237,6 +3247,7 @@
|
|||
slot.innerHTML = '<div class="diff">' + summaryHtml + headerHtml + rowsHtml + '</div>';
|
||||
}
|
||||
|
||||
// === V2_FOUNDATION_BEGIN ===
|
||||
// ============================================================
|
||||
// FOUNDATION HELPERS (v1.10.0 Sesjon 1)
|
||||
// ============================================================
|
||||
|
|
@ -3511,6 +3522,50 @@
|
|||
);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// DATA-VERSION MIGRATION (v1->v2)
|
||||
// ============================================================
|
||||
//
|
||||
// State.dataVersion sporer parser-output-format separat fra
|
||||
// state.schemaVersion (som sporer state-shape). v1.9.0 produserte
|
||||
// parser-output uten verdict/keyStats; v1.10.0 utvider med felles
|
||||
// grunnskjelett-data. Migrasjonen er additive — eksisterende felter
|
||||
// forblir uendret.
|
||||
//
|
||||
// v1_to_v2-handler: itererer projects[].reports[cmdId].parsed; hvis
|
||||
// verdict eller keyStats mangler, utled fra eksisterende felter via
|
||||
// inferVerdict + inferKeyStats. Setter state.dataVersion = 2 så
|
||||
// migrasjonen er idempotent (re-kjøring er no-op).
|
||||
|
||||
function migrateDataVersion(state, archetypeFor) {
|
||||
if (!state) return state;
|
||||
if (state.dataVersion === 2) return state;
|
||||
const projects = state.projects || [];
|
||||
for (let i = 0; i < projects.length; i++) {
|
||||
const reports = (projects[i] && projects[i].reports) || {};
|
||||
const ids = Object.keys(reports);
|
||||
for (let j = 0; j < ids.length; j++) {
|
||||
const cmdId = ids[j];
|
||||
const r = reports[cmdId];
|
||||
if (!r || !r.parsed) continue;
|
||||
const arche = typeof archetypeFor === 'function' ? archetypeFor(cmdId) : null;
|
||||
if (!arche) continue;
|
||||
if (r.parsed.verdict == null) r.parsed.verdict = inferVerdict(r.parsed, arche);
|
||||
if (!Array.isArray(r.parsed.keyStats)) r.parsed.keyStats = inferKeyStats(r.parsed, arche);
|
||||
}
|
||||
}
|
||||
state.dataVersion = 2;
|
||||
return state;
|
||||
}
|
||||
|
||||
function defaultArchetypeFor(commandId) {
|
||||
const cmds = (CATALOG && CATALOG.commands) || [];
|
||||
for (let i = 0; i < cmds.length; i++) {
|
||||
if (cmds[i].id === commandId) return cmds[i].report_archetype || null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Eksponer for tester og fremtidig renderer-iterasjon (Sesjon 3-5)
|
||||
window.__renderPageShell = renderPageShell;
|
||||
window.__renderVerdictPill = renderVerdictPill;
|
||||
|
|
@ -3518,6 +3573,9 @@
|
|||
window.__inferVerdict = inferVerdict;
|
||||
window.__inferKeyStats = inferKeyStats;
|
||||
window.__KEY_STATS_CONFIG = KEY_STATS_CONFIG;
|
||||
window.__migrateDataVersion = migrateDataVersion;
|
||||
window.__defaultArchetypeFor = defaultArchetypeFor;
|
||||
// === V2_FOUNDATION_END ===
|
||||
|
||||
// ---- RENDERERS routing-objekt (17 commands) ----
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue