@sema-agent/client-core 0.111.0 → 0.112.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 +75 -0
- package/README.md +15 -6
- package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
- package/dist/checkpointRowVerdict.d.ts +3 -0
- package/dist/checkpointRowVerdict.js +14 -1
- package/dist/consoleCaPin.d.ts +136 -0
- package/dist/consoleCaPin.js +827 -0
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/deviceRebind.js +3 -3
- package/dist/effectiveFacts.d.ts +9 -0
- package/dist/effectiveFacts.js +33 -0
- package/dist/engineAddress.d.ts +1 -0
- package/dist/engineAddress.js +4 -1
- package/dist/engineCredentialRelease.d.ts +54 -0
- package/dist/engineCredentialRelease.js +146 -0
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +1 -0
- package/dist/engineHealthFacts.d.ts +0 -11
- package/dist/engineHealthFacts.js +0 -21
- package/dist/engineHealthProbeVerdict.d.ts +1 -0
- package/dist/engineHealthProbeVerdict.js +21 -13
- package/dist/engineUnavailable.d.ts +3 -2
- package/dist/engineUnavailable.js +16 -12
- package/dist/engineUrl.js +4 -2
- package/dist/gateFailureCodes.js +2 -2
- package/dist/generated/sdkFactTables.d.ts +1 -0
- package/dist/generated/sdkFactTables.js +13 -0
- package/dist/generated/settingsSchemaFns.d.ts +1 -0
- package/dist/generated/settingsSchemaFns.js +3 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +38 -9
- package/dist/generated/settingsSchemaTables.d.ts +52 -0
- package/dist/generated/settingsSchemaTables.js +18 -0
- package/dist/generated/settingsSchemaTypes.d.ts +23 -13
- package/dist/generated/settingsSchemaUrlShape.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlShape.js +17 -0
- package/dist/hitl/decisionRefusal.d.ts +4 -0
- package/dist/hitl/decisionRefusal.js +12 -2
- package/dist/hitl/localAllowRedemption.d.ts +9 -6
- package/dist/hitl/localAllowRedemption.js +20 -0
- package/dist/hitl/parkOwnership.js +2 -1
- package/dist/hitl/parkResolver.js +7 -0
- package/dist/hitl/screenDecisionCards.js +3 -2
- package/dist/hitl/sessionPolicyWire.js +2 -2
- package/dist/hitl/standingRows.d.ts +4 -2
- package/dist/hitl/standingRows.js +10 -3
- package/dist/hooksReaderGenerations.js +1 -1
- package/dist/i18n/messages.en.d.ts +163 -0
- package/dist/i18n/messages.en.js +163 -0
- package/dist/i18n/messages.zh.js +174 -0
- package/dist/index.d.ts +30 -5
- package/dist/index.js +15 -2
- package/dist/liveModelCatalog.d.ts +4 -0
- package/dist/liveModelCatalog.js +10 -1
- package/dist/localConfig/documents.d.ts +61 -0
- package/dist/localConfig/documents.js +51 -0
- package/dist/localConfig/kernel.d.ts +149 -0
- package/dist/localConfig/kernel.js +597 -0
- package/dist/localConfig/mcp/edit.d.ts +161 -0
- package/dist/localConfig/mcp/edit.js +846 -0
- package/dist/localConfig/mcp/servers.d.ts +165 -0
- package/dist/localConfig/mcp/servers.js +776 -0
- package/dist/localConfig/mcp/views.d.ts +170 -0
- package/dist/localConfig/mcp/views.js +429 -0
- package/dist/localConfig/modelPool.d.ts +262 -0
- package/dist/localConfig/modelPool.js +1489 -0
- package/dist/localConfig/modelPoolWords.d.ts +13 -0
- package/dist/localConfig/modelPoolWords.js +20 -0
- package/dist/localConfig/receiptShape.d.ts +7 -0
- package/dist/localConfig/receiptShape.js +135 -0
- package/dist/localConfig/settingsWrite.d.ts +127 -0
- package/dist/localConfig/settingsWrite.js +237 -0
- package/dist/localConfig/skills.d.ts +124 -0
- package/dist/localConfig/skills.js +397 -0
- package/dist/localConfig/skillsWords.d.ts +10 -0
- package/dist/localConfig/skillsWords.js +5 -0
- package/dist/mcpProbeWire.js +2 -1
- package/dist/mcpWireCaps.js +1 -1
- package/dist/memoryVerbsWire.js +3 -2
- package/dist/model/onboardJudgement.d.ts +14 -4
- package/dist/model/onboardJudgement.js +91 -139
- package/dist/modelConfigGapNotice.d.ts +20 -0
- package/dist/modelConfigGapNotice.js +102 -0
- package/dist/modsKernelIdentity.js +2 -47
- package/dist/ownKey.d.ts +1 -0
- package/dist/ownKey.js +40 -8
- package/dist/permissionsDeclaration.d.ts +2 -1
- package/dist/permissionsDeclaration.js +31 -17
- package/dist/promptBlockedCopy.js +2 -2
- package/dist/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +12 -4
- package/dist/runLedgerSnapshot.js +3 -3
- package/dist/runPermissionModeSwitch.js +2 -3
- package/dist/seatContract.d.ts +154 -4
- package/dist/seatContract.js +228 -2
- package/dist/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +4 -1
- package/dist/sessionMemoryErase.js +2 -1
- package/dist/sha256Bytes.d.ts +1 -0
- package/dist/sha256Bytes.js +46 -0
- package/dist/skillOverrideChain.d.ts +83 -0
- package/dist/skillOverrideChain.js +378 -0
- package/dist/skillsWireCaps.d.ts +3 -0
- package/dist/skillsWireCaps.js +16 -1
- package/dist/turnFailurePresentation.js +4 -10
- package/docs/INTEGRATION-CLIENTS.md +614 -14
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -49,6 +49,81 @@
|
|
|
49
49
|
> 挡住 ⇒ 本批把它机械化——④a0 对 `pending` 行**要求段头已是日期形**(`(未发布)` 直接红),阶段一
|
|
50
50
|
> commit 漏转在发布前就红,不再靠人记。
|
|
51
51
|
|
|
52
|
+
## 0.112.0(2026-11-10)
|
|
53
|
+
|
|
54
|
+
> 主题:本地配置共用内核与其上三个配置域(MCP 服务器 / 技能 / 模型池)归包,连同服务端 7.149.0 · 类型包 38.1.0 · 设置契约 25.1.0 提货 ‖ 设置契约换钉 18.0.0 → 25.1.0:hook 条目判官多承运六键、服务端读者代际表一行不读键 1 → 5,其余各项零读点(接入文档 **§141 SS25-1 – SS25-9**;行为变:设置文件 hooks 这些键的坏值改判坏块)‖ 本地配置共用内核骨架:文档名表 + 全局状态文件唯一定位口 · 文件读数四态 · 写律一只编排口 · 回执四臂 + 预演 · 拒因闭集与两语句 · 车道判与写位前置 · 写意图表 + 设置写计划(CC-1452;接入文档 **§141 LC-1 – LC-9**;加性)‖ MCP 服务器配置归包:读侧一只 `mcpServersReport` · 写侧一只 `applyMcpServerEdit` · 两只视图投影器 · 座位能力位 `mcpServers` / `mcpServerEdit`(CC-1443 / CC-972;接入文档 **§141 MC2**;🔴 型面 BREAKING 窄)‖ 技能归本地配置内核:根表 `skillRootsOf` · 有效值读口 · 可编辑判 · 视图 · 写计划 · 座位能力位 `skills` / `skillsEdit`(CC-1445;接入文档 **§141 SK2-1 – SK2-10**;🔴 型面 BREAKING 窄)‖ 模型池与档位:纯计划口 `poolWritePlan` + 内核意图 · 视图与有效缺省读口 · 座位能力位 `modelPool` / `modelPoolEdit` 与三动词 · 存不存只问写不写律、验证状态三态 · 在线目录丢行数随目录走(CC-828;接入文档 **§141 MP-1 – MP-13**;🔴 型面 BREAKING 窄 + 行为变:缺省只走唯一律 `defaultModelChoiceOf`)‖ 模型配置缺席项 → 归因句:一只判词口 `modelConfigGapNotice`,五处读者同一铸点(CC-1465;接入文档 **§141 MG-1 – MG-5**;加性)‖ 服务端 7.149.0 / 类型包 38.1.0 提货:决断拒收出路词 `wayOut` 与出路句口 · 模型行视图窗口来源 · 读拒地板披露读口 `readDenyFloorOf` · 「原样重发改不了判」码表读类型包快照(CC-1458 / CC-1457;接入文档 **§141 S7149-0 – S7149-7**;🔴 行为变) ‖ 模型池余项:迁移合并律 · 孤儿钥匙槽清扫 · 缺省模型唯一律(CC-1460;接入文档 **§141 MX-1 – MX-9**;🔴 行为变) ‖ 本机引擎凭据只走归属证明之后的连接:判官 `engineCredentialReleaseVerdictOf` · 工厂 `makeLocalEngineWireClient`(CC-1466;接入文档 **§141 AO-1 – AO-5**;加性) ‖ 控制台 CA 钉的判定与规范化:地址判官 `readCenterAddress` · 信任 origin · 指纹三口 · 证书集判官 · 取证书重试计划 · 拒因句(CC-1241;接入文档 **§141 CA-1 – CA-9**;加性) ‖ 一事实一读口:店持久性只读能力面 · 引擎不可用行的应答位收探活判决、第九臂 · 被挡句第三方话封长走共享截断规则(CC-1461 / CC-1462 / CC-1463;接入文档 **§141 OR-1 – OR-6**;🔴 型面 BREAKING 窄 + 文案变) ‖ 安全停判官 `isHitlSafetyErrorLike` 的名字读法并入单一读口(CC-1397;接入文档 **§141 IH-1**;行为窄化) ‖ 本地写 allow 规则与卡上整工具一行改问兑付判官(CC-1420;接入文档 **§141 LA2-1 – LA2-4**;🔴 行为变 + 型面加性)
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **本地配置共用内核骨架(CC-1452;接入文档 §141 LC-1 – LC-9)**:新增本地配置文件的一张文档名表 `LOCAL_CONFIG_DOCUMENTS`(逻辑名 · 四槽路径模板 · 设置契约覆盖面 · 锁秩引用名 · 热度;项目级文件只在 `.sema` 下,全局状态文件住配置家)与全局状态文件唯一定位口 `globalStateFilePathOf({ configHome, oauthSuffix? })`(不探旧位);文件读数四态 `LocalConfigFileReading`(`loaded{doc, revision}` / `absent` / `unreadable{cause}` / `outside_fence`,成因取设置契约 `ROOT_DOCUMENT_UNREADABLE_REASONS`);写律一只编排口 `applyLocalConfigIntent` 与预演口 `previewLocalConfigIntent`:意图 = 单文件提交序列(准备步 / 恰一只效果步 / 收尾步;效果步写的文件独占,同一只文件至多在准备段与收尾段各写一次),每步锁内现读、计划恰一次、交整份下一形与修订号,拒即终局、对端口零重放,残留词闭集 `LOCAL_CONFIG_RESIDUES` 照实回执;域计划入参带模式位 `mode`(`commit` / `preview`;域计划不从修订号推断自己在不在预演);文件读数的文档与整文件下一形只从忠实快照铸 —— 采样有截断或跳件(超深子树、环、自有可枚举访问器)⇒ 读数 `unreadable{io}`、计划 `invalid_request`;回执四臂 `LocalConfigReceipt`(`applied{appliesOn, changed, residue?, disclosures?}` / `refused{reason, detail?, residue?}` / `unavailable{cause}` / `unknown{cause, residue?}`)+ 预演型 `LocalConfigPreview`,拒因闭集 `LOCAL_CONFIG_REFUSALS`(12 词)、`LOCAL_CONFIG_UNAVAILABLE_CAUSES`(4)、`LOCAL_CONFIG_UNKNOWN_CAUSES`(2)、`LOCAL_CONFIG_APPLIES_ON`(3),每词两语一句(`localConfigReceiptSentence` / `localConfigResidueSentence`);披露闭集 `LOCAL_CONFIG_DISCLOSURE_KINDS`(`decided_by` / `shadowed_by`;步计划锁内算 `disclose`,并集进 `applied.disclosures` 与预演,拒 / 说不清两臂不带)与句口 `localConfigDisclosureSentence`;车道判 `localConfigAccess`(Cloud ⇒ `engine_is_remote`、不能确认单用户 ⇒ `not_single_user`、配置家未定 ⇒ `config_home_unpinned`,读写同拦;浏览器两条路分判;写位七前置 `LOCAL_CONFIG_WRITE_PRECONDITIONS`);写意图表 `LOCAL_CONFIG_WRITE_INTENTS` 与派生写键闭集 `SETTINGS_WRITE_KEYS`,设置写计划 `settingsWritePlan`(文档进、文档出;层准入经设置契约单元表)与 `settingsWriteStep`。公开导出 +22(型 +37);零既有名变。门 `run-local-config-kernel-test.mjs`。
|
|
59
|
+
- **MCP server configuration as one shared runtime (CC-1443 C, CC-972; integration doc §141 MC2).** New read entry `mcpServersReport(files, facts, settings, supplementarySources?)`: one source precedence table (claude.ai < plugin < user < approved project < local < managed < agent < dynamic; enterprise file present ⇒ enterprise + managed only, same name enterprise wins), one override-by-name merge, one project approval rule (trusted folder ⇒ merged values; otherwise per-layer presence; session approvals in both; no settings source ⇒ nothing approved from settings, so project rows stay `pending_approval` while session approvals supplied by the host still count), one tool-list agreement rule (`withheldBy: narrowing_conflict | narrowing_invalid`), and one rule that an eligible configuration source being unreadable holds back every server (`withheldBy: layer_unreadable`; rows stay listed): a reading slot that is an accessor or not a reading, a server table or a container on its path that is present but not an object, a table whose keys cannot be read, and a malformed stop or rejection list all count as unreadable, never as absent or empty; a missing file, a file outside the fence, or a reading the host did not supply contributes nothing. With a workspace open, an unreadable global state file therefore holds back every server, enterprise-configured ones included. Names compare byte for byte; the host's own built-in server names are refused alike on read and write. Deployment rows are listed beside request rows (`deployment`); the plugin slot reads the roster the host supplies (`pluginRoster`); prompts and resources read `not_yet`. New pure helpers `mcpProjectChainOf` / `mcpPathWithinFence` / `expandMcpServerEntry`. New write entry `applyMcpServerEdit(edit, store, ctx, { dryRun? })` for six intents (`add` with `onNameTaken: refuse | replace | rename`, `update` with `base` and explicit secret carry-over `keep`, `remove` with or without a scope, `setEnabled`, `setProjectApproval`, `importFromSibling`): one single-file intent through the local configuration kernel; the receipt is the kernel's four arms (`applied` / `refused` / `unavailable` / `unknown`, dry run `preview`); the global state file only changes at the edited key path; a file that does not exist yet is created (a project without `.mcp.json`, a first global state file), while an unreadable file or a malformed container is refused (`scope_unreadable`). `update` with `unset` removes `env` / `headers` / `args` entirely and nothing of them counts as carried over; `unset` together with an edit of the same key is refused (`invalid_request`). `remove` without a scope checks the layer it resolves to against the same writability rule as an explicit scope (before and inside the lock). Plugin de-duplication signatures come from a plain-data snapshot; a plugin entry whose `env` cannot be snapshotted is listed as unusable (`entry_unreadable`) instead of failing the whole report. The kernel refusal table gains six words (`name_unusable` / `name_reserved` / `mcp_entry_invalid` / `ambiguous_scope` / `credentials_need_reentry` / `base_conflict`), each with a sentence in both languages; the write-intent table gains `mcpJsonEnabled` / `mcpJsonDisabled` (local settings only; value form `listItem`). Bridge views `mcpServerReportView` / `mcpServerEditOutcomeView` carry no secret values (env / header member names only, credential arguments masked, configured addresses through the address display). The edit outcome view carries the kernel receipt as is (`receipt`: one of the four arms or the dry-run `preview`, with its disclosures, refusal detail and residue) beside the MCP pages (`refusal` / `plan` / `notices` / `probe` / `sentence`); a refusal page only appears with a `refused` receipt whose reason it maps to. Connection test `probeMcpServerEdit` checks the read lane (a host that lists servers without the shared write lock can still test) and the entry itself, without a write dry run, then dials once with the same entry the read side would load; each result row carries the authorization record (`authorization`: the same view as the seat MCP panel, `'unreadable'` when present but unreadable, `null` when absent), so a deployment-supplied `authorizeUrl` can send the user straight to sign in. Seat: two capabilities `mcpServers` (`listMcpServers` / `probeMcpServerEntry`) and `mcpServerEdit` (`editMcpServer`), each verb with a closed-shape outbound check; `listMcpServers` answers the report view or the kernel `unavailable` arm (`{ kind: 'unavailable', cause }`), the same form as `listModelPool` and `listSkills`; request type `McpServerEditRequest`, request check `checkMcpServerEditRequest`. Guard: `run-local-config-mcp-test.mjs`.
|
|
60
|
+
- **Skills in the local configuration kernel (CC-1445; integration doc §141 SK2-1 – SK2-10)** — one root table, one view, one effective-state reader, one write plan.
|
|
61
|
+
- `skillRootsOf(cwd, hostFacts)`: where skills, commands and agents come from — managed (`managedDir`, when the host gives one), the user's configuration home, each project level from the working directory up to the repository root (nearest first, `.sema/<kind>` only), additional directories, and the host's plugin roster. A `.claude` folder is never read. Relative paths, `.`/`..` segments and a missing configuration home answer `undefined`.
|
|
62
|
+
- `skillOverrideEffectiveOf(layers, skill)`: the one reading of `skillOverrides` (`{ value, decidedBy }`): managed settings first; then the merged settings (full names before bare names; local over project over user) and the session source; aliases are tightened only by managed settings; plugin skills ignore ordinary layers; MCP skills take the first enabled layer that names them; built-in skills are clamped to `user-invocable-only` when built-ins are turned off; skills hidden behind a plugin are `off`. `skillOverrideLockOf(layers, skill)` answers whether the state can be changed here (`policy` / `flag` / `plugin` / `skill-author` / `reserved-name`).
|
|
63
|
+
- `skillsViewOf(listings, layers, trust)`: every skill with `name` / `layer` / `status` (`applied` or `excluded` with `reason`: `overridden` / `model_invocation_off` / `untrusted` / `unconfirmed` / `shadowed`) / `description` (only when the header states one and the skill reaches the model in full) / `nameOnly` / `effective` / `editable`, plus the count of withheld roots. Roots under a project or an additional directory need a trusted verdict; without one their skills are `untrusted` or `unconfirmed` and do not shadow anything.
|
|
64
|
+
- `skillOverrideWritePlan(edit, context)` + `skillsSetEditOf` / `skillsClearEditOf`: a state change writes the local layer when a workspace is open (`scope: 'local'`, the same key and file the terminal writes) and the user layer otherwise (`scope: 'user'`); it writes only the difference from the layers below, migrates bare-name keys, keeps sibling MCP skills' states when a shared label key is removed, and after the write reports the deciding layer (`decided_by`, or `shadowed_by` when a higher layer still decides). A locked state is refused with one of four new reasons (`skill_locked_by_higher_layer` / `skill_managed_by_plugin` / `skill_locked_by_author` / `skill_name_unstorable`), each with its sentence in both languages. A skill that is not in the supplied loaded-skill context (`context.subjects`) is refused with `not_found` instead of being guessed as a directory skill; `skillsClearEditOf` returns `undefined` for an entry whose editable verdict is locked or unreadable; the baseline below a write layer reads only enabled layers (a disabled local layer does not count when the user layer is written). `skillCreatePlan` / `skillRemovePlan` are typed now and answer `pending` until the next window.
|
|
65
|
+
- Seat: read capability `skills` (verb `listSkills`) and write capability `skillsEdit` (verb `editSkills`); both outbound shapes are closed. `editSkills` answers `{ receipt }` with the kernel receipt as is, the same envelope as `editModelPool` and `editMcpServer`.
|
|
66
|
+
- `skillCommandsToSpecs(…, { skillOverrides })`: when the host passes the settings layers, a skill whose effective state is `off` or `user-invocable-only` is not sent and a `name-only` skill is sent with an empty description — the same answer as the view, so a skill turned off in one client is not sent by another. Without the option the output is byte-identical to 0.111.0.
|
|
67
|
+
- **Breaking (narrow):** `SeatCapabilityName` gains `skills` and `skillsEdit`; `LocalSessionsApi` gains `listSkills` and `editSkills`; `LocalConfigRefusal` gains four words (exhaustive `switch` / `Record` over these unions turns red once).
|
|
68
|
+
- **模型池与档位(CC-828;接入文档 §141 MP-1 – MP-13)**:新增模型池纯计划口 `poolWritePlan(edit, modelsDoc, settingsDoc, effectiveEnv)`(两份文档进、两份文档出;意图闭集 `MODEL_POOL_EDIT_KINDS` 十二词(第十二词 `sweepOrphanKeySlots` 见下方「模型池余项」条):`add`〔批量;任一条结构性拒 ⇒ 整次拒并逐条列因;存不存逐条只问写不写律 `onboardWriteVerdict`:探活证明配置错 ⇒ 拒 `probe_failed`,说不出判决或没探过且请求未显式 `acceptUnverified` ⇒ 拒 `probe_unverified`,显式接受才存;条目验证状态三态 `probe`(`MODEL_POOL_PROBE_STATES`:`verified` / `unverified` / `unprobed`);`credential: { kind: 'none' }` 无钥本地条目不写钥匙槽,能否发出由引擎配对判官按无钥律判〕/ `update`〔显示名 / 看图表态 / 两只上限〕/ `remove`〔仍被缺省模型 / 角色 / 旧编组引用 ⇒ `entry_in_use`;档位绑定与 @ 名单随之撤,后果在 `warnings`〕/ `setDefault`〔只写 `roles.default`〕/ `importEnvModels` / `importChannel` / `bindTier` / `switchTierGroup` / `addTierGroup` / `removeTierGroup` / `migrateTierGroups`〔把用户设置里的旧档位两键一次性迁进模型目录并删旧键,幂等〕);内核意图包装 `modelPoolIntentOf` 与一次编辑的编排 `editModelPoolWith`(多文件 = 单文件提交序列:加 = 准备步只写没有条目引用的钥匙槽 → 效果步写目录条目、把条目切到这只槽 → 收尾步删换钥匙换下、已零引用的旧槽;删反序;残留 `orphan_key_slot` / `legacy_tier_groups_left` 照实回执;效果步锁内复核准备步落下的名,提交时恒核准备步的修订号钉,只有预演不核);视图 `modelPoolViewOf`(零钥匙值;读不懂的条目计数并标 `catalog_incomplete`;预设注册入口取本包预设单表)、有效缺省读口 `effectiveDefaultModelOf`(只认条目过滤律读得懂的启用条目,与视图同读、同入参;`roles.default` 在场胜于老结构键 `default`;设置文件顶层 `model` 遮蔽时带 `shadowed_by` 披露;目录读不出 / 缺省位读不懂答 `unknown` 臂,不是 `none`)、每行改动构造口 `modelPoolRowEditOf`、座位编辑换算 `modelPoolEditOfSeat`、渠道探测读取器 `channelProfilesOf`(四源;`importChannel` 落下条目的输出上限只取档案声明值或预设精确表的确证上限,家族参考值不写)、模型发现 `discoverEndpointModels`。**行为变化**:缺省模型只经 `setDefault`、`add` 显式选缺省与缺省模型唯一律(`add` / `importChannel` 未给 `defaultIndex` 时;见下方「模型池余项」条)改动,其余池写都不改缺省模型;老结构键 `default` 只由会写缺省位的四个意图(`add` / `importChannel` / `setDefault` / `migrateTierGroups`)落成 `roles.default`(缺省位读不懂 ⇒ 原样不动),其余编辑原样保留。单条接入写入计划 `onboardWritePlan` 改为 `add` 一条的薄壳(入参 / 答形 / 拒因词不变;退役登记 RL-8281);🔴 行为变:重配同一条目而钥匙换了 ⇒ 另铸新槽、旧槽原样留在用户设置 env 里(0.111.0 原位改写那只槽的值;薄壳没有收尾步,旧槽计入视图 `orphanKeySlots`,由 `sweepOrphanKeySlots` 删),钥匙没换 ⇒ 沿用原槽、零写。内核拒因表尾加 `entry_in_use` / `credential_unpaired` / `env_catalog_present` / `probe_failed` / `probe_unverified`(各一句两语)。座位:能力位 `modelPool`(`listModelPool` / `discoverModels`)与 `modelPoolEdit`(`editModelPool({ edit, dryRun? })`);`listModelPool` 答视图本身或内核 `unavailable` 臂 `{ kind: 'unavailable', cause }`(三只本地配置列表动词同一形);`probeOnboardEntry` 结局加可缺 `firstOutputMs`;`OnboardProviderRow` 加可缺 `signupUrl`;`applyOnboardEntry` 登退役(RL-8282),`applyModelConfig`(RL-171)取代件改为 `editModelPool`。在线目录:回体读口丢掉的行数随目录走(`LiveModelCatalog.unreadableRows`,`> 0` 才在场),受理判官在读不全的目录上答 `unknown{catalog_incomplete}`(CC-1229)。
|
|
69
|
+
- **模型配置缺席项 → 归因句 `modelConfigGapNotice(missing, lang?)` + 型 `ModelConfigGap` / `ModelConfigGapNotice` / `ModelConfigPart` / `ModelConfigKeyChannel`**(CC-1465;**§141 MG-1 – MG-5**;型面加性:根入口运行期 +1、型 +4;消息目录 +18 键 `model.configGap.*`):`{ parts, keyChannel?, catalogEntries? }`(缺的件:模型名 / 网关地址 / 钥匙;钥匙带车道、目录带受影响的启用条目数)⇒ 三态结果 `{ kind: 'gap', head, detail }` / `{ kind: 'none' }`(`parts` 空:没有缺席,不编句)/ `{ kind: 'malformed' }`(`parts` 读不成无重复的件词数组:读不出缺什么 ≠ 什么都不缺)。`head` 是一个短语(「no API key is configured」),`detail` 是一句缘由(列出缺的件与它们在引擎里的设置名;模型名缺席时说引擎没有模型名不会启动;带钥匙车道 / 条目数时点名受影响的目录条目);en / zh 同一目录键族,`lang` 缺省英文。「零配置闸 / 交互提交拒句 / `/status` 模型行 / 首启重提议 / doctor 网关地址缺失行」同读这一口、只差取 `head` 还是 `detail`,不再各铸各的「no model name」。可选位缺席 / 表外词 / 坏数 ⇒ 当没报,句子不提;只认自有数据位,永不抛。
|
|
70
|
+
- **决断拒收读数多一位出路词 `wayOut`(`cancel_run` / `newer_worker`)与它的出路句口**(CC-1457;**§141 S7149-2**):服务端 7.149.0 起,引擎判「这台引擎续不了这张卡」的 409 拒体带一只机读出路词 —— `cancel_run`(这张卡在这台引擎上不收任何决定,出路只有取消这一跑)/ `newer_worker`(行写自更新的引擎,不低于那一版的执行端续得了它,卡仍待决)。`readDecisionRefusalReading` / 决断腿冻结的读数与 `classifyDecisionRefusal` 的分类各多一位 `wayOut?`(present-iff:状态 409 ∧ 词恰是闭集二词;别的状态 / 表外词 / 坏形 ⇒ 缺席,不编)。出路句口 `decisionRefusalWayOutContent(wayOut, lang?)` 与待决行判决的出路句**同一句口**:`newer_worker` = 判决 `lacking` 那一句(由更新版本的引擎续跑),`cancel_run` = 「这里决不了 —— 取消这一跑」;目录零新句。型 `DecisionRefusalWayOut`。
|
|
71
|
+
- **模型行视图多一位窗口来源 `contextWindowSource`**(CC-1458;**§141 S7149-3**):`liveModelRowsOf` 的行在带 `contextWindow` 时多 `contextWindowSource: 'declared' | 'assumed' | 'unknown'`(型 `ContextWindowSource`)。服务端 7.149.0 起 `GET /v1/models` 标出窗口是声明的还是引擎假定的(假定窗 7.149.0 起 131072);行上没有来源位(更早的服务端)/ 表外词 ⇒ `unknown`,**不是** `declared`。数照旧在 `contextWindow`。
|
|
72
|
+
- **终局结果的读拒地板披露读口 `readDenyFloorOf(result)`**(CC-1458;**§141 S7149-4**):服务端 7.149.0 起,一条 run 照跑了而读拒规则不按字节守时,终局结果多 `readDenyFloor: { code, message }`。读口三态:`unkept`(带服务端那一句)/ `not_reported` / `unreadable`(型 `ReadDenyFloorReading`)。🔴 `not_reported` **不是**「读拒被守住了」:run 没起跑、读拒表空、执行环境守地板、更早的服务端,四种都读这一臂。
|
|
73
|
+
- **本机引擎凭据的归属证明时刻判官 `engineCredentialReleaseVerdictOf(input)` · 工厂 `makeLocalEngineWireClient(cfg)` · 不出示原因闭集 `ENGINE_CREDENTIAL_WITHHOLD_REASONS`**(CC-1466;**§141 AO-1 – AO-5**;型面加性:根入口运行期 +3、型 +7):本机引擎的凭据只走开于「这一代引擎的归属被证明之后」的连接。两种传输够格:每发新开一条连接、答完即关(`reuse: 'none'`);或证明之后才开、绑着同一代引擎的池(`reuse: 'generation'`,`boundTo` 与被证明的那一代同一,且 `openedAt ≥ match.provenAt`)。不声明传输(即缺省全局连接池)、声明了却交全局 `fetch`、归属读不出或不符 ⇒ 一律不出示:请求照发(匿名),判词带 `identity: 'unproven'` 与原因,池换代或早于证明时带 `retireTransport: true`。归属读数由宿主交(三臂 `match{identity, provenAt?}` / `mismatch{which}` / `unreadable`,`which` 取本机引擎判官 `stranger` 臂的同一词表),同代比较只走 `engineIdentityVerdict`。工厂先判后造,仍只经 `makeEngineWireClient` 一个构造点;入参各位(归属读数、传输声明及其各位)只采样一次、冻结成快照,判词与造出的客户端读同一份 —— 令牌只在判词 `present` 且快照里有声明的传输时上线,并且只走那只传输。附着别的进程起的引擎时,诊断能力探针 / 侧信道读口 / 后台任务探针三处带凭据的出站应改经这只工厂;本包内没有调用点,接线是终端接入方的义务(见接入文档 §141 AOy ②)。缺席不推出「是这一台」;取值器不执行、敌意入参不抛。
|
|
74
|
+
- **控制台 CA 钉的判定与规范化 `readCenterAddress` / `trustOriginOf` / `caFingerprintsOf` / `caFingerprintOfDer` / `caFingerprintDisplay` / `readCaBootstrapBody` / `caBootstrapOpen` / `caBootstrapStep` / `caPinRefusalSentence` · 常量 `CA_PIN_LIMITS` · 型 `CenterAddressSeat` / `CenterAddressRefusal` / `CenterAddressReading` / `TrustOriginRefusal` / `TrustOriginReading` / `CaFingerprintsRefusal` / `CaFingerprintsReading` / `CaCertificateParser` / `CaCertificateFacts` / `CaBootstrapRequest` / `CaServedCertificate` / `CaBootstrapRefusal` / `CaBootstrapReading` / `CaBootstrapPhase` / `CaBootstrapStopReason` / `CaBootstrapStop` / `CaBootstrapDecision` / `CaBootstrapState` / `CaBootstrapEvent` / `CaBootstrapStep` / `CaPinRefusal`**(CC-1241;**§141 CA-1 – CA-9**;型面加性:根入口运行期 +10、型 +21;消息目录新域 `centerTrust`,41 键):地址判官一只、两座位 —— 邀请链接(一律 `https://`、路径只许空或 `/`、片段只许 `ca=<规范指纹>[,…]`)与手输中心地址(`http://` 只许本机、路径按中继路径律、不许片段);成功臂带 TLS 钉键 `origin`(scheme + host + port)与签发中心键 `centerKey`(origin + 去尾斜杠的路径,与会话映射的命名空间键同一读法)。`trustOriginOf` 把交给传输的最终 URL(含 `ws://` / `wss://`)读成钉键。指纹恒为整张证书 DER 的 SHA-256、拼写 = 设置契约的 `sha256:` + 64 小写 hex;旗入口另收大写 / 冒号形并折叠。证书集判官收应答体原始字节与宿主交的平台解析端口:每张 `pem` 必须逐字节等于它自己 DER 的规范 PEM、DER 长度形规范;端口读数用 `raw` 逐字节绑在这份字节上;served 内部同指纹整次拒;点名指纹必须在 served 里且自签。取证书重试计划:1 + 3 次、单调钟 120 s 预算,`Retry-After` 是下限(> 60 s 或越预算即停、不夹),缺席即停;宿主存回的终态判词逐位验形后按自有数据位重铸(决定词不是 `stop` / 停因表外 / 附加位缺多坏 ⇒ `stop bad_input`,不原样交回)。拒因句:40 个拒因词各一句(en / zh),只说规则与数(数取 `CA_PIN_LIMITS`)、不回显输入;词表外答通用句。全部纯函数:零 fs / 网络 / 读钟 / 随机 / 定时器,永不抛。
|
|
75
|
+
- **One outbound shape for local configuration results (§141 LCO).** The kernel receipt (four arms or the dry-run `preview`) is checked by one closed-shape rule wherever it leaves the host: the model pool, skills and MCP write verbs all answer `{ receipt, …pages }` and agree on every receipt, and the three list verbs answer their view or the kernel `unavailable` arm (`{ kind: 'unavailable', cause }`). Shapes the kernel never mints are refused at the seat: a `preview` whose `writes` names a read-only file or contradicts `changed`, an empty `detail`, an empty `residue` or `disclosures`. Guard: `run-seat-carriers-test.mjs` (C9).
|
|
76
|
+
|
|
77
|
+
### Changed
|
|
78
|
+
|
|
79
|
+
- 设置契约换钉 18.0.0 → 25.1.0(接入文档 **§141 SS25-1 / SS25-4 – SS25-9**):开发依赖 `^18.0.0` → `^25.1.0`(lock 钉 25.1.0);构建期生成物重生成 18 只 —— 16 只仅「源」注释行的版本号,2 只有内容:hook 条目判官抄本与型镜像。公面导出、型面、对外 peer、运行期依赖都不动;换钉前编译红 0。生成器的型镜像登记内建多收 `Readonly`(上游 hook 条目字段表的声明型用到它;少登记一名生成器拒生成并点名)。
|
|
80
|
+
- hook 条目判官抄本承运的键变多(设置契约 19.0.0 / 20.0.0;接入文档 **§141 SS25-2 / SS25-3**):command 条目 `args`(字符串数组)· `onFailure`(`continue` / `block`)· `rewakeMessage` / `rewakeSummary`(非空串)· `cloud`(不判值),http 条目 `onFailure` · `cloud`,prompt 条目 `continueOnBlock`(布尔)。这些键的坏值自此是坏块(与上游判官同答:守卫事件整份拒、非守卫事件剔那一条)。设置文件里 command 条目的 `args` 不是字符串数组(含 `null`)的条目,由「exec 形闸拿掉 / `null` 照发」改为判官判坏块(非守卫事件剔件、守卫事件整份拒)。
|
|
81
|
+
- 服务端 hooks 读者代际表(7.139.0 – 7.146.x 一行;接入文档 **§141 SS25-3**)的不读键由 `onFailure` 一个扩到五个:+`rewakeMessage` / `rewakeSummary` / `cloud` / `continueOnBlock` —— 抄本新承运这四键后不扩则在这一代服务端上照投、新提交整条 400;扩后这四键仍按 `key_not_read` 拿掉,请求体与换钉前同答。未登记的更高代际 / 版本读不出 ⇒ 最保守行(各代不读键的并集 = 五键)。
|
|
82
|
+
- **拒体带出路词的决断拒收不再读作「稍后原样再送」**(CC-1457;**§141 S7149-2**;🔴 行为变):`wayOut` 在场 ⇒ 读数 / 分类不铸 `transient`(与技能授予变了、行自己的拒、引擎复活不了同一条律);`newer_worker` ⇒ `decisionRefusalClosesOut` 不收口(那张卡在更新的执行端上续得了,在这里停下这一跑等于放弃它),`cancel_run` 照常。服务端 7.149.0 上受影响的是 `checkpoint.unsupported_version`(拒体照带 `retriable: true`)那一形:修前读作瞬时。词缺席(更早的服务端)⇒ 读数与修前逐位同。
|
|
83
|
+
- **停驻审批收场句按引擎的出路词给出路**(CC-1457;**§141 S7149-2**;🔴 文案变):拒收读数带 `newer_worker` ⇒ 收场句尾接「由更新版本的引擎续跑」那一句(新目录键 `approval.park.newerWorker`,内嵌与判决 `lacking` 同一句);带 `cancel_run` ⇒ 取消专句。词缺席 ⇒ 修前按码族推断的那一句逐字节不变。
|
|
84
|
+
- **停驻被拒族那一句按同一出路词改口**(CC-1457;**§141 S7149-2**;🔴 文案变,只在交入出路词时):`refusedParkContent` 入参多一位 `wayOut?`(原样交同一只错误的 `readDecisionRefusalReading(err).wayOut`;本口不另读拒体)。`newer_worker` ∧ 卡未结掉 ⇒ 出路半句改成与停驻收场句同一句口(「更新版本的引擎续得了它」;`print` 车道仍附取消动词),`checkpoint.unsupported_version` 的为什么半句改说「由更新的引擎版本停驻」(修前举例「更早的版本」)。不交 / `cancel_run` / 表外词 / 那一跑已结掉 ⇒ 与修前逐字节同。修前同一张卡上,收场句说「由更新版本的引擎续跑」而这一句说「取消再另起」。
|
|
85
|
+
- **「原样重发改不了判」的码表读类型包那一份**(CC-1458;**§141 S7149-5**;🔴 行为变,一码):失败呈现的「不给重试」码表改读类型包 `NON_RETRYABLE_CODES` 的构建期快照(修前是本包手写的六码);类型包 38.1.0 起表里多 `internal.org_delivery_quota_unreadable`(跨主体投递口读不出配额状态,修好之前每次投递都被拒)⇒ 这一码在 500 上不再给「再试一次」。同口的 429 `org_delivery.rate_limited` 照旧给重试,等待窗头源优先、头被剥掉时读体上的 `retryAfterSec`。
|
|
86
|
+
- **MCP 断言头「不发送」那一句的版本射程改说到 7.149.0**(CC-1458;**§141 S7149-0**):`mcpAssertionHeaderNotSentNotice` 的句子由「server versions up to 7.148.0 accept this setting but do not send the header」改为「up to 7.149.0」—— 服务端 7.149.0 的处置表仍为 `withheld`(只受理、不把这一位交给引擎);读法与出句条件不变。
|
|
87
|
+
- **门夹具现役服务端 7.148.0 → 7.149.0;开发依赖类型包 `@sema-agent/sdk` 38.0.0 → 38.1.0**(CC-1458;**§141 S7149-0 / S7149-1**;peer 地板 `>=25.0.0` 与支持底线不动):服务端 registry `dist.shasum` `06b03abf22cbd37566df953fea2f06815dc5db96`、`gitHead` `4ddd53ff8ba95bf63354b58203d01db51e025795`(随包精确钉引擎 7.66.0 / 设置契约 24.0.0);类型包 `dist.shasum` `78f92a6b5df8e424e55bfef6f0c480cb752e2cf7`。
|
|
88
|
+
- **模型池余项:迁移合并律 · 孤儿钥匙槽清扫 · 缺省模型唯一律**(CC-1460;**§141 MX-1 – MX-9**;🔴 行为变,三件同模块):① **迁移合并律**:`migrateTierGroups` 修前在模型目录已有档位组时只删旧两键、不合并(旧私键里独有的组随之消失);现改为并入 —— 旧键独有的组并入目录的档位组表(目录里读不懂的项原样留着),同名组按目录为准、旧组不拷,**内容真不同**的同名组名进 `applied.disclosures` / `preview.disclosures` 的新披露词 `tier_group_overridden`(`layer: 'models'`,`detail` = 逗号分隔的组名;`localConfigDisclosureSentence` 两语句、附言缺席走通句),同名同绑定 = 上一次迁移已拷过 ⇒ 静默(幂等);活动组与缺省模型只在目录原本没有任何档位组时由旧键定;`roles.default` 只在缺省位缺席时物化(读不懂 ≠ 缺席,不覆盖);收尾步删旧两键前重算,两步之间旧键又多了没并入的组 ⇒ 不删、残留 `legacy_tier_groups_left`(再跑一次迁移即并入)。② **孤儿钥匙槽清扫**:`MODEL_POOL_EDIT_KINDS` 追加第十二词 `sweepOrphanKeySlots`(`{ kind: 'sweepOrphanKeySlots' }`,座位入站判官同收):用户设置 env 里名带钥匙槽前缀、值是字串、且没有任何目录条目(含停用的)引用的键整只删;单步写用户设置、同一把锁里锁住模型目录现读,零引用才删;目录读不全(整份读不出 / 有不是对象的项)⇒ 拒 `scope_unreadable`;下次引擎启动生效。`ModelPoolView` 新增必有字段 `orphanKeySlots`(个数,没有孤儿 = `0`,与清扫计划同一读法;座位出站判官新增该必选键)。③ **缺省模型唯一律**:新导出 `defaultModelChoiceOf(existing, batch, declined?)` ⇒ `{ kind: 'pick', index } | { kind: 'unchanged', reason }`(缘由闭集 `MODEL_POOL_DEFAULT_KEEP_REASONS`);`add` / `importChannel` 没给 `defaultIndex` 时只问它:已有有效缺省(`roles.default` 点名且在 / `{ select }` / 活动档位组绑定;仅靠「第一条启用条目」兜底的不算)⇒ 不动;有效缺省读口答 `unknown` ⇒ 不动(`existing_unknown`);没有 ⇒ 本批第一条验证状态 `verified` 的;都没有 ⇒ 不设(不写 `roles.default`,也不清它);显式 `defaultIndex` 仍最大;单条接入薄壳 `makeDefault: false` = 显式不选(律不介入)。公面运行期 +2(`defaultModelChoiceOf` / `MODEL_POOL_DEFAULT_KEEP_REASONS`),型 +3(`DefaultModelBatchRow` / `DefaultModelChoice` / `ModelPoolDefaultKeepReason`)。
|
|
89
|
+
- 引擎地址规范化口 `normalizeEngineBaseUrl` 的 `http(s)://` 字面前缀与 query / fragment 两判改调设置契约的同一只判官(构建期生成物;CC-1241;**§141 CAy ②**;零行为变);对任何输入答案不变(门对修前原式各 6000+ 串差分零分歧)。
|
|
90
|
+
- **店持久性只剩能力面一只读口;`readEngineHealthStore` / `EngineHealthStoreReading` 退出公面**(CC-1461;**§141 OR-1 / OR-2**;🔴 型面 BREAKING:根入口运行期 −1、型 −1):服务端 7.148.0 起 `/health.store.durability` 与 `GET /v1/capabilities` 的 `store.durability` 是同一只装配值、同一次求值的两份投影 —— 同一事实。本包只读能力面那一张(`projectStorePostureCapability` / `observedStorePosture` / `storePersistence` / `storePostureDoctorDetail` / `storePostureHeadWord`):它多带声明后端、装配后端与降级成因,且匿名读者的 `/health` 不含 `store`。0.111.0 的 `/health` 店持久性读口删(退役登记 RL-14611);能力面还没落地时读口答 `unobserved`,不回落健康面。
|
|
91
|
+
- **引擎不可用行的「有没有应答」改收探活判决;上一台没停完是第九臂 `previous_not_stopped`**(CC-1462;**§141 OR-3 – OR-5**;🔴 型面 BREAKING:`EngineUnavailableFacts.answer` 由三词改为 `HealthProbeVerdict`;闭集 `ENGINE_UNAVAILABLE_REASONS` 追加一词):`answer` 原样交 `classifyHealthProbe` / `latestSegmentHealthAnswer` 的产物 —— `unanswered` ⇒「没应答」头 + 等它应答,`answered_not_ok` / `answered_ok` / 缺席 / 坏形 ⇒ 两形都真的中性句。判决对象只经一只读法认(与 `healthAnswerClause` 同调:同一份判决两口同词,坏形两口同拒)。0.111.0 的 `silent` / `answered` / `drain-stuck` 三词退役(退役登记 RL-14621;作 `answer` 交入 ⇒ 与缺席同答);「上一台引擎被要求停下、等满仍没退」改走臂 `previous_not_stopped`(头句「the previous sema engine has not finished stopping」与「等它退出」出路与 0.111.0 逐字同,机读位改写这一臂词)。
|
|
92
|
+
- **被挡终局句的第三方话超长时接省略标记 `…`**(CC-1463;**§141 OR-6**;🔴 文案变,只在 > 1000 码元时):封长改经包内共享截断规则 —— 与失败原因展示、通告句说明位同一条规则(截到封长再接 `…`,标记在封长之外)。≤ 1000 码元逐字节不变。
|
|
93
|
+
- **运行账快照判「读流器耗尽」只问读流器那一只读口**(CC-1397;🔴 行为窄化):`readRunLedgerSnapshot` 不再按 `name` 宽读 —— 名字只在原型链 / 自有访问器上的对象不再当「读完」证据(⇒ 快照读不出);真类实例被改名仍算,跨打包重建形(自有数据位同名)照旧。
|
|
94
|
+
- **`isHitlSafetyErrorLike` 的 `name` 读法并入决断出口读口**(CC-1397;**§141 IH-1**;🔴 行为窄化):只认自有数据位,只在原型链上的名不算、访问器不执行、已撤销代理不抛;函数入参仍不判。真类实例与跨打包重建形照旧命中。
|
|
95
|
+
- **引擎拒码字面改取常量**(CC-1402;零行为变):`limit.rate_exceeded` / `gone.ask` / `checkpoint.unsupported_version` / `checkpoint.invalid_outcome` / `capability.operator_principals_required` / `internal.memory_control_plane_corrupt` / `corrupt` / `draining` 十五处改读常量;`AskGoneDetail.code` / `CheckpointUnsupportedVersionDetail.code` 的声明文本变 `typeof 常量`,字面类型不变。
|
|
96
|
+
- **本地写的 allow 规则「会不会生效」与卡上「本地整工具」一行改问同一只判官**(CC-1420;**§141 LA2-1 – LA2-4**;🔴 行为变 + 型面加性):修前 `localAllowRuleEnforceable(rule, caps)` 与 `standingRowsOf` 的本地整工具一行只按规则形判(装配判官收不收这条 allow),不问规则落在哪一设置层、店里有没有同意 —— 写进本地 / 项目设置层的 allow 自身够不着 allow 地板(上游层准入答 `below_trust_floor`),却被判「可执行」「可给这一行」,与 `localAllowRedeemability`(CC-1412)对同一问题答两个答案。现在两处都经包内共用子判官把落点读数交 `localAllowRedeemability`(`declared` 主语,规则文本 = 要写的规则 / 卡上工具名):`localAllowRuleEnforceable(rule, caps, landing?)` 多可选第三参 `landing`(落点读数 `LocalAllowDeclaredFacts` = 设置层 / 工作区信任 / 托管开关 / 作用域根 / 规则店列举结局),读数多一位 `redemption`(判官判词原样),`enforceable` ⇔ 规则形发得出 ∧ 判官答可兑付;`StandingRowsHostFacts` 多可选位 `wholeToolLanding`(同形),本地整工具一行在发送读数之后再问判官 —— 不可兑付 ⇒ 不给、理由 `redemption_closed`(三态 `refused`),判不出或落点读数缺席 ⇒ 不给、理由 `redemption_unknown`(三态 `unknown`);**不新增理由词**(沿用 CC-1412 的两词)。用户设置层 / 启动旗层 / 托管层自身放行 allow;本地 / 项目 / 他工具项目设置层只认店里的同意。只传两参 / 不交 `wholeToolLanding` 的旧调用方:`enforceable` 恒 `false`、本地整工具一行不给(放宽方向闭合)。公面:根入口 +1 型名 `LocalAllowDeclaredFacts`,运行期名数不变。
|
|
97
|
+
- **`-p` 车道「设置读不干净,allow 规则这一发没送」那一句整族进两语消息目录**(CC-1392;三端零动作;句字节不变):`permissionsAllowKeptNotice(report, settingsRead, facts?, lang?)` 多一只可选 `lang`;托管策略专句三形(拉取中 / 拉取失败 / 说不清)× 条数单复数与通用句 × 问题数 / 去处 / 读健康各形,整族住目录 `session.hostSettings.allowKept.*` 十五键(英 / 中),数字与宿主给的去处只作参数;缺省 `lang` 与显式 `'en'` 的英文逐字节与修前同、表外语言按英文,中文随宿主装的中文目录出句。裸英文句基线该文件摘要 7 → 0。
|
|
98
|
+
|
|
99
|
+
### Fixed
|
|
100
|
+
|
|
101
|
+
- **接入文档两句勘误 · 发布说明附录行数勘误**(CC-1475;**§141 ERR-1 / ERR-2**;零行为变、零型变):§140 已发段不动,由 141-ERR 取代两句 —— 140-HEy ② 的 `fresh` 铸源改为治理视图(`refilterHostSettings` 只收治理视图;锁存计划入参候 CC-1476);140-COa 首行射程句自指本段,改指「§139 及以前」。发布说明附录行数勘误:0.111.0 发布说明附录 C 为 114 行(原写 64 行)。
|
|
102
|
+
|
|
103
|
+
### Gates
|
|
104
|
+
|
|
105
|
+
- `run-hooks-unread-keys-projection-test.mjs`:抄本档位在 pre-ss19 / ss19+ 之外加 ss20+(U0d 钉抄本实际投影与档位一致,含 `continueOnBlock`)· U12a / U12b 期望由 `["onFailure"]` 改五键 · **U3 / U4 / U12e 的服务端读者夹具改取行内老一代**(修前取现役 7.147.0,它读这五键,负控前提不成立 ⇒ U3b 长红)· 新增 U12e2(代际表若标夹具这一代读 `rewakeMessage` ⇒ 夹具 400)· U12h(现役夹具读五键:原样投全受理 —— 代际表上边界的真读数)· U1k / U1k2(prompt 条目 `continueOnBlock` 按 `key_not_read` 拿掉、同组 command 条目照带);红先 = 代际表回单键 37 + 1 格红。
|
|
106
|
+
- `run-cloud-effective-projection-test.mjs` S13np0 / S13np / S13n / S13g / S13ip:判据自证与期望按已装设置契约主版本取 —— `readEffectiveWire` 对缺席 `a2a`:< 20 补空名单、≥ 20 保持缺席;铸点对带未知键对端:< 22 剥键装上并发 `unknown-keys-dropped`、≥ 22 整条丢并发 `entry-dropped`(`reasonCode: entry-unknown-key`);新增 S13i2(这一行走既有读数与措辞);原始体无键 ⇒ `absent` 两代都成立。
|
|
107
|
+
- `run-plugin-hooks-projection-test.mjs` D9 / D9b / D9c / D10 / D10b:设置文件路径的非数组 `args`(串 / 对象 / 数 / `null`)由判官接手 —— 非守卫事件剔那一条,守卫事件整份拒;D10 加 `args: undefined` 正控(照发、不拒)。
|
|
108
|
+
- `run-upstream-tables-test.mjs`:G23-5 独立样本池 +15 格(新取值类与新承运键的好值坏值,守卫与非守卫事件各有)· N24 负控的「未登记内建」例子换 `Required` + 新一格(登记内建少 `Readonly` ⇒ 拒生成并点名)。
|
|
109
|
+
- `run-settings-hooks-salvage-test.mjs` P2b:对照键由 `args`(判官 19.0.0 起承运)换成判官仍剥的手写 `plugin` 键,并钉判官投影是新对象。
|
|
110
|
+
- **新门 `run-engine-attach-ownership-test.mjs`**(CC-1466;117 格):公面 / 判官矩阵(归属三臂 × 传输声明 × 证明时刻)/ 三面 × 换代前后 × 证明时刻到 / 未到 / 判官同源(全矩阵 × 三面 ≡ 判官;替身判官恒出示 ⇒ 三面同时偏离)/ 缺省连接池零凭据 / 敌意入参 / 冻结 / sdk 探活选项位 / 入参一次采样(传输槽 / fetch 槽两次读答不同也不会让令牌走缺省出口;每个键恰读一次)/ 结构钉。
|
|
111
|
+
- `run-store-posture-durability-projection-test.mjs`:+SPD10(新一代夹具真 `/health` 路由与真 `projectStoreCapability` 对同一装配四形同值 · 两只铸点实参同一表达式 · 匿名 `/health` 无 `store` · 两面不一致构造格只有能力面一个答案 · 退役两名零复活)+ SPD8i / SPD8j(词读器值级读者恰能力面一只 · 健康读口文件零读 `store` 键);SPD7 夹具调用补 7.149.0 起必带的 local 声明位。
|
|
112
|
+
- `run-session-read-redaction-projection-test.mjs`:`/health` 店持久性读口各段删(SR0b / SR3i / SR5 / SR6 / SR7b / SR9b)。
|
|
113
|
+
- `run-engine-unavailable-line-test.mjs`:EU1 九词;EU5 子形改交判决、第九臂两格;+EU8(同一探活输入两口同词 · 坏形两口同拒 · 旧三词与缺席同答 · 第九臂机读位 · 源码零旧词 · 声明面 `answer` 型)。
|
|
114
|
+
- `run-prompt-blocked-sentence-projection-test.mjs`:PB9c / PB9d 超长带 `…`;PB6d / PB9j 改钉共享截断规则;+PB9k(两处封长读数 + 标记在场)。
|
|
115
|
+
- `run-gate-negative-controls-test.mjs`:+1 枚 `retirement-ledger-retired-anchor-revival`(植入 RL-14611 锚 ⇒ F 段红)。
|
|
116
|
+
- 目录语料 `cc1378`:`answer` 两条改交判决(摘要沿用)、第九臂两条新增。
|
|
117
|
+
- `run-run-ledger-snapshot-test.mjs` S38(读流器耗尽只认读口)· `run-selfheal-reopen-test.mjs` G4⑤(安全停判官 `name` 只认自有数据位)· `run-interrupt-refusal-note-test.mjs` IR6g / IR6h 扩面(拒码字面零并存,唯一码位读点走常量)· `run-memory-verbs-wire-test.mjs` F9 改形 · `run-sdk-33-pick-projection-test.mjs` SKa 缺席臂诚实跳段 + 负控 +1(CC-1397 / CC-1402 / CC-1469)。
|
|
118
|
+
- **新门 `run-console-ca-pin-test.mjs`**(CC-1241;§141 CA;324 格):A 地址(链接解析 / origin 规范化 / 形判官与规范指纹拼写取设置契约构建期抄本)· B 指纹(旗入口收拒表 / 整张 DER 的 SHA-256 对 node:crypto 与 X509 `fingerprint256` / 三种错哈法必不等 / 包内恰一份 SHA-256 实现)· C 证书集(真端口参考实现 / 集合律 / 规范 PEM 变体 / DER 长度律 / 端口绑定核验 / 取值器零执行 / 读钟与随机桩)· D 429 计划(注入单调钟六场景 / 早醒 / 超睡 / 取消 / 倒钟 / 终态粘住与存着的 stop 逐位验形并重铸 / 坏状态 / 随机事件序列性质格)· E 签发中心键 · F 收口零行为变(对修前原式抽样差分零分歧)· G 拒因句。
|
|
119
|
+
- **新门 `run-local-config-models-test.mjs`**(CC-828;§141 MP;158 格):模型池每次编辑 = 纯计划口包成内核单文件提交序列 —— MP1 供给面 · MP2 / MP3 批量 `add`(一次计划一次目录写;任一条结构性拒整次拒、逐条列因)· MP4 存不存只走唯一判官 · MP5 无钥本地条目 · MP6 `remove`(在用 ⇒ `entry_in_use`)· MP7 / MP8 缺省只写 `roles.default`、设缺省后池写不回滚 · MP9 / MP13 一次性迁移与故障注入步序(换钥匙三步:准备步只写没人引用的槽、收尾删旧槽;提交恒核准备步的修订号钉)· MP10 环境模型 · MP11 / MP12 终端现形当真值格(老结构键 `default` 只由会写缺省位的意图落规范形)· MP14 – MP19 视图 / 座位 / 探活与模型发现 / 在线目录读不全 / 渠道探测(导入上限不写家族参考值)/ 档位四意图。
|
|
120
|
+
- **新门 `run-local-config-skills-test.mjs`**(CC-1445;§141 SK2;179 格):S 供给面 · R 根表 × 工作目录形(`.claude` 在场也不读)· T 真值表十五行每行一正一反 · W 写层两形经真内核写律(差分 / 删键 / 锁拒 / 遮蔽披露 / 清键 / 下层只读启用的层 / 主语不在 ⇒ `not_found`)· V 视图与清键构造口(锁住 / 读不出不给)· P 投影同答(终端关掉的技能桌面 / 网页不发)· K 座位两只动词出站门 · C 新建 / 删除答 `pending` · X 结构钉。
|
|
121
|
+
- **新门 `run-model-config-gap-notice-test.mjs`**(CC-1465;§141 MG;76 格):缺席项归因句唯一判词口 —— G0 公面 / 型面与合成消费方真跑 tsc · G1 五面 × 三种缺法 × 两语三十格对独立参照模型与金样 · G2 可选位 · G3 无缺席 / 坏形分开答 · G4 永不抛 · G5 判词单源(五面同口、换目录键面全变、源文件零字面英文句、植入对照被抓)。
|
|
122
|
+
- **新门 `run-model-pool-migrate-sweep-test.mjs`**(CC-1460;§141 MX;111 格):MX0 供给面 · MM 迁移合并律(目录空 / 同名 / 独有三形 × 披露格,零静默丢;两步之间旧键新增的组 ⇒ 不删并残留)· MS 孤儿钥匙槽清扫(零引用删 / 有引用留 / 读不全拒 / 步间别的写者无悬空引用)· MD 缺省模型唯一律与有效缺省读口(表驱动对拍、替身律对拍判红;视图与计划同读、新字段胜、读不懂答 `unknown` 且不被覆盖)。
|
|
123
|
+
- **新门 `run-server-7149-pick-projection-test.mjs`**(CC-1458 / CC-1457;§141 S7149;62 格):服务端 7.149.0 + 类型包 38.1.0 换钉读点 —— SP0 尺子自证 · SP1 夹具身份 · SPa 拒体出路词 · SPb 窗口来源 · SPc 读拒地板三态 · SPd 投递口两码 · SPe 新 503 两码 · SPf 404 ask ⇒ gone · SPg 处置表两向 · SPh 钉文件零诊断。
|
|
124
|
+
- `run-seat-carriers-test.mjs` +C9(§141 LCO;全门 213 格):本地配置三域出站形 —— 三只写门对同一份内核回执同收同拒 · MCP 结局视图带回执臂原样、拒写细节对得上拒因 · 三只列表门「此路不通」同一形 · 「测试连接」只判读车道(没有共享写锁的宿主照测、恰拨一次)。
|
|
125
|
+
- `run-onboard-judgement-test.mjs` OB4:重配同一条目而钥匙换了 ⇒ 另铸新槽、旧槽原样(钥匙没换 ⇒ 沿用原槽、零写)· `run-task-notification-entry-sampling-test.mjs` 采样口调用点名册收忠实采样口。
|
|
126
|
+
|
|
52
127
|
## 0.111.0(2026-11-09)
|
|
53
128
|
|
|
54
129
|
> 主题:中文消息目录改住子路径 `./i18n/zh`、根入口不再带中文表;宿主在装配根 `installMessageCatalog('zh', ZH_MESSAGES)` 一次(CC-1357;接入文档 **§140 EX-1 – EX-6**;🔴 型面 BREAKING:根入口退出 `ZH_MESSAGES`;行为变:未装中文目录的宿主渲 `'zh'` 得英文)‖ 包入口闭集收成一张登记表,B0 单例定论(CC-1022;**§140 EX-7**;零行为变) ‖ 座位契约两件 —— Quick Entry 快捷键读写动词 + 会话 hooks 名册只读动词(CC-1369;接入文档 **§140 QE-1 – QE-6 / HR-1 – HR-8**) ‖ 子代理模型词:代理准入判官 `subagentModelAdmissionOf` · 准入拒那一句 `subagentModelAdmissionLine` · 调用层当场拒那一句 `subagentModelCallRefusalReason` · 读数 `default` 一类 · 宿主断言词 `reads-this-config` · 引擎词表一张(CC-1362;接入文档 **§140 AM-1 – AM-7**;型面加性 + 型面加宽〔读数类别 +1〕+ 行为变:`default` 规范拼写、受理判官 `best` 说不清) ‖ 「永不抛」的抛出物字段读口上根入口 `thrownSlotOf` / `errnoCode`(CC-1370;接入文档 **§140 TS-1 – TS-4**;型面加性:根入口运行期 +2)‖ 场景卡技能清单能力位读器的读数改为模块级冻结单例,与根入口全部 `observed*` 读口同律(CC-1355;**§140 SC-1 / SC-2**;读数形零变)‖ `-p` 车道「托管策略还没拿到,allow 规则这一发没送」那一句按拉取态分三形(CC-1372;**§140 PK-1 – PK-5**;🔴 行为变:文字 —— 旧调用方不给拉取态位 ⇒ 得保守句,不再是原句) ‖ 人拒带说明位:工具结果行信封位 `_sema_refusal_noted` / 读口第五位 `refusalNoted` + 子代内容槽拒绝分类词与说明位(CC-1380 / CC-1381;接入文档 **§140 RN-1 – RN-6**;型面加性 + 行为变) ‖ 用户附件这一件怎么走 —— 唯一判官 attachmentRouteOf(工具相对这台机器在哪 × 附件腿 ⇒ 照附 / 照附带来源句 / 不附两因)、不附两因进「没带上」原因闭集、用户面原因句两语与来源句(CC-1389;接入文档 **§140 AR-1 – AR-6**;型面加性:根入口运行期 +5、型 +5;原因闭集加宽) ‖ 屏上决定卡的三个事实 —— 卡种 / 门实例身份 / 来源代,每种载体一只读口(CC-1373 / CC-1375;接入文档 **§140 SQ-1 – SQ-4**;加性) ‖ 换代两拍一只判官 `engineGenerationCardPlan` + 到期判定 + 金样(CC-1374;**§140 SQ-5 – SQ-7**;加性) ‖ 引擎决定判定 `screenCardsHoldEngineDecision`(CC-1375;**§140 SQ-8**;加性) ‖ 内置输出风格表下沉进包(CC-1340;接入文档 **§140 BO**;加性)‖ 排队用户行 `pending-<uuid>` 行形归包(CC-1337;接入文档 **§140 PU**;加性)‖ 停驻行卡 `parkRow.taskId` 退役(CC-1348;接入文档 **§140 CP**;🔴 型面 BREAKING,0.110.0 已预告)‖ 展示出口 query 区标签裸值止点成文句收口(CC-1300;接入文档 **§140 DQ**;字节不变) ‖ 「不再询问」本地落规则档兑付契约(LA;加性 + 行为变 + 🔴 型面 BREAKING 窄) ‖ 计划审阅卡卡事实的证据代 `evidenceRevision` + 过期卡判官 `planReviewEvidenceMovedOf`(CC-1400;接入文档 **§140 EG-1 – EG-4**;加性) ‖ 失败通知的原因位 `error` 两条来路一事一源(CC-1407;**§140 WF2-1 – WF2-3**;行为变:推送来路事实位多 `error`) ‖ 外来说明文本的封长规则只剩一份、量与引擎同(CC-1409;**§140 TR-1 – TR-3**;行为变:截断处整段多一码元) ‖ workflow 完成的取件位补充(CC-1422;**§140 WD-1 – WD-5**;行为变:轮询先交时,同一次完成带取件位的补投帧补一件取件位通知) ‖ 耐久审批门通告事实读口的来源词 `source` 改与成因词 `cause` 同形的开集读法(CC-1356;接入文档 **§140 NC-1 – NC-3**) ‖ 会话成本读口 `sessionCostReadingOf` · 分叉种子 `forkSeedCostOf` · 逐轮读数 `turnCostReadingOf` / `runCostSettlementOf` · 值级端口第二十六 / 二十七件 `accountRowOfResult` / `foldAccount`(CC-1008 A 件;接入文档 **§140 CO-1 – CO-8**;🔴 型面 BREAKING:完整型端口袋 +2 必填成员) ‖ 记忆暴露通告开头句回到平话(CC-1456;接入文档 **§140 MP-1**;行为变:文字) ‖ `settings.env` 随最终 hooks 重算,补入条目点名的名补上(CC-1421;**§140 HE-1 – HE-3**;🔴 行为变:139-HE-10 成文改口) ‖ 引擎改指口列表口工厂形 + 连续性证据绑地址对 + 接线错不可重试(CC-1408;**§140 RP3-1 – RP3-3**;🔴 型面 BREAKING) ‖ 交易句随界面语言(**§140 MR2-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.112.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
|
|
@@ -535,7 +535,7 @@ guard still cross-checks the table by name).
|
|
|
535
535
|
| `scripts/run-rewind-engine-action-test.mjs` | The two pure judgements the terminal client used to keep for its rewind command. The dispatch gate says whether, right now, the engine has explicitly said that a given rewind mode cannot be done: each of the three modes (rewind with code restore, rewind the conversation only, restore code only) reads the same availability judges the package already ships for the menu, only an explicit off refuses, and a missing, unreadable or unobserved reading never refuses. The action judgement takes the chosen option, the target position the host has already resolved (session root, after the root, or undecidable, with the engine entry handle if there is one) and the capability reading, and answers whether to arm the one-shot rewind keys, to reopen the engine session (the two modes that carry a resume point, chosen at the session root, which the server will not rewind past) or to do nothing, with a reason; an undecidable position never acts in either direction, and the code-only mode looks only at the handle. The preview used by the confirmation screen is the same answer's kind. The guard checks both judgements against hand-written truth tables over every bit combination and every target shape, that the dispatch gate and the menu can never disagree, that the default reading follows the current engine target, that hostile inputs never throw and never act, and that the module keeps no mode list or resume-point list of its own. A live comparison against the terminal client's own copies runs in the layering guard. |
|
|
536
536
|
| `scripts/run-tool-result-content-projection-test.mjs` | How a tool's result body becomes the content of the tool result in the transcript. A result that carries images keeps them: each image whose data is a string and whose type is supported (JPEG, PNG, GIF or WebP) appears as an image block with exactly the bytes the engine sent (the data is not re-validated, matching the reference client), in order, in both the interactive and the print output, while the structured result next to it stays the same text as before. A block that cannot be shown (an image without string data or with an unsupported type, or a block of an unknown kind) is left out and the content ends with one notice saying that unsupported content was omitted, so nothing disappears silently. Plain text and text-only results are unchanged strings, a body the engine already shortened stays a string with the truncation note, and an error result's content is always text. The text readings of a result body (the flattening helpers and the subagent viewer's result slot) come from the same projection and agree with each other. That projection is also the one text reading behind the public `toolEndOutputText` (an empty block list reads as an empty string, an image as `[image]`, an object that is not a string or a block list as absent) and behind the classifier-denial and aborted-call checks, so a frame that carries an image or an unreadable block is never mistaken for one of those engine-minted bodies, and a classifier denial is recognised only when it arrives as a bare string or a single block (a signature split across blocks is not a denial). Whether a result is an error is decided once for both the interactive and the print output: a structured result reporting a failing exit code is an error in both, whatever the tool's name and even when the result carries no body. The task-output tool's content is the model-facing text in both outputs, with the structured task record kept beside it. A result block that reports a media item as not delivered (a descriptor with the media type, an optional MIME type and the decoded byte count, or a summary block with the number of folded blocks and their total bytes) is shown as one sentence at its own position instead of being swallowed by the single unsupported-content notice, and a block whose fields are malformed stays an unreadable block. The same judgement is public: `toolOutputMediaAbsenceOf` reads such a block and `toolOutputMediaAbsenceSentence` gives its sentence in English or Chinese. |
|
|
537
537
|
| `scripts/run-refused-park-family-test.mjs` | The refused-resume family (`refusedParkFromError`, `refusedParkContent`, `refusedParkBlockedContent`): three 409 codes whose refusal comes back every time the same decision is sent again (the stored park is not supported by this engine version, its resource ledger carries a retired wall-clock allowance, or the engine's gate refuses its stored task configuration or permission-mode seed). The suite checks the reader on SDK error objects and on flattened failure facts (status policy, field token, still-pending reading, getters that throw), compares every sentence byte for byte against a frozen copy of the terminal's previous implementation over each combination of code, field, pending state, lane and run id, pins the deliberate differences one by one, and checks that the sentences are correct per lane, never print an unknown code, pass the package hygiene list and do not trip the already-resolved word scan. Since 0.108.0 the interactive way-out sentence holds for both engine generations: send a message and the client offers to cancel the run, answering the card first if it comes back instead (en / zh). |
|
|
538
|
-
| `scripts/run-prompt-blocked-sentence-projection-test.mjs` | The sentence for a run whose first prompt was held back by a deployment's `userPromptSubmit` hook. The engine frames its own explanation for the model in an envelope that carries the session's reminder mark, and the terminal row used to print that envelope verbatim (`Run blocked: <system-reminder mark="…">…`) while the machine-readable cause beside it went unread. The package now has one sentence-maker for the `blocked` terminal, shared by the terminal row and the result frame's first error: a hook that refused the prompt reads `UserPromptSubmit operation blocked by hook:` followed by the hook's own words (treated as untrusted text — control and bidirectional characters shown as visible escapes, credentials washed, folded to one line, envelope tags removed even when spelled with zero-width characters — and since 0.104.0 also when the engine hands them over in its defused entity spelling `<system-reminder>`, when they are `task-notification` tags, or when the engine's length cut left half a tag glued to its truncation mark `…` (half a tag name without that mark is ordinary text and stays, so a trailing comparison such as `elapsed < t` is kept); only the display copy is decoded, and only the two entities the installed engine actually emits, which the suite pins by running the engine's own defusal functions); a hook that crashed, timed out, or was cancelled mid-check gets one fixed sentence each, saying the prompt was not submitted; an unrecognised cause word prints only the lead and never echoes the word. When the machine-readable cause is missing or malformed, the old `Run blocked: <reason>` line stays, with a whole engine envelope unwrapped so no tag or mark reaches the screen, and an agent's own free-text reason now goes through the same display path as the hook's words (control and bidirectional characters shown as visible escapes, credentials washed, folded to one line, capped at 1000 units without splitting an escape), so clean text is byte-for-byte what it was and an empty or blank reason reads as the generic sentence. The new line counts as a governance stop (it is not an `API Error:`) and is recognised by the same row predicate as `Run stopped` / `Run blocked`. The suite also pins the single mint site in source, covers the interactive lane, and checks the tag remover is linear on near-miss input. Since 0.110.0 that sentence-maker, `runBlockedText`, is also exported from the package root as the very same function (not a copy), so a host that renders a blocked run itself calls it instead of writing its own line; the suite pins the identity, the unchanged signature, that the English lead constant stays out of the root surface, and that the root call returns the same bytes as the terminal row and the result frame's first error across nine blocked shapes. |
|
|
538
|
+
| `scripts/run-prompt-blocked-sentence-projection-test.mjs` | The sentence for a run whose first prompt was held back by a deployment's `userPromptSubmit` hook. The engine frames its own explanation for the model in an envelope that carries the session's reminder mark, and the terminal row used to print that envelope verbatim (`Run blocked: <system-reminder mark="…">…`) while the machine-readable cause beside it went unread. The package now has one sentence-maker for the `blocked` terminal, shared by the terminal row and the result frame's first error: a hook that refused the prompt reads `UserPromptSubmit operation blocked by hook:` followed by the hook's own words (treated as untrusted text — control and bidirectional characters shown as visible escapes, credentials washed, folded to one line, envelope tags removed even when spelled with zero-width characters — and since 0.104.0 also when the engine hands them over in its defused entity spelling `<system-reminder>`, when they are `task-notification` tags, or when the engine's length cut left half a tag glued to its truncation mark `…` (half a tag name without that mark is ordinary text and stays, so a trailing comparison such as `elapsed < t` is kept); only the display copy is decoded, and only the two entities the installed engine actually emits, which the suite pins by running the engine's own defusal functions); a hook that crashed, timed out, or was cancelled mid-check gets one fixed sentence each, saying the prompt was not submitted; an unrecognised cause word prints only the lead and never echoes the word. When the machine-readable cause is missing or malformed, the old `Run blocked: <reason>` line stays, with a whole engine envelope unwrapped so no tag or mark reaches the screen, and an agent's own free-text reason now goes through the same display path as the hook's words (control and bidirectional characters shown as visible escapes, credentials washed, folded to one line, capped at 1000 units without splitting an escape), so clean text is byte-for-byte what it was and an empty or blank reason reads as the generic sentence. The new line counts as a governance stop (it is not an `API Error:`) and is recognised by the same row predicate as `Run stopped` / `Run blocked`. The suite also pins the single mint site in source, covers the interactive lane, and checks the tag remover is linear on near-miss input. Since 0.110.0 that sentence-maker, `runBlockedText`, is also exported from the package root as the very same function (not a copy), so a host that renders a blocked run itself calls it instead of writing its own line; the suite pins the identity, the unchanged signature, that the English lead constant stays out of the root surface, and that the root call returns the same bytes as the terminal row and the result frame's first error across nine blocked shapes. Over-long reasons are cut by the package's one truncation rule for third-party text and end with an ellipsis, the same rule used for failed-run reasons. |
|
|
539
539
|
| `scripts/run-active-run-busy-read-projection-test.mjs` | How the package reads a rejected submission (the session already has a run in flight) in its terminal row, in its result frame and in the public discriminator `activeRunBusySignal`: one discriminator body and one carrier rule, shared by all three. The server's rejected and conflict terminal frames carry `status: 'failed'` since 7.125.0; the older idempotent-replay form — a cached copy of the original 409 conflict body wrapped as `done{ result, replay: true }`, with neither `status` nor a terminal word — is no longer recognised, since the package's support floor moved past the servers that sent it. The suite pins what such a body reads as today (the discriminator answers null, the row is the single `Outcome unknown` line, the result frame carries the unknown-outcome flag, the public projector agrees, with or without the replay flag, code only, id only), checks over a pool of sixteen frames that the discriminator and the row agree in both directions (including a cause-form frame that carries the busy code), pins which objects count as the carrier, pins that the retired folding function and its flag are gone from the source and the build, and pins in source that the discriminator and the carrier rule are each defined once. |
|
|
540
540
|
| `scripts/run-fleet-terminal-retain-test.mjs` | The fleet ledger's rule for terminal rows has one home and one function. A terminal row (completed, failed, killed) lives only in the retention pool and never in the active set, whichever way it arrives — a task frame or a reconnect snapshot — and both arms go through the same admission function. A row brought back by a reconnect snapshot therefore expires with the retention window exactly like one that arrived as a frame; before, the snapshot arm left it in the active set for good, and a lost removal frame did the same to a frame-delivered row, and clearing the pool could not clear it. The suite refutes the change on three axes: timing (snapshot before or after the terminal frame, interleaved with removal, repeated delivery, resurrection, a later snapshot that does not carry the row, a row being viewed, pool clearing, and every terminal word through both paths with identical answers), concurrency (twin rows of one task in either order, a notification-retired entry meeting a snapshot row, notifications against a snapshot-carried row, two sessions' ledgers), and failure class (a status outside the terminal vocabulary, absent, or null is never turned into a terminal row; rows without a usable id, with a non-string id, or null entries are dropped and counted, never thrown on). It also pins that the removal hook still reports a known row for a settled terminal row, because downstream bookkeeping credits a removal only when neither the stale mark nor the unknown-row mark is present. Finally it pins the terminal evidence the ledger keeps past the window (status word plus cycle, per task tail, bounded): after a row has aged out or the pool was cleared, a same-cycle completed notification cannot turn a known failure or kill into a success, while a newer cycle, a revival, and the upgrade direction still pass; the evidence itself is cycle-monotonic, so an older generation's terminal row, or one arriving late after a revival, neither overwrites nor re-plants it. Since 0.97.0 it also pins the ledger's single per-task rule, applied in the one admission function to task frames and snapshot rows alike: a reading from an older cycle than the task has already shown is ignored (it neither revives the row, nor withdraws the terminal evidence, nor lets a snapshot drop the task's newer in-flight row); a newer cycle retires older in-flight aliases of the same task; within one cycle, or when the order cannot be told, an in-flight alias wins over a terminal row; otherwise the terminal row settles the task and twin rows collapse into one. Every arrival order of a set of readings, through either arm, gives the same projection and the same in-flight reading. A notification from an older cycle than the task has shown leaves the rows alone even when the running row's latest frame carried no cycle, and the bounded per-task cycle record never evicts a task that still has rows. |
|
|
541
541
|
| `scripts/run-bg-subagent-row-test.mjs` | The background-subagent identity predicate every end shares. The fleet read surface lists every non-terminal task row — and since server 7.125.0 a session-scoped stream also brings back the session's own run row and its foreground delegation rows — so "is this row a background subagent" needs exactly one answer. `isBackgroundSubagentRow` applies four rules in order: a row with no id, a composite id, or a `run-leg` lane mark is never a subagent (the last two are foreground delegation rows); a non-agent handle (background shell or monitor) never is; a single-segment row with a readable parent is; a row without a readable parent is only when its id is an agent-family handle. `isBackgroundWorkRow` adds the non-agent handles for the "N background tasks" counts, and `isOwnBackgroundSubagentRow` adds ownership — a session-scoped stream replaces the ownership half only, never the row-kind half. The handle shapes are not retyped here: the durable agent-handle pattern is the installed engine's own, and the non-agent prefix letters are read from the engine's task registry when the tables are generated. The read-surface row now carries `sourceLane` (only when the wire row has a non-empty string), and task frames and reconnect snapshots reach the predicate through the same row shape. The suite checks each rule with a positive and a negative example, the absence cases (no id, unreadable parent, unusable lane mark), the 7.125.0 stream shape against the older shape, and that the lane word and the prefix table each have exactly one home in the source. |
|
|
@@ -751,7 +751,7 @@ guard still cross-checks the table by name).
|
|
|
751
751
|
| `scripts/run-session-hooks-roster-test.mjs` | Two seat verbs. The Quick Entry shortcut: the seat capability `quickEntryShortcut` gates `getQuickEntryShortcut` and `setQuickEntryShortcut`; the state says which shortcut is saved, which one is registered right now (`null` when none, never an empty string) and why a saved shortcut failed to register; a refused change is a result with a closed reason (invalid request, unsupported combination, registration refused by the system, or the preference could not be written) that carries the unchanged state, never an error and never a false success. The session hooks roster: the seat capability `hooksRoster` gates `readSessionHooksRoster`, whose answer is produced only by `sessionHooksRosterOf(plan)`, a row-by-row projection of the same hooks plan that assembles the turn — event, matcher and hook index, entry type, status (engine, shell, not run, not sent) and reason, plus per-layer outcomes and HTTP allowlist drops. Every string in a roster is a closed-set word, so commands, URLs and user-written key names cannot appear. The guard checks both verbs' registration and declared signatures, both outbound checks (including the false-success and closed-leg contradictions), the shortcut pre-check, a host stand-in for each verb, a planted-secret sweep over a pool of plans, and a row-by-row comparison between roster and plan. |
|
|
752
752
|
| `scripts/run-subagent-model-ports-test.mjs` | The subagent model word ports share one reading. One vocabulary of engine words that catalog rows do not list (tier words, provider aliases, `best`, `default`) is read by both the word resolver and the catalog acceptance judge. `subagentModelAdmissionOf({ word, liveCatalog?, local? })` judges whether this engine admits an agent entry carrying the word the reading sends: it asks the same acceptance judge, except that the mention list does not gate agents and an engine word the catalog does not serve is reported as `not_served`; with no catalog from the engine the answer is unknown, never refused. `subagentModelAdmissionLine` renders the sentence for a refusal and `subagentModelCallRefusalReason` the sentence for a call-time refusal, both from closed reasons through the message catalog. The gate compares the admission verdict with the installed engine's tier expansion and the server's exact-key agent check on generated catalogs, and checks the vocabulary, `default`, both host assertion words, absence, hostile inputs and the sentences in both languages. |
|
|
753
753
|
| `scripts/run-thrown-slot-reader-test.mjs` | Two readers for the fields of a thrown value, both of which never throw. `thrownSlotOf(value, name, kind?)` reads one field of whatever was thrown — an error object, a proxy, a revoked proxy, `null` or a primitive. By default it reads along the prototype chain (where a built-in error's `name` lives); with `kind: true` it reads only the value's own keys; with `kind: 'data'` it reads only its own data fields, so an accessor is never run and a field planted on `Object.prototype` is never seen. A field that is absent and a field that cannot be read (a getter or proxy trap that throws, a revoked proxy, `null` or `undefined` as the thrown value) both answer `undefined`, so the result can be defaulted or printed directly; narrow with `typeof` before using it as a string or number. `errnoCode(value)` is the fixed call for the error code of a system error: the own, non-empty string `code`, and `undefined` for everything else. |
|
|
754
|
-
| `scripts/run-engine-unavailable-line-test.mjs` | What a client says when the engine cannot serve the session, and what the way out is. One reader takes the engine's start-up log lines: structured lines are read first and plain echoed text only as a fallback, and a refusal code is recognised only where the engine states it as a code. A data-folder refusal additionally yields its variant, the recorded engine version, the engine's own version and the marker path when the engine names them, and nothing when it does not. One line names the case, carries a machine-readable prefix and the exit details (none when unknown), and gives the way out for that case; the lane only changes how retrying is phrased. Ways out for a refused data folder follow how the client is installed: an update command is offered only to global and managed installs, a client started by the host never suggests overriding the data folder and instead names the configuration-folder variable the start-up table pins, and with no install shape the engine's own words are shown unchanged. Headless runs exit with 69. |
|
|
754
|
+
| `scripts/run-engine-unavailable-line-test.mjs` | What a client says when the engine cannot serve the session, and what the way out is. One reader takes the engine's start-up log lines: structured lines are read first and plain echoed text only as a fallback, and a refusal code is recognised only where the engine states it as a code. A data-folder refusal additionally yields its variant, the recorded engine version, the engine's own version and the marker path when the engine names them, and nothing when it does not. One line names the case, carries a machine-readable prefix and the exit details (none when unknown), and gives the way out for that case; the lane only changes how retrying is phrased. Ways out for a refused data folder follow how the client is installed: an update command is offered only to global and managed installs, a client started by the host never suggests overriding the data folder and instead names the configuration-folder variable the start-up table pins, and with no install shape the engine's own words are shown unchanged. Headless runs exit with 69. Whether the engine answered its health probe is told with the probe verdict itself (unanswered, answered but not ok, answered ok), read by the same function that words the verdict, so the line and the verdict sentence never disagree; an engine that was asked to stop and is still running is its own reason. |
|
|
755
755
|
| `scripts/run-self-heal-conversation-left-test.mjs` | Conversation-left handling for the busy-session self-heal. A host can answer one optional question, `stillHere()` (is the conversation that issued this action still the one on screen?), and the package reads it one way only, as three states: a strict `true` means still here, a strict `false` means the conversation was left, and a reader that is supplied but answers anything else or throws means it cannot be confirmed; no reader at all keeps the previous behaviour. When a resend is about to be authorised but the conversation was left or cannot be confirmed, the outcome becomes `resend-withheld-left` or `resend-withheld-unconfirmed` (not delivered either way, so the host never sends the message into a different conversation) with its own sentences in both languages; the deferred-batch wait `waitForInjectedResubmit` asks the same question every round and settles `left` or `unconfirmed`; and ending a run after the conversation was left maps to six result classes with their own sentences. |
|
|
756
756
|
| `scripts/run-refusal-noted-projection-test.mjs` | Refusal notes on tool results. When a person refuses a tool call on the approval card and attaches a note, the engine records the note and the turn continues with that direction; a refusal without a note is a bare refusal. Tool result rows (interactive transcript and print frames) carry `_sema_refusal_noted: true` when the same row's denial kind is `user-rejected` and its gate record is a person's refusal whose note is present (empty or non-string notes count as absent), read with `toolResultRowFlagsOf(row).refusalNoted`; the key name is exported as `SEMA_REFUSAL_NOTED_KEY` and listed in `TRANSCRIPT_ROW_SIDECAR_KEYS`. Subagent content events, items and view slots carry the same facts as `denialKind` (the same closed vocabulary as the main transcript) and `refusalNoted`, on the live stream, the background tail and replay alike, and the seat validator accepts only those values. The gate checks every refusal and note shape on both lanes, row self-consistency, key order, replay equivalence, the reader's isolation, the three subagent views, the seat contract, and by syntax tree that the key name and the rule each live in one place. |
|
|
757
757
|
| `scripts/run-decide-ack-outcomes-test.mjs` | Tool-permission receipts on the seat answer one question, whether the user's decision is in effect right now, with exactly three answers: yes (`ok: true`), no (`ok: false`), or not known (`ok: false` with an `unconfirmed` slot naming the cause). The cause words are the package's existing words for a decision that got no verdict (`transport`, `server_error`, `local_error`, `aborted`, `gone_after_retry`) plus `registry_unreadable` for a host that could not read the pending-request list when it settled the receipt. The `unconfirmed` and `settledElsewhere` slots never appear together, `unconfirmed` always comes with `ok: false`, and when `settledElsewhere` is present `ok` must say the opposite of `contrary`; the receipt's key set is closed. A receipt with neither slot is still valid and reads as before. One reader turns a receipt into applied, not applied or unconfirmed and judges with the same check the outbound gate runs, a sentence helper gives the unconfirmed line in both interface languages (the after-retry cause reuses the existing sentence), and a mint helper turns a thrown decision error into the slot using the same classification the decision sender already applies, returning nothing when the engine gave a verdict. The guard covers every arm accepted and every malformed or contradictory form refused with the slot named, accessors never run, and the three counterexamples: a server error folded into a refusal, an unreadable pending-request list folded into success, and both slots in one receipt. |
|
|
@@ -768,9 +768,9 @@ guard still cross-checks the table by name).
|
|
|
768
768
|
| `scripts/run-host-setting-notice-projection-test.mjs` | The host settings notice arm. Every sentence a `hostTurnSettings()` product says (turn, session or diagnostic plane) becomes one `host_setting_notice` chrome event through the single minting function `hostSettingNoticeEventsOf(notices)`, whose payload is the notice itself; the arm is on the seat list, so a seat host forwards it unchanged and both renderer lanes read one arm. A sentence minted for one row of the product carries that row's `key` and `cause`, and the refusal sentence of the verdict is the very same object as the one in the list. The arm is not a terminal event: it carries no error or outcome field. Malformed entries are skipped one by one, malformed row bits drop only themselves, and accessors are never run |
|
|
769
769
|
| `scripts/run-prompt-suggestions-tail-test.mjs` | The follow-up for prompt suggestions after a completed turn. A suggestion batch has one minting rule, shared by the stream frame and the run record, and one arm. The main path is the stream frame, which servers from 7.149.0 put before the terminal frame; `followUpPromptSuggestions` asks the run record only when the main path cannot already have delivered: not when suggestions were not requested, not when the frame was seen on the stream, and not when the stream reached its terminal frame on a server that sends the frame first (`promptSuggestionsOnStream`, which reads the capability bit together with the server version because older servers report the bit as true on every leg). Polling is bounded by six requests and twelve seconds (no request starts once the budget is spent, and a request in flight waits only for what is left of it), stops on an empty batch or on a run that did not complete, and mints the same arm the stream would have produced |
|
|
770
770
|
| `scripts/run-approval-card-request-assembly-test.mjs` | The single assembly path for an approval card request. `approvalCardRequestOf(facts, host)` turns a card-facts reading (the output of `approvalCardFactsOfV1Frame`, `approvalCardFactsOfFrame`, `approvalCardFactsOfGeneric` or `approvalCardFactsOfV1`) plus the host positions `ApprovalCardHostBits` (`callKey`, and optionally `taskId`, `signal` and the four window positions read by `approvalWindowKeysOf`) into an `ApprovalCardRequest`, and the package's own live-card path uses the same assembly. The guard reads the key sets of the request, facts and host-position types from the shipped declarations with the type checker and requires every request key to be classified as a fact, a host position, or one of the five positions only the package's own card paths stamp, so a new request key that nobody classified fails the gate. Every fact key and every host key is fed alone and all together and must arrive as the same value; keys outside each closed set never cross (a host cannot overwrite a fact, and a facts reading cannot smuggle a host or package-only position); only own data properties are read, so getters never run, inherited and undefined-valued keys are left out and a throwing read drops only that key; malformed inputs answer undefined and nothing throws. Real readings from the three projection entries equal the earlier spread form key for key and in the same order, the four positions a hand-picked copy used to drop arrive intact, and the request the live-card path hands to the card port equals the assembly of the same frame's projection with the card's host positions, with a syntax-tree check that the live path calls the assembly instead of spreading the facts inline. |
|
|
771
|
-
| `scripts/run-session-read-redaction-projection-test.mjs` | Session-history redaction
|
|
772
|
-
| `scripts/run-store-posture-durability-projection-test.mjs` | How the store posture reads whether a replica is durable across engine generations. Older engines report a durable boolean; newer ones report one three-state durability word (durable, ephemeral, unknown) that is the same assembled value as the health report's. Exactly one generation's key must be present: a word outside the three is carried as reported and reads as unknown rather than being folded into a known word, both keys at once or neither discards the whole reading, and "unknown" is never read as "not durable". The doctor line and its head word come from the message catalog in both languages, with the older-engine sentences unchanged byte for byte; the ephemeral sentence does not claim the state is held in memory. Checked against both engine generations' own projections and member lists, and the three words are recognised in exactly one place in the package. |
|
|
773
|
-
| `scripts/run-local-allow-redemption-test.mjs` | Redeeming a "don't ask again" choice made on a read-only approval path (a parked pending row, or the v1 ask frame, whose answer body has no rule slot). A local-settings allow line never takes effect on its own: the settings contract places that layer below the floor for allow rules, so the only consent that counts is a live rule of the same identity (allow, exact text, the same project root or global) in the engine's rule store. One judge, `localAllowRedeemability`, answers for a line already on disk and for an option about to be shown, in three states: redeemable (by the layer itself, or by consent in the store), not redeemable with a closed reason, or unknown with a closed cause; it never throws and never runs accessors. A repository-shipped allow line with no matching consent is judged not redeemable, whatever the workspace trust reading says. The redemption call, `redeemReadOnlyRuleOffer`, asks the same judge first, applies the five shape narrowings, then sends a settings import that contains only the chosen rule, never the settings file itself, and redeems the ticket only when the preview is exactly that one rule at that project root. Its receipt is one of four closed arms: applied, refused (certainly not stored), unavailable (the route is closed or cannot be reached), or unknown (the redemption was sent and the outcome cannot be told). The approval card's don't-ask-again row for the read-only slot reads the same judge. |
|
|
771
|
+
| `scripts/run-session-read-redaction-projection-test.mjs` | Session-history redaction. `sessionReadRedactionOf` is the one reader for the capabilities bit `sessionReadRedaction`: the boolean `true` of earlier servers, or a non-empty list of leaf names (passed through exactly as sent), reads as `redacted`; an absent bit, an empty list, `false` or any malformed form reads as `unconfirmed` and is never taken to mean the history is unredacted. Checked against the real bytes of two server generations; the reader never throws and never runs an accessor, and the health report reader carries no store-durability field (durability is read from the capabilities store only). |
|
|
772
|
+
| `scripts/run-store-posture-durability-projection-test.mjs` | How the store posture reads whether a replica is durable across engine generations. Older engines report a durable boolean; newer ones report one three-state durability word (durable, ephemeral, unknown) that is the same assembled value as the health report's. Exactly one generation's key must be present: a word outside the three is carried as reported and reads as unknown rather than being folded into a known word, both keys at once or neither discards the whole reading, and "unknown" is never read as "not durable". The doctor line and its head word come from the message catalog in both languages, with the older-engine sentences unchanged byte for byte; the ephemeral sentence does not claim the state is held in memory. Checked against both engine generations' own projections and member lists, and the three words are recognised in exactly one place in the package. The health report's store section is the same assembled value as the capabilities store, so the package reads durability from the capabilities store alone and offers no second reader; checked against the newer engine's own health route and projection, which must report the same word for the same assembly. |
|
|
773
|
+
| `scripts/run-local-allow-redemption-test.mjs` | Redeeming a "don't ask again" choice made on a read-only approval path (a parked pending row, or the v1 ask frame, whose answer body has no rule slot). A local-settings allow line never takes effect on its own: the settings contract places that layer below the floor for allow rules, so the only consent that counts is a live rule of the same identity (allow, exact text, the same project root or global) in the engine's rule store. One judge, `localAllowRedeemability`, answers for a line already on disk and for an option about to be shown, in three states: redeemable (by the layer itself, or by consent in the store), not redeemable with a closed reason, or unknown with a closed cause; it never throws and never runs accessors. A repository-shipped allow line with no matching consent is judged not redeemable, whatever the workspace trust reading says. The redemption call, `redeemReadOnlyRuleOffer`, asks the same judge first, applies the five shape narrowings, then sends a settings import that contains only the chosen rule, never the settings file itself, and redeems the ticket only when the preview is exactly that one rule at that project root. Its receipt is one of four closed arms: applied, refused (certainly not stored), unavailable (the route is closed or cannot be reached), or unknown (the redemption was sent and the outcome cannot be told). The approval card's don't-ask-again row for the read-only slot reads the same judge. The same judge also answers for a rule a client is about to write into a given settings layer and for the whole-tool row on an approval card: a rule of the right shape to be sent still does not count as taking effect when its layer sits below the allow floor and the store holds no matching consent, and a missing or malformed landing reading is unknown, which offers nothing. |
|
|
774
774
|
| `scripts/run-health-probe-verdict-test.mjs` | The verdict on one liveness probe of an engine's health endpoint, read in one place: the probe was not answered at all (it timed out or could not connect), was answered healthy, or was answered but not healthy (a non-success status code, or a success status whose body does not report that the engine is ok). One function folds the four arms of the SDK probe result into those three states and never reports an unreadable result as "did not answer"; one function turns a verdict into a short clause in English or Chinese that, for the answered-but-not-healthy state, names only the HTTP status code; one selector picks, from the observations of one unhealthy stretch, the most recent that was answered, ignoring observations older than the stretch and skipping malformed ones. The guard drives the real SDK probe against local servers (healthy, a failing status, a success status whose body reports draining, no answer, nothing listening), a hand-written table of the four arms with the status-code boundaries, unreadable and hostile inputs (accessors, prototype-chain values, trapping proxies) that must neither throw nor run a getter, the exact sentences in both languages, and a seeded random pool compared with an independently written reference selector. A syntax-tree scan then pins that the only place in the package that reads the probe result's liveness flag is the verdict function, that every call of the SDK probe hands its result straight to it, that the package's own liveness helper is derived from it, and that verdict objects for the two answered states are built in that one module only; a planted violation proves the scanner can see. Finally the liveness helper is compared with the SDK's own flag on real servers, so deriving it from the verdict changed no answer. |
|
|
775
775
|
| `scripts/run-hooks-shell-owned-no-executor-projection-test.mjs` | Hooks written under client-run events say so when nothing runs them. Hook events the engine never fires (every event in the settings contract except the nine engine events) never go on the wire, so whether such a hook runs depends only on whether this client's own hook runner runs that event and hook type. When it does, nothing is recorded; when it does not, the plan's dropped-hooks table carries exactly one row for the entry with the reason `no_executor` (the same word and sentence plugin and session hooks already use for that case), marked as running nowhere, and the hooks-not-run notice says one sentence per settings layer. The engine-contract reasons (exec-form commands, `mcp_tool`, unread keys, an authored group `source`) are judged on engine events only. Governance still comes first: a closed hooks leg, managed-only hooks, safe mode and workspace-trust withholding keep their own rows and produce no `no_executor` rows. The suite covers all five settings layers times every client-run event, the runner's event and type tables (absent, listed, unlisted, malformed), the three hook sources, malformed documents and misspelled event names, pins the single place the row is minted, and sweeps every plan it builds. |
|
|
776
776
|
| `scripts/run-attachment-name-cc-form-test.mjs` | Entity-form display for attachment names and paths. `showAttachmentNameCc(name)` writes `<` and `>` as `<` and `>` and every C0, DEL, C1, line-separator and paragraph-separator code unit as a decimal `&#N;` reference, and leaves everything else (including `&`, quotes, backslashes, format characters and lone surrogates) as it is. The gate walks a 103-row rule table, 4000 deterministic random strings against an independent per-code-unit reference, idempotence, a two-form output table (the existing JSON-style form is untouched and shares no code with the entity form), and source pins that keep the two forms independent. |
|
|
@@ -778,6 +778,15 @@ guard still cross-checks the table by name).
|
|
|
778
778
|
| `scripts/run-interrupt-deny-delivery-test.mjs` | Interrupt denials take each leg's ordinary decision delivery: when a turn is stopped while an approval card is open, the tool-level deny that settles the pending question is sent like any other answer on that leg — on the live card leg through the bounded transport retry and the one invited re-send after a 202 parking reply, on the durable approval and question legs through the decide bridge's own retry — with a lifetime of its own (the turn's signal is already aborted) equal to one delivery budget. The warning that the session may stay locked is shown when that delivery has failed after its last attempt, or when the budget runs out with no answer; `CANCEL_DENY_BUDGET_MS` is that budget (8000 ms). A retry that finds the question already settled stays silent, at most one of the sends is accepted, and a second caller for the same card joins the delivery in flight instead of presenting another card. |
|
|
779
779
|
| `scripts/run-p2-clearance-gate-test.mjs` | A release-closing ledger gate. Before the release that closes the clearance window, every earlier committed P2+ item must be closed or deferred with a falsification note. The gate reads the clearance queue and the ledger status column, counts the items still open (open, in progress, blocked, resolved but unverified, or deferred only on cost), prints one machine-readable count line plus a per-item list, and turns red only when the package version is the gate version or later and the gate version's changelog section already carries a release date; before that it reports the count and passes. When the ledger files are not reachable (for example a remote container without the sibling repository) it skips honestly and says so instead of passing. Self-checks cover every status form, the version and date matrix, and negative controls on throwaway ledger copies. |
|
|
780
780
|
| `scripts/run-server-7148-pick-projection-test.mjs` | What the client reads from the newest server release and client library generation. A refusal's machine-readable facts are read from one place, the root of the refusal body, for every server in the supported range: older servers that nested some facts under `detail` are normalized once where the error is first read, so hook-setting refusals, conflicting-field refusals, rule-entry problems, attachment refusals and scenario refusals read the same on both shapes, and a hook refusal names the exact setting coordinate on both. The anonymous `/health` reading only yields the facts the server shows to callers without credentials; everything else reads as absent, never as zero or false. A 404 for an approval question reads as not settled. The Esc interrupt sends exactly one request on both library generations, and a cancelled run whose heartbeat had lapsed is read and worded as such. Exercised against the server's own refusal minters and health route on two server generations, through the real library error mapper and run resource. |
|
|
781
|
+
| `scripts/run-local-config-kernel-test.mjs` | The shared local configuration kernel. One document table names every local configuration file once: its logical name, a path template with four slots (resolved by the host's configuration-home resolver, never by this package), how much of its shape the settings contract owns, the name of its lock rank, and whether the product also writes it outside configuration edits; project-level files live only under `.sema`, and the global state file lives inside the configuration home, located by one function that never probes an older location. A file reading has four states: loaded with a revision, absent, unreadable with a cause from the settings contract's closed set, or outside the fence. Every edit is an intent made of single-file steps that each lock their files, re-read them inside the lock, plan exactly once, hand the host one whole next document with the revision it was planned on, and are never replayed after a step was not written; a multi-file intent is a sequence of such commits (a key slot before the catalog entry, deletions in reverse) whose receipt lists any harmless residue. The receipt has four arms (applied with when it takes effect and any disclosure of which layer decides or overrides the value, refused with a closed reason that always means nothing was saved, unavailable with a closed cause, unknown only when a write was handed over and its outcome cannot be told), a preview is a separate shape that carries the same disclosures, and every word has one sentence in both interface languages. One lane check runs first: a Cloud engine, an engine not confirmed to serve one user, or an unsettled configuration home blocks reads and writes alike; the two browser routes are judged separately, a direct route to the local companion service is read-only for now, and writes are offered only when every named precondition holds. The write intent table derives the settings write keys, takes layer admission and value shape from the settings contract's unit table, and the settings write plan is a pure document-in, document-out function. |
|
|
782
|
+
| `scripts/run-local-config-mcp-test.mjs` | MCP server configuration as one shared runtime. Reading: one source precedence table and one override-by-name merge across the user, project and local layers plus the additional sources a host supplies, one project approval rule (merged values when the folder is trusted, per-layer presence otherwise, session approvals in both, nothing approved without a settings source), one tool-list agreement rule (a name whose places disagree on its tool list is held back), and one rule that a configuration file able to add or limit servers being unreadable holds back every server instead of silently dropping that file; names compare byte for byte, and the host's own built-in server names are refused alike on read and write. Deployment rows are listed beside request rows. Writing: one edit entry point (add, update, remove, enable or disable, project approval, import) that hands exactly one file to the shared local configuration kernel and answers with the kernel's four receipt arms; the hot global state file only changes at the edited key path. A dry run writes nothing, and a connection test dials once, only after the dry run succeeds, with the same entry the read side would load. Bridge views carry no secret values. |
|
|
783
|
+
| `scripts/run-local-config-skills-test.mjs` | Skills in the shared local configuration kernel. One root table lists where skills, commands and agents come from: managed, the user's configuration home, each project level from the working directory up to the repository root (nearest first) under `.sema` only, additional directories, and the host's plugin roster; a `.claude` folder is never read. One view lists every skill with its layer, whether it reaches the model and why not (turned off, model invocation turned off by its own file, folder not trusted, trust not confirmed, or shadowed by a same-named skill from a higher layer), the description only when its header states one, its effective state with the layer that decides it, and whether it can be changed here. The effective state follows one chain: managed settings first, then the merged settings (full names before bare names, local over project over user), aliases tightened only by managed settings, plugin skills untouched by ordinary layers, MCP skills by the first enabled layer that names them, built-in skills clamped when built-ins are off. A state change writes the local layer when a workspace is open and the user layer otherwise, writes only the difference from the layers below, migrates bare-name keys, keeps sibling MCP skills' states when a shared label key is removed, refuses with one of four sentences when the state is locked, and reports which layer decides the result after the write; the projection to the engine reads the same effective state, so a skill turned off in one client is not sent by another. |
|
|
784
|
+
| `scripts/run-local-config-models-test.mjs` | Model pool and tiers on the shared local configuration kernel. Every pool edit (add one or many models, update one, remove one, set the default, import environment models, import from another tool's profile, bind a tier, switch, add or remove a tier group, or migrate the old tier settings once) goes through one pure planner that takes the model catalog and the user settings and returns both next documents, then runs as single-file kernel steps: a model's key slot is written before its catalog entry, a removal deletes the entry before its now-unused key slot, and each step re-checks inside its lock what the earlier step decided. A batch is refused as a whole when any entry is malformed, with one reason per entry; an entry whose probe did not pass is still saved and marked unverified; an entry for a local endpoint may carry no key at all, and is accepted only when the engine's own pairing judge says a keyless request is allowed there. The default model has one place, the catalog's default role: only setting the default (or picking one while adding) writes it, no other pool edit recomputes it, and the default reader reports when the settings file's top-level model shadows it for new sessions. Removing a model that is still the default, bound by a role, or listed in an old roster is refused; tier bindings and the @-mention allowlist follow the removal and the consequences are reported. The view lists every entry without any key value, counts entries it could not read instead of claiming a complete catalog, and takes provider sign-up links from the package's own preset table. The seat adds one read capability (the pool view and a separate candidate-model discovery call) and one write capability (one edit verb with a dry-run option); keys are accepted only on the request side. The probe reports first-token latency as a number, and the live catalog reader carries the count of rows it dropped so the acceptance judge answers incomplete instead of refusing. |
|
|
785
|
+
| `scripts/run-model-config-gap-notice-test.mjs` | Model-configuration gap sentences. `modelConfigGapNotice({ parts, keyChannel?, catalogEntries? }, lang?)` turns the list of missing model-configuration items (model name, gateway base URL, API key — the key tagged with its channel, and the number of enabled catalog entries the gap affects) into one `{ head, detail }` pair in English or Chinese, so every place that has to say why a model cannot be used reads the same sentence and differs only in whether it takes the short head or the longer detail. The gate checks thirty cells (five readers, single, double and all-three gaps, two languages) against an independent reference model, twelve pinned sentences, the optional fields (absent, out-of-set and malformed values read as not reported and only act when the item they belong to is missing), the empty and malformed answers (an empty list says nothing is missing and invents no sentence; an unreadable list is reported as malformed, never as nothing missing), hostile inputs (throwing getters, revoked proxies, prototype pollution: own data properties only) and single sourcing: the five readers' fields are the one function's fields, replacing one catalog key in a separate process changes exactly the readers that take that field, the source holds no English sentence literal, and each head sentence occurs once in the whole source tree. A consumer compile checks the shipped declarations, and planted second sources prove the checkers can fail. |
|
|
786
|
+
| `scripts/run-server-7149-pick-projection-test.mjs` | What the client reads from the newest server release and client library generation. When the engine refuses a parked approval because this engine cannot continue it, the refusal now names the way out: cancel the run, or continue it on a newer engine. The client reads that word once, keeps it on the refusal reading and classification, stops treating such a refusal as worth resending as is, does not stop the run when a newer engine can continue it, and words the way out with the same sentence it already uses for the same verdict on a pending row; the sentence for a refused parked step uses that same wording when the caller hands it the word, and is unchanged otherwise. A model row's context window now says whether it was declared or assumed; the client keeps the number and adds the source, and an older server's row reads as unknown, never as declared. A run result that disclosed that its read-deny rules were not byte-enforced reads as such, and its absence is never read as the rules being kept. The list of error codes for which resending cannot change the answer is the library's own list, snapshotted at build time, so a newly listed code stops being offered as retryable. |
|
|
787
|
+
| `scripts/run-model-pool-migrate-sweep-test.mjs` | Model pool leftovers. Migrating the old tier settings now merges them into the model catalog instead of dropping groups that exist only in the old settings: a group with the same name keeps the catalog's version and is disclosed in the write receipt only when its content really differs. A separate edit sweeps orphaned key slots (a stored key that no model references any more), checking for references again inside the same lock, and the model-pool view always carries a count of such slots. One shared rule decides which model becomes the default when a batch is added without an explicit choice: keep an explicitly configured default; otherwise take the first model in the batch that was verified; if none was verified, change nothing. Pure planner functions and a stand-in-rule check over the real built package. |
|
|
788
|
+
| `scripts/run-engine-attach-ownership-test.mjs` | Local engine credentials and connection reuse. A credential for a local engine is sent only over a connection opened after the moment the engine on that port was proven to be the expected one: either a transport that opens a new connection for every request, or a pool opened after that proof and bound to the same engine generation. `engineCredentialReleaseVerdictOf` takes the host's ownership reading (match, mismatch or unreadable) and the declared transport and answers present, or withhold with `identity: 'unproven'`, a reason from `ENGINE_CREDENTIAL_WITHHOLD_REASONS` and whether a bound pool should be closed. An undeclared transport means the shared default pool and never carries the credential, and nothing is inferred from a missing reading. `makeLocalEngineWireClient` applies the verdict before building the client, so requests still go out without the credential when it is withheld. The gate checks the judge matrix, three attach-time call shapes (diagnostics capability probe, side query, background task probe) across a generation change and before and after the proof, that every shape follows the same judge (a stand-in judge shifts all three), that the default pool never sees the credential, hostile inputs, and that the SDK health probe still has no connection-reuse option. |
|
|
789
|
+
| `scripts/run-console-ca-pin-test.mjs` | Console certificate pinning, decided in one place. `readCenterAddress` reads an invitation link or a typed center address once and answers with the TLS trust origin (`origin`) and the credential partition key (`centerKey`), or with one of sixteen closed refusal reasons: invitation links must be `https://` with no path and may carry only a `#ca=` list of canonical fingerprints, a typed address may use plain `http://` only for this machine, and user info, percent-encoded hosts, trailing dots and non-standard IP spellings are refused. `trustOriginOf` maps the final URL handed to a transport (including `ws://` and `wss://`) to its trust origin. Fingerprints are always the SHA-256 of the whole certificate DER, in the settings contract's `sha256:` spelling; flag input also accepts uppercase and colon-separated forms and folds them. `readCaBootstrapBody` takes the raw bytes of the console's certificate answer and a host-supplied certificate parser, requires every served certificate to be canonical single-block PEM with standard DER lengths, binds the parser's reading to the exact bytes, refuses duplicates inside the served set, and requires every named fingerprint to be served and self-signed. `caBootstrapOpen` / `caBootstrapStep` plan the fetch: one attempt plus three retries on a 120-second monotonic budget, `Retry-After` is a lower bound and its absence means stop, never a clamp. `caPinRefusalSentence` turns any refusal reason into one English or Chinese sentence that states the rule and the limit and never echoes input. All of it is pure: no file system, network, clock, randomness or timers, and nothing throws. The gate checks every reason and success form, the single-source bindings to the settings contract's URL judge and digest spelling, that the shared SHA-256 leaf is the only implementation in the package, that the engine address normaliser and the relay path check behave exactly as before after moving onto the shared readers, and that every refusal sentence exists in both languages without echoing its input. |
|
|
781
790
|
|
|
782
791
|
Each suite carries a floor that only moves up — a refactor that stops executing a group of
|
|
783
792
|
assertions is a failure, not a quieter pass. Guards anchor on the **installed artefact's content**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { engineCapNestedValue } from '../engineCapsCache.js';
|
|
2
|
-
import { isStatusDerivedCoarseCode } from '../engineErrorCodes.js';
|
|
2
|
+
import { LIMIT_RATE_EXCEEDED, isStatusDerivedCoarseCode } from '../engineErrorCodes.js';
|
|
3
3
|
import { clientHasVerbs, engineWireFor, INJECTED_WIRE_SETTLE_MS, noAnswerDetailFrom, sendOnce, settleInjected } from '../engineWireFor.js';
|
|
4
4
|
import { engineWireDebugEnabled } from '../engineWireTarget.js';
|
|
5
5
|
import { hostLog } from '../host.js';
|
|
@@ -135,7 +135,7 @@ function refusedWhyOf(rawCode, status) {
|
|
|
135
135
|
return 'session_not_found';
|
|
136
136
|
if (code === 'not_found.route')
|
|
137
137
|
return 'route_absent';
|
|
138
|
-
if (code ===
|
|
138
|
+
if (code === LIMIT_RATE_EXCEEDED)
|
|
139
139
|
return 'rate_limited';
|
|
140
140
|
if (code.startsWith('auth.'))
|
|
141
141
|
return 'not_permitted';
|
|
@@ -32,3 +32,6 @@ export type CheckpointDeadlineState = 'armed' | 'none' | 'unknown';
|
|
|
32
32
|
export declare function checkpointDeadlineStateOf(row: object | null | undefined): CheckpointDeadlineState;
|
|
33
33
|
export declare function unboundWayOutContent(state: CheckpointDeadlineState, lang?: UiLanguage | (string & {})): string;
|
|
34
34
|
export declare function rowBarWayOutContent(bar: CheckpointRowBar, state: CheckpointDeadlineState, lang?: UiLanguage | (string & {})): string;
|
|
35
|
+
export type DecisionRefusalWayOut = 'cancel_run' | 'newer_worker';
|
|
36
|
+
export declare function isDecisionRefusalWayOut(v: {} | null | undefined): v is DecisionRefusalWayOut;
|
|
37
|
+
export declare function decisionRefusalWayOutContent(wayOut: DecisionRefusalWayOut | (string & {}), lang?: UiLanguage | (string & {})): string | undefined;
|
|
@@ -121,6 +121,19 @@ export function unboundWayOutContent(state, lang) {
|
|
|
121
121
|
}
|
|
122
122
|
export function rowBarWayOutContent(bar, state, lang) {
|
|
123
123
|
if (bar.kind === 'lacking')
|
|
124
|
-
return
|
|
124
|
+
return lackingWayOutContent(lang);
|
|
125
125
|
return unboundWayOutContent(state, lang);
|
|
126
126
|
}
|
|
127
|
+
function lackingWayOutContent(lang) {
|
|
128
|
+
return renderMessage(msg('approval.rowUnresumable.lackingWayOut'), isUiLanguage(lang) ? lang : undefined);
|
|
129
|
+
}
|
|
130
|
+
const WAY_OUT_WORDS = Object.freeze({ cancel_run: true, newer_worker: true });
|
|
131
|
+
const DECISION_REFUSAL_WAY_OUTS = Object.freeze(Object.keys(WAY_OUT_WORDS));
|
|
132
|
+
export function isDecisionRefusalWayOut(v) {
|
|
133
|
+
return typeof v === 'string' && DECISION_REFUSAL_WAY_OUTS.includes(v);
|
|
134
|
+
}
|
|
135
|
+
export function decisionRefusalWayOutContent(wayOut, lang) {
|
|
136
|
+
if (!isDecisionRefusalWayOut(wayOut))
|
|
137
|
+
return undefined;
|
|
138
|
+
return wayOut === 'newer_worker' ? lackingWayOutContent(lang) : unboundWayOutContent('unknown', lang);
|
|
139
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { UiLanguage } from './env/uiLanguage.js';
|
|
2
|
+
export declare const CA_PIN_LIMITS: Readonly<{
|
|
3
|
+
addressMaxChars: 2048;
|
|
4
|
+
authorityMaxChars: 300;
|
|
5
|
+
fingerprintsMax: 16;
|
|
6
|
+
fingerprintMaxChars: 128;
|
|
7
|
+
bodyMaxBytes: 1048576;
|
|
8
|
+
servedMax: 16;
|
|
9
|
+
pemMaxBytes: 16384;
|
|
10
|
+
budgetMs: 120000;
|
|
11
|
+
roundMs: 10000;
|
|
12
|
+
retriesMax: 3;
|
|
13
|
+
waitCapMs: 60000;
|
|
14
|
+
jitterMaxMs: 2000;
|
|
15
|
+
}>;
|
|
16
|
+
export type CenterAddressSeat = 'invite' | 'address';
|
|
17
|
+
export type CenterAddressRefusal = 'bad_input' | 'empty' | 'too_long' | 'unsafe_character' | 'scheme' | 'userinfo' | 'percent_in_host' | 'unparseable' | 'query' | 'fragment' | 'trailing_dot' | 'ip_not_canonical' | 'plaintext_remote' | 'path' | 'fingerprint' | 'too_many_fingerprints';
|
|
18
|
+
export type CenterAddressReading = {
|
|
19
|
+
readonly ok: true;
|
|
20
|
+
readonly seat: CenterAddressSeat;
|
|
21
|
+
readonly origin: string;
|
|
22
|
+
readonly centerKey: string;
|
|
23
|
+
readonly fingerprints: readonly string[];
|
|
24
|
+
} | {
|
|
25
|
+
readonly ok: false;
|
|
26
|
+
readonly reason: CenterAddressRefusal;
|
|
27
|
+
};
|
|
28
|
+
export type TrustOriginRefusal = 'empty' | 'too_long' | 'unsafe_character' | 'scheme' | 'userinfo' | 'percent_in_host' | 'unparseable' | 'trailing_dot' | 'ip_not_canonical';
|
|
29
|
+
export type TrustOriginReading = {
|
|
30
|
+
readonly ok: true;
|
|
31
|
+
readonly origin: string;
|
|
32
|
+
} | {
|
|
33
|
+
readonly ok: false;
|
|
34
|
+
readonly reason: TrustOriginRefusal;
|
|
35
|
+
};
|
|
36
|
+
export declare function readCenterAddress(raw: string | null | undefined, seat: CenterAddressSeat): CenterAddressReading;
|
|
37
|
+
export declare function trustOriginOf(url: string | null | undefined): TrustOriginReading;
|
|
38
|
+
export type CaFingerprintsRefusal = 'bad_input' | 'prefix' | 'fingerprint' | 'too_many_fingerprints';
|
|
39
|
+
export type CaFingerprintsReading = {
|
|
40
|
+
readonly ok: true;
|
|
41
|
+
readonly fingerprints: readonly string[];
|
|
42
|
+
} | {
|
|
43
|
+
readonly ok: false;
|
|
44
|
+
readonly reason: CaFingerprintsRefusal;
|
|
45
|
+
readonly index?: number;
|
|
46
|
+
};
|
|
47
|
+
export declare function caFingerprintsOf(texts: readonly string[] | null | undefined): CaFingerprintsReading;
|
|
48
|
+
export declare function caFingerprintOfDer(der: Uint8Array): string;
|
|
49
|
+
export declare function caFingerprintDisplay(fp: string | null | undefined): string | undefined;
|
|
50
|
+
export type CaCertificateParser = (der: Uint8Array) => CaCertificateFacts | null | undefined;
|
|
51
|
+
export interface CaCertificateFacts {
|
|
52
|
+
readonly raw: Uint8Array;
|
|
53
|
+
readonly subject: string;
|
|
54
|
+
readonly notAfter: string;
|
|
55
|
+
readonly selfSigned: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface CaBootstrapRequest {
|
|
58
|
+
readonly named?: readonly string[];
|
|
59
|
+
readonly parseCertificate?: CaCertificateParser;
|
|
60
|
+
}
|
|
61
|
+
export interface CaServedCertificate {
|
|
62
|
+
readonly fingerprint: string;
|
|
63
|
+
readonly pem: string;
|
|
64
|
+
readonly selfSigned: boolean;
|
|
65
|
+
readonly subject?: string;
|
|
66
|
+
readonly notAfter?: string;
|
|
67
|
+
}
|
|
68
|
+
export type CaBootstrapRefusal = 'bad_input' | 'parser_unavailable' | 'body_too_large' | 'body_not_json' | 'body_shape' | 'served_count' | 'certificate_too_large' | 'certificate_not_canonical' | 'certificate_unparseable' | 'served_duplicate' | 'named_not_served' | 'anchor_not_self_signed' | 'unconfigured_with_fingerprints';
|
|
69
|
+
export type CaBootstrapReading = {
|
|
70
|
+
readonly kind: 'unconfigured';
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: 'served';
|
|
73
|
+
readonly certificates: readonly CaServedCertificate[];
|
|
74
|
+
readonly anchors: readonly CaServedCertificate[];
|
|
75
|
+
} | {
|
|
76
|
+
readonly kind: 'refused';
|
|
77
|
+
readonly reason: CaBootstrapRefusal;
|
|
78
|
+
readonly index?: number;
|
|
79
|
+
};
|
|
80
|
+
export declare function readCaBootstrapBody(body: Uint8Array, request: CaBootstrapRequest): CaBootstrapReading;
|
|
81
|
+
export type CaBootstrapPhase = 'idle' | 'in-flight' | 'reading' | 'waiting' | 'stopped';
|
|
82
|
+
export type CaBootstrapStopReason = 'bad_input' | 'cancelled' | 'timed_out' | 'transport_failed' | 'content_type' | 'ca_unavailable' | 'endpoint_missing' | 'unexpected_status' | 'retry_after_unusable' | 'retry_after_too_long' | 'retries_exhausted' | 'budget_exhausted';
|
|
83
|
+
export interface CaBootstrapStop {
|
|
84
|
+
readonly action: 'stop';
|
|
85
|
+
readonly reason: CaBootstrapStopReason;
|
|
86
|
+
readonly status?: number;
|
|
87
|
+
readonly retryAfterSec?: number;
|
|
88
|
+
readonly remainingSec?: number;
|
|
89
|
+
}
|
|
90
|
+
export type CaBootstrapDecision = {
|
|
91
|
+
readonly action: 'attempt';
|
|
92
|
+
readonly timeoutMs: number;
|
|
93
|
+
} | {
|
|
94
|
+
readonly action: 'wait';
|
|
95
|
+
readonly afterMs: number;
|
|
96
|
+
readonly retryAfterSec: number;
|
|
97
|
+
} | {
|
|
98
|
+
readonly action: 'read-body';
|
|
99
|
+
} | {
|
|
100
|
+
readonly action: 'proceed';
|
|
101
|
+
} | CaBootstrapStop;
|
|
102
|
+
export interface CaBootstrapState {
|
|
103
|
+
readonly phase: CaBootstrapPhase;
|
|
104
|
+
readonly deadlineMs: number;
|
|
105
|
+
readonly lastNowMs: number;
|
|
106
|
+
readonly attempts: number;
|
|
107
|
+
readonly roundDeadlineMs?: number;
|
|
108
|
+
readonly notBeforeMs?: number;
|
|
109
|
+
readonly retryAfterSec?: number;
|
|
110
|
+
readonly stop?: CaBootstrapStop;
|
|
111
|
+
}
|
|
112
|
+
export type CaBootstrapEvent = {
|
|
113
|
+
readonly type: 'begin';
|
|
114
|
+
} | {
|
|
115
|
+
readonly type: 'response';
|
|
116
|
+
readonly status: number;
|
|
117
|
+
readonly contentType?: string;
|
|
118
|
+
readonly retryAfter?: string;
|
|
119
|
+
readonly jitter?: number;
|
|
120
|
+
} | {
|
|
121
|
+
readonly type: 'checkpoint';
|
|
122
|
+
} | {
|
|
123
|
+
readonly type: 'timed-out';
|
|
124
|
+
} | {
|
|
125
|
+
readonly type: 'failed';
|
|
126
|
+
} | {
|
|
127
|
+
readonly type: 'cancelled';
|
|
128
|
+
};
|
|
129
|
+
export interface CaBootstrapStep {
|
|
130
|
+
readonly state: CaBootstrapState;
|
|
131
|
+
readonly decision: CaBootstrapDecision;
|
|
132
|
+
}
|
|
133
|
+
export declare function caBootstrapOpen(nowMs: number): CaBootstrapState;
|
|
134
|
+
export declare function caBootstrapStep(state: CaBootstrapState, event: CaBootstrapEvent, nowMs: number): CaBootstrapStep;
|
|
135
|
+
export type CaPinRefusal = CenterAddressRefusal | TrustOriginRefusal | CaFingerprintsRefusal | CaBootstrapRefusal | CaBootstrapStopReason;
|
|
136
|
+
export declare function caPinRefusalSentence(reason: CaPinRefusal | (string & {}), lang?: UiLanguage): string;
|