人手改的那一手真正落得下去;界面不撒谎那几处补齐

手改是**兜 AI 的错**的那一手 —— 这一轮把它从「摆在那儿但落不了地」做成真的:

件上就地改
· 保存**按地址收**,不看当下那张卡:载荷从前借道工单的 `blocks[i]` 取列名,
  于是熔断卡(没有 blocks)在屏上时,人补的那一格一个字都送不出去 ——
  而他要补的恰恰是把这一单卡住的那个必填格。授权面改由活动清单的台账声明把关。
· **能增删行**:错不止「这一格填错了」,还有「这一行不该在」与「漏了一行」。
  删挂记号不当场抹掉(看得见、可后悔),且**删要说出来**(`drops`)——
  「没回传就是删了」会把一次不完整的回传变成一次删表。
· **必填没填按不下提交**:与放行门 L1 同一个数同一套算法;闸上摆出差在哪一行哪一格。
· 只写真改了的那几行 —— 改一格却留「修订 4 行」的痕,那句话是假的。

判据与门
· 裁量判据带谓词时**谓词说了算**:「选填缺口已补齐」基座数得出来,
  人填好的目标价它照样判「客户未提供」的毛病由此消掉。
· 验收卡判据**读时现算** —— 人在成果件上补一格,判据跟着变。
· 放行门认「**办完了没有**」不认「有人写过」:从前写个 `false` 就把门推开,
  于是一单没打标就进了放行门。三个数全由基座现数。
· 拒回把「活没干完」说成「数或行对不上」的毛病:判据点名的表一行都没写时直说那一步没办。
  **指向两扇打不开的门,比不指还糟。**

界面不撒谎
· 日志只有三色:负责人绿 · 智能体蓝 · 系统灰(归侧五种是度量的分法,不是给人看的)。
· 验收收口答两件事:落了什么(按**交付物**点名,一份成果的几张表并成一行)、
  往哪儿去(转出哪一口、带过去哪些字段);一个口都没发就直说到此为止。
· 签完到收尾之间那一段有自己的话「字已签下,正在落地」—— 中间态本来就该说出来,只是要说对。
· 消息不再被内部事件刷屏:只有从通道进来的件才谈得上「无人认领」。
· 建客户公司与联系人**一次确认落两行**;联系人编码自增不问人;卡面摆表的人读名。

