@sema-agent/client-core 0.79.0 → 0.79.1

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,23 @@
49
49
  > 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
50
50
  > commit 漏转在发布前就红,不再靠人记。
51
51
 
52
+ ## 0.79.1(2026-09-21)
53
+
54
+ > 主题:**终帧结构化产出改用 CC 拼法 + 写审批退化卡拿回路径 + 云控制面子路径入口**(patch;peer 地板不动 `>=11.2.1`;根公面运行期导出 1184 不变)。三件:终帧结构化产出同帧铸 CC 形 `structured_output`(旧拼法 `structuredOutput` 过渡一版,0.80.0 删);写审批 `argsOmitted` 退化卡在没有受护写入的部署上重新解得出路径;云控制面十值二型经本包**第二个入口** `@sema-agent/client-core/registry` 原样转口(根入口零变,不用它的端零升级动作)。
55
+
56
+ ### Fixed
57
+
58
+ - **终帧结构化产出改用 CC 拼法**(CC-130):`outputSchema` 任务的产出此前只以 camelCase `structuredOutput` 铸在成功终帧上,而 CC `SDKResultSuccess` 的那一位是 snake_case `structured_output` —— 那不是一个 additive 的超集位,是**把 CC 同名键的名字拼错了**,按 CC 形读 `result.structured_output` 的消费方一律读空。本版起同一帧**同时**铸 `structured_output`(权威)与 `structuredOutput`(deprecated,**0.80.0 删**),两键同值且**同一引用**;wire 位恰读一次(各读一次会让值随读变的取值器把两键铸成两个对象);缺席、以及**键在场而值 `undefined`**,都是两键都不铸(绝不铸值为 `undefined` 的键);`null` / `0` / `""` / `false` 是真产出,照铸;数组与原始值等非记录形照带、同一引用(形状归调用方的 schema,本包不筛形);错误信封两个拼法都不带(CC 错误臂没有这一位)。CC 到底是哪个拼法,由门从类型镜像的语法树现场见证,不是门里抄的一份常量 —— 上游改名那天门会说话。⚠️ 构建期去注释让 `@deprecated` 进不了声明文件,退役通告只在本档与接入文档。
59
+ - **写审批退化卡在没有受护写入的部署上拿回路径**(CC-129):`tool_approval` 帧带 `argsOmitted`(且流上没有 `tool_start.args`)时,卡上的路径从引擎自己那句审批问话里兜出来。此前那只读口把问话当**整串**锚死,而引擎在问句之后**恒追加**一句说明(有些配置下再追加一句写入域说明)⇒ 引擎环境不提供受护写入的部署上读口永不命中,卡的 diff 退化成空写 —— 恰恰是用户只能靠这张卡做安全决策的场景。现在锚在**恒在且逐字**的那一段(句首的问句本体 + 句体里的路径收口)上,后面跟什么都忽略;路径自带一只引号也逐字解得出。缺席照旧诚实且在一处更严:路径是原样插值的自由文本,自己就能带上收口形,收口形出现两次以上时读口**答缺席而不挑一只**;问句本体不在句首、同一策略的另两句问话、空路径,同答缺席。
60
+
61
+ ### Changed
62
+
63
+ - **请求装配矩阵 `outputSchema` 行的理由句**:不再点名某个壳的旗子为唯一来源(哪个壳今天真的接了无人值守入口是壳侧的事,本表只说座位);`live` 位的含义不变 = 仅在 live 车道 stamp,不是「有生产者」。零行为面。
64
+
65
+ ### Added
66
+
67
+ - **云控制面经本包自己的入口 `@sema-agent/client-core/registry` 原样转口**(CC-128 ①):端需要的十个值(云控制面客户端类、个人域 / 团队 draft 配置读、生效配置条件读、健康探针、反馈投递、认证路径常量、内容寻址纯函数、两只以 `instanceof` 判的错误类)与两个型(令牌对 / 令牌存储契约)从本包再导出,**就是上游导出的同一个对象**,不是包装 —— 包一层就把「同一实现」这条唯一的抗漂移保证拆掉了。它住在**第二个入口**而不是根上,镜像上游把它放在子路径的分层:主体不同(一边是引擎的服务凭证,一边是一个人的会轮换的令牌),从不碰云控制面的端既不该解析它也不该类型检查它。**根入口一个字不变,导出数不变,不用这一面的端升级是零动作。** 子路径的 `types` 要 `moduleResolution` 为 `bundler` / `node16` / `nodenext`。本口只给存量搬落点用,新的云控制面逻辑写进本包。设备面子路径刻意不转:它是 Node-only 面(零 import、靠 `Buffer` 全局)。已知限:上游该子路径的两份声明文件引用一个它只列在自己 devDependencies 里的声明包,import **本子路径**且关掉 `skipLibCheck` 的消费方会看到恰两条找不到模块的错误,只 import 根入口的看不到;两个读数都由门钉住,上游补齐那天这条随之消失。登录 / 令牌刷新 / scope 切换那五名签名型正落在这条缺口上,本版**不转**,端那条腿仍需直连。
68
+
52
69
  ## 0.79.0(2026-09-21)
53
70
 
54
71
  > 主题:**server 7.93.0 过境批 —— 写口回执第六臂 + 无 run 可读的 MCP 状态面 + 审批卡「清不掉」那一位 + 请求装配第三车道与四个 wire 键归包**(🔴 **minor**:peer sdk 地板 `>=11.0.1` → **`>=11.2.1`**;型面 BREAKING:`writePersistedRule` 结局联合 +1 臂 `unverified`、`RulesFailure` +2 kind、拒因表 +1 词、`RequestLane` +1 词、`RequestFieldSpec` 新增必填列;行为面 BREAKING:无人值守车道从此带 `model`;deny 收口帧按归因分两串;模型轮结束划 assistant 消息界;公面运行期导出 1154 → **1184**;wire 新键进车道表:`approverPosture` / `maxTokens` / `outputRetries`;审批帧新键 `mandated`)。🔴 **不可发组合**:server 7.93.0 + client-core < 0.79.0(`stillLive: "unknown"` 第六臂 / `mcpProbe` 读口)。**成文改口段见接入文档 §85 85y,按表态制点名三端。**
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.79.0
38
+ **Version:** 0.79.1
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
@@ -308,7 +308,7 @@ guard still cross-checks the table by name).
308
308
  | `scripts/run-gate-vocabulary-test.mjs` | The two gate vocabularies — who denied a call (`DeniedBy`, nine words) and who asked about it (`AskOrigin`, eleven) — together with the one place their sentences are minted, so the same denial does not read three different ways across three clients. The tables are copies, not opinions: the gate parses the members straight out of the installed SDK's declarations and reconciles them against the package's tables in both directions, so a word added upstream (nobody renders it, the user sees a bare code) and a word only the package believes in (a branch that can never fire) both fail. Every word must carry its own literal sentence and no two may collide, including the sibling pairs the upstream deliberately split apart — an organization store and a personal rule store being unreadable send you to different people, and the two tighten origins exist precisely to name which layer of engine logic asked. The two fallbacks are pinned distinct because the sets differ in kind: one is genuinely closed on the wire (an out-of-set record is withheld by the engine, so reading one means the record is damaged) while the other is genuinely open (the server only checks for a non-empty string, so an unknown word just means the client is older than the engine) Alongside them sits an **uplift anchor** rather than a third table: the reason a call was decided the way it was is a distinct semantic face from who denied it and who asked, one upstream has not mirrored into the SDK at all, and one whose newest member — a shell command allowed because it only reads — has no sentence anywhere yet. Minting the union here would create the second drifting source the day upstream publishes it, so the guard instead asserts the **absence** from both ends: the SDK declarations carry no such union near that word, and the installed engine’s own list does not carry the word either. The engine end fires first, on the batch that raises the dependency, which is exactly when the ownership question should be answered; the SDK end fires when the mirror lands. Either red is the work order to mint the sentence, never a reason to delete the anchor. A fourth mint now sits beside the three tables and is not a table at all: a single presence-only fact — that no saved rule and no standing posture can retire this question — earns one sentence, taking no argument precisely so a caller cannot mistake it for a second kind of mandate, pinned distinct from every sentence the tables mint, pinned never to point at rule-writing, and pinned not to overclaim the stronger neighbouring demand that a person rather than a configuration must answer |
309
309
  | `scripts/run-engine-identity-test.mjs` | The engine generation anchors on `/health` (`pid`, `instanceId`, `startedAt`; engine >=7.67.0). `/health` is the one unauthenticated door and its heartbeat is always green, so "another host restarted the shared engine" used to be discoverable only by having some authenticated request hit a 401 first — a path that misreads a restart as a network fault. The reader narrows each anchor independently (one malformed field never hides the other two) and always hands back a reading object rather than an absence, because the caller is asking which anchors answered, not whether there was a response. The comparison is a three-word verdict, not a boolean: `unknown` when the two readings share no comparable anchor at all — an empty intersection means nothing could be compared, never that nothing changed — and the boolean convenience is pinned so that only `true` is an assertion. Any comparable anchor differing decides `changed`, so a reading whose `startedAt` matches while its `instanceId` does not cannot be waved through as the same life; precedence only decides which anchor gets named in the diagnosis |
