Fix chat metadata integrity persistence

This commit is contained in:
Youzini-afk
2026-03-29 12:25:38 +08:00
parent 6cec03182b
commit afca95a164
2 changed files with 19 additions and 16 deletions

View File

@@ -1596,7 +1596,6 @@ function persistGraphToChatMetadata(
reason = "graph-persist", reason = "graph-persist",
revision = graphPersistenceState.revision, revision = graphPersistenceState.revision,
immediate = false, immediate = false,
rotateIntegrity = false,
} = {}, } = {},
) { ) {
if (!context || !currentGraph) { if (!context || !currentGraph) {
@@ -1618,9 +1617,7 @@ function persistGraphToChatMetadata(
}); });
} }
const nextIntegrity = rotateIntegrity const nextIntegrity = getChatMetadataIntegrity(context);
? createLocalIntegritySlug()
: getChatMetadataIntegrity(context);
stampGraphPersistenceMeta(currentGraph, { stampGraphPersistenceMeta(currentGraph, {
revision, revision,
reason, reason,
@@ -1629,7 +1626,6 @@ function persistGraphToChatMetadata(
}); });
writeChatMetadataPatch(context, { writeChatMetadataPatch(context, {
[GRAPH_METADATA_KEY]: currentGraph, [GRAPH_METADATA_KEY]: currentGraph,
...(nextIntegrity ? { integrity: nextIntegrity } : {}),
}); });
const saveMode = triggerChatMetadataSave(context, { immediate }); const saveMode = triggerChatMetadataSave(context, { immediate });
@@ -1669,7 +1665,7 @@ function persistGraphToChatMetadata(
function queueGraphPersist( function queueGraphPersist(
reason = "graph-persist-blocked", reason = "graph-persist-blocked",
revision = graphPersistenceState.revision, revision = graphPersistenceState.revision,
{ immediate = true, rotateIntegrity = true } = {}, { immediate = true } = {},
) { ) {
maybeCaptureGraphShadowSnapshot(reason); maybeCaptureGraphShadowSnapshot(reason);
updateGraphPersistenceState({ updateGraphPersistenceState({
@@ -1678,7 +1674,7 @@ function queueGraphPersist(
revision || 0, revision || 0,
), ),
queuedPersistMode: immediate ? "immediate" : "debounced", queuedPersistMode: immediate ? "immediate" : "debounced",
queuedPersistRotateIntegrity: Boolean(rotateIntegrity), queuedPersistRotateIntegrity: false,
queuedPersistReason: String(reason || ""), queuedPersistReason: String(reason || ""),
pendingPersist: true, pendingPersist: true,
writesBlocked: true, writesBlocked: true,
@@ -1731,7 +1727,6 @@ function maybeFlushQueuedGraphPersist(reason = "queued-graph-persist") {
reason, reason,
revision: targetRevision, revision: targetRevision,
immediate: graphPersistenceState.queuedPersistMode !== "debounced", immediate: graphPersistenceState.queuedPersistMode !== "debounced",
rotateIntegrity: graphPersistenceState.queuedPersistRotateIntegrity,
}); });
} }
@@ -2682,7 +2677,7 @@ function loadGraphFromChat(options = {}) {
updateGraphPersistenceState({ updateGraphPersistenceState({
metadataIntegrity, metadataIntegrity,
queuedPersistMode: "immediate", queuedPersistMode: "immediate",
queuedPersistRotateIntegrity: true, queuedPersistRotateIntegrity: false,
queuedPersistReason: "shadow-snapshot-newer-than-official", queuedPersistReason: "shadow-snapshot-newer-than-official",
}); });
const persistResult = maybeFlushQueuedGraphPersist( const persistResult = maybeFlushQueuedGraphPersist(
@@ -2816,7 +2811,7 @@ function loadGraphFromChat(options = {}) {
updateGraphPersistenceState({ updateGraphPersistenceState({
metadataIntegrity: getChatMetadataIntegrity(context), metadataIntegrity: getChatMetadataIntegrity(context),
queuedPersistMode: "immediate", queuedPersistMode: "immediate",
queuedPersistRotateIntegrity: true, queuedPersistRotateIntegrity: false,
queuedPersistReason: "shadow-snapshot-promoted", queuedPersistReason: "shadow-snapshot-promoted",
}); });
const persistResult = maybeFlushQueuedGraphPersist( const persistResult = maybeFlushQueuedGraphPersist(
@@ -2855,7 +2850,7 @@ function loadGraphFromChat(options = {}) {
}); });
updateGraphPersistenceState({ updateGraphPersistenceState({
queuedPersistMode: "immediate", queuedPersistMode: "immediate",
queuedPersistRotateIntegrity: true, queuedPersistRotateIntegrity: false,
queuedPersistReason: shouldRetry queuedPersistReason: shouldRetry
? "shadow-snapshot-restored" ? "shadow-snapshot-restored"
: "shadow-snapshot-blocked", : "shadow-snapshot-blocked",
@@ -3026,7 +3021,6 @@ function saveGraphToChat(options = {}) {
markMutation = true, markMutation = true,
captureShadow = true, captureShadow = true,
immediate = markMutation, immediate = markMutation,
rotateIntegrity = markMutation,
} = options; } = options;
ensureCurrentGraphRuntimeState(); ensureCurrentGraphRuntimeState();
@@ -3068,14 +3062,13 @@ function saveGraphToChat(options = {}) {
console.warn( console.warn(
`[ST-BME] 图谱写回已被安全保护拦截chat=${chatId}state=${graphPersistenceState.loadState}reason=${reason}`, `[ST-BME] 图谱写回已被安全保护拦截chat=${chatId}state=${graphPersistenceState.loadState}reason=${reason}`,
); );
return queueGraphPersist(reason, revision, { immediate, rotateIntegrity }); return queueGraphPersist(reason, revision, { immediate });
} }
return persistGraphToChatMetadata(context, { return persistGraphToChatMetadata(context, {
reason, reason,
revision, revision,
immediate, immediate,
rotateIntegrity,
}); });
} }

View File

@@ -637,6 +637,11 @@ result = {
?.title, ?.title,
"事件-shadow-newer", "事件-shadow-newer",
); );
assert.equal(
reader.runtimeContext.__chatContext.chatMetadata?.integrity,
"integrity-official-older",
"影子快照补写正式图谱时不能改写宿主 metadata.integrity",
);
assert.equal( assert.equal(
reader.api.readGraphShadowSnapshot("chat-shadow-newer"), reader.api.readGraphShadowSnapshot("chat-shadow-newer"),
null, null,
@@ -724,8 +729,8 @@ result = {
assert.equal( assert.equal(
harness.runtimeContext.__chatContext.chatMetadata?.integrity === harness.runtimeContext.__chatContext.chatMetadata?.integrity ===
"integrity-before-first-save", "integrity-before-first-save",
false, true,
"真正改图后应轮换 metadata.integrity,阻止旧页面覆盖", "插件保存图谱时不能改写宿主 metadata.integrity",
); );
assert.equal( assert.equal(
harness.runtimeContext.__chatContext.chatMetadata?.st_bme_graph?.__stBmePersistence harness.runtimeContext.__chatContext.chatMetadata?.st_bme_graph?.__stBmePersistence
@@ -765,6 +770,11 @@ result = {
reader.runtimeContext.__chatContext.chatMetadata?.st_bme_graph?.nodes?.length, reader.runtimeContext.__chatContext.chatMetadata?.st_bme_graph?.nodes?.length,
1, 1,
); );
assert.equal(
reader.runtimeContext.__chatContext.chatMetadata?.integrity,
"meta-ready-promote",
"metadata 就绪后提升影子快照时不能改写宿主 metadata.integrity",
);
assert.equal(reader.runtimeContext.__contextImmediateSaveCalls, 1); assert.equal(reader.runtimeContext.__contextImmediateSaveCalls, 1);
assert.equal(reader.runtimeContext.__contextSaveCalls, 0); assert.equal(reader.runtimeContext.__contextSaveCalls, 0);
assert.equal(live.lastPersistedRevision, 9); assert.equal(live.lastPersistedRevision, 9);