@sema-agent/client-core 0.102.0 → 0.103.0
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 +96 -0
- package/README.md +8 -5
- package/dist/adapt/toolCards.d.ts +2 -1
- package/dist/adapt/toolCards.js +3 -1
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +5 -1
- package/dist/adapter/downstream/eventToSdkMessage.js +21 -3
- package/dist/adapter/downstream/terminalToSdkResult.js +0 -1
- package/dist/adapter/downstream/wiringManifestView.js +4 -1
- package/dist/cloudConfigWireCaps.js +6 -3
- package/dist/credentialPlaneCapability.d.ts +22 -0
- package/dist/credentialPlaneCapability.js +75 -0
- package/dist/deviceExecutorManagementCapability.d.ts +1 -0
- package/dist/deviceExecutorManagementCapability.js +3 -1
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +3 -1
- package/dist/engineNoticeCodes.d.ts +26 -0
- package/dist/engineNoticeCodes.js +121 -12
- package/dist/engineRowRef.js +1 -0
- package/dist/errorSupplementRoles.js +1 -3
- package/dist/eventLeg.js +2 -1
- package/dist/fleet/fleetProjection.js +15 -9
- package/dist/gateOutcome.d.ts +20 -0
- package/dist/gateOutcome.js +89 -0
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +6 -2
- package/dist/generated/engineFactTables.js +41 -1
- package/dist/generated/engineNoticeTables.js +18 -0
- package/dist/generated/settingsSchemaDefaultModel.d.ts +1 -1
- package/dist/generated/settingsSchemaDefaultModel.js +2 -2
- package/dist/generated/settingsSchemaFns.d.ts +15 -0
- package/dist/generated/settingsSchemaFns.js +25 -2
- package/dist/generated/settingsSchemaHooksClassifier.js +109 -29
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +213 -93
- package/dist/generated/settingsSchemaMcpServerName.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpServerName.js +8 -0
- package/dist/generated/settingsSchemaOwnKeyRead.d.ts +1 -0
- package/dist/generated/settingsSchemaOwnKeyRead.js +172 -0
- package/dist/generated/settingsSchemaPlainJsonObject.d.ts +1 -0
- package/dist/generated/settingsSchemaPlainJsonObject.js +28 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.js +10 -7
- package/dist/generated/settingsSchemaTierWords.d.ts +1 -0
- package/dist/generated/settingsSchemaTierWords.js +7 -0
- package/dist/generated/settingsSchemaTypes.d.ts +3 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/decisionConflict.js +11 -11
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +4 -2
- package/dist/hitl/editedRuleTextPrecheck.d.ts +1 -0
- package/dist/hitl/editedRuleTextPrecheck.js +26 -1
- package/dist/hitl/persistedRulesWire.js +1 -0
- package/dist/hitl/planReviewWire.d.ts +2 -1
- package/dist/hitl/planReviewWire.js +8 -12
- package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
- package/dist/hitl/sessionPolicyDeliverable.js +0 -5
- package/dist/hitl/sessionPolicyWire.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +18 -6
- package/dist/hitl/toolApprovalWire.js +9 -4
- package/dist/i18n/messages.en.d.ts +5 -0
- package/dist/i18n/messages.en.js +6 -1
- package/dist/i18n/messages.zh.js +6 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/inheritEnvWire.d.ts +1 -0
- package/dist/inheritEnvWire.js +8 -5
- package/dist/mcpEngineLeg.d.ts +3 -0
- package/dist/mcpEngineLeg.js +4 -1
- package/dist/mcpLiveness.d.ts +18 -0
- package/dist/mcpLiveness.js +48 -1
- package/dist/mcpReconnect.d.ts +3 -0
- package/dist/mcpReconnect.js +6 -0
- package/dist/mcpStatusSupersetKeys.js +24 -1
- package/dist/mcpWireCaps.d.ts +2 -3
- package/dist/mcpWireCaps.js +9 -8
- package/dist/memoryEntriesWire.d.ts +35 -1
- package/dist/memoryEntriesWire.js +110 -14
- package/dist/modsFace.js +7 -3
- package/dist/postureKnob.js +1 -1
- package/dist/prepareRefusal.d.ts +0 -1
- package/dist/prepareRefusal.js +0 -3
- package/dist/promptProfileWireCaps.d.ts +1 -3
- package/dist/promptProfileWireCaps.js +2 -2
- package/dist/request/taskRequest.d.ts +1 -1
- package/dist/request/taskRequest.js +3 -3
- package/dist/retryStatus.d.ts +13 -1
- package/dist/retryStatus.js +20 -5
- package/dist/seatContract.js +10 -0
- package/dist/sessionMemoryErase.js +24 -2
- package/dist/turnFailurePresentation.js +8 -1
- package/dist/wireFailureShape.d.ts +12 -1
- package/dist/wireFailureShape.js +58 -24
- package/dist/wireRefusalCopy.d.ts +0 -3
- package/dist/wireRefusalCopy.js +0 -17
- package/docs/INTEGRATION-CLIENTS.md +155 -10
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -49,6 +49,102 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
+
## 0.103.0(2026-10-29)
|
|
53
|
+
|
|
54
|
+
> 主题:一次重锚到引擎 7.59.0(开发依赖 `@sema-agent/core` / `@sema-agent/mods-kernel` 7.59.0 · `@sema-agent/sdk` 28.0.0 · `@sema-agent/settings-schema` 14.8.0;生成表按新上游重生成)接入文档 **§131 PK-1 – PK-10** —— MCP 授权失败记录一只读口四处过境 · 两只新通知事实读器 · 状态帧等待两位 · 工具结果行改参记录 `_sema_rewrite` 与改参句 · 服务器名 `remote-` 前缀律 · 决断拒收「行完整性」只认正证据 · 请求键 `promptProfile` 换布尔 `promptLean`(🔴 型面 BREAKING)· 三处退役(RL-300 / RL-301 / RL-302)· 引擎 7.59.0 的抹除证明 v2 与整工具规则候选读得出 · 服务端 7.137.0 随附件 **§131 PK-10**(求助无门出路清单 · `invalid_session` 并进会话坏档判定 · 规则编辑文本修剪单铸点 · 计划审阅决断体带门身份 · 凭据平面读口 · 可收形 / 设备直达入口 / `inheritEnv` 拒因三位)· 结果帧成功臂不再带 `errors[]`(🔴 行为变,**§131 LG-1**)· 六只派生窄视图退出根入口(🔴 型面 BREAKING,**§131 LG-2**)。peer 地板不动。
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- **🔴 型面 BREAKING:请求键 `promptProfile`(两词 `simple` / `classic`)换布尔 `promptLean`;映射口 `promptProfileFromEnv` → `promptLeanFromEnv`**(CC-1044;**§131 PK-7**;退役登记 RL-300):`TaskRequestInput.promptLean?: boolean`(`false` = 完整长形;缺席 = 目录缺省),车道表那一行同名换掉;`promptLeanFromEnv(env)` 只答 `false`(环境词 `classic`,大小写与首尾空白归一)或 `undefined`(其余一律不带键)。型 `PromptProfile` 与旧映射口退出根入口,零别名。按名调用旧口 / 入参写 `promptProfile` 的宿主编译红,改调新口 / 新键。🔴 行为:`promptLean` 只有服务端 7.137.0 起受理(7.136.x 及更早的服务端对它答 `400 request.body_shape`);宿主只在用户显式选了长形时才交这一键。**升级顺序**:服务端先升到 ≥ 7.137.0,再放用户选 `classic`(先升本包而服务端仍旧 ⇒ 选了 `classic` 的用户每一单都被拒)。
|
|
59
|
+
- **🔴 型面 BREAKING:根入口停转口 `RuleSuggestion`**(CC-1044;**§131 PK-7**;退役登记 RL-302):上游类型包删了这只退役前身型(规则候选只有 `RuleOffer` 一代,本包读口自 0.93.0 起只读 `ruleOffers`)。从本包引这只型的宿主编译红,改引 `RuleOffer`。
|
|
60
|
+
- **fleet 行 wire 键清单**(CC-1044;**§131 PK-7**;退役登记 RL-301):task 行清单去掉幻影键 `queuedCount`(上游类型删了声明;视图自 0.95.0 起就不带它);workflow 行清单加 `errorCode` / `parked` 两键(登记为「设计上不投影」—— 两者折进运行状态那一只判法,视图键不变)。对清单做精确等值断言的端须改断言。
|
|
61
|
+
- **决断拒收 409 分码:`row_integrity` 只认正证据**(CC-1045;**§131 PK-5**;🔴 行为变,只对「两词都缺」的拒收可见):`approval_binding_mismatch` 而没有 `field` 时,只有拒收体带了 `reason`(行完整性词,读法与 `field` 同:`extra` 优先、顶层兜底、只读自有数据位、非空串)才判 `row_integrity`;两词都缺 ⇒ 不给词(修前从缺席推断为坏行,把可改正的载荷拒读成「那一行坏了」)。拒收体的 `field` / `reason` 与机读袋各只读一次,分码出自同一份读数。🔴 射程:服务端 7.132.0 起才把拒收体的 `reason` 过境(支持底线 7.129.1 – 7.131.x 不带),引擎 7.59.0 起 `bound_input_hash_missing` 那一形的坏行才带 `reason` —— 在这些组合上,真坏了的那一行也拿不到 `row_integrity`,按一般拒收出句(按分码走「坏行」路的端在那里按一般绑定不符处置;见 Known limitations)。
|
|
62
|
+
- **MCP 服务器名 `remote-` 前缀律**(CC-1044;**§131 PK-8**;🔴 行为变,只对以小写 `remote-` 起头的名字可见):名字用法判官改用配置契约 14.8.0 的 MCP 服务器名判官;小写 `remote-` 起头的名字(含恰为 `remote-`)保留给已连接设备提供的 MCP 服务器 —— 本地整表口与云腿同拒(本地成因新词 `name_reserved`,带「改名」出路句;云腿成因词不变),大小写异形(`Remote-x`)照收、不算设备名;首尾空白先答空白。`McpConfigDropReason` / `McpServerNameUnusableReason` 各多一词 `name_reserved`(对两型穷举的端补一臂)。
|
|
63
|
+
- **中心配置腿承运 MCP 条目的 `startupTimeoutMs`**(CC-1044;**§131 PK-8**;🔴 行为变,只对中心配置里写了这一键的条目可见):配置契约 14.8.0 起中心配置条目也声明这台服务器的启动上限;`cloudMcpToSpecs` 与本地腿 `mcpConfigToSpec` 同一读法 —— 入口读一次,在场就原样上体,不判、不钳(值形判官在引擎);读就抛 ⇒ 这一台记 `entry-unreadable`。修前中心下发的上限被剥掉、这一台按缺省上限起。可达性:只在中心配置下发的条目原样带着这一键时生效(配置契约 14.8.0 起条目声明它;下发方是否原样透传本包不判);服务端请求面受理这一键。
|
|
64
|
+
- **请求面 MCP 条目嵌套位读不出时降级而不整台丢**(配置契约 14.6.0 起的请求面快照读法,随换钉到达;**§131 PK-8**):`env` / `headers`(整个或成员值)/ `principalHeader` 是检视不了的外来值(已撤销代理等)⇒ 与该位的任何非法值同律:这一台照上、丢该位、降级行点名该位(句子说「could not be inspected」);`args` 整个读不出仍判整份传输坏。修前这几形整台 `transport_invalid`。同批:传输位不是普通数据对象(类实例等)⇒ 这一台判传输坏;`principalHeader` / `assertionHeader` 只在原型链上 ⇒ 不读(只认自有位),并记一条读数问题。
|
|
65
|
+
- **钩子设置分类随配置契约 14.8.0 重生成**(**§131 PK-8**;🔴 行为变,只对非 JSON 形的设置对象可见):别的运行环境(realm)里造的普通对象按普通对象读;形状读不出的值(已撤销的代理)与靠迭代协议装内容的对象(`Map` / `Set` 等)按最严处置(当作可能带护栏标记);钩子条目与钩子块上的 `type` 只认自有位(原型链上的不算)。从 JSON 解析出来的设置零变化。
|
|
66
|
+
- **回执段 mod 行带 `provenance`**(CC-1045;**§131 PK-6**):`wiring_manifest.mods[]` 两形行视图(`WiringManifestModMountedView` / `WiringManifestModRefusedView`)多可选位 `provenance`(宿主给这条注册的出处标签,原串;非空串才在场)。
|
|
67
|
+
- **`invalid_session` 并进会话坏档判定**(CC-1044 ②;**§131 PK-10**;🔴 行为变,只对这一码可见):服务端 7.137.0 起,存着的会话日志父链走不通(悬空父 / 成环 / 叶子不在日志里)答 `invalid_session`(同步口 500、流式 `done` 终局、后台 run 行)。`isCorruptSessionCode` 认 `corrupt_session` / `invalid_session` 两词,三处载体读口、分诊位 `sessionUnreadable`、失败呈现(不给重试)、终局行与结果帧 `errors[0]` 的补句都随它,与 `corrupt_session` 同一句;码原样(`_sema_error_code`)。修前这一码走通用 5xx、给重试。导入面的 `422 invalid_entries`(调用方交来的日志坏)不认。
|
|
68
|
+
- **计划审阅决断体带门身份 `checkpointId`**(CC-1044 ⑥;**§131 PK-10**;🔴 行为变,只对报 `planReviewCheckpointId: true` 的服务端可见):决断时门身份读得出(宿主递了停驻结果)且这台引擎的能力位恰为 `true` ⇒ 体末多 `checkpointId`(去键重发的那一发照带)。能力位读哪台引擎的:已装目标形读目标地址上的;注入连线形读连线自己给的 `capsBaseUrl` 上的(不给 ⇒ 不带,不借已装目标的能力);门已换 ⇒ 服务端答 `409 approval_stale`、任何状态不动,结局落「没生效」。位缺席 / 非真 / 没观测 ⇒ 体逐字节同旧。自己给计划审阅请求签直连门证明的宿主须把这一位签进信封扩展对象。
|
|
69
|
+
- **计划审阅注入连线读 `capsBaseUrl` 就抛 ⇒ 连线不可用**(CC-1044 ⑥;**§131 PK-10**;🔴 行为变,只对给了取值器抛或严格代理连线的宿主可见):这一位与整族注入连线同读,读就抛的连线立卡不出(`armPlanReviewApproval` 答 `false`)、决断不发(「没送出」)。修前这一位一次也不读、决断照常送出。
|
|
70
|
+
- **`inheritEnv` 拒体读口认领请求上的任一值**(CC-1044 ⑨;**§131 PK-10**;🔴 行为变,只对请求带的不是 `"all"` 的拒可见):请求上真带了 `inheritEnv`(任一值,含 `"scrub"` 与词表外的值)而拒体机读位点名了这一项 ⇒ `inheritEnvRefusalFromError` 答肯定读数并带 `reason`(值形被拒的 `unknown_word` / `not_a_string` 也读得到),失败呈现出肯定句;拒体没有机读位时仍只对 `"all"` 答条件句。肯定句首段改说这一项的受理规则(只收缺省与整份环境两种取值,整份环境另要求工具跑在引擎自己那台机器上且请求属于某个会话),不再断言这次请求要了整份环境。修前请求带的不是 `"all"` 一律答 `null`。
|
|
71
|
+
- **规则编辑文本提交前修剪**(CC-1044 ⑤;**§131 PK-10**;🔴 行为变,只对带外缘空白的编辑可见):活卡编辑臂上 wire 的文本与预检口交给判官的文本同经 `trimEditedRuleText` —— 修掉前导 / 尾随空白与工具名和 `(` 之间的空白,内部空白不动。修前这几形得 `400 request.body_shape`(服务端 7.137.0 起)。
|
|
72
|
+
- **引擎帧三臂登记**(**§131 PK-6**):`approval_complete` / `session_titled` 两帧投影口有痕丢弃(`dropped` / `unsupported_arm`,修前落 `unknown_arm`),`cross_boundary_taint` 帧归「不在本切片」组(`none` / `not_in_slice`,修前同落 `dropped` / `unknown_arm`);HITL 帧集多 `approval_complete`(事件腿同族登记上下文后照放)。用户可见零变化;按丢弃词统计或告警的宿主会看到这三帧的词变了。
|
|
73
|
+
|
|
74
|
+
- **🔴 结果帧成功臂不再带 `errors[]`**(CC-1088;**§131 LG-1**;行为变,只对 `subtype: 'success'` 且 `is_error: true` 的结果帧可见):0.101.0 起,判型答 CC 成功臂的未完成终局(末行是 API 错误行或模型正文 —— 经 `runStream` 的失败 / 被拦 / 取消 / 结局不明都落这一臂)除必填键 `result` 外多带一份原因文本 `errors[]`,是给「按 `errors[0]` 出失败句」的端换读 `result` 的过渡一版(CC 成功臂没有这一键)。本版删这一键:`result` 不变(末行正文;读不出时是原先 `errors[]` 逐条换行拼接的同一串,同一只凭据网),错误臂的 `errors[]` 不变(CC 错误臂成员)。**改法**:成功臂的失败句读 `result`,错误臂读 `errors[0]`(通用写法 `frame.errors?.[0] ?? frame.result`);只判成败的端(读 `is_error` / `terminalReasonForResult`)零变化。终端的两处 `errors` 读点只读错误臂 / 无 `result` 的兜底形,不受影响;网页端 / 桌面端判成败读 `is_error`,零读点(推断:本机 origin/main 快照)。🔴 例外一形:停驻 ∧ 本流末行是模型正文 ⇒ 帧走成功臂,`-p` 停驻出路句(`Turn suspended awaiting …`)此前只在这个 `errors[0]` 上,本版起这一形上没有承载键(KL-1031;见 Known limitations)。
|
|
75
|
+
|
|
76
|
+
- **🔴 型面 BREAKING:六只派生窄视图退出根入口**(CC-843 / CC-836;**§131 LG-2**;退役登记 RL-179 · RL-192 – RL-196 执行,门钉不复活;公面运行期导出 −6):`hookMatcherRefusalFromError`(= 族读口 `settingsHooksRefusalFromError(err)?.matcher`;型 `HookMatcherRefusal` 留作 `matcher` 位的型)· `mcpConfigsToSpecs`(= `projectMcpConfigs(servers).specs`;坏形条目的丢弃与降级行读同一口的 `dropped` / `degraded`)· `legacyToolNameFailureNoteOf` 与 `imageInvalidFailureNoteOf`(各 = `prepareRefusalNoteOf(code)` 在 `config.legacy_tool_name` / `config.image_invalid` 上的答案,句子逐字不变;码从 `prepareRefusalCodeOf` 取)· `userAttachmentRefusalContent`(= `prepareRefusalNoteOf('config.user_attachment_invalid', { index })`)· `userInvokedSkillRefusalContent`(= `prepareRefusalNoteOf('config.user_invoked_skill_unknown')`)。六只自 0.100.0 起都是同一张「码 → 句」表或同一份投影的派生窄视图(同一只抛出物两口同答),三端生产源已不读。**编译红必改**:按名 import 这六名的宿主(含测试夹具)改读上面的单口(终端测试侧读点:`enginePinCapsReadings.test.ts` · `sessionPolicyWire.test.ts`;网页端测试侧:`run-bff-mcp-projection-test`、差分基线夹具;随升本版同窗换读)。`errorSupplementRoleOf` 对后两只句口的 `replacement` 声明随读口退出(它以读口函数本身为键):改读 `prepareRefusalNoteOf` 的宿主按未声明处理(`supplement`,机器行照旧在前)。
|
|
77
|
+
- **登记物到期收口**(**§131 LG-2**;不上公面,除上一条的六名):退役登记里到期的 19 行逐行处置 —— 六行按上一条执行退役;十一行(RL-171 · RL-184 · RL-185 · RL-220 – RL-226 · RL-290)消费端三树仍钉本包 0.100.0、读点未清 ⇒ 按「消费端删掉包装之后的下一个本包版本」续到 0.104.0(读点坐标与承接票写在登记行里,首次承诺窗留史、只追加);RL-227(引擎通知渲染器的不拉 `node:*` 出口)与 RL-251(停驻门卡词存量行过窗)前提未成立,未改窗,到期复核照旧挂着。
|
|
78
|
+
- **来源词表 `POSTURE_SOURCE_WORDS` 加 `lane`(四词 → 五词)**(**§131 PK-11**;🔴 公面值变):服务端 7.133.0 起部署旋钮与读面档位的来源多一词 `lane`(从隔离型执行车道 —— e2b / k8s / local-docker —— 派生的缺省值;类型包 28.0.0 `PostureSource` 与 spec 闭 enum 同序:`env` · `center` · `lane` · `posture` · `engine-default`)。读口本就按开集原样透传 `source`(修前读数上已能见到 `lane`),变的是这张优先序表:`lane` 落在 `center` 与 `posture` 之间;「运维表态过吗」判官 `postureSourceIsOperatorPinned('lane')` 答 `false`(只 `env` / `center` 算)。对这张表做长度 / 逐元素断言的端改断言。
|
|
79
|
+
|
|
80
|
+
### Added
|
|
81
|
+
|
|
82
|
+
- **MCP 授权失败记录读口 `readMcpAuthorization(row)` 与四处过境**(CC-1045;**§131 PK-1**;根入口运行期 +4〔读口 + `MCP_FAILURE_KINDS` / `MCP_AUTHORIZATION_REASONS` / `MCP_FAILURE_UNAUTHORIZED`〕,型 +2):引擎 7.59.0 起 MCP 端点答 401(或带 `insufficient_scope` 的 403)记为失败类 `unauthorized` + `authorization: { reason, authorizeUrl?, resourceMetadataUrl? }`(不再是 `http_status` + `httpStatus`)。读口三读数:`absent`(自有键不在)/ `unreadable`(在场而读不出:非记录、访问器、读抛、`reason` 不是非空串)/ `record`(只读自有数据位、开集键不透传、冻结)。过境四处:接线回执 `mcp[]` 行视图(`authorization` 或 never-false 位 `authorizationUnreadable: true`)· 引擎腿连接读口 `mcpEngineLegConnectionOf`(失败臂带同两位;原始行与行视图两种入参同答)· 重连回执 `status` 视图 · `-p` 机读输出 `mcp_status` 行的超集键 `_sema_engineLeg`(引擎腿读数的冻结拷贝:原始值位逐位拷,授权记录经同一只读口拷,记录 / 读不出 / 缺席三形与连接读口同答)。`authorizeUrl` 是部署座给的可信地址;`resourceMetadataUrl` 是端点自述、不可信,只供展示,绝不当跳转目标。
|
|
83
|
+
- **两只通知事实读器**(CC-1045;**§131 PK-2**;根入口运行期 +2):`readMcpAuthorizationRequired(notice)`(`mcp.authorization_required`:`server` / `reason` / `sessionId` / `runId` 必填,`authorizeUrl` 可选,主体名不进视图)· `readContextImageRemoved(notice)`(`context.image_removed`:摘掉的图张数 `images` 正整数 + 两只 id);两码挂进事实读器派发表。通知码册随引擎 100 → 106。
|
|
84
|
+
- **状态帧等待两位**(CC-1045;**§131 PK-3**;根入口运行期 +1〔`BRAIN_STATUS_WAIT_SEGMENTS`〕,型 +1):`sleptMs`(宿主挂起结束的那次重试等待,有限非负数;`0` 是合法读数)/ `waitSegment`(等首 token 的哪一段,开集原样;上游两词 `response_headers` / `first_token`)经 wire → 内部臂 → 重试状态两层白名单都到;坏形只丢自己(两位在帧上只认自有数据位,取值器不执行、读抛只丢那一位);座位格对 `sleptMs` 同一条「有限非负」(负数 / 非有限不合座)。
|
|
85
|
+
- **工具结果行改参记录 `_sema_rewrite` 与改参句**(CC-1045;**§131 PK-4**;根入口运行期 +2〔`toolInputRewriteOf` / `rewriteExtensionNamesOf`〕,型 +3;零新臂):引擎 `tool_end.rewrite`(`{ by: 作者[], input }`)原样上信封超集键 `_sema_rewrite`(作者按采纳序、`input` 原值;`input` 的容器层数上限与引擎冻结参数的界同为 256 层,引擎铸的记录恒在界内;`input` 缺席或读不出 —— 访问器、非纯数据、比这一界还深,只可能来自宿主自拼的帧 —— 只丢 `input`,作者与改参句照出);作者里含扩展(`kind: "extension"`)⇒ `modCardSentence` 出改参句「Arguments changed by {by} before the call was let through」/「参数在放行前被 {by} 改过」(扩展名按首次采纳序去重;只有策略 / 审批者改过 ⇒ 记录过境、零句)。这句话不据记录说「已运行」:引擎 7.59.0 起「放行后自拒」(`gate` 放行 ∧ `isError` ∧ `notExecuted`)可与改参记录并存,句子只说谁改了参数。代答格与改参记录同帧 ⇒ 代答句优先。消息目录 +1 键 `config.mods.rewrite.inputBy`。
|
|
86
|
+
- **门拒臂 `extension?`**(CC-1045;**§131 PK-6**):`denied` 门视图带拒这只调用的那张扩展注册的名(引擎在 `classic.PreToolUse` / `tool.check` 站拒时记下;在场 ⇔ 拒者是钩子且注册名已知)。
|
|
87
|
+
- **规则匹配读数 `tool` 一键 · 会话策略记录元键 `operatorRules`**(**§131 PK-6**):持久规则的匹配说明多「整个工具匹配」一形(消息目录 +1 键 `rules.match.tool`);会话策略记录的元键多运维规则一位(不当规则桶读)。
|
|
88
|
+
- **询问类 `write_protection_on_disk`**(**§131 PK-9**):成因句与强制词 `write_protection` 同句(词表来自引擎生成物)。
|
|
89
|
+
- **结构化卡类型 `bash_self_kill_refused`**(**§131 PK-6**):Bash 工具拒自杀式模式 kill 的卡类型进结构化卡白名单(工具错误自带句子,按任一条 Bash 错误渲染)。
|
|
90
|
+
- **求助无门通告的出路清单**(CC-1044 ①;**§131 PK-10**;根入口运行期 +1〔`askUnresolvableRemedyContent`〕,型 +1〔`AskUnresolvableRemedyView`〕;消息目录 +2 键):`readAskUnresolvable` 视图多可选位 `remedies`(`approver` / `permission_mode` + `value` / `disclosedOn`;kind 闭集取引擎生成表,集外 kind 与坏员只丢自己,读空不铸,读抛只省这一位);句口 `askUnresolvableRemedyContent(remedy, lang?)` 按 kind 一句(`permission_mode` 句点名模式词并说明每次放行都标在那次工具调用上;呈不呈由宿主按本部署允不允许那一档定)。
|
|
91
|
+
- **成员 git 凭据平面读口 `observedSandboxGitCredentialPlane(baseUrl?)`**(CC-1044 ⑧;**§131 PK-10**;根入口运行期 +1,型 +2):能力位 `credentialPlane.sandboxGit` 五态 —— 没观测 / 没报(服务端 < 7.137.0;不说成 `off`)/ 读不出(一行坏即整只读不出)/ `off` + 关因原词(开集)/ `on` + 逐 origin 行。
|
|
92
|
+
- **三只读数各多一位**(CC-1044 ④ ⑧ ⑨;**§131 PK-10**):决断拒收读数 `acceptableForm`(只在 `409 resume.constraint_rejected` 且体上有这一位时;值不判形、原样交出)· 设备车道读数 `relayUrl`(非空串才在)· `inheritEnvRefusalFromError` 读数 `reason`(只在机读位点名 `inheritEnv` 时读;开集原样,句子不按拒因分)。
|
|
93
|
+
- **规则编辑文本修剪口 `trimEditedRuleText(text)`**(CC-1044 ⑤;**§131 PK-10**;根入口运行期 +1):自己拼编辑体的宿主经它修剪(幂等;非串原样返回)。
|
|
94
|
+
- **计划审阅注入连线 `PlanReviewWire` 多可选位 `capsBaseUrl`**(CC-1044 ⑥;**§131 PK-10**;型面只增):与整族注入连线同一位(`PlanReviewWire` 现继承 `EngineWireInjection<PlanReviewWireClient>`),值是宿主 `kickEngineCapsProbe(baseUrl, …)` 用的那把地址;决断腿只在这把键上读 `planReviewCheckpointId`。0.94.0 删掉的同名位以这一形回来。
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
|
|
98
|
+
- **MCP 授权「在场读不出」不再在连接读口 / 重连视图上折成缺席**(CC-1045;**§131 PK-1**):同一行上的授权记录读不出时,两处都立 `authorizationUnreadable: true`,不把「引擎送了一份读不懂的」说成「没要授权」。
|
|
99
|
+
- **授权记录读口在已撤销的代理上不抛**(**§131 PK-1**):行本身或 `authorization` 位是已撤销的代理时,`readMcpAuthorization` 答 `unreadable`(修前形判在代理上抛,连接读口随之抛出)。
|
|
100
|
+
- **`mcp.authorization_required` 的 `authorizeUrl` 只认自有位**(**§131 PK-2**):原型链上的同名值不进视图(它是可信跳转地址,宿主自拼对象的继承值不能冒充部署座给的地址)。
|
|
101
|
+
- **两只确定性读面码不再给重试**(**§131 PK-10**):`approvals.read_corrupt` / `workflow.journal_incompatible` 落进失败呈现时与类型包重试器同判(不给原样重试)。
|
|
102
|
+
- **重试状态映射口每位读一次**(**§131 PK-3**):`waitSegment` 与 `providerCondition` / `providerConditionSource` 判形与落位读的是同一个值(修前判一次、落位再读一次)。
|
|
103
|
+
- **通告事实派发口 `readEngineNoticeFacts` 在已撤销的代理上不抛**(**§131 PK-2**):形判移进保护边界,与各只直读器对同一入参同答缺席(修前派发口抛 `TypeError`)。
|
|
104
|
+
- **读回的会话规则记录原样当 `prior` 交回不再抛**(**§131 PK-6**):服务端 7.135.0 起读回体带运维规则位 `operatorRules`;修前它被当成表外键,`tightenedSessionRules(prior, add)` 抛 `TypeError`(收紧后的规则写不回)。现按元键放过,写回体只带规则桶、不回送它。
|
|
105
|
+
- **持久规则匹配词 `tool` 有了说明句**(**§131 PK-6**):治理行「匹配形」一列对整工具规则出「whole-tool match (every call to the tool)」/「整个工具匹配(这个工具的每一次调用)」(修前落「a match form this build does not know」)。
|
|
106
|
+
- **决断拒收 409 的「行完整性」要求 `field` 真缺席**(**§131 PK-5**):`field` 在场而读不出(非串 / 空串 / 访问器,或机读袋读不出)不再当缺席,不据它判 `row_integrity`;值为 `undefined` 的自有键仍按缺席(类型包失败类在构造里把体上没有的位照样落成自有键)。
|
|
107
|
+
- **抹除证明 v2 读得出**(**§131 PK-10**;🔴 行为变,只对引擎 7.59.0 起的抹除可见):引擎 7.59.0 起抹除证明换 v2 信封(去掉每一处文件名身份 `slug`、残留表换成载体表;服务端 7.138.0 原样下发)。读口 `readMemoryEraseReceipt` 认 v1 / v2 两版,3 及以上照拒(`unsupported_version`)。修前 v2 一律判「版本不认得」:每一次成功抹除都落「收执读不懂」(会话抹除口 `receipt_unreadable`、抹除动词 `result_unreadable`),用户看到的是「没法确认抹了没有」。
|
|
108
|
+
- **v2 已抹除行的绑定不再读成 `null`**(**§131 PK-10**;🔴 型面):v2 的 bound 臂只带 `scope`,读成 `{ state: 'bound', scope }`(不编文件名身份;`slug` 在场则须非空串,原样带出);v1 的 bound 臂照旧要求 `slug`(普通 JSON 收执逐字照旧;只在原型链上的 `slug` 不再采信)。`MemoryErasedRow.binding` 的型由类型包的 `MemoryErasedBinding`(v1 形,`slug` 必选)改为本包读数型 `MemoryErasedBindingReading`(`slug` 可缺;由类型包型派生,退役登记 RL-311)。修前 v2 的每一条 bound 行读成 `null`(这一格读不出)。
|
|
109
|
+
- **抹除结果「部分」不再把残留记录说成条目没删**(**§131 PK-10**;🔴 行为变 + 型面,只对引擎 7.59.0 起的抹除可见):v2 收执的「部分」可以是条目全删了、只剩几类引用它们的存储记录没确认清掉(如引擎成文重放也清不掉的证据绑定行)。读口 `readMemoryEraseReceipt` 的读数多两位:`residuals`(残留载体表:八类逐类「删了几份 / 还剩几份」或「查不了」,加 `replay` / `propagation` 两词;v1 或表读不出 ⇒ `null`)与 `partialCause`(「部分」的成因三态:有条目没删成 / 条目已删只剩残留记录〔带类清单〕/ 判不出;「已抹除」⇒ `null`)。会话抹除结局按成因出三句:原句「some memory entries … were not erased yet」只给真有条目没删成的那一形;条目已删的那一形说「每一条都已抹除或早已不在,另有 N 类引用它们的存储记录没确认清掉,重发也未必清得掉」;判不出的那一形不说条目没删。修前一切「部分」都说条目还没删。
|
|
110
|
+
- **决断拒收分码判官的直接入口对机读袋只取一次**(**§131 PK-5**):不传协议名读数直接调 `decisionConflictOf` 时,协议名判型与拒体词位共用入口那一次袋读数(修前两处各读一次,随读变值的代理能让「行完整性」读成别的词)。
|
|
111
|
+
- **审批卡上「不再询问这个工具」的规则候选读得出**(**§131 PK-6**;🔴 行为变 + 🔴 型面):引擎 7.59.0 给没有规则文法的工具铸整工具候选(`match: "tool"`、`command` 为空串;服务端照放)。候选读口 `readRuleOffers` 的匹配词改判引擎的持久规则匹配词闭集(构建期生成表;类型包至 28.0.0 的候选匹配词表 `RULE_OFFER_MATCHES` 少 `tool`,是它的子集),`command` 空串合形(缺席 / 非串照丢)。`RuleOfferReading` single 臂与 batch `command` 成员的 `match` 型改为引擎闭集词(多 `tool`)。修前这一形整条丢掉,卡上那一格消失。
|
|
112
|
+
- **v1 呈卡投影读得出引擎卡词 `approvalCard`**(CC-981;**§131 PK-11**;🔴 行为变 + 型面加性):服务端 7.136.0 起 `approval_request` 帧的卡(活铸帧与断线重放帧同一份)带引擎卡词 `card.approvalCard`(与活卡帧顶层同一次读定;类型包 28.0.0 卡键锚第 23 员)。`approvalCardFactsOfV1(card)` 经与活卡帧腿同一把窄读 `readApprovalCardWord` 读它:引擎卡词原样上卡;表外词 / 大小写变体 / 非串 / 空串 / 访问器 / 只在原型链上 / 缺席 ⇒ 不长这一位(不编 `generic`)。`ApprovalCardV1Facts` 多可选位 `approvalCard`。修前 v1 腿恒缺,断线重连后从重放帧重建的卡落回通用卡;服务端 ≤ 7.135.x 的卡不带 ⇒ 照旧缺席。v1 卡上的「以后别问」本地整工具一行照旧不给(授予绑定那一步先答 `grant_binding`)。
|
|
113
|
+
|
|
114
|
+
### Gates
|
|
115
|
+
|
|
116
|
+
- **`scripts/run-core-7590-pick-projection-test.mjs`**(CC-1044 / CC-1045;**§131 PK-1 – PK-10**;包侧投影门):A 两只 MCP 闭集与已装引擎逐员同序 + 等待段词表 + 两只新码挂在导出读器上 · B 授权记录三态(含原型链、访问器、已撤销代理)· C 三处过境(行视图 / 连接读口两种入参 / 重连 `status`)· D / E 两只通知读器 · F 等待两位两层白名单 · G `remote-` 前缀律两腿 · H 询问类同句 · K 内核契约 5 + `classic.SubagentStart` · Z 引擎新增而本包不读的四名零代码读点(植入自证)。
|
|
117
|
+
- **`scripts/run-core-7590-pick-projection-test.mjs` 加段**:P 决断口 409 分码一次快照(计数代理:袋 / `field` / `reason` 各读一次;随读变值的两形反例;十四形静态回归表)· D6 / D7 派发口与直读器对已撤销代理同答 · F6 – F8 座位格 `sleptMs` 有限非负、第一层两位逐键受保护读 · W 改参参数深度与已装引擎的界对拍(引擎冻结投影各深度原样过境、比界还深只丢 `input`、重读同答)· R 越地板三帧丢弃词 · O `operatorRules` 当 `prior` 交回 / `tool` 匹配句。**`scripts/run-mcp-status-superset-keys-test.mjs` 加 MK7**(`_sema_engineLeg` 授权记录在场 / 读不出 / 缺席 / never-false / 互斥、结构位只经唯一读口;差分与拷贝两格加授权两形)。
|
|
118
|
+
- **扩门**:mods 面投影门 W-③b 段(改参记录七格 × 两出口、九种坏形、参数读不出只丢参数三形、代答同帧、铸点语法单点)· CC 形消息键普查门(`_sema_rewrite` 路由行)· 内核过境门 7.59.0 列(契约 5,站行 142 / 53)· 上游生成表门(四个新闭包组 + 第 21 批)· MCP 名判官两门(第五个成因词;独立生成池改 32 位乘法后全池被抽到)· 请求面 MCP 条目形门(嵌套位降级分组)· fleet 视图键门 · 重试状态 / 通知码册 / 纯函数门的员数与读器格 · 装配回归语料去掉退役键后同法重取摘要。
|
|
119
|
+
- **引擎真铸两形**(`scripts/run-core-7590-pick-projection-test.mjs` M 段):已装引擎的文件后端亲手铸一份抹除证明(v2)与它的重放,读口读成 present、bound 臂带 `scope`、先前抹除行照读;引擎亲手铸的三条整工具候选读成 single、下标原样;读口认的匹配词 ⊇ 引擎闭集全集。抹除收执门 R2b / R2c / R4h / R4i(v1 / v2 正例、3 及以上拒、bound 臂 `slug` 两版规则)· 会话抹除投影门 J5e · 抹除动词门 V5e · 「部分」成因:引擎真铸收执(条目全落位、载体半未清)与八类补齐的残留形(状态交已装引擎的判官算)读成「条目已删只剩残留记录」、会话句不说条目没删(M7 / M8)· 抹除收执门 R10(残留表八类两臂原样、十四种坏表 ⇒ 表 `null` 收执照读、`residuals` / `carriers` 访问器逐键隔离、成因矩阵十四形)· 会话抹除投影门 J5e – J5k(v2 全清 ⇒ 已抹除;仅载体残留 ⇒ 不说条目没删、带类数;v1「部分」⇒ 判不出;条目真没删成 ⇒ 原句;降级腿七类查不了 ⇒ 人决定)· 决断口 409 直接入口一次快照(P1d / P3d / P5:两答代理经直接入口只读一次袋、答行完整性) · 规则候选读口门 ⑨b 改为对引擎闭集双向全等、⑨b′ 整工具候选与空 `command` 正例 · 上游生成表第 22 批(`PERSISTED_RULE_MATCHES`)。
|
|
120
|
+
- **sdk 见证编译两代同过**(地板一代 23.1 / 24.0 与开发锚 28.0):比地板新的三臂改 switch 前类型守卫、事件腿帧名钉 / fleet 键元组钉 / 会话策略元键表各按代豁免一次(退役登记 RL-304 – RL-307,条件 = 支持底线 sdk 抬到 ≥ 26.1.0);sdk 钉文件 mods 组(`provenance` 领先类型包,末格反钉)与 request-field 组(不读三族登记成词串)改形。
|
|
121
|
+
- **登记物跟上游**:审批帧键门主腿与下一代探针腿同读(类型包 26.0.0 起锚删保读键);退役登记 `ruleSuggestions` 按退出条件删行(两锚都删了它),卡面账删 `persistedRuleShadowed`、补 `approvalCard`(卡入参早已带同名位)· 耐久卡键普查删 `ruleSuggestions` 四行 · 通知码册门 7.59.0 一代(一百零六员;六码受众 / 铸方对引擎包根、码册元组逐元素对拍;两只新读器进样本与夹具)· 耐久卡键普查补账(摘要位已读 `grantBinding`;停驻身份 / 授予清单 / 无裁定成因三位登记不投)· 透明键账加 `sessionMetaKey`(请求面未声明 ⇒ 两腿都不承运)· 询问类门「同句并掉的类」改按引擎句表推出(加钉被并掉的四只)。
|
|
122
|
+
- **`scripts/run-server-7137-pick-projection-test.mjs`**(CC-1044 ① – ⑥ ⑧ ⑨;**§131 PK-10**;包侧投影门):A 出路清单读口(生成表第 22 批与已装引擎逐员同序;坏员 / 集外 kind / 读抛 / 原型链)与两语句口 · B `invalid_session` 三处载体 / 分诊 / 不给重试 / 坏档句 / 结果帧补句(导入面 422 负控;`principal_not_a_name` 400 走既有 4xx 读法)· C 同步腿原样转口与类型包重试器对 `terminal` / `transient` / 缺席的发次 · D `acceptableForm` present-iff(值不判形;只在原型链上的继承位不采信)· E 修剪十三形、幂等、过引擎拼写判官、活卡编辑臂与预检口同经 · F 决断体门身份按能力位带(真假假假与没观测;去键重发照带;注入连线形按 `capsBaseUrl` 带、不给不带、门已换落「没生效」、立卡到答卡端到端)· H 能力位缺席 = `absent`、凭据平面五态、`relayUrl` · I `inheritEnv` 拒因(含值形被拒的真组合与失败呈现句)/ `mcpUnavailable` 过境 / 技能不带 `mods` · K 读数形对类型包 28 编译期对拍 · Z 不读的四名在源码零读点、修剪调用点恰两处。
|
|
123
|
+
- **扩门**(**§131 PK-10**):会话完整性门 A4c / A5d 的「别的码」由 `invalid_session` 改 `internal.error`(这一码已并进同一判定)· 引擎通告目录门 F3l 的出路清单格改为「逐条同值读出」(本版读这一清单)· 能力位台账 +10 行(本版三位 + 类型包 26 – 28 的七位,读点 / 零读点由台账门逐行核)· 上游生成表第 22 批(`APPROVAL_REMEDY_KINDS`)· 出句口语料 `cc1044` · 计划审阅注入连线门 W3h / W3j(`PlanReviewWire` 只经 `EngineWireInjection` 继承 `capsBaseUrl`;读它就抛的连线与整族同判不可用)· `inheritEnv` 门 IE4 / IE7 / IE9 与失败呈现门 IE-T2(请求带的不是 `"all"` 而机读位点名这一项 ⇒ 肯定读数与肯定句;肯定句新金样)。
|
|
124
|
+
- **登记物同批**:`scripts/registry.json` 棘轮 `portability.index` 391 → 395(四只设置契约闭包组新叶)、`typeshape.unknownExport` 565 → 573(八处全在生成物闭包组的注入形参型,照上游声明;各一条 ledger)· `docs/refactor/p1-scan/singleton-manifest.json` +16 条。
|
|
125
|
+
- **`scripts/run-pkg-policy-registration-test.mjs`**(CC-1092;包侧登记门;无行为面):本包 `package.json` 对跨包策略登记表里本包一行逐项相等 —— 依赖四类的包名集合(只比名字不比版本范围,多一个少一个都红并带差集)· `exports` 键集 · 登记的版本(等于 `version` 或 CHANGELOG 最高已发段,bump 前后两态都合法;两头都不等点名「政策未跟版」)· `description` 首句。登记表由 `SEMA_PKG_POLICY_PATH` 钉住时只看它(不回落),没钉自包根向上找相邻的兄弟检出;都不可达则整门 `SKIPPED-SECTION`、退出码 0、不算通过。负控套 +1 枚:给 `devDependencies` 多登一个包 ⇒ 依赖那一格红并点名多出的包。
|
|
126
|
+
|
|
127
|
+
- **登记物门读数**(**§131 LG-1 – LG-2**):CC 形消息键普查门过渡表 1 → 0 行(成功臂 `errors` 出表,旧名回来即 C1 违例);结果帧各门按臂取失败句(成功臂读 `result`、错误臂读 `errors[0]`)并钉成功臂不带 `errors`(判型门 PA11a、展示净化门 S4 / S9 / X30b、停驻真因门 P4 / P9、拦截句门 PB1b、路由门 RT4、纯函数门 055⑥′、坏档句门 B6 / A6 / A7、通知门 TN7、终局身份门 G1d、错配句门 D2);句表门 M-自证改读已装类型包的实际词表(不写死个数);退役登记 RL-179 · RL-192 – RL-196 在已退役栏、名字账判「名不在」根入口 / 构建产物 / 门脚本代码位置;角色声明门 ES1 十八只。
|
|
128
|
+
- **门跟上游读数重钉**(引擎 7.59.0 / 类型包 28.0.0;只换判据所依的上游事实,不放宽):让位披露门 L5b(类型包 26.0.0 起帧型不再声明 `persistedRuleShadowed`、声明继任键)· v1 卡投影门 V2 处置表按卡键锚逐元素(+`approvalCard` 落位;两只退役键移到锚外段 V2r,读法照钉)、V1 差分加卡词一行 · 7.126 提货门 C5 改钉「v1 卡经同一把窄读读卡词」· 旋钮 / 读面两门 F4 / F5 / A7 / G5 不再写死词数,读 spec 闭 enum 与包内词表逐词同序 · 人话轮门 HT10e 夹具写最小合法 PNG 头(引擎 7.59.0 准入的头部一步要签名后紧跟 IHDR),并用引擎自己的头部判官自证 · MCP 面板门 TC0 – TC2 改用拨号前仍判的撞名形(主体头名 = 引擎包根导出的 `MCP_ASSERTION_HEADER`;声明里的 `headers` 已退役)· 撞名门 NC0b 铸点改钉撞名模块的拒启口(全包恰一处;调用者恰挂载处与连通探针口)· 场景技能门 A8 正控换两只按类型包 28.0.0 真声明仍成立的形 · 会话策略两门 Y5a / S0 / E3 改读引擎改名后的覆盖判官 `isCoveringRuleName(name, behavior)` / `ruleNameCovers`;会话规则形门 E6 拆出 E6b —— 引擎 7.59.0 起对端段部分通配 `mcp__git*` 写口收、真门拦以 `mcp__git` 起头的工具,本包仍以 `wildcard` 扣下(落进 KL-890「引擎认、本包仍扣」那一格;尾分隔形与对端段铸不出的形写口照旧拒)· 子代模型词门的引擎目录夹具改为合形 Model(引擎 7.59.0 判目录行形)并自证 · 附件座位门 J4 夹具补零挂载的 mod 总线(引擎 7.59.0 附件读入口经它问 `@` 提及站)· 展示净化门两处直调投影的扁平历史帧注明回放面 · 裸句基线 +4(座位值形标签一句 + 抹除「部分」成因三句,各记一条账)。
|
|
129
|
+
- **runner 到点判词让过一轮事件循环**:单门上限 / 宽限到点的两只回调先让事件循环处理完已到达的门退出事件再判 —— runner 进程被饿住(高负载)时,宽限内已自行退出的门不再记「宽限内未退出 ⇒ SIGKILL」、上限前已退出的门不再记超时;真没退的门照旧先 SIGTERM、宽限到点 SIGKILL。中断安全门加 R11 / R12(本门进程把事件循环占住跨过宽限到点 / 上限到点)两格;R3 判词对而落定读数越过上限 + 宽限、且 runner 进程里的循环旁证记到盖住门退出时刻的空档(被饿住)时,同一组上限 / 宽限有界重跑一次,判据与界都不变。
|
|
130
|
+
|
|
131
|
+
### Known limitations
|
|
132
|
+
|
|
133
|
+
- `approval_complete`(开卡族的引擎侧消卡帧)本版只登记不消费:由 `approval_request` 开的卡不随它撤(与上一版同,修前落 `unknown_arm`)。
|
|
134
|
+
- 状态帧等待两位、工具结果改参记录、MCP 授权记录三处上游类型包尚未声明,本包按结构读(等待两位登记 RL-303;类型包补声明的那一批改类型面直读)。
|
|
135
|
+
- 卡上「整个工具」形的规则候选(`match: "tool"`、`command` 为空串)本版仍被候选读口丢掉:类型包(至 28.0.0)的候选匹配词表还没有这一词,读口按类型包的词表判;类型包声明这一形之后的下一个本包版本按它的形读。
|
|
136
|
+
- 状态帧等待两位、工具结果改参记录、MCP 授权记录、mod 行 `provenance` 四处上游类型包尚未声明,本包按结构读(登记 RL-303 / RL-308 / RL-309 / RL-310;类型包补声明的那一批改由类型面约束)。类型包(至 28.0.0)仍按 v1 声明抹除证明,v2 已抹除行的绑定读数型由本包派生(登记 RL-311)。
|
|
137
|
+
- 决断拒收的「那一行坏了」分码(`row_integrity`)在服务端 7.129.1 – 7.131.x 上永远给不出(这几版不把拒收体的 `reason` 过境),引擎 7.59.0 之前对 `bound_input_hash_missing` 那一形同样给不出:真坏行在这些组合上按一般拒收出句。支持底线升到服务端 ≥ 7.132.0 且引擎 ≥ 7.59.0 之后不再有这一形。
|
|
138
|
+
- `delegation.ask_unresolvable` 的机读出路清单 `remedies`(与句子同义的闭集重述)本版不读;句子照读。
|
|
139
|
+
- 待决列表行(耐久腿)上服务端新投的技能授予清单 `boundGrants` 与分类器无裁定成因 `classifierNoRuling` 本版不上卡(活卡帧腿照旧投;耐久腿的授予绑定三态 `grantBinding` 照旧读行上的摘要)。
|
|
140
|
+
- `400 request.field_invalid` 理由闭集新增的两族(`too_large` · URL 带凭据两词)本版帽读口 `fieldLimitRefusalFromError` 不读(答 `null`),服务端原句照常上屏(`inheritEnv` 四词由 `inheritEnv` 拒体读口读)。
|
|
141
|
+
- 服务端 7.137.0 随附的两件本版不读(§131a):接线回执的 `skills` 段与 `TaskResult.resultEntryIds`。
|
|
142
|
+
- 注入连线形的计划审阅腿只在宿主给了 `capsBaseUrl` 且那把键上的能力探测已落定时带 `checkpointId`:不给 / 没探 ⇒ 不带(没有「计划已变」保护,服务端按旧方式受理);`409 approval_stale` 拒体的 `currentPending` 本版不读,结局句不点名当前门。
|
|
143
|
+
- `invalid_session` 与 `corrupt_session` 共用一句坏档句(「保存的历史读不出 —— 存的日志已损坏」);要分「读不出」与「父链走不通」的宿主按码分。
|
|
144
|
+
- 出路清单里 `permission_mode` 那一句本包不判该不该呈:本部署禁了那一档时它会折回 `default`,而部署的这一层设置不在本包可见的读数里。
|
|
145
|
+
- 依赖服务端下一版的五项本版 pending(§131a):计划卡按发起调用联卡与滞留输入 id · 请求承运的 `classifyAllShell` · 规则写拒绝体逐条 `layer` · 历史读口的账行 · MCP 条目 `sessionMetaKey` 承运(今天的服务端请求面不收这把键;设置里写了它的用户本版看不到效果)。
|
|
146
|
+
- 停驻 ∧ 本流末行是模型正文那一形的 `-p` 停驻出路句(**§131 LG-1**;KL-1031):结果帧走成功臂、`result` 是那段正文,出路句原只在过渡键 `errors[0]` 上,本版删该键后这一形上没有承载键。可达性窄:引擎对停驻调用先铸工具行,末行通常是工具行,那一形走错误臂、出路句仍在 `errors[0]`;终端文本车道在成功臂上只读 `result`。落点未定(判官对停驻终局不走末行规则,或出路句改骑 `result` / `_sema_` 键)。
|
|
147
|
+
|
|
52
148
|
## 0.102.0(2026-10-28)
|
|
53
149
|
|
|
54
150
|
> 主题:0.102.0 会话送后台四读口归包(能力位读数 · 连线句柄与本包亲手开流 · 交接资格一只判官 · 交接动词与后台观看)接入文档 **§130 BG-1 / BG-2 / BG-3 / BG-4 / BG-5 / BG-6** · 会话级思考开关归包(状态机 + `reasoningEffort` 单铸点投影 + 座位动词 / 能力位 / 会话行位)接入文档 **§130 TL-1 / TL-2 / TL-3 / TL-4 / TL-5** · mods 三类用户面座位(注册卡 / 工具结果行旁拒句 / 代答句)与桌面装载座位的读口 / 句口 —— 零新臂、既有公面型零改动、`./mods` 子路径入口零改动;接入文档 **§130 MF-1 / MF-2 / MF-3 / MF-4 / MF-5 / DU-1 / DU-2 / DU-3 / PS-1 / PS-2 / PS-3 / PS-4**(DU / PS:配置地址展示口七臂、无方案 userinfo 与边界判据进通用网、展示口非串入参 · 配置地址路径段与 Slack webhook 锚定形、设置判官读同一只扫描、凭据面规则按版本的阶梯链) · 会话映射的引擎命名空间键含规范化路径(经中心中继的多台引擎同 origin 异路径不再串键)与出包文案卫生(两条出包串中性化、同形存量清理、卫生门词表扩形),接入文档 **§130 NK-1 / HY-1**。
|
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.
|
|
38
|
+
**Version:** 0.103.0
|
|
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
|
|
@@ -356,7 +356,7 @@ guard still cross-checks the table by name).
|
|
|
356
356
|
| `scripts/run-limits-env-failloud-test.mjs` | `SEMA_HEADLESS_*` env-lane limits reject invalid values as loudly as the flag lane (no silent "no budget" runs) The sentence about whether an attached engine honors an explicit limit flag (`limitsSupportNotice`) and the helper naming the explicitly given limit flags (`explicitLimitFlagNames`) are pinned here: no sentence when the capability probe was not observed or the version is at or above the support floor, a "may ignore" sentence below it, a "cannot be confirmed" sentence when no readable version was reported, and only the three limit flag names are ever echoed. |
|
|
357
357
|
| `scripts/run-streamjson-timing-honesty-test.mjs` | Stream timing & terminal honesty ([2084]): held errored fs-write results release on model progress; a wall-clock stop maps to `error_during_execution` with a truthful salvage note; the synthetic API-error assistant row carries the `<synthetic>` in-message sentinel. Also ([2489], core 5.8.0): the run-limit `errorCode` -> CC subtype map is pinned code by code (`limits.max_{cost,turns,tokens,walltime}_exceeded`), token/wall-clock stops keep the text the engine already produced, and the `failed` event arm shares the one mapping point. The 5.7 dual-vocabulary legs retired with server 6.0.0 (which bundles core 5.8.0); four **retirement negative controls** stand in their place — the retired `status:'timeout'` and the retired codes must fall to the honest fallback subtype and must never drop back to an empty success, so putting any of them back turns the gate red |
|
|
358
358
|
| `scripts/run-background-view-test.mjs` | `createBackgroundView` lifecycle: polling/notify pairing, per-source degrade (`501 → not-configured` vs `unavailable`), no capabilities probe of its own (whether the assistant face is configured is read only from that route's own `501`, the same arm as the fleet source; the view makes zero `/v1/capabilities` requests), and dispose really aborting the in-flight fleet snapshot (pure projection lives in the pure suite's W-A segment) |
|
|
359
|
-
| `scripts/run-fleet-view-keys-test.mjs` | The fleet projection views, **both directions**: `FleetTaskView`/`FleetWorkflowView` ⇄ their key lists (compile-pinned) ⇄ what a maximal/minimal row really projects, plus a wire-key coverage ledger (every `FleetTaskRow` key is either projected or carries a written reason why not) and a drift ledger against the shell's render contract. A one-directional assignability check is blind to optional keys — which is how `startedAt` was silently dropped Two keys
|
|
359
|
+
| `scripts/run-fleet-view-keys-test.mjs` | The fleet projection views, **both directions**: `FleetTaskView`/`FleetWorkflowView` ⇄ their key lists (compile-pinned) ⇄ what a maximal/minimal row really projects, plus a wire-key coverage ledger (every `FleetTaskRow` key is either projected or carries a written reason why not) and a drift ledger against the shell's render contract. A one-directional assignability check is blind to optional keys — which is how `startedAt` was silently dropped Two keys left the view in 0.95.0 — the queue-depth count on a task row (a phantom key no server ever sent; since 0.103.0 the SDK no longer declares it, so it is gone from the wire-key list too) and the run-level error code on a workflow row: whatever the input holds, the view has no such key. Since 0.103.0 the workflow row's `errorCode` and `parked` are declared wire keys recorded in the not-projected ledger, because both fold into the row's display status. Where the shell's render contract still declares them, the drift ledger lists exactly those two as a transitional entry that must equal the measured set, so the day the shell drops its declaration the entry is a zombie and the gate says so. |
|
|
360
360
|
| `scripts/run-usage-verbatim-channel-test.mjs` | The two complementary usage disciplines (core 3.0.0 metering semantics): the CC `ModelUsage` mirror stays pure (five pinned keys, `totalInputTokens` has no seat), while the sema-owned channel forwards the engine `turn_end.usage` object **verbatim** (six keys, incl. `totalInputTokens`) via `last_turn_usage.engineUsage` / `handle.latestEngineUsage` — honest absence on pre-3.0.0 engines, no fabricated zeros |
|
|
361
361
|
| `scripts/run-plan-review-decide-verify-test.mjs` | `decidePlanReview`'s post-decide honesty ([2315]/[2316], engine RB-471 family): a 2xx from the decide endpoint is **not** a terminal — the wire re-pulls the task status and words the outcome by the real shape (still-locked / legal new gate / genuinely left park / unverified), never claiming success it hasn't earned; when the engine answers that the session's stored resume context cannot be read, the outcome names the unreadable row and says the decision was not applied. Driven against a real fake-engine HTTP server through the shipped dist. The outcome queue item also carries a machine-readable `_sema_planReviewOutcome` (task id, a package-minted dispatch number, decision, effect) so a host can tell which in-flight decision an outcome belongs to without searching the prose; the prose is byte-identical, the number is minted only for a decision the in-flight latch admits, and a caller that passes no metadata gets no key. A plan-review card answered with free text and no option picked (or on the reject option with a note) is read as a rejection carrying that text as its reason, on both the first card and a reopened card; the reason is narrowed by the same step as an approval-denial reason (trimmed, blank dropped, capped at 4096 characters) and a note on the card wins over any reason the caller supplied. An approval with a note stays an approval and sends no note; an empty answer, a contradictory multi-select, several questions or an option outside the shown card stay dismissed; an answer without a note produces a request body byte-identical to before. |
|
|
362
362
|
| `scripts/run-shell-gate-durable-allow-test.mjs` | The durable approval leg for **shell** gates. The tool_end HOLD/REJECT predicate must cover Bash the same way park detection already does (otherwise the park poison frame `Operation aborted` hits the transcript, `endedCalls` swallows the real replayed result, and the user who pressed Yes watches a command that really ran be reported as aborted); a replayed, already-decided park must resume reading the stream instead of being reported as a failed turn; `lastEventId` must track numeric `seq` too. Mutation-proven: each of the three fixes reverted turns the gate red |
|
|
@@ -463,7 +463,7 @@ guard still cross-checks the table by name).
|
|
|
463
463
|
| `scripts/run-allow-rule-shadow-projection-test.mjs` | The reader for the fact that a standing allow layer matched a call but could not clear its ask (`readApprovalAllowRuleShadow`, `approvalAllowRuleShadowed`, and the structured `allowRuleShadow` disclosure stamped on the approval card). Servers send a list of members with their matched entries, and that list is the only thing read. Since 0.98.0 the single text that older servers and older parked rows sent is no longer read as a disclosure: a frame or row that carries only that older text has no disclosure and no sentence, while its presence still counts against automatic answers — the card paths record it as unreadable evidence and the automatic-answer check answers "not known" for it, also when a bare frame is handed straight to the check — so retiring the reading never lets a remembered rule answer an ask it could not answer before. The guard covers every member, several members in order, empty entry lists, the count of omitted entries, member names this build does not know, four kinds of malformed values (all of which still count as evidence), absence, the older text on both card paths and the parked-ask path through the real card port (including a row whose risk descriptor is inherited or comes from a getter), a check against the previous release that every older-shaped frame and row it treated as evidence is still not answered automatically, real frames and durable rows minted by the server fixtures when available, and the effect on every automatic lane. The one sentence a card shows for that fact is minted in one place (`allowRuleShadowSentence`): an absent disclosure renders nothing (it never says there is no rule), an unreadable one says so, and entries and member words arrive display-sanitised. |
|
|
464
464
|
| `scripts/run-engine-agent-absence-projection-test.mjs` | Absent background agents: when the engine stops reporting a background agent and no final state has arrived, the row is marked absent and this package owns every decision about it, so all clients agree. One predicate says whether a row is absent (the mark, not the status, decides). An absent row keeps its last known status, never counts as running, and is never counted as completed, failed or stopped; its elapsed time stops at the last moment it was seen, and its sentence says it may still be running. The end-of-turn sweep never settles an absent row (or a resident one). A row that comes back, or a real final state for the current cycle, clears the mark; a late final state from an earlier cycle does not. Absent rows are never removed at the short grace window. After the hard limit (30 minutes from the last time they were seen) the host is asked for the background-agent registry reading of each row: only a reading that the agent has ended or is not listed lets the row go, and each removal is returned as a fact the host must act on and announce; a reading of running, unknown, missing or unrecognised keeps the row and schedules nothing, so no standing poll is created. Until a registry reading is available every absent row stays. A row someone is viewing is held and reported separately only once the registry confirms it is gone. The row sentence, the removal sentence and the late-result sentence come from one place, never state an outcome or that the agent finished, and escape control characters in names, in the engine's removal word and in the late-result status. An end-to-end cell drives the real fleet projection and the real absence channel through every decision. From 0.84.0 the package also reads the registry itself: a reader lists the session's background registry only when the server advertises the listing, classifies its failures as unavailable (a failed read keeps the HTTP status and error code when the error carries them, and never invents either), and refuses a partly readable listing as a whole; a classifier turns the listing into the per-row reading, treating a registry status it cannot place as unknown and reading "not listed" only for keys shaped like registry handles and only when the host states the engine is a single process and names the row's session, because a key from another identity space proves nothing by being absent and, on a multi-replica deployment, a listing answered by another replica does not contain this session's agents at all (without that statement a missing row reads unknown and the row stays); and a predicate returns the agents the registry still counts as live that the host has no row for. A listing at the server's 500-row cap cannot show that an agent is gone either, so a missing row there reads unknown; the cap is checked against the engine's own list clamp and, when a server build is supplied, against the server's route. Each listing carries its session and a per-client sequence number, and a listing superseded by a later delivered read, or read for another session than the one the host names, counts for nothing. Only the exact listing object the reader returned can authorize removing a row or adding one: a spread copy, a structured clone, a filtered or a hand-built listing reads unknown and adds nothing, the listing, its row array and every row are frozen, the cap check uses the row count recorded when the page was read, and rewriting a listing's sequence number fools nothing. The fill predicate holds back agents first seen within the absence settle window — timed on one monotonic local clock from when this client's reader first saw the id, so a skew between the server's clock and this one, or reconnecting to a long-running agent, cannot skip the window — agents without a readable registration time and agents the host saw end since the read went out; the registry key of a row, progress or absence event is whichever of its two ids is shaped like a registry handle; and none of the reader, the classifier or the predicate throws. |
|
|
465
465
|
| `scripts/run-plan-review-dismissal-test.mjs` | An automatic reopen does not put back a plan-review card the user closed (the first-presentation path neither checks nor clears that record, so a replayed park frame still presents its card). A plan-review card the user dismissed (Esc, abort, or any answer that is not approve or reject) is recorded per session and run at the moment of dismissal, synchronously, before anything queued behind the card can be released; a reopen marked `trigger: 'automatic'` then refuses with `{ reopened: false, dismissedByUser: true }` instead of minting a new card the user's next keystroke would land on, while the user's own next action (`trigger: 'user'`) reopens it and clears the record. The record is keyed by gate instance when the host supplies an instance reader: a new plan gate on the same run is still surfaced, and anything that cannot prove the gate is new (no reader, a failed, empty, thrown or timed-out read) refuses on the conservative side. The asynchronous form re-checks after its reads and before minting — a decision handed over meanwhile (seen by the package, or reported by the host's optional hand-over predicate) answers as "your answer is on its way"; a record that changed meanwhile makes the stale evaluation mint nothing and answer from the current record: another close refuses as the user's close and keeps the newer record, a card already back on screen (the user's own action or a concurrent automatic reopen, waited for within the receipt window and re-read once the wait is over) answers `reopened: true`, and a record that is gone (session change, ledger overflow) answers a plain refusal without `dismissedByUser`; a hand-over predicate that throws refuses with a plain `{ reopened: false }`. Each run has at most one reopen on its way: a reopen that arrives while an earlier one's card is published but not yet settled joins it instead of minting a second card and retiring the first card's answer path. Instance readers are snapshotted when they resolve, so a host that hands over its own live set still gets a new gate recognised; and a decisive-looking host answer note does not clear the record for the very card the package's own responder already judged non-decisive (the label was not on that card). A successful reopen replaces only the record taken before the card was minted (with an on-screen marker, not a deletion), a decisive answer clears it, the per-session ledger is bounded, and a session change clears its bucket. Without `trigger` the reopen answers exactly as before, apart from joining a reopen already on its way. A reopen for a session with no view subscribed to question frames (`onQuestionFrameFor(sessionKey, handler)`; `onQuestionFrame` for the default session) refuses with `{ reopened: false, _sema_noPresentationSurface: true }` — in the synchronous and the receipt form alike, per session key, and also when the view goes away while the asynchronous check is reading — and that answer comes before the user-closed check, at the entry and after the asynchronous read alike, whether or not the read proved a newer gate (after the read, a decision handed over while the read was in progress, and a dismissal record that was replaced or cleared meanwhile, still take precedence over the missing view); a host log or probe port that throws changes none of the reopen answers (the suite runs the same arrangement with a quiet and with a throwing log port and requires the same answer and the same card frames); every other refusal (receipt window lapsed, decision in flight, user-closed card, non-default slot without a delivery path, record gone) keeps its own keys without the flag. The first-presentation call does not check for a view: without one it still answers `true` and the card frame goes nowhere, which the suite records as today's behaviour, not as a guarantee. A free-text answer on the plan card (no option picked, a non-blank note) counts as a decisive answer: it clears the record and delivers exactly one rejection; a blank note, or a contradictory multi-select that carries a note, does not. |
|
|
466
|
-
| `scripts/run-plan-review-injected-wire-test.mjs` | The plan-review orchestration accepts a host-supplied engine client, so a browser host behind a same-origin relay — which cannot install a token-bearing engine target — runs the package's own decision path instead of rebuilding it. With a client injected, the decision, its in-flight latch, the resend-once-without-the-key handling of a `request.field_conflict` refusal, the post-decide status re-pull, the six-state effect classification and the outcome text are byte-for-byte what the installed-target path produces, proven against a real relay-form SDK client and a fake engine while the installed target points at a different fake engine that must receive nothing. The three-choice card depends only on the host's declaration
|
|
466
|
+
| `scripts/run-plan-review-injected-wire-test.mjs` | The plan-review orchestration accepts a host-supplied engine client, so a browser host behind a same-origin relay — which cannot install a token-bearing engine target — runs the package's own decision path instead of rebuilding it. With a client injected, the decision, its in-flight latch, the resend-once-without-the-key handling of a `request.field_conflict` refusal, the post-decide status re-pull, the six-state effect classification and the outcome text are byte-for-byte what the installed-target path produces, proven against a real relay-form SDK client and a fake engine while the installed target points at a different fake engine that must receive nothing. The three-choice card depends only on the host's declaration; since 0.103.0 the connection's optional `capsBaseUrl` is the same capability-evidence key every injected connection carries, read only to decide whether a decision carries the gate identity, and a connection whose `capsBaseUrl` cannot be read is unusable like any other injected connection (no card, nothing sent); every request of the relay-form client leaves without an `authorization` header, checked beside a token-bearing client on the same spy so the absence is not the spy's blindness; and a planted token never reaches a log line, an outcome sentence, a queue item or the host callback on any of the failure paths. A decision may carry a `reason` (trimmed, dropped when blank, capped at the server's limit), an `onOutcome` callback hands the outcome back to hosts that have no model-prompt queue (called once per admitted decision, never for a latched duplicate, and its own failure never affects delivery), a reopen with an injected client no longer needs a host delivery function on a non-default session, and the two capability probes take the same injected client with a bounded wait. A decision that the injected client's own time limit cuts off is reported as sent without an answer within the time limit (it may have taken effect), in the same sentence the installed-target path uses when its limit is reached, while a connection that cannot be made is still reported as unreachable and one that drops after the decision went out is reported as possibly applied (the same no-answer judgement the background-agent verbs use); a client built with the documented decision budget answers a slow approval exactly as the installed target does, and a client whose namespaces are callable functions is accepted as before. The package's own reads through an injected client — the two probes and the post-decide re-pull — settle at their deadlines even while the client sleeps through a retry back-off, and abort the request underneath; a malformed injected connection is reported as not sent, never thrown. |
|
|
467
467
|
| `scripts/run-subagent-injected-wire-test.mjs` | The background-agent verbs — the child report read, the live tail, the task-handle output read and stop, steer, the resume assembly, manual compaction with its capability warm-up, and the delegated-prompt read — accept a host-supplied engine client, and the plan-review orchestration now resolves its client through the same single construction point, so a browser host behind a same-origin relay runs every one of these paths without an installed engine target. With a client injected, each entry sends only through it: proven against a real relay-form SDK client and a fake engine while the installed target (default and keyed slots alike) points at a different fake engine that must receive nothing, with the row's own session parameter carried, no `authorization` header on any request (checked beside a token-bearing client on the same spy), and a planted token never reaching a log line, a return value or a failure detail on the injected, installed-target and unreachable paths. The capability evidence behind the task-handle verbs and the row stop gate is read only under the key the host names, never from the installed target; the report, tail and compaction warm-up cache their own probe under that key and re-probe when it is absent. A malformed injected client or connection lands on each entry's existing cannot-send outcome (`null`, `no-wire`, `unavailable`, `offline`, `unreadable`) with zero requests, never a throw or an unhandled rejection. Every request through an injected client settles at the package's own deadline even while the client sleeps through a retry back-off and aborts the request underneath; the caller's own signal still applies, and the old signatures answer as before apart from the no-answer outcomes described next. A steer, resume or stop that may have reached the engine but got no answer — the package's own deadline on an injected client, the client's per-request limit on either path, or a transport failure that cannot be shown to have happened before anything was sent (the connection dropped after the request went out) — is reported with a machine-readable `unconfirmed: true` beside the unchanged `reason`, so a host can say it may have taken effect instead of calling it a failure; a cancellation by the caller after the request went out is reported the same way (only the wait was cancelled), while a real 4xx or 5xx answer, a connection that could not be made at all, a verb that threw before returning a promise, and a cancellation already in place before the call (nothing is sent) carry no such key. An installed target is copied by value when a call resolves it, so a delayed or retried compaction still goes to the engine and credentials it was resolved against even if the host's target object changes meanwhile, and a verb that throws synchronously is classified exactly like one that rejects. The resume failure classifier that hosts reuse for their own direct calls makes the same judgement from the same single source, so every client renders it the same way. A successful sub-agent steer carries the server's acceptance id (`messageId`) only when the receipt holds a non-empty string; older servers leave it out. |
|
|
468
468
|
| `scripts/run-gate-interrupt-safety-test.mjs` | The two safety properties of running the suites themselves. The collecting runner no longer kills a suite outright when its time limit expires: it sends a termination signal first, waits a grace period for the suite to clean up, and only then kills it — and it records the suite as timed out however it exits, so a suite that exits cleanly after the signal is still not counted as passing. The limit and the grace period can be widened for a single suite in `gates-manifest.json` (an optional entry with a written reason; a malformed entry, including one with a misspelled field, stops the runner before any suite starts instead of silently falling back to the default, and an entry filed under a misspelled name is reported by this guard rather than ignored), and the negative-control suite is widened there. Every property is exercised on byte-for-byte copies of the real runner and the real negative-control suite in a throwaway directory: a suite that honours the signal finishes within the grace period, one that ignores it is killed when the grace period ends, and the summary lines are unchanged; once a suite has exited the runner waits at most a short drain window for its output pipes, so a child process that inherited them and outlives the suite neither turns a passing suite into a timeout nor holds the runner past the limit, the grace period and that window; the negative-control suite, interrupted in the middle of a rehearsal by any of the three signals or by the runner's own time limit, restores the file byte-for-byte, leaves no backup behind, stops the rehearsed guard together with anything it started, regenerates the build output (checked on a small project in the throwaway directory), and exits with 128 plus the signal number; a rebuild that would overrun the grace period is cut short and its compiler stopped; a backup left behind by an earlier run — next to a later target, loose in the source tree, or inside a symlinked dependency directory — makes it refuse to start without touching anything, naming the file and how to restore it. |
|
|
469
469
|
| `scripts/run-system-reminder-open-tag-test.mjs` | The opening-tag locator for the engine's `<system-reminder>` envelope, for hosts that split a message into envelopes and body text themselves rather than only stripping or unwrapping it. `findSystemReminderOpenTag(text, from?)` returns the start and end of the next opening tag at or after `from` (UTF-16 indices, `end` one past the tag) or `null`, and it recognises exactly the two shapes the engine mints — a bare tag, or a tag with a single `mark` attribute whose value is 22 base64url characters — through the very same matcher the strip and unwrap entry points use, so there is no second grammar to drift. The guard pins both engine shapes to the exact index, refuses the non-engine shapes listed in the integration guide plus near relatives (and does not let them swallow a real tag that follows), refuses an opening tag truncated at the end of the text, answers `null` without throwing for a non-string text and for a `from` outside the integer range 0..length, and shows that the locator ignores block context (a tag inside a block body, an unclosed tag and a nested inner tag are all located — pairing with a close is the caller's loop, as in the strip entry point). On twenty thousand seeded random strings mixing both shapes, truncations, near relatives and nesting, the set of tags the locator finds equals the set derived purely from the observable answers of the strip and unwrap entry points, and a strip and an unwrap rebuilt on the locator agree with the real ones byte for byte. Two timing cells show a single call over many near-miss tags and a full walk with `from` moving forward both stay linear |
|
|
@@ -475,7 +475,7 @@ guard still cross-checks the table by name).
|
|
|
475
475
|
| `scripts/run-plan-review-decision-ledger-test.mjs` | The plan-review reopen path refuses on one decision ledger shared by every delivery path, not only the package's own POST window: a decision the host reports as handed over (before the card's answer reaches the package, or on the host's own delivery path) counts as in flight until it settles; a pending-row read that started before a decision settled is a stale snapshot of the gate just answered, so a reopen carrying that read mark refuses; and a decision proven not to have taken effect (nothing sent, a refusal that by contract changed nothing, or the engine proven to still hold the very same gate instance — a status alone does not prove it, since a run that moved on to a new plan gate reports the same status) neither counts as in flight nor makes such a snapshot stale, so a failed decision does not consume a legitimate reopen. The ledger's capacity bound never evicts the package's own in-flight decisions, so a duplicate approval stays latched however many decisions are in flight. The package's own in-flight window now runs from the POST to the moment the outcome is emitted (settlement happens before the outcome is queued, so a read the host starts from the queue port is not stale), while the duplicate-delivery latch keeps its POST-only window. A handed-over decision the package's delivery path then sends is the same ledger entry (the host's early settle does not release it); two decisions on one run each settle on their own; positive evidence that the run left the gate settles what is open without releasing the latch; bad inputs neither throw nor record. The ledger is checked against the terminal's current implementation vector by vector when that tree is on disk. Positive evidence that the run left the gate can arrive after the host has handed a decision over and before the package's delivery path picks it up (while the host is still waiting on its gate snapshot, or in the microtasks between that wait ending and the delivery call); the delivery path then still picks up that same entry instead of minting a new one, so the latest decision mark the host keyed its snapshot and its not-applied notice on does not move, the duplicate-delivery latch and the capacity rule hold for it, and the three failure outcomes read byte for byte as they would without the hand-over. Only an entry settled by such evidence is picked up again: one the host settled itself, one it revoked, and one that already produced an outcome are not, and a new decision gets a new mark |
|
|
476
476
|
| `scripts/run-session-background-stop-test.mjs` | The session-level stop for background work (`stopEngineSessionBackground`): one call asks the engine to stop the background tasks of a session, with `includeRetained` passed through as the required true / false choice. It resolves its client through the same single construction point as the other engine verbs (a host-supplied client, or the installed engine target for the chosen session slot) and sends nothing unless the engine has declared the stop face (`background.exitFaces` strictly `true`) under the capability key that applies: evidence that is missing or unread, an older engine without the face, a malformed flag, a flag found only on the prototype chain, or evidence recorded for a different deployment all end in `unavailable` with zero requests. The request body on the wire is exactly `{"includeRetained": <boolean>}` whatever object the caller passes. A 200 answer returns the receipts verbatim (identifier and outcome word; a row whose word it does not recognise is kept with that word as it is, so the host can still name it and the companion below sorts it as may still be running), counts rows whose identifier or word it cannot read instead of inventing them, and leaves the receipt list absent rather than empty when the body cannot be read. Refusals are sorted by machine code before HTTP status (missing service credential, no ownership face, unknown session versus missing route on the same 404, request shape, not permitted, rate limited with the server's wait hint, anything else), a server failure is an `error`, and each call sends exactly one request even through a client configured to retry. A request that may have reached the engine but got no answer — a time limit, a connection that dropped after the request went out, or a cancellation by the caller after the request went out — carries `unconfirmed: true`, while a real answer, a connection that never opened, or a cancellation already in place before the call (nothing is sent) does not. Malformed arguments, options, connections, clients, capability records, answer bodies and error objects never throw and never leave an unhandled rejection, and a planted token never reaches a log line or a result. A pure companion (`engineSessionBackgroundReceiptReadingOf`, with the frozen state list `ENGINE_SESSION_BACKGROUND_RECEIPT_STATES` derived from its wording table) sorts each receipt word into stopped, still running (kept on purpose) or may still be running, with one fixed sentence per state so every client says the same thing: each of the four words lands in its state, while any word it does not recognise — a future word, a different letter case, stray whitespace, a near spelling, a prototype-chain name — lands in may still be running with the word carried back verbatim, and non-string input (boxed strings and objects with their own `toString` included) lands there too without being coerced and without throwing; it never reports stopped for anything it cannot confirm. The three sentences differ, the two that are not stopped never use the word stop, and the state list and the states actually produced match in both directions. |
|
|
477
477
|
| `scripts/run-session-integrity-refusal-test.mjs` | Three refusals a session can meet on newer servers, read the same way on every client. When a session's saved history cannot be read, the server answers with one code whether the refusal arrives as an HTTP error, as the failure recorded at the end of a streamed run, or on the background run's record; one predicate decides it for all three carriers, it keys on the code alone — never on the status or on the engine's wording — and one sentence explains it: the history is damaged, retrying will not help, whoever operates the engine has to repair it, and meanwhile a new session works. The package's own end-of-run error line and the error of the result frame both carry that sentence, identically, and nothing changes for any other code. When a delete is refused because background agents the session started are still running somewhere this server cannot stop them, the refusal is read with the ids it names — each id checked on its own, a bad entry dropped rather than invented, and a list with no usable entry reported as absent rather than as an empty list, which would read as "no agents left"; a refusal because a run is still in progress is read with that run's id, and any other conflict falls back to a sentence that does not guess. When a decision reaches an approval that moved in the meantime (stopped, decided elsewhere, parked again, claimed by another decision, or — newly — belonging to a session that was deleted), the package reads the code rather than the error class, says the decision was not applied and that the pending approvals should be fetched again, and the approval legs treat it as "the approval is no longer where it was" and keep reading the run, instead of letting the wording of the server's sentence decide. When the server package is supplied, the guard drives the server's own code for each of these answers and pushes the result through the SDK's error mapping before the package reads it. |
|
|
478
|
-
| `scripts/run-inherit-env-wire-test.mjs` | The request field that lets the model-driven shell inherit this machine's whole environment (`"all"`) or keep the default scrubbed environment (`"scrub"`). Both words go out exactly as given on the two user lanes, an absent value is never filled in, and any other value (including a list of variable names) is refused before anything is sent. The value reaches a request only through a helper that checks the engine's version: a server whose version cannot be read gets nothing, and the caller receives the reason plus one sentence saying what the run's shell gets instead, including that leaving the field out also clears an earlier whole-environment choice on engines that know it; from 0.92.0 a readable version always gets the field (a server below the support floor refuses the request loudly rather than being skipped quietly). An invalid-field refusal of a request that asked for `"all"` is read by code with one conditionally worded sentence, because the same code has other causes. From 0.101.0 the reader first looks at the machine-readable field position of the refusal: when it names another field the sentence is left out, when it names this field the sentence is stated plainly instead of conditionally, and when the refusal carries no field position the conditional sentence is unchanged. |
|
|
478
|
+
| `scripts/run-inherit-env-wire-test.mjs` | The request field that lets the model-driven shell inherit this machine's whole environment (`"all"`) or keep the default scrubbed environment (`"scrub"`). Both words go out exactly as given on the two user lanes, an absent value is never filled in, and any other value (including a list of variable names) is refused before anything is sent. The value reaches a request only through a helper that checks the engine's version: a server whose version cannot be read gets nothing, and the caller receives the reason plus one sentence saying what the run's shell gets instead, including that leaving the field out also clears an earlier whole-environment choice on engines that know it; from 0.92.0 a readable version always gets the field (a server below the support floor refuses the request loudly rather than being skipped quietly). An invalid-field refusal of a request that asked for `"all"` is read by code with one conditionally worded sentence, because the same code has other causes. From 0.101.0 the reader first looks at the machine-readable field position of the refusal: when it names another field the sentence is left out, when it names this field the sentence is stated plainly instead of conditionally, and when the refusal carries no field position the conditional sentence is unchanged. From 0.103.0 a request that carried the field with any other value is read the same way when the refusal names this field (value refusals are named too), the plainly stated sentence says which values the engine accepts rather than claiming the request asked for the whole environment, and a refusal without a field position is still attributed only to `"all"`. |
|
|
479
479
|
| `scripts/run-disable-skills-wire-test.mjs` | The request field that turns off every skill for one request (the deployment's skills, skills the client sends and skills listed on agent definitions). It is carried on the two user lanes only as the literal true; false or an absent value sends nothing, and any other value is refused before anything is sent. A request that also carries a non-empty skill list, or an agent definition with skills, is refused by name both when it is built and again after agent definitions are added later, because the engine rejects that combination. The value reaches a request only through a helper that reads the engine's capability report: when the engine has not reported the capability, reports it as unavailable, has not been read yet, or reports it in a form that cannot be read, nothing is sent (an engine that does not know the field rejects the whole request) and the caller receives the reason plus one sentence saying skills stay on for this run. Requests that do not use the field are byte-identical to the release before it was introduced, apart from images on the one-shot lane, which gained a seat in a later release and are checked by the request-receipt and human-submission guards instead. |
|
|
480
480
|
| `scripts/run-engine-caps-settled-within-test.mjs` | The bounded wait for the engine's capability report. `engineCapsSettled` takes an optional `withinMs` and answers whether the wait ended because the probe settled or because the time ran out; without `withinMs` it behaves exactly as before. The bounded form creates a timer only when a probe is actually in flight, clears it on every path, never rejects, treats an unusable budget (zero, negative, not a finite number, a malformed options value) as no waiting rather than waiting forever, clamps an oversized budget to the platform maximum, and counts the budget once per call even if the engine is replaced during the wait. `disableSkillsDeclarationSettled` waits within a bound for the report and then answers exactly as the synchronous `disableSkillsDeclaration` does, so when the probe was started by the host, lands in time and reports the capability as available, the very first request can turn skills off, and in every other case (probe too slow, failed, never started, capability not reported or reported as unavailable) the caller gets the same answer the synchronous mouth gives. It never starts a probe itself. Timing cells run on an injected clock, and a real-timer pair checks that no timer handle is left behind. |
|
|
481
481
|
| `scripts/run-mandated-card-values-test.mjs` | Approval cards that newer servers mark as mandatory for four kinds of question (a deployment command policy, an operator's never-auto list, an exhausted durable budget, and supervisor routing) are built with the server's own code and fed through both card paths: the card carries the mandatory mark and the matching reason word, the shared check reports it as mandatory, no mandate word is invented, and a session-wide allow that the server declines to remember produces the single not-remembered notice. An ordinary approval-list card stays non-mandatory and remembered, and the older card shapes are shown to read the other way. This check needs an installed server package to run and reports itself as skipped otherwise. |
|
|
@@ -489,7 +489,7 @@ guard still cross-checks the table by name).
|
|
|
489
489
|
| `scripts/run-support-floor-projection-test.mjs` | The package's machine-readable support floor: the oldest server, engine and SDK versions it still supports, kept in `scripts/support-floor.json` with the source of each value and exported at runtime as `SUPPORT_FLOOR` (with `supportFloorOf` and the engine version reading `engineVersionTier`). Since 0.95.0 the constant is not a hand-kept copy of the declaration but its build-time product: a generator writes one comment-free, import-free file from the declaration, and the check fails when the checked-in file differs from a fresh generation, carries a comment, when the runtime constant is not that very object, or when the source holds a literal version string; it proves itself against an unfaithful generator (a dropped key, a changed key order, a stale file, an injected comment, an orphan or missing file) and against twelve malformed declarations. The check also fails when the declaration cannot be read or is malformed, when the exported values differ from it, when the SDK value differs from the SDK peer range, and (when the full fixture set is required) when no server fixture in the list matches the declared server version or that server pins and installs a different engine than declared; every fixture in the list is printed with whether it sits below, at or above the floor. The version reading answers engine at and above the floor, legacy below it and unknown for anything that is not a plain release version (pre-releases, build metadata, a leading v, whitespace, wrong segment counts, leading zeros, the word unknown, non-strings); a caller-supplied threshold can only raise the floor, a malformed one is refused before any version is read, and hostile inputs never throw. The same reading exists for the version of the engine install's core package (`coreVersionTier`): the same parser, the same three answers and the same result type, differing only in where the lower bound comes from (the declared engine floor rather than the declared server floor); the check compares the two readings on one pool of inputs, pins the golden cases, and fails when either reading carries its own version comparison instead of calling the one shared function. Since 0.93.0 the check also pins that exactly one function in the whole source tree reads a version string (a planted version-shaped regular expression or split-and-parse is detected by the same scan); the per-feature version checks that used to carry their own thresholds — the limits and detach checks, the goal stop-hook tier, the plan-review three-choice tier and the inherited-environment server tier — no longer exist. Since 0.96.0 the check also covers the effective threshold read: the one value the engine version reading actually applies — the declared server floor or the caller's own floor, whichever is higher — is exposed as a single read, so a message that names the threshold prints the very version the check used. It pins that the read gives the same answer as the check on a pool of floors (the answer is exactly the lowest version the check lets through, including across segment boundaries), that a malformed caller floor is refused identically by both, that both come from one shared function whose body is a single delegation, that a version segment above 2^53 − 1 is treated as unreadable (a floor with one is refused, a version string with one reads as unknown) so the printed threshold and the admitted minimum cannot disagree, and that the generated declaration object is not part of the public surface. Since 0.98.0 the check also pins that the two outward copies of the floor — the README support-floor line and the support-floor row of the integration guide's version table — carry exactly the declared server, engine and SDK versions, so raising the floor in one place and not the others fails. Since 0.101.0 the check also covers a pure version comparison (`compareReleaseVersions`): two plain release versions compare as lower, equal or higher, and anything that is not a plain release version on either side — a pre-release or build suffix, a leading v, whitespace, leading zeros, a wrong segment count, a segment above 2^53 − 1, a non-string, an object that merely converts to one — reads as undefined, never as equal. It compares the answers with an independently written reference over a pool of versions; pins that the effective threshold read is the higher of the caller's floor and the declared floor by this very comparison, and that the three-way answers of the two version readings are the translation of this comparison against that threshold; proves itself against eight unfaithful comparisons (suffix stripped, string order, unreadable folded into equal, throwing on unreadable, accepting a leading v, converting non-strings, unbounded segments, leading zeros); and pins that the comparison only calls the shared read and compare helpers with no comparison of its own, and that no other function in the source tree calls those two helpers. |
|
|
490
490
|
| `scripts/run-server-7113-fixture-test.mjs` | Adoption checks against the published server package, run once per server generation (the one that carries the change and the one just before it). Session reads, live steer and policy settlement are driven through the package's real routes and modules; the attachment checks read the package's shipped source text instead. Attachments: the keys the server's shipped shape description lists are exactly the keys this package knows, the server's shipped refusal for the retired plan-mode reminder key names its retirement, every value this package's attachment switch can produce stays inside the accepted set, and naming the retired key is refused locally instead of being sent. Session reads: a non-owner reading a session's detail, head or event stream gets a not-found whose code names the session (the previous generation named a run), and this package's session read answers the same way on both. Live steer: without an idempotency key the engine's input id equals the message id on the receipt, a queued frame and an applied frame on one input id each project as their own event with every field as written, and the delivery ledger records delivery once. Policy settlement: an unattended answer by class is recorded under the policy party as an allow settled by policy, read back verbatim, no longer read as a person's approval, and a tool-end frame carrying it still projects. |
|
|
491
491
|
| `scripts/run-read-deny-tiers-test.mjs` | The check for the built-in read-deny tier lists and for the validator of the deployment key's comma-separated value. The nine sample inputs agreed with the terminal are pinned (an empty input means removing the key and never a stored empty string; `none` is the explicit empty posture and must stand alone; whitespace around entries is trimmed with the same rule the server uses; an empty entry and an unknown or mis-cased tier are refused, while a tier listed twice is accepted and kept as written, exactly as the server reads it), the remaining shapes are covered (Unicode whitespace, separators other than commas, zero-width characters, every tier alone and all of them in either order), a non-string input never throws and a result never carries an empty string as its value, and the explanation sentence is one line, free of internal wording, and shows a user-supplied value only after credential masking, control-character escaping and a length cap (a two-million-character entry is neither echoed nor slow). The validator is also run against a fake tier table: adding a tier makes it accepted, removing one makes it refused, and the source holds no tier name, so the generated table is the only source of tiers. There is no comparison against the server because the server package offers no callable parser for this value. |
|
|
492
|
-
| `scripts/run-hook-matcher-verdict-test.mjs` | The hook-matcher admission verdict `hookMatcherVerdict(event, matcher)` against the published server package's real task admission: for 38 matcher shapes on each tool event, a `refused` verdict (the matcher selects a tool alias but not that alias's canonical name) matches a 400 from the server, and `accepted` / `matchesAll` match an admitted request; from server 7.115.0 the refusal's machine-readable `detail` (event, alias, canonical) must equal the verdict's pair. Shapes the verdict does not judge are listed with their reason and are never treated as accepted. The guard also pins that the verdict reads the generated alias table (adding a pair to a copy of the table changes the copy's verdict), that only the three tool events are judged, that the verdict is case-sensitive and never throws on non-string input, and that pathological user regexes return within a bounded time (each call runs in a worker with a deadline; the same regex run directly against the longest tool name does not finish). After the fact, `
|
|
492
|
+
| `scripts/run-hook-matcher-verdict-test.mjs` | The hook-matcher admission verdict `hookMatcherVerdict(event, matcher)` against the published server package's real task admission: for 38 matcher shapes on each tool event, a `refused` verdict (the matcher selects a tool alias but not that alias's canonical name) matches a 400 from the server, and `accepted` / `matchesAll` match an admitted request; from server 7.115.0 the refusal's machine-readable `detail` (event, alias, canonical) must equal the verdict's pair. Shapes the verdict does not judge are listed with their reason and are never treated as accepted. The guard also pins that the verdict reads the generated alias table (adding a pair to a copy of the table changes the copy's verdict), that only the three tool events are judged, that the verdict is case-sensitive and never throws on non-string input, and that pathological user regexes return within a bounded time (each call runs in a worker with a deadline; the same regex run directly against the longest tool name does not finish). After the fact, the `matcher` position of `settingsHooksRefusalFromError` reads the server's own refusal: from 7.115.0 the refusal's `field` and `detail` give the event, the alias and the current name, which must equal this function's verdict on the same matcher; older refusals carry no such fields and the reader answers nothing rather than parsing the sentence. From 0.96.0 the verdict reads a matcher only through the settings contract's own reading (`hookMatcherSelects` / `hookMatcherForm`: a name list, or the whole string as an unanchored regular expression), generated at build time from the installed contract package: the guard pins that the verdict answers the same as the installed contract functions combined with the server's refusal rule on more than 60 shapes, that three shapes which only an anchored reading would answer differently are judged as the current server judges them, that the verdict's module constructs no regular expression of its own, that accepted verdicts carry no name list, and that the per-generation reading table in the integration guide matches every published server generation. |
|
|
493
493
|
| `scripts/run-human-turn-encoding-test.mjs` | The check for the data envelope that carries a user's @-attached file, notebook, image, PDF or directory to an engine that has no attachment seat, and for the single function that turns one human submission into what the request carries. The envelope bytes are pinned against the 45 reference samples agreed with the terminal (the sample file is a byte-for-byte copy), and four extra samples with an instruction inside the file contents are checked for shape: the instruction stays between the two fence lines with a line-number prefix, the fence is longer than any tilde run in the envelope, and the header carries no reminder tag, no claim that a tool was called and no imperative. The three boundary rules (fence length over the whole envelope including look-alike tildes, visible escapes for in-line break characters, quoting and escaping of names) each have their own cells; a malformed descriptor throws and accessor properties are never run. Every envelope is wrapped in a closed-set `<attachment>` tag carrying a `path` attribute (a reference sentence gets a self-closing tag line instead); the text inside the tag is pinned byte for byte against the envelopes minted before the wrap, 26 frozen fixtures covering every descriptor kind; the attribute is the shown path with the four markup characters escaped, checked on hand-written cases and a seeded pool; descriptors without a path get a tag without attributes; and each envelope reads as exactly one opening line and one closing line. For the assembly: the projection rule (non-empty items joined by a newline, attachments before the item text), the image seat plan (pasted images first, at most 20 images, each image up to the engine's inline-image limit and 6 MiB in total, only when the model can see images), the 8 MiB request-body accounting (exactly at the limit is accepted and one byte more degrades or refuses, compared with the real serialized body on six body shapes), the order in which attachments are reduced to a reference sentence, the three-step handling on the follow-up carrier (contents, then reference sentences, then keep queued) and its agreement with the engine's own follow-up text validator on a seeded pool, the delivery shares and the reduced list as two views of one record, the refusal reasons, the image-vision verdict and the attachment-seat capability reader. The two engine limits the package reads from generated constants (the per-image size and the follow-up text length) are checked against the engine's own exports, and the per-image size also against the engine's inline-image admission path; the limits it still mirrors are checked against a server package fixture's real admission path when one is configured, and every server fixture generation must admit an image of the per-image limit. Pasted images take seats first but are held to the same count, per-image and total limits; an image over a limit is left out and recorded as not sent. Very long rider lists are handed to the ledger without overflowing the call stack, and an encoded submission handed to the ledger as-is records partly sent entries as partly delivered. The fixed sentence for an attachment left out because a read-approval rule applies is the same for files, directories, paths and MCP resources and names no rule layer. |
|
|
494
494
|
| `scripts/run-replayed-approval-disposition-test.mjs` | Approval requests read back from a run's event log are only raised as questions when the pending-approval list says they are still open: `replayedApprovalDisposition(frame, basis)` answers `live` / `decided` / `unknown` (a frame without an event-log position is live; one listed by this connection's opening snapshot or by a pending list read after the frame arrived is live; one missing from a complete list is decided, with the crash-convergence cause when the same response carries one; an incomplete, missing or unreadable list, or no read, is unknown and never treated as open), and the in-stream approval leg applies the same verdict before raising a card — a decided frame raises no card and sends no decision, an unknown one raises no card, sends nothing, hands the frame to `onReplayedApproval` and shows one notice, the list is re-read for every such frame (never cached across frames), the read is bounded, and the opening-snapshot evidence is reset on every new connection. The test for 'does this frame carry an event-log position' is public (`hasLedgerPositionKey`: either an `id` or a `seq` key that is present and not null counts, whatever its value; it is the exact opposite of the verdict's live-leg shortcut), and the one sentence a host shows for a decided or unknown frame is minted in one place (`replayedApprovalSentence`): a decided frame is described only as no longer listed by the engine as waiting (a tool name, when given, is sanitised and shown inside quotation marks), a crash-convergence cause says the engine denied it automatically (it stopped unexpectedly, or was shut down in an orderly way), nothing is ever described as approved or as having run, an unknown frame says it could not be confirmed, and every sentence says no decision was sent. A question the bridge has already seen settled (answered, dismissed with an interrupt, or closed by an engine closing frame) is never raised again by a repeated frame — with or without an event-log position, whether or not the opening snapshot lists it, and even when the pending list read afterwards still lists it: the verdict is `decided` with a `settled` word (never together with a crash-convergence cause), no card, no decision, no list read, no notice, and one hand-off to `onReplayedApproval`. Only certain outcomes are recorded (a card the host withdrew or a decision that failed to send is not, so a repeated frame still raises a card then), the record is first-outcome-wins, survives new connections, is bounded, and the sentence for it is minted in the same one place without saying what the outcome was. A host that keeps its own set of already-closed approvals asks one public predicate (`replayedApprovalClosesCardFrame`) whether a handed-back disposition should make later card frames for the same approval count as closed: only a decided disposition carrying a known crash-convergence cause does; a decided one without a cause (the answering replica may simply not have it in memory), a settled one, a live or unknown one, an unfamiliar cause and any malformed value do not, so a card that might still be answerable stays visible. |
|
|
495
495
|
| `scripts/run-server-7116-fixture-test.mjs` | Checks against the published 7.116.0 server package and every older package in the list, each held to an exact per-generation table. Answering a stream approval that the server has already closed without a human decision (a 410 `gone.ask`, which from 7.116.0 also covers an approval left pending by a process that crashed or shut down) is produced by the server's own convergence step and decision route, and through both SDK error mappings is read by `askGoneFromError` and turned by `askGoneContent` into a three-part sentence whose way out depends on the cause; the decision-failure note and the already-resolved check claim it by code; the two process-ended causes are the same closed list as crash-converged rows, the sentence carries no machine words, and the one denied-group word the reader keeps equals the server's table. Run death codes from the server's run-detail route reach the abort-cause reader and the synthesized terminal unchanged, with one way-out sentence per class. An empty operator list now answers 501 `capability.operator_principals_required`, read as `operators_unconfigured` (nothing was done) by the memory and rules readers and the rule write, while 403 stays `operator_only`; a plan-review decision hitting an unavailable-face 501 is `not_applied`; the four new capability bits are read by their readers. Protocol rule names whose server segment the engine never mints are held back from the allow list, while deny and ask rules are sent unchanged and listed in the report's `unreachable` table; the server's own judge refuses exactly the listed rules (naming the same minted prefix), the request without them is accepted, and the whole request is refused by 7.116.0 and accepted by older servers. The remember-refused card flag reaches the card from both paths. |
|
|
@@ -671,6 +671,9 @@ guard still cross-checks the table by name).
|
|
|
671
671
|
| `scripts/run-mods-face-projection-test.mjs` | The three user-facing mod seats. A registration record is read one way wherever it comes from (the run receipt's `mods` section, the refused-registration notice's detail, the in-process kernel's records): own data properties only, each key isolated, the two shapes told apart by member presence, no derived disposition word. `modRowsOf` answers `undefined` for anything that is not an array or where no row survives (unreadable is not zero) and `[]` for an empty list; `readModRegistrationRefusedNotice` turns the refused-registration notice into the refused row, or answers `undefined` so the host keeps the engine's own line. On tool result rows the package adds `_sema_answered_by`, the registration that answered a call at the `tool.call` station in place of the tool, from one criterion evaluated once at the single row mint against the same gate view it writes to `_sema_gate`: the engine's own fail-closed marker `engine` never counts as an answering registration, a refusal needs a `denied` / `hook` gate record and `isError: true`, an answer in place needs a gate record that is not a denial and `isError: false`, and an unreadable gate record or an `isError` that cannot be read yields nothing. `modCardSentence` renders the registration card in its two shapes and the refused-by / answered-in-place line; `modLoaderFailureSentence` renders a load failure from whatever the host caught. The gate drives the real kernel in process, the installed server package's receipt and notice projections, and frames derived from the engine's `tool_end` type through both the interactive and the print outputs; it compares the receipt projection byte for byte with the previous reading over the existing samples and a generated pool, and checks that every outward string goes through the display sanitizer. |
|
|
672
672
|
| `scripts/run-display-untrusted-phase-ladder-test.mjs` | The ladder behind the credential side of the display outlet. Since 0.102.0 the rules added in a release run only after the older rules have settled on their own, and then alternate with them until nothing changes, so, for every input, the masked text before any length cap covers at least what the older rules (everything outside the table, including this release's changes to them) mask on their own; not masking less than the previous release is measured on frozen pools, not guaranteed by construction. The gate checks that there is one rule table, that rows are only additive candidate generators read through a single emit point, and that the single-pass reading is gone (the upload check and the settings judge read the same ladder). Against the previous published release (a tarball path in `SEMA_DU_BASELINE_TGZ`; any other version reports a skipped section, not a pass) it checks on frozen pools that the first ladder step, taken on the production path, is byte-identical to the previous release in text and position map wherever this release's base rules did not change, and identical to a variant with an empty table everywhere; that no original character becomes visible again, at the scanner and at the address-reading level (where this release reads a configured address differently from the previous one, it either withholds the whole string or every original character the previous release's reading hid stays hidden, checked by flipping one character at a time and watching which positions of the rebuilt address change, not by the package's own alignment); that exit idempotence does not get worse in seven option groups, nor on any single row in six of them; that clean text is collected once; that folding this release's rows into the first step would expose values on constructed rows; and that the nested value judge and the machine-readable wash agree. Pinned counterexamples: for addresses whose own text already has something to hide (a backslash that would shorten the authority, an encoded `@`, a host the rebuild would lower-case), every credential reading (machine-readable wash, upload check, settings judge, settings notice) answers that it carries a credential and the configured-address output is pinned byte for byte; across the pools, a `scheme://` value whose userinfo the wash hides is never judged clean; the widened scheme-less userinfo reading only adds candidates; both families are idempotent; an anchored form inside a control string stays as-is in the first step; whole-string withholding of an ambiguous or unparseable address is not switched off by marker-shaped or escape-shaped text in the value; a backslash address keeps its own text whenever that reading already hides everything the rebuilt reading would. Also: the same text written twice in one address is never taken as the source of the other copy, a marker or a literal escape outside the authority no longer decides how a backslash address is read (one inside the authority marks it as already displayed and keeps its own text), every pool row's chosen reading is checked against the other one by flipping characters (both directions for backslash addresses; for single-slash and no-slash forms every hidden run must land whole and verbatim in one URL field), the package's own position map between the text and the rebuilt address agrees with that flipping test (surrogate pairs, non-ASCII, upper-case hosts, ports), placeholders and the outlet's own escapes in a backslash address stay where they were, and an anchored form inside a control string stays as-is in the first step in its raw, escaped and percent-encoded spellings. Nine in-gate negative controls (restarting the second step from the original text, dropping the step tags, letting the judge read only the last step, no longer accepting a marker inside the anchored tail, dropping the step tags at each of three local copy points: nested control-string content, nested on-screen and decoded content, a bare query part, dropping them for decoded content alone, and rebuilding a backslash address without first asking whether its own text already hides enough) each turn a cell red. |
|
|
673
673
|
| `scripts/run-session-namespace-key-test.mjs` | Engine namespace key of the session map. The key under which a connected engine's continuity record (engine session id, last task id, sync watermark) is stored is its lowercased origin plus its normalized path: trailing slashes are dropped, path case and percent-escapes are kept as written, and the query, fragment and userinfo are not part of it, so two engines behind one relay origin no longer share a record. A target with an empty path keeps the earlier origin-only key and reads its older entry unchanged; an entry stored under the bare origin is never read for a target that has a path (one reading, no fallback). The self-spawned engine stays `local`; a malformed url, and a url whose origin is opaque, falls back to its raw lowercased string. Cells cover the key shape and spelling variants, role and origin separation, the same-engine comparison an auto-sync no-op check builds on, reading of older records, boundaries (IPv6 hosts, default ports, dot segments, percent-escapes, doubled slashes), the single exported reading, and a never-throws sweep. |
|
|
674
|
+
| `scripts/run-core-7590-pick-projection-test.mjs` | Readings that follow the engine's 7.59 changes. An MCP server that answers 401 or 403 is now reported with the failure kind `unauthorized` and an `authorization` record (`reason`, optional trusted `authorizeUrl`, optional untrusted `resourceMetadataUrl`); `readMcpAuthorization` reads it in three ways (absent, present but unreadable, a record) from own data properties only, and the wiring-receipt row, the per-server connection reading and the reconnect result carry the record as given or a `authorizationUnreadable: true` flag, never folding unreadable into absent. The `mcp.authorization_required` and `context.image_removed` notices have fact readers; the status frame's `sleptMs` and `waitSegment` reach the retry status; a server name starting with lowercase `remote-` is refused on both config paths while other letter cases are accepted; the ask class `write_protection_on_disk` reads with the same sentence as the `write_protection` mandate; the extension kernel contract is 5; a hook denial carries the denying extension's registered name when known; an MCP server's `startupTimeoutMs` reaches the request on both config paths as given. Names the engine added that this package does not read are pinned to zero code reads. An erase receipt the engine marks partial carries its cause (entries not erased, only leftover stored records that refer to erased entries, or unknown), and the session erase outcome no longer says entries were not erased when only leftover records remain; the decision-conflict reader takes one snapshot of the error's `extra` bag at entry. |
|
|
675
|
+
| `scripts/run-server-7137-pick-projection-test.mjs` | Readings that follow the server's 7.137 additions. A `delegation.ask_unresolvable` notice's `remedies` list is read into the existing fact view (kinds from the engine's closed set, an unknown kind or a malformed member dropped on its own, an empty list never minted), with one sentence per way out from `askUnresolvableRemedyContent`; `invalid_session` (a stored session log whose parent chain does not resolve) is treated like `corrupt_session` on every carrier: no retry offer, the same damaged-session sentence, the original code kept; a `resume.constraint_rejected` refusal carries `acceptableForm` as given whenever the refusal includes it; edited rule text is trimmed at its outer edges (and between the tool name and the parenthesis) by one function, `trimEditedRuleText`, before both the live card arm and the precheck port; a plan-review decision carries `checkpointId` only when the gate identity is known and the engine reports `planReviewCheckpointId: true` (through an injected connection, only under the connection's own `capsBaseUrl`, never borrowing the installed target's evidence); `observedSandboxGitCredentialPlane` reads `credentialPlane.sandboxGit` in five states and never reads an absent bit as off; the device lane reading carries `relayUrl` when present; an `inheritEnv` refusal of a request that carried the field, with any value, carries the engine's `reason` word when the field is named, and its sentence states which values the engine accepts instead of claiming the request asked for the whole environment. Session-sync retries stay with the client's retrier, which stops on a terminal permanence. |
|
|
676
|
+
| `scripts/run-pkg-policy-registration-test.mjs` | Package policy registration. The package's own `package.json` is checked, item by item and by equality, against its row in the cross-package policy table: the package-name sets of the four dependency kinds (version ranges are not compared; one name more or fewer is red and the difference is printed), the `exports` key set, the pinned version (equal to the `version` field or to the highest released CHANGELOG section, so both sides of a version bump are legal, and a bump the table did not follow is red), and the first sentence of `description`. The table is taken from `SEMA_PKG_POLICY_PATH` when that is set (no fallback), otherwise from a sibling checkout found by walking up from the package root; when it cannot be reached the whole gate reports a skipped section and exits 0, which is not a pass. A negative control adds one unlisted dev dependency and expects the dependency check to go red |
|
|
674
677
|
|
|
675
678
|
Each suite carries a floor that only moves up — a refactor that stops executing a group of
|
|
676
679
|
assertions is a failure, not a quieter pass. Guards anchor on the **installed artefact's content**
|
|
@@ -2,7 +2,7 @@ import type { AdapterContext, AdapterOutput } from '../seam.js';
|
|
|
2
2
|
import { structuredToToolUseResult, type ToolKillCause, type ToolResultBody } from '../toolResult.js';
|
|
3
3
|
import { type Frame, type IdOf } from './ids.js';
|
|
4
4
|
import type { EngineRowRef } from '../engineRowRef.js';
|
|
5
|
-
import { type GateOutcomeView } from '../gateOutcome.js';
|
|
5
|
+
import { type GateOutcomeView, type ToolInputRewriteView } from '../gateOutcome.js';
|
|
6
6
|
type RichToolUseResult = NonNullable<ReturnType<typeof structuredToToolUseResult>>;
|
|
7
7
|
export interface ToolResultOutcome {
|
|
8
8
|
readonly body: ToolResultBody;
|
|
@@ -38,6 +38,7 @@ export interface ToolResultRowFlagParts {
|
|
|
38
38
|
readonly _sema_approval_window_expired?: true;
|
|
39
39
|
readonly _sema_denial_limit_window_expired?: true;
|
|
40
40
|
readonly _sema_answered_by?: string;
|
|
41
|
+
readonly _sema_rewrite?: ToolInputRewriteView;
|
|
41
42
|
}
|
|
42
43
|
export declare function toolResultRowFlagParts(arm: object | null | undefined, gate: GateOutcomeView | undefined): ToolResultRowFlagParts;
|
|
43
44
|
interface ToolEndPayload {
|
package/dist/adapt/toolCards.js
CHANGED
|
@@ -6,7 +6,7 @@ import { toolResultBlocksOf } from '../toolResultContent.js';
|
|
|
6
6
|
import { bashExitOf, bashExitReadingFailed } from '../bashExitReading.js';
|
|
7
7
|
import { isCcToolDenialKind } from '../gateVocabulary.js';
|
|
8
8
|
import { guardedRead, ownSnapshotWhenTyped, readFrameStringKey, readFrameTrueMark, readOwnDataValue } from '../ownKey.js';
|
|
9
|
-
import { gateDeniedBy, isApprovalWindowExpiredGate, isDeniedGate, isDenialLimitAutoDeniedGate } from '../gateOutcome.js';
|
|
9
|
+
import { gateDeniedBy, isApprovalWindowExpiredGate, isDeniedGate, isDenialLimitAutoDeniedGate, toolInputRewriteOf } from '../gateOutcome.js';
|
|
10
10
|
import { TOOL_END_INTERRUPTED_NEVER_STARTED } from '../engineErrorCodes.js';
|
|
11
11
|
function toolUseResultParts(v) {
|
|
12
12
|
return v !== undefined ? { tool_use_result: v } : {};
|
|
@@ -58,6 +58,7 @@ export function toolResultRowFlagParts(arm, gate) {
|
|
|
58
58
|
return {};
|
|
59
59
|
const notExecuted = readFrameTrueMark(arm, 'notExecuted');
|
|
60
60
|
const answeredBy = modAnsweredByOf(arm, notExecuted, gate);
|
|
61
|
+
const rewrite = toolInputRewriteOf(arm);
|
|
61
62
|
return {
|
|
62
63
|
...(notExecuted ? { _sema_not_executed: true } : {}),
|
|
63
64
|
...(readFrameTrueMark(arm, '_sema_collateral_abort') ? { _sema_collateral_abort: true } : {}),
|
|
@@ -65,6 +66,7 @@ export function toolResultRowFlagParts(arm, gate) {
|
|
|
65
66
|
...(isApprovalWindowExpiredGate(gate) ? { _sema_approval_window_expired: true } : {}),
|
|
66
67
|
...(isDenialLimitAutoDeniedGate(gate) ? { _sema_denial_limit_window_expired: true } : {}),
|
|
67
68
|
...(answeredBy !== undefined ? { _sema_answered_by: answeredBy } : {}),
|
|
69
|
+
...(rewrite !== undefined ? { _sema_rewrite: rewrite } : {}),
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
72
|
const MOD_ENGINE_ORIGIN = 'engine';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentEvent, CheckpointGate, TaskResult } from '@sema-agent/sdk';
|
|
2
2
|
import { type WiringManifestView } from './wiringManifestView.js';
|
|
3
3
|
import { type SDKMessage, type EmitContext, type ModelUsage } from '../types.js';
|
|
4
|
-
import { type McpLivenessView } from '../../mcpLiveness.js';
|
|
4
|
+
import { type McpAuthorizationView, type McpLivenessView } from '../../mcpLiveness.js';
|
|
5
5
|
import { type ContextUsageSectionRow, type PromptIdentityLayersRow, type PromptManifestIdentityRow, type PromptManifestSectionRow } from '../../ownKey.js';
|
|
6
6
|
export declare const INTERNAL_SDK_ARM_TYPES: ReadonlySet<string>;
|
|
7
7
|
export type EventProjectionNoneReason = 'usage_only' | 'terminal_delegated' | 'hitl_out_of_slice' | 'not_in_slice' | 'empty_payload';
|
|
@@ -38,6 +38,8 @@ export interface WiringManifestMcpEntryView {
|
|
|
38
38
|
httpStatus?: number;
|
|
39
39
|
liveness?: McpLivenessView;
|
|
40
40
|
livenessUnreadable?: true;
|
|
41
|
+
authorization?: McpAuthorizationView;
|
|
42
|
+
authorizationUnreadable?: true;
|
|
41
43
|
}
|
|
42
44
|
export declare function projectMcpSection(raw: unknown): WiringManifestMcpEntryView[] | undefined;
|
|
43
45
|
export type SubmitWiringManifestReading = {
|
|
@@ -76,6 +78,7 @@ export interface WiringManifestModMountedView {
|
|
|
76
78
|
readonly name: string;
|
|
77
79
|
readonly seat: string;
|
|
78
80
|
readonly tier: string;
|
|
81
|
+
readonly provenance?: string;
|
|
79
82
|
readonly events: readonly string[];
|
|
80
83
|
readonly observe?: readonly string[];
|
|
81
84
|
readonly skipped?: readonly WiringManifestModSkipView[];
|
|
@@ -84,6 +87,7 @@ export interface WiringManifestModRefusedView {
|
|
|
84
87
|
readonly name: string;
|
|
85
88
|
readonly seat: string;
|
|
86
89
|
readonly tier: string;
|
|
90
|
+
readonly provenance?: string;
|
|
87
91
|
readonly refusedBy: string;
|
|
88
92
|
readonly reason: string;
|
|
89
93
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { modRowsOf, readFleetSegment, readInstructionsSegment, wiringManifestViewOf } from './wiringManifestView.js';
|
|
2
2
|
import { stamp, snapshotSegmentIdentity, } from '../types.js';
|
|
3
3
|
import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
|
|
4
|
-
import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js';
|
|
4
|
+
import { ccToolDenialKindForToolEnd, gateOutcomeOf, toolInputRewriteOf } from '../../gateOutcome.js';
|
|
5
5
|
import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
|
|
6
6
|
import { projectHandsSection } from '../../handsSeam.js';
|
|
7
|
-
import { readMcpLiveness } from '../../mcpLiveness.js';
|
|
8
|
-
import { contextUsageReadingOf, humanInputAttachmentsOf, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataNonEmptyString } from '../../ownKey.js';
|
|
7
|
+
import { readMcpAuthorization, readMcpLiveness } from '../../mcpLiveness.js';
|
|
8
|
+
import { contextUsageReadingOf, humanInputAttachmentsOf, guardedRead, markMcpSectionDroppedNamedRows, ownSnapshotTyped, promptManifestIdentityOfFrame, promptManifestSectionViewOf, readFrameStringKey, readFrameTrueMark, readOwnDataFiniteNumber, readOwnDataNonEmptyString } from '../../ownKey.js';
|
|
9
9
|
import { SEGMENT_END_IDENTITY_KEYS, eventSeq, stripToolUseSideChannels } from '../types.js';
|
|
10
10
|
import { frozenSet } from '../../frozenSet.js';
|
|
11
11
|
import { isCoreWorkflowRunTerminal } from '../../terminalStatuses.js';
|
|
@@ -73,6 +73,11 @@ const dropped = (why, type) => ({ kind: 'dropped', why, type });
|
|
|
73
73
|
function isCompactionStartedFrame(ev) {
|
|
74
74
|
return ev.type === 'compaction_started';
|
|
75
75
|
}
|
|
76
|
+
const BEYOND_FLOOR_ARMS = Object.freeze(['cross_boundary_taint', 'approval_complete', 'session_titled']);
|
|
77
|
+
function isBeyondFloorArm(ev) {
|
|
78
|
+
const word = ev.type;
|
|
79
|
+
return typeof word === 'string' && BEYOND_FLOOR_ARMS.includes(word);
|
|
80
|
+
}
|
|
76
81
|
function assertNeverArm(_ev) {
|
|
77
82
|
}
|
|
78
83
|
export function eventToSdkMessage(ev, ctx) {
|
|
@@ -106,6 +111,10 @@ function withEngineIdentity(p, ev, ctx, identityFrame = ev) {
|
|
|
106
111
|
function projectEvent(ev, ctx) {
|
|
107
112
|
if (isCompactionStartedFrame(ev))
|
|
108
113
|
return compactionStartedProjection(ev, ctx);
|
|
114
|
+
if (isBeyondFloorArm(ev)) {
|
|
115
|
+
const word = ev.type;
|
|
116
|
+
return word === 'cross_boundary_taint' ? nothing('not_in_slice') : dropped('unsupported_arm', word);
|
|
117
|
+
}
|
|
109
118
|
switch (ev.type) {
|
|
110
119
|
case 'task_started':
|
|
111
120
|
return taskStartedProjection(ev, ctx);
|
|
@@ -230,6 +239,7 @@ function projectEvent(ev, ctx) {
|
|
|
230
239
|
const denialKind = ccToolDenialKindForToolEnd(ev);
|
|
231
240
|
const toolEndNotExecuted = readFrameTrueMark(ev, 'notExecuted');
|
|
232
241
|
const toolEndAnsweredBy = readFrameStringKey(ev, 'answeredBy');
|
|
242
|
+
const toolEndRewrite = toolInputRewriteOf(ev);
|
|
233
243
|
return projected(stamp(ctx, armBody({
|
|
234
244
|
type: 'tool_end_result',
|
|
235
245
|
toolCallId: ev.toolCallId,
|
|
@@ -253,6 +263,7 @@ function projectEvent(ev, ctx) {
|
|
|
253
263
|
...(denialKind !== undefined ? { _sema_denial_kind: denialKind } : {}),
|
|
254
264
|
...(toolEndNotExecuted ? { notExecuted: true } : {}),
|
|
255
265
|
...(toolEndAnsweredBy !== undefined ? { answeredBy: toolEndAnsweredBy } : {}),
|
|
266
|
+
...(toolEndRewrite !== undefined ? { rewrite: toolEndRewrite } : {}),
|
|
256
267
|
...(ev.eventId !== undefined ? { eventId: ev.eventId } : {}),
|
|
257
268
|
...(ev.parentToolCallId !== undefined
|
|
258
269
|
? { parentToolCallId: ev.parentToolCallId }
|
|
@@ -272,6 +283,10 @@ function projectEvent(ev, ctx) {
|
|
|
272
283
|
const nonEmptyStr = (v) => (typeof v === 'string' && v.length > 0 ? v : undefined);
|
|
273
284
|
const providerCondition = nonEmptyStr(ev.providerCondition);
|
|
274
285
|
const providerConditionSource = nonEmptyStr(ev.providerConditionSource);
|
|
286
|
+
const stWait = ev;
|
|
287
|
+
const sleptMsRaw = guardedRead(() => readOwnDataFiniteNumber(stWait, 'sleptMs'));
|
|
288
|
+
const sleptMs = sleptMsRaw !== undefined && sleptMsRaw >= 0 ? sleptMsRaw : undefined;
|
|
289
|
+
const waitSegment = readFrameStringKey(stWait, 'waitSegment');
|
|
275
290
|
return projected(stamp(ctx, armBody({
|
|
276
291
|
type: 'retry_status',
|
|
277
292
|
phase: ev.phase,
|
|
@@ -287,6 +302,8 @@ function projectEvent(ev, ctx) {
|
|
|
287
302
|
...(timeoutMs !== undefined ? { timeoutMs } : {}),
|
|
288
303
|
...(providerCondition !== undefined ? { providerCondition } : {}),
|
|
289
304
|
...(providerConditionSource !== undefined ? { providerConditionSource } : {}),
|
|
305
|
+
...(sleptMs !== undefined ? { sleptMs } : {}),
|
|
306
|
+
...(waitSegment !== undefined ? { waitSegment } : {}),
|
|
290
307
|
...(typeof ev.eventId === 'string' ? { eventId: ev.eventId } : {}),
|
|
291
308
|
...(typeof ev.parentToolCallId === 'string' ? { parentToolCallId: ev.parentToolCallId } : {}),
|
|
292
309
|
})));
|
|
@@ -555,6 +572,7 @@ export function projectMcpSection(raw) {
|
|
|
555
572
|
...(typeof r.delivered === 'string' && r.delivered.length > 0 ? { delivered: r.delivered } : {}),
|
|
556
573
|
...(typeof r.httpStatus === 'number' && Number.isFinite(r.httpStatus) ? { httpStatus: r.httpStatus } : {}),
|
|
557
574
|
...((cell) => cell.kind === 'observation' ? { liveness: cell.liveness } : cell.kind === 'unreadable' ? { livenessUnreadable: true } : {})(readMcpLiveness(r)),
|
|
575
|
+
...((cell) => cell.kind === 'record' ? { authorization: cell.authorization } : cell.kind === 'unreadable' ? { authorizationUnreadable: true } : {})(readMcpAuthorization(r)),
|
|
558
576
|
});
|
|
559
577
|
}
|
|
560
578
|
if (raw.length > 0 && rows.length === 0)
|
|
@@ -127,6 +127,8 @@ function modRowOf(r) {
|
|
|
127
127
|
const name = nonEmpty(ownSlot(r, 'name'));
|
|
128
128
|
const seat = nonEmpty(ownSlot(r, 'seat'));
|
|
129
129
|
const tier = nonEmpty(ownSlot(r, 'tier'));
|
|
130
|
+
const provenance = nonEmpty(ownSlot(r, 'provenance'));
|
|
131
|
+
const provenancePart = provenance !== undefined ? { provenance } : {};
|
|
130
132
|
if (name === undefined || seat === undefined || tier === undefined)
|
|
131
133
|
return undefined;
|
|
132
134
|
const events = ownSlot(r, 'events');
|
|
@@ -143,7 +145,7 @@ function modRowOf(r) {
|
|
|
143
145
|
const why = nonEmpty(reason);
|
|
144
146
|
if (by === undefined || why === undefined)
|
|
145
147
|
return undefined;
|
|
146
|
-
const refused = { name, seat, tier, refusedBy: by, reason: why };
|
|
148
|
+
const refused = { name, seat, tier, ...provenancePart, refusedBy: by, reason: why };
|
|
147
149
|
return refused;
|
|
148
150
|
}
|
|
149
151
|
const eventList = events.state === 'value' ? ownStringList(events.value) : undefined;
|
|
@@ -155,6 +157,7 @@ function modRowOf(r) {
|
|
|
155
157
|
name,
|
|
156
158
|
seat,
|
|
157
159
|
tier,
|
|
160
|
+
...provenancePart,
|
|
158
161
|
events: eventList,
|
|
159
162
|
...(observeList !== undefined ? { observe: observeList } : {}),
|
|
160
163
|
...(skipList !== undefined && skipList.length > 0 ? { skipped: skipList } : {}),
|