Archived
fix(loop-engine): 「配方跑完了还没算办完」交人消息改 kind: observation —— R10 第六处
这条是五(六)处里最不能隐身的:它是配方没做到位时交人的那一句,人打开工作日志 想知道的第一件事就是「为什么停了」,而从前 kind: 'result' 不在 SKELETON 里, 这条消息永远进不了工作日志,单子看着像凭空卡住。只改 kind,detail 不动。 card 动作里「这一步已经发过卡,不再发第二张」那条保持 internal: true 不改 —— 它每次重入(卡开着的每一拍)都会打一遍,是典型的排障痕,machinery() 的过滤 存在的意义就是滤掉这类;摆到人面前只会把真正要看的东西淹掉。 新增回归测试:跑真实的 turn-runner.ts,让案例落到「没 guide、没发卡、doneWhen 不成立」这条分支,把捕获到的留痕喂给 structuredLog 全程,断言可见且归系统。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -2285,6 +2285,38 @@ describe('auto 步:配方在拍首跑', () => {
|
|||||||
expect(h.appended.some((a) => a.title.includes('nope.nope'))).toBe(true);
|
expect(h.appended.some((a) => a.title.includes('nope.nope'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('配方跑完了、这一步还没算办完(没 guide、没发卡、doneWhen 不成立)→ 交人,且这条消息真的到得了工作日志(R10 第六处)', async () => {
|
||||||
|
const h = harness({
|
||||||
|
parsed: AUTO_MODEL,
|
||||||
|
runtime: AUTO_RUNTIME,
|
||||||
|
sfeelCondition: () => false,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
item: 'S1',
|
||||||
|
guide: '',
|
||||||
|
writes: [],
|
||||||
|
reads: [],
|
||||||
|
tools: [],
|
||||||
|
// say 不写不撤、不发卡 —— 配方跑完仍落到「没算办完,交人」那条分支
|
||||||
|
auto: { do: [{ kind: 'say', text: '已核对,尚缺关键信息' }] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const out = await h.runner.runTurn(TASK);
|
||||||
|
expect(h.decided).toHaveLength(0);
|
||||||
|
expect(out.status).toBe('awaiting');
|
||||||
|
const line = h.appended.find((a) => a.title.includes('还没算办完'));
|
||||||
|
expect(line).toBeDefined();
|
||||||
|
/*
|
||||||
|
* **这一条是五处里最不能隐身的**(2026-08-29,coordinator 裁定):它是交人的那一句 ——
|
||||||
|
* 配方没做到位、单子就停在这儿了,人打开工作日志想知道的第一件事就是「为什么停了」。
|
||||||
|
* 从前 kind: 'result' 不在 SKELETON 里,这一笔永远进不了工作日志,单子看着像凭空卡住。
|
||||||
|
*/
|
||||||
|
const lines = structuredLog([asLogEntry(line!)]);
|
||||||
|
expect(lines).toHaveLength(1);
|
||||||
|
expect(lines[0]?.who).toBe('system');
|
||||||
|
});
|
||||||
|
|
||||||
it('这一步有 guide:配方跑完照常问模型(半 auto)', async () => {
|
it('这一步有 guide:配方跑完照常问模型(半 auto)', async () => {
|
||||||
const h = harness({
|
const h = harness({
|
||||||
parsed: OPEN_MODEL,
|
parsed: OPEN_MODEL,
|
||||||
|
|||||||
@@ -2052,10 +2052,15 @@ export function createTurnRunner(deps: TurnRunnerDeps): LoopEngineService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current.guide.trim() === '') {
|
if (current.guide.trim() === '') {
|
||||||
/* 没有 guide、没发卡、doneWhen 也不成立 → 配方没做到位,是包的 bug,交人 */
|
/*
|
||||||
|
* 没有 guide、没发卡、doneWhen 也不成立 → 配方没做到位,是包的 bug,交人。
|
||||||
|
* **kind: 'observation'**(2026-08-29,R10 第六处)—— 从前是 `kind: 'result'`,
|
||||||
|
* 不在 `SKELETON` 里,这条**交人**的消息永远进不了工作日志,单子看着像凭空卡住,
|
||||||
|
* 而人打开日志想知道的第一件事就是「为什么停了」。只改 kind,detail 不动。
|
||||||
|
*/
|
||||||
await deps.memory.append({
|
await deps.memory.append({
|
||||||
taskId,
|
taskId,
|
||||||
kind: 'result',
|
kind: 'observation',
|
||||||
title: `「${current.item}」的配方跑完了,可这一步还没算办完 —— 交给你看一眼`,
|
title: `「${current.item}」的配方跑完了,可这一步还没算办完 —— 交给你看一眼`,
|
||||||
detail: { auto: current.item },
|
detail: { auto: current.item },
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user