310
310
  | `scripts/run-posture-knob-projection-test.mjs` | The three deployment knobs on the operator face (`serverGates.durableApproval` / `streamAskWindowMs` / `sessionAutoTitle`, engine >=7.67.0), each read as a value **plus who set it plus one operator-facing pointer** rather than a bare value — a bare boolean cannot answer why this particular machine is on this setting or how to pin it back, and a default that flips with the deployment shape is invisible without that. A worker too old to report readings still sends a bare boolean; the reader folds it into the same shell so consumers keep one branch, but raises a `legacy` bit, answers `undefined` from the machine-readable source accessor, and mints a sentence that contains no source word at all — claiming a source nobody reported is worse than admitting the worker cannot say. The other two knobs are honestly absent on such a worker rather than defaulted, a malformed side knob drops only itself while the anchor knob drops the whole reading, and the four sentences are pinned literally distinct so an operator can tell "not observed" from "not reported" from a real value. The last leg reads the installed SDK's `openapi.yaml` and `types.d.ts` directly, including a pin that exactly one knob on this face is numeric — the premise the millisecond-to-prose rendering rests on |
311
- | `scripts/run-terminal-facts-projection-test.mjs` | The four unconsumed terminal-receipt facts: `TaskResult.effectiveReasoning` / `effectiveMemoryScopes` are narrowed into `_sema_effective_reasoning` / `_sema_effective_memory_scopes` on the CC-shaped `result` (success and error envelopes alike; a malformed value mints nothing, never a default tier), the resume **reopen** family (`resume.env_failed` / `tool_unavailable` / `tool_contract_mismatch`) is a frozen closed set with a reader and three-sentence copy that is disjoint from the refusal and retry-later sets, and `routePairingVerdict` reads `ModelInfo.routePairing` as ok / broken / unknown without policing the open set. |
311
+ | `scripts/run-terminal-facts-projection-test.mjs` | The four unconsumed terminal-receipt facts: `TaskResult.effectiveReasoning` / `effectiveMemoryScopes` are narrowed into `_sema_effective_reasoning` / `_sema_effective_memory_scopes` on the CC-shaped `result` (success and error envelopes alike; a malformed value mints nothing, never a default tier), the resume **reopen** family (`resume.env_failed` / `tool_unavailable` / `tool_contract_mismatch`) is a frozen closed set with a reader and three-sentence copy that is disjoint from the refusal and retry-later sets, and `routePairingVerdict` reads `ModelInfo.routePairing` as ok / broken / unknown without policing the open set. A fifth section pins the structured-output key pair on the success result: the CC-spelled `structured_output` is the authoritative home for the value the wire calls `structuredOutput`, and the camelCase spelling this package used to mint on its own — a misspelling of the CC field, not an additive field of our own — rides alongside it for one release with the **same value and the same reference**, so a consumer reading either name gets the same object. The wire position is read exactly once, because two reads let a value-changing accessor mint the two names as two different objects; absence is absence on both names; a wire key that is present but `undefined` mints neither, since a key whose value is `undefined` makes a consumer that tests presence read "the engine produced nothing" as "the engine produced an empty result"; falsy-but-present values such as `null`, `0`, `""` and `false` still mint both, and so do shapes that are not records at all — an empty array, a populated array, a string, a number, a boolean — each carried through by the same reference, because the shape of that value is decided by the caller's own schema and the package does not get to filter it; and the error envelope mints neither, because the CC error arm has no such field. Which spelling CC itself declares is witnessed from the mirror's own syntax tree rather than a constant copied into the guard, so the day that field is renamed upstream the guard says so. |
312
312
  | `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. |
313
313
  | `scripts/run-wire-refusal-copy-test.mjs` | Two wire refusals read the same way on every client: a cancel's 409 carries one of two codes with opposite dispositions (`conflict.approval_settled` — someone else already decided, go read the result; `conflict.run_not_running` — nothing changed, send the cancel again), an unrecognised or codeless 409 is reported as such rather than guessed, and the submit-side 429 `usage.window_exhausted` is read as a waitable refusal whose wait is stated only when the engine supplied one. `ControlRouter.cancel` raises a distinct safety code for the retry-directly case. |
314
314
  | `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). |
@@ -411,6 +411,7 @@ guard still cross-checks the table by name).
411
411
  | `scripts/run-registrar-tables-test.mjs` | The four registrar table bodies — this Guards table and the three census tables in the repository's negative-control record — are **generated** from `scripts/gates-manifest.json`, the one file that describes a suite. Every row's text must equal what the generator emits, the manifest's suite set must equal the suites on disk, each entry must declare how it is negative-controlled (rehearsed, blind, or behavioural, with the census taker itself declared as such since it does not appear in its own tables), and each row's outward prose is scanned against the published-surface word list — the same list the packaging-hygiene guard uses, shared rather than copied — before the generator may write it into this file. Adding a guard is therefore one manifest entry plus one generator run instead of six hand edits across three files, and a description that drifts in one place and not the others stops being expressible. The row count is no longer what is compared: the earlier arrangement checked the census tables by **length**, so rows naming the wrong suites reconciled green. Positive controls run entirely on in-memory copies — a changed description, a dropped entry, an added entry, a changed class and a hand-edited row on disk each have to make the same judgement speak — and the quieter halves are pinned too: nothing outside a table body may move, a line inside one that is not a recognisable row makes the generator refuse rather than drop it, byte equality is backed by a column-count check (a cell holding a bare pipe splits a row into extra columns, and a code span does not protect it), and the malformed rows kept byte-for-byte as they are found are registered individually, so the registration turns red the day it stops being needed rather than outliving its reason — audited in both directions, since a registration pointing at a row that is no longer malformed and one pointing at a guard that was reclassified or deleted are both exemptions nobody reads |
412
412
  | `scripts/run-mcp-probe-face-test.mjs` | The engine's **run-free MCP status face** (server ≥7.93.0, sdk 11.2.0): the `capabilities.mcpProbe` bit read the same four-state way as its eleven sibling capability readers, and two call ports on top of it — read the deployment's own declared servers, or probe a caller-supplied list. Presence of the bit is carried by the engine version, so an **absent key means an older engine** (that route answers a coded 404) and is read as *not reported*, never as *no*; an explicit `false` is the engine's own no and is reported without inventing a reason (whether caller-supplied declarations are accepted is a different bit's question); a non-boolean is malformed and is dropped rather than folded into a no. The availability verdict answers only *should this call go on the wire*: an explicit no means zero requests, and both kinds of *cannot tell* are sent anyway, so an older engine answers with its own coded refusal instead of being silently skipped. One failure judge serves both ports and asks **provenance before status**: a 4xx, 501 or 503 that carries no machine code proves nothing about who answered and is reported as *no verdict*; twelve coded refusals each get their own arm (three identity codes, one of which sits outside the `auth.` family so a prefix fallback would miss it; three different treatments ride the same 400), and a coded answer this version does not recognise lands in *cannot tell*, never in *this engine has no such face*. Retry-after seconds ride 429 and 503 and are absent rather than 0 when the engine gave none. The 200 body is narrowed through the **same per-row narrower** as the streaming `wiring_manifest.mcp[]` leg and the session panel's replay leg, liveness cell included; on this face rows are paired with the submitted declarations **by index**, so a dropped row makes the whole answer unreadable rather than a half table, a row count that differs from the submitted count is reported as misaligned, and an honest empty `servers: []` is kept apart from *non-empty but nothing readable*. `probedAt` and `ttlSec` pass through untouched — this package mints no freshness verdict — the declaration list is handed over as-is with its length snapshotted once, a list that serialises itself differently from what was counted is refused locally with zero requests, and no port ever retries a dial. |
413
413
  | `scripts/run-sdk-wire-transit-test.mjs` | The package's pass-through of a few SDK names (`sdkWireTransit`), pinned: every value re-export is the **same reference** as the SDK's own (a client class the host recognises with `instanceof`, the two approval-frame predicates, the three session-bundle calls and the SDK error class), not a look-alike wrapper — wrapping would discard the one anti-drift guarantee a pass-through has; every type re-export is present by name in the emitted declaration file; the gate's list and the source file's export lists are compared in both directions so a name added to one without the other turns red; and a name the SDK does not export must fail the same test, so the gate is not vacuously green. |
414
+ | `scripts/run-sdk-registry-transit-test.mjs` | The package's cloud control-plane surface (`sdkRegistryTransit`), which lives behind its own `./registry` subpath entry point rather than on the root barrel, and this guard holds both halves of that decision. Upstream publishes the same surface behind a subpath of its own, because the subject differs: the engine-wire surface speaks for one engine's service credential, this one for a person's rotating token, and their refresh and error semantics were deliberately never merged. Keeping it behind a second entry point means a client that never touches the control plane neither resolves nor type-checks it. Every value re-export is therefore read from the file the subpath entry actually resolves to, and must be the **same reference** as upstream's own (the control-plane client class, the three config reads, the health probe, the feedback call, the auth-path constant, the content-address helper, and the two typed error classes a host recognises with `instanceof`); every type re-export is compared with the emitted declaration file in both directions; the gate's list and the source file's export lists are likewise compared both ways; and the root entry is checked to carry none of these names, with the root barrel's own source checked to reference the entry file nowhere — a name leaking onto the root would put the cost of this surface back on clients that never asked for it. The subpath is then verified end to end: the installed SDK must really publish its own `./registry` entry and declare every transited name inside it, and this package's own `exports` must point that subpath at exactly the files the gate just judged. Portability is two checks rather than one, done with a parser rather than a text search: the upstream subpath's emitted JavaScript, walked recursively, must contain neither a `node:` specifier (static, side-effect, dynamic, `require` and re-export forms all exercised) nor a Node **global** — because the same package's third entry point is a Node-only surface that imports nothing at all and reaches for the `Buffer` global, so a specifier check alone would pass it as isomorphic, while a byte-level search of it reports two `node:` hits that live entirely inside a documentation example. A text scanner that merely strips comments first gets both directions wrong on ordinary JavaScript — a regular-expression literal containing a slash pair swallows the rest of its line, and the word in a string reads as a reference — so both scanners run off the syntax tree and are checked against fixtures for each failure direction as well as against that real material — including a dynamic import written with a template literal, which a check that accepts only quoted strings misses entirely, and a dynamic import whose target cannot be determined statically, which is refused rather than read as no edge at all. Zero-processing is likewise enforced with a syntax-tree allowlist rather than a keyword search: every top-level statement must be a named re-export carrying that one specifier, so an import followed by an in-place edit of the upstream prototype is refused with a file and line — that shape leaves the name lists untouched and even keeps the same-reference check green, since both sides are then the one object that was damaged. The last section measures, rather than merely notes, one declaration-level gap: two of the upstream subpath's declaration files reference a package the SDK lists only among its own dev dependencies. Moving such a check to a scratch directory is not isolation, because package resolution walks the ancestor directories, so the gate builds a sandbox served by a restricted compiler host and proves the isolation both ways — a decoy copy of the missing package placed one level above the sandbox must silence the errors for an unrestricted host and must not silence them for the restricted one. Then it installs this package into that same sandbox as a real consumer would, and pins the two readings that justify the entry-point split: a consumer that imports only from the root sees no unresolved-module errors at all, while a consumer that imports the subpath sees exactly the two, reported honestly rather than swallowed by this layer. The day upstream ships those declarations, that section turns red and the note comes out with it. The separation itself rests on the root closure being computed correctly, so the portability guard that computes it was extended in the same change: a template-literal dynamic import is followed like any other edge, and an edge whose target cannot be resolved statically is refused on every one of the four graphs — without that, a single line in a third file already reachable from the root would put this surface back into the root runtime while every guard stayed green. |
414
415
 
