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:
john
2026-06-30 00:27:15 +08:00
parent 742aee7148
commit 98721371a4
31 changed files with 1440 additions and 141 deletions
+165 -1
View File
@@ -4,7 +4,13 @@ import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { hasRecentOwnPublicHtmlReference, isStubPublicHtmlContent, materializeMissingPublicHtmlWrites, syncPublicDocxDownloads } from './mindspace-public-finish-sync.mjs';
import {
hasRecentOwnPublicHtmlReference,
isStubPublicHtmlContent,
materializeMissingPublicHtmlWrites,
materializePublicHtmlWritesFromSessionEvent,
syncPublicDocxDownloads,
} from './mindspace-public-finish-sync.mjs';
const CURRENT_USER = { id: 'a6fb1e97-2b0f-447b-b138-4561d8e5c53e', username: 'john' };
@@ -324,3 +330,161 @@ test('materializeMissingPublicHtmlWrites skips existing real html when content i
fs.rmSync(publishDir, { recursive: true, force: true });
}
});
test('detects a recent edit_file tool request on an existing public html page', () => {
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'public-finish-sync-'));
try {
const htmlPath = path.join(publishDir, 'public/guide.html');
fs.mkdirSync(path.dirname(htmlPath), { recursive: true });
fs.writeFileSync(htmlPath, '<body>一二三</body>', 'utf8');
const messages = [
{
role: 'assistant',
content: [
{
type: 'toolRequest',
toolCall: {
value: {
name: 'edit_file',
arguments: {
path: 'public/guide.html',
old_str: '一二三',
new_str: '二三四',
},
},
},
},
],
metadata: { userVisible: true },
},
];
assert.equal(hasRecentOwnPublicHtmlReference(messages, CURRENT_USER, { publishDir }), true);
} finally {
fs.rmSync(publishDir, { recursive: true, force: true });
}
});
test('materializeMissingPublicHtmlWrites applies edit_file patches onto existing public html', () => {
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'public-finish-sync-'));
try {
const htmlPath = path.join(publishDir, 'public/guide.html');
fs.mkdirSync(path.dirname(htmlPath), { recursive: true });
fs.writeFileSync(htmlPath, '<!doctype html><title>Existing</title><body>一二三</body>', 'utf8');
const result = materializeMissingPublicHtmlWrites({
messages: [
{
role: 'assistant',
content: [
{
type: 'toolRequest',
toolCall: {
value: {
name: 'edit_file',
arguments: {
path: 'public/guide.html',
old_str: '一二三',
new_str: '二三四',
},
},
},
},
],
},
],
publishDir,
});
assert.deepEqual(result.materialized, ['public/guide.html']);
assert.match(fs.readFileSync(htmlPath, 'utf8'), /二三四/);
assert.doesNotMatch(fs.readFileSync(htmlPath, 'utf8'), /一二三/);
} finally {
fs.rmSync(publishDir, { recursive: true, force: true });
}
});
test('materializeMissingPublicHtmlWrites chains multiple edit_file patches for the same html', () => {
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'public-finish-sync-'));
try {
const htmlPath = path.join(publishDir, 'public/guide.html');
fs.mkdirSync(path.dirname(htmlPath), { recursive: true });
fs.writeFileSync(htmlPath, '<body>一 · 二三</body>', 'utf8');
const result = materializeMissingPublicHtmlWrites({
messages: [
{
role: 'assistant',
content: [
{
type: 'toolRequest',
toolCall: {
value: {
name: 'edit_file',
arguments: {
path: 'public/guide.html',
old_str: '一',
new_str: '二',
},
},
},
},
{
type: 'toolRequest',
toolCall: {
value: {
name: 'edit_file',
arguments: {
path: 'public/guide.html',
old_str: '二三',
new_str: '三四',
},
},
},
},
],
},
],
publishDir,
});
assert.deepEqual(result.materialized, ['public/guide.html']);
assert.match(fs.readFileSync(htmlPath, 'utf8'), /二 · 三四/);
} finally {
fs.rmSync(publishDir, { recursive: true, force: true });
}
});
test('materializePublicHtmlWritesFromSessionEvent writes public html from message event before finish', () => {
const publishDir = fs.mkdtempSync(path.join(os.tmpdir(), 'public-event-sync-'));
try {
const result = materializePublicHtmlWritesFromSessionEvent(
{
type: 'Message',
message: {
id: 'assistant-1',
role: 'assistant',
metadata: { userVisible: true },
content: [
{
type: 'toolRequest',
toolCall: {
value: {
name: 'write',
arguments: {
path: 'public/shenwu-gate.html',
content: '<!doctype html><html><body>神口门</body></html>',
},
},
},
},
],
},
},
{ publishDir },
);
assert.deepEqual(result.materialized, ['public/shenwu-gate.html']);
assert.match(
fs.readFileSync(path.join(publishDir, 'public/shenwu-gate.html'), 'utf8'),
/神口门/,
);
} finally {
fs.rmSync(publishDir, { recursive: true, force: true });
}
});