@sema-agent/client-core 0.72.11 → 0.72.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -49,6 +49,32 @@
49
49
  > 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
50
50
  > commit 漏转在发布前就红,不再靠人记。
51
51
 
52
+ ## 0.72.12(2026-09-18)
53
+
54
+ > 主题:**「缺席被折成正向终态」病形按类清剿**(test 证据帖 [7541] + sema-internal #59 M1 / #64 M6,owner:client-core;表态 [7543];CC-50 P1 + CC-51)。头条 = 本包 `fleetAgentPanelProjection` 缺席兜底把「引擎不再上报这一行」铸成 `end{isError:false}` ⇒ cli 屏上 `✔ Completed`(两条现场腿秒级实测)。**patch**:型面 additive(`EngineAgentPanelEvent` 新臂 `absent`、`WorkflowRunState.status` / `WorkflowPhase.status` 各加 `'unknown'`、结果帧新超集键 `_sema_outcome`、+2 常量 +2 函数,公面 989 → 993;peer 不动);**行为面有三处刻意的真变化**,逐条在「取舍」段。接入面 §59。
55
+
56
+ ### Changed
57
+
58
+ - **头条(CC-50 M1):fleet 行缺席不再 settle、不再铸 `end{isError:false}`** —— `projectFleetAgentRows` 的缺席路径改发第三态事件 **`{ kind:'absent', taskId, lastSeenAtMs, absentForMs }`**(A 形,[7543] ②;`EngineAgentPanelEvent` additive 新臂),行保持未结局;真终态帧迟到照发那**唯一一次** `end`(缺席不再占用去重记号 —— server [7545]:子行随父 run 离场按 `orphaned` 移除,真终局由后续对账周期补发,结构性晚于本包 30 s 窗);行回来照发 `fleet-row`(即使值未变,消费端据此撤 absent 标);已上报 absent 且不再在场的条目按上报时刻 + 回收期回收,回收后迟到终态仍恰一次 `end`。`ABSENT_SETTLE_MS` 名字沿用(公面导出),语义改为「缺席上报窗」。消费端义务:认得 `absent` ⇒ 渲「engine no longer reports this agent · outcome unknown」并停表,**不许**翻译成 completed / failed / stopped;认不得(老壳,三臂无 else)⇒ 行停在最后已知态 —— 可被证伪的「不知道」,不是 Completed。🔴 边界:`agent.status` / `isError` 的值域**一字不改**(壳详情页头的 catch-all else 会把任何第三个词渲成 Stopped,test 亲读)。panel store 把 `absent` 按进度类缓冲(同行合并、满了先让位)。pure 门 ③ 段改钉 + 9 格、honesty F13 反转(迟到终态**必须**发那一次 end)。
59
+ - **六站一次改齐,规则只有一条:「缺席 / 解不出 / 非串 / 认不出的词 ⇒ `unknown` 位,绝不落 completed / success / running」**(#59 A-05 / A-06 / A-07 / A-08 / A-12 / A-17;#64 A-28):① `TaskOutput` structured 腿 `retrieval_status:'success'` 但无 status 且模型面解不出 ⇒ `task.status:'unknown'`(此前 success ⇒ completed 两级连折;`not_ready` / `timeout` 仍 running —— 那是引擎的正向证据);② legacy 腿模型面解不出 status ⇒ `unknown`;③ `parseWorkflowPollEnvelope` 缺 status ⇒ `unknown`(此前 completed,且 `completed ∈ WF_TERMINAL` 顺手 `markEngineWorkflowNotified` 把补发通道缴械 —— 现在零调用);④ `normalizeTaskNotification` / `taskNotificationDedupKeyFromWire` 缺 status ⇒ `unknown`,summary 改说 `Background task "<id>" reported without a status (outcome unknown)`,去重键 `:unknown` 不与真 completed 同桶;⑤ `createBackgroundView` 200 回体缺 `tasks` 键 ⇒ 源健康位 `unavailable`(此前 ok + 空表);⑥ `projectWorkflowRun` run / phase 状态 `default` 臂 ⇒ `'unknown'`(此前 `'running'`;`WorkflowRunState.status` / `WorkflowPhase.status` 联合各 +1 additive),`coerceWorkflowStatus` 未知词 ⇒ `idle`(FleetTaskStatus 是 wire 闭集无 unknown 位,与同文件 `coerceTaskStatus` 同律);pure 门 ⑩ 段 13 格 + 三处旧判据改钉(它们此前**钉住的正是病形**)。
60
+ - **结果边界(#59 A-12,「取舍」段第 1 条)**:`terminalToSdkResult` 对 **终态记录整个缺席**(`readRunTerminal` 返 `null`)不再落 `success` 臂 —— 改 `error_during_execution` + `is_error:true` + additive **`_sema_outcome:'unknown'`** + `errors[0]` 逐字「run ended with no terminal record — outcome unknown, not a failure verdict (…treat the result as unverified)」;认不出的终态词那臂同带该旗(句子仍报出那个词)。🔴 **稀疏**:真 completed / 真 failed 帧不带此键(G2-e)。**包内消费者同 commit 落下**(test [7541] G2-d,「铸了就要有人读」):`runStream` 终局臂读结果帧上的旗,合成一行 **`Outcome unknown: <同一句>`**(第三条中性终局行身份;`OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText` 导出,只认行首;行类旗 `isApiErrorMessage` 置位同 `Model output error:` 行),壳零接线即用户可见面有差异;合成终态行收成单铸点 `syntheticTerminalRow`(铸链数不增)。type-superset +1 = 55;identity-copy 门 G1d 七格。
61
+ - **反钉 = 以点扫面的门,不是六个站点门**:新门 **`run-absence-fold-census-test.mjs`**。病形锚在**兜底位置的值**(函数尾无条件 return / 所有已知臂不匹配的 default / 没有词可传时铸的字面 / 异常路径的返回值):**兜底位置只许 `unknown` 或诚实缺席,不许任何正向词**;语法形只是检出手段。检出走 **AST**(不看注释与字符串,多行写法不漏)五形:M1a `??` / `||` 右臂正向终态词 · M1b 三元 **else 臂**正向终态词(任意条件)· M6 显式 `default:` 首 return 正向词 · M2 `catch` 块首 return `true / [] / {}` 与 `.catch(() => 健康值)` 箭头形 · M0 函数尾无条件 return 正向词且函数内另有 return。存量登记 `scripts/absence-fold-baseline.json` 今日 **5 条**各带 why(`detachWire` fail-soft 版本闸候 CC-53 三态 / `coerceAgentState` default ⇒ progress:`AgentState` = CC atlas WPe 输入词表 EXACTLY —— **声明的限制** / `backgroundView` `… : 'ok'` 有「刚成功拉到列表」的正向证据 / `scratchpadWireCaps` catch ⇒ `{}` = 不发可选键的诚实缺席 / `toolResult` `retrieval_status` else 臂 `success`:CC 闭集无第三格且有「调用已返回」的正向证据),未登记命中红且点名 file:line,登记数 = 实际数(虚高也红);判别力自证走**围栏**(任一形负控不过 ⇒ 门拒绝出数):五形逐形注入内存副本各多报恰一处 + 两个正确写法回归钉(`{ kind:'completed' }` / `case 'x': return 'done'`)+ 注释与字符串不算;头条反钉(AST:零 `isError: false` 属性赋值、`kind:'absent'` 恰一处)。门 AST 化后**自扫出两处同类**一并修:`projectWorkflowRun` 合成阶段 `synthPhaseStatus` 尾三元与 `bucketStatus` 空桶仍折 `running`(无活跃证据 ⇒ `unknown`;腿上 park 仍压过 run 级 failed)、TaskOutput 腿的 `retrieval_status` 是 **CC 同名键**(闭集 success / timeout / not_ready;老壳卡片 success 才展示正文、not_ready 渲「still running」):闭集里没有「不知道」,绝不塞第四个词 —— 认不出 / 缺席 ⇒ `success`(正向证据 = 这份 structured detail 是一次已返回的取回调用的产物),「结局不知道」由 `task.status:'unknown'` 承载(登记在普查基线带 why);`task.status` 只在引擎**亲口**说 not_ready / timeout 时回落 running。负控套 +1(19/19)。`docs/DISEASE-SHAPES.md` **DS-06** 入册。
62
+
63
+ ### 取舍(三处真行为变化,不是「纠正疏忽」;test [7541] 直讯三轮互收执)
64
+
65
+ 1. **SDK 结果边界 fail-closed**:CC `subtype` 闭集没有第三格,边界上必须给一个终局。误报错的代价 = 用户多跑一次;误报成功的代价 = 用户信一份坏产物 ⇒ 取前者,并用 `_sema_outcome:'unknown'` + 逐字句子把「这不是失败判决」说出来。此前「零行为变化」维持 success 的那一路(mock 车道 / 不带终态词的旧合成帧)**从 success 翻成 error**;要成功请在帧上带真终态词(`status:'completed'` 或 `terminal:{kind:'completed'}`)。
66
+ 2. **缺席不再 settle**:老壳上离场的行不会自己消失(回收由本包台账侧照旧,只是不发 `end`),行停在最后已知态直到真终态帧或壳认得 `absent`。
67
+ 3. **通知 / 去重键 / TaskOutput 状态位的第三个词 `unknown`**:渲染面按开集读的端零变化;按闭集 switch 的端会走 default —— 请勿把 default 渲成正向词(那正是 #64)。
68
+
69
+ - **异源对抗复审四轮,下游兼容六条全部真修**:① `retrieval_status`(见上)两个中间版本都被打回 —— 原词透传 / 铸 `unknown` 会让老壳把已完成的 final answer 渲成 Task not ready;按 structured 两键推 `not_ready` 漏了模型面文本回落取得的终态与正文,且 `not_ready` 在老壳上 = 假「仍在运行」(pure ⑩ S9 六格含该复现形);② `taskNotificationDeliverySupplement` 尾模板对任何词都说 `already finished`,与同批新铸的 `unknown` 合成出假终局 ⇒ 只对**通知自己的终态词**(新单源 `TASK_NOTIFICATION_TERMINAL_STATUSES` / `isTaskNotificationTerminalStatus`,住在词表属主 `runTerminal.ts`:core `TaskNotificationStatus` 四终态 completed / failed / killed / cancelled;`event` 非终态;不借 run 级词表 —— 那张没有 cancelled)说 finished,其余说「state this client cannot confirm … outcome is unknown here」(S10 三格);③ run 状态词认不出 / 缺席但腿上有活跃证据 ⇒ run 级按证据说 `running`(老壳用 `status === 'running'` 算 workflowActive),零证据才 `unknown`,不拿「腿全做完」反推 run 完成(S11);④ 合成阶段保留腿上的 error 证据:同一组腿有无 phase 标签,阶段状态一致(error + progress ⇒ 阶段 failed、run 仍 running;S12)。
70
+
71
+ ### Known limits(本版新增)
72
+ - run 状态词认不出且腿上**零活跃证据**时 run 级为 `unknown`:尚未认 `unknown` 的壳按 `status === 'running'` 算 workflowActive ⇒ 该 run 下 inactive 的腿会显示为 Stopped(此前显示 running,两者都不是事实);壳半场按 §59 S-4 接 `unknown` 后消失。
73
+ - 普查门 AST 五形**不覆盖**:`if / else if` 链最后一个 `else` 里的 return、带插值的模板字面量(本版 `taskNotificationDeliverySupplement` 即此形,已人工修)、解构 / 参数默认值;加检出形不改规则(DS-06)。
74
+
75
+ - `coerceAgentState`(workflow agent 行)default 仍 ⇒ `progress`:`AgentState` 是 CC atlas WPe **输入词表 EXACTLY**,没有 unknown 位可落;run / phase 两级已落 `unknown`。登记在 `absence-fold-baseline.json` 带 why,候 CC 词表或另铸 additive 位。
76
+ - `fleetAgentPanelProjection` 的 `row.status ?? 'running'` 是**内部**终态判用的占位(fleet-row 事件不带 status),不上屏;`row.tokens ?? 0` 属 M4(#62 A-18)归 CC-52(0.72.13)。
77
+
52
78
  ## 0.72.11(2026-09-18)
53
79
 
54
80
  > 主题:**core 7.23.0 提货**(发车帖 [7537] / 提货单 [7538] @client-core 段:镜像一件 + 加法三件 + 零动作两件;CC-49)。**patch**:型面零变化(通告闭集 +1,零新导出;公面 989 不变;peer 不动;devDep core `~7.23.0`)。接入面 §58。
package/README.md CHANGED
@@ -35,7 +35,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
35
35
 
36
36
  ## Scope
37
37
 
38
- **Version:** 0.72.11
38
+ **Version:** 0.72.12
39
39
 
40
40
  - **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
41
41
  B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
@@ -311,6 +311,7 @@ public-surface guard checks that last one).
311
311
  | `scripts/run-export-liveness-test.mjs` | Every runtime export in the public baseline must be **alive**: referenced by some gate, or explicitly registered in `scripts/export-liveness.json` as `contract` (consumed by a client with no gate yet), `internal` (an internal helper amplified onto the public surface by `export *`), `candidate` (with ticket + retire-by) or `retire` (dead; retire-by version). Registration is accounting, not exemption: a row for a name a gate already references is stale and must go, a row for a name no longer exported is red, `retire`/`candidate` rows go red the moment `package.json` reaches their retire-by version, and the row count only ratchets down. When the sibling client trees are on disk the consumption evidence is checked by name — a `contract` row's claimed consumers must equal the real set, and a `retire` name must not be imported by any client. Names that have already left the surface are kept in a per-version `removed` ledger: they must never reappear in the baseline or the registry, and the ledger's versions must not run ahead of the changelog. |
312
312
  | `scripts/run-tool-disclosure-progress-projection-test.mjs` | The two wire arms sdk 9.6.0 adds — `tool_disclosure` (name-only tool census: open-set `policy`, `thresholdPercent` absent ≠ default, `deferred`/`activated` full snapshots) and `tool_progress` (one frame, two beats: Bash ticks carry an output tail with `totalLines`/`totalBytes` that come and go together; other tools carry only `elapsedSeconds`) — project to neutral internal arms plus chrome arms. Required keys missing ⇒ `malformed`; bad optional keys drop only themselves; the sub-flow three-key gate keeps child frames off the leader lane; both arms are `required: false` in the arm table with duties stated (the output tail is untrusted raw and must never be fed back to the model). |
313
313
  | `scripts/run-mcp-panel-projection-test.mjs` | The `GET /v1/sessions/:id/mcp` panel reader (`projectMcpPanel`; server >=7.77.0 adds the optional `lastLegMcp` key) and the single wording mint for its "last leg" line. Absence of `lastLegMcp` is one literal sentence that never blames the engine version (a new session, a leg outside the retention window, a leg without a manifest and an older engine all look the same on the wire); a key that is present but unreadable is a different sentence plus a `lastLegMcpUnreadable: true` mark, never folded into absence. The `mcp[]` roster goes through the same reader as the live `wiring_manifest` third section, so a replayed roster and a live one have one shape. The two faces of the panel (`servers[]` and the last-leg roster) may legitimately differ, so the view carries no agreement flag and none of the five sentences mentions `servers`. Required keys are pinned to the SDK `openapi.yaml` component bytes **0.69.0:** `fetchMcpPanel` fetches the panel through the SDK client's own `sessions.mcp` call (same transport and auth as every other read) and projects it; transport failure, an unreadable body and an empty session id all come back as `undefined`, never as a fabricated empty panel 0.71.0 adds section K: `mcpEngineLegPresence(view)` — the engine-side MCP presence tri-state read only off the panel view (`unknown` when the view could not be read, never rendered as "no MCP configured") |
314
+ | `scripts/run-absence-fold-census-test.mjs` | A package-wide census of the "absence folded into a positive outcome" defect shape, so that fixing the six sites this release does not merely move the shape somewhere else. The defect is defined by position, not syntax: a fallback position (the unconditional tail return, the `default:` arm, the literal minted when there is nothing to pass on, the value returned from an error path) may only say `unknown` or stay absent, never a positive word. Detection walks the syntax tree of every source file, so comments, strings and multi-line spellings cannot hide or fake a hit, and covers five forms: the right arm of `??` / `||`, the else arm of a ternary, the first return of an explicit `default:`, a `catch` block or `.catch(() => …)` arrow returning a healthy value, and a function whose last statement returns a positive word after other returns. Every remaining hit must be registered with a written reason, an unregistered hit fails the gate naming the file and line, the registered count must equal the real count so a cleared site cannot leave a spare allowance behind, and the gate proves its own teeth behind a fence (a failed self-proof refuses to report any count): each form injected into an in-memory copy must add exactly one hit, two correct spellings are pinned as non-hits, and samples inside comments or strings do not count. It also pins the headline site: the fleet panel projection no longer mints an `end` with `isError: false` on absence |
314
315
  | `scripts/run-leader-conflict-test.mjs` | The leader-run terminal `needs_human` + `result.conflict` (engine ≥7.83.0), read once for all three shells. A `result` without a `conflict` key is reported as `none` and worded as "no conflict details" rather than "no conflict": on the wire it is indistinguishable from an older engine that never reports one, and the reader does not pick a side. A `conflict` that is present but unreadable is a third word, never folded into `none`, because a tree that carries conflict markers must not be rendered as clean. `filesTruncated` is honoured only as `true` (absent means the list is complete; any other value makes the section unreadable), `workers[].applied` is passed through as the boolean fact it is, `salvaged[].patch` is handed to the save path byte-for-byte (an artifact, not screen text; a malformed row is dropped alone, and a salvage list that is present but cannot be fully read is flagged rather than rendered as "no patches"), and `rejHead` — the one on-screen diagnostic — is escaped and bounded before display. The record never throws on hostile input, extra members do not cross, arrays are fresh copies, and the single sentence minted here names the base, the files, which branches landed and which did not, and how many patches can be saved, without ever suggesting a retry: `needs_human` is a run waiting for a person, and the no-details sentence says plainly that it is not proof of a merge |
315
316
  | `scripts/run-mcp-reconnect-test.mjs` | The in-session MCP re-dial verb (`POST /v1/sessions/:id/mcp/reconnect`, engine ≥7.85.0), consumed. The single discriminant is `outcome` and all three answers are HTTP 200, so the reader branches on the word and never on the status; the `unsupported` answer carries exactly five keys and the reader refuses to invent a zero or an empty list for the four fields the engine did not produce, while `accepted` / `refused` treat those four as required and go malformed when one is missing. The tool roster follows the **presence** of `toolNames` (absent = untouched, empty = withdrawn), the connection record passes `errorCode` through as an open set, and every remote-authored string is sanitised and bounded before display. Failures are classified by `errorCode` alone, a missing code is reported as unknown rather than guessed, the verb never throws, and the request-side guard (non-empty name, ≤190 chars) stops a call that the contract would reject anyway. The capability bit reads absent as "cannot tell" rather than "unavailable", and the one sentence the contract insists every UI carries — that re-dialing is a transaction, not a refresh — is minted here once |
316
317
  | `scripts/run-core-value-ports-test.mjs` | The port-injection seam for ten **engine value-level** facilities (autonomous-loop prompt assembly, permission-rule loosening, tool-policy composition, protocol/retired-name/grammar lookups, rule compilation, the discussion workflow name). This package cannot re-export them (the engine barrel drags Node built-ins into the browser bundle), so it declares the ports and honest-absence readers; a Node host installs the engine's own functions verbatim. The guard pins: every reader returns `undefined` when nothing is installed (never a fabricated empty array or default policy), arguments and results pass through by reference, engine errors propagate unchanged, partial installs read partially, restore functions unwind to the previous bag, and the module source has zero engine imports |
@@ -59,8 +59,9 @@
59
59
  * unknown — → 'error_during_execution' true(防御:
60
60
  * 非 completed 的终局一律≠空成功;errors[] 里如实报出那个词的字面。**因由座在场
61
61
  * 却整个读不出**(坏形/混合载体)也落这一臂,措辞改说「读不出」而不是编一个词)
62
- * 〈整个缺席〉 — → 'success' false
63
- * (mock 车道 / 不带终态词的旧合成帧;读器返 null,零行为变化)
62
+ * 〈整个缺席〉 — → 'error_during_execution' true(0.72.12 CC-50:
63
+ * (mock 车道 / 不带终态词的旧合成帧;读器返 null) fail-closed 取舍 + `_sema_outcome:'unknown'`;
64
+ * 此前落 'success' = 把「没有终态记录」编成成功;unknown 臂同带该标记)
64
65
  *
65
66
  * errorCode 透传:引擎的码骑 additive seam 字段 `errorCode`(CC schema 无此字段——与 success 臂的
66
67
  * `model` 同款超集姿势),集成面可精确分流(limits.max_tokens_exceeded vs cancelled …)。
@@ -739,6 +739,8 @@ function errorResult(ctx, parts) {
739
739
  // ADAPTER-F4:具名 additive 位(见 `ErrorResultParts.salvagedResult`)。展开的是**一个已知键**,
740
740
  // 覆写不到上面任何一个不变量;要加第二个位必须动这里,而动这里在 diff 里显形。
741
741
  ...(parts.salvagedResult !== undefined ? { result: parts.salvagedResult } : {}),
742
+ // CC-50:结局不知道的稀疏标记(见 `ErrorResultParts.outcomeUnknown`);真终局帧永不带。
743
+ ...(parts.outcomeUnknown === true ? { _sema_outcome: 'unknown' } : {}),
742
744
  });
743
745
  }
744
746
  /** `done` → SDKResultSuccess (contract 02 §2.10 / 08 CS-10). */
@@ -783,8 +785,8 @@ observed) {
783
785
  // 🔴 0.60.0(engine ≥7.64.0 / sdk 8.4.0):终局分流的判据从**八个平面键**换成**一条带标因由**
784
786
  // (`result.terminal`)。读法单源在 `runTerminal.readRunTerminal` —— 本文件一个 `status` 字面
785
787
  // 都不再比较(平面形的两个来源、以及「不认识的终态词绝不落成功」那条不变量,全在读器里)。
786
- // `null` = 这份载体上连终态词都没有(mock 车道 / 不带 status 的旧合成帧)⇒ 维持成功臂,
787
- // 与形变前逐字节同行为。
788
+ // `null` = 这份载体上连终态词都没有(mock 车道 / 不带 status 的旧合成帧)⇒ 0.72.12 起 fail-closed +
789
+ // `_sema_outcome:'unknown'`(此前维持成功臂;取舍见 `ErrorResultParts.outcomeUnknown`)。
788
790
  const terminal = readRunTerminal(rRaw);
789
791
  const durationMs = elapsedMs(ctx);
790
792
  // [909]B1 — errorCode 透传(additive seam 字段;CC schema 无此键,与 success 臂 `model` 同款超集
@@ -892,11 +894,26 @@ observed) {
892
894
  // [909]B1 — 防御臂:四臂之外的未知终态词(core 未来加因由臂 / 未知 wire 变形)绝不洗成空成功
893
895
  // —— error_during_execution + errors[] 如实报出那个词的字面。读器把两代字节的这一格都归到
894
896
  // `unknown` 臂(因由形取 `terminal.kind`,扁平形取 `status`),所以本臂对两代同样有效。
895
- // 🔴 **终态词整个缺席**(mock 车道 / 旧合成帧;读器返 `null`)维持 success 臂,零行为变化。
897
+ // 🔴 **终态词整个缺席**(读器返 `null`):0.72.12 CC-50 起**不再**落 success 臂 —— 此前这里维持成功
898
+ // (mock 车道 / 不带终态词的旧合成帧「零行为变化」),等于把「这份载体上连终态词都没有」编成一份成功
899
+ // 结果。改为 fail-closed + `_sema_outcome:'unknown'`(取舍与理由见 `ErrorResultParts.outcomeUnknown`);
900
+ // 旧合成帧那一路从 success 翻成 error 是**真行为变化**,随 0.72.12 发车帖「取舍」段披露,mock 车道
901
+ // 要成功请在帧上带真终态词(`status:'completed'` / `terminal:{kind:'completed'}`)。
902
+ if (terminal === null || terminal === undefined) {
903
+ return errorResult(ctx, {
904
+ ...errorBase,
905
+ subtype: 'error_during_execution',
906
+ outcomeUnknown: true,
907
+ errors: [
908
+ 'run ended with no terminal record — outcome unknown, not a failure verdict (this client cannot tell whether the run succeeded; treat the result as unverified)',
909
+ ],
910
+ });
911
+ }
896
912
  if (terminal?.kind === 'unknown') {
897
913
  return errorResult(ctx, {
898
914
  ...errorBase,
899
915
  subtype: 'error_during_execution',
916
+ outcomeUnknown: true,
900
917
  errors: [
901
918
  terminal.message ??
902
919
  (terminal.word !== undefined
@@ -175,6 +175,14 @@ export declare const MODEL_OUTPUT_ERROR_PREFIX = "Model output error";
175
175
  export declare function isModelOutputErrorText(text: string): boolean;
176
176
  /** 这一行是不是「模型输出问题」行(渲染面 / 归约面的谓词;与铸点同源,端别自抄前缀字面)。与 {@link isGovernanceStopRowText} 互斥。 */
177
177
  export declare function isModelOutputErrorRowText(text: string): boolean;
178
+ /**
179
+ * 0.72.12 CC-50:第三条中性终局行身份 —— **结局不知道**(done 帧无终态记录 / 认不出的终态词)。
180
+ * 三端渲染面按行首认它(与 `Model output error:` / `Run stopped:` 同律);它不是 API 错误、不是失败判决,
181
+ * 是「别把这次结果当已验证」。铸点单源在 runStream 终局臂(读结果帧 `_sema_outcome`)。
182
+ */
183
+ export declare const OUTCOME_UNKNOWN_ROW_PREFIX = "Outcome unknown";
184
+ /** 这一行是不是「结局不知道」终局行(只认行首)。 */
185
+ export declare function isOutcomeUnknownRowText(text: string): boolean;
178
186
  /**
179
187
  * 终态是不是治理/契约面的(⇒ 中性行),而不是 provider/HTTP 面的(⇒ 保留 `API Error:`)。
180
188
  *
@@ -197,6 +197,35 @@ export function isModelOutputErrorText(text) {
197
197
  export function isModelOutputErrorRowText(text) {
198
198
  return text.trimStart().startsWith(`${MODEL_OUTPUT_ERROR_PREFIX}:`);
199
199
  }
200
+ /**
201
+ * 0.72.12 CC-50:第三条中性终局行身份 —— **结局不知道**(done 帧无终态记录 / 认不出的终态词)。
202
+ * 三端渲染面按行首认它(与 `Model output error:` / `Run stopped:` 同律);它不是 API 错误、不是失败判决,
203
+ * 是「别把这次结果当已验证」。铸点单源在 runStream 终局臂(读结果帧 `_sema_outcome`)。
204
+ */
205
+ export const OUTCOME_UNKNOWN_ROW_PREFIX = 'Outcome unknown';
206
+ /**
207
+ * 合成终态行的**唯一铸点**(0.72.12 起两处共用:`API Error:` / `Run stopped:` / `Model output error:` 那一行,与
208
+ * `Outcome unknown:` 那一行)。
209
+ * [2084]③:message 内部要有判别哨兵——外层 isApiErrorMessage/err- uuid 只护住读信封的消费者,而转录回喂/摘要器/
210
+ * 评分器读的是 message 本体,没有 in-message 标记就会把这句引擎文案当成模型自己说的话。CC 2.1.220 同款哨兵 =
211
+ * model:'<synthetic>'(下游投影层对 string 型 model 原样保留,不再回填真模型名)。
212
+ * 🔴 `isApiErrorMessage: true` 是 CC 的**行类**旗(「这是合成的终态错误行,不是模型说的话」),不是「provider API
213
+ * 错误」的断言:可见性过滤 / -p 契约投影 / tick 熔断都读它。
214
+ */
215
+ function syntheticTerminalRow(ctx, text) {
216
+ return {
217
+ session_id: ctx.sessionId ?? '',
218
+ uuid: `err-${Date.now().toString(36)}`,
219
+ type: 'assistant',
220
+ message: { role: 'assistant', model: '<synthetic>', content: [{ type: 'text', text }] },
221
+ parent_tool_use_id: null,
222
+ isApiErrorMessage: true,
223
+ };
224
+ }
225
+ /** 这一行是不是「结局不知道」终局行(只认行首)。 */
226
+ export function isOutcomeUnknownRowText(text) {
227
+ return text.trimStart().startsWith(`${OUTCOME_UNKNOWN_ROW_PREFIX}:`);
228
+ }
200
229
  /**
201
230
  * 终态是不是治理/契约面的(⇒ 中性行),而不是 provider/HTTP 面的(⇒ 保留 `API Error:`)。
202
231
  *
@@ -833,18 +862,7 @@ async function* runStreamInner(events, ctx, handle = {}) {
833
862
  ? // 0.72.8 CC-43:第二条中性臂 —— 模型输出坏了(core 原句锚),不是 API 错误;busy / 治理两臂优先(结构位赢过文本锚)。
834
863
  `${MODEL_OUTPUT_ERROR_PREFIX}: ${errText}${maxTokHint}`
835
864
  : `API Error: ${errText}${maxTokHint}`;
836
- yield {
837
- session_id: ctx.sessionId ?? '',
838
- uuid: `err-${Date.now().toString(36)}`,
839
- type: 'assistant',
840
- // [2084]③:message 内部要有判别哨兵——外层 isApiErrorMessage/err- uuid 只护住读信封的
841
- // 消费者,而转录回喂/摘要器/评分器读的是 message 本体,没有 in-message 标记就会把这句
842
- // 引擎文案当成模型自己说的话。CC 2.1.220 同款哨兵 = model:'<synthetic>'(下游投影层对
843
- // string 型 model 原样保留,不再回填真模型名)。
844
- message: { role: 'assistant', model: '<synthetic>', content: [{ type: 'text', text: rowText }] },
845
- parent_tool_use_id: null,
846
- isApiErrorMessage: true,
847
- };
865
+ yield syntheticTerminalRow(ctx, rowText);
848
866
  }
849
867
  // plan_review park(core [508]③ 拍板形状):done `status:"needs_review"` + gate plan_review 不是
850
868
  // 普通完成——壳弹审批卡(planReviewWire 合成 question 借 AskUserQuestion overlay;决断走
@@ -895,7 +913,21 @@ async function* runStreamInner(events, ctx, handle = {}) {
895
913
  // 字节的证据都不是;按那句话办,一条账数得全的 run 会被渲成「≥」并被宿主持久化成不完整状态
896
914
  // (失效方向在这里**不是**安全的那一侧,它是在断言一件没发生的事)。
897
915
  // ⇒ 观测位改为 per-stream 局部量,终帧按值收(第三参),与上面对账臂读的是同一份。
898
- yield terminalToSdkResult(ev, ctx, { usageMissingObserved, nestedUsageByTask });
916
+ const resultFrame = terminalToSdkResult(ev, ctx, { usageMissingObserved, nestedUsageByTask });
917
+ // 0.72.12 CC-50(test [7541] G2-d「铸了就要有人读」):结果帧上的 `_sema_outcome:'unknown'`(终态记录整个
918
+ // 缺席 / 认不出的终态词;铸点与取舍见 terminalToSdkResult `ErrorResultParts.outcomeUnknown`)在**这里**被消费 ——
919
+ // 交互面合成一行 `Outcome unknown:` 终局行(句子与结果帧 `errors[0]` 单源),壳零接线即可见;它**不是**
920
+ // `API Error:`(那是 provider 故障身份),也不是「失败」:结果边界 fail-closed 是取舍,行文案把这一点说出来。
921
+ // 🔴 稀疏:真 completed / 真 failed 帧不带旗,这里零行(G2-e 负控)。
922
+ const outcome = resultFrame.
923
+ _sema_outcome;
924
+ if (outcome === 'unknown') {
925
+ const errs = resultFrame.errors;
926
+ const sentence = Array.isArray(errs) && typeof errs[0] === 'string' ? errs[0] : 'the run ended without a terminal record this client can read';
927
+ // 行类旗 isApiErrorMessage 置位(合成终态行),不是「provider 错误」断言 —— 同 Model output error 行。
928
+ yield syntheticTerminalRow(ctx, `${OUTCOME_UNKNOWN_ROW_PREFIX}: ${sentence}`);
929
+ }
930
+ yield resultFrame;
899
931
  return;
900
932
  }
901
933
  // Every other arm → typed three-state projection(REF-CC-058)。
@@ -184,7 +184,10 @@ export function createBackgroundView(client, opts) {
184
184
  async function pullAssistant() {
185
185
  try {
186
186
  const { tasks } = await client.assistant.tasks({ signal: abort.signal });
187
- return { health: capsApprovals === false ? 'not-configured' : 'ok', tasks: tasks ?? [] };
187
+ // 0.72.12 CC-50(#59 A-17):200 回体缺 tasks 键 = 读不出,不是「零任务」⇒ unavailable(空表 + ok 是编的)。
188
+ if (!Array.isArray(tasks))
189
+ return { health: 'unavailable', tasks: [] };
190
+ return { health: capsApprovals === false ? 'not-configured' : 'ok', tasks };
188
191
  }
189
192
  catch (err) {
190
193
  debugLog(`assistant.tasks degrade: ${String(err)}`);
@@ -199,7 +202,9 @@ export function createBackgroundView(client, opts) {
199
202
  try {
200
203
  // G19 一次性快照 verb:SDK 内部开 SSE 流取首 snapshot 帧即断;abort.signal 直通 ⇒ dispose 能掐在飞连接。
201
204
  const { tasks } = await client.fleet.snapshot({ signal: abort.signal });
202
- return { health: 'ok', tasks: tasks ?? [] };
205
+ if (!Array.isArray(tasks))
206
+ return { health: 'unavailable', tasks: [] }; // CC-50:同 assistant 腿
207
+ return { health: 'ok', tasks };
203
208
  }
204
209
  catch (err) {
205
210
  debugLog(`fleet.snapshot degrade: ${String(err)}`);
@@ -102,6 +102,23 @@ export type EngineAgentPanelEvent = {
102
102
  * explicit close arm carries it; the defensive sweeps settle without one). The consumer persists it
103
103
  * on the row (task.result) + appends it to a live-viewed transcript (拍1 查看态 seed). */
104
104
  report?: string;
105
+ } | {
106
+ /**
107
+ * 0.72.12 CC-50(test [7541] / sema-internal #59 头条站点):这一行**从引擎的行帧投影里消失**
108
+ * 超过 `ABSENT_SETTLE_MS` 仍没见到终态帧。它**不是**终局 —— 本包手上没有任何载体说明这只代理
109
+ * 完没完成(server [7545]:父 run 离场时子行按 `orphaned` 被移除,真终局由后续对账周期补发,
110
+ * 结构性晚于这个窗)。此前这条路径铸 `end{isError:false}`,把「不知道」编成了「成功」,屏上
111
+ * 渲成 ✔ Completed(两条现场腿秒级实测)。
112
+ * 消费端义务:认得 ⇒ 渲「engine no longer reports this agent · outcome unknown」并停表,
113
+ * **不许**把它翻译成 completed / failed / stopped 任何一个终态词;认不得(老壳)⇒ 行停在最后
114
+ * 已知态(可被证伪的「不知道」)。真终态来了仍走 `end`(恰一次);行回来了走 `fleet-row`。
115
+ */
116
+ kind: 'absent';
117
+ taskId: string;
118
+ /** 最后一次在投影里见到这一行的钟(epoch ms)。 */
119
+ lastSeenAtMs: number;
120
+ /** 发出这条事件时已缺席多久(ms;≥ `ABSENT_SETTLE_MS`)。 */
121
+ absentForMs: number;
105
122
  } | {
106
123
  /** Exception-path safety net (published by seamQuery after every turn, throw or return):
107
124
  * the consumer settles ALL rows it owns that are still running. Idempotent. */
@@ -86,7 +86,8 @@ export function publishEngineAgentPanelEvent(ev) {
86
86
  // bounded policy) — a subagent that starts at that point would replay as "still settled", forever.
87
87
  if (ev.kind === 'sweep' && buffer.length > 0 && buffer[buffer.length - 1]?.kind === 'sweep')
88
88
  return;
89
- const progress = ev.kind === 'tick' || ev.kind === 'fleet-row';
89
+ // 'absent'(0.72.12)按 PROGRESS 类缓冲:同一行只有最新一条有信息(per (kind, taskId) 合并),满了先让位。
90
+ const progress = ev.kind === 'tick' || ev.kind === 'fleet-row' || ev.kind === 'absent';
90
91
  if (progress) {
91
92
  const kind = ev.kind;
92
93
  const taskId = ev.taskId;
@@ -149,7 +150,7 @@ export function publishEngineAgentPanelEvent(ev) {
149
150
  return;
150
151
  }
151
152
  // Full: the oldest PROGRESS event yields (its taskId's next rollup supersedes it anyway).
152
- const evictAt = buffer.findIndex(b => b.kind === 'tick' || b.kind === 'fleet-row');
153
+ const evictAt = buffer.findIndex(b => b.kind === 'tick' || b.kind === 'fleet-row' || b.kind === 'absent');
153
154
  if (evictAt >= 0) {
154
155
  buffer.splice(evictAt, 1);
155
156
  buffer.push(ev);
@@ -97,8 +97,15 @@ export function coerceWorkflowStatus(s) {
97
97
  return 'killed';
98
98
  case 'parked':
99
99
  return 'awaiting approval';
100
- default:
100
+ case 'queued':
101
+ return 'queued';
102
+ case 'running':
101
103
  return 'running';
104
+ default:
105
+ // 0.72.12 CC-51(#64 同形):认不出的词不再谎报活跃 —— 与同文件 `coerceTaskStatus`(REF-CC-043)同律落
106
+ // 非活跃中性词 `idle`(FleetTaskStatus 是 wire 闭集,无 unknown 位;idle = 「活着但此刻没在推进」,
107
+ // 是闭集里唯一不断言方向的词)。
108
+ return 'idle';
102
109
  }
103
110
  }
104
111
  /**
@@ -37,7 +37,7 @@ export interface FleetAgentRowLike {
37
37
  * 详情页 elapsed 只能锚「壳建行时刻」——遗留行上渲出 1h+ 的假时长。缺席=老引擎,消费端保持现状。 */
38
38
  startedAt?: number;
39
39
  }
40
- /** 行从投影集消失多久之后按 completed 兜底 settle(重连空窗 / snapshot 清表远小于此)。 */
40
+ /** 行从投影集消失多久之后上报 `absent`(0.72.12 起不再 settle;重连空窗 / snapshot 清表远小于此)。名字沿用(公面导出)。 */
41
41
  export declare const ABSENT_SETTLE_MS = 30000;
42
42
  /**
43
43
  * 测试钩:清投影台账 —— **全部 sessionKey**,不是只清 default 桶。
@@ -36,9 +36,13 @@
36
36
  * setAppState 全树重渲)。
37
37
  * ② 终态行发一次 `end`(幂等台账),并摘除常驻标 —— 与 bg_notification 合成链同一个 settle 边,
38
38
  * 两边先到先得,消费端 settle 本身幂等(running 才动)。
39
- * ③ 缺席兜底:行从投影集里消失且**超过宽限窗**仍没见终态 ⇒ 按 completed settle。诚实边界:这是
40
- * 安全网不是真相源(真终态来自行帧终态 / bg_notification),宽限窗内的重连空窗(snapshot 清表)
41
- * 不会误结。lastSeen 恒**先**按本次在场行刷新、再判缺席,所以 footer 长时间卸载后重挂也不误结。
39
+ * ③ 缺席上报(0.72.12 CC-50 改形):行从投影集里消失且**超过宽限窗**仍没见终态 ⇒ 发一条 `absent`
40
+ * 事件(**不是** `end`、**不** settle)。此前这里「按 completed settle」= 把「引擎不再上报这一行」
41
+ * 编成「成功」—— 本包手上没有任何载体说明它完没完成(test [7541] 两条现场腿秒级实测:屏上
42
+ * ✔ Completed 的真实来源就是这一格;server [7545]:子行随父 run 离场被 `orphaned` 移除,真终局由
43
+ * 后续对账周期补发,结构性晚于这个窗)。真终态帧迟到照发那唯一一次 `end`;行回来照发 `fleet-row`。
44
+ * 宽限窗内的重连空窗(snapshot 清表)不上报;lastSeen 恒**先**按本次在场行刷新、再判缺席,所以
45
+ * footer 长时间卸载后重挂也不误报。
42
46
  * ④ 行 id 尾段判(`${runId} ${taskId}` 复合形取尾;真机 1.277.4 上子行 id 是裸 a+16hex,复合形是
43
47
  * run 发布器双生行的形)——REF-CC-042:与同包 `workflow.rowIdTail` 同一个函数(import,不再
44
48
  * 就地维护第二份;该函数出过等价性事故,0.1.1 修,见 `workflow.ts` 头注)。
@@ -49,7 +53,7 @@ import { TERMINAL_FLEET_TASK_STATUSES } from './fleet/fleetProjection.js';
49
53
  import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
50
54
  // L-215+(0.65.0;core [6908]):「非成功终局」的单铸谓词(与 notifications 的同名位同源)。
51
55
  import { isTerminalNotSuccess } from './runTerminal.js';
52
- /** 行从投影集消失多久之后按 completed 兜底 settle(重连空窗 / snapshot 清表远小于此)。 */
56
+ /** 行从投影集消失多久之后上报 `absent`(0.72.12 起不再 settle;重连空窗 / snapshot 清表远小于此)。名字沿用(公面导出)。 */
53
57
  export const ABSENT_SETTLE_MS = 30_000;
54
58
  /** REF-CC-045(fleet2-07):settled 条目的回收期 —— settle 后这么久仍未再被投影 ⇒ 台账整条
55
59
  * delete,给 `fleetAgentProjectionSizeFor()` 一个上界(此前 `seen` 只增不减,长会话里每个
@@ -177,6 +181,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
177
181
  settled: true,
178
182
  // notif-F13:settle 时刻只在**首次** settle 时铸(重复投影的终态行不许一路续命回收期)。
179
183
  settledAtMs: prev?.settled ? prev.settledAtMs : nowMs,
184
+ absentReportedAtMs: undefined,
180
185
  });
181
186
  continue;
182
187
  }
@@ -186,6 +191,7 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
186
191
  // 值↔undefined 之间来回抖,每秒白发两次事件。
187
192
  if (!prev ||
188
193
  prev.settled ||
194
+ prev.absentReportedAtMs !== undefined || // 行回来了:即使值未变也发一条,消费端据此撤掉 absent 标
189
195
  prev.status !== status ||
190
196
  prev.tokens !== tokens ||
191
197
  (toolUses !== undefined && prev.toolUses !== toolUses) ||
@@ -216,29 +222,39 @@ export function projectFleetAgentRowsFor(sessionKey, rows, nowMs = Date.now()) {
216
222
  lastSeenAt: nowMs,
217
223
  settled: false,
218
224
  settledAtMs: undefined, // 又活了 ⇒ 回收钟归零(重新 settle 时重铸)
225
+ absentReportedAtMs: undefined, // 在场 ⇒ 缺席周期结束(下次再消失是新周期,会再上报一次)
219
226
  });
220
227
  }
221
- // ③ 缺席兜底 —— 必须在【本次在场行全部刷完 lastSeen 之后】判,否则 footer 长时间卸载后重挂
222
- // 会把仍在跑的行按「陈旧」误结。
228
+ // ③ 缺席上报 —— 必须在【本次在场行全部刷完 lastSeen 之后】判,否则 footer 长时间卸载后重挂
229
+ // 会把仍在跑的行按「陈旧」误报。🔴 0.72.12 CC-50:这里只发 `absent`,**不** settle、不铸 end ——
230
+ // 缺席不是终局,本包不替引擎下这个断言;真终态帧迟到照走 ② 发那唯一一次 end(去重记号不被缺席占用)。
223
231
  for (const [taskId, s] of seenMap) {
224
- if (present.has(taskId) || s.settled)
232
+ if (present.has(taskId) || s.settled || s.absentReportedAtMs !== undefined)
225
233
  continue;
226
- if (nowMs - s.lastSeenAt <= ABSENT_SETTLE_MS)
234
+ const absentForMs = nowMs - s.lastSeenAt;
235
+ if (absentForMs <= ABSENT_SETTLE_MS)
227
236
  continue;
228
- publishEngineAgentPanelEvent({ kind: 'end', taskId, isError: false });
229
- seenMap.set(taskId, { ...s, settled: true, settledAtMs: nowMs }); // notif-F13:settle 时刻按**现在**铸
237
+ publishEngineAgentPanelEvent({ kind: 'absent', taskId, lastSeenAtMs: s.lastSeenAt, absentForMs });
238
+ seenMap.set(taskId, { ...s, absentReportedAtMs: nowMs });
230
239
  }
231
240
  // ④ REF-CC-045(fleet2-07):settled 条目回收 —— 给台账一个上界(此前只增不减)。settle 已发过
232
241
  // 事件,delete 对外无事件,消费端 settle 本身幂等。
233
242
  // [2393] notif-F13/sweep-F7 两处纠(判据见 SETTLED_RETENTION_MS 头注):
234
243
  // · 锚 `settledAtMs`(settle 那一刻)而不是 `lastSeenAt`(最后一次被投影);
235
244
  // · 只回收**已不在场**的条目 —— 仍在场的终态行删了会每拍重发 end。
245
+ // 0.72.12:已上报 absent 且始终不再在场的条目同样有上界 —— 锚 `absentReportedAtMs`(上报那一刻),
246
+ // 回收后迟到的终态帧仍会发恰一次 end(prev 缺席 ⇒ 首次 settle),行回来则按新行重建。
236
247
  for (const [taskId, s] of seenMap) {
237
- if (!s.settled || present.has(taskId))
248
+ if (present.has(taskId))
238
249
  continue;
239
- const settledAt = s.settledAtMs ?? s.lastSeenAt;
240
- if (nowMs - settledAt > SETTLED_RETENTION_MS)
250
+ if (s.settled) {
251
+ const settledAt = s.settledAtMs ?? s.lastSeenAt;
252
+ if (nowMs - settledAt > SETTLED_RETENTION_MS)
253
+ seenMap.delete(taskId);
254
+ }
255
+ else if (s.absentReportedAtMs !== undefined && nowMs - s.absentReportedAtMs > SETTLED_RETENTION_MS) {
241
256
  seenMap.delete(taskId);
257
+ }
242
258
  }
243
259
  if (seenMap.size === 0)
244
260
  seen.delete(sessionKey);
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * ⚠️ 调用方契约(交叉复审 [MED] 登记):cli 原版在渲染前有两条默认值回填——
3
- * summary 缺省 ⇒ `Background task "${taskId}" ${status}`;status 非串 ⇒ 'completed'。
3
+ * summary 缺省 ⇒ `Background task "${taskId}" ${status}`;status 非串 ⇒ 'unknown'(0.72.12 起;此前 'completed')。
4
4
  * 本纯函数不做回填(职责在 adapt() 输入侧),直接透传引擎原始 JSON 会渲出空 <summary>。
5
5
  * 落 adapt() 时必须先补齐这两个字段再调本函数。
6
6
  * 另注:<status> 段转义为**有意统一变更**(cli 原版曾不转义;2026-07-25 双侧统一为转义,
@@ -35,7 +35,7 @@ export declare function renderTaskNotificationXml(n: TaskNotificationFields): st
35
35
  export declare function deriveNotificationResidualLines(n: Record<string, unknown>): string[];
36
36
  /**
37
37
  * 引擎 task_notification 原始 payload → renderTaskNotificationXml 的入参(**含上面注释里那两条
38
- * 回填**:summary 缺省 ⇒ `Background task "<id>" <status>`;status 非串 ⇒ 'completed')。
38
+ * 回填**:summary 缺省 ⇒ `Background task "<id>" <status>`;status 非串 ⇒ 'unknown',summary 改说 outcome unknown)。
39
39
  * task_id 空串/缺失 ⇒ null(RB-75 同族:空 id 会塌成 ':status' 共享桶互吞,无 id 的通知本就无意义)。
40
40
  * 字段名映射按 wire 真形:task_id/output_file/task_type/source 是 snake/wire 名,其余同名。
41
41
  */
@@ -9,7 +9,7 @@ import { unrefTimer } from './unrefTimer.js';
9
9
  import { clearEnginePanelTaskResident, publishEngineAgentPanelEvent, } from './engineAgentPanelStore.js';
10
10
  // L-215②(0.65.0;core [6908]):「非成功终局」的**单铸谓词** —— 面板 settle 的 `isError` 位与
11
11
  // 三端自己的后台白名单必须读同一个判据;内联一个 `=== 'failed' || === 'killed'` 就是第二份会漂的台账。
12
- import { isTerminalNotSuccess, isTerminalStatus } from './runTerminal.js';
12
+ import { isTaskNotificationTerminalStatus, isTerminalNotSuccess, isTerminalStatus } from './runTerminal.js';
13
13
  function escapeXml(v) {
14
14
  return v.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
15
15
  }
@@ -58,7 +58,7 @@ export function deriveNotificationResidualLines(n) {
58
58
  }
59
59
  /**
60
60
  * 引擎 task_notification 原始 payload → renderTaskNotificationXml 的入参(**含上面注释里那两条
61
- * 回填**:summary 缺省 ⇒ `Background task "<id>" <status>`;status 非串 ⇒ 'completed')。
61
+ * 回填**:summary 缺省 ⇒ `Background task "<id>" <status>`;status 非串 ⇒ 'unknown',summary 改说 outcome unknown)。
62
62
  * task_id 空串/缺失 ⇒ null(RB-75 同族:空 id 会塌成 ':status' 共享桶互吞,无 id 的通知本就无意义)。
63
63
  * 字段名映射按 wire 真形:task_id/output_file/task_type/source 是 snake/wire 名,其余同名。
64
64
  */
@@ -66,7 +66,8 @@ export function normalizeTaskNotification(n) {
66
66
  const taskId = typeof n.task_id === 'string' && n.task_id.length > 0 ? n.task_id : undefined;
67
67
  if (taskId === undefined)
68
68
  return null;
69
- const status = typeof n.status === 'string' ? n.status : 'completed';
69
+ // 0.72.12 CC-50(#59 A-08):status 非串 ⇒ 'unknown'(此前 'completed',并用它编 summary 与去重键)。
70
+ const status = typeof n.status === 'string' ? n.status : 'unknown';
70
71
  const lines = Array.isArray(n.lines)
71
72
  ? n.lines.filter((l) => typeof l === 'string')
72
73
  : [];
@@ -76,7 +77,9 @@ export function normalizeTaskNotification(n) {
76
77
  status,
77
78
  summary: typeof n.summary === 'string' && n.summary.length > 0
78
79
  ? n.summary
79
- : `Background task "${taskId}" ${status}`,
80
+ : status === 'unknown'
81
+ ? `Background task "${taskId}" reported without a status (outcome unknown)`
82
+ : `Background task "${taskId}" ${status}`,
80
83
  ...(typeof n.task_type === 'string' ? { taskType: n.task_type } : {}),
81
84
  ...(typeof n.toolUseId === 'string' && n.toolUseId.length > 0 ? { toolUseId: n.toolUseId } : {}),
82
85
  ...(typeof n.output_file === 'string' && n.output_file.length > 0
@@ -121,7 +124,8 @@ export function taskNotificationDedupKey(n) {
121
124
  export function taskNotificationDedupKeyFromWire(n) {
122
125
  return taskNotificationDedupKey({
123
126
  taskId: typeof n.task_id === 'string' ? n.task_id : '',
124
- status: typeof n.status === 'string' ? n.status : 'completed',
127
+ // CC-50:与 normalizeTaskNotification 同判,缺席不与真 completed 同桶。
128
+ status: typeof n.status === 'string' ? n.status : 'unknown',
125
129
  ...(typeof n.seq === 'number' || typeof n.seq === 'string' ? { seq: n.seq } : {}),
126
130
  ...(typeof n.task_type === 'string' ? { taskType: n.task_type } : {}),
127
131
  });
@@ -1050,7 +1054,15 @@ export function taskNotificationDeliverySupplement(objective) {
1050
1054
  return `${SUPPLEMENT_LINE_PREFIX}completed — only this notification delivery failed. Check /tasks for the result.`;
1051
1055
  }
1052
1056
  const statusNote = status && status.length > 0 ? ` (status: ${status})` : '';
1053
- return `${SUPPLEMENT_LINE_PREFIX}already finished${statusNote} — only this notification delivery failed. Check /tasks for the result.`;
1057
+ // 0.72.12 CC-50(异源对抗复审 R2 [medium]):只对**明确终态**说 already finished。此前这个尾模板对任何词都断言「已结束」,
1058
+ // 而同批 normalizeTaskNotification 开始对缺 status 的通知铸 `unknown` ⇒ 补充行重新造出终局确定性(DS-06:兜底位置落正向词,
1059
+ // 且模板表达式逃过 AST 五形)。缺席 / unknown / 未来词 / 活跃词 ⇒ 只陈述投递失败,不推断任务结局。
1060
+ // 终态词表对账**通知**自己的词(单源 `runTerminal.TASK_NOTIFICATION_TERMINAL_STATUSES`),不借 run 级 `isTerminalStatus`
1061
+ // (那张表没有 cancelled、多一个 blocked,语义不同)。
1062
+ if (isTaskNotificationTerminalStatus(status)) {
1063
+ return `${SUPPLEMENT_LINE_PREFIX}already finished${statusNote} — only this notification delivery failed. Check /tasks for the result.`;
1064
+ }
1065
+ return `${SUPPLEMENT_LINE_PREFIX}is in a state this client cannot confirm${statusNote} — this notification delivery failed and the task's outcome is unknown here. Check /tasks for its current state.`;
1054
1066
  }
1055
1067
  /**
1056
1068
  * API-error 行文拆分(渲染层消费):尾部的 supplement 行(若在)分离出来渲 dim,main 保留原始
@@ -313,3 +313,12 @@ export type RunTerminalStatus = (typeof RUN_TERMINAL_STATUSES)[number];
313
313
  * 🔴 表外词 ⇒ `false` = 「本端认不出这是个终局」,**不是**「它还在跑」;要判「在跑」请读正向证据。
314
314
  */
315
315
  export declare function isTerminalStatus(status: unknown): status is RunTerminalStatus;
316
+ /**
317
+ * 0.72.12 CC-50:**通知**(`task_notification.status`)自己的终态词表 —— 引擎 `TaskNotificationStatus` 五词里的四个终态
318
+ * (`completed` / `failed` / `killed` / `cancelled`;第五词 `event` 是唯一非终态 = 仍在跑的 Monitor 批)逐字镜像。
319
+ * 🔴 它与 run 级 {@link RUN_TERMINAL_STATUSES} 是**两张表**(那张有 `blocked`、没有 `cancelled`):通知说「已取消」是明确终态,
320
+ * 借 run 级表会把它读成「认不出」(异源对抗复审抓出)。住在词表属主文件里,src 别处零内联(终态词汇门 D3)。
321
+ */
322
+ export declare const TASK_NOTIFICATION_TERMINAL_STATUSES: readonly string[];
323
+ /** 这个通知 status 是不是**明确终态**;表外词(`event` / `unknown` / 未来词 / 缺席)⇒ false = 「本端不能断言它结束了」。 */
324
+ export declare function isTaskNotificationTerminalStatus(status: string | undefined): boolean;
@@ -320,3 +320,14 @@ export const RUN_TERMINAL_STATUSES = Object.freeze([
320
320
  export function isTerminalStatus(status) {
321
321
  return typeof status === 'string' && RUN_TERMINAL_STATUSES.includes(status);
322
322
  }
323
+ /**
324
+ * 0.72.12 CC-50:**通知**(`task_notification.status`)自己的终态词表 —— 引擎 `TaskNotificationStatus` 五词里的四个终态
325
+ * (`completed` / `failed` / `killed` / `cancelled`;第五词 `event` 是唯一非终态 = 仍在跑的 Monitor 批)逐字镜像。
326
+ * 🔴 它与 run 级 {@link RUN_TERMINAL_STATUSES} 是**两张表**(那张有 `blocked`、没有 `cancelled`):通知说「已取消」是明确终态,
327
+ * 借 run 级表会把它读成「认不出」(异源对抗复审抓出)。住在词表属主文件里,src 别处零内联(终态词汇门 D3)。
328
+ */
329
+ export const TASK_NOTIFICATION_TERMINAL_STATUSES = Object.freeze(['completed', 'failed', 'killed', 'cancelled']);
330
+ /** 这个通知 status 是不是**明确终态**;表外词(`event` / `unknown` / 未来词 / 缺席)⇒ false = 「本端不能断言它结束了」。 */
331
+ export function isTaskNotificationTerminalStatus(status) {
332
+ return status !== undefined && TASK_NOTIFICATION_TERMINAL_STATUSES.includes(status);
333
+ }
@@ -471,7 +471,8 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
471
471
  return wrap({
472
472
  task_id: parsed.taskId ?? '',
473
473
  task_type: 'local_agent',
474
- status: parsed.status ?? 'completed',
474
+ // 0.72.12 CC-50(#59 A-06):解不出 ⇒ unknown,不编 completed。
475
+ status: parsed.status ?? 'unknown',
475
476
  description: parsed.taskId ?? '',
476
477
  output: parsed.output ?? '',
477
478
  result: parsed.output ?? '',
@@ -824,19 +825,27 @@ modelText) {
824
825
  const taskId = typeof s.task_id === 'string' ? s.task_id : undefined;
825
826
  if (taskId === undefined)
826
827
  return null;
827
- const retrieval = s.retrieval_status === 'timeout' || s.retrieval_status === 'not_ready'
828
- ? s.retrieval_status
829
- : 'success';
830
828
  const taskType = typeof s.taskType === 'string' ? s.taskType : '';
831
829
  const inner = s.details && typeof s.details === 'object' ? s.details : undefined;
832
830
  const hasStatus = typeof s.status === 'string' && s.status.length > 0;
833
831
  const hasContent = typeof s.content === 'string';
832
+ // 0.72.12 CC-50(#59 A-05 前半)。🔴 `retrieval_status` 是 **CC 同名键**(闭集 success / timeout / not_ready):老壳卡片
833
+ // success 才展示正文、not_ready 渲「still running」、timeout 渲超时 —— 闭集里没有「不知道」,绝不往里塞第四个词。
834
+ // 认不出 / 缺席 ⇒ `success`:正向证据 = 这份 structured detail 是一次**已返回**的取回调用的产物(引擎没说 timeout /
835
+ // not_ready 就是取回来了);「结局不知道」由下面的 `status:'unknown'` 承载,不由 retrieval 位承载。
836
+ // (异源对抗复审两轮:原词透传 ⇒ 已完成正文被藏;按 structured 两键推 not_ready ⇒ 漏了文本回落且渲成假「仍在运行」。
837
+ // 本行登记在 scripts/absence-fold-baseline.json 带 why。)
838
+ const rawRetrieval = typeof s.retrieval_status === 'string' ? s.retrieval_status : undefined;
839
+ const engineSaidNotReady = rawRetrieval === 'timeout' || rawRetrieval === 'not_ready';
840
+ const retrieval = engineSaidNotReady ? rawRetrieval : 'success';
834
841
  // 🔴 惰性回落:structured 把 status 和正文都带齐了就**根本不解**模型面文本(T13 正则退位);
835
842
  // 少哪一半就只为那一半解一次。判据锚在「这两个量还缺不缺」,不锚在「structured 在不在」。
836
843
  const parsed = hasStatus && hasContent ? null : parseModelFacingTaskOutput(modelText ?? '');
844
+ // 0.72.12 CC-50(#59 A-05):retrieval success 只说「取到了」,不说「完成了」⇒ 无 status 落 unknown;
845
+ // 引擎**亲口**说 not_ready / timeout 才是「还没好」的正向证据 ⇒ running(本包按无证据推出来的 not_ready 不算)。
837
846
  const status = hasStatus
838
847
  ? s.status
839
- : (parsed?.status ?? (retrieval === 'success' ? 'completed' : 'running'));
848
+ : (parsed?.status ?? (engineSaidNotReady ? 'running' : 'unknown'));
840
849
  // 'unknown' 分支类型上没有 output 字段(REF-CC-TYPESHAPE-14:不是「值恰好是 undefined」)——
841
850
  // 显式按 kind 取,别对整个 union 裸访问不共有的属性。
842
851
  const bodyText = hasContent ? s.content : parsed && parsed.kind !== 'unknown' ? parsed.output : undefined;
package/dist/workflow.js CHANGED
@@ -69,7 +69,9 @@ export function parseWorkflowPollEnvelope(body) {
69
69
  return null;
70
70
  return {
71
71
  taskId: j.task_id,
72
- status: typeof j.status === 'string' && j.status.length > 0 ? j.status : 'completed',
72
+ // 0.72.12 CC-50(#59 A-07):缺 status ⇒ 'unknown'。此前折成 'completed',而 'completed' ∈ WF_TERMINAL ⇒
73
+ // 消费点顺手 markEngineWorkflowNotified,把真完成通知的补发通道一起缴械。缺席不是终局。
74
+ status: typeof j.status === 'string' && j.status.length > 0 ? j.status : 'unknown',
73
75
  ...(typeof j.name === 'string' && j.name.length > 0 ? { name: j.name } : {}),
74
76
  };
75
77
  }
@@ -94,10 +94,21 @@ function coerceRunStatus(s) {
94
94
  return 'running';
95
95
  case 'parked':
96
96
  return 'parked'; // 前向预挂(见上方族头注):词真到了就原样透出,绝不折成「在跑」
97
+ case 'queued':
98
+ return 'running'; // 无 run 级 queued 词,排队按活跃渲(正向证据:引擎说它在队里)
97
99
  default:
98
- return 'running'; // queued / unknown-future → render as an active run (open-set fallback)
100
+ return 'unknown'; // 0.72.12 CC-51(#64 A-28):认不出的词 ⇒ unknown,不渲成「在跑」;壳渲原串 + 未知标
99
101
  }
100
102
  }
103
+ /** run 级状态的证据式收口:认得的词照旧;`unknown` 时腿上有活跃证据(start / progress / queued)⇒ `running`。 */
104
+ function runStatusWithLegEvidence(coerced, agents) {
105
+ if (coerced !== 'unknown')
106
+ return coerced;
107
+ const active = agents.some(a => a.state === 'start' || a.state === 'progress' || a.state === 'queued');
108
+ if (active)
109
+ return 'running';
110
+ return 'unknown';
111
+ }
101
112
  /** detail phase status (service projects {title,status,done,total}) → the monitor's phase vocabulary. */
102
113
  function coercePhaseStatus(s) {
103
114
  switch (s) {
@@ -112,8 +123,10 @@ function coercePhaseStatus(s) {
112
123
  return 'not-started';
113
124
  case 'parked':
114
125
  return 'parked'; // 前向预挂,同 coerceRunStatus
115
- default:
126
+ case 'running':
116
127
  return 'running';
128
+ default:
129
+ return 'unknown'; // CC-51:同 coerceRunStatus
117
130
  }
118
131
  }
119
132
  /** SDK WorkflowAgentRow.status ("the input vocab the display derivation reads", types.ts:352) → the monitor's
@@ -338,7 +351,12 @@ function bucketStatus(bucket) {
338
351
  if (bucket.some(a => a.state === 'parked') && bucket.every(a => a.state === 'parked' || a.state === 'done')) {
339
352
  return 'parked';
340
353
  }
341
- return 'running';
354
+ // 0.72.12 CC-51(异源对抗复审 R1 [high];DS-06 病形本体 = 兜底位置落正向词):`running` 只在有腿真在跑 / 排队时说;
355
+ // 空桶(零腿)与全是 inactive 之类没有活跃证据的桶 ⇒ unknown。上一行的 `length > 0` 守卫做对了「空集 every 恒真」那一格,
356
+ // 却栽在这个尾 return 上 —— 病不在粗心,在「兜底位置写什么」缺纪律。
357
+ if (bucket.some(a => a.state === 'start' || a.state === 'progress' || a.state === 'queued'))
358
+ return 'running';
359
+ return 'unknown';
342
360
  }
343
361
  /** 合成 `Workflow` 单格(路径三:wire 既无结构化 phases 也无 agent 上的 phase 标)的状态词。
344
362
  * 跟 run 走(同 {@link coerceRunStatus} 的臂),run 说不出 `parked` 时再从腿上推一次 —— 今天真正
@@ -350,8 +368,15 @@ function synthPhaseStatus(runStatus, agents) {
350
368
  return 'parked';
351
369
  const derived = bucketStatus(agents);
352
370
  if (derived === 'parked')
353
- return 'parked';
354
- return runStatus === 'failed' ? 'failed' : 'running';
371
+ return 'parked'; // 腿上的 park 压过 run 级 failed(core 7.10.0 把一条腿 park 收在 failed)
372
+ // 腿上的 error 是明确失败证据(bucketStatus 失败优先)—— 合成格与带 phase 标签的同组腿必须同判(异源对抗复审 R3)。
373
+ if (runStatus === 'failed' || derived === 'failed')
374
+ return 'failed';
375
+ // 0.72.12 CC-51(异源对抗复审 R1 [high]):此前尾三元 `failed ? 'failed' : 'running'` 把「run 缺 status / 认不出的词」折成在跑。
376
+ // 正向证据两处:run 自己说 running / queued,或腿上有人在跑;都没有 ⇒ unknown。
377
+ if (runStatus === 'running' || runStatus === 'queued')
378
+ return 'running';
379
+ return derived === 'running' ? 'running' : 'unknown';
355
380
  }
356
381
  /** THE projector: SDK `WorkflowRun` (client.workflows.get) → the monitor's `WorkflowRunState`. Pure/total —
357
382
  * tolerates absent/permissive fields and never throws (the graceful-degrade contract lives above, in the
@@ -367,7 +392,10 @@ export function projectWorkflowRun(run) {
367
392
  : agents.reduce((s, a) => s + (a.tokens ?? 0), 0); // no stats on the wire → sum the agent rows
368
393
  const state = {
369
394
  workflowRunId: run.id,
370
- status: coerceRunStatus(run.status),
395
+ // 0.72.12 CC-51(异源对抗复审 R2 [medium]):run 状态词认不出 / 缺席时先看腿上的**活跃证据** —— 有腿在跑 / 排队 ⇒ running
396
+ // (老壳用 `status === 'running'` 算 workflowActive,run 落 unknown 会把明明在跑的腿渲成 Stopped);零证据才 unknown。
397
+ // 不拿「腿全做完了」反推 run 完成:那是 run 自己的话。
398
+ status: runStatusWithLegEvidence(coerceRunStatus(run.status), agents),
371
399
  // CC-12(0.69.1):park 两新键**进视图**(修前只出读器,端拿不到裸体 ⇒ 渲染面结构性造不出);铸法与缺席律逐字同两读器。
372
400
  ...(parks !== undefined ? { parks } : {}),
373
401
  ...(readWorkflowResumeAdmissionIncomplete(run) ? { resumeAdmissionIncomplete: true } : {}),
@@ -70,7 +70,7 @@ export interface WorkflowPhase {
70
70
  /** 🔴 `parked` = 这一格里没有一条腿能自己往前走(全员不是完成就是停在审批门上)。见 `AgentState`
71
71
  * 的同名头注;上游今天不给 phase 铸这个词(core:「a phase or group never parks」),本包这一位有两个
72
72
  * 来路:①上游哪天真铸了 ⇒ 原词透出而不是折成 running;②本包从桶里的腿**推**出来。 */
73
- status: 'not-started' | 'running' | 'done' | 'failed' | 'parked';
73
+ status: 'not-started' | 'running' | 'done' | 'failed' | 'parked' | 'unknown';
74
74
  doneCount: number;
75
75
  totalCount: number;
76
76
  agents: WorkflowAgent[];
@@ -86,7 +86,8 @@ export interface WorkflowRunState {
86
86
  * running|completed|failed(一条腿 park ⇒ 整只 run 按 `WorkflowAgentParkedError` 收在 `failed`),
87
87
  * 所以今天没有任何受支持的引擎在这一位上发 `parked`。留这条臂是为了「词真到了就原样透出」,
88
88
  * 绝不是说它现在会到 —— 判「这条 run 停着等人批」今天要看**腿**那一级(见 `AgentState.parked`)。 */
89
- status: 'running' | 'done' | 'failed' | 'stopped' | 'paused' | 'parked';
89
+ /** 0.72.12 CC-51:`unknown`(additive)= wire 上认不出的 run 状态词;绝不再折成 running(端要渲原串请读 wire `run.status`)。 */
90
+ status: 'running' | 'done' | 'failed' | 'stopped' | 'paused' | 'parked' | 'unknown';
90
91
  cloud?: boolean;
91
92
  agentCount: number;
92
93
  totalTokens: number;
@@ -19,11 +19,11 @@
19
19
 
20
20
  | 项 | 值 | 真源 |
21
21
  |---|---|---|
22
- | 本包 | `@sema-agent/client-core` **0.72.11**(本批发布版 = **patch**:core 7.23.0 提货 —— CC-49 通告码 66 → 67 `config.write_protection_unresolved`(operator;兄弟码 `target_view_absent` = 没有视图,这枚 = 有视图解析不出)+ `permission_denials` 自动升级腿通电(`gates[].toolCallId` ⇒ `tool_use_id`;CC-34 引擎半场);型面零变化、公面 989、peer 不动、devDep core ~7.23.0;§58。上一版 0.72.10 = **patch**:CC-41 leader run 终局 `needs_human` + `result.conflict` 三形读面(none 缺席不可分 / unreadable 在场读不懂 / conflict;`salvaged[]` 原样给落盘口;措辞单源不提重试);型面纯 additive、公面 989、peer 不动;§57。上一版 0.72.9 = **patch**:server 7.85.0 提货 —— CC-30 会话内 MCP re-dial 消费口(`reconnectMcpServer` 三态 / unsupported 恒五键 / 交易文案单源)+ CC-39② memory-status `autoConsolidationArmed` 三态 + CC-45 resume 补充句渲保留秒数;型面纯 additive、公面 985、peer 不动;§56。上一版 0.72.8 = **patch**:清账三票 —— `memory:"off"` 请求键(CC-39③,server 7.84.0 S-405)+ `runStream` 第二条中性臂 `Model output error:`(CC-43)+ 注入件撞活 run 自动 steer 零卡(CC-44);型面纯 additive、公面 977、peer 不动;§55。上一版 0.72.7 = **patch**:core 7.22.0 提货 —— 通告码 66 `mcp.server_redialed` + 读器 `readMcpServerRedialed` + `wiring_manifest.readDeny` 第九段 `_sema_readDeny`(缺席 = 没有内置行判这条腿);型面纯 additive、公面 971、peer 不动、devDep core ~7.22.0;§54。上一版 0.72.6 = **patch**:cli L-379 包侧半场 —— `steerFollowIntent` steer 后续听意图三态(tail / after-decision / after-wake)+ `activeRunSelfHealRow` 续听声明第五参;型面纯 additive、公面 969、peer 不动;§53。上一版 0.72.5 = **patch**:server 7.82.1 提货 —— `capabilities.webSearch.backend` 部署默认 WebSearch 后端四态读面(键缺席 = 老引擎判不了 ≠ `none`);型面纯 additive、公面 968、peer 不动;§52。上一版 0.72.4 = **patch**:core 7.21.x 三件经 server 7.82.0 提货 —— `wiring_manifest.autoConsolidation` 第八段 `_sema_autoConsolidation`(缺席 = indeterminate 不折 false);型面纯 additive、公面 962、peer 不动;§51。上一版 0.72.3 = **patch**:core #863 记忆单系统半场 ① —— `projectAgentsForWire` 投影 `agents[].memory`(user|project|local 三词同映射引擎平面 agent:<type>);型面纯 additive、公面 962、零 wire 新键、peer 不动;§50。上一版 0.72.2 = **patch**:workflow 视图两票 —— `LiveWorkflowController.resolution()` 六态(snapshot() 的 null 三义拆开)+ `noteOwnWorkflowRun` own 台账同拍登记;型面纯 additive、公面 961、零 wire 键、peer 不动;§49。上一版 0.72.1 = **patch**:server 7.80.1 提货 —— 409 `conflict.resume_context_unavailable` 结构读数(`staleAfterSec` / `runId`;sdk 9.6.0 尚未带键,经 sdk 今天恒缺席)+ `SkillSpec.baseDir`(只在本机车道带);型面纯 additive、公面 960、peer 不动;§48。上一版 0.72.0 = **minor**:型面 BREAKING —— 39 个零消费导出退出公面(CC-32 退役批,[7419] §45 预告 / cli [7422] 同意 / web-client·desktop 过节拍沉默 = 同意;名单见 §47a S-1);运行期零 BREAKING、公面 956、peer 不动、devDep core ~7.20.1;随批:已退役名账 `removed` + export-liveness 门 G 段 + 冻结账门 ⑧c;§47。上一版 0.71.4 = **patch**:core 7.20.1 提货 —— `ENGINE_NOTICE_CODES` 65 + `wiring_manifest.writeProtection` 第七段 `_sema_writeProtection`;型面纯 additive、公面 995、peer 不动、devDep core `~7.20.1`;§46。上一版 0.71.3 = **patch**:门体系清账批 —— CC-24 export-liveness 门 + 39 个导出退役预告(0.72.0 删,表态制)/ CC-26 `as unknown as` 铸链棘轮 / CC-25 冻结账门 ⑧ 段 / CC-06 B-081 包侧半场(终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` + resume reopen 族 + `routePairingVerdict`);型面纯 additive、公面 986 → 995、peer 不动;§45。上一版 0.71.2 = **patch**:接入方验收两票归包 —— CC-28 B-132 decide 拒体三句去内部车道词 / CC-29 B-133 committedUuids 唯一性(重复 ⇒ 形 f);零型面变化、公面 986、peer 不动;§44。上一版 0.71.1 = **patch**:接入档打回修正 —— CC-27 `ApprovalCardRequest.readRootCandidate?` 帧→卡透传位 + 新导出型 `ReadRootCandidateView`;型面纯 additive、公面 986 不变、peer 不动;§43。上一版 0.71.0 = **minor**:型面 BREAKING 六件 —— peer sdk 地板 >=9.6.0 + agent-types >=0.3.0 / `SkillsListingTruncatedFactsView` 删 `requestedBudgetBytes?`·`laneClamped?` / `WiringManifestMcpEntry` → `WiringManifestMcpEntryView` / `MAX_AGENT_SKILLS` 删 / `decide.workflow_host_not_parked` 退役;运行期零 BREAKING。内容:core 7.20.0 提货(闭集 +5 六十四码)/ 🔴 CC-16 `text_segment_end.committedUuids[]` / CC-08 全五件(tool_disclosure / tool_progress 两 chrome 臂、wiring_manifest tools·hooks·lsp 进切片、tool_roster_delta 接上、context_usage 进切片、`readRootCandidate` 镜像)/ CC-19 `mcpEngineLegPresence` 归包 / CC-20 not_parked clean-cut;公面 986;§42 / 42y 八条)|
22
+ | 本包 | `@sema-agent/client-core` **0.72.12**(本批发布版 = **patch**:「缺席被折成正向终态」按类清剿 —— CC-50 M1 头条(fleet 行缺席改发 `absent` 不再铸 `end{isError:false}`)+ 六站一次改齐(缺席 ⇒ `unknown`)+ 结果边界 fail-closed 取舍 + `_sema_outcome` + `Outcome unknown:` 行 + CC-51 M6(default 臂不再谎报 running)+ 普查门 + DS-06;型面 additive、公面 993、peer 不动;行为面三处真变化见 CHANGELOG 取舍段;§59。上一版 0.72.11 = **patch**:core 7.23.0 提货 —— CC-49 通告码 66 → 67 `config.write_protection_unresolved`(operator;兄弟码 `target_view_absent` = 没有视图,这枚 = 有视图解析不出)+ `permission_denials` 自动升级腿通电(`gates[].toolCallId` ⇒ `tool_use_id`;CC-34 引擎半场);型面零变化、公面 989、peer 不动、devDep core ~7.23.0;§58。上一版 0.72.10 = **patch**:CC-41 leader run 终局 `needs_human` + `result.conflict` 三形读面(none 缺席不可分 / unreadable 在场读不懂 / conflict;`salvaged[]` 原样给落盘口;措辞单源不提重试);型面纯 additive、公面 989、peer 不动;§57。上一版 0.72.9 = **patch**:server 7.85.0 提货 —— CC-30 会话内 MCP re-dial 消费口(`reconnectMcpServer` 三态 / unsupported 恒五键 / 交易文案单源)+ CC-39② memory-status `autoConsolidationArmed` 三态 + CC-45 resume 补充句渲保留秒数;型面纯 additive、公面 985、peer 不动;§56。上一版 0.72.8 = **patch**:清账三票 —— `memory:"off"` 请求键(CC-39③,server 7.84.0 S-405)+ `runStream` 第二条中性臂 `Model output error:`(CC-43)+ 注入件撞活 run 自动 steer 零卡(CC-44);型面纯 additive、公面 977、peer 不动;§55。上一版 0.72.7 = **patch**:core 7.22.0 提货 —— 通告码 66 `mcp.server_redialed` + 读器 `readMcpServerRedialed` + `wiring_manifest.readDeny` 第九段 `_sema_readDeny`(缺席 = 没有内置行判这条腿);型面纯 additive、公面 971、peer 不动、devDep core ~7.22.0;§54。上一版 0.72.6 = **patch**:cli L-379 包侧半场 —— `steerFollowIntent` steer 后续听意图三态(tail / after-decision / after-wake)+ `activeRunSelfHealRow` 续听声明第五参;型面纯 additive、公面 969、peer 不动;§53。上一版 0.72.5 = **patch**:server 7.82.1 提货 —— `capabilities.webSearch.backend` 部署默认 WebSearch 后端四态读面(键缺席 = 老引擎判不了 ≠ `none`);型面纯 additive、公面 968、peer 不动;§52。上一版 0.72.4 = **patch**:core 7.21.x 三件经 server 7.82.0 提货 —— `wiring_manifest.autoConsolidation` 第八段 `_sema_autoConsolidation`(缺席 = indeterminate 不折 false);型面纯 additive、公面 962、peer 不动;§51。上一版 0.72.3 = **patch**:core #863 记忆单系统半场 ① —— `projectAgentsForWire` 投影 `agents[].memory`(user|project|local 三词同映射引擎平面 agent:<type>);型面纯 additive、公面 962、零 wire 新键、peer 不动;§50。上一版 0.72.2 = **patch**:workflow 视图两票 —— `LiveWorkflowController.resolution()` 六态(snapshot() 的 null 三义拆开)+ `noteOwnWorkflowRun` own 台账同拍登记;型面纯 additive、公面 961、零 wire 键、peer 不动;§49。上一版 0.72.1 = **patch**:server 7.80.1 提货 —— 409 `conflict.resume_context_unavailable` 结构读数(`staleAfterSec` / `runId`;sdk 9.6.0 尚未带键,经 sdk 今天恒缺席)+ `SkillSpec.baseDir`(只在本机车道带);型面纯 additive、公面 960、peer 不动;§48。上一版 0.72.0 = **minor**:型面 BREAKING —— 39 个零消费导出退出公面(CC-32 退役批,[7419] §45 预告 / cli [7422] 同意 / web-client·desktop 过节拍沉默 = 同意;名单见 §47a S-1);运行期零 BREAKING、公面 956、peer 不动、devDep core ~7.20.1;随批:已退役名账 `removed` + export-liveness 门 G 段 + 冻结账门 ⑧c;§47。上一版 0.71.4 = **patch**:core 7.20.1 提货 —— `ENGINE_NOTICE_CODES` 65 + `wiring_manifest.writeProtection` 第七段 `_sema_writeProtection`;型面纯 additive、公面 995、peer 不动、devDep core `~7.20.1`;§46。上一版 0.71.3 = **patch**:门体系清账批 —— CC-24 export-liveness 门 + 39 个导出退役预告(0.72.0 删,表态制)/ CC-26 `as unknown as` 铸链棘轮 / CC-25 冻结账门 ⑧ 段 / CC-06 B-081 包侧半场(终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` + resume reopen 族 + `routePairingVerdict`);型面纯 additive、公面 986 → 995、peer 不动;§45。上一版 0.71.2 = **patch**:接入方验收两票归包 —— CC-28 B-132 decide 拒体三句去内部车道词 / CC-29 B-133 committedUuids 唯一性(重复 ⇒ 形 f);零型面变化、公面 986、peer 不动;§44。上一版 0.71.1 = **patch**:接入档打回修正 —— CC-27 `ApprovalCardRequest.readRootCandidate?` 帧→卡透传位 + 新导出型 `ReadRootCandidateView`;型面纯 additive、公面 986 不变、peer 不动;§43。上一版 0.71.0 = **minor**:型面 BREAKING 六件 —— peer sdk 地板 >=9.6.0 + agent-types >=0.3.0 / `SkillsListingTruncatedFactsView` 删 `requestedBudgetBytes?`·`laneClamped?` / `WiringManifestMcpEntry` → `WiringManifestMcpEntryView` / `MAX_AGENT_SKILLS` 删 / `decide.workflow_host_not_parked` 退役;运行期零 BREAKING。内容:core 7.20.0 提货(闭集 +5 六十四码)/ 🔴 CC-16 `text_segment_end.committedUuids[]` / CC-08 全五件(tool_disclosure / tool_progress 两 chrome 臂、wiring_manifest tools·hooks·lsp 进切片、tool_roster_delta 接上、context_usage 进切片、`readRootCandidate` 镜像)/ CC-19 `mcpEngineLegPresence` 归包 / CC-20 not_parked clean-cut;公面 986;§42 / 42y 八条)|
23
23
  | peer:wire 契约 | `@sema-agent/sdk` **>=9.6.0**(value-level,非 type-only;**0.71.0 抬版**:`tool_disclosure` / `tool_progress` 两帧型与 `ToolApprovalFrame.readRootCandidate` 自 9.6.0 起;0.69.0 曾抬到 >=9.4.0(`reasoning_end` / `lastLegMcp`),0.60.0 抬到 >=8.4.0;地板由 `scripts/run-sdk-floor-test.mjs` 的 `FLOOR` 与 public-surface 门 C-CC-3「不低于见证到的最低实装版」双钉)| `package.json` `peerDependencies` |
24
24
  | peer:会话词汇表 | `@sema-agent/agent-types` **>=0.3.0**(type-only,零运行时;0.71.0 抬版:devDep 与 peer 同步,type-superset 门 ④ 撞名预警对着 0.3.0 的 .d.ts 求值) | 同上 |
25
25
  | runtime dep | `diff` ^9.0.0(**唯一**一条;portability 门按**等值**钉死) | `package.json` `dependencies` |
26
- | 公开导出面 | **989** 个运行期符号(+ 45 个测试钩;= 0.72.10 的值:相对 0.72.9 +4 —— CC-41 `LEADER_RUN_STATUSES` / `LEADER_REJ_HEAD_DISPLAY_MAX` / `projectLeaderConflict` / `leaderConflictDetail`;985 = 0.72.9 的值:相对 0.72.8 +8 —— CC-30 `MCP_RECONNECT_OUTCOMES` / `MCP_RECONNECT_TRANSACTION_NOTICE` / `projectMcpReconnectResult` / `classifyMcpReconnectFailure` / `reconnectMcpServer` / `projectMcpReconnectCapability` / `mcpReconnectOutcomeDetail`、CC-39② `readAutoConsolidationArmed`;977 = 0.72.8 的值:相对 0.72.7 +6 —— CC-39③ `MEMORY_OFF` / `memoryOffDeclarationField` / `memoryOffDeclared`、CC-43 `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`;971 = 0.72.7 的值:相对 0.72.6 +2 —— CC-42 core 7.22.0 提货 `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`;969 = 0.72.6 的值:相对 0.72.5 +1 —— CC-40 `steerFollowIntent`;968 = 0.72.5 的值:相对 0.72.4 +6 —— CC-31 server 7.82.1 提货 `capabilities.webSearch.backend` 四态读面:`WEB_SEARCH_BACKEND_NONE` / `projectWebSearchBackendCapability` / `observedWebSearchBackend` / `noteEngineCapsForWebSearchBackend` / `forgetWebSearchBackendReading` / `webSearchBackendDoctorDetail`;962 = 0.72.3 的值:相对 0.72.2 +1 —— CC-39① `AGENT_MEMORY_WORDS`;0.72.2 相对 0.72.1 +1 —— CC-37 `noteOwnWorkflowRun`;0.72.1 相对 0.72.0 +4 —— CC-33 server 7.80.1 提货:`RESUME_CONTEXT_UNAVAILABLE` / `resumeContextUnavailableFromError` / `resumeContextUnavailableContent` / `skillBaseDirOf`;0.72.0 相对 0.71.4 −39 —— CC-32 退役批删 export-liveness 登记 retire 的 39 个零消费导出(23 常量 + 16 函数,名单见 §47);995 = 0.71.3 的值:相对 0.71.2 +9 —— CC-06 `readEffectiveReasoning` / `readEffectiveMemoryScopes` / `resumeReopenFromError` / `resumeReopenContent` / `routePairingVerdict` 五函数 + `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` 四常量;986 = 0.71.0 的值:相对 0.70.2 −`MAX_AGENT_SKILLS` −`DECIDE_WORKFLOW_HOST_NOT_PARKED` +`projectToolRosterDelta` +`mcpEngineLegPresence`;986 = 0.70.0 的值:相对 0.69.2 **一件 additive(`readSkillsListingTruncated`,§39)、零删除**;985 = 0.69.2 的值:相对 0.69.1 **三件 additive、零删除**(CC-13 `isSubFlowSegmentEnd` / `SEGMENT_END_IDENTITY_KEYS` / `droppedWhySentence`,§38);982 = 0.69.0 未发布版的值(原排 0.68.3,因 peer 地板抬升改 minor)= 相对 0.68.2 **十七件 additive、零删除**:`fetchMcpPanel`(CC-03 补件,§36e)+ `readWorkflowResumeAdmissionIncomplete`(CC-05 core 7.18.0 #755)+ `installCoreValuePorts`/`hasCoreValuePorts`/`hasCoreValuePort`/`coreValuePortMisses`/`CORE_VALUE_PORT_NAMES` + 十读口(CC-07 core 值级端口,§36d);0.68.2 相对 0.68.1 十三件 additive:`SEMA_SEGMENT_ID_KEY`(CC-01 段身份键,§35f)/ `projectMcpPanel`+`mcpPanelLastLegDetail`+`projectMcpSection`(CC-03 `/mcp` 面板读视图,§35g)/ `resolveTextSegmentAuthority`/`createTextSegmentLedger`(L-318 `text_end` 权威段替换的判决单源 + print 形段账,详见 §35b/§35c)/ `memoryCaptureDeclarationField`/`MEMORY_CAPTURE_OFF`(L-316 会话级隐私声明的字面唯一铸点,§35d)/ `engineUrl`/`probeHealth`(L-61 件④ SDK 纯工具面原样转口,§35d)/ `AgentClient`/`isApprovalRequestFrameV1`/`isApprovalRevokeFrameV1`(L-61 存量清零:SDK **wire 面**原样转口,§35e)。`0.68.1`/`0.68.0` 是 **952**,那批是相对 0.67.2 **二十件 additive、🔴 两件删除(BREAKING)**:additive = `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`/`RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`RUN_TERMINAL_STATUSES`(L-247 终态词两表分源,详见 §33b)/ `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(L-244 子代下界位自有名,§33g)/ `ASK_UNRESOLVABLE_CAUSES`/`readAskUnresolvable`/`DURABLE_MANDATE_SOURCES`/`readDurableGateUnavailable`(core 7.17.0 #709 ①② 两只通告事实窄读器,§33c)/ `WORKFLOW_PARK_TRUTH_UNREADABLE`/`WORKFLOW_PARK_NOT_PENDING`/`WORKFLOW_PARK_BINDING_BROKEN`/`WORKFLOW_PARK_REQUIRES_RUN_STORE`(四个单码常量 🔧 0.72.0 退役)/`WORKFLOW_PARK_REFUSAL_CODES`/`isWorkflowParkRefusalCode`/`readWorkflowParks`(core 7.17.0 #652 park 真相四码 + parks 三键读器,§33d)/ `ENGINE_STOP_REASONS`/`engineStopReasonToCc`(L-246 A13 停止原词映射下沉,§33g)/ `readCancelRequested`(L-230 读面,§33f);🔴 **删除两件** `TERMINAL_NOT_SUCCESS_STATUSES`/`TERMINAL_STATUSES`(随 L-247 两表分源更名成 `RUN_TERMINAL_*`,clean-cut **不留别名** —— 留一个别名等于让端可以继续按合起来的那张表读,分源就白做了,详见 §33b)。`0.67.0` 是 **934**,那批是相对 0.66.0 **七件 additive、🔴 两件删除**:additive = `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`(core 7.14.0 退役 `classifierUnavailable` 之后的**拒绝面**继任读器与措辞,详见 §32b)/ `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`(core 7.14.0 #688 C3 的规则店机制位三件,详见 §32d);🔴 **删除两件** `classifierUnavailableOf`/`classifierUnavailableDetail`(随 core 7.14.0 的 Retired keys 表整族退役,clean-cut 不留别名,详见 §32b;同批删的还有**型** `ClassifierUnavailableView`、卡位与帧位 `classifierUnavailable`、以及一条恒真的型面钉 `_askOriginWordsPin`)。`0.66.0` 是 **929**,那批是一件 additive、零删除:`readRunCostFacts`(终局成本事实的唯一读器:`costBreakdown` / `nested` 窄读 + 对账三段与两个判别位,终帧超集键与 chrome 对账臂共用它;详见 §31c);已发的 **0.65.x 十一件 additive、两件删除**:additive = `DECIDE_WORKFLOW_HOST_UNKNOWN`/`DECIDE_WORKFLOW_HOST_NOT_PARKED`/`DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED`/`DECIDE_WORKFLOW_LANE_CODES`/`readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070 `/decide` 回执读面与三码人话,详见 §30h)/ `TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇单铸谓词,详见 §30j);🔴 **删除两件** `AUTO_MODE_BREAKER_CAUSES`/`classifierBreakerOf`(熔断族随 core 7.12.0 的 Removed(BREAKING) 整只退役,clean-cut 不留别名,详见 §30k②;同批删的还有**型** `ClassifierBreakerView` 与 `ClassifierStatusView.breaker` 一位)。`0.64.2` 是 **919**,那批是一件 additive、零删除:`readDenialLimitFallback`(限额回落卡的窄读器上公面,壳侧同判据副本退役,详见 §29③);`0.64.0` 是 **918**,那批是件①+件② 十三件 additive、零删除:`CLASSIFIER_STATUS_STATES`/`classifierBreakerOf`/`classifierStatusOf`/`classifierStatusDetail`(分类器状态面,详见 §28②)/ `THINKING_FORMATS`/`THINKING_FORMAT_WIRE_TWINS`/`THINKING_DISABLE_PROBE_ORDER`/`MODEL_PROBE_VERDICTS`/`PROBE_PROMPT`/`PROBE_MAX_TOKENS`(两个探针常量 🔧 0.72.0 退役)/`probeRequestBody`/`probeModelCapability`/`applyProbeToEntry`(模型思考能力探测,详见 §28①);`0.63.0` 是 **905**,那批是八件 additive、零删除:`projectServerGateKnobs`/`postureKnobSourceOf`/`postureSourceIsOperatorPinned`/`postureKnobDetail`/`POSTURE_SOURCE_WORDS`(S-178 三根 posture 旋钮读数,详见 §27b)/ `PERSISTED_RULE_BEHAVIORS`/`PERSISTED_RULE_BEHAVIOR_UNKNOWN`/`persistedRuleBehaviorOf`/`persistedRuleBehaviorLabel`/`revokeTargetFromPersistedRule`(三态规则身份,§27c)/ `engineIdentityOf`/`engineIdentityVerdict`/`engineIdentityChanged`/`engineIdentityChangedBy`/`ENGINE_IDENTITY_ANCHORS`(S-179 代际锚,§27d)/ `GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail`(门词汇 +2,§27e)/ `PERMISSION_RULE_ISSUE_CODES`/`RETIRED_PERMISSION_RULE_ISSUE_CODES`/`permissionRuleIssueDetail`(规则 lint 码表,§27f)/ `projectToolRoster`/`toolRosterNames`/`toolShimFromRoster`/`applyToolRosterDelta`(L-161 工具名册,§27g)/ `ENGINE_NOTICE_CODES`/`ENGINE_NOTICE_AUDIENCE`/`noticeAudienceOf`/`engineNoticeInCatalog`/`MCP_INJECTION_DROP_REASONS`/`readMcpInjectionDrop`(L-167 通告码册,§27h)/ `AUTO_MODE_UNAVAILABLE_CAUSES`/`AUTO_MODE_BREAKER_CAUSES`/`classifierUnavailableOf`/`classifierUnavailableDetail`(件⑧ 分类器不可用事实,§27h2);`0.62.0` 是 **869**,那批是五件 additive、**零删除**:`capForDisplay`(呈前消毒 + 封长的共用铸点,详见 §26⑦)/ `SEAT_SEND_MESSAGE_KEY_ORIGINS`(座位载荷逐键出身表,详见 §26③)/ `configureSubagentContentStore`+`subagentContentStoreConfig`+`SUBAGENT_CONTENT_STORE_DEFAULTS`(子代内容账本字节预算,测试钩 `__resetSubagentContentStoreConfigForTests` +1,详见 §26②);`0.61.0` 是 **864**,那批是三件 additive、**零删除**:`projectReadFacePosture`/`readFacePostureDetail`/`readFaceDisagreement`(S-167 READ 容纳面 operator 读器,详见 §25);`0.60.0` 是 **861**,那批是二十五件 additive、**零删除**:`readRunTerminal`/`runTerminalCode`/`runTerminalGateKind`/`runTerminalGateToolName`/`isReviewPark`/`REVIEW_PARK_GATE_KINDS` 六件终局因由读器 + `gateOutcomeOf`/`isDeniedGate`/`gateDeniedBy`/`gateApprover`/`isApprovalWindowExpiredGate`/`isDenialLimitAutoDeniedGate`/`isParkSlaExpiredGate`/`isHumanSettledGate` 八件门记录读器 + `projectWriteProtectionCapability`/`noteEngineCapsForWriteProtection`/`observedWriteProtection`/`forgetWriteProtectionReading`/`writeProtectionDoctorDetail`/`projectWriteProtectionPosture`/`writeProtectionPostureDetail` 七件写保护读面(测试钩 `__resetWriteProtectionReadingsForTests` +1)+ `readWireErrorCode` + 真机边界①的两件 `isGateParkedToolEnd`/`GATE_PARKED_ERROR_CODE` + 异源复审逼出的 `engineCapsGeneration`;`0.59.0` 是 **836**,那批是八件 additive:`RULE_OFFERS_ABSENCE_REASONS`/`DENIAL_LIMIT_KINDS` 两张闭词表再导出 + `engineCapValue` 能力位四态通用读口 + `projectSqlEngineCapability`/`observedSqlEngine`/`noteEngineCapsForSqlEngine`/`forgetSqlEngineReading`/`sqlEngineDoctorDetail` 五件 SQL 姿态读面(测试钩 `__resetSqlEngineReadingsForTests` +1);`0.58.0` 是 **828**,那批是三件 additive:`RULE_OFFER_MATCHES`/`RULE_OFFER_BATCH_MEMBER_KINDS`/`RULE_OFFER_UNCOVERED_REASONS` 三张闭词表再导出 + `RESUME_REFUSAL_CODES`/`RESUME_PLACEMENT_MISMATCH`/`resumeRefusalFromError`/`resumeRefusalContent` 四件文案铸点;`0.57.0` 是 **821**;`0.56.0`/`0.55.0` 是 **815**;已发 `0.54.0`(design/385 十件 additive 含 `AUTHORITY_ENVELOPE_TAGS` 🔧 0.72.0 退役);`0.52.0` 是 **805**(L-69⑨ 两件);`0.51.0` 是 **803**;`0.50.0` 是 **800**(S-81 五件);`0.49.0` 是 **795**;`0.48.0` 是 **794**;npm `0.47.0` 是 **790**,`0.46.0` 是 **787**,`0.44.0` 是 **783**,`0.43.1`/`0.43.0` 是 **776**,`0.42.0` 是 **771**,`0.41.0` 是 **767**,`0.39.0` 是 **766**,`0.38.0` 是 **764**;`0.37.0` 是 **753**,见 `CHANGELOG.md`) | `scripts/public-export-baseline.json` 的 `count` / `testHookCount` —— **别手抄进别处,以该文件为准** |
26
+ | 公开导出面 | **993** 个运行期符号(+ 45 个测试钩;= 0.72.12 的值:相对 0.72.11 +4 —— CC-50 `OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText` / `TASK_NOTIFICATION_TERMINAL_STATUSES` / `isTaskNotificationTerminalStatus`;989 = 0.72.10 的值:相对 0.72.9 +4 —— CC-41 `LEADER_RUN_STATUSES` / `LEADER_REJ_HEAD_DISPLAY_MAX` / `projectLeaderConflict` / `leaderConflictDetail`;985 = 0.72.9 的值:相对 0.72.8 +8 —— CC-30 `MCP_RECONNECT_OUTCOMES` / `MCP_RECONNECT_TRANSACTION_NOTICE` / `projectMcpReconnectResult` / `classifyMcpReconnectFailure` / `reconnectMcpServer` / `projectMcpReconnectCapability` / `mcpReconnectOutcomeDetail`、CC-39② `readAutoConsolidationArmed`;977 = 0.72.8 的值:相对 0.72.7 +6 —— CC-39③ `MEMORY_OFF` / `memoryOffDeclarationField` / `memoryOffDeclared`、CC-43 `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`;971 = 0.72.7 的值:相对 0.72.6 +2 —— CC-42 core 7.22.0 提货 `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`;969 = 0.72.6 的值:相对 0.72.5 +1 —— CC-40 `steerFollowIntent`;968 = 0.72.5 的值:相对 0.72.4 +6 —— CC-31 server 7.82.1 提货 `capabilities.webSearch.backend` 四态读面:`WEB_SEARCH_BACKEND_NONE` / `projectWebSearchBackendCapability` / `observedWebSearchBackend` / `noteEngineCapsForWebSearchBackend` / `forgetWebSearchBackendReading` / `webSearchBackendDoctorDetail`;962 = 0.72.3 的值:相对 0.72.2 +1 —— CC-39① `AGENT_MEMORY_WORDS`;0.72.2 相对 0.72.1 +1 —— CC-37 `noteOwnWorkflowRun`;0.72.1 相对 0.72.0 +4 —— CC-33 server 7.80.1 提货:`RESUME_CONTEXT_UNAVAILABLE` / `resumeContextUnavailableFromError` / `resumeContextUnavailableContent` / `skillBaseDirOf`;0.72.0 相对 0.71.4 −39 —— CC-32 退役批删 export-liveness 登记 retire 的 39 个零消费导出(23 常量 + 16 函数,名单见 §47);995 = 0.71.3 的值:相对 0.71.2 +9 —— CC-06 `readEffectiveReasoning` / `readEffectiveMemoryScopes` / `resumeReopenFromError` / `resumeReopenContent` / `routePairingVerdict` 五函数 + `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` 四常量;986 = 0.71.0 的值:相对 0.70.2 −`MAX_AGENT_SKILLS` −`DECIDE_WORKFLOW_HOST_NOT_PARKED` +`projectToolRosterDelta` +`mcpEngineLegPresence`;986 = 0.70.0 的值:相对 0.69.2 **一件 additive(`readSkillsListingTruncated`,§39)、零删除**;985 = 0.69.2 的值:相对 0.69.1 **三件 additive、零删除**(CC-13 `isSubFlowSegmentEnd` / `SEGMENT_END_IDENTITY_KEYS` / `droppedWhySentence`,§38);982 = 0.69.0 未发布版的值(原排 0.68.3,因 peer 地板抬升改 minor)= 相对 0.68.2 **十七件 additive、零删除**:`fetchMcpPanel`(CC-03 补件,§36e)+ `readWorkflowResumeAdmissionIncomplete`(CC-05 core 7.18.0 #755)+ `installCoreValuePorts`/`hasCoreValuePorts`/`hasCoreValuePort`/`coreValuePortMisses`/`CORE_VALUE_PORT_NAMES` + 十读口(CC-07 core 值级端口,§36d);0.68.2 相对 0.68.1 十三件 additive:`SEMA_SEGMENT_ID_KEY`(CC-01 段身份键,§35f)/ `projectMcpPanel`+`mcpPanelLastLegDetail`+`projectMcpSection`(CC-03 `/mcp` 面板读视图,§35g)/ `resolveTextSegmentAuthority`/`createTextSegmentLedger`(L-318 `text_end` 权威段替换的判决单源 + print 形段账,详见 §35b/§35c)/ `memoryCaptureDeclarationField`/`MEMORY_CAPTURE_OFF`(L-316 会话级隐私声明的字面唯一铸点,§35d)/ `engineUrl`/`probeHealth`(L-61 件④ SDK 纯工具面原样转口,§35d)/ `AgentClient`/`isApprovalRequestFrameV1`/`isApprovalRevokeFrameV1`(L-61 存量清零:SDK **wire 面**原样转口,§35e)。`0.68.1`/`0.68.0` 是 **952**,那批是相对 0.67.2 **二十件 additive、🔴 两件删除(BREAKING)**:additive = `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`/`RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`RUN_TERMINAL_STATUSES`(L-247 终态词两表分源,详见 §33b)/ `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(L-244 子代下界位自有名,§33g)/ `ASK_UNRESOLVABLE_CAUSES`/`readAskUnresolvable`/`DURABLE_MANDATE_SOURCES`/`readDurableGateUnavailable`(core 7.17.0 #709 ①② 两只通告事实窄读器,§33c)/ `WORKFLOW_PARK_TRUTH_UNREADABLE`/`WORKFLOW_PARK_NOT_PENDING`/`WORKFLOW_PARK_BINDING_BROKEN`/`WORKFLOW_PARK_REQUIRES_RUN_STORE`(四个单码常量 🔧 0.72.0 退役)/`WORKFLOW_PARK_REFUSAL_CODES`/`isWorkflowParkRefusalCode`/`readWorkflowParks`(core 7.17.0 #652 park 真相四码 + parks 三键读器,§33d)/ `ENGINE_STOP_REASONS`/`engineStopReasonToCc`(L-246 A13 停止原词映射下沉,§33g)/ `readCancelRequested`(L-230 读面,§33f);🔴 **删除两件** `TERMINAL_NOT_SUCCESS_STATUSES`/`TERMINAL_STATUSES`(随 L-247 两表分源更名成 `RUN_TERMINAL_*`,clean-cut **不留别名** —— 留一个别名等于让端可以继续按合起来的那张表读,分源就白做了,详见 §33b)。`0.67.0` 是 **934**,那批是相对 0.66.0 **七件 additive、🔴 两件删除**:additive = `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`(core 7.14.0 退役 `classifierUnavailable` 之后的**拒绝面**继任读器与措辞,详见 §32b)/ `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`(core 7.14.0 #688 C3 的规则店机制位三件,详见 §32d);🔴 **删除两件** `classifierUnavailableOf`/`classifierUnavailableDetail`(随 core 7.14.0 的 Retired keys 表整族退役,clean-cut 不留别名,详见 §32b;同批删的还有**型** `ClassifierUnavailableView`、卡位与帧位 `classifierUnavailable`、以及一条恒真的型面钉 `_askOriginWordsPin`)。`0.66.0` 是 **929**,那批是一件 additive、零删除:`readRunCostFacts`(终局成本事实的唯一读器:`costBreakdown` / `nested` 窄读 + 对账三段与两个判别位,终帧超集键与 chrome 对账臂共用它;详见 §31c);已发的 **0.65.x 十一件 additive、两件删除**:additive = `DECIDE_WORKFLOW_HOST_UNKNOWN`/`DECIDE_WORKFLOW_HOST_NOT_PARKED`/`DECIDE_WORKFLOW_REMEMBER_UNSUPPORTED`/`DECIDE_WORKFLOW_LANE_CODES`/`readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070 `/decide` 回执读面与三码人话,详见 §30h)/ `TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇单铸谓词,详见 §30j);🔴 **删除两件** `AUTO_MODE_BREAKER_CAUSES`/`classifierBreakerOf`(熔断族随 core 7.12.0 的 Removed(BREAKING) 整只退役,clean-cut 不留别名,详见 §30k②;同批删的还有**型** `ClassifierBreakerView` 与 `ClassifierStatusView.breaker` 一位)。`0.64.2` 是 **919**,那批是一件 additive、零删除:`readDenialLimitFallback`(限额回落卡的窄读器上公面,壳侧同判据副本退役,详见 §29③);`0.64.0` 是 **918**,那批是件①+件② 十三件 additive、零删除:`CLASSIFIER_STATUS_STATES`/`classifierBreakerOf`/`classifierStatusOf`/`classifierStatusDetail`(分类器状态面,详见 §28②)/ `THINKING_FORMATS`/`THINKING_FORMAT_WIRE_TWINS`/`THINKING_DISABLE_PROBE_ORDER`/`MODEL_PROBE_VERDICTS`/`PROBE_PROMPT`/`PROBE_MAX_TOKENS`(两个探针常量 🔧 0.72.0 退役)/`probeRequestBody`/`probeModelCapability`/`applyProbeToEntry`(模型思考能力探测,详见 §28①);`0.63.0` 是 **905**,那批是八件 additive、零删除:`projectServerGateKnobs`/`postureKnobSourceOf`/`postureSourceIsOperatorPinned`/`postureKnobDetail`/`POSTURE_SOURCE_WORDS`(S-178 三根 posture 旋钮读数,详见 §27b)/ `PERSISTED_RULE_BEHAVIORS`/`PERSISTED_RULE_BEHAVIOR_UNKNOWN`/`persistedRuleBehaviorOf`/`persistedRuleBehaviorLabel`/`revokeTargetFromPersistedRule`(三态规则身份,§27c)/ `engineIdentityOf`/`engineIdentityVerdict`/`engineIdentityChanged`/`engineIdentityChangedBy`/`ENGINE_IDENTITY_ANCHORS`(S-179 代际锚,§27d)/ `GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail`(门词汇 +2,§27e)/ `PERMISSION_RULE_ISSUE_CODES`/`RETIRED_PERMISSION_RULE_ISSUE_CODES`/`permissionRuleIssueDetail`(规则 lint 码表,§27f)/ `projectToolRoster`/`toolRosterNames`/`toolShimFromRoster`/`applyToolRosterDelta`(L-161 工具名册,§27g)/ `ENGINE_NOTICE_CODES`/`ENGINE_NOTICE_AUDIENCE`/`noticeAudienceOf`/`engineNoticeInCatalog`/`MCP_INJECTION_DROP_REASONS`/`readMcpInjectionDrop`(L-167 通告码册,§27h)/ `AUTO_MODE_UNAVAILABLE_CAUSES`/`AUTO_MODE_BREAKER_CAUSES`/`classifierUnavailableOf`/`classifierUnavailableDetail`(件⑧ 分类器不可用事实,§27h2);`0.62.0` 是 **869**,那批是五件 additive、**零删除**:`capForDisplay`(呈前消毒 + 封长的共用铸点,详见 §26⑦)/ `SEAT_SEND_MESSAGE_KEY_ORIGINS`(座位载荷逐键出身表,详见 §26③)/ `configureSubagentContentStore`+`subagentContentStoreConfig`+`SUBAGENT_CONTENT_STORE_DEFAULTS`(子代内容账本字节预算,测试钩 `__resetSubagentContentStoreConfigForTests` +1,详见 §26②);`0.61.0` 是 **864**,那批是三件 additive、**零删除**:`projectReadFacePosture`/`readFacePostureDetail`/`readFaceDisagreement`(S-167 READ 容纳面 operator 读器,详见 §25);`0.60.0` 是 **861**,那批是二十五件 additive、**零删除**:`readRunTerminal`/`runTerminalCode`/`runTerminalGateKind`/`runTerminalGateToolName`/`isReviewPark`/`REVIEW_PARK_GATE_KINDS` 六件终局因由读器 + `gateOutcomeOf`/`isDeniedGate`/`gateDeniedBy`/`gateApprover`/`isApprovalWindowExpiredGate`/`isDenialLimitAutoDeniedGate`/`isParkSlaExpiredGate`/`isHumanSettledGate` 八件门记录读器 + `projectWriteProtectionCapability`/`noteEngineCapsForWriteProtection`/`observedWriteProtection`/`forgetWriteProtectionReading`/`writeProtectionDoctorDetail`/`projectWriteProtectionPosture`/`writeProtectionPostureDetail` 七件写保护读面(测试钩 `__resetWriteProtectionReadingsForTests` +1)+ `readWireErrorCode` + 真机边界①的两件 `isGateParkedToolEnd`/`GATE_PARKED_ERROR_CODE` + 异源复审逼出的 `engineCapsGeneration`;`0.59.0` 是 **836**,那批是八件 additive:`RULE_OFFERS_ABSENCE_REASONS`/`DENIAL_LIMIT_KINDS` 两张闭词表再导出 + `engineCapValue` 能力位四态通用读口 + `projectSqlEngineCapability`/`observedSqlEngine`/`noteEngineCapsForSqlEngine`/`forgetSqlEngineReading`/`sqlEngineDoctorDetail` 五件 SQL 姿态读面(测试钩 `__resetSqlEngineReadingsForTests` +1);`0.58.0` 是 **828**,那批是三件 additive:`RULE_OFFER_MATCHES`/`RULE_OFFER_BATCH_MEMBER_KINDS`/`RULE_OFFER_UNCOVERED_REASONS` 三张闭词表再导出 + `RESUME_REFUSAL_CODES`/`RESUME_PLACEMENT_MISMATCH`/`resumeRefusalFromError`/`resumeRefusalContent` 四件文案铸点;`0.57.0` 是 **821**;`0.56.0`/`0.55.0` 是 **815**;已发 `0.54.0`(design/385 十件 additive 含 `AUTHORITY_ENVELOPE_TAGS` 🔧 0.72.0 退役);`0.52.0` 是 **805**(L-69⑨ 两件);`0.51.0` 是 **803**;`0.50.0` 是 **800**(S-81 五件);`0.49.0` 是 **795**;`0.48.0` 是 **794**;npm `0.47.0` 是 **790**,`0.46.0` 是 **787**,`0.44.0` 是 **783**,`0.43.1`/`0.43.0` 是 **776**,`0.42.0` 是 **771**,`0.41.0` 是 **767**,`0.39.0` 是 **766**,`0.38.0` 是 **764**;`0.37.0` 是 **753**,见 `CHANGELOG.md`) | `scripts/public-export-baseline.json` 的 `count` / `testHookCount` —— **别手抄进别处,以该文件为准** |
27
27
  | 常驻门 | 以 `scripts/gates-manifest.json` 的 `suites` 长度为准(**本档不抄这个数**) | `scripts/gates-manifest.json`;`npm test` 的名单等值门与它逐名对账 |
28
28
  | 沿革档 | 0.29.0 起建 `CHANGELOG.md`;更早批次记账在 `src/index.ts` 文件头 + `docs/REFACTOR-LEDGER.md` | — |
29
29
 
@@ -121,7 +121,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
121
121
 
122
122
  ## §2 公共导出面地图(按域)
123
123
 
124
- > 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**989** 项)。
124
+ > 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**993** 项)。
125
125
  > 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
126
126
  > **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
127
127
  > 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
@@ -145,16 +145,16 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
145
145
  `WorkflowsGateUnknownDenial` 四形**不在**基线里,`src/selfOrchestrationDenial.ts` 对基线贡献
146
146
  **4** 项运行期导出(三个函数 + `SELF_ORCHESTRATION_RETRY_WITHOUT`)。
147
147
 
148
- 989 项的内部构成(帮助端估读表大小;0.72.10 +2 常量 +2 函数(CC-41);0.72.9 +2 常量 +6 函数(CC-30 / CC-39②);0.72.8 +2 常量 +4 函数(CC-39③ / CC-43);0.72.7 +1 常量 +1 函数(CC-42);0.72.6 +1 函数(CC-40);0.72.5 +1 常量 +5 函数(CC-31);0.72.3 +1 常量(CC-39①);0.72.2 +1 函数(CC-37);0.72.1 +1 常量 +3 函数(CC-33);0.72.0 −23 常量 −16 函数(CC-32 退役批);0.71.3 +4 常量 +5 函数(CC-06);0.71.0 −2 常量 `MAX_AGENT_SKILLS` / `DECIDE_WORKFLOW_HOST_NOT_PARKED` +2 函数 `projectToolRosterDelta` / `mcpEngineLegPresence`;0.70.0 起 +1 函数;0.69.2 起 +3:常量 1 / 函数 2):**288** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
148
+ 993 项的内部构成(帮助端估读表大小;0.72.12 +2 常量 +2 函数(CC-50);0.72.10 +2 常量 +2 函数(CC-41);0.72.9 +2 常量 +6 函数(CC-30 / CC-39②);0.72.8 +2 常量 +4 函数(CC-39③ / CC-43);0.72.7 +1 常量 +1 函数(CC-42);0.72.6 +1 函数(CC-40);0.72.5 +1 常量 +5 函数(CC-31);0.72.3 +1 常量(CC-39①);0.72.2 +1 函数(CC-37);0.72.1 +1 常量 +3 函数(CC-33);0.72.0 −23 常量 −16 函数(CC-32 退役批);0.71.3 +4 常量 +5 函数(CC-06);0.71.0 −2 常量 `MAX_AGENT_SKILLS` / `DECIDE_WORKFLOW_HOST_NOT_PARKED` +2 函数 `projectToolRosterDelta` / `mcpEngineLegPresence`;0.70.0 起 +1 函数;0.69.2 起 +3:常量 1 / 函数 2):**290** 项是 `SCREAMING_SNAKE` 常量数据表/词汇表
149
149
  (矩阵、键集、env 名、锚串)而非可调用物;**6** 项是 PascalCase 运行期值
150
150
  (`ControlRouter` / `ControlSafetyError` / `HitlBridge` / `HitlSafetyError` / `DecideTransportRetryExhaustedError`);
151
151
  **37** 项是 `*For(sessionKey, …)` 的 per-session 变体(0.72.0 −4:`clearArmedGateFor` / `onGateArmedFor` / `registerArmedGateFromQuestionIdFor` / `notePlanReviewAnsweredIfDecisiveFor` 退出公面)(§6;其中 `engineNamespaceKeyFor` 是命名巧合 —— 参数是 baseUrl 不是 sessionKey,见域 14)。
152
152
 
153
- ### 2b. 域图(16 域,逐域计数之和 = 989)
153
+ ### 2b. 域图(16 域,逐域计数之和 = 993)
154
154
 
155
155
  | # | 域 | 名数 | 承重导出 | 用途 | 实现锚 |
156
156
  |---|---|---|---|---|---|
157
- | 1 | **适配内核(下行主链)** | 60 | `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`(0.72.8 CC-43:runStream 第二条中性臂 —— core malformed tool-call 一族的行身份;§55)· `readEffectiveReasoning` · `readEffectiveMemoryScopes`(0.71.3 CC-06:终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` 的窄读器,§45)· `isSubFlowSegmentEnd` · `SEGMENT_END_IDENTITY_KEYS` · `droppedWhySentence`(0.69.2 CC-13:三件出公面,§38)· `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `SEMA_SEGMENT_ID_KEY`(0.68.2 CC-01:committed assistant 文本行顶层段身份键的唯一字面量出处,壳只读)· `projectMcpSection`(0.68.2 CC-03:`wiring_manifest.mcp[]` 与 `/mcp` 面板 `lastLegMcp.mcp[]` 共用的同一只条目读器)· `readRunCostFacts`(0.66.0:终局成本事实的**唯一读器** —— `TaskStats.costBreakdown` / `nested` 逐键窄读 + 对账三段(own/nested/compaction)与两个「没定价」判别位;终帧的两个超集键与 chrome 臂 `run_cost_reconciled` **共用它**,两面不会各算各的,详见 §31c)· `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`(0.68.0 / L-247:**core 终局因由**闭集,四词 `completed|failed|blocked|paused`)· `RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`RUN_TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇的**单铸谓词**,0.68.0 随 L-247 **两表分源**更名 —— `killed` 属 server run 行状态面、`paused` 属 core 因由面,合成一张会让两边加词时都读不出该改哪儿;`blocked` 是 agent 自报终态,`suspended`/`needs_review` 刻意不在表里,详见 §33b / §30j)· `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(0.68.0 / L-244:子代用量下界位的**自有名**与唯一判据,与终帧 `_sema_usage_lower_bound` 分名,详见 §33g) · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` · `readRunTerminal` / `runTerminalCode` / `runTerminalGateKind` / `runTerminalGateToolName` / `isReviewPark` / `REVIEW_PARK_GATE_KINDS`(0.60.0 / engine ≥7.64.0:一次 run **怎么结束的**唯一读器 —— 终局从八个平面键换成一条带标因由 `terminal`,四臂 + `unknown` 防御臂 + `plane` 两代字节标;🔴 不认识的终态词绝不折成成功、本包不提供「因由→五词 status」的兼容投影,详见 §24b)| 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts`、`src/runTerminal.ts` |
157
+ | 1 | **适配内核(下行主链)** | 62 | `OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText`(0.72.12 CC-50:第三条中性终局行「结局不知道」,读结果帧 `_sema_outcome`;§59)· `MODEL_OUTPUT_ERROR_PREFIX` / `isModelOutputErrorText` / `isModelOutputErrorRowText`(0.72.8 CC-43:runStream 第二条中性臂 —— core malformed tool-call 一族的行身份;§55)· `readEffectiveReasoning` · `readEffectiveMemoryScopes`(0.71.3 CC-06:终帧 `_sema_effective_reasoning` / `_sema_effective_memory_scopes` 的窄读器,§45)· `isSubFlowSegmentEnd` · `SEGMENT_END_IDENTITY_KEYS` · `droppedWhySentence`(0.69.2 CC-13:三件出公面,§38)· `adapt` · `createWireToCcAdapter` · `runStream` · `eventToSdkMessage` · `terminalToSdkResult` · `SEMA_SEGMENT_ID_KEY`(0.68.2 CC-01:committed assistant 文本行顶层段身份键的唯一字面量出处,壳只读)· `projectMcpSection`(0.68.2 CC-03:`wiring_manifest.mcp[]` 与 `/mcp` 面板 `lastLegMcp.mcp[]` 共用的同一只条目读器)· `readRunCostFacts`(0.66.0:终局成本事实的**唯一读器** —— `TaskStats.costBreakdown` / `nested` 逐键窄读 + 对账三段(own/nested/compaction)与两个「没定价」判别位;终帧的两个超集键与 chrome 臂 `run_cost_reconciled` **共用它**,两面不会各算各的,详见 §31c)· `TERMINAL_CAUSE_KINDS`/`isTerminalCauseKind`(0.68.0 / L-247:**core 终局因由**闭集,四词 `completed|failed|blocked|paused`)· `RUN_TERMINAL_NOT_SUCCESS_STATUSES`/`isTerminalNotSuccess`/`RUN_TERMINAL_STATUSES`/`isTerminalStatus`(L-215② 终局词汇的**单铸谓词**,0.68.0 随 L-247 **两表分源**更名 —— `killed` 属 server run 行状态面、`paused` 属 core 因由面,合成一张会让两边加词时都读不出该改哪儿;`blocked` 是 agent 自报终态,`suspended`/`needs_review` 刻意不在表里,详见 §33b / §30j)· `SEMA_SUBAGENT_USAGE_PARTIAL_KEY`/`subagentUsageIsPartial`(0.68.0 / L-244:子代用量下界位的**自有名**与唯一判据,与终帧 `_sema_usage_lower_bound` 分名,详见 §33g) · `turnUsageToModelUsage` · `isRunStreamActive` · `ADAPTER_DIVERGENCES` · `readRunTerminal` / `runTerminalCode` / `runTerminalGateKind` / `runTerminalGateToolName` / `isReviewPark` / `REVIEW_PARK_GATE_KINDS`(0.60.0 / engine ≥7.64.0:一次 run **怎么结束的**唯一读器 —— 终局从八个平面键换成一条带标因由 `terminal`,四臂 + `unknown` 防御臂 + `plane` 两代字节标;🔴 不认识的终态词绝不折成成功、本包不提供「因由→五词 status」的兼容投影,详见 §24b)| 引擎 SSE `AgentEvent` → 端要渲的**双面输出**:transcript(`SDKMessage`)+ chrome(瞬态 `ChromeEvent`)。**本包存在的理由** | `src/adapt.ts`、`src/adapt/{arms,wireShapes,panelTasks}.ts`(经 `adapt.ts` 再导出)、`src/adapter/runStream.ts`、`src/adapter/downstream/*`、`src/adapter/types.ts`、`src/runTerminal.ts` |
158
158
  | 2 | **seam 公共契约** | 2(其余为 type-only) | `CHROME_ARMS` · `deriveTranscriptId` | 公共词汇 + **id 确定性不变量**(同一条流重放 ⇒ 同一串 id)。`CHROME_ARMS` = 端「我要消费哪些 chrome 臂」的对照清单 | `src/seam.ts` |
159
159
  | 3 | **HITL 决断卡链**(§4/§5 主战场) | 160 | `makeHitlCanUseTool` · `HitlBridge` · `findPendingForTask` · `readDecideReceipt`/`decideAcceptedNotResolved`/`decideRefusalFromError`(B-070:`/decide` 200 = **投递受理**不是「门已解决」;`executionOutcome` 缺席 = 未知,详见 §30h) · `HitlSafetyError` · `bridgeAskUserQuestionGates` · `surfaceToolApprovalFrameAndRespond` / `surfaceFsApprovalAndDecide` · `readToolApprovalRespondAck` · `installApprovalCardPort(For)` · `installHitlHostSurface(For)` · `armPlanReviewApproval` · `reopenPlanReviewCard` · `decidePlanReview` · `startApprovalsFeed` · `pendingRowIsOwnedByThisSession` · `approvalCallKey`/`liveFrameCallKey`/`planReviewQuestionId` · `registerArmedGateFor`/`wasGateArmedFor` · `waitForGateArmed(For)`/`onGateArmed`/`gateArmedWaitMs`(#244 F1 呈现回执事件源) · `planReviewArmedKey(For)`/`notePlanReviewAnswered(For)`/`notePlanReviewAnsweredIfDecisive`(A-024.4 plan 呈现分代) · `toolEndOutputText` · `isAskTool` · `waitForParkRowBirth` · `classifyAskParkRows` / `askParkRowArm` / `classifyAskParkChainFailure` · `readDecisionNoteAudit` / `decisionNoteAuditLine` · `resumeRunningOptions` / `resumeChoiceFromLabels` · `persistedRulesLaneAvailable`/`persistedRulesGovernanceAvailable` · `classifyRulesFailure` · `listAllPersistedRules` · `classifySkippedReason` · `readRulePersistOutcome`(#244 F2:persist-ack 读口与 `readToolApprovalRespondAck` 合成一处) · `parseLocalAllowRule`(durable 腿本地落规则窄化骨架,谓词经 `LocalAllowRuleDeps` 注入) · `readToolApprovalRespondRefusal`(#225 件5,0.42.0:respond 抛错的结构化原文读口 —— 三位各自防御读、各自缺席不铸、**三位皆缺席时整只返 `undefined`**;原样交还零加工,UNTRUSTED-for-display)· `installEditedRuleTextPrechecker` / `hasEditedRuleTextPrechecker` / `precheckEditedRuleText`([5076] 转出口,0.42.0:core 5.57.0 `precheckEditedRuleText` 的**端口注入形** —— 类型面 + 注入口 + 诚实缺席读口。🔴 **不是** value 级 re-export,理由见 §7 缺口 **P-34**;未装 ⇒ 返 `undefined`,绝不编一个 `{ok:true}`)· `surfaceRuleArmNotSent` / `RULE_NOT_SENT_WARN_TEXT` + `surfaceRuleArmRejected` / `RULE_NOT_SENT_REJECTED_WARN_TEXT`(#334,0.43.0:人在卡上按下的「不再询问」被整条丢弃时的诚实告知——**两条刻意分开**:前者=**引擎能力位未确认**(换台引擎/等探测就好),后者=**这次选择没过包内表核/互斥核**(表外文本/坏下标/两臂同场,换引擎也不会变) —— 编辑臂 `respondFreeFormRules` 与批臂 `respondBatchRuleOffers` 两条同形存量共用一条,与 `surfaceRememberNotApplied` 同族纪律:决断照送、只是规则没存,静默丢掉用户明确意图 = 让人以为功能坏了)· `projectCrashConverged`(L-38,0.49.0:`/v1/approvals` additive 键 `crashConverged` 的分桶投影 —— 崩溃收敛的孤儿审批读面,**缺席 ≠ 空数组**、分桶恰一个合取、坏行丢弃并计数,详见 §12;同批把 `ApprovalsResourceLike.list()` 的返回位 additive 放宽成 `ApprovalsListEnvelope`,老形 `{pending}` 仍可赋值)· `readRuleOffers` / `readRuleOfferSupply`(L-103/[C228],0.57.0 additive 导出:「不再询问」候选两代 wire 键的窄读器**公面化** —— 此前只经卡端口出包,不走卡端口架构的宿主只能自己重铸一把,而它承载的是兑付安全判据(原始下标不前移/逐条丢坏/闭集 kind/两代取舍序),详见 §20)· `RULE_OFFERS_ABSENCE_REASONS` / `DENIAL_LIMIT_KINDS`(0.59.0 / sdk 8.3.0 提货:`ruleOffersAbsence` 三词与 `denialLimitFallback.limit` 二词的**运行期**闭词表再导出 —— 与 0.58.0 那三张同一条纪律:端拿它做判定别再手抄字面量。⚠️ **本包自己不拿这两张表做窄读判定**(两处都按开集透传,词表属主是 core、server 已按闭集拒过),再导出只是给端的 `switch` 一份可数的表,端仍必须带 `default` 臂,详见 §23a)· `DecideTransportRetryExhaustedError`(Inkglow-1085 P0a:decide 出站瞬断重试耗尽的 typed 判别 —— HitlBridge 内建单次退避重试,耗尽走重呈臂不判死 turn;端一般只消费行为,不需要 instanceof) · `gateOutcomeOf` / `isDeniedGate` / `gateDeniedBy` / `gateApprover` / `isApprovalWindowExpiredGate` / `isDenialLimitAutoDeniedGate` / `isParkSlaExpiredGate` / `isHumanSettledGate`(0.60.0 / engine ≥7.64.0:`tool_end.gate` 整条门记录的窄读器 + 判定谓词 —— 取代退役的四个正交词 `settledBy`/`resolution`/`autoDenied`/`approver`。🔴 **判定归包**:「是不是审批窗自己走完的拒绝」旧形上是端各自拼的两键合取,而三条窗词现在分得开、合并读回去等于把刚修好的判别力扔掉;⚠️ 公面型一律带 `View` 后缀 —— 本文件的 `GateOutcome`(决断腿结局)与 sdk 的 `GateOutcome`(引擎门记录)**同名不同义**,详见 §24c)· `isGateParkedToolEnd`(「这次调用没在这里结算」的**第二形**谓词:gate 缺席 + `errorCode:"gate.parked"`;端判这件事必须与 `isApprovalWindowExpiredGate` **两形合读**) · `readWireErrorCode`(B-037 候包件②:decide/取件失败上引擎 wire 机器码的单源读口,结构视图读不 `instanceof`;与本包铸的 `code` 是两个命名空间,详见 §24g)| suspended→decide→resume 环。🔴 **D-1 两元组 verbatim 回显**是字节级断言的安全不变量,端**不许重实现它的任何一段**。🔴 键空间边界(web [C1] d3 拦截):`gateIdentity` 四常量两函数只覆盖 HITL questionId/callKey 空间;seat 的 `TOOL_PERMISSION_REQUEST_ID_DOMAINS`(`plan:` 等)是另一键空间,**两者绝不合并**(合并=座位校验器静默拒全部 plan-review 卡) | `src/hitl/hitlBridge.ts`、`toolApprovalWire.ts`、`askGateWire.ts`、`planReviewWire.ts`、`hitlHostSurface.ts`、`gateIdentity.ts`、`armedGateRegistry.ts`、`parkOwnership.ts`、`parkResolver.ts`、`approvalsFeed.ts`、`frameRouter.ts`(**只挑名导出** `toolEndOutputText`/`ENGINE_ABORT_TOOL_RESULT`/`isAskTool`/`HITL_REJECT_MESSAGE`/`HITL_INTERRUPT_MESSAGE_FOR_TOOL_USE`)、`parkRowBirthWait.ts`、`approvalDecisionNoteAudit.ts`、`askParkRowRouting.ts`、`resumeRunningCard.ts`(#265 上收的判定层)、`persistedRulesWire.ts`、`localAllowRule.ts`(#244 F2 规则侧)、`crashConverged.ts`(L-38 崩溃收敛读面)、`src/gateOutcome.ts` |
160
160
  | 4 | **子代 wire + 面板侧信道台账** | 86 | `tailEngineSubagent` · `installSubagentActivitySink` · `installSubagentTailMetaSink`(#280 件2:tail meta 帧发布口,`contentFrames` 判别位载体)· `stopEngineTask` + `classifyTaskStopConflict` · `fetchEngineSubagentReport` · `steerEngineSubagent`(0.32.0 未发布 #280 件A:additive 第三参 `childTaskId` —— 端有行上下文时**应当**传,传了就走「台账优先 / 缺席即诚实缺席 + `noteBgOwnerAbsence` 留痕」的 Q3 口径,与 tail·taskOutput·subagentOutput 三腿同姿势、与孪生 resume 腿共用同一个 `resolveOwnerRunId` 判据;**不传**则逐字维持旧行为=回落在飞 run)· `resumeSettledSubagent` + `resolveSubagentResumeContext` + `resolveOwnerRunId` + `classifySubagentResumeFailure` + `subagentResumeAvailable`(#242 批 2 A-028.7:resume 判定半场上收,与 steer 孪生同居;取址三态 = 台账有行用行值 / 指名了行但台账缺席则**诚实缺席绝不回落在飞 run** / 没指名行才回落。出路文案归端)· `recordSubagentOwnerFromProgress` + `getBgParentRunOwner`(A-028.6:「子代 → 宿主 run」**单表**,宿主 run 必须由持 stream-local 值的调用方显式传入,包内绝不从 `activeEngineRunId()` 推断)· `noteBgOwnerAbsence`(#242 批 3 [4000] Q3=B:tail/taskOutput·taskStop/subagentOutput 三腿台账缺席即诚实缺席**绝不回落在飞 run**,缺席 warn 留痕每 (腿,taskId) 一条)· `clearBgTerminalFacts`(#242 批 3 扫码修:复活=新周期,旧周期终态事实作废——fleetLedger 复活两腿按尾段清账,factsAccepted 方向核不再拿上周期终态当先例)· `auditRetainWithoutWake`([4000] Q5:引擎宣示 `subagentResume` + 本端在付 `retainSubagentSessions` + 端未实现 `wakeSubagent` ⇒ 响亮一条;`CLIENT_VERBS.wakeSubagent` 维持 fail-soft)· `subscribeSubagentContent` · `subscribeEngineAgentPanel` · `publishQuestionFrame` / `respondToQuestion` · `configureSubagentContentStore` / `subagentContentStoreConfig` / `SUBAGENT_CONTENT_STORE_DEFAULTS`(0.62.0:子代内容账本的**字节预算** —— 此前只有条数帽而单条无上限,一条 base64 工具结果就能让一个子代槽吃到十几 MB;越限从最早的内容开始丢并留一条可渲染的 `truncated` 记录,总帽淘汰整条最久未用的账本。配置面 fail-loud,详见 §26②)| 驱动与观测委派子代;经 module 级台账喂活体 agent/task 面板。全部**能力位 gate**(§5b) | `src/subagent/*.ts`、`src/subagentContentStore.ts`、`src/engineAgentPanelStore.ts`、`src/engineInlineTaskStats.ts`、`src/engineToolLabelStore.ts`、`src/liveQuestionStore.ts` |
@@ -169,7 +169,7 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
169
169
  | 13 | **座位 IPC 契约** | 34 | `LOCAL_SESSIONS_SPEC` · `SEAT_METHOD_NAMES` · `SEAT_EVENT_TYPES` · `isLocalSessionEvent` · `isToolPermissionRequest` · `toolPermissionRequestId` · `SEAT_VALIDATOR_KEY_COVERAGE` · `SEAT_SEND_MESSAGE_KEY_ORIGINS`(0.62.0:座位载荷**逐键出身**登记 —— 每个位要么写明转投哪个引擎请求位、要么写明为什么不上 wire;常驻门对**装在盘上的** sdk 型面逐名核,详见 §26③)| desktop↔web 座位 IPC 契约的**单一真源**(此前两边各一份、名字零重合 ⇒ 编译器永远不会告诉你它们漂了)。🔴 加 verb 忘了加 `LOCAL_SESSIONS_SPEC` **不报错**:preload 不注册 channel、渲染端读到 `undefined` | `src/seatContract.ts`(**零 import**,纯类型 + 常量 + 纯谓词)。🔴 **证据等级标注(0.42.0,test [5087] 的「语料**种类**缺口」/ cli [5088] 认领件)**:该文件里所有以「CC 如何如何」为形的断言(`212 methods` / `854-channel census` / 方法名逐字保留 / `fQe` 逐字段对照 / 一切 `.vite/build/index.chunk-*.js` 坐标)**证据等级 = 桌面 unpack,本地语料库不可复验** —— 本仓手边可复验的参照语料**只覆盖终端 CLI 形态**的静态产物,拿它去 grep 桌面壳里的符号只会零命中,而零命中在这里**既不证真也不证伪**。复核这些断言**不得**拿本仓语料当反证 |
170
170
  | 14 | **宿主端口与会话槽** | 41 | `installHost` · `installHostFor` · `installCoreValuePorts` + 十读口 + 三存在性口(0.69.0 CC-07:core 值级面端口注入,Node 宿主装配根装、浏览器 lane 恒缺席)· `hostPortMisses(For)` · `DEFAULT_SESSION_KEY` · `hostEnv` · `unrefTimer` · `parseLocaleTag` / `pickUiLanguage`(#244 F4 族D A-028.20:locale tag 手术单源 + UI 语言判定;与 `resolveRegionHint` 双出口成文 —— 语言偏好域 en/zh ≠ 地址可达域 cn/intl/unknown,`zh-Hant` 前者 zh 后者 intl 是设计)· `engineNamespaceKeyFor` / `mergeSessionMapRecord` / `mergeEngineEntry`(A-028.12:会话 id 映射单一键形 + merge 判定;存储经 `SessionMapStorePort` 归端 —— cli 文件锁/原子写,web localStorage)| 进程/端级装配层(settings/fs/queue/timers/session/log/probe),与 per-turn 的 `AdapterContext` **分层**。头注的判定规则:**这个能力每 turn 都会变吗?** 会 ⇒ `ctx`;不会 ⇒ `installHost` | `src/host.ts`、`src/hostEnv.ts`、`src/sessionSlot.ts`、`src/unrefTimer.ts`、`src/env/{localeGeo,localeTag,uiLanguage}.ts`、`src/sessionMap.ts` |
171
171
  | 15 | **控制面与传输** | 139 | `reconnectMcpServer` / `projectMcpReconnectResult` / `classifyMcpReconnectFailure` / `projectMcpReconnectCapability` / `mcpReconnectOutcomeDetail` + `MCP_RECONNECT_OUTCOMES` / `MCP_RECONNECT_TRANSACTION_NOTICE`(0.72.9 CC-30:会话内 MCP re-dial 消费口,outcome 三态 / unsupported 恒五键 / 名册按 toolNames 在场性;§56)· `readAutoConsolidationArmed`(0.72.9 CC-39②:memory-status `autoConsolidationArmed` 三态,缺席 = 老 server 判不了;§56)· `steerFollowIntent`(0.72.6 CC-40:steer 后续听意图三态 tail / after-decision / after-wake,按 `SteerReceipt.delivery` 判;§53)· `projectWebSearchBackendCapability` / `observedWebSearchBackend` / `noteEngineCapsForWebSearchBackend` / `forgetWebSearchBackendReading` / `webSearchBackendDoctorDetail` + `WEB_SEARCH_BACKEND_NONE`(0.72.5 CC-31:`capabilities.webSearch.backend` 四态读面 —— 键缺席 = 老引擎判不了 ≠ `none` = 引擎明说没有默认后端;与 `sqlEngineCapability` / `writeProtectionCapability` 同构;§52)· `resumeContextUnavailableFromError` / `resumeContextUnavailableContent`(0.72.1 CC-33:409 `conflict.resume_context_unavailable` 读数 `{ code, staleAfterSec?, runId? }` + 三句人话;§48)· `mcpEngineLegPresence`(0.71.0 CC-19:引擎侧 MCP 在场三值,只从面板视图求;§42)· `ControlRouter`(+ `ControlSafetyError`)· `fetchMcpPanel`(0.69.0:经 sdk `sessions.mcp` 取体 + 投视图,不裸 fetch)· `projectMcpPanel` + `mcpPanelLastLegDetail`(0.68.2 CC-03:`GET /v1/sessions/:id/mcp` 面板体防御读视图 + `lastLegMcp` 一行措辞铸点;缺席 = 键不铸、读不懂 = `lastLegMcpUnreadable`、禁与 `servers[]` 对账)· `makeEngineWireClient` + `resolveWireAuth` · `installEngineWireTarget` · `diagnoseSseIdleTear` / `isSseIdleError` · `attemptActiveRunSelfHeal` + `activeRunBusySignal` + `activeRunSelfHealRow` / `activeRunBusyHeadlessRow` · `kickEngineCapsProbe` / `engineCapTrue` / `invalidateEngineCaps(baseUrl, probe?)`(#307 S25:引擎温切后的 caps 生产失效口 —— kick 自带幂等闸,同 baseUrl 重启后不显式失效就永远读到旧引擎那一版能力位;调用方 = 壳的 respawn/restartEngine。🔴 **推荐两参形**:第二参给替代探测则「推进代际 + 注册新探测」在同一同步块内完成,失效与下一次 kick 之间那个「等待者读到未判」的窗按构造不存在;单参形保留给「只丢缓存、这一刻没有替代探测」的调用方,那种情形下读到未判是诚实结局) · `engineCapValue`(S-131,0.59.0:能力位的**四态**通用读口 `unobserved`/`not_reported`/`null`/`value` —— 既有三口把四种「读不出」全折成 fail-closed 一档,对**放行**问题是对的、对**读面/诊断**问题是错的:`null`(引擎明确说没有,正面事实)会与「老引擎不报」「还没探到」在屏上同形。`value` 位刻意不做形校验,形归各能力位自己的窄读器,详见 §23b)· `projectSqlEngineCapability` / `observedSqlEngine` / `noteEngineCapsForSqlEngine` / `forgetSqlEngineReading` / `sqlEngineDoctorDetail`(S-131,0.59.0:`Capabilities.sql`(server ≥7.60.0)的四态读面**从壳侧上收** —— 归层债,0.58.0 时它长在壳里正是因为包侧没有嵌套对象读口。🔴 **导出名与壳侧那份逐字同名 = drift-lock**;`txnMode: null` 是铸点域内的合法值不是畸形;换代失效口清成未观测而不是留旧值,详见 §23b)· `mapBrainStatusToRetry` · `waitForClaimRelease` + `CLAIM_RELEASED_STATES` / `CLAIM_HELD_STATES` · `atMostOnceFailureClass` / `readSteerDelivery` · `clearRunningChoiceOffer`(Inkglow-1085 P0b①:「Do nothing」登记的清口 —— 端的「重新打开操作菜单」入口;登记在场时 attemptActiveRunSelfHeal 不整卡重弹,not-parked 结局带 `alreadyOffered: true` 判别位,端据此降级渲一行)· `INTERACTIVE_WAY_OUT`(默认出路串单源)· `engineSessionParamFor`(design/285 批 0:`?session=` 派生的 **per-key** 形 —— `hostSessionFor(sessionKey)?.currentSessionId()` + [1501] 空串归一;零参 `engineSessionParam()` = 默认槽兼容层,取值链逐字等价)· `normalizeWirePrincipal`(A-028.10:principal 在场性 trim 原语 —— 全空白=缺席不发头,engineWireTarget 两臂/makeEngineWireClient/壳 livePrincipal 同尺)· `readSessionMemoryStatus` / `classifyMemoryStatusFailure` / `readCaptureOptOut` / `readLastCapture`(S-53 会话记忆姿态读面,0.48.0:失败分诊**码优先**——两个 404 分道 `not_found.session` / `not_found.route`,无码 404 不猜落 failed;五键逐键缺席语义两个合读器,`lastCapture` 三态的判别材料是 `committedCount` 不是本键;IO 归宿主注入 `MemoryStatusClientLike`,详见 §11) · `classifyTurnWireError` / `isWireTransportError` / `isPreStreamDrainingReject` / `isResumeAtRejection` / `drainingRetryDelayMs` / `scenarioDenyFromError` + `WIRE_NETWORK_ERROR_PATTERN`(A-028.11/.13:turn 错误分型判定半场,人话文案与渲染归端)· `resumeRetryLaterFromError`(L-102,0.57.0:resume 族**时间性拒绝**二码的判型半场 —— 这一族里唯一**带得出「等多久」**(`retryAfterSec`)的两个码。🔴 闭集**不是**「哪些码可以等」的名单:同族 `resume.row_recycling` 同样可等(窗口自清)只是没有秒数 ⇒ 本读口返回 `null` 只意味着没命中这两码,详见 §21) · `projectWriteProtectionCapability` / `observedWriteProtection` / `noteEngineCapsForWriteProtection` / `forgetWriteProtectionReading` / `writeProtectionDoctorDetail` / `projectWriteProtectionPosture` / `writeProtectionPostureDetail`(S-138,0.60.0:`Capabilities.writeProtection` (engine ≥7.63.0)的**四态**读面 + operator 面行表 —— 与上面 S-131 那一格**同构同纪律**。🔴 三位刻意不合成一个布尔;`not_reported` **不是**「这台部署没有写保护表」(座位缺席恰是缺省表在岗);逐行 name/kind 走**最小披露**只上 operator 面,详见 §24e)· `projectReadFacePosture` / `readFacePostureDetail` / `readFaceDisagreement`(S-167,0.61.0:operator 面 `diagnostics.wiring.readFace`(engine ≥7.65.0)的窄读器 —— 与上面S-138 那一格**同构同纪律**。🔴 三句「答不出来」逐字互异且没有一句等于「没有 READ 档」;`source` 按开集读;与租户面 `capabilities.readFace` 刻意不合流,只带一个纯比较函数,详见 §25)| 上行通道的**监管**半场(submit / steer / kill / 队列命令定序)+ 传输构造、caps 探测、SSE 断流分诊、**409 active-run 自愈** | `src/controlRouter.ts`、`steering.ts`、`sseIdleTriage.ts`、`retryStatus.ts`、`diagnostics.ts`、`engineWireSdk.ts`、`engineWireTarget.ts`、`src/principalWire.ts`、`src/wireErrorTriage.ts`、`engineSessionParam.ts`、`engineCapsCache.ts`、`liveInitToolFace.ts`、`adapter/activeRunSelfHeal.ts`、`src/sessionMemoryStatus.ts`、`src/writeProtectionCapability.ts`、`src/webSearchBackendCapability.ts`、`src/mcpReconnect.ts`、`src/readFacePosture.ts` |
172
- | 16 | **引擎词汇表与包自检** | 93 | `ENGINE_NOTICE_CODES` 67(0.72.11 CC-49:core 7.23.0 +1 `config.write_protection_unresolved`,operator,兄弟码 `target_view_absent` 之后;§58)· `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`(0.72.7 CC-42:通告 `mcp.server_redialed` 事实读器,outcome 三词闭集、added/removed 计数;§54)· `RESUME_CONTEXT_UNAVAILABLE`(0.72.1 CC-33;不进两个 resume 闭集:不可等、也不是换参数)· `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` · `resumeReopenFromError` / `resumeReopenContent`(0.71.3 CC-06:resume reopen 族三码闭集 + 读口 + 三句,§45)· `readSkillsListingTruncated`(0.70.0 CC-04:`skills.listing_truncated` 事实读器,§39)· `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `DECIDE_WORKFLOW_LANE_CODES`(+ 三个具名码;`/decide` workflow 车道,三条出路刻意不合并,详见 §30h)· `STOP_CONFLICT_CODES` · `isInterruptedToolEndCode` · `isRewindFamilyCode` · `CLIENT_VERBS` · `compensationSplitViolations` · `DELEGATION_CAP_CODES` / `isDelegationCapCode` / `DELEGATION_CONCURRENCY_CAP` / `DELEGATION_SESSION_CAP`(0.38.0 #318 件④:core 5.48.0 design/323 委派席位到限**两码,处置不对称禁合并** —— 并发帽=**可等**(兄弟结束即有位)/ 会话累计帽=**等也没用**(这条会话的配额用尽))· `CONFIG_DELEGATION_ENTRY_CAPS`(同批入 `CONFIG_REFUSAL_CODES` 识别表)· `delegationCapDispositionOf` / `MCP_SERVER_REVOKED`(0.39.0 载体到货消费件:core 5.50.0 补 `{ error: code, code }` 孪生拼法后两码真上 `tool_end.errorCode`,0.38.0「先立词不落消费分支」的已知局限自此解除;处置轴 `wait-for-slot` / `reuse-existing-or-await-reap` 机器可读(累计帽=retained-window 帐,行回收配额即回,处置=SendMessage 复用,**非**「换会话/永久耗尽」——0.38.0 段该句系勘误),未知 `delegation.*` 码 ⇒ `undefined`;`mcp.server_revoked` = 操作员 mid-session 吊销 server 后的工具面本地闸(被吊销的 server **名**今天不过 wire 境:detail.server 是进程内位,抬升腿只 lift code——归因渲染候 core 补 typed detail,已点名);载体门 = engine-vocab G3 腿锚 core dist 铸点)· `CAPABILITY_SELF_ORCHESTRATION_REQUIRED`(S-81,server 7.57.0:提交面的 selfOrchestration 准入拒绝码。🔴 **复用码** —— 与其它 `capability.*` 501 同体形而处置不同,消费点必须按**恰等**判、绝不放宽成前缀判;判型与「去键重发一次」归 `src/selfOrchestrationDenial.ts`,详见 §13) · `GATE_PARKED_ERROR_CODE`(0.60.0:「门把这次调用 park 了」的机读码单源 —— `frameRouter` 的连坐/中断判据与 `gateOutcome.isGateParkedToolEnd` 读同一个常量;真机黑盒直证 park 短路帧上**没有 `gate`**,这个码是那一形唯一的信号,详见 §24c)| 三端分臂共用的**去字面化** `errorCode` 词表(病根正是三端各抄一份字面);编译期 verb 闭合门;搬迁补偿登记表 | `src/engineErrorCodes.ts`(计数以 `scripts/public-export-baseline.json` 为准,别手抄;A-028.11/.13 补 `DRAINING_ERROR_CODE`/`SCENARIO_NOT_ALLOWED_ERROR_CODE`/`RESUME_AT_ERROR_CODE_PREFIX`;#318 件④ 补 `delegation.*` 族四位 + `config.delegation_entry_caps`;0.39.0 补三新码消费件三位);S-81 补 `capability.self_orchestration_required` 一位;L-102 补 `resume.*` 时间性拒绝二码 + 闭集 `RESUME_RETRY_LATER_CODES` 三位)、`src/classifierVerdictWire.ts`、`src/compensations.ts`、`src/clientSlice.ts`;**0.67.0 补锚**(这三件的导出一直计在本域,而本表此前没有它们的锚行 —— 如实补上,不是搬家):`src/gateVocabulary.ts`(`GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail` + 🆕 `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`,详见 §32d)、`src/autoModeUnavailable.ts`(`AUTO_MODE_UNAVAILABLE_CAUSES` + 🆕 `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`;🔴 同批**删**`classifierUnavailableOf`/`classifierUnavailableDetail`,详见 §32b)、`src/classifierStatus.ts`(`CLASSIFIER_STATUS_STATES`/`classifierStatusOf`/`classifierStatusDetail`)|
172
+ | 16 | **引擎词汇表与包自检** | 95 | `TASK_NOTIFICATION_TERMINAL_STATUSES` / `isTaskNotificationTerminalStatus`(0.72.12 CC-50:通知自己的四终态词,含 `cancelled`;与 run 级终态表两张表;§59)· `ENGINE_NOTICE_CODES` 67(0.72.11 CC-49:core 7.23.0 +1 `config.write_protection_unresolved`,operator,兄弟码 `target_view_absent` 之后;§58)· `MCP_REDIAL_OUTCOMES` / `readMcpServerRedialed`(0.72.7 CC-42:通告 `mcp.server_redialed` 事实读器,outcome 三词闭集、added/removed 计数;§54)· `RESUME_CONTEXT_UNAVAILABLE`(0.72.1 CC-33;不进两个 resume 闭集:不可等、也不是换参数)· `RESUME_REOPEN_CODES` / `RESUME_ENV_FAILED` / `RESUME_TOOL_UNAVAILABLE` / `RESUME_TOOL_CONTRACT_MISMATCH` · `resumeReopenFromError` / `resumeReopenContent`(0.71.3 CC-06:resume reopen 族三码闭集 + 读口 + 三句,§45)· `readSkillsListingTruncated`(0.70.0 CC-04:`skills.listing_truncated` 事实读器,§39)· `CONFIG_REFUSAL_CODES` / `isConfigRefusalCode` · `DECIDE_WORKFLOW_LANE_CODES`(+ 三个具名码;`/decide` workflow 车道,三条出路刻意不合并,详见 §30h)· `STOP_CONFLICT_CODES` · `isInterruptedToolEndCode` · `isRewindFamilyCode` · `CLIENT_VERBS` · `compensationSplitViolations` · `DELEGATION_CAP_CODES` / `isDelegationCapCode` / `DELEGATION_CONCURRENCY_CAP` / `DELEGATION_SESSION_CAP`(0.38.0 #318 件④:core 5.48.0 design/323 委派席位到限**两码,处置不对称禁合并** —— 并发帽=**可等**(兄弟结束即有位)/ 会话累计帽=**等也没用**(这条会话的配额用尽))· `CONFIG_DELEGATION_ENTRY_CAPS`(同批入 `CONFIG_REFUSAL_CODES` 识别表)· `delegationCapDispositionOf` / `MCP_SERVER_REVOKED`(0.39.0 载体到货消费件:core 5.50.0 补 `{ error: code, code }` 孪生拼法后两码真上 `tool_end.errorCode`,0.38.0「先立词不落消费分支」的已知局限自此解除;处置轴 `wait-for-slot` / `reuse-existing-or-await-reap` 机器可读(累计帽=retained-window 帐,行回收配额即回,处置=SendMessage 复用,**非**「换会话/永久耗尽」——0.38.0 段该句系勘误),未知 `delegation.*` 码 ⇒ `undefined`;`mcp.server_revoked` = 操作员 mid-session 吊销 server 后的工具面本地闸(被吊销的 server **名**今天不过 wire 境:detail.server 是进程内位,抬升腿只 lift code——归因渲染候 core 补 typed detail,已点名);载体门 = engine-vocab G3 腿锚 core dist 铸点)· `CAPABILITY_SELF_ORCHESTRATION_REQUIRED`(S-81,server 7.57.0:提交面的 selfOrchestration 准入拒绝码。🔴 **复用码** —— 与其它 `capability.*` 501 同体形而处置不同,消费点必须按**恰等**判、绝不放宽成前缀判;判型与「去键重发一次」归 `src/selfOrchestrationDenial.ts`,详见 §13) · `GATE_PARKED_ERROR_CODE`(0.60.0:「门把这次调用 park 了」的机读码单源 —— `frameRouter` 的连坐/中断判据与 `gateOutcome.isGateParkedToolEnd` 读同一个常量;真机黑盒直证 park 短路帧上**没有 `gate`**,这个码是那一形唯一的信号,详见 §24c)| 三端分臂共用的**去字面化** `errorCode` 词表(病根正是三端各抄一份字面);编译期 verb 闭合门;搬迁补偿登记表 | `src/engineErrorCodes.ts`(计数以 `scripts/public-export-baseline.json` 为准,别手抄;A-028.11/.13 补 `DRAINING_ERROR_CODE`/`SCENARIO_NOT_ALLOWED_ERROR_CODE`/`RESUME_AT_ERROR_CODE_PREFIX`;#318 件④ 补 `delegation.*` 族四位 + `config.delegation_entry_caps`;0.39.0 补三新码消费件三位);S-81 补 `capability.self_orchestration_required` 一位;L-102 补 `resume.*` 时间性拒绝二码 + 闭集 `RESUME_RETRY_LATER_CODES` 三位)、`src/classifierVerdictWire.ts`、`src/compensations.ts`、`src/clientSlice.ts`;**0.67.0 补锚**(这三件的导出一直计在本域,而本表此前没有它们的锚行 —— 如实补上,不是搬家):`src/gateVocabulary.ts`(`GATE_DENIED_BY_WORDS`/`gateDeniedByDetail`/`ASK_ORIGIN_WORDS`/`askOriginDetail` + 🆕 `RULE_STORE_UNREADABLE_KINDS`/`isRuleStoreUnreadableKind`/`ruleStoreUnreadableDetail`,详见 §32d)、`src/autoModeUnavailable.ts`(`AUTO_MODE_UNAVAILABLE_CAUSES` + 🆕 `CLASSIFIER_DENY_CAUSES`/`isClassifierDenyCause`/`classifierDenyCauseOf`/`classifierDenyCauseDetail`;🔴 同批**删**`classifierUnavailableOf`/`classifierUnavailableDetail`,详见 §32b)、`src/classifierStatus.ts`(`CLASSIFIER_STATUS_STATES`/`classifierStatusOf`/`classifierStatusDetail`)|
173
173
 
174
174
  🔴 **`engineErrorCodes` 的开集纪律**(该文件头注逐字):这些 `ReadonlySet` / 前缀谓词一律是**识别表**,
175
175
  回答的是「我认不认得这个码」,**绝不是**「合法码只有这些」。消费点 `switch` **必须留 `default`**,
@@ -8620,3 +8620,43 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
8620
8620
  3. peer sdk >=9.6.0 / agent-types >=0.3.0 不动;server 承载版到货前这枚码不出现。
8621
8621
 
8622
8622
  **包侧缺口:** ① CC-46 `plan_review` 体 `permissionModeAfter` 发口(候 server 7.86.0 S-433 [7532] 裁定 + sdk 型面);② CC-34 `permission_denials` 自动升级验证(core #897 已到 7.23.0;候 server 7.87.0 透传半场);③ CC-36 托管 MCP 活性三态读口(候 core 7.23.x #874);④ `staleAfterSec` / `runId` 经 sdk 到端(候 sdk 出键);⑤ `Capabilities.webSearch` / `mcpReconnect` / `TaskRequestBody.memory` / `WiringManifest.readDeny` / `SessionMemoryStatus.autoConsolidationArmed` / reconnect 端点与体 / `LeaderRecord.result` 冲突形 经 sdk 声明(候 sdk 出键);⑥ `agents.listing_truncated` detail 读器候消费场景(by-design);⑦ `ClassifierSeat.defaulted?` 候 sdk 出键(by-design);⑧ §NNz「declined 键真零命中」机读第二刀(候形式化)。
8623
+
8624
+ ## §59 🆕 0.72.12 「缺席被折成正向终态」按类清剿(CC-50 M1 头条 + 六站 / CC-51 M6;test [7541] / #59 #64);patch
8625
+
8626
+ > **patch**:型面 additive(`EngineAgentPanelEvent` 新臂 `absent`;`WorkflowRunState.status` / `WorkflowPhase.status` 各 +`'unknown'`;结果帧超集键 `_sema_outcome`;+2 常量 +2 函数,公面 989 → 993;peer 不动)。**行为面三处真变化**见 CHANGELOG 0.72.12「取舍」段;表态与设计输入:[7543](A 形推荐)/ test 直讯三轮((c)+(a) 合体、G2-d/e/f、`agent.status` 值域不动)/ server [7545](`removeReason` 单成员闭集 `orphaned`、补偿周期 60 s 晚于 30 s 窗)。
8627
+
8628
+ ### 59a. 处置表
8629
+
8630
+ | # | 面 | 本包做了什么 | 端要做什么 |
8631
+ |---|---|---|---|
8632
+ | S-1 | **fleet 行缺席 > `ABSENT_SETTLE_MS`(30 s)**(头条 #59;A 形) | `projectFleetAgentRows` 缺席路径发 `{ kind:'absent', taskId, lastSeenAtMs, absentForMs }`,**不** settle、**不**铸 `end`;真终态迟到照发唯一一次 `end`;行回来发 `fleet-row`;条目按上报时刻 + 回收期回收 | 🔴 壳半场票(cli):面板消费加 `absent` 臂 ⇒ 行渲「engine no longer reports this agent · outcome unknown」+ 停表 + 不进 Completed / Failed / Stopped 任一格;**`agent.status` / `isError` 值域不改**(详情页头 catch-all else ⇒ Stopped);老壳认不得 ⇒ 行停 running(可证伪的不知道,零假绿);G2-f 四面(/tasks 行 / 舰队行 / 详情页头 / 页脚计数)不得互相矛盾 |
8633
+ | S-2 | TaskOutput 状态位(structured / legacy 两腿)、workflow 轮询信封、`task_notification`、去重键 | 缺席 / 解不出 / 非串 ⇒ `'unknown'`;summary 改句;`unknown` 不进 `WF_TERMINAL` ⇒ 不再顺手 `markEngineWorkflowNotified` | 渲染面按**开集**读:`unknown` 渲原词 + 未知标;闭集 switch 的 default **不许**渲正向词 |
8634
+ | S-3 | `createBackgroundView` 200 回体缺 `tasks` 键 | 源健康位 `unavailable`(不再 ok + 空表) | `sources.*` 已是三态,端渲「读不出」不渲「零任务」 |
8635
+ | S-4 | `projectWorkflowRun` run / phase 状态未知词 | `status:'unknown'`(联合 additive;run 级先看腿上活跃证据,有腿在跑 ⇒ `running`);合成阶段 / 空桶同律;`coerceWorkflowStatus` 未知词 ⇒ `idle` | 端 switch 加 `unknown` 臂(tsc 会红一次 = 通知);渲原串 + 未知标;🔴 算 workflowActive 别只写 `status === 'running'` 然后把其余一律当已终止 —— `unknown` 不是终止,inactive 的腿此时渲「未知」不渲 Stopped |
8636
+ | S-5 | **SDK 结果边界:done 帧无终态记录 / 认不出的终态词** | `error_during_execution` + `is_error:true` + **`_sema_outcome:'unknown'`**(稀疏;真 completed / failed 不带)+ `errors[0]` 逐字句;`runStream` 合成 `Outcome unknown: <同一句>` 行(`OUTCOME_UNKNOWN_ROW_PREFIX` / `isOutcomeUnknownRowText`) | `-p` / stream-json 消费方:`is_error:true` 且 `_sema_outcome==='unknown'` ⇒ 渲「结局未知,请核实」而**不是**「失败」,不据它重试;交互面按行首认 `Outcome unknown:`(与 `Model output error:` / `Run stopped:` 同律);mock 车道要成功请带真终态词 |
8637
+ | S-6 | 包内普查门 `run-absence-fold-census-test.mjs` + `scripts/absence-fold-baseline.json` + DS-06(病形锚「兜底位置只许 unknown」) | AST 五形扫(`??`/`||` 右臂 · 三元 else 臂 · `default:` 首 return · `catch` / `.catch(() => …)` 健康值 · 函数尾 return)+ 存量 5 条带 why 只降 + 围栏式判别力自证 | 无行为面;端可照抄门形建自己的普查(cli `closed-set-literal` 族已有) |
8638
+ | S-7 | `noticeAudienceOf(未知码)` ⇒ `'operator'`(test [7547] 请确认) | **契约句(有意的保守缺省)**:认不出的通告码只进运维面、不渲给用户;「在不在册」的判据是 `engineNoticeInCatalog`,两口分工 —— 这不是缺席折正向词(operator 不是结局断言,是受众收窄) | 判「某码已被本包认得」请写**自有键在场 + 值相等**两格,不要只写 `noticeAudienceOf(x) === 'operator'`(对未知码恒真) |
8639
+
8640
+ ### 59z. 逐键处置表
8641
+
8642
+ | # | 键 / 面 | 处置 | 坐标 / 理由 |
8643
+ |---|---|---|---|
8644
+ | 1 | `EngineAgentPanelEvent.kind:'absent'` `{taskId, lastSeenAtMs, absentForMs}` | **consumed(新铸;additive 臂)** | `src/fleetAgentPanelProjection.ts` ③ / `src/engineAgentPanelStore.ts`;pure ③ 九格 + honesty F13 |
8645
+ | 2 | `_sema_outcome:'unknown'`(SDKResult error 臂) | **consumed(稀疏;type-superset 登记)** | `src/adapter/downstream/terminalToSdkResult.ts` `#errorResult`;消费 `src/adapter/runStream.ts` 终局臂;identity-copy G1d 七格 |
8646
+ | 3 | `task.status` / `parseWorkflowPollEnvelope().status` / `TaskNotificationFields.status` 的 `'unknown'` 值 | **consumed(开集加词)** | pure ⑩ S1–S5 |
8647
+ | 4 | `WorkflowRunState.status` / `WorkflowPhase.status` `'unknown'` | **consumed(联合 additive;合成阶段 / 空桶同律)** | `src/workflowClient.ts` `#coerceRunStatus` / `#coercePhaseStatus` / `#synthPhaseStatus` / `#bucketStatus`;pure ⑩ S7 / S8 六格 + B6/G-20 改钉 |
8648
+ | 4b | TaskOutput `retrieval_status`(CC 同名键,闭集三词)认不出的词 / 缺席 | **declined(保持 `success`,值域恒在闭集内)**:闭集无「不知道」位,`not_ready` / `timeout` 在老壳上渲成「仍在运行 / 超时」= 新的假话;`success` 的正向证据 = 取回调用已返回;「结局不知道」改由 `task.status:'unknown'` 承载 | `src/toolResult.ts` `case 'task-output'`;普查基线登记带 why;pure ⑩ S9 六格 |
8649
+ | 4c | 通知投递失败补充行(`taskNotificationDeliverySupplement`)| **changed(只对通知自己的终态词 completed / failed / killed / cancelled 说 finished;`event` / unknown / 缺席 / 未来词说 outcome unknown)** | `src/notifications.ts`;pure ⑩ S10 三格 |
8650
+ | 4d | run 级状态的腿上活跃证据 / 合成阶段的 error 证据 | **changed(未知 run 词 + 已投影的腿在跑 / 排队 ⇒ `running`;零证据 ⇒ `unknown`;合成阶段腿上 error ⇒ `failed`,与带 phase 标签的同组腿一致)** | `src/workflowClient.ts` `#runStatusWithLegEvidence` / `#synthPhaseStatus`;pure ⑩ S11 / S12 |
8651
+ | 5 | `BackgroundView.sources.*` 对缺 `tasks` 键 ⇒ `unavailable` | **consumed** | `src/agentSession/backgroundView.ts` `#pullAssistant` / `#pullFleet`;background-view ⑩ |
8652
+ | 6 | `task_remove.removeReason`(server [7545]:单成员闭集 `orphaned`,不在契约 S-449) | **pending** | 行帧投影入参今天不带它;server 进契约 + 壳透传后 `absent` 事件可附 `removeReason` |
8653
+ | 7 | `coerceAgentState` default ⇒ `progress` | **declined(声明的限制)** | `AgentState` = CC atlas WPe 输入词表 EXACTLY;登记 `absence-fold-baseline.json` 带 why |
8654
+ | 8 | `fleetProjection` 8 个数值键 `?? 0`(#62 A-18)/ `detachWire` `/health` 不可达 ⇒ true(#60 A-25) | **pending(CC-52 / CC-53,0.72.13)** | 基线登记带 why |
8655
+
8656
+ ### 59y. 🔴 三端升级必读(固定段式,[C295])
8657
+
8658
+ 1. 换钉 `^0.72.12`:面板消费加 `absent` 臂(不进任何终态格;`agent.status` 值域不动);`-p` 消费方读 `_sema_outcome`;交互面认 `Outcome unknown:` 行首;workflow / TaskOutput / 通知状态位按开集读 `unknown`。
8659
+ 2. **不接线的端也有变化**(取舍段三条):终态缺席的 done 帧从 success 翻 error;离场的行不再自动变 Completed(停在最后已知态);状态位多一个词 `unknown`。
8660
+ 3. peer sdk >=9.6.0 / agent-types >=0.3.0 不动;老 server 行为不变(变化全在本包投影层)。
8661
+
8662
+ **包侧缺口:** ⓪ CC-52 M4 `fleetProjection` 数值键 `?? 0` → 缺席不落键(0.72.13,窗 09-20)+ CC-53 M2 `engineSupportsDetach` 三态(同车);① CC-46 `plan_review` 体 `permissionModeAfter` 发口(候 server 7.86.0 S-433 [7532] 裁定 + sdk 型面);② CC-34 `permission_denials` 自动升级验证(core #897 已到 7.23.0;候 server 7.87.0 透传半场);③ CC-36 托管 MCP 活性三态读口(候 core 7.23.x #874);④ `staleAfterSec` / `runId` 经 sdk 到端(候 sdk 出键);⑤ 七件 wire 面经 sdk 声明(含 `LeaderRecord.result` 冲突形 / `_sema_outcome`;候 sdk 出键);⑥ `agents.listing_truncated` detail 读器候消费场景(by-design);⑦ `ClassifierSeat.defaulted?` 候 sdk 出键(by-design);⑧ §NNz「declined 键真零命中」机读第二刀(候形式化);⑨ `absent` 事件附 `removeReason`(候 server S-449 进契约 + 壳透传)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/client-core",
3
- "version": "0.72.11",
3
+ "version": "0.72.12",
4
4
  "description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
5
5
  "license": "MIT",
6
6
  "type": "module",