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) {