fix: 用容器生命周期核实恢复并单列三份总体验收

审阅发现spawn后快照早于恢复实际执行,不能证明没有重启;改用杀前至目标结果落账的Docker历史事件,保留缓存完整性限制。逐份stats不再冒称任务书总体通过;独立验收要求三份不同研究、成功杀进程及不重叠区间。两项缺陷附回归,7项定向测试与check通过,独立复审无新问题;真实B尚待启动。
This commit is contained in:
2026-10-04 04:52:13 -04:00
parent b7be524cdc
commit de8e13b031
5 changed files with 473 additions and 25 deletions
+86 -5
View File
@@ -1,5 +1,5 @@
import { execFileSync } from "node:child_process";
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
import { forwardAccounts, frozenConfig, jsonFile } from "../lib/forward.ts";
import { ofKind, readLedger } from "../lib/ledger.ts";
@@ -40,6 +40,10 @@ const config =
name,
null,
);
const daemonTime = () =>
execFileSync("docker", ["info", "--format", "{{.SystemTime}}"], {
encoding: "utf8",
}).trim();
const inspect = (container: string) =>
JSON.parse(
execFileSync("docker", ["inspect", container], {
@@ -130,6 +134,8 @@ try {
if (started !== undefined) {
// 容器名是正式入口记录在结构文档里的约定,不 import flow 内部文件。
const container = `inforsi-${name}-${run}`;
// 从杀前划定历史事件区间,覆盖恢复启动到目标结果落账;不把 spawn 当成恢复已执行。
const lifecycleSince = daemonTime();
const before = inspect(container);
jsonFile(
join(
@@ -208,20 +214,95 @@ try {
afterKill,
);
observe("after-kill");
active = start(null);
const afterResume = inspect(container);
jsonFile(
join(
out,
"container-after-resume.json",
"container-before-resume.json",
),
afterResume,
inspect(container),
);
jsonFile(
join(
out,
"container-events-window.json",
),
{
since: lifecycleSince,
until: null,
run,
resultSeq: null,
},
);
active = start(null);
watching = watchTimeline(
studyDir,
active.child,
join(out, "timeline.jsonl"),
);
let targetResult;
while (true) {
targetResult = ofKind(
readLedger(studyDir),
"runResult",
).find(
(r) =>
r.content
.run ===
run,
);
if (
targetResult !==
undefined ||
active.child
.exitCode !==
null ||
active.child
.signalCode !==
null
)
break;
await sleep(100);
}
const lifecycleUntil = daemonTime();
// Docker CLI 按时间回读,不依赖事件订阅的启动时序;原文全存,stats 核对缓存上限和目标 die。
const events = execFileSync(
"docker",
[
"events",
"--since",
lifecycleSince,
"--until",
lifecycleUntil,
"--format",
"{{json .}}",
],
{ encoding: "utf8" },
);
writeFileSync(
join(
out,
"container-events.jsonl",
),
events,
);
jsonFile(
join(
out,
"container-events-window.json",
),
{
since: lifecycleSince,
until: lifecycleUntil,
run,
resultSeq:
targetResult?.seq ??
null,
},
);
if (targetResult === undefined)
throw new Error(
"恢复进程没有交出目标结果,生命周期证据不完整;保留现场",
);
hit = true;
break;
}