415
416
  Each suite carries a floor that only moves up — a refactor that stops executing a group of
416
417
  assertions is a failure, not a quieter pass. Guards anchor on the **installed artefact's content**
@@ -193,6 +193,10 @@ export function readRunCostFacts(stats, observed) {
193
193
  reconcile,
194
194
  };
195
195
  }
196
+ function structuredOutputParts(r) {
197
+ const so = r.structuredOutput;
198
+ return so !== undefined ? { structured_output: so, structuredOutput: so } : {};
199
+ }
196
200
  function effectiveFactParts(rec) {
197
201
  const reasoning = readEffectiveReasoning(rec.effectiveReasoning);
198
202
  const scopes = readEffectiveMemoryScopes(rec.effectiveMemoryScopes);
@@ -503,10 +507,7 @@ export function doneToSdkResult(ev, ctx, observed) {
503
507
  is_error: false,
504
508
  num_turns: stats?.turns ?? 0,
505
509
  result: r.result ?? '',
506
- ...(() => {
507
- const so = r.structuredOutput;
508
- return so !== undefined ? { structuredOutput: so } : {};
509
- })(),
510
+ ...structuredOutputParts(r),
510
511
  ...(degraded !== undefined ? { degraded } : {}),
511
512
  stop_reason: null,
512
513
  total_cost_usd: costOrNull(stats),
@@ -447,11 +447,20 @@ export function isToolApprovalFrame(ev) {
447
447
  typeof e.approvalId === 'string' &&
448
448
  e.approvalId.length > 0);
449
449
  }
450
- const FS_WRITE_GATE_ASK_PATTERN = /^approve write to "([^"]+)"\?$/;
450
+ const FS_WRITE_GATE_ASK_PREFIX = 'approve write to "';
451
+ const FS_WRITE_GATE_ASK_PATH_CLOSE = '"?';
451
452
  function pathFromGateMessage(message) {
452
453
  if (typeof message !== 'string')
453
454
  return undefined;
454
- return FS_WRITE_GATE_ASK_PATTERN.exec(message)?.[1];
455
+ if (!message.startsWith(FS_WRITE_GATE_ASK_PREFIX))
456
+ return undefined;
457
+ const body = message.slice(FS_WRITE_GATE_ASK_PREFIX.length);
458
+ const close = body.indexOf(FS_WRITE_GATE_ASK_PATH_CLOSE);
459
+ if (close <= 0)
460
+ return undefined;
461
+ if (body.indexOf(FS_WRITE_GATE_ASK_PATH_CLOSE, close + 1) !== -1)
462
+ return undefined;
463
+ return body.slice(0, close);
455
464
  }
