修:引擎作用域不得吸入他单事实 + 记录 G2 未分流的排查线索

任务视图铺到顶层的字段,原先取「该对象最新一行」—— 那一行很可能是**别的任务**
放行后的正式版记录。实测:NE555P 的打标读到了上一单 LM358DR 的情报
(historyDays 30 / 在产),被判成 Type A;修正后按自己的事实判成 Type B「重估后报」,
与 P-03 规则一致。

改为只铺**本任务自己写下的**草稿(读己之写),别人的事实仍在 `域.对象` 整表里、
要用得显式取。ledger 门面因此新增 `taskDrafts(taskId)` —— 与 `taskView` 的区别是
它只回我写过的那些行。

顺带记录:A1 已能 released 且节点实例正确落 terminal,但 G2 并行网关未起出
下游 A3 / A2;排查线索写进 PROGRESS.md 待办 1。

gates: tsc / eslint / depcruise(317 模块)/ 393 测试 全绿

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-27 04:39:32 +08:00
co-authored by Claude Opus 5
parent 2b99fd163a
commit 1721bcf6e3
7 changed files with 63 additions and 5 deletions
@@ -0,0 +1,12 @@
{
"messageId": "rfq-020@beta.com",
"from": "buyer@beta.com",
"to": [
"rfq@we.com"
],
"cc": [],
"subject": "【询价】客户 C002 RFQ-20260727K 求报价",
"body": "客户编码 C002,询价单号 RFQ-20260727K。\nLM358DR TI 年用量 20000 目标价 7.90 交期 8w",
"receivedAt": "2026-07-27T11:00:00.000Z",
"attachments": []
}
@@ -0,0 +1,12 @@
{
"messageId": "rfq-021@beta.com",
"from": "buyer@beta.com",
"to": [
"rfq@we.com"
],
"cc": [],
"subject": "【询价】客户 C002 RFQ-20260727L 求报价",
"body": "客户编码 C002,询价单号 RFQ-20260727L。\nNE555P TI 年用量 6000 目标价 3.10 交期 12w",
"receivedAt": "2026-07-27T12:00:00.000Z",
"attachments": []
}
@@ -0,0 +1,12 @@
{
"messageId": "rfq-030@beta.com",
"from": "buyer@beta.com",
"to": [
"rfq@we.com"
],
"cc": [],
"subject": "【询价】客户 C003 RFQ-20260727M 求报价",
"body": "客户编码 C003,询价单号 RFQ-20260727M。\nNE555P TI 年用量 6000 目标价 3.10 交期 12w",
"receivedAt": "2026-07-27T13:00:00.000Z",
"attachments": []
}
+10 -4
View File
@@ -140,10 +140,16 @@ export function wireEngines(deps: EngineWiringDeps): EngineWiring {
offset: 0,
});
scope[`${address.domain}.${address.object}`] = page.rows;
const latest = page.rows[page.rows.length - 1];
if (latest === undefined) continue;
for (const [field, value] of Object.entries(latest)) {
// 空值不盖掉已有事实:没写进去的字段不该把起单入参抹成 undefined
}
/*
* 铺到顶层的只能是**这一单自己写下的**事实(草稿层 = 读己之写)。
* 不能拿「该对象最新一行」来铺:那一行很可能是别的任务放行后的正式版记录,
* 一铺就把别人的结论当成了自己的输入 —— 打标会照着上一单的情报出结果。
* 别人的事实仍在 `域.对象` 整表里,要用得显式去取。
*/
for (const draft of await deps.ledger.taskDrafts(taskId)) {
for (const [field, value] of Object.entries({ ...draft.key, ...draft.patch })) {
if (value !== null && value !== undefined) scope[field] = value;
}
}
+6
View File
@@ -90,6 +90,12 @@ export type LedgerService = {
query(query: LedgerQuery): Promise<LedgerPage>;
/** 任务视图 = 正式版 + 本任务草稿层 */
taskView(taskId: TaskId, query: LedgerQuery): Promise<LedgerPage>;
/**
* **本任务自己写的**草稿条目(读己之写的读面)。
* 与 `taskView` 的区别:那个是「正式版 + 我的草稿」的合并视图,
* 这个只回我写过的那些行 —— 引擎求值要区分「这一单的事实」与「别人放行后的事实」。
*/
taskDrafts(taskId: TaskId): Promise<Array<{ domain: string; object: string; key: Record<string, unknown>; patch: Record<string, unknown> }>>;
/** 落地预检第五项:数据冲突检查 */
checkConflicts(taskId: TaskId): Promise<ConflictFinding[]>;
discardDrafts(taskId: TaskId): Promise<void>;
@@ -204,6 +204,11 @@ export function createLedgerService(deps: LedgerServiceDeps): LedgerService {
return { rows, total: rows.length };
},
async taskDrafts(taskId) {
const drafts = await deps.drafts.list(taskId);
return drafts.map((d) => ({ domain: d.domain, object: d.object, key: d.key, patch: d.patch }));
},
async checkConflicts(taskId) {
const drafts = await deps.drafts.list(taskId);
if (drafts.length === 0) return [];
+6 -1
View File
@@ -113,7 +113,12 @@ DMN 三分类规则 P-03 + 台账声明 + 样例集。depcruise 已实测拦下
## 已知待办(按优先级)
1. **判据 ④–⑨ 逐节点端到端**:A1 释放后 G2 分流已具备条件,A3/A2(loop)、A4、AP、A6、A7 逐条跑。
1. **判据 ④–⑨ 逐节点端到端**:A1 已能到 `released` 且节点实例正确落 `terminal`,
但 **G2 并行网关未把下游 A3 / A2 起出来** —— 工作流停在 A1 之后。
已排除:投递无失败、无异常日志、`selectEdges` 对并行分叉返回全部出边、
`dispatchOf` 对活动节点返回 start-task。下一步从 `advanceFrom` 的实际入参查起
(`onTaskTerminal` 里 `Object.values(ports)[0]` 目前是 `{}`,
`outputPortsOf` 按输出口声明的属性名取值、与台账列名对不上,值得先看这里)。
2. **判据 ③ 的机器路径**:`JCAI_LLM_API_KEY` 现为占位符,LLM 步一律走声明给定的人兜底。
接任一 OpenAI 兼容端点即可验证机器路径;两条缝的 record/replay 也需先有一次 live 录制。
3. **编排画布的手绘编辑器**:只读态(`FlowDiagram`)已接真实流程包;