From 09885c3dbda17132d5274335d1fc6b9661dc1315 Mon Sep 17 00:00:00 2001 From: xcs Date: Sat, 29 Aug 2026 06:32:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(memory):=20=E5=B7=A5=E4=BD=9C=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=8A=8A=E9=85=8D=E6=96=B9=E5=81=9A=E7=9A=84=E4=BA=8B?= =?UTF-8?q?=E5=BD=92=E7=B3=BB=E7=BB=9F=20=E2=80=94=E2=80=94=20=E5=AE=83?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=20AI=20=E5=88=A4=E7=9A=84,=E4=B9=9F=E4=B8=8D?= =?UTF-8?q?=E6=98=AF=E4=BA=BA=E5=8A=9E=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不加这一条,配方的留痕会掉进 default 分支记在「任务助手」名下,日志上看着像 AI 干的。 自主率的分法要认第三档:确定的事交系统,判断交 AI,责任交人。 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet --- .../memory/__tests__/task-memory.test.ts | 23 +++++++++++++++++++ .../memory/internal/domain/task-log.ts | 7 ++++++ 2 files changed, 30 insertions(+) diff --git a/apps/api/src/modules/memory/__tests__/task-memory.test.ts b/apps/api/src/modules/memory/__tests__/task-memory.test.ts index 54f1d6c..067dd6a 100644 --- a/apps/api/src/modules/memory/__tests__/task-memory.test.ts +++ b/apps/api/src/modules/memory/__tests__/task-memory.test.ts @@ -642,3 +642,26 @@ describe('进对话区的交代也只摆首句', () => { expect(detailOf(one)).toEqual(['这句已进对话区。']); }); }); + +/** + * 日志三色:配方做的事归系统(2026-08-29,ADR-014)。 + * + * 用 `action-intent` 造例 —— 它在 `SKELETON` 里(能真的走完 `structuredLog` 全程, + * 不像 `result` 那样在骨架这一关就被滤掉、永远到不了 `actorOf`), + * 且不带 `detail.auto` 时会落进 `actorOf` 的 `default` 分支(署「任务助手」), + * 正好能对照出「加了 `detail.auto` 之后改署系统」这条判定是否生效。 + */ +describe('日志三色:配方做的事归系统', () => { + it('带 detail.auto 的那几行是**系统**做的 —— 既不是 AI 判的,也不是人办的', () => { + const lines = structuredLog([ + entry('action-intent', { title: '芯片主数据:写下 2 行', detail: { auto: 'S1#3' } }), + ]); + expect(lines[0]?.who).toBe('system'); + expect(lines[0]?.actor).toBe('系统'); + }); + + it('没有 detail.auto 的 action-intent 照旧记在 AI 名下 —— 老行为一个字不变', () => { + const lines = structuredLog([entry('action-intent', { title: '我判齐了' })]); + expect(lines[0]?.who).toBe('agent'); + }); +}); diff --git a/apps/api/src/modules/memory/internal/domain/task-log.ts b/apps/api/src/modules/memory/internal/domain/task-log.ts index 0dc25b5..6be8deb 100644 --- a/apps/api/src/modules/memory/internal/domain/task-log.ts +++ b/apps/api/src/modules/memory/internal/domain/task-log.ts @@ -269,6 +269,13 @@ function actionOf(e: MemoryEntry): string { * 由上层换成名字;换不到就退回「员工」,不编名字。 */ function actorOf(e: MemoryEntry): { actor: string; actorId: string | undefined; who: 'owner' | 'agent' | 'system' } { + /* + * **配方做的事归系统**(2026-08-29,ADR-014)。自主率的分法要认第三档: + * 它既不是 AI 判出来的,也不是人办的 —— 是系统按声明做的。 + * 不加这一条的话,`kind: 'result'` 会掉进 `default` 分支被记在「任务助手」名下, + * 日志上看着像 AI 干的 —— **界面不撒谎**。 + */ + if (typeof e.detail?.['auto'] === 'string') return { actor: '系统', actorId: undefined, who: 'system' as const }; const by = e.detail?.['by']; const id = typeof by === 'string' && by !== '' ? by : undefined; switch (e.kind) {