Archived
fix(w05): 复核轮审核人说了算,并把这一轮改了什么说进对话区
用户第二次实测:「重做还是没有修改掉内容」—— 他写「静态电流结论改成不匹配」,而两颗料的 静态电流都是 5mA,AI 搬出第一轮那份规矩里的第 3 条(硬约束不因措辞变成 match)把他顶了回去: evidence_note 白纸黑字「维持上一轮 match…硬规矩要求按实际值判定,不能因措辞改变结论」。 **行的范围这次是对的**(只把那一条交给 AI、只写回那一条),错在**谁说了算**。三处想岔了: ① 那条规矩管的是它自己判的时候别被措辞带偏,不是用来否决审核人的; ② 方向也反了 —— 它守的是「不许把不满足说成满足」(危险方向),而他要的是收紧结论; ③ 更根本:审核人在件上本来就能亲手改任何一条四态,AI 在重判这条路上顶回去, 等于同一件事在两条路上给出相反的答案。 改:复核指令明写这条覆盖 —— 他点名要什么结论就落什么,不要顶回去;落的同时 evidence_note 记两句「按谁的意见」+「数据面是什么」,下一个人回看能一眼分清数据判的还是人定的。 同批(用户接着提:「需要把 ai 的修改意见通过右边 ai 聊天窗口展示出来,不然都不知道发生了什么」): 复核完在对话区说一句「按你的意见复核了 N 条 —— <参数名>:<判断依据>」,摆的是件上那一行 自己的话,不另编一句。**它必须排在卡之前** —— 发了卡这一拍就收了,排在卡后面的 say 要等 下一拍才跑:原来那句「差异结论已送审,请核对」实测正是在人答完之后才出现的;而且它与卡自己的 ask 本来就是同一件事,一并退役。 验收:e2e w05 5/5 released、被拒 0;案例 0 三条断言全绿 —— 「复核那一轮在对话区说了话」「打回点名要的结论真落下去了(使能阈值 = conditional)」 「打回只动了被点名的那几条」。包内 +2 测。W05@2.21.0 已装库。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -406,8 +406,8 @@ describe('S3 / S4 配方', () => {
|
||||
const s4 = stepOf('T_release')?.auto?.do ?? [];
|
||||
const s2 = stepOf('S2_assess')?.auto?.do ?? [];
|
||||
|
||||
it('S3 九笔:圈范围 → 兜底扩范围 → 复核重判 → 落明细 → 明细重算 → 关系 → 验证记录 → 卡 → 交代', () => {
|
||||
expect(s3.map((a) => a.kind)).toEqual(['project', 'project', 'analyze', 'project', 'project', 'project', 'project', 'card', 'say']);
|
||||
it('S3 九笔:圈范围 → 兜底扩范围 → 复核重判 → 落明细 → 明细重算 → 关系 → 验证记录 → 交代 → 卡', () => {
|
||||
expect(s3.map((a) => a.kind)).toEqual(['project', 'project', 'analyze', 'project', 'project', 'project', 'project', 'say', 'card']);
|
||||
for (const at of [0, 1, 3, 4]) expect(s3[at]?.kind === 'project' && s3[at].into).toBe('substitution.difference_item');
|
||||
expect(s3[5]?.kind === 'project' && s3[5].into).toBe('substitution.relation');
|
||||
expect(s3[6]?.kind === 'project' && s3[6].into).toBe('validation.record');
|
||||
@@ -457,6 +457,19 @@ describe('S3 / S4 配方', () => {
|
||||
/* 判法一处真源:复核指令以第一轮那份规矩打头,后面才接复核纪律 */
|
||||
const rules = s2[0]?.kind === 'analyze' ? s2[0].instruction : '';
|
||||
expect(redo?.kind === 'analyze' && redo.instruction.startsWith(rules)).toBe(true);
|
||||
/*
|
||||
* **复核轮审核人说了算**(2026-09-01 用户第二次实测:「重做还是没有修改掉内容」)——
|
||||
* 他写「静态电流结论改成不匹配」,而两颗料的静态电流都是 5mA,AI 搬出第一轮那条
|
||||
* 「硬约束不因措辞变成 match」把他顶了回去。那条规矩管的是**它自己判**的时候别被措辞带偏;
|
||||
* 审核人是这一步的责任人(要签他的字,他在件上本来就能亲手改任何一条四态),不归它管。
|
||||
* 指令里必须**明写这条覆盖**,否则前面那份规矩排在前面、模型照旧照它办。
|
||||
*/
|
||||
const tail = redo?.kind === 'analyze' ? redo.instruction.slice(rules.length) : '';
|
||||
expect(tail).toContain('这一轮不归它管');
|
||||
expect(tail).toContain('他点名要什么结论,就落什么');
|
||||
expect(tail).toContain('不要顶回去');
|
||||
/* 落的同时要把「按谁的意见、数据面是什么」记进依据 —— 下一个人得能分清人定的与数据判的 */
|
||||
expect(tail).toContain('数据面');
|
||||
/* 入参:上一轮结论 + 他写的意见 —— 少了任何一样,重判要么无据可依,要么读不到意见 */
|
||||
const fields: Readonly<Record<string, unknown>> = redo?.kind === 'analyze' ? redo.input.fields : {};
|
||||
for (const key of ['last_status', 'last_impact', 'last_evidence', 'last_unknown_disposition', 'reviewer_note']) {
|
||||
@@ -549,8 +562,31 @@ describe('S3 / S4 配方', () => {
|
||||
expect(stepOf('S3_review')?.auto?.let).toBe(stepOf('S2_assess')?.auto?.let);
|
||||
});
|
||||
|
||||
/*
|
||||
* **交代必须排在卡之前**(2026-09-01 用户:「需要把 ai 的修改意见通过右边 ai 聊天窗口展示出来,
|
||||
* 不然都不知道发生了什么」)—— 发了卡这一拍就收了,排在卡后面的 `say` 要等**下一拍**才跑,
|
||||
* 那时人早看完卡了。实测:原来那句「差异结论已送审,请核对」出现在人答完之后。
|
||||
* 两句互斥:被打回那一轮说「按你的意见改了哪一条、改成什么」(摆的是件上那一行自己的
|
||||
* `evidence_note`,不另编一句);第一轮说「结论已备好,请核对」。
|
||||
*/
|
||||
it('打回那一轮的交代排在卡之前,摆的是件上那一行的判断依据', () => {
|
||||
const kinds = s3.map((a) => a.kind);
|
||||
/* **排在卡之前**:发了卡这一拍就收了,排在后面的 say 要等下一拍 —— 那时人早看完卡了 */
|
||||
expect(kinds.lastIndexOf('say')).toBeLessThan(kinds.indexOf('card'));
|
||||
/* 只在被打回那一轮说 —— 第一轮那句与卡自己的 ask 是同一件事,退役了 */
|
||||
const redoSay = s3[7];
|
||||
expect(redoSay?.kind === 'say' && redoSay.when).toBe('case_redo_note != ""');
|
||||
const text = redoSay?.kind === 'say' ? redoSay.text : undefined;
|
||||
const parts = JSON.stringify(text);
|
||||
expect(parts).toContain('按你的意见复核了');
|
||||
/* 摆的是件上那一行自己的话与名字 —— 对话区与件上说的是同一件事,就该是同一句话 */
|
||||
expect(parts).toContain('evidence_note');
|
||||
expect(parts).toContain('parameter_name');
|
||||
expect(parts).toContain('substitution_difference_item_redo_scope_named');
|
||||
});
|
||||
|
||||
it('S3 的卡:审核面孔、单一选项、挂本步的件', () => {
|
||||
const card = s3[7];
|
||||
const card = s3[8];
|
||||
expect(card?.kind === 'card' && card.as).toBe('decide');
|
||||
expect(card?.kind === 'card' && card.variant).toBe('review');
|
||||
expect(card?.kind === 'card' ? card.options ?? [] : []).toHaveLength(1);
|
||||
|
||||
Reference in New Issue
Block a user