fix(mindspace): edit_file 落盘、Finish 聊天 merge 与回归守卫
- finish-sync 支持 edit_file 覆盖 public HTML - Finish 同步 merge 本地流式消息,剥离 agent 内部前缀 - 新增 verify:mindspace-publish-guards 与 AGENTS.md 跨工具说明 - 发版脚本接入回归门禁;103 runtime 发布含备份回退 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Chat Finish sync invariants (regression guard — do not simplify away).
|
||||
*
|
||||
* Context (2026-06): Finish could arrive before Goose persisted assistant turns.
|
||||
* Blind replace with the server snapshot wiped the live chat and exposed agent-only
|
||||
* prefixes (routing hints / skill prefaces) when displayText was missing.
|
||||
*
|
||||
* Required behaviour:
|
||||
* - merge local streamed messages with server snapshot (never blind replace)
|
||||
* - retry sync while server has fewer messages than the local view
|
||||
* - user-facing text must strip agent-only prefixes when displayText is absent
|
||||
*
|
||||
* Tests: chat-finish-sync.test.mjs, conversation-display.test.mjs
|
||||
* Verify: scripts/verify-chat-finish-sync.mjs (source guards)
|
||||
* Docs: docs/regression-guards/mindspace-publish-and-chat-finish.md
|
||||
*/
|
||||
|
||||
/** @typedef {{ id?: string; role?: string; metadata?: Record<string, unknown>; content?: unknown[] }} ChatMessage */
|
||||
|
||||
/**
|
||||
* Merge an authoritative server conversation snapshot into the currently
|
||||
* displayed messages without erasing what the user can already see.
|
||||
*
|
||||
* @param {ChatMessage[]} current
|
||||
* @param {ChatMessage[]} incoming
|
||||
*/
|
||||
export function mergeConversationSnapshot(current, incoming) {
|
||||
if (!Array.isArray(incoming) || incoming.length === 0) {
|
||||
return Array.isArray(current) ? current : [];
|
||||
}
|
||||
const base = Array.isArray(current) ? current : [];
|
||||
const incomingIds = new Set(incoming.map((message) => message?.id).filter(Boolean));
|
||||
const localOnly = base.filter((message) => message?.id && !incomingIds.has(message.id));
|
||||
return localOnly.length ? [...incoming, ...localOnly] : incoming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish-time sync: server may lag behind the streamed UI — keep the local tail.
|
||||
*
|
||||
* @param {ChatMessage[]} localMessages
|
||||
* @param {ChatMessage[]} serverMessages
|
||||
*/
|
||||
export function mergeSessionMessagesAfterFinish(localMessages, serverMessages) {
|
||||
return mergeConversationSnapshot(localMessages, serverMessages);
|
||||
}
|
||||
Reference in New Issue
Block a user