A1 三案例端到端全 released:全 A 类直通 12 拍 / 客户点名跳一条 10 拍 / 新客户缺必填 14 拍。
五道门禁全绿(971 passed)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
This commit is contained in:
2026-08-02 13:41:44 +08:00
co-authored by Claude Opus 5
parent 94f1c7a4ef
commit 259192f736
228 changed files with 27850 additions and 2847 deletions
@@ -28,19 +28,20 @@ describe('planConsumption —— 三级消费', () => {
triggerHits: ['tr1'],
ownedTaskId: 't1',
hasOwner: true,
fromChannel: true,
});
expect(plan.taskTargets).toEqual(['t1']);
expect(plan.triggerTargets).toEqual(['tr1']);
expect(plan.messageFallback).toBe(false);
});
it('皆未命中且无主 → 消息兜底', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: undefined, hasOwner: false });
it('**入站件**皆未命中且无主 → 消息兜底(系统自己发的不算,见下面那组)', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: undefined, hasOwner: false, fromChannel: true });
expect(plan.messageFallback).toBe(true);
});
it('有主但零监听命中 → 仅记录,不兜底、不降级为无主', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: 't7', hasOwner: true });
const plan = planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: 't7', hasOwner: true, fromChannel: true });
expect(plan.messageFallback).toBe(false);
expect(plan.recordOnlyTask).toBe('t7');
expect(plan.taskTargets).toEqual([]);
@@ -54,6 +55,7 @@ describe('planConsumption —— 三级消费', () => {
triggerHits: [],
ownedTaskId: undefined,
hasOwner: true,
fromChannel: true,
});
expect(plan.messageFallback).toBe(false);
expect(plan.recordOnlyTask).toBeUndefined();
@@ -65,12 +67,19 @@ describe('planConsumption —— 三级消费', () => {
triggerHits: [],
ownedTaskId: 't7',
hasOwner: true,
fromChannel: true,
});
expect(plan.recordOnlyTask).toBeUndefined();
});
it('无主但触发命中 → 不兜底', () => {
const plan = planConsumption({ listenerHits: [], triggerHits: ['tr1'], ownedTaskId: undefined, hasOwner: false });
const plan = planConsumption({
listenerHits: [],
triggerHits: ['tr1'],
ownedTaskId: undefined,
hasOwner: false,
fromChannel: true,
});
expect(plan.messageFallback).toBe(false);
});
});
@@ -96,3 +105,36 @@ describe('deadlineMillis —— 监听时限必配', () => {
expect(() => deadlineMillis('PT0S')).toThrow(/大于零/);
});
});
/**
* **消息兜底只兜从外面进来的件**(2026-08-02 用户:「消息怎么总莫名其妙的出内容」)。
*
* 「无主入站待认领」是件具体的事:一封信进来了,没匹配上任何单也没触发任何流,
* 得有个人去认领它。而系统自己发的事件不是这种东西 —— 台账写一行会发 `data` 事件,
* 没人监听它是**常态**,不是待办。
*
* 不分这一刀的实测下场:装一次活动包(主数据 systemWrite)就往三个人的收件箱里
* 塞了十几条「无主入站待认领:(无主题) … 原件:无」—— 没有主题、没有原件、
* 没人能对它做任何事。那不是待认领的件,是一条内部广播。
*/
describe('消息兜底:只兜入站件', () => {
const plan = (over: Partial<Parameters<typeof planConsumption>[0]> = {}) =>
planConsumption({ listenerHits: [], triggerHits: [], ownedTaskId: undefined, hasOwner: false, fromChannel: true, ...over });
it('一封信进来、谁都没接住 → 该有人认领', () => {
expect(plan().messageFallback).toBe(true);
});
it('**台账写一行发的事件谁都没接住 → 什么也不做**(它不是件)', () => {
expect(plan({ fromChannel: false }).messageFallback).toBe(false);
});
it('接住了就不兜底 —— 监听命中或触发命中,任一即可', () => {
expect(plan({ listenerHits: [{ taskId: 't1' }] }).messageFallback).toBe(false);
expect(plan({ triggerHits: ['tr1'] }).messageFallback).toBe(false);
});
it('有主的件不兜底 —— 那是「主不是任务」,不是没人认领', () => {
expect(plan({ hasOwner: true }).messageFallback).toBe(false);
});
});
@@ -66,6 +66,22 @@ export function planConsumption(input: {
* 把它们判成无主,等于把每次起单都当成「没人认领的入站件」塞进别人收件箱。
*/
readonly hasOwner: boolean;
/**
* 这条事件**是从外面进来的件**吗 —— 只有它才谈得上「无人认领」。
*
* 「无主入站待认领」是一件具体的事:一封信进来了、没匹配上任何单也没触发任何流,
* **得有个人去认领它**。而系统自己发的事件不是这种东西:
* 台账写一行会发 `data` 事件、引擎起一单会发工作流事件 ——
* 没人监听它们是**常态**,不是待办。
*
* 不分这一刀的下场实测过(用户 2026-08-02:「消息怎么总莫名其妙的出内容」):
* 装一次活动包(主数据 `systemWrite`)就往三个人的收件箱里塞了十几条
* 「无主入站待认领:(无主题) —— 事件 6d17debb… 未命中任何任务监听与触发器。原件:无」。
* 没有主题、没有原件、没人能对它做任何事 —— 那不是待认领的件,是一条内部广播。
*
* 判据取**来源**不取类型:同样是 `data`,从通道进来的是件,台账写出来的是事实。
*/
readonly fromChannel: boolean;
}): ConsumptionPlan {
const taskTargets = fanOutTargets(input.listenerHits);
const triggerTargets = [...new Set(input.triggerHits)];
@@ -73,8 +89,8 @@ export function planConsumption(input: {
return {
taskTargets,
triggerTargets,
// 有主但零监听命中 → 仅记录,不兜底;消息只兜**真正无主**的件(OS 6.3)
messageFallback: nothingHit && !input.hasOwner,
// 有主但零监听命中 → 仅记录,不兜底;消息只兜**真正无主的入站件**(OS 6.3)
messageFallback: nothingHit && !input.hasOwner && input.fromChannel,
recordOnlyTask:
input.ownedTaskId !== undefined && !taskTargets.includes(input.ownedTaskId)
? input.ownedTaskId
@@ -51,6 +51,8 @@ export function createEventService(deps: EventServiceDeps): EventService {
triggerHits,
ownedTaskId,
hasOwner: envelope.correlation.target !== undefined,
// 只有**从通道进来的件**谈得上「无人认领」—— 台账写一行发的 data 事件不是件
fromChannel: envelope.source.kind === 'channel',
});
// 扇出:每个命中目标一份独立投递,信封「关联 = 单目标」保持单目标