fix(dashboard): verify assistant-health saves with read-back
This commit is contained in:
@@ -123,6 +123,30 @@ function buildRollbackPatchesFromSnapshot(snapshot) {
|
||||
};
|
||||
}
|
||||
|
||||
function getByPath(obj, dottedPath) {
|
||||
if (!obj || typeof obj !== 'object') {return undefined;}
|
||||
const parts = dottedPath.split('.');
|
||||
let cursor = obj;
|
||||
for (const part of parts) {
|
||||
if (!cursor || typeof cursor !== 'object' || !(part in cursor)) {
|
||||
return undefined;
|
||||
}
|
||||
cursor = cursor[part];
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
function valuesMatch(expected, actual) {
|
||||
if (Array.isArray(expected) && Array.isArray(actual)) {
|
||||
if (expected.length !== actual.length) {return false;}
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
if (expected[i] !== actual[i]) {return false;}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return expected === actual;
|
||||
}
|
||||
|
||||
function setAssistantSaveState(message, tone = 'neutral') {
|
||||
_assistantSaveState = {
|
||||
message,
|
||||
@@ -550,8 +574,28 @@ async function applyAssistantPatch(patches, statusEl) {
|
||||
message = `Runtime-only save (${applied.length} updated, file persistence unavailable)`;
|
||||
tone = 'warning';
|
||||
} else {
|
||||
message = `Saved to runtime + config file (${applied.length} updated)`;
|
||||
tone = 'success';
|
||||
// Verify read-after-write so UI cannot claim persistence when value did not stick.
|
||||
try {
|
||||
const fresh = await _dashboardClient.call('config.get');
|
||||
const mismatches = [];
|
||||
for (const [key, value] of Object.entries(patches)) {
|
||||
const actual = getByPath(fresh, key);
|
||||
if (!valuesMatch(value, actual)) {
|
||||
mismatches.push(`${key} expected=${JSON.stringify(value)} actual=${JSON.stringify(actual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (mismatches.length > 0) {
|
||||
message = `Saved response received but read-back mismatch: ${mismatches.join('; ')}`;
|
||||
tone = 'error';
|
||||
} else {
|
||||
message = `Saved to runtime + config file (${applied.length} updated)`;
|
||||
tone = 'success';
|
||||
}
|
||||
} catch (verifyError) {
|
||||
message = `Saved response received, but verification failed: ${verifyError instanceof Error ? verifyError.message : String(verifyError)}`;
|
||||
tone = 'warning';
|
||||
}
|
||||
}
|
||||
setAssistantSaveState(message, tone);
|
||||
statusEl.textContent = message;
|
||||
|
||||
Reference in New Issue
Block a user