Archived
人手改的那一手真正落得下去;界面不撒谎那几处补齐
手改是**兜 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:
@@ -95,12 +95,102 @@ export const dmnModelSchema = z.object({
|
||||
});
|
||||
export type DmnModel = z.infer<typeof dmnModelSchema>;
|
||||
|
||||
/**
|
||||
* **步骤剧本** —— 一个计划项一条,把「这一步是什么状态」写成机器读得懂的东西。
|
||||
*
|
||||
* 为什么要有它(2026-07-31 加,起因是 A1 反复空转):
|
||||
* 从前每一拍喂给模型的是**整本说明书 + 全部工具 + 全部可写台账**,
|
||||
* 模型得自己从六步里认出「我现在在第几步」。认对了还好,认岔了就开始转圈 ——
|
||||
* 实测 S1 已经把八字段写齐了,而说明书里 S3 写着「把八字段补到齐」,
|
||||
* 模型于是把同样三行又写一遍,被「写了等于没写」拒回,下一拍再写一遍,如此往复。
|
||||
*
|
||||
* 治法不是把说明书写得更啰嗦,是**把状态挪进引擎**:
|
||||
* ① `doneWhen` 让引擎自己算得出「这一步的成果已经在那儿了」—— 是就直接收掉,
|
||||
* **不问模型**(能算的不问 LLM:同输入必同结论、零 token);
|
||||
* ② `guide` / `writes` / `tools` 让每一拍的上下文**只装当前这一步要用的东西** ——
|
||||
* 上下文小了,模型跑偏的余地也就小了。
|
||||
*
|
||||
* 不写剧本的活动照旧跑(整本说明书 + 全部工具),只是没有这两样好处。
|
||||
*/
|
||||
export const planStepSchema = z.object({
|
||||
/** 对应 CMMN 里的计划项 id —— 对不上的条目安装期即拒 */
|
||||
item: z.string().min(1),
|
||||
/** 一句话:这一步交出什么 */
|
||||
intent: z.string().min(1),
|
||||
/** 这一步的做法(从说明书里搬过来的那一段)—— 只在轮到它时进上下文 */
|
||||
guide: z.string().min(1),
|
||||
/** 这一步可写哪几个台账地址「域.对象」;空 = 这一步不写台账 */
|
||||
writes: z.array(z.string()).default([]),
|
||||
/**
|
||||
* 这一步**要读哪几个台账地址** —— 与 `writes` 对称,同样是「域.对象」。
|
||||
*
|
||||
* 为什么非声明不可:`域.对象` 整表那一段进提示词前会**按字符截断**
|
||||
* (整表里躺着历史所有已放行单的行,只会越来越长,不截会把上下文吃光)。
|
||||
* 截断是盲的 —— 砍掉的可能恰是这一步要用的那张表。实测:A1 第一步要拿发件邮箱
|
||||
* 去 \`customer.contact\` 认客户,而这一单的来函正文与 BOM 附件就占了近 2000 字,
|
||||
* 客户联系人表整个落在刀口外;模型看不见,只能报「主数据里没找到」,
|
||||
* 于是老客户被当成新客户 —— **而库里那一行一直好端端在**。
|
||||
*
|
||||
* 声明了的表**排在最前且不参与截断**:这一步该看见的,一定看得见。
|
||||
*/
|
||||
reads: z.array(z.string()).default([]),
|
||||
/**
|
||||
* 这一步的**工作区画面**(视图模版名)—— 人办这一步时看的那份件。
|
||||
*
|
||||
* 不写就由模型临场挑。而「这一步该看哪张」是**写清单时就定死的事**:
|
||||
* 阶段二派执行单,人要看的是那份询价受理需求;模型挑了「缺口清单」,
|
||||
* 人拿到的就不是那份件了(实测:两份目标件都在包里,推出来的却是旧的那张)。
|
||||
* 画面归活动定,不归模型临场发挥 —— 模型仍可用 `say.view` 换画面,
|
||||
* 但**没换的时候按这里推**,而不是不推或推上一张。
|
||||
*/
|
||||
view: z.string().optional(),
|
||||
/** 这一步可调哪几件工具;空 = 这一步不调工具 */
|
||||
tools: z.array(z.string()).default([]),
|
||||
/**
|
||||
* **这一步算干完了没有** —— 对任务视图求值的 S-FEEL 谓词。
|
||||
*
|
||||
* 真了引擎就自己把这一项收掉,不问模型。所以它必须是「成果已存在」的判据,
|
||||
* 不是「该不该做」的判据:写成 `missing_key_total = 0` 这种**开局就为真**的式子,
|
||||
* 会让那一步在还没干之前就被收掉。
|
||||
*
|
||||
* **`X != null` 是个坑**:S-FEEL 里未绑定的名字 `!= null` 求值为 **true**,
|
||||
* 写它等于让那一步开局即收。要判「这个键写过没有」,用正向式子(`X >= 0`);
|
||||
* 布尔列更要绕开 —— 它合法值含 false,拿它分不清「没写」与「写了 false」,
|
||||
* 该改判同一步写下的计数列。
|
||||
*/
|
||||
doneWhen: z.string().optional(),
|
||||
});
|
||||
export type PlanStep = z.infer<typeof planStepSchema>;
|
||||
|
||||
/**
|
||||
* 阶段 —— **给人看的进度刻度**,引擎一眼都不看。
|
||||
*
|
||||
* 计划项是给引擎的:一件事拆到能判「干完没有」的粒度,A1 有六项。
|
||||
* 可六格进度条对人没有意义 —— 「查历史价 / 打标 / 定去向」在业务上是**一件事**
|
||||
* (判这单该怎么走),人关心的是「到哪一步了」,不是引擎拆了几项。
|
||||
* 所以另立一层:几个计划项合成一个阶段,进度条按阶段走。
|
||||
*
|
||||
* **只声明激活态的阶段**。结束态不在这里 —— 每个活动都以放行收口(铁律③),
|
||||
* 那是系统的规矩不是活动的阶段;进度条自己在末尾加这一格。
|
||||
*/
|
||||
export const casePhaseSchema = z.object({
|
||||
/** 阶段名 —— 进度条上显示的就是它 */
|
||||
name: z.string().min(1),
|
||||
/** 这一阶段含哪几个计划项(CMMN item id);**全收完** = 这一阶段过了 */
|
||||
items: z.array(z.string().min(1)).min(1),
|
||||
});
|
||||
export type CasePhase = z.infer<typeof casePhaseSchema>;
|
||||
|
||||
export const loopModelSchema = z.object({
|
||||
/** 案例模型 · 机器面:CMMN XML,语义引擎以它为运行结构 */
|
||||
cmmnXml: z.string().min(1),
|
||||
/** 案例模型 · 叙事面:说明书,与 XML **同版本发布,不允许分叉**(AM 12.2) */
|
||||
narrative: z.string().min(1),
|
||||
dmn: dmnModelSchema,
|
||||
/** 步骤剧本:一个计划项一条(见 `planStepSchema`);**不写照旧跑**(整本说明书 + 全部工具) */
|
||||
steps: z.array(planStepSchema).optional(),
|
||||
/** 阶段:进度条的刻度(见 `casePhaseSchema`);**不写就没有进度条**,不编 */
|
||||
phases: z.array(casePhaseSchema).optional(),
|
||||
});
|
||||
export type LoopModel = z.infer<typeof loopModelSchema>;
|
||||
|
||||
@@ -186,6 +276,9 @@ export const staticAuditFindingSchema = z.object({
|
||||
'dynamic-eval',
|
||||
'ledger-type-conflict',
|
||||
'acceptance-level-misreported',
|
||||
'acceptance-predicate-unbound',
|
||||
'deliverable-address-unbound',
|
||||
'ledger-kind-invalid',
|
||||
]),
|
||||
severity: z.enum(['error', 'warn']),
|
||||
message: z.string(),
|
||||
|
||||
Reference in New Issue
Block a user