456
465
  function isNonNegativeFinite(v) {
457
466
  return typeof v === 'number' && Number.isFinite(v) && v >= 0;
@@ -27,7 +27,7 @@ export const REQUEST_FIELD_MATRIX = [
27
27
  { field: 'limits', lanes: ['print', 'utility'], live: true, why: 'P2-3-b:`-p` 的预算护栏(--max-* flag 族),交互 REPL 由人随时 Esc', whyUtilityLane: '有座:side-channel 必须带预算护栏(墙钟 / 输出 token / 轮数)—— 它同样没有人看着,而且没有后续回合可以中断' },
28
28
  { field: 'interactiveTools', lanes: ['print', 'utility'], live: true, why: '[909]B 件3:无人值守 stamp false,从 roster 源头灭掉 AskUserQuestion/plan 门。交互车道 stamp false 等于自废武功', whyUtilityLane: '有座:side-channel 绝不该弹交互问答 / plan 门(没有人在看这条提交)。它与 excludeAllTools 是**两条独立**的收紧声明、在这条车道上**并存**(本车道强制带卸载声明,见 `refuseUtilityWithoutToolUnload`;这一位是它旁边那条「连问都别问」的声明,不是它的降级替身)' },
29
29
  { field: 'oneShot', lanes: ['print', 'utility'], live: true, why: 'SDK TaskRequest.oneShot(server ≥7.12.0 消费):`-p` 提交是一次性的——没有后续回合接住异步后台通知,core 据此把「结束回合等通知」指引换成 block-wait;交互车道有后续回合,stamp true 就是谎报。老 worker 静默忽略(开集提交体),故发送侧不设能力位前置门(oneShotWireCaps 头注)', whyUtilityLane: '有座:side-channel 就是一次性提交 —— 没有后续回合接住异步后台通知,引擎据此把「结束回合等通知」换成 block-wait' },
30
- { field: 'outputSchema', lanes: ['print', 'utility'], live: true, why: '结构化输出约束(sdk `TaskRequest.outputSchema`:最终答案必须匹配的 JSON Schema)。上游只验形状与序列化尺寸(坏形 400 响亮拒)、深层合法性归引擎 ⇒ 本层原样透传、不预铸第二判官。来源只在无人值守车道(`--json-schema` 一类旗);交互面今天没有入口 ⇒ 缺席是**没有来源**,不是漏。⚠️ 本行只管**上行**这一位:结果一侧的结构化产出落不落 CC 形 result 帧是下行投影的事,不在本表', whyUtilityLane: '有座:side-channel 的典型形正是「要一个可机读的小答案」(分类 / 摘要 / 抽取),结构化输出约束是它最直接的位,而 schema 由壳自己给 ⇒ 有来源' },
30
+ { field: 'outputSchema', lanes: ['print', 'utility'], live: true, why: '结构化输出约束(sdk `TaskRequest.outputSchema`:最终答案必须匹配的 JSON Schema)。上游只验形状与序列化尺寸(坏形 400 响亮拒)、深层合法性归引擎 ⇒ 本层原样透传、不预铸第二判官。来源只可能在无人值守车道(schema 由壳的无人值守入口给;哪个壳今天真的接了那条入口是壳侧的事,本表只说座位);交互面今天没有入口 ⇒ 缺席是**没有来源**,不是漏。⚠️ 本行只管**上行**这一位:结果一侧的结构化产出落不落 CC 形 result 帧是下行投影的事,不在本表', whyUtilityLane: '有座:side-channel 的典型形正是「要一个可机读的小答案」(分类 / 摘要 / 抽取),结构化输出约束是它最直接的位,而 schema 由壳自己给 ⇒ 有来源' },
31
31
  { field: 'outputRetries', lanes: ['print', 'utility'], live: true, why: '结构化输出的重试轮数(sdk `TaskRequest.outputRetries`;与 `outputSchema` 是**成对旋钮** —— 没有 schema 时引擎忽略它)。🔴 座位集与 `outputSchema` 那一行**逐字相同**:一半有座一半没座 = 端调得动重试轮数却调不动它所服务的约束(同座孪生分开定座,正是「主轴改了、孪生漏了」那一族)。上游接受域很窄(有限、≥1、向下取整、封顶 10),**表外一律整键省略**并回落引擎缺省 ⇒ 本层对坏值**响亮拒**(见 `refuseBadOutputRetries`),但**不预夹** [1,10]:夹是上游的事,本层不铸第二判官', whyUtilityLane: '有座:与 outputSchema 同座孪生 —— side-channel 要机读小答案时,重试轮数是同一个旋钮的另一半' },
32
32
  { field: 'maxCostUsd', lanes: ['print', 'utility'], live: true, why: '花费上限声明(sdk `TaskRequest.maxCostUsd`,请求体**顶层**位;上游向下夹到部署上限 —— 只许要得更少)。与 `limits` 同一条理由只在无人值守车道:交互面由人随时中断。🔴 坏值(非数 / 非有限 / 非正)在本层**响亮拒**:上游对这一位的坏值是安静忽略并回落部署上限,不是 4xx(见 `refuseBadMaxCostUsd`)', whyUtilityLane: '有座:小预算是本车道的定义之一(与 limits 同一条理由);上游向下夹到部署上限,只许要得更少' },
33
33
  { field: 'maxTokens', lanes: ['print', 'utility'], live: true, why: '整任务 token 预算上限声明(sdk `TaskRequest.maxTokens`,请求体**顶层**位,与 `maxCostUsd` 同属上游那一族「调用方要求的上限」:向下夹到部署上限 —— 只许要得更少)。🔴 座位集与 `maxCostUsd` 那一行**逐字相同**:同一条预算轴的两种计价单位,分开定座就是让其中一条静默漂。🔴 坏值(非数 / 非有限 / 非正 / 非整)在本层**响亮拒**:上游对这一位的坏值是安静按「调用方没给」处理并回落部署上限,不是 4xx —— 部署没设上限时这一次运行就没有 token 闸,而声明人不会知道(见 `refuseBadMaxTokens`)', whyUtilityLane: '有座:与 maxCostUsd 同轴孪生 —— 小预算是本车道的定义之一,两种计价单位都该能声明' },
@@ -0,0 +1,6 @@
1
+ export { RegistryClient } from '@sema-agent/sdk/registry';
2
+ export { getMeConfig, getScopeConfigDraft, getEffective } from '@sema-agent/sdk/registry';
3
+ export { probeRegistryHealth, postFeedback } from '@sema-agent/sdk/registry';
4
+ export { REGISTRY_AUTH_PATHS, skillContentAddress } from '@sema-agent/sdk/registry';
5
+ export { RegistryApiError, OAuthFlowError } from '@sema-agent/sdk/registry';
6
+ export type { RegistryTokens, TokenProvider, } from '@sema-agent/sdk/registry';
@@ -0,0 +1,5 @@
1
+ export { RegistryClient } from '@sema-agent/sdk/registry';
2
+ export { getMeConfig, getScopeConfigDraft, getEffective } from '@sema-agent/sdk/registry';
3
+ export { probeRegistryHealth, postFeedback } from '@sema-agent/sdk/registry';
4
+ export { REGISTRY_AUTH_PATHS, skillContentAddress } from '@sema-agent/sdk/registry';
5
+ export { RegistryApiError, OAuthFlowError } from '@sema-agent/sdk/registry';
@@ -19,7 +19,7 @@
19
19
 
20
20
  | 项 | 值 | 真源 |
21
21
  |---|---|---|
22
- | 本包 | `@sema-agent/client-core` **0.79.0**(本批发布版 = **minor**:server 7.93.0 过境批 —— peer sdk 地板 >=11.2.1 + 写口回执第六臂 unverified 与 503 体 committed 分臂(CC-124)+ 无 run 可读的 MCP 状态面(CC-74)+ 审批卡 mandated 位(CC-110)+ 请求装配第三车道 utility 与 approverPosture / maxTokens / outputRetries 三键 + print 车道 model 座(CC-116 / 118 / 123)+ 拒因两面分铸与四个机读位(CC-125)+ 模型轮边界划消息界(CC-126)+ 委派结果人类面读口按来源声明体内定位(CC-127)+ sdk 转口三件(CC-128)+ 通告码 memory.project_scope_absent(CC-122);公面 1184;§85。上一版 0.78.2 = **patch**:门的棘轮登记数字单真源 —— 五只门十一格棘轮 + 218 条沿革账搬进 scripts/registry.json、门只读不抄、负控改篡改登记物、下调通道 RATCHET-SLACK、新门 run-registry-test(CC-79 第一期)+ 两格存量松量收掉 + submit-wiring-manifest 门补 count===1 边界格;src 零改动,dist 逐字节同 0.78.1;公面 1154;§84。上一版 0.78.1 = **patch**:两辆并行车收货 + 三张跟进票 —— displayBody 人类面读口 + 围栏解析头尾配对收紧(CC-113)/ MCP 两处「没报」措辞分句(CC-115)/ 记忆治理面五动词调用口(CC-97 b)/ 非流式提交回执接线回执读口 readSubmitWiringManifest(CC-121)/ 三份失败判官抛出物读取收口(CC-119);公面 1154;§83。上一版 0.78.0 = **minor**:peer sdk 地板 >=9.8.1 → >=11.0.1(CC-106)+ 单步写口 200 体按 stillLive 判别联合改读、第五臂 revoked、三型取自 sdk、RulesFacade.write 必填、PersistedRuleLiveness 转口(CC-103)+ DeniedBy 第十词 read_boundary 专句(CC-106 ④)+ excludeAllTools 车道行;型面 BREAKING 三处、行为面同 0.77.2;公面 1143;§82。上一版 0.77.2 = **patch**:出包面结构卫生 —— 构建期 removeComments,dist js / d.ts 零注释(新门 run-dist-comments-test.mjs + 卫生门词表 32 条 + 文档向前执法;CC-100)+ gateDeniedByDetail 表外词兜底句改「本版不认识这个层名」(CC-111 ①);行为 / 型面逐字节同 0.77.1;公面 1143;§81。上一版 0.77.1 = **patch**:外部验收三件回填 —— 读器族边界残留 projectMcpReconnectCapability 只认自有键(CC-107)/ rewind 四子键恰读一次(CC-108)/ 子代输出合并按回体 output.type · retrieval_status 定处置(CC-109,server ≥7.92.0 cursorSemantics 缺席面);型面 additive 一处;公面 1143;§80。上一版 0.77.0 = **minor**:请求装配逐键去向回执 + print 车道补座 + 表外键响亮拒(CC-101,四条行为 BREAKING)/ 会话策略写端口(CC-105)/ 持久规则单步写面(CC-103)/ workflow 子代面板行代际三向恢复(CC-104,零改码)/ 能力位读器族口径整族改齐 + 外部验收 F-A / F-B 处置 + 合并树异源复审两轮处置;公面 1143;§79。上一版 0.76.2 = **patch**:制品卫生 —— 清 dist 重 build 去掉两只已撤出源码的编译产物 + dist ⇄ src 对账门;零源码 / 零型面 / 零行为改动;公面 1122;§78。上一版 0.76.1 = **patch**:能力位读器工厂(CC-75)/ MCP 活性观察读口(CC-36)/ `capabilities.peerLane` · `permissionRulesWrite` 四态读口(CC-102)/ 记忆治理面两只读口 + 三只条目面回体读口(CC-97 a)/ 主车道证明逐次新建(CC-99)+ 修 0.76.0 的 F1 / F2(身份四键一次性快照只修了投影口一侧);公面 1122;§77。上一版 0.76.0 = **minor**:六票一批 —— `prompt_assembled` 投影臂 / 审批 feed 三态(**型面 BREAKING**)/ `ApprovalResolution` 单源联合 / 记忆 spec 读口 / 终态词表上游钉 / `tasks_expand` 退役(**型面 BREAKING**),外加身份四键一次性快照(跨全部内部臂);公面 1081;§76。上一版 0.75.1 = **patch**:面板短命子代反序缓行放不出的残洞(外部复验 D1)+ 同代 running 帧三向定形(B4)+ #969 提货 `spawnName` 透传与 `agentType` 改读诚实来源(CC-95);§75。上一版 0.75.0 = **minor**:压缩的非 compacted 结局上 chrome 面 `compaction_outcome`(新内部臂 —— 自建 print 出口的端先表态)+ peer sdk 地板 `>=9.8.1`;型面 additive(ChromeEvent +1 臂)、公面 1065、零 wire 新键;§74。上一版 0.74.5 = **patch**:core 7.24.0 提货 `_sema_freed_tokens?` + 首见即终态的行零事件(幽灵完成行)+ `isNewEngineAgentPanelCycle` / `approvalOutcomeNoteOf` 上公面;型面 additive、公面 1065、peer 不动;§73。上一版 0.74.4 = **patch**:面板键「先发布的键为准」(tick 归不了一的三序不再两行)+ 前代 UUID 迟到 tick 丢弃 + `readRunCancelContext` 下钻收紧;型面 additive、公面 1061、peer 不动;§72。上一版 0.74.3 = **patch**:面板子代身份归一(tick / end 的 UUID 归到 fleet 尾段,宿主零改)+ run 记录 `cancelContext` 读口与成因四词 + workflow 行 `errorCode` + reopen 第二臂两件;型面纯 additive、公面 1061、peer 不动;§71。上一版 0.74.2 = **patch**:`capabilities.deviceExecutor.management` 四态读口(缺席 ≠ false;`deviceExecutor: false` = 车道缺席;管理动词可用性三态归包);公面 1052;§70。上一版 0.74.1 = **patch**:审批卡无决断收口 + 结局回交;§69。上一版 0.74.0 = **minor**:peer sdk 地板 >=9.7.1 + covers 过境 + 面板周期身份 + 离场读口;§68。上一版 0.73.5 = **patch**:workflow 规模告警判定上收进包(`evaluateWorkflowSize` 三态:未知的规模不当作规模正常;分母口径与帽优先级单源;env 读口纯函数);型面纯 additive、公面 1044、peer 不动;§67。上一版 0.73.4 = **patch**:终帧 `permission_denials` 第三键 ⇐ 同一条流 `tool_start` 入参按 `toolCallId` join(三道闸;join 不上留 sema 载体;🔴 更正 0.73.2「自动升级收口」一句)+ 审批 feed push 侧取件失败的欠账退避重试;型面纯 additive、公面 1033、peer 不动;§66。上一版 0.73.3 = **patch**:CC-61 sdk 9.7.1 提货 + `capabilities.approvalsStreamLive` 四态读口(缺席 = 判不出;`livePendingNeedsReconcile` 只在引擎明说会推时才让对账节拍降兜底)+ CC-60 五条模型面文案锚包侧半场(cursorSemantics 机读位 / result 行注记 / bash 首行两变体与良性槽 / 通知 seed 并集 / parked 臂);型面纯 additive、公面 1032、peer 不动;§65。上一版 0.73.2 = **patch**:CC-59 悬挂 ask 全卡 —— `livePending[].frame`(server ≥7.87.0)两道闸窄读进视图,在场即走流内帧腿同一条路(入参可见、改写可转发),缺席保持盲卡;CC-34 收口(引擎半场随 7.87.0 到货,判据交黑盒);型面纯 additive、公面 1026、peer 不动;§64。上一版 0.73.1 = **patch**:CC-57 `decidePlanReview` outcome 尾句按「决断有没有生效」四态选(单铸点 `planReviewOutcomeTail`;此前本地拒发仍让模型汇报已拒绝)+ CC-56 cancel 的 409 按机器码分家(`cancelConflictFromError` 三形 / 新安全码 `cancel_run_not_running`)与提交面 429 用量窗读口 + 人话;型面纯 additive、公面 1026、peer 不动;§63。上一版 0.73.0 = **minor,型面 BREAKING**:fleet 视图八个数值键改可选 —— CC-52 `FleetTaskView.elapsedMs` / `tokens` / `queuedCount` 与 `FleetWorkflowView.doneCount` / `totalCount` / `failedCount` / `tokens` / `elapsedMs` 不再 `?? 0`(有键 = 真值含真 0,缺键 = 不知道;逐键缺席语义见 §62b)+ 台账补偿链无基数不铸;公面导出名零增减 1019、零 wire 变化、peer 不动;§62。上一版 0.72.14 = **patch**:悬挂的流内 ask 拉半场 —— CC-55 `startApprovalsFeed` 快照加 `livePending` 段并进变化摘要(键缺席 = 未报,不铸空)+ 视图 / 去重账 / 与流内帧腿同链的决断口(入参不可见上卡明说、改写不转发)+ 宿主闸对账节拍 + 待决计数读口(不知道 = null);型面纯 additive、公面 1019、peer 不动;§61。上一版 0.72.13 = **patch**:server 7.86.0 提货 —— CC-46 plan_review `permissionModeAfter` 发口(三选卡双闸:宿主声明只读起步 ∧ 引擎 ≥7.86.0;400 field_conflict 两种处置)+ CC-54 `capabilities.executionLane` 四态读面(键缺席 ≠ 不是本机车道;`toolsRunHere` 判据归包)+ CC-53 detach 版本闸三态;型面 additive(另撤回 0.72.12 的主通道 `absent` 臂,改独立缺席订阅口)、公面 1011、peer 不动;§60;**预告 0.73.0 BREAKING**:fleet 视图数值键改可选。上一版 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 八条)|
22
+ | 本包 | `@sema-agent/client-core` **0.79.1**(本批发布版 = **patch**:终帧结构化产出同帧铸 CC 形 `structured_output`(旧拼法 `structuredOutput` 过渡一版,0.80.0 删;CC-130)+ 写审批 `argsOmitted` 退化卡在无受护写入部署形上重新解得出路径(CC-129)+ 云控制面十值二型经本包第二个入口 `@sema-agent/client-core/registry` 原样转口(根入口零变;CC-128 ①);根公面 1184;§86。上一版 0.79.0 = **minor**:server 7.93.0 过境批 —— peer sdk 地板 >=11.2.1 + 写口回执第六臂 unverified 与 503 体 committed 分臂(CC-124)+ 无 run 可读的 MCP 状态面(CC-74)+ 审批卡 mandated 位(CC-110)+ 请求装配第三车道 utility 与 approverPosture / maxTokens / outputRetries 三键 + print 车道 model 座(CC-116 / 118 / 123)+ 拒因两面分铸与四个机读位(CC-125)+ 模型轮边界划消息界(CC-126)+ 委派结果人类面读口按来源声明体内定位(CC-127)+ sdk 转口三件(CC-128)+ 通告码 memory.project_scope_absent(CC-122);公面 1184;§85。上一版 0.78.2 = **patch**:门的棘轮登记数字单真源 —— 五只门十一格棘轮 + 218 条沿革账搬进 scripts/registry.json、门只读不抄、负控改篡改登记物、下调通道 RATCHET-SLACK、新门 run-registry-test(CC-79 第一期)+ 两格存量松量收掉 + submit-wiring-manifest 门补 count===1 边界格;src 零改动,dist 逐字节同 0.78.1;公面 1154;§84。上一版 0.78.1 = **patch**:两辆并行车收货 + 三张跟进票 —— displayBody 人类面读口 + 围栏解析头尾配对收紧(CC-113)/ MCP 两处「没报」措辞分句(CC-115)/ 记忆治理面五动词调用口(CC-97 b)/ 非流式提交回执接线回执读口 readSubmitWiringManifest(CC-121)/ 三份失败判官抛出物读取收口(CC-119);公面 1154;§83。上一版 0.78.0 = **minor**:peer sdk 地板 >=9.8.1 → >=11.0.1(CC-106)+ 单步写口 200 体按 stillLive 判别联合改读、第五臂 revoked、三型取自 sdk、RulesFacade.write 必填、PersistedRuleLiveness 转口(CC-103)+ DeniedBy 第十词 read_boundary 专句(CC-106 ④)+ excludeAllTools 车道行;型面 BREAKING 三处、行为面同 0.77.2;公面 1143;§82。上一版 0.77.2 = **patch**:出包面结构卫生 —— 构建期 removeComments,dist js / d.ts 零注释(新门 run-dist-comments-test.mjs + 卫生门词表 32 条 + 文档向前执法;CC-100)+ gateDeniedByDetail 表外词兜底句改「本版不认识这个层名」(CC-111 ①);行为 / 型面逐字节同 0.77.1;公面 1143;§81。上一版 0.77.1 = **patch**:外部验收三件回填 —— 读器族边界残留 projectMcpReconnectCapability 只认自有键(CC-107)/ rewind 四子键恰读一次(CC-108)/ 子代输出合并按回体 output.type · retrieval_status 定处置(CC-109,server ≥7.92.0 cursorSemantics 缺席面);型面 additive 一处;公面 1143;§80。上一版 0.77.0 = **minor**:请求装配逐键去向回执 + print 车道补座 + 表外键响亮拒(CC-101,四条行为 BREAKING)/ 会话策略写端口(CC-105)/ 持久规则单步写面(CC-103)/ workflow 子代面板行代际三向恢复(CC-104,零改码)/ 能力位读器族口径整族改齐 + 外部验收 F-A / F-B 处置 + 合并树异源复审两轮处置;公面 1143;§79。上一版 0.76.2 = **patch**:制品卫生 —— 清 dist 重 build 去掉两只已撤出源码的编译产物 + dist ⇄ src 对账门;零源码 / 零型面 / 零行为改动;公面 1122;§78。上一版 0.76.1 = **patch**:能力位读器工厂(CC-75)/ MCP 活性观察读口(CC-36)/ `capabilities.peerLane` · `permissionRulesWrite` 四态读口(CC-102)/ 记忆治理面两只读口 + 三只条目面回体读口(CC-97 a)/ 主车道证明逐次新建(CC-99)+ 修 0.76.0 的 F1 / F2(身份四键一次性快照只修了投影口一侧);公面 1122;§77。上一版 0.76.0 = **minor**:六票一批 —— `prompt_assembled` 投影臂 / 审批 feed 三态(**型面 BREAKING**)/ `ApprovalResolution` 单源联合 / 记忆 spec 读口 / 终态词表上游钉 / `tasks_expand` 退役(**型面 BREAKING**),外加身份四键一次性快照(跨全部内部臂);公面 1081;§76。上一版 0.75.1 = **patch**:面板短命子代反序缓行放不出的残洞(外部复验 D1)+ 同代 running 帧三向定形(B4)+ #969 提货 `spawnName` 透传与 `agentType` 改读诚实来源(CC-95);§75。上一版 0.75.0 = **minor**:压缩的非 compacted 结局上 chrome 面 `compaction_outcome`(新内部臂 —— 自建 print 出口的端先表态)+ peer sdk 地板 `>=9.8.1`;型面 additive(ChromeEvent +1 臂)、公面 1065、零 wire 新键;§74。上一版 0.74.5 = **patch**:core 7.24.0 提货 `_sema_freed_tokens?` + 首见即终态的行零事件(幽灵完成行)+ `isNewEngineAgentPanelCycle` / `approvalOutcomeNoteOf` 上公面;型面 additive、公面 1065、peer 不动;§73。上一版 0.74.4 = **patch**:面板键「先发布的键为准」(tick 归不了一的三序不再两行)+ 前代 UUID 迟到 tick 丢弃 + `readRunCancelContext` 下钻收紧;型面 additive、公面 1061、peer 不动;§72。上一版 0.74.3 = **patch**:面板子代身份归一(tick / end 的 UUID 归到 fleet 尾段,宿主零改)+ run 记录 `cancelContext` 读口与成因四词 + workflow 行 `errorCode` + reopen 第二臂两件;型面纯 additive、公面 1061、peer 不动;§71。上一版 0.74.2 = **patch**:`capabilities.deviceExecutor.management` 四态读口(缺席 ≠ false;`deviceExecutor: false` = 车道缺席;管理动词可用性三态归包);公面 1052;§70。上一版 0.74.1 = **patch**:审批卡无决断收口 + 结局回交;§69。上一版 0.74.0 = **minor**:peer sdk 地板 >=9.7.1 + covers 过境 + 面板周期身份 + 离场读口;§68。上一版 0.73.5 = **patch**:workflow 规模告警判定上收进包(`evaluateWorkflowSize` 三态:未知的规模不当作规模正常;分母口径与帽优先级单源;env 读口纯函数);型面纯 additive、公面 1044、peer 不动;§67。上一版 0.73.4 = **patch**:终帧 `permission_denials` 第三键 ⇐ 同一条流 `tool_start` 入参按 `toolCallId` join(三道闸;join 不上留 sema 载体;🔴 更正 0.73.2「自动升级收口」一句)+ 审批 feed push 侧取件失败的欠账退避重试;型面纯 additive、公面 1033、peer 不动;§66。上一版 0.73.3 = **patch**:CC-61 sdk 9.7.1 提货 + `capabilities.approvalsStreamLive` 四态读口(缺席 = 判不出;`livePendingNeedsReconcile` 只在引擎明说会推时才让对账节拍降兜底)+ CC-60 五条模型面文案锚包侧半场(cursorSemantics 机读位 / result 行注记 / bash 首行两变体与良性槽 / 通知 seed 并集 / parked 臂);型面纯 additive、公面 1032、peer 不动;§65。上一版 0.73.2 = **patch**:CC-59 悬挂 ask 全卡 —— `livePending[].frame`(server ≥7.87.0)两道闸窄读进视图,在场即走流内帧腿同一条路(入参可见、改写可转发),缺席保持盲卡;CC-34 收口(引擎半场随 7.87.0 到货,判据交黑盒);型面纯 additive、公面 1026、peer 不动;§64。上一版 0.73.1 = **patch**:CC-57 `decidePlanReview` outcome 尾句按「决断有没有生效」四态选(单铸点 `planReviewOutcomeTail`;此前本地拒发仍让模型汇报已拒绝)+ CC-56 cancel 的 409 按机器码分家(`cancelConflictFromError` 三形 / 新安全码 `cancel_run_not_running`)与提交面 429 用量窗读口 + 人话;型面纯 additive、公面 1026、peer 不动;§63。上一版 0.73.0 = **minor,型面 BREAKING**:fleet 视图八个数值键改可选 —— CC-52 `FleetTaskView.elapsedMs` / `tokens` / `queuedCount` 与 `FleetWorkflowView.doneCount` / `totalCount` / `failedCount` / `tokens` / `elapsedMs` 不再 `?? 0`(有键 = 真值含真 0,缺键 = 不知道;逐键缺席语义见 §62b)+ 台账补偿链无基数不铸;公面导出名零增减 1019、零 wire 变化、peer 不动;§62。上一版 0.72.14 = **patch**:悬挂的流内 ask 拉半场 —— CC-55 `startApprovalsFeed` 快照加 `livePending` 段并进变化摘要(键缺席 = 未报,不铸空)+ 视图 / 去重账 / 与流内帧腿同链的决断口(入参不可见上卡明说、改写不转发)+ 宿主闸对账节拍 + 待决计数读口(不知道 = null);型面纯 additive、公面 1019、peer 不动;§61。上一版 0.72.13 = **patch**:server 7.86.0 提货 —— CC-46 plan_review `permissionModeAfter` 发口(三选卡双闸:宿主声明只读起步 ∧ 引擎 ≥7.86.0;400 field_conflict 两种处置)+ CC-54 `capabilities.executionLane` 四态读面(键缺席 ≠ 不是本机车道;`toolsRunHere` 判据归包)+ CC-53 detach 版本闸三态;型面 additive(另撤回 0.72.12 的主通道 `absent` 臂,改独立缺席订阅口)、公面 1011、peer 不动;§60;**预告 0.73.0 BREAKING**:fleet 视图数值键改可选。上一版 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` **>=11.2.1**(value-level,非 type-only;**0.79.0 抬版**:11.2.x 声明 `capabilities.mcpProbe`、`mcpCapabilities` / `probeMcp` + `McpProbeFace`、写回执第三支 `stillLive: "unknown"`,11.2.1 再补 `TaskRequest.approverPosture` 与审批帧键 `mandated`(型面 + 运行期键锚),本包按 11.2.1 编译,11.0.1 失去物料见证;**0.78.0 曾抬到 >=11.0.1**:11.x 声明 `DeniedBy` 第十词 `read_boundary`、`rules.write` 200 体按 `stillLive` 判别联合、`RemovalLiveness` / `RuleWriteRequest` / `RuleWriteResult` / `RuleWriteBehavior` 包根导出、`TaskRequest.excludeAllTools`,本包按 11.0.1 编译,9.8.1 失去物料见证;**0.75.0 曾抬到 >=9.8.1**:9.8.x 声明 `Capabilities.deviceExecutor.management?`,9.7.1 失去物料见证;**0.74.0 曾抬到 >=9.7.1**:9.7.x 追平的六处型面是本包 0.73.3 起的编译基线,且 9.6.0 失去物料见证;**0.71.0 曾抬到 >=9.6.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` |
@@ -125,10 +125,10 @@ SDK 核对「本包 import 的每个值级符号仍然导出」「`TaskStats.cos
125
125
 
126
126
  > 📦 **随包 / 不随包**:npm 包只带 `dist` / `README` / `CHANGELOG` / 本档 / `LICENSE`。本档各处提到的 `docs/type-superset.json`、`scripts/*.json`、`scripts/run-*-test.mjs` 都是**仓内登记物与门,不随包发出** —— 装包的消费者找不到它们是预期;`_sema_` 超集键的**随包契约**就是本档各 §NNz 逐键处置表(键名 / 值域 / 缺席语义逐条在表里)。
127
127
  >
128
- > 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**1184** 项)。
128
+ > 全集真源 = `scripts/public-export-baseline.json` 的 `names`(**1184** 项;该基线只覆盖**根**入口,子路径入口 `./registry` 的名单在 §86 与 `scripts/run-sdk-registry-transit-test.mjs` A / C 段)。
129
129
  > 本节**不逐名抄**,只给「域 → 承重导出 → 用途 → 实现锚」。承重导出 = 一个端为了让这个域干活
130
130
  > **必须**直接调到的那几个符号;其余是它们的类型、变体与辅助位。
131
- > 单一入口:`import { … } from '@sema-agent/client-core'`(`exports` 只有 `.` 一个;
131
+ > 两个入口:根 `import { … } from '@sema-agent/client-core'`(会话运行时;`exports` 的 `.`)+ `import { … } from '@sema-agent/client-core/registry'`(云控制面原样转口,0.79.1 起;`exports` 的 `./registry`,§86);
132
132
  > 内部路径**不是**公面,`src/abortableSleep.ts` / `src/envFlag.ts` / `createSessionSlot` 是刻意不出 barrel 的包内叶)。
133
133
 
134
134
  ### 2a. 🔴 基线是**运行期**契约,不是全部公面(端最容易误读的一格)
@@ -9599,6 +9599,66 @@ installCoreValuePorts({ resolveAutonomousLoopPrompt, loosenReasons, combinePolic
9599
9599
 
9600
9600
  **包侧缺口:** ① 出包面注释存量(别仓名 / 票号 / 帖号 / 过程词)与卫生门判据太窄(CC-100)—— 方案候拍板(dist 去注释 vs 手清),0.77.2 · ② `DeniedBy` 第十词 `read_boundary` / `teamName` / `stillLive` 三词随 sdk 10 型面在 0.78.0 吸收(CC-106)· ③ `capabilities.mcpProbe` 候 core 7.26.0 #951 → server 7.93.0(CC-74)。
9601
9601
 
9602
+ ## §86 🆕 0.79.1 终帧结构化产出改用 CC 拼法 + 写审批退化卡拿回路径 + 云控制面进子路径入口 `@sema-agent/client-core/registry`(patch;根公面 1184 不变、peer 地板不动)
9603
+
9604
+ > **patch**:peer `@sema-agent/sdk` 地板不动(`>=11.2.1`);🔴 **根公面运行期导出 1184 一个不变**(§0a 计数零变)。三件:
9605
+ > ① **终帧结构化产出改用 CC 拼法**(CC-130):`outputSchema` 任务的产出此前只以 camelCase `structuredOutput` 铸在成功终帧上,而 CC 形 `SDKResultSuccess` 的那一位叫 **`structured_output`**(snake_case;同族 subtype `error_max_structured_output_retries` 亦 snake_case)—— 按 CC 形读 `result.structured_output` 的消费方一律读空。本版起同一帧**同时**铸两个名字、同值同引用;旧拼法 deprecated,**0.80.0 删**。**销 §79 ① 的 pending**:那一行处置表写的「`outputSchema` 下行 `structured_output` **pending** 另票」(0.77.0 登)就是本票,下行位本版落地。
9606
+ > ② **写审批退化卡拿回路径**(CC-129):`tool_approval` 帧带 `argsOmitted`(或流上没有 `tool_start.args`)时,审批卡的路径回落**开始能解出来了** —— 此前在「引擎环境不提供受护写入」的部署形上它恒缺席,卡上的 diff 恒退化成空写。**行为面只改这一处**,零型面、零导出变化。
9607
+ > ③ **云控制面十个值 + 两个型走新的第二个入口** `@sema-agent/client-core/registry`(CC-128 ①;`package.json` exports 的 `./registry`),与上游 `@sema-agent/sdk/registry` **同一引用**;零 wire 键、零投影臂、零缺席语义变化。**不用云控制面的端:零升级动作。**
9608
+
9609
+ ### 86a. 处置表
9610
+
9611
+ | # | 面 | 本包做了什么 | 端要做什么 |
9612
+ |---|---|---|---|
9613
+ | S-1 | `result.structured_output`(成功臂;CC-130) | **added**:CC 形权威位,值 = wire `TaskResult.structuredOutput` 原样过境(同一引用,不窄化不深拷) | **consumed**:读这一位 |
9614
+ | S-2 | `result.structuredOutput`(成功臂;CC-130) | **deprecated**:与 S-1 同值同引用并存一版;**0.80.0 删** | 改读 S-1;0.80.0 之前不要新增按此键的读法 |
9615
+ | S-3 | 错误信封(`SDKResultError` 形;CC-130) | **n-a**:两个拼法**都不铸** —— CC 错误臂没有这一位 | 零改;别在失败终帧上等这一位 |
9616
+ | S-4 | 写审批卡的路径回落 `args.file_path`(退化腿;CC-129) | **fixed**:判据从「整串两端锚死」改成「问句本体在**句首** + 路径收口在句体里**唯一**」的体内定位;引擎在那句问话之后恒追加的说明句(以及可选的写入域说明句)**原样忽略**。解不出 / 判不出仍是**诚实缺席**(空写),不猜 | **零换装**。若端自己从 ask 文案里兜过路径(壳侧热修),现在可以撤掉并改读卡上的 `args.file_path`;撤之前先核对两边对「解不出」的处置是否一致 |
9617
+ | R-0 🔴 **入口** | 本包新开第二个入口 `./registry`(CC-128 ①) | 云控制面**不进根 barrel**:根链对上游那条声明面缺口与将来的 Node-only 漂移保持干净;根公面 / §0a / 根闭包全零变;两个入口的图**不相交**(子路径入口文件零相对 import、零本包自引用,由门按 dist 产物实扫) | 只用会话运行时的端:**零动作**;要云控制面的端:改从 `@sema-agent/client-core/registry` 取 |
9618
+ | R-1 | 云控制面十个值 | **added(原样转口)**:`RegistryClient` / `getMeConfig` / `getScopeConfigDraft` / `getEffective` / `probeRegistryHealth` / `postFeedback` / `REGISTRY_AUTH_PATHS` / `skillContentAddress` / `RegistryApiError` / `OAuthFlowError` —— 与 `@sema-agent/sdk/registry` **同一引用**(门按 `===` 钉),零包装零默认值 | 把这十名的 import 落点从 SDK 子路径改到 `@sema-agent/client-core/registry`;`instanceof` 判据零改(是同一个类对象)。🔴 **新码不许走转口口**:新的云控制面逻辑写进本包 |
9619
+ | R-2 | 令牌契约两个型 | **added(`export type`)**:`RegistryTokens` / `TokenProvider` | 同上;`TokenProvider` 仍是**宿主要实现**的接口,本包不提供实现(刻意不转 `InMemoryTokenProvider`) |
9620
+ | R-3 | 未转的五名 | **declined / pending** —— `requestDeviceCode` / `pollUntilApproved` / `refreshTokens` / `listScopes` / `switchScope` 今天转不干净(签名型来自上游只在 devDependencies 里的声明包) | 端的登录 / 令牌刷新 / scope 切换那条腿**继续直连**;退役条件本批到 **六 / 七**(内容寻址那条腿已可退役) |
9621
+ | R-4 | `@sema-agent/sdk/device` | **declined** —— Node-only 面(零 import、靠 Node 全局 `Buffer`),转它等于把只在 Node 里成立的面放进本包的浏览器打包面 | 需要设备面的端自行直连,别期待本包转口 |
9622
+
9623
+ ### 86b. 缺席语义(逐键)
9624
+
9625
+ - **结构化产出两键同出同缺**(CC-130):引擎 `TaskResult` 上这一位缺席 ⇒ **两键都不铸**(不是铸一个值为 `null` / `{}` 的键)。**键在场而值 `undefined` 同缺席**:也是两键都不铸 —— 铸一个值为 `undefined` 的键,会让按 `in` / `hasOwnProperty` 判在场的消费方把「引擎没产出」读成「产出是空的」。**falsy 不等于缺席**:`null` / `0` / `""` / `false` 是真产出,两键照铸;端的在场判据请写 `Object.hasOwn(r, 'structured_output')` 或 `!== undefined`,**不要写 truthy**。**非记录形也照带**:数组(含空数组)、串、数字、布尔 —— 形状由调用方自己的 `outputSchema` 决定,本包不解释、不筛形、不深拷,原样过境且**引用相同**。严格形校验的取舍:把整条 `result` 按 CC 形做封闭校验(`.strict()` / `additionalProperties: false`)的消费方会因 `structuredOutput` 这个 CC 没有的键拒收整帧;该面在 0.79.0 及以前已因十余个既有 additive 位(`errorCode` / `model` / `_sema_*` 族)同样不可用 —— 本版不是新风险源,0.80.0 删旧拼法后此条销。
9626
+ - **卡入参 `args.file_path`(退化腿;CC-129)**:**缺席 = 这次没解出可信的路径**,不是「路径是空的」。四种形归同一格:① 帧上根本没有那句问话(耐久盲卡形);② 是**另一句** ask(引擎那条策略还会说「这次调用没有可约束的路径目标」和「真实目标解不出来」两句,后者其实带着路径,本包**刻意不读**);③ 问句本体**不在句首**(整段协议文本被嵌进了别人的话里);④ 🔴 **歧义**:路径收口形在句体里出现两次以上 —— 路径是引擎原样插进去的自由文本,它自己就能带上收口形,判不出哪一只是真收口,**答缺席,绝不挑第一只**;⑤ 空路径(收口紧贴前缀)同答缺席。尾巴**不参与判定**:引擎在问句之后追加的说明句怎么改措辞都不影响解出来的路径;反过来,问句本体那一段**逐字**改口会让本读口当天全缺席。路径里**自带一只引号**时逐字解得出(修前那条判据在这一形上也解不出)。
9627
+ - **云控制面(CC-128 ①)**:本批**零新键、零新读口**,转出去的是上游那一个函数 / 类对象本身,缺席语义一律以上游为准,本包不加一层判读、不补默认值、不替宿主选 `fetch`、不替宿主存令牌。
9628
+
9629
+ ### 86c. 黑盒判据骨架
9630
+
9631
+ > 🔴 判据分两类,别混用:**标「本版证明」的格**在 0.79.0 产物上必须 FAIL、在 0.79.1 上必须 PASS;**标「回归约束」的格**两版都 PASS,证不了本次修复,只保证没被改坏。验收方请记下两次跑的**产物标识**(版本 + tarball shasum),只跑一版证不出方向。本包发布前已在 0.79.0 的 npm tarball(shasum `dce5cea3…`)上实跑 O-G1 / O-G2 / O-G4 / O-G6 与 A-G1:全 FAIL;候选产物全 PASS。
9632
+
9633
+ - **O-G1**(本版证明):`done` 帧 `result.structuredOutput = {verdict:'ok'}`(**成功臂**,`status: 'completed'`)⇒ 终帧 **`Object.hasOwn(msg, 'structured_output') === true`**。喂到错误信封上两版都不铸,整组判据当场失去判别力。
9634
+ - **O-G2**(本版证明):同一帧 `msg.structured_output === msg.structuredOutput`,且**两者 === 喂进去的那个对象**(引用相等,不是深等)。
9635
+ - **O-G3**(回归约束):`done.result` 不带该位 ⇒ 两个键都不在(`hasOwn` 与 `in` 两向);带该键但值 `undefined` ⇒ 同答。
9636
+ - **O-G4**(本版证明):值取 `null` / `0` / `""` / `false` 四形,以及 `[]` / `[{…}]` / 非空串 / 数字 / `true` 五形 ⇒ **两键**在场且 `===` 该值。
9637
+ - **O-G5**(回归约束):`done.result.terminal.kind = 'failed'` 且带该位 ⇒ 终帧 `is_error === true` 且**两个键都不在**。
9638
+ - **O-G6**(本版证明,给自建管线的端):`TaskResult` 上把该位定义成每次返新对象的取值器 ⇒ 两键仍 `===` 相等(本包对 wire 位恰读一次)。
9639
+ - **A-G1**(本版证明):用装着的引擎包构造一只**没有**受护写入能力的写门策略,让它对一次受护写发问,拿它**自己拼出来的那句话**当 `tool_approval` 帧的文案(帧带 `argsOmitted`、流上不给 `tool_start.args`)。断言:卡入参 `args.file_path` **逐字等于**喂给策略的那个路径。🔴 红基线:同一输入在 0.79.0 上 ⇒ `args` 是**空对象**。
9640
+ - **A-G2**(回归约束 + 本版证明各半):同一条策略换成**有**受护写入能力(那句话后面什么都不追加)⇒ 照解(两版皆 PASS);再让它同时带上写入域说明句(两截尾巴)⇒ 照解(0.79.0 FAIL)。三形同一个路径值。
9641
+ - **A-G3**(回归约束):让路径本身带上收口形(引擎原样插值,真造得出)⇒ `args` 空对象、`file_path` 缺席。
9642
+ - **A-G4**(回归约束):同一条策略的另两句 ask(没有可约束的路径目标 / 真实目标解不出)⇒ 两句都不读,`args` 空对象 —— 第二句带着路径也不读。
9643
+ - **A-G5**(回归约束):把那句问话**嵌进**一段别的话里(前面加一句引子)⇒ 不读。
9644
+ - **R-G1**(本版证明):`import * as reg from '@sema-agent/client-core/registry'` 与 `import * as up from '@sema-agent/sdk/registry'`,十名逐个 `reg[n] === up[n]` 为真(不是「结构相同」,是同一个对象);`new reg.RegistryApiError(404,'x') instanceof up.RegistryApiError` 为真。0.79.0 上子路径根本解析不到。
9645
+ - **R-G2**(回归约束):`import * as root from '@sema-agent/client-core'` 上这十二名 `Object.hasOwn(root, n)` 全 false(根入口零漏出)。
9646
+ - **R-G3**(本版证明):`package.json` exports 恰 `.` + `./registry` 两个入口,`./registry` 的 `types` / `default` 两指向都落在盘上真文件;`npm pack` 清单含 `dist/sdkRegistryTransit.js` 与 `.d.ts`。0.79.0 上 exports 只有 `.`。
9647
+ - **R-G4**(上游树:回归约束;本包入口:本版专属):`@sema-agent/sdk/registry` 递归全树零 `node:` 说明符 ∧ 零 Node 全局(两版皆 PASS,验的是装着的上游);`--platform=browser` 打**本包**子路径入口零 error、产物零 `require(` / 零 `node:`(0.79.0 上该入口不存在,只在 0.79.1 上验)。
9648
+ - **R-G5**(本版专属,新入口检查):子路径入口产物零相对 import、零本包自引用、外向边恰 `{@sema-agent/sdk/registry}`(两个入口的图不相交)。0.79.0 上没有这份产物,不在旧版上跑。
9649
+ - **R-G6**(三格分开读):在一棵**不继承祖先 `node_modules`** 的隔离树上 `skipLibCheck: false` —— ① 只 import 根入口 ⇒ **0 条** TS2307(**两版皆 PASS**,回归约束);② 0.79.0 上 import `@sema-agent/client-core/registry` ⇒ **解析不到该子路径**(旧版没有这个入口;这是预期,不是「两条 registry-core 错误」);③ 0.79.1 上 import 该子路径 ⇒ **恰 2 条** TS2307,逐条指着 `@sema-agent/registry-core`(登记值;上游补齐那天变 0 并同批销账)。
9650
+
9651
+ ### 86y. 🔴 三端升级必读(固定段式,[C295])+ 成文改口
9652
+
9653
+ 1. **换钉 `^0.79.1` 之后**:sdk 钉不用动(peer 地板 `>=11.2.1` 不变)。逐面:
9654
+ - **结构化产出**:把 `result.structuredOutput` 的读法改成 `result.structured_output`(CC 形)。两个键在本版同值同引用,改读法是**零风险**的一步,可以先改再验。🔴 **0.80.0 会删 `structuredOutput`**,本版是唯一的过渡窗:端侧若有按旧键名的类型声明 / 快照夹具 / JSON 断言,请同批改;0.80.0 之后按旧键读到的是 `undefined`,而 `undefined` 在这条语义上表示「引擎没产出」—— 不改就会把「有产出」静默读成「没产出」。⚠️ 构建期去注释让 `@deprecated` 进不了声明文件,退役通告只在 CHANGELOG 与本段。
9655
+ - **写审批卡**:**零换装**。要做的只有一件事:搜端侧有没有自己从审批卡的问话文本里兜路径的代码(在包侧回落恒缺席的那段日子里,壳很可能自己兜过);有就撤掉、改读卡上的 `args.file_path`;🔴 撤之前确认端侧那一份对「解不出」的处置也是**缺席**而不是猜一个。
9656
+ - **云控制面**:十个值 + 两个型改从 `@sema-agent/client-core/registry` 取;`instanceof` / 错误分支 / 调用签名**逐字节零改**(是同一份实现)。🔴 **子路径 `types` 要 `moduleResolution: bundler` 或 `node16` / `nodenext`**(`node10` 解析不到 `exports` 子路径的 `types` 条件)。🔴 **不用云控制面的端零动作**:根入口导出一个不多,也不会多出那两条 TS2307。🔴 **新码不许走本转口口**:它只给存量搬落点用。🔴 **本批不覆盖登录那条腿**:设备码申请 / 轮询 / 令牌轮换 / scope 列举 / scope 切换五名**没转**,那条腿本批**仍需**直连,豁免不许在本批销掉。🔴 **`skipLibCheck: false` 且 import 子路径的端注意**:会多出**恰两条** `Cannot find module '@sema-agent/registry-core'`;三档取舍:① 留在 `skipLibCheck: true`(三端现状);② 自己装一份那个声明包;③ 等上游把那两处 `import type` 的型改成自带(根治,本包零改动跟批)。
9657
+ 2. **零改的面**:§79–§85 全部原样适用;wire 面、投影臂、审批帧既有每一个键的过境字节与缺席语义、请求装配、转录切行一个字节未动;写审批卡除 S-4 那一处外的每一个键不变;根公面导出、peer 地板、`tool_approval` 帧键镜像、卡入参键集都不变。
9658
+ 3. **成文改口(旧判据眼作废 → 新判据眼)**:① 「本包终帧 DROP CC `structured_output`」(投影器头注与旧段)**作废** → 它现在是铸出来的位;② §34 处置表第 6 行「本包不碰 `structuredOutput` 的字节,`src/` 全树 0 命中」在**字节**那一半仍成立(原样过境、同一引用),在**命中数**那一半自 TaskResult 五键批起已过期;③ 旧判据「终帧上有 `structuredOutput`」不再能区分修前修后 → 新判据眼只认 `structured_output`,并对错误臂断言两键都无;④ §79 ① 「`structured_output` pending 另票」**销**;⑤ 「引擎那句写审批问话后面跟了别的字节 ⇒ 本包一律不解析」**作废** → 尾巴原样忽略,问句本体在句首且收口唯一就解;按旧口径断言「带后缀的文案必然解不出路径」的验收格会把正确行为判成红;⑥ 「卡上没有路径 = 引擎没给」**作废** → 0.79.0 及更早版本上那多半是本包的判据没能说话,0.79.1 起缺席才真的是「这次没解出可信的路径」;⑦ §0a「单一入口,`exports` 只有 `.` 一个」**作废** → 两个入口(根 + `./registry`),内部路径仍不是公面。
9659
+
9660
+ **包侧缺口:** ① 同形族第二处(CC-131):`type:'user'` 转录记录上本包铸 `toolUseResult`,而 CC `SDKUserMessage` 声明 `tool_use_result`(CC 自己的转录记录面用 camelCase、SDK 消息面用 snake_case)—— 先钉「本包交的 user 记录对标哪一面」再决定改名 / 双键 / 不动 · ② 引擎那条写门策略的**第二句** ask(真实目标解不出)其实带着路径,本包**不读**(那一句说的是「这个路径解析不了」,当成卡上的路径展示会让用户以为门确认过这个目标);升级判据 = 有端报出「那一形的卡也需要路径」的现场 · ③ 退化卡上方那句降级说明在**解不出**时照样声称「从问话重建了」,以及编辑闸没覆盖退化腿、耐久 park 腿入参不披露 —— 三条挂 CC-135 · ④ 上游 registry 子路径的声明面传递引用一个它只列在 devDependencies 里的声明包 ⇒ import 子路径且 `skipLibCheck: false` 的下游多两条 TS2307(门里按登记值钉住;上游补齐那天销账)· ⑤ 云控制面退役条件本批到 **六 / 七**:登录 / 令牌刷新 / scope 切换那条腿仍需直连(五名转不干净,与 ④ 同一条缺口)· ⑥ `./device` 子路径 Node-only,本包不转 · ⑦ 本包不转 `InMemoryTokenProvider`(上游给测试用的存储实现)· ⑧ 转口口是**原样**的:上游的重试节奏 / 401 单飞 refresh / 错误分类一个字节不加工,本包不背书也不加判读 · ⑨ 子路径入口的公面名单**没有** `public-export-baseline.json` 那样的登记物(基线只收根入口的运行期导出),它的等值登记在 `scripts/run-sdk-registry-transit-test.mjs` 的 A / C 段(门名单 ⇄ 源码双向);要不要给子路径也开一本基线,下一版定 · ⑩ §85 缺口原样。
9661
+
9602
9662
  ## §85 🆕 0.79.0 server 7.93.0 过境批:写口回执第六臂 + 无 run 可读的 MCP 状态面 + 审批卡「清不掉」那一位 + 请求装配第三车道与四个 wire 键;minor(型面 / 行为面 BREAKING + 地板)
9603
9663
 
9604
9664
  > **minor**:peer `@sema-agent/sdk` 地板 `>=11.0.1` → **`>=11.2.1`**(四处同批);公面运行期导出 1154 → **1184**(策展清单口径,不含测试钩;运行期 `Object.keys` 全量 = 该数 + 57 个测试钩);请求装配新键三枚进车道表(`approverPosture` / `maxTokens` / `outputRetries`)+ 第三条车道 `utility`;审批帧新键 `mandated`;型面 BREAKING —— `writePersistedRule` 结局联合 +1 臂 `unverified`、`RulesFailure` +2 kind、拒因表 +1 词、`RequestLane` +1 词、`RequestFieldSpec.whyUtilityLane` 必填;行为面 BREAKING —— 无人值守车道从此带 `model`;deny 收口帧按归因分两串(策略拒不再冠成「用户不想继续」);模型轮结束划 assistant 消息界(轮末段粘连 + 假阳性披露修复)。🔴 **不可发组合**:server 7.93.0 + client-core < 0.79.0(`stillLive: "unknown"` 第六臂 / `mcpProbe` 读口)。按表态制点名三端(48h 三选一)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/client-core",
3
- "version": "0.79.0",
3
+ "version": "0.79.1",
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",
@@ -10,6 +10,10 @@
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
12
  "default": "./dist/index.js"
13
+ },
14
+ "./registry": {
15
+ "types": "./dist/sdkRegistryTransit.d.ts",
16
+ "default": "./dist/sdkRegistryTransit.js"
13
17
  }
14
18
  },
15
19
  "repository": "github:sema-agent/sema-client-core",