基线:鉴权会话+工作组+工作台三区修复+编排工作区+产品设计文档

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-27 20:43:35 +08:00
co-authored by Claude Fable 5
parent 61fe181678
commit ac85ecf2ea
119 changed files with 16634 additions and 1246 deletions
@@ -0,0 +1,62 @@
/**
* 对话流投影 —— 「对话区只承载非结构化消息 + 决策选择题」(AM 07)。
* 这里守的是**筛选口径**:引擎自转不进对话,人的话不重影,工单卡带得上指涉。
*/
import { describe, expect, it } from 'vitest';
import type { NarrativeEntry } from '../internal/domain/chat-projection.ts';
import { projectChat } from '../internal/domain/chat-projection.ts';
const entry = (kind: string, over: Partial<NarrativeEntry> = {}): NarrativeEntry => ({
id: `e-${kind}`,
at: '2026-07-27T10:00:00.000Z',
kind,
title: `${kind} 标题`,
...over,
});
describe('projectChat —— 对话流与工作日志同源不同筛选', () => {
it('引擎自转的条目一律不进对话区', () => {
const noise = ['engine-transition', 'evaluation', 'action', 'thought', 'ledger-write', 'action-intent', 'card-reply', 'control'];
expect(projectChat(noise.map((k) => entry(k)))).toEqual([]);
});
it('人的自由输入不投影 —— say 已直接落成消息,再投一遍就是重影', () => {
expect(projectChat([entry('human-input', { title: '按 A 方案办' })])).toEqual([]);
});
it('事件到达投成系统事件,类型认得就用、认不得按数据事件计', () => {
const out = projectChat([
entry('observation', { id: 'o1', detail: { kind: 'time' } }),
entry('observation', { id: 'o2', detail: { kind: '莫名其妙' } }),
entry('observation', { id: 'o3' }),
]);
expect(out.map((m) => (m.k === 'system' ? m.type : m.k))).toEqual(['time', 'data', 'data']);
});
it('发工单投成 AI 发言并带上指涉 —— 卡在对话流上出现,点开即定位视图区', () => {
const [msg] = projectChat([
entry('card-sent', { title: '请你执行:补齐定价说明', detail: { kind: 'work-order', id: 'wo-1' } }),
]);
expect(msg?.k).toBe('ai');
expect(msg?.k === 'ai' ? msg.ref : undefined).toBe('wo-1');
expect(msg?.k === 'ai' ? msg.tag : undefined).toBe('guidance');
});
it('验收件标判据、执行件标指导', () => {
const out = projectChat([
entry('card-sent', { id: 'a', title: '请你验收:定价方案', detail: { kind: 'work-order', id: 'wo-a' } }),
entry('card-sent', { id: 'b', title: '请你执行:补齐说明', detail: { kind: 'work-order', id: 'wo-b' } }),
]);
expect(out.map((m) => (m.k === 'ai' ? m.tag : undefined))).toEqual(['criterion', 'guidance']);
});
it('跨人卡不在本任务对话流上露面 —— 它进对方的消息要素', () => {
expect(projectChat([entry('card-sent', { detail: { kind: 'chat-card', id: 'c-1' } })])).toEqual([]);
});
it('放行裁决与终态投成阶段结论', () => {
const out = projectChat([entry('release-verdict', { id: 'r' }), entry('terminal', { id: 't' })]);
expect(out).toHaveLength(2);
expect(out.every((m) => m.k === 'ai' && m.tag === 'conclusion')).toBe(true);
});
});