dsh-ptc-plus 0.5.3 → 0.5.6

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.
Files changed (49) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +3 -3
  3. package/client.cjs +3326 -2881
  4. package/compiler-core.cjs +127 -127
  5. package/compiler-core.cjs.map +2 -2
  6. package/docs/README.md +1 -0
  7. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +2 -2
  8. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -4
  9. package/docs/architecture.md +1 -1
  10. package/docs/capability-planning-components.md +6 -6
  11. package/docs/capability-projection.md +1 -1
  12. package/docs/capability-surface.md +133 -0
  13. package/docs/client-ui.md +17 -15
  14. package/docs/client-visual-contract.md +7 -7
  15. package/docs/installation.md +14 -7
  16. package/docs/panel-concept.md +171 -0
  17. package/docs/publishing.md +1 -1
  18. package/docs/release-notes.md +1 -1
  19. package/docs/releases/v0.5.4.md +79 -0
  20. package/docs/releases/v0.5.5.md +41 -0
  21. package/docs/releases/v0.5.6.md +41 -0
  22. package/docs/runtime-reference.md +14 -0
  23. package/docs/verification.md +1 -1
  24. package/index.js +117 -30
  25. package/internal/binding-adoption.js +103 -11
  26. package/internal/capability-command-receipt.js +99 -15
  27. package/internal/capability-environment.js +1108 -348
  28. package/internal/capability-plan.js +18 -2
  29. package/internal/capability-policy.js +13 -0
  30. package/internal/capability-selection.js +330 -0
  31. package/internal/direct-surface-owner.js +17 -4
  32. package/internal/edit-transport-owner.js +3 -2
  33. package/internal/host-tool-sdk.js +17 -29
  34. package/internal/message-sources.js +21 -0
  35. package/internal/program-bindings.js +13 -4
  36. package/internal/runtime-bridge-owner.js +9 -9
  37. package/internal/runtime-config.js +10 -0
  38. package/internal/session-log-view.js +47 -5
  39. package/internal/settings-compat.js +6 -0
  40. package/internal/user-bindings-owner.js +20 -3
  41. package/package.json +45 -31
  42. package/src/client-authoring-view.js +7 -8
  43. package/src/client-capabilities-view.js +871 -948
  44. package/src/client-capability-sort.js +22 -9
  45. package/src/client-copy.js +116 -294
  46. package/src/client-settings-view.js +90 -33
  47. package/src/client-styles.js +67 -19
  48. package/src/client.js +46 -21
  49. package/internal/capability-delivery-proof.js +0 -70
package/docs/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
 
13
13
  - [Architecture](architecture.md): ownership boundaries, prompt-prefix stability, runtime lifecycle, journals, and recovery.
14
14
  - [Context management](context-management.md): model-facing layers, evidence limits, progressive disclosure, and measured optimization rules.
15
+ - [Capability page contract](capability-surface.md): the capability page's concept contract — its two addresses, columns, words, receipt, single renderer, and its stated limitations.
15
16
  - [Capability Surface](capability-projection.md): typed program bindings and progressive discovery.
16
17
  - [Program Data Plane](program-data-plane.md): canonical values and result completeness.
17
18
  - [Durable / Volatile Recovery](durability-design.md): replay model and external-input boundaries.
@@ -19,9 +19,9 @@ The editor captures the most recent eligible cell at the persisted `tool/ptc-dis
19
19
 
20
20
  The editor accepts exactly one `edits` or `regex_edits` array. Exact edits require unique nonempty `old_string` matches. Each regex edit requires `pattern`, `flags`, `replacement` and `expected_matches`; replacement uses JavaScript `$1`, `$<name>` and `$$` syntax. At most 16 nonoverlapping edits are applied atomically. `internal/rejected-cell-editor.js` owns matching, expansion and CPU/source budgets.
21
21
 
22
- For an accepted edit, the nested SDK call returns `{ accepted: true, scheduled: true, target_call_seq }`. This is an acceptance receipt, not the revised computation's value or an idempotence promise. The current outer cell continues with its existing state and original return value or error. After that cell releases its worker, but before its top-level `run_code` result settles, PTC Plus dispatches the complete revised source through DSH's real `tools.execute({ name: 'run_code', ... })` pipeline. The root result retains that outer canonical value or error and forwards the derived result's Host-rendered content, images, additional contexts and, for a successful root result, turn-conclusion flag. The definition-owned `projectContent` callback is installed before dispatch starts, so derived content reaches root post-policy; `exec.deferContext` and `exec.concludeTurn` carry contexts and the successful root conclusion. Root policy may replace or block that presentation. The runtime bridge preserves existing callbacks and their property descriptors, restores only its own installed callbacks on disposal, and unwinds partial installation on failure. The next cell sees the revised bindings. A nested receipt rejected or changed before acceptance prevents dispatch; cancellation or disposal before dispatch does likewise. Removal of the final root metadata after a derived run has executed invalidates recovery evidence but cannot undo its effects.
22
+ For an accepted edit, the nested SDK call returns `{ accepted: true, scheduled: true, target_call_seq }`. This is an acceptance receipt, not the revised computation's value or an idempotence promise. The current outer cell continues with its existing state and original return value or error. After that cell releases its worker, but before its top-level `run_code` result settles, PTC Plus dispatches the complete revised source through DSH's public invocation pipeline. Registry Hosts accept the execution input through `tools.execute`; executor Hosts use the published `@deepseek-ai/dsh-tools/pipeline` `ToolExecutionPipeline.prepare`, `dispatch` and `complete` stages with the selected live transport definition. The invocation retains the actual root token as `parent`, the original `rootCallId` and the root's step admission. The Host still owns validation, policy, cancellation and final result materialization; a root model-call batch cannot carry this nested relation. The root result retains that outer canonical value or error and forwards the derived result's Host-rendered content, images, additional contexts and, for a successful root result, turn-conclusion flag. The definition-owned `projectContent` callback is installed before dispatch starts, so derived content reaches root post-policy; `exec.deferContext` and `exec.concludeTurn` carry contexts and the successful root conclusion. Root policy may replace or block that presentation. The runtime bridge preserves existing callbacks and their property descriptors, restores only its own installed callbacks on disposal, and unwinds partial installation on failure. The next cell sees the revised bindings. A nested receipt rejected or changed before acceptance prevents dispatch; cancellation or disposal before dispatch does likewise. Removal of the final root metadata after a derived run has executed invalidates recovery evidence but cannot undo its effects.
23
23
 
24
- The model-authored outer `run_code` remains the sole top-level call in assistant history. Official nested events retain the editor's real name, arguments and settled receipt. The plugin records its actual derived `tools.execute` call through public `Session.append`: the start carries losslessly detached arguments, a distinct sub-call identity, the original root ID and that still-running root's ID as its parent. The actual execution uses the root's real token as `parent`. Its settled event records the canonical error status and metadata; rendered content passes through the public scoped `tools/ptc-dispatch-log` waterfall with the real root execution. A throwing log projector falls back to the original settled content. These records describe actual executions and do not invent an assistant call, parent or completion. Recovery proves exactly one start and one later settlement for each editor and actual derived sub-call identity within its root-call/final-result window. A metadata start sequence alone cannot resolve duplicate dispatch identities; settled ID reuse outside that window remains independent.
24
+ The model-authored outer `run_code` remains the sole top-level call in assistant history. Official nested events retain the editor's real name, arguments and settled receipt. The plugin records its actual derived Host invocation through public `Session.append`: the start carries losslessly detached arguments, a distinct sub-call identity, the original root ID and that still-running root's ID as its parent. The actual execution uses the root's real token as `parent`. Its settled event records the canonical error status and metadata; rendered content passes through the public scoped `tools/ptc-dispatch-log` waterfall with the real root execution. A throwing log projector falls back to the original settled content. These records describe actual executions and do not invent an assistant call, parent or completion. Recovery proves exactly one start and one later settlement for each editor and actual derived sub-call identity within its root-call/final-result window. A metadata start sequence alone cannot resolve duplicate dispatch identities; settled ID reuse outside that window remains independent.
25
25
 
26
26
  If the public Host never invokes `presentationMeta` for this owned nested success, the bridge may capture its canonical frozen value and tentative settlement through the read-only pre-policy `projectContent` callback. Private evidence is admissible only for the exact execution token, session, parent and continuation, with no initial plugin journal, no subsequent projector call, unchanged base metadata, final success and the same canonical value object. Host value replacement, block/error, missing capture or removal of already projected metadata rejects it. The sidecar supplies only the plugin-owned actual derived settlement and root relation; it never changes the Host result or restores pre-policy content. Final root metadata remains required. The proof comes from public canonical value identity and the before/after policy callbacks, without a Host version branch.
27
27
 
@@ -8,9 +8,9 @@ PTC Plus integrates with DSH services, request bindings, prompt assembly, sessio
8
8
 
9
9
  PTC Plus must remain independently installable on unmodified official DSH distributions. Host source is read-only research evidence, not an implementation workspace for plugin features. Plugin changes must not patch host source or installed packages, introduce install-time host patches, or require a custom host build. Plugin-owned components, panels, styling, portals and public renderer replacements are valid UI choices within the consumed contracts; integration does not require every visual element or layout to be native. A locally invented extension declaration is not a published public capability. Choose among published surfaces according to the required user experience rather than assuming that a UI feature must become a historical message node. If none can satisfy the required behavior, record the actual limitation; do not substitute a custom distribution or present a compatibility fallback as delivery.
10
10
 
11
- The compatibility target is the latest available DSH release. Production behavior, configuration, tests, installation guidance, and current compatibility claims depend on public extension contracts and observed live schemas, never on a DSH version allowlist or comparison. An upstream default projection is not an extension ceiling: when public scoped registration and presentation support a plugin-owned capability, PTC Plus preserves that capability and its model-visible identity instead of deleting or renaming it to match the default. Deterministic normalization remains valid for a call that is outside the declared direct surface when the live schema proves one native target and the lowering preserves arguments, call identity, authority, and result semantics. Deterministic tests exercise the consumed contracts; model-backed and packaging acceptance runners use the installed DSH and record `dsh --version` in generated reports so failures remain attributable without turning the observed value into policy. Concrete DSH release numbers may appear only in source comments that identify historical integration or evaluation evidence and cannot influence execution or acceptance.
11
+ The compatibility target is the latest available DSH release. The manifest declares a bounded `engines.dsh` range for DSH-owned installation and startup preflight. Runtime interface selection depends on public extension contracts and observed live schemas, never on a DSH version comparison. An upstream default projection is not an extension ceiling: when public scoped registration and presentation support a plugin-owned capability, PTC Plus preserves that capability and its model-visible identity instead of deleting or renaming it to match the default. Deterministic normalization remains valid for a call that is outside the declared direct surface when the live schema proves one native target and the lowering preserves arguments, call identity, authority, and result semantics. Deterministic tests exercise the consumed contracts; model-backed and packaging acceptance runners use the installed DSH and record `dsh --version` in generated reports so failures remain attributable without turning the observed value into policy. The manifest range, its lockfile counterpart, package-admission tests and user guidance may name DSH versions to state and verify the admission contract. Those declarations do not select runtime interface branches.
12
12
 
13
- Release discovery is separated from candidate verification. Support is expressed as channels, not versions. `compat/channels.json` is generated from the official dist-tags and records, per channel, the resolved host release, the tarball integrity of every host package whose published surface the plugin probes, and whether that channel may block a release: `latest` (newest published release) and `next` (in-flight release candidate) block, while `alpha` (a pre-adaptation for a line the host has not released yet) only reports. A probe package the release does not publish is recorded with the version and integrity that release's own dependency range resolves to, so the channel still names the bytes an install receives; a probe package the release neither publishes nor depends on is recorded as absent, and the install proof rejects a graph that contains one. These records are reproducibility evidence selected by the channel declarations; they are not compatibility allowlists or runtime branches. `npm run host:channels:update` is the only way to refresh them and starts from the registry; ordinary `verify` and the full branch of `check` make no registry request and validate the tracked manifest offline. The root manifest declares the official `next` channel for the DSH packages used by development, and `host:channels:graph` moves the lock onto the release that channel resolves to; the scheduled channel workflow runs it in the same commit as a channel change. Ordinary gates read whichever graph the lock froze and never resolve a tag.
13
+ Release discovery is separated from candidate verification. Verification targets are expressed as channels; the manifest range separately bounds Host admission. `compat/channels.json` is generated from the official dist-tags and records, per channel, the resolved host release, the tarball integrity of every host package whose published surface the plugin probes, and whether that channel may block a release: `latest` (newest published release) and `next` (in-flight release candidate) block, while `alpha` (a pre-adaptation for a line the host has not released yet) only reports. A probe package the release does not publish is recorded with the version and integrity that release's own dependency range resolves to, so the channel still names the bytes an install receives; a probe package the release neither publishes nor depends on is recorded as absent, and the install proof rejects a graph that contains one. These records are reproducibility evidence selected by the channel declarations; they are not compatibility allowlists or runtime branches. `npm run host:channels:update` is the only way to refresh them and starts from the registry; ordinary `verify` and the full branch of `check` make no registry request and validate the tracked manifest offline. The root manifest declares the official `next` channel for the DSH packages used by development, and `host:channels:graph` moves the lock onto the release that channel resolves to; the scheduled channel workflow runs it in the same commit as a channel change. Ordinary gates read whichever graph the lock froze and never resolve a tag.
14
14
 
15
15
  The scheduled channel refresh resolves every channel from its dist-tag. When a channel moves it commits the regenerated manifest on an automation-owned branch, opens or updates one pull request, and dispatches the normal CI workflow once for that candidate. GitHub suppresses workflow runs from branch and pull-request events produced by the workflow's `GITHUB_TOKEN`, so the explicit dispatch is the candidate's only CI run. If no channel moved, the refresh writes the identical document and nothing is committed. The Host contract suite installs each channel on demand from the manifest into an ignored cache, proves the installed versions against the manifest, packs the plugin, and runs the execution-seam, RPC-codec, compressed Session persistence, and pathless Cordis companion contracts through a repository-external consumer that exposes the selected Host's public packages. `npm run test:host-contract -- <channel>` selects one channel, and the default selection is the blocking set. CI runs one job per channel and lets the `alpha` job report without failing the workflow. No compatibility run independently selects tags for DSH service packages, because their dist-tags need not move as one cohort.
16
16
 
@@ -65,7 +65,7 @@ capability, storage and observation rules independently of transport.
65
65
 
66
66
  **Pin one verified DSH release.** A pin makes one historical environment reproducible but turns normal upstream progress into an artificial incompatibility and allows the implementation to drift from the release users actually install.
67
67
 
68
- **Maintain a supported-version range.** A range communicates broader intent, but semver cannot prove compatibility with evolving extension contracts. Maintaining the range duplicates evidence already produced by contract and end-to-end tests while still requiring every new release to be evaluated. The package therefore declares `engines.dsh: "*"` for the Host-owned manifest preflight, preserving capability-based admission without a release allowlist. The packed contract suite runs the selected Host's public `evaluatePluginCompatibility` before importing plugin code; required service peers still establish package resolution.
68
+ **Leave manifest admission unrestricted.** A wildcard admits Host versions beyond the compatibility boundary the package declares to users. The package therefore retains a bounded `engines.dsh` range, while capability checks select runtime interfaces. A range is an admission contract, not proof that every matching release has passed testing. Updating a Host within the range does not justify removing its bounds; moving a bound requires an explicit compatibility decision and relevant Host evidence. The packed contract suite runs the selected Host's public `evaluatePluginCompatibility` before importing plugin code; required service peers still establish package resolution.
69
69
 
70
70
  **Treat the upstream default tool projection as an immutable plugin limit.** This avoids scoped presentation work, but discards capabilities that the public registry supports and can force valid model calls through lossy aliases. Defaults describe the host's built-in product choice; public extension contracts define what a plugin may add. Invalid out-of-surface calls may still be normalized when their intended native target is provable.
71
71
 
@@ -75,4 +75,4 @@ capability, storage and observation rules independently of transport.
75
75
 
76
76
  Feature completion requires evidence from the actual packaged plugin running on the selected unmodified Host, including the affected user flow. Component fixtures and public-interface unit tests validate narrower properties; they do not prove that a required renderer exists or is loaded in that distribution. A clean code review and passing deterministic checks are separate from product acceptance. Both must cover the final change before a feature is described as delivered; commit and publish authorization remain separate user decisions.
77
77
 
78
- Each upstream DSH release becomes the immediate compatibility target and must pass the public-surface, packaging, and model-backed checks appropriate to the change. The automated pull request makes an upstream tag movement an explicit source candidate; the lockfile and CI result keep its proof reproducible after the registry moves again. Users are not blocked by stale version metadata. Historical reports remain attributable through generated runtime metadata or source comments, while a passing older run never substitutes for validation against the latest release.
78
+ Each upstream DSH release becomes the immediate compatibility target and must pass the public-surface, packaging, and model-backed checks appropriate to the change. The automated pull request makes an upstream tag movement an explicit source candidate; the lockfile and CI result keep its proof reproducible after the registry moves again. When a new target falls outside the declared range, its admission bounds must be reviewed and updated with the relevant evidence before claiming support. Historical reports remain attributable through generated runtime metadata or source comments, while a passing older run never substitutes for validation against the latest release.
@@ -23,7 +23,7 @@ DSH 的公开 presentation 为 `native` 或 `ptc`。agent composition owner、
23
23
 
24
24
  `edit_run_code` 在持久化 `tool/ptc-dispatch-start` 处捕获当前 open turn 最近的可编辑 cell,按 root、parent、sub-call identity、参数与 sequence 校验正式事件。调查工具不擦除目标,后来的 settlement 不追溯改变它。调用必须且只能提交 `edits` 或 `regex_edits` 之一,并可携带 `expected_target_call_seq`;目标前置条件不一致时不派生执行。`internal/rejected-cell-editor.js` 统一拥有 schema、匹配、JavaScript replacement 语义、预算和原子源码物化。
25
25
 
26
- 接受收据为 `{ accepted: true, scheduled: true, target_call_seq }`,拒绝为 `{ accepted: false, scheduled: false, reason }`。接受只表示待执行:外层 cell 的后续语句仍使用当前状态,保留其 canonical return 或 error。外层 worker 结束后、根结果结算前,runtime bridge 通过 DSH 公共 `tools.execute()` 执行完整修订源码,并通过调用开始前已安装的公开 `projectContent` 将派生 content、images 送入根 post-policy;`exec.deferContext` 与 `exec.concludeTurn` 转发 additionalContexts 和成功根结果的 concludesTurn。成功根结果保留 Host canonical 对象,避免重新投影丢失 journal;根 policy 仍可替换或阻断这些展示内容。 runtime bridge 保留原有 callback 与 property descriptor;安装失败时撤回已安装部分,卸载时只恢复自己仍拥有的 callback。普通外层计算失败不撤销已接受编辑;取消、lease 结束或 disposal 阻止未开始的派生执行。同一根 cell 至多接受一次编辑,派生执行不能重新取得根编辑资格。
26
+ 接受收据为 `{ accepted: true, scheduled: true, target_call_seq }`,拒绝为 `{ accepted: false, scheduled: false, reason }`。接受只表示待执行:外层 cell 的后续语句仍使用当前状态,保留其 canonical return 或 error。外层 worker 结束后、根结果结算前,runtime bridge 通过 DSH 公共调用流水线执行完整修订源码:registry 宿主使用 `tools.execute()`,executor 宿主使用已发布的 `ToolExecutionPipeline.prepare/dispatch/complete`,保留原 `rootCallId`、真实 parent token 与根调用的 step admission,并通过调用开始前已安装的公开 `projectContent` 将派生 content、images 送入根 post-policy;`exec.deferContext` 与 `exec.concludeTurn` 转发 additionalContexts 和成功根结果的 concludesTurn。成功根结果保留 Host canonical 对象,避免重新投影丢失 journal;根 policy 仍可替换或阻断这些展示内容。 runtime bridge 保留原有 callback 与 property descriptor;安装失败时撤回已安装部分,卸载时只恢复自己仍拥有的 callback。普通外层计算失败不撤销已接受编辑;取消、lease 结束或 disposal 阻止未开始的派生执行。同一根 cell 至多接受一次编辑,派生执行不能重新取得根编辑资格。
27
27
 
28
28
  assistant history 保留原始根 `run_code`,正式 nested events 保留 editor 的名称、delta 参数与收据。插件通过公开 `Session.append` 记录真实派生 `run_code` 的 start/settle,实际执行的 parent token 与事件 parent 都来自仍在运行的根 transport;公开 scoped `tools/ptc-dispatch-log` 使用真实根 execution 留存内容。根结果私有 `dshPtcPlusPostEdit` 记录完整派生源码、journal、目标、editor 的 `startSeq` 与实际执行的 `executionStartSeq`;不虚构 assistant call、父调用或结算。最终 metadata 丢失不能撤销已发生效果,只使未证明状态丧失恢复资格。恢复 owner 校验根 journal 的收据、editor 和派生执行的正式 dispatch pairs、canonical 结算事实、目标变换与根/目标双重模型可见来源,按实际 root 后 derived 顺序恢复状态;cold replay 返回 recorded binding 值,不重新派发 editor 或外部效果。成功修订成为下一编辑目标。历史顶层 editor metadata 继续由其原有 generation 校验。详见 [ADR 0005](adr/0005-temporary-rejected-cell-edit-transport.md)。
29
29
 
@@ -19,7 +19,7 @@
19
19
 
20
20
  `internal/capability-policy.js` 统一校验和解析可复用规则。`defaults` 必须同时包含 `availability: enabled|closed` 和 `disclosure: host|full|on-demand|adaptive`;`categories`、`mcpServers`、`items` 可分别覆盖其中一个维度。默认 → 类别 → 已证明 MCP 来源 → 单项按维度覆盖;MCP 来源关闭是外层移除,优先于子项启用,但不删除子项偏好。每个派生条目保留两项原意、各自来源和兼容的有效 `selection`,关闭时仍保留 disclosure。未解析的非空单项 ID 保留为可撤销输入,只有真实受管库存使规则生效。管理关闭时所有实际能力沿用 host;未选用的关闭规则不参与库存过滤或归属诊断。
21
21
 
22
- `host` 保留已有 PTC 提供方说明路径;纯启停不会让其余能力变成按需。共享说明只在没有沿用宿主的消费者时移除,SDK 仅保留 host 披露的可用工具与始终可调用的编辑传输成员(`edit_run_code` 不属于管理域,每次渲染都保留其宿主签名);全体仍为 host 时保留原 SDK。Skill 全部沿用时保留宿主目录;混合披露时完整保留 host Skill 的目录说明并隐藏按需说明,不加载正文。按需项始终可获取完整契约。v3 另外区分 Skill 原生准入与有效调用路径:关闭模型 loader 不关闭独立用户入口;无可用入口时派生不可用而保留偏好,管理关闭也不将缺失入口计入实际供给或统计资格;未选用的关闭偏好不参与该事实。MCP 资源契约只列实际可用且未关闭的操作。全部功能未选用或只使用预览时不强制读取能力库存。
22
+ `host` 保留已有 PTC 提供方说明路径;纯启停不会让其余能力变成按需。共享说明只在没有沿用宿主的消费者时移除,SDK 仅保留 host 披露的可用工具与始终可调用的编辑传输成员(`edit_run_code` 不属于管理域,每次渲染都保留其宿主签名);全体仍为 host 时保留原 SDK。Skill 全部沿用时保留宿主目录;混合披露时完整保留 host Skill 的目录说明并隐藏按需说明,不加载正文。按需项始终可获取完整契约。策略世代与旧版覆盖方案同样区分 Skill 原生准入与有效调用路径:关闭模型 loader 不关闭独立用户入口;无可用入口时派生不可用而保留偏好,管理关闭也不将缺失入口计入实际供给或统计资格;未选用的关闭偏好不参与该事实。哪一层写下这个关闭不改变它的含义——保存策略里的一条规则,与策略世代之前冻结、至今未刷新的方案所带的旧版覆盖记录,都由同一个判据读成关闭。条目因此也带 `reason: 'invocation-path'`:它对应策略世代的 `availabilitySource: 'invocation-path'`,说的是「库存已证明这条自身调用路径不可达」,而不是某个人工规则(`mcp-server-disabled`)或基线未选(`baseline-not-selected`);旧版方案重算时这一类条目已被判为 closed,不会把「本会话已无路可走」的能力继续当成完整契约陈述一遍。MCP 资源契约只列实际可用且未关闭的操作;旧版层把整条路径写成一句话,操作仍齐全时保留那句话,缺一个时只列剩下的并说明一种都不剩。这句话由同一个函数(`resourceOperationNotice`)为组合与可探索的读法各生成一次,所以未被变更的会话读到的字节不变;资源 server 行的供给就是「还剩一个操作可陈述」。派生行的读法比成员行多一个输入:`metadata` 接受本 cell 程序的成员集(装配侧把桥算出的那一份交给它),所以「这句话说的是哪几个操作」是组合交付过、记录没关掉、这一步真的交给了程序三者的交集;没有观察过准入的调用方读到的是组合。宿主那张 `mcp-resource-servers` 目录由同一个归属集合重写:它列的名字只能作为 `server` 参数交给三个资源操作,所以这一步一个都没交付时目录列不出任何 server(段落整段离开),`mcp:<server>` 说明随它所属的行离开或留下,同 server 仍有工具交付时保留;没组成立方案时没有行可归属,目录只按准入判定。准入收窄的是本插件自己的契约视图而不是替换它:宿主发布的定义是面向模型的投影,不带 output schema,照它记录契约会把结果写成 `unknown`,并产生一个没有活动库存能对上的 revision。开关关闭或暂停时不应用记录里的关闭:两者都委托宿主能力与展示,组合与环境都不成立,记录仍保留、重开后再生效。全部功能未选用或只使用预览时不强制读取能力库存。
23
23
 
24
24
  只有 adaptive 项消费 `allocation.baseline`、`allocation.statistics` 和 `allocation.budget`;关闭预算约束时允许全部选中的分配候选,仍计量正文与超额。显式 full 不因任一预算选择被降级或截断。统计采集由 `capabilityStatistics.enabled` 单独拥有,不取决于管理或分配是否选用;管理关闭时从公共 live inventory 取得真实资格,记录 host 披露;Host 增删沿真实 live inventory 更新统计资格,不变更冻结配置。停止采集后仍可选用留存有效证据。只读观察既不采集也不需要启用统计分配。
25
25
 
@@ -70,23 +70,23 @@ capabilityCoverage(state, { userId, workspaceId, id, revision })
70
70
 
71
71
  Skill 目录的 `snapshot.complete` 由公共 registry 拥有,表示本次 provider 发现与 revision 稳定性已证明。暂时不完整不证明某个 Skill 已撤下:已有冻结环境保留最近完整观察或已校验、已接受的本会话 `capability-contracts` 更新所证明的 Skill 视图,不发布未完整证明的新 Skill,也不把这轮 Skill 观察计为新的统计资格。工具与 MCP 继续消费当前 live owner。冷恢复沿同一已接受契约来源保留确证撤下结果,不能由初始快照复活旧 Skill。新环境和显式刷新仍要求完整目录,失败保留旧环境;取消和真实 Host 错误保持原语义。session Skill projection 仅在实际输出变化时调用 registration-scoped `invalidate()`,不因每次父子会话准备使全局 revision 无意义变化。
72
72
 
73
- 保存普通设置不改已有会话;`/capabilities refresh` 在公共 maintenance 边界主动同步。`/capabilities list [all|skills|tools|mcp|mcp_tools] [query]` 只读检索当前受管库存,关闭项仍可查、可重新启用。`/capabilities set session|global <id> full|on-demand|closed|automatic|inherit` 明确操作范围:`session` 只改变本会话临时选择,`global` 以真实设置 namespace 和 revision CAS 保存并在同一次操作内更新本会话,不刷新其他已有会话;`inherit` 仅用于取消临时覆盖,`automatic` 撤销该项显式选择。旧组合命令的 MCP server 只接受关闭、恢复自动和取消临时覆盖;新维度命令支持独立可用性与说明规则,重新启用仍保留子项策略。ID 由命令草稿入口编码,输入匹配由正式 `input.hint` 声明。
73
+ 保存普通设置不改已有会话;`/capabilities refresh` 在公共 maintenance 边界主动同步。`/capabilities list [all|skills|tools|mcp|mcp_tools] [query]` 只读检索当前受管库存,关闭项仍可查、可重新启用;它逐行重述面板同一列的同一陈述,因此能力行分别陈述启用与披露、服务行只陈述启用,某维度记录没写下时写 `automatic`(本会话两列写 `inherit`),不拿别的层的答案替它作答,不把整行压成一个词去替未记录的维度作答。`/capabilities set session|global <id> full|on-demand|closed|automatic|inherit` 明确操作范围:`session` 只改变本会话临时选择,`global` 以真实设置 namespace 和 revision CAS 保存并在同一次操作内更新本会话,不刷新其他已有会话;`inherit` 仅用于取消临时覆盖,`automatic` 撤销该项显式选择。旧组合命令的 MCP server 只接受关闭、恢复自动和取消临时覆盖;新维度命令支持独立可用性与说明规则,重新启用仍保留子项策略。ID 由命令草稿入口编码,输入匹配由正式 `input.hint` 声明。
74
74
 
75
75
  新环境 `ptc-capability-environment/v4` 冻结总选择 `settings.contextEnabled` 与原子项,即使整组暂停也通过 accepted 计划消息保存来源;新会话和明确刷新使用最新设置。历史 v1-v3 不接受这一新维度,保持原代际解释。
76
76
 
77
77
  `ptc-capability-environment/v2` 独立记录 `sourceSettings`、`sessionOverrides` 和合并后的 `settings`;恢复校验合并结果、完整方案及精确正文。普通刷新保留临时选择,全局单项快捷操作清除同项旧临时覆盖;命名配置只导出全局源设置。恢复后的首次检索、刷新或修改均从同一已验证输入来源读取,不要求先发一个模型请求。检索不准备方案或制造统计。
78
78
 
79
- 已初始化会话在完成所有可失败的 Skill 投影准备后,追加一次正式计划消息;准备或追加失败保留旧完整环境。首轮前不得越过受保护 system head;实际命令回执在 `CommandResult.text` 内保留结构化 pending 提案,由 Host 记录配对的 `command/run` 和成功 `command/done`,首次 accepted step 才将其通知投递给模型。取消、失败、缺少配对或损坏回执不能证明临时选择,也不能由迟到的 handler 返回值重新激活。只调用导出的 `appendPluginRecord` 仍违反外部插件禁令,故不采用。全局保存成功而后续读取或会话发布失败时报告 saved-only 及原因,不回滚已经确认的全局写入,不假称本会话已更新。历史无方案的会话保持原提供方式,损坏方案通过真实发布边界关闭管理并继续宿主环境,用户可主动刷新。
79
+ 已初始化会话在完成所有可失败的 Skill 投影准备后,追加一次正式计划消息;准备或追加失败保留旧完整环境。首轮前不得越过受保护 system head。会话选择由本会话日志中的选择记录(`ptc-capability-selection/v1`)决定,与命令回执无关:回执只报告该记录、待投递方案或保存结果,缺少、失败、未配对或损坏的回执既不能证明也不能撤销一项选择,迟到的 handler 返回值同样不能重新激活它。日志没有任何选择记录时(0.5.4 及更早没有这条记录,只把选择写进方案快照的 `sessionOverrides`),同一条读(`capabilitySelectionOf`)把最新一条以 `user/message` 投递的方案消息的 `sessionOverrides` 折算为该记录的等价形态并返回 `decided`(整选择词与维度规则两种拼写同义,比较按决定而不是拼写),使升级后的首次准备原地恢复那条方案、不从空集重算、不静默撤销旧选择;有记录时仍以记录为准,读到该旧形态后的下一次写入把全部选择重述进新记录。只存在于命令回执提案里的方案不由这条读覆盖:它仍由 `recordedPlan` 在恢复路径读取,首次准备只在该读到的选择与那条方案的选择逐项相等时原地恢复它,否则按该组合自己的 `sourceSettings` 与记录重算,那条提案自己的会话选择因此不被恢复(`docs/panel-concept.md` §9 记作未交付)。命令已组合出尚未 accepted 的方案时,才在 `CommandResult.text` 内保留结构化 pending 提案,由 Host 记录配对的 `command/run` 和成功 `command/done`,冷启动据此恢复该方案消息;该提案就是那条方案消息,其快照携带当时的 `sessionOverrides`:在当前代际它重述已记录的选择,在 0.5.4 及更早它可能就是那个会话选择唯一的载体;无论哪种,它都不新增也不代替记录。只调用导出的 `appendPluginRecord` 仍违反外部插件禁令,故不采用。全局保存只按读取到的 revision 写入 saved 列(`capabilityOverrides`/`capabilityPolicy`),不发布也不重算本会话方案,方案由下一步从记录与其来源设置重算(已有冻结来源的会话仍以该来源为准,直到用户显式刷新),因此保存之后不存在「全局已存、会话失败」的中间状态。历史无方案的会话保持原提供方式,损坏方案通过真实发布边界关闭管理并继续宿主环境,用户可主动刷新。
80
80
 
81
81
  家族资格顺序和单调观察修订独立于可淘汰样本保存在统计文件的 `families` provenance 中;缺失或损坏的 provenance 不作为有效统计。
82
82
 
83
83
  正式 `tool/result` 的 `dshPtcPlusCapabilities` 元数据记录 `ptc-capability-evidence/v1` 的方案 digest、展开与使用身份。恢复按原方案和当前 ordered surface 中完整契约及依赖的实际文本去重;计算内展开不等于模型可见,选用说明恢复时在独立预算内补回近期实际使用且已展开的 API 契约及依赖,不补回 Skill 正文,不改变 binding 保留规则。`run_code` 的正式 output presentation metadata 与 `edit_run_code` 的派生结果共同携带证据。
84
84
 
85
- 设置清单通过只读 `ptcPlusCapabilities/invoke` 的 `catalog` 操作读取 code agent 当前的公共工具与 Skill inventory,以及已捕获 prompt sections 的 MCP server 目录,不创建模型请求、发布方案或加载 Skill 正文;`inspect` 独立提供冻结会话方案。目录的 `name` 与 `source` 仅为 UI 展示:普通 Tool 说明来自 DSH 注册表,捕获的 MCP owner section 才能证明具体服务器;Skill 来源取公开 provider/source,跨 agent 来源冲突标为未确认。它们不进入冻结能力快照、修订或模型说明。没有可观察 code agent 时展示明确空状态,读取失败保留最后观察结果及已保存选择,可用状态改为未确认。
85
+ 设置清单与面板读的是同一条读:只读 `ptcPlusCapabilities/invoke` 的 `session-catalog` 操作。指名会话时目录取自该会话的 header,供给来自该会话作用域自己的声明(或该会话记录的冻结面)+ 已保存配置 + 该会话自己的日志;未指名时只读 `hostSupply({})`,那是宿主在进程作用域的声明(不含 preset 在 agent 作用域注册的条目),不是任何会话的陈述,因此不充作会话的行集。会话作用域还在时,清单读该作用域的注册表视图、Skill 层与该作用域贡献的 prompt sections;作用域已不在时读会话记录的冻结方案,并因此不需要可刷新的运行时;记录没有冻结过面时(没有方案、方案损坏、组合时没有要求库存——最后一种由记录自己的 `settings` 经 `requiresCapabilityInventory` 判定,与组合时同一个判据)这次读失败并点名缺失的记录,不返回空行集。它不创建模型请求、发布方案或加载 Skill 正文;`inspect` 独立提供冻结会话方案。目录的 `name` 与 `source` 仅为 UI 展示:普通 Tool 说明来自 DSH 注册表,捕获的 MCP owner section 才能证明具体服务器;Skill 来源取公开 provider/source,调用资格取该次供给的声明;冻结面只带 id、name、category 与调用资格,不带 provider/source 桶,所以冷会话的 Skill 行来源写「技能」而不写桶名——一份供给只有一个工作目录,因此不存在需要标注的跨 agent 冲突。它们不进入冻结能力快照、修订或模型说明。某一来源读不出时整次读失败,页面在表格上方给出原始错误与重试并保留上一次成功结果,不把没读到的供给画成空表,也不给条目另加「未确认」这类状态。
86
86
 
87
- 设置刷新按钮通过只读 `targets` 获取活跃 PTC 会话身份,并要求明确选择目标;星光菜单从公共 slot 读取当前会话的命令可用性,与绑定编写共用输入框保护,将 `/capabilities refresh` 预填到空输入框并关闭菜单,等待用户发送。设置按钮由 `CapabilityRefreshButton` 通过 authenticated `commands.execute` 直接执行;最终都委托同一 Host 刷新 owner。身份观察不读取或准备冻结方案,管理关闭时仍可主动同步关闭配置。目录/方案重读保持只读。Client 在取消、断线、preset 改变、会话切换、卸载或插件关闭后丢弃迟到回执;停止等待不表示撤销已提交的 Host 效果。
87
+ 设置刷新按钮通过只读 `targets` 获取当前 live 会话身份,并要求明确选择目标;星光菜单从公共 slot 读取当前会话的命令可用性,与绑定编写共用输入框保护,将 `/capabilities refresh` 预填到空输入框并关闭菜单,等待用户发送。设置按钮由 `CapabilityRefreshButton` 通过 authenticated `commands.execute` 直接执行;最终都委托同一 Host 刷新 owner。身份观察不读取或准备冻结方案,管理关闭时仍可主动同步关闭配置。目录/方案重读保持只读。Client 在取消、断线、preset 改变、会话切换、卸载或插件关闭后丢弃迟到回执;停止等待不表示撤销已提交的 Host 效果。
88
88
 
89
- 管理默认关闭。设置工作台分为能力、上下文、统计、配置四个页签。能力页默认直达清单,名称下展示精确 ID,类型和来源独立显示;行内启停只修改可用性,上下文选择、常用集与继承规则在单项详情中独立编辑。筛选在独立小窗中按需打开,提供类型、来源、规则、常用与可用状态筛选;五列表头支持升序、降序、默认三态排序,会话列表复用同一展示排序 owner。清单支持勾选多个条目(表头复选框选择当前筛选结果);批量设置打开一次性小弹窗,将所选真实可用目标固化为单项变更,确认才写入,会话工作台以同样的选择方式把批量选择暂存为待应用更改,由底部按钮决定应用到会话或全局;默认、类别和来源的持久继承规则使用独立入口。类型切换清除不兼容来源,Tools 与 MCP 工具的浏览入口区分,来源规则只使用已证明的 server 身份。详情区分保存值与明确选定会话的结果。上下文页以能力说明、说明恢复、结果与日志三个固定目的地组织双栏设置,各项开关及额度独立,关闭保留参数;预算预览位于能力说明详情。全部开关使用官方 capsule track、圆形 thumb、尺寸和主题 token。统计页可切换查看所选活跃 PTC 会话的当前工作区或全局使用数、合格家族样本数和覆盖率;不完整窗口或不可用证据保持明确状态。能力说明的预算预览从该会话当前 SDK/Skill/MCP 清单、已保存配置与实际统计调用同一纯方案 owner,显示完整/按需/关闭选择、原因、正文大小、包含共享依赖的总预算和超额。观察通过 `allocation` RPC,使用只读 assembly observation,不准备或发布会话方案,不登记样本、读取 Skill 正文、调用工具或请求模型;目标退出和迟到回复会失效。配置序列化由 Client 完成,用户无需编写 JSON;最低样本数超过窗口等无效输入不提交。已有配置中暂不可用的能力选择保留并可撤销。配置页以左侧命名配置库、右侧所选详情组织;唯一保存当前设置、导入和更多动作在列表下方,会话观察另行展开,与已保存配置分开。`capabilityProfiles` 的 `ptc-capability-profiles/v1` 文档保存最多 100 份具名能力设置,支持命名保存、重命名、删除、文件导入导出和一次公共设置 mutation 切换;导入不自动应用,同名导入生成新名称。会话观察同时提供源设置,用户可读取并命名保存,不复制统计证据或计算状态。切换配置不刷新旧会话,明确选定目标的正式 Host 命令才提交刷新;原冻结方案继续展示选择、原因、覆盖率、显式超额和待刷新状态。格式与边界见 [ADR 0040](adr/0040-separate-capability-configurations-from-session-observations.md)。有界 `capabilities.search` 的原接口保持兼容,见[能力投影](capability-projection.md)。大结果和日志使用宿主 spill 服务保留完整展示,存储失败回退原文;canonical 程序值不受预览影响。
89
+ 管理默认关闭。设置工作台分为能力配置、提示设置、使用统计、提示文本和配置方案五个页签。能力页挂的是唯一能力面(见 [能力面:概念契约](capability-surface.md)):设置入口陈述保存·启用与保存·披露两格并可写(服务行的保存·披露格陈述 `各成员自定`,没有控件,§8.1a),本会话两列整列不存在;单项详情弹窗与筛选小窗随该契约删除。搜索、类别与来源筛选仍在页内工具条上,页面默认按供给顺序列出,每个可比较值的列表头都提供升序、降序、回供给顺序三态排序(回执列陈述整句,不参与)。清单逐行勾选多个条目,表头不提供全选;批量设置打开一次性小弹窗,把所选能力行各自被改的维度提交为逐项写入,确认才写入(服务行不参与,它自己的保存格编辑 `mcpServers.<server>`,§8.1a);会话能力面板在同一入口选定一次维度,确认后对每条已勾选目标提交同一条会话命令,不暂存;默认、类别和来源的持久继承规则使用独立入口。类型切换清除不兼容来源,Tools 与 MCP 工具的浏览入口区分,来源规则只使用已证明的 server 身份。上下文页以能力说明、说明恢复、结果与日志三个固定目的地组织双栏设置,各项开关及额度独立,关闭保留参数;预算预览位于能力说明详情。全部开关使用官方 capsule track、圆形 thumb、尺寸和主题 token。统计页可切换查看所选活跃 PTC 会话的当前工作区或全局使用数、合格家族样本数和覆盖率;不完整窗口或不可用证据保持明确状态。能力说明的预算预览从该会话当前 SDK/Skill/MCP 清单、已保存配置与实际统计调用同一纯方案 owner,显示完整/按需/关闭选择、原因、正文大小、包含共享依赖的总预算和超额。观察通过 `allocation` RPC,使用只读 assembly observation,不准备或发布会话方案,不登记样本、读取 Skill 正文、调用工具或请求模型;目标退出和迟到回复会失效。配置序列化由 Client 完成,用户无需编写 JSON;最低样本数超过窗口等无效输入不提交。已有配置中暂不可用的能力选择保留并可撤销。配置页以左侧命名配置库、右侧所选详情组织;唯一保存当前设置、导入和更多动作在列表下方,会话观察另行展开,与已保存配置分开。`capabilityProfiles` 的 `ptc-capability-profiles/v1` 文档保存最多 100 份具名能力设置,支持命名保存、重命名、删除、文件导入导出和一次公共设置 mutation 切换;导入不自动应用,同名导入生成新名称。会话观察同时提供源设置,用户可读取并命名保存,不复制统计证据或计算状态。切换配置不刷新旧会话,明确选定目标的正式 Host 命令才提交刷新;原冻结方案继续展示选择、原因、覆盖率、显式超额和待刷新状态。格式与边界见 [ADR 0040](adr/0040-separate-capability-configurations-from-session-observations.md)。有界 `capabilities.search` 的原接口保持兼容,见[能力投影](capability-projection.md)。大结果和日志使用宿主 spill 服务保留完整展示,存储失败回退原文;canonical 程序值不受预览影响。
90
90
 
91
91
  组件和接入证据见 `test/capability-plan.test.js`、`test/capability-statistics.test.js`、`test/capability-environment.test.js`、`test/plugin-program-bindings.test.js`、`test/context-result-preview.test.js` 与能力设置 Client 用例。固定 7 项普通任务加 1 项 canary 的 Command Goat / DeepSeek V4.1 Flash 付费配对已运行并完成 16 份盲评。插件侧盲评总分为 correctness 22/24、efficiency 15/24、clarity 21/24,原生基线为 22/24、10/24、21/24;机器验收因原生基线 3 项超过预设调用或 token 上限而阻止。全任务 traffic 为插件 132,332、基线 340,712(普通任务排除 canary 后为 122,933 对 325,862),这是一轮单 replicate 结果,不构成普遍收益保证。
92
92
 
@@ -42,7 +42,7 @@ await capabilities.inspect({ symbols: ["repl.state", "code.run"], budget: 2 })
42
42
 
43
43
  当前 replay 分类为 `recorded-value`:PTC journal 会在 cold replay 返回已记录的 canonical value,不重新 dispatch tool。它不表示外部 effect 被撤销、重做或验证。`owner-replay`、`volatile` 与 `unknown` 已属于 metadata vocabulary,但只有 owner/DSH 提供证据后才能声明。
44
44
 
45
- explorer 不调用 capability、不提升 authority、不读取隐藏服务、不触发辅助模型请求。`tools` metadata 来自执行时 agent scope 的 live schemas;`repl.state` 与 `code.run` metadata 由插件自身契约提供。模型若要根据探索结果决定下一步,仍会发生正常的后续 turn。当前公共扩展面没有跨 prompt assembly 与 runtime dispatch 的冻结 token,因此定义变化不能被描述成原子 snapshot。
45
+ explorer 不调用 capability、不提升 authority、不读取隐藏服务、不触发辅助模型请求。`tools` metadata 来自执行时 agent scope 的 live schemas,并且只取本 cell 程序绑定里真实可调用的成员:metadata 与可调用的 `tools.*` 是同一个集合,所以本会话记录关闭的能力和这一步没有交付的注册定义都不在其中——「探索得到」与「调用得到」不会分叉。`skills` 与 `mcp` 两个命名空间是派生行:它们的契约本身就是一句「怎么调」,所以除了组合交付过、记录没关掉,还要问这一步的程序真的拿到了那个共享操作——桥把本 cell 的成员集交给 `metadata`,共享加载器不在这份成员集里时 Skill 行只保留用户入口或整行离开,资源 server 行只陈述这一步交付的操作、一个都不剩时不再是这一步的能力;没有观察过准入的调用方读到的是组合(`internal/capability-environment.js` 的 `metadata`,装配侧在 `internal/runtime-bridge-owner.js`)。`repl.state` 与 `code.run` metadata 由插件自身契约提供。模型若要根据探索结果决定下一步,仍会发生正常的后续 turn。当前公共扩展面没有跨 prompt assembly 与 runtime dispatch 的冻结 token,因此定义变化不能被描述成原子 snapshot。
46
46
 
47
47
  能力管理开启时,同一冻结方案拥有启用与披露选择,当前宿主契约拥有首轮说明、按需检索及编译前实际成员投影。可用性与说明分别选择;host 项继续保留原说明路径,只有完整或按需项由方案替代其 SDK 说明。分配、统计采集、恢复与预览各自独立;见 [ADR 0043](adr/0043-compose-capability-and-context-policies.md)。配置保存不重排已有会话;`/capabilities refresh` 同步环境并提交持久通知。search 的字节边界不能独自证明完整任务 token 降低;接入证据见[公共接口覆盖](context-public-interface-coverage.md),格式和恢复路径见[组件说明](capability-planning-components.md)。
48
48
 
@@ -0,0 +1,133 @@
1
+ # 能力面:概念契约
2
+
3
+ ## 0. 这份文档约束什么
4
+
5
+ 「能力面」是唯一一个陈述**某个地址上、某条能力给不给、给多少**的页面。它只有一个渲染器、一套词、一条写通道、一种回执。多入口合法,多页面非法。
6
+
7
+ 本文决定形状。代码与本文不一致处,代码是缺陷;本文与下面这条红线不一致处,本文是缺陷:
8
+
9
+ > 一格的取值不得由「某个进程/服务/运行时/命令没有在运行,或某个全局开关没有启用」改变。判定:把那个来源摘掉,这个值会变吗?
10
+ >
11
+ > 两列都陈述各自记录的字:记录写 `automatic` 就上屏 `automatic`,记录写 `closed` 就上屏 `closed`;保存列没为这个对象写下就写 `自动`,本会话列没有记录写 `继承`——绑定行的记录是采纳记录,它写 `使用`/`不使用`/`记录损坏`,没写下时回执写 `未写下`,不借用 `继承`。解析(这些字在运行时意味着什么)属于行为,不属于页面,任何一步解析的结果都不上屏;由 server 层记录作答、而成员自己的条目没有写下那一维时,回执列点名那一层(§8.1b)。本会话列的样式(行左缘色条、启用格内的状态标记、词的颜色与字重)只让这些字更快被读出,不新增值、不改写入判定:一个状态既不被样式创造,也不因样式缺席而消失。保存列的样式同理只让保存列自己的字更快被读出:`开启`/`关闭` 用成功/错误色并加粗、`自动` 用业务色,所以没有本会话列的设置入口也读得出这份记录把哪些对象写成关闭。两列的样式都不表示这一行在这里得到什么:保存条目、类别规则与 `mcpServers.<server>` 规则在运行时谁压住谁属于解析(§8.1b、§8.1c),既不上屏,也不成为另一列的颜色。
12
+
13
+ 非目标:不改冻结方案语义与 `/capabilities refresh` 的同步边界;不改写通道(一个写者、一种回执);统计采集与预算预览不在本页(见 §5)。
14
+
15
+ ## 1. 概念
16
+
17
+ | 概念 | 回答 | 边界(属于/不属于) | 后果 | 邻居 |
18
+ | --- | --- | --- | --- | --- |
19
+ | **页面** | 哪些决定必须共用一套词、一条写通道、一种回执 | 属于:对象集、维度集、每地址一列值、一条写通道、一次全成功或全失败的读。不属于:打开它的位置、容器、显示多少列 | 同一(对象, 地址)处处同值、同词、同记录、同回执;任一项不同即第二个页面 | 组件(机制);入口(到达位置) |
20
+ | **入口** | 从哪来、这次带来哪些地址 | 属于:打开位置、地址集、跨越生效边界的动作。不属于:任何值、任何词、列义(行集不由入口挑选,而随它固定的地址集推出:绑定采纳没有保存地址,所以绑定行只出现在会话入口;设置入口读未点名会话的宿主声明,会话入口读该会话的声明面,两者是同一份读的两个作用域,入口不能只挑其中一部分行) | 只能缩小**决定集**,不能缩小地址集;地址集的变化只表现为整列存在/不存在 | 页面;地址 |
21
+ | **地址** | 这条决定写进哪份记录、从哪一刻被读到 | 属于:新会话默认/本会话两个值及其生效边界。不属于:值本身、观察对象、任何运行状态 | 两份记录互不改写;「已保存」不等于「已生效」 | 观察对象(读谁的事实) |
22
+ | **供给** | 这个地址上有哪些对象各自可以被单独决定 | 属于:该地址的声明面(宿主对该作用域声明的工具、Skill、MCP 服务、绑定条目)。不属于:配置、记录、证据、统计、装了什么 | 供给没有就没有行;能单独决定才成行 | 规则的适用面(规则谈论尚未供给的对象) |
23
+ | **给不给** | 这个地址上这个对象给不给 | 属于:给/不给,以及没有选择时由规则或宿主推导。不属于:给多少、能不能跑、装没装上、用没用过 | 不给时说明、发现、执行三面一致地不体现它;不删偏好、不删行 | 给多少;供给;证据 |
24
+ | **给多少** | 给的时候契约以什么方式、占多少上下文 | 属于:沿用宿主/完整/按需/按依据分配,及其依据与额度参数。不属于:可执行性、实测占用、统计样本 | 显式完整不被预算降级;超预算被陈述但不改决定 | 观察(预算预览与覆盖率) |
25
+ | **规则** | 一个还没有被逐个决定的对象,值从哪来 | 属于:默认地址上的默认/类别/来源/单项覆盖顺序与区域参数。不属于:行、本会话记录、观察 | **只有默认地址需要规则**,因为它要陈述尚未供给的对象;本会话地址只有记录 | 行决定(优先级见 §2 裁决三) |
26
+ | **观察** | 已经发生了什么/照现在会得到什么 | 属于:覆盖率、样本状态、预算占用、已投递方案与当前记录的差异。不属于:决定的值、控件、行集、任何「能不能改」的条件 | 永远只读;缺就是空表或一句样本状态,绝不让控件消失或变灰 | 决定;证据;地址 |
27
+ | **证据** | 这个会话里有没有被接受执行证明拿到过 | 属于:已结算结果里的 used。不属于:选择记录、统计覆盖、模型是否知道 | 有就是标记,没有就是没有那件事;不属于决定页(裁决四) | 观察(派生);给不给(允许) |
28
+ | **回执** | 这条决定留下哪张回执 | 属于:写入者给出的记录地址与内容。不属于:决定的值、证明程度 | 一次写入一条回执;回执点名写进哪份记录、什么值 | 证据(内容 vs 地址) |
29
+
30
+ **写权与控件是两个词,按地址种类定义。** 地址有两种:**对象地址**写某一条能力自己的条目,**规则地址**写某个作用域的规则(例如 `mcpServers.<server>`)。写权只回答「这一格写哪条地址」——会话入口的格写本会话记录,设置入口的格写保存文档;入口一打开就固定,与当前可写性无关。控件存在只回答「这次入口是否固定了这一格所写的那条地址」:固定了就一定有控件,只读或插件停用只把它禁用、不撤掉,别的层为这一维作答也不撤掉。服务行陈述的是规则,它的保存格编辑的就是那份规则文档里的那一条,所以这条定义对服务行同样成立,不需要例外。
31
+
32
+ ## 2. 四条裁决(均以反例定,不以偏好定)
33
+
34
+ **裁决一:第一维用「启用」,废「可用性」。**
35
+ 反例:产品里没有「并发上限」,本会话也没采纳「写入前备份」。用「可用性」时「并发上限」那格只能写「不可用」——一个按不动的控件,而「不可用」不是值、不是决定、不在任何记录里;救法只有灰掉一格或一格写「可用·未启用」。
36
+ 判据:**这一格的控件按下与不按下的区别,是否由本页写下的一句话造成?** 不是 → 不许作带控件列的值。
37
+
38
+ **裁决二:第二维用「披露」,废「说明方式」,且取值必须换成「谁读得到、从哪一刻」。**
39
+ 反例:磁盘满、备份没建立,人要「别解释」但模型必须知道。用「说明方式」时这格要写「不说明」,而「不说明」不是一种说明方式:写「摘要」与人要求相反,留空与「缺失即没有那格」冲突,新增「无」则列名与取值自相矛盾。
40
+ 判据:**列出该列名全部合法取值;若存在常见会话使这格在列名 A 下必须写 A 不承认的值,而列名 B 下写得出一个真实地址,取 B。**
41
+
42
+ **裁决三:保存与本会话是两个概念、两格。**
43
+ 反例:项目记录「写入前备份=开」是三周前别人保存的;本次会话要跑一次性实验必须关,团队默认必须保持开。一格一值时「下次开会话会怎样」与「这一格现在是什么」答案相反。
44
+ 判据:**存不存在一个合法会话,使两份记录的当前值相反、且两个值都要被读到?** 存在 → 两个概念两格。
45
+
46
+ **裁决四:证据列移出决定页,换成「回执」列。**
47
+ 反例:还没测时每行证据格空着——有格无值;测了且与决定相反时同一行两个真值来源矛盾(启用=是,证据=未建立);证据会馊,要加时间或重测,那格就同时写请求与结果。
48
+ 判据:**删掉这一列,本页还有没有哪个决定因此不可判定?** 删证据,每个决定照样可判;删回执,「这条决定去哪对账」不可判。
49
+
50
+ ## 3. 三条不变式(改写后)
51
+
52
+ 1. **入口只能缩小这批决定,不能缩小这些决定要读的地址;一个决定只要还在页上,它需要的全部地址就必须同时在场。**
53
+ 反例:从「项目」入口只看到保存值「开」,而这一回合跑的是会话记录里的「关」——每个字都为真,屏幕在说假话。
54
+ 2. **带控件的格子只写决定,并且它自己就确定自己的地址;一格的读法若需要同行另一格才能确定,必须拆成两格或把地址写进格子。**
55
+ 反例:「披露=仅模型」在保存=开时指「下一会话第一格读得到」,在会话=关时这话不成立。值没变、地址由邻格决定——一格一值两地址,比一格两值更难发现。
56
+ 3. **缺失是该地址上的一份「未写下」回执;「没有那一格」只表示该坐标不在此页地址集,且此页必须能报出自己的地址集。**
57
+ 反例:没有这一版产品/本会话还没决定/决定被撤回,三种缺失在屏幕上一模一样;恢复会话时读到空,分不清「从未写下」与「写下又撤回」,而后者可能已按旧值跑过。
58
+
59
+ ## 4. 页面形状与入口
60
+
61
+ 七列:`对象 | 类型 | 来源 | 保存·启用 | 保存·披露 | 本会话·启用 | 本会话·披露`,外加 `回执` 列(会话入口)。
62
+
63
+ | 作用域 \ 入口 | 会话入口(固定本会话) | 设置入口(固定新会话默认) |
64
+ | --- | --- | --- |
65
+ | 保存 | **只陈述**(本次入口没有固定它) | 陈述 + 控件 |
66
+ | 本会话 | 陈述 + 控件;无记录写 `继承` | **整列不存在**(该记录在本页没有所有者) |
67
+
68
+ 控件存在 ⟺ 该格陈述的地址被这次入口固定。写权在打开时确定,显示永不改变写权。
69
+
70
+ 由此推出两条产品事实,不需要另加规则:在会话里看得到默认值但改不了它——要改默认就换入口;保存的改动到新会话的第一次读取才被读到,它不等于「已生效」。
71
+
72
+ 每个取值都是它那一列问题的答案,列名对每个取值都成立:
73
+
74
+ - `保存·启用` / `保存·披露`:配置为**这个对象**写下的那一维的值(`启用` / `关闭`,或四种披露之一)。每一维独立判断:记录没为这个对象写下这一维时写 `自动`——那是「这一维在这份记录里没有值」,不是一个被推导出来的默认。分类规则、成员行上的 server 规则与文档底层都会在运行时为这个对象作答,但那是解析:它们不是这个(对象, 地址)持有的字,因此不上屏、不改值,也不撤掉控件(§8.1c)。
75
+ - `本会话·启用` / `本会话·披露`:会话入口的能力行两格是下拉,写的是本会话记录对这一维的决定;记录没写就写 `继承`。由 server 层记录决定的那一维,值列仍写 `继承`(这一对象自己的记录没有字),回执列点名那一层(`经 mcpServers.<server>`)——那一层的规则由它自己那一行写。能力行的两格是控件而不是陈述:因为值列写的是这一格自己的记录,写下去一定看得见;绑定行的两格由采纳记录的形状决定,见 §8.4。
76
+ - `保存·披露` / `本会话·披露`:`人机·原文·首轮` / `人机·全文·首轮` / `仅模型·目录·首轮` / `仅模型·分配·不重读`——前两半回答「谁读得到」(人机同读/仅模型),后半回答「从哪一刻」(首轮起/不重读)。记录没为这个对象写下时,保存列写 `自动`、本会话列写 `继承`;MCP 服务无自身披露,两格写 `各成员自定`。
77
+ - `回执`:这条决定留下哪张记录,以及那份记录在该行上**写下的字**:`本会话记录 · <dimension> <记录原文>`;由上一层记录决定时写 `本会话记录 · 经 <layer> · <dimension> <记录原文>`。该地址没写下时写 `未写下`。绑定行的记录是采纳记录,写 `绑定采纳记录 · 使用/不使用/记录损坏`,没写下时同样写 `未写下`。
78
+
79
+ ## 5. 观察面不在本页
80
+
81
+ 统计、预算预览、覆盖率只有被试(会话家族 × 工作区 × 时间窗),不落在任何行上。它们不属于本页;若留在设置里,必须自认被试,且不得借用本页的列、行与分区标题——取值词表共用是唯一例外,见 §8.6。ADR 0040 后果段「观察需要一个活跃 PTC 会话」与本契约冲突:本页观察不落在任何行上,而 ADR 仍把它写成后果。两者由 ADR 0040 拥有,本契约只能记录冲突与取舍需求(观察面留在设置里时必须自认被试,或由 ADR 修订把这条后果收窄),不能单方面宣布它失效。
82
+
83
+ ## 6. 唯一渲染器
84
+
85
+ 本页的渲染器是 `src/client-capabilities-view.js` 的会话能力面。**出现第二个渲染器即缺陷**:任何入口都必须挂它,不得自带列、词、控件或回执。
86
+
87
+ - 设置页工作台的能力详情栏、`tools.edit` 弹窗随本契约删除。
88
+ - 词表由本页声明,任何界面不得新增同义名:`是否启用/上下文/不单独设置/自适应/规则结果(default · default)/未应用` 一律退场。`按依据分配` 仍是分配依据(自适应如何分配)的取值名,不是披露列的第五个词;`可用性/说明方式` 只作为层级规则编辑器的规则维名存在,不是本页的列名(列名是 `保存·启用`/`保存·披露`/`本会话·启用`/`本会话·披露`)。
89
+ - 结构测试:只允许一个能力面渲染导出;再冒出一个即红。
90
+
91
+ ## 7. 证伪
92
+
93
+ 1. 摘掉运行时或关掉任一全局开关,两列都不变:两列都陈述各自记录写下的字,解析不上屏,所以没有一格跟随当前配置的底层。记录没写的那一维:保存列写 `自动`、本会话列写 `继承`,它们是「这里没有记录」,不是被推导出来的默认。
94
+ 2. 换入口,只有地址集与写权变:地址集决定整列存不存在,能陈述的行随之增减,而词、值、回执不变。
95
+ 3. 同一(对象, 地址)在两个入口给出同一值、同一词、同一条记录、同一种回执。
96
+ 4. 屏幕不出现「未观察/未记录/未证明/未确认/不可用/暂不可用/未启用/未应用」任何变体。
97
+ 5. 从任意入口都读得懂每一格:遮住同行其他格后,该格的地址仍可判定。
98
+
99
+ ## 8. 显式限制
100
+
101
+ 以下是本契约无法原样兑现、必须以限制形式承认的点。它们不是实现缺口,而是契约自身形状的后果。
102
+
103
+ **8.1 会话入口不固定保存地址,因此保存两格只陈述。** 会话入口固定的是本会话记录,不是新会话默认;控件只落在这次入口固定的那个地址上,所以 `保存·启用` 与 `保存·披露` 在该入口只有陈述。要改默认必须换入口——设置入口固定新会话默认,且保存的改动到新会话的第一次读取才被读到,它不是「已生效」。若将来要给会话入口写权,须先在本契约里给「从会话里保存」这个动作一个地址与一条回执,而不是让一格兼任两个地址。
104
+
105
+ **8.1a 服务行的保存格编辑规则,不参与批量。** 服务行陈述的是 `mcpServers.<server>` 这条规则,它的保存格编辑同一份规则文档里的那一条(选 `自动` 即删掉该维,§8.2)。它没有披露控件,披露格写 `各成员自定`:披露由成员各自决定(§8.3)。批量写的是对象条目,所以不写服务行——那一维由它自己那一格写。
106
+
107
+
108
+ **8.1b 成员某一维由谁作答,只由**本会话记录**里服务那一行写了什么决定;成员自己写下的字优先陈述。** 会话入口陈述的是记录,所以为成员作答的是记录里 `mcpServers.<server>` 那一条(不是保存文档里的同名规则——那是解析,见 §8.1c):它为某一维写下一个不是 `自动` 的字,才为该服务的成员作答,回执点名那一层。记录写 `自动` 是另一件事:那是这一维的**删除**,合并时把那一维从规则里去掉(与保存地址删掉对象规则同一件事,§8.2;`test/capability-environment.test.js` 的「session choices migrate combined preferences independently and reject unknown dimension evidence」用一条物品规则演示同一条折叠——会话 `自动` 让保存的 `关闭` 从合并策略里消失,服务条目走同一条路),所以该维不再由服务作答,成员回到类别/默认那一层——本页不陈述那次回落,成员行仍按「自己没写」写 `继承`;记录**没写**这一维才是 `继承`:它对规则不出声,保存地址的答案原样保留。两个词因此在同一格里并排时不是同义词:`继承` 不出声,`自动` 删掉这一维。成员自己的条目写了这一维时,作答在成员这条地址上:值列与回执都陈述成员写下的字,回执不点名服务——点名会与同一行的值列相反(值列说这一行写了这一维,回执说这一维属于上一层)。代价是本页陈述记录、不陈述规则链的优先级:运行时先取服务那一层(由保存文档与记录合并得到)的答案,所以成员那格写 `启用` 不保证该成员在这个会话里被给到,要知道谁压住谁只能读服务行自己的那一格。控件不受影响:写权只由这次入口固定的地址决定(§1),不由别的层是否作答改变。
109
+
110
+ **8.1c 保存格只陈述为这个对象写下的那个条目。** 一行一格只回答「这份记录为这个对象写了什么」:`policy.items.<id>`(服务行是 `policy.mcpServers.<server>`)里写下的那一维照写,没写就写 `自动`。分类规则、成员行上的 server 规则与文档底层会在运行时为这个对象作答,但那是解析:它们不是这个(对象, 地址)持有的字,既不上屏、不改值,也不压住控件,因此成员格上不会出现「控件的写权在别的层」这种问题,也不需要第二套控件。写入器另有一条判据:`internal/runtime-config.js` 把 `capabilityPolicyForConfig(...)` 无条件写进 resolved config,两份文档逐字节相同,所以 `capabilityPolicySaved` 记下这份文档是从记录的 `capabilityPolicy` 解析来的还是系统合成的——首次写入因此从记录自己的层起,合成出来的底层永远不进记录。
111
+
112
+ **8.2 撤销一条对象规则就是保存格写 `自动`。** 保存格陈述的是地址对该对象写下的值;把它选成 `自动` 就是把这一维从对象层删掉(记录为空时连条目一起消失),规则链随即由上一层重新作答——「非法状态不可表示」想要的结果,与「移除对象规则」这个动作是同一件事,不需要第二个入口。写下一个与规则链答案相同的值是另一回事:那一维确实写下了,保存格陈述写下的字而不是 `自动`,代价是记录里多出一条与推导结果同值的规则。
113
+
114
+ **8.3 服务行的披露格陈述「这个决定在哪」,不是披露取值。** 服务行陈述的是 `mcpServers.<server>` 这条规则,而这条规则**可以**自己写下一个披露字:继承规则窗口编辑它、`set session mcpServers.<server> disclosure <字>` 也接受它、导入的方案可能带着它。写下时它在运行时为**自己没写这一维**的成员作答(规则链的层序是类别 → 服务 → 成员,成员自己的字更高,见 §8.1b),但服务行的两个披露格仍写 `各成员自定`——披露的决定位置在成员那里,服务行不陈述一个「服务自己的披露」。回执不受影响:它陈述这份记录写下的每一个字,包括只有披露字、可用性没写的那种规则(那时回执写 `disclosure <字>`,不写 `未写下`)——否则回执会否认同一次读里已经带着的字。三个代价:成员自己都写了披露时,服务那一层的字没有成员行点名;搜索或筛选把成员行藏起来时,服务规则的字只留在会话入口的回执里(设置入口没有回执列,那一层在那边只在继承规则窗口里可读);服务行只在它自己写下那一维时才陈述它,没有写下就没有字可陈述。
115
+
116
+ **8.4 绑定行的两个保存格取自绑定文档,不是能力配置,且采纳记录的「未写下」按条算。** 绑定不是能力:它的保存地址是绑定文档(`enabled` 与 `modelContext.includeDeclaration`),本会话地址是采纳记录(`use` / `skip` / `damaged`)。采纳记录只承载取舍、不承载披露,所以绑定行的 `本会话·启用` 是两态按钮、`本会话·披露` 陈述 `继承`——这一行的两格形状由采纳记录决定,不是缺控件。映射进本页的词表时,`includeDeclaration` 为真读作 `人机·全文·首轮`,为假读作 `仅模型·目录·首轮`。绑定行只在会话入口出现:设置入口固定新会话默认,而绑定采纳没有保存地址。一条读得懂的采纳记录会为每个条目写下取舍:它点名的条目写 `不使用`,未点名的写 `使用`。回执栏的 `未写下` 按条算:记录点名了这条才写「绑定采纳记录 · <字>」,否则写 `未写下`。这处不对称是本契约保留的限制——记录决定了取舍,却没有为未点名的条目逐条留字;要让回执在整行都写记录,先得让采纳记录携带每一条的字。
117
+
118
+ **8.5 `回执` 列的点名粒度是记录加内容,不是文件路径。** 写入通道是一条命令(`/capabilities set …`),回执是它返回的那一句:哪张记录、哪个维度、什么值。本页不陈述日志文件名或字节偏移——那属于写通道,不属于页面。
119
+
120
+ **8.6 观察表仍借用本页的词。** 设置页的计划与预算观察表用同一份取值词表陈述冻结方案的选择。§6 要求词表唯一,所以它们必须用同一批词;§5 要求观察面不借用本页的**列、行与分区标题**(取值词表共用是它写明的唯一例外),这条仍然成立——两张要求并不冲突:词表共用,列、行、分区标题不共用。
121
+ **8.7 应用方案时不写入「由其余配置合成」的策略。** 方案是配置文档的一份拷贝,`capabilityProfileConfiguration` 会把它补成完整文档,所以一份从「未保存过策略」的记录保存出来的方案里同样带着当时合成的 `capabilityPolicy`。应用方案的那次写入按来源判据处理它:与「用这份配置的其余字段合成的策略」逐字相同的策略不属于任何记录,就不写回记录(§8.1c),并且把记录里原有的策略**移除**(设置服务的 `{op:'unset'}`)——所以应用一份这样的方案之后,保存列继续写 `自动`、管理开关也够不到这些格,无论记录此前有没有策略——除非方案还带着旧版 `capabilityOverrides`:那个字段是写下的记录,不是合成的策略,它随方案写回,保存列按 §8.1c 陈述它写下的字;与合成结果不同的策略是写下的记录,照写。仍未收窄的两处:旧版本保存的方案里那份策略若与今天的合成结果不同,应用它仍会被当成写下的记录;一次失败的激活回滚只对策略用 `unset`,与它同源的两个开关(`capabilityRecoveryEnabled`、`modelPreviewEnabled`)仍按提交值写回;记录确有策略时那条分支由「a rollback keeps a policy the committed record had saved」覆盖,仍未覆盖的是没有 `mutate` 的写入器上那两个开关的写回。
122
+ **8.8 三处主张只有部分证据。** 服务行的保存格(`mcpServers.<server>` 那条规则)在 jsdom 用例里只钉住「这一行唯一的保存控件是 `保存·启用` 那一格,它的披露格写 `各成员自定`,它没有勾选」;把选中的值写进同一份文档的 `mcpServers.<server>` 由 `changeCapabilityRule` 的用例覆盖(`test/capability-plan.test.js` 里写 `mcpServers.__proto__` 的那条),页面层没有端到端断言。以设置入口为主体那两个浏览器夹具的目录没有服务行,所以它们那边没有对应断言(别的夹具渲染同一份目录时带着服务行,但不写它的规则)。策略写者「从记录自己的层起笔」这条在逐行保存控件的两个分支(§8.1c)与 `set global <id> <维度> <值>` 那条命令上各有用例钉住,提示设置面板的基线分支没有回归敏感断言。设置入口那次未指名的目录读由后端用例钉住行集、两列 `inherit` 与「不列绑定行」,但页面层只用桩替换了这次读,没有端到端断言。§8.3 的两条写入路径各有用例:继承规则窗口写服务规则的披露字由客户端用例钉住,`set session mcpServers.<server> disclosure <字>` 由后端用例钉住。
123
+
124
+ **8.9 设置入口只陈述宿主在进程作用域的声明,不是新会话的完整声明面。** 未指名会话的那次读走 `hostSupply({})`,它看到的是宿主在进程作用域注册的对象。preset 在 agent 作用域注册的工具与该作用域解析出的 Skill 层只存在于会话作用域,因此它们不是设置入口的行:这个入口既不能为它们写下对象规则,也不能撤销一条——§8.2 说的「撤销不需要第二个入口」只覆盖这次读陈述得到的对象。保存策略在运行时仍按 id 管辖这些对象,所以这不是「它们没有被配置」,而是「这一页够不到它们的条目」。要让它们成行,得让这个入口读一份被点名会话的作用域(行集会变成那个会话的声明面,而写入的仍是新会话默认),或给规则地址第二处入口;两者都是产品形状的改动,不在本契约内。
125
+
126
+ **8.10 「不给」在三个模型可见面上同时成立,本页仍留着那一行。** §1 给「给不给」写的后果是「说明、发现、执行三面一致地不体现它」,代价在这里说清。三个面是 `tools:sdk` 声明块(说明)、程序的 `tools.*` 成员(执行)、`capabilities.*` 元数据(发现),它们读同一个判据:本会话记录写下的决定,加上这一步实际交付的定义集——宿主自己就是按每一步的准入渲染声明、并据此构造程序成员,所以「注册表里有、这一步没交付」的对象同样不在三个面上。记录一写下「关闭」,三个面就在同一次读里不再体现它,不等下一次组合:记录是这个会话的决定,组合只是记录的一次读法。属于某个能力的 `tool:<name>` 指引段按同一判据处置:它是对这个能力说的、模型可见的话,能力不在这一步的交付集里就没有成员可供给它指引,所以它随能力一起离开——组合是「一次读法」而不是准入,一份比这一步更宽的旧组合不能把它留下;下一步交付了同一个定义,这一节再出现。两个调用通道(`run_code`、`edit_run_code`)是程序被调用的方式而不是能力,不受这条约束。仍然点名它的东西都不是「模型能调用或发现」的主张:本页那一行(用户重新打开它的唯一入口,也是「关闭」这个决定仍然存在的地方)、会话日志里那条记录、已经投递的历史方案消息(它是历史陈述)。由此有三条限制:(a) 一次决定的变更会让声明文本在方案消息投递之前就改变,方案消息陈述的是它被投递时的那份组合,不追认后来的记录;(b) 页面在会话作用域陈述的是该作用域的声明面(§8.9),不是某一步的准入,所以这一步没交付的对象仍有行——否则用户就再也无法为它写规则。宿主不再持有该会话时没有作用域可读,那一页改陈述它日志里最后一版方案,也就是那一步实际交付的面;行集因此随组合收敛,而不是随注册表;(c) 开关关闭或暂停时这条判据不生效:暂停的能力上下文与关闭的管理开关都委托宿主能力与展示,组合与环境都不成立,记录仍是这个会话的选择但不被应用,重开后再生效(`test/capability-environment.test.js` 的「a switch that is off delegates the Host surface, so a recorded closure is retained but not applied」钉住它)。判据不分层:决定由哪一层写下(保存策略里的一条规则,还是策略世代之前冻结、至今未刷新的方案所带的旧版覆盖记录)不改变它意味着什么。关闭一个共享加载器(`tools.skill`)也会撤回那些把它写成唯一模型路径的发现行:还能由用户调用的 Skill 行留下并改说它仅剩的那条路(不再出现 `await tools.skill(`),既无模型路径也无用户路径的行不再是本会话的能力;资源 server 行同理,一次关闭之后 `capabilities.*` 里不再有任何一行叫模型去调用这个会话关掉的成员(`test/capability-environment.test.js` 的「a closure the legacy layer states withdraws the same Skill invocation path with user entry true」「…user entry false」与「a closure the legacy layer states withdraws the resource operation its contract names」钉住这三条)。这条陈述也不是组合的陈述:组合说的是它被组合时的那条路,而记录在这之后写下时就是会话最新的说法(`change` 只写记录,从不写方案),所以可探索的行说的是「组合交付的」与「决定留下的」的交集。Skill 行在那一步只会丢掉模型路径,不会拿到一份组合没说过的路径;资源 server 行的可用性就是「还剩一个操作可陈述」,它所属的 `mcp:<server>` 指引段与 `mcp-resource-servers` 目录条目跟着同一个答案走(`test/capability-environment.test.js` 的「a loader closed after the composition leaves the Skill row only the path it still has with user entry true」「…user entry false」与「an operation closed after the composition leaves the resource row only the calls it still has」钉住这三条)。
127
+
128
+ 派生的两行(`skills.*`、`mcp.*`)比 `tools.*` 多读一个输入,因为它们的契约本身就是一句「怎么调」的话。一条 `tools.*` 行在声明与执行面上的成员身份由三步决定:组合交付过、记录没关掉、这一步的准入交给了程序;派生行说的是同一个交集的第三条边——**这一步的程序真的拿到了那个共享操作**。组合只被组合一次并复用,一步交付得比组合少并不会让它重组(会话什么都没决定),所以一行可以一边属于仍然「被供给」的能力、一边叫模型去调这一步并不存在的成员:关闭窗口之外还有一个更窄的窗口,它的输入是准入而不是记录。读取方是 `capabilities.*` 的桥:它按程序的成员集请求 `metadata`,`tools.skill` 不在其中时 Skill 行只留用户入口或整行离开,三个资源操作只留这一步交付的那些、一个都没有时整行离开;没有观察过准入的调用方继续读组合,因为「没有观察」不是「观察到更少」。同一交集的第三条边也解释了为什么这一步不会「多出」路径:组合没冻结过的操作从来不是这次组合陈述过的,任何行都不会开始陈述它(`test/capability-environment.test.js` 的「a step that withholds the shared loader leaves the Skill row only the path it has with user entry true」「…user entry false」与「a step that withholds a shared resource operation leaves the resource row only the calls the program has」钉住这三条,`test/plugin-program-bindings.test.js` 的「the explorer states the shared operations the cell program has, not the ones the composition froze」钉住桥真的把这份成员集交给了它)。
129
+
130
+ **8.11 宿主那张 server 目录也是「这一步能调什么」的陈述。**`mcp-resource-servers` 是宿主唯一一段把能力名字当成参数列出来的文本:它列的名字只能作为 `server` 参数交给三个资源操作,而那三个操作是唯一收这个参数的能力,所以它列谁、列不列,说的都是这一步能调什么。装配侧因此按这一步仍然成行的资源 server 行重写它——三个操作一个都没交付时目录列不出任何 server,段落整段离开(宿主原文里那个 `["…"]` 也随之不再出现),`mcp:<server>` 段随它所属的行一起离开或留下:同一个 server 若还交付了 `mcp__<server>__*` 工具,那段 server 说明仍然成立,因为它描述的是那个 server,不是某一次调用的签名。没组成立方案(管理关闭)时没有行可以归属,目录按准入单独判定:三个操作都不在这一步的交付集里就撤回,有一个就保留原文字节。可及路径是宿主自己的逐步准入:`when` 每步重新求值,作用域限制(`agent.ctx.tools.restrict`)只影响那一个作用域的视图,两者都能让「注册表里有、这一步没交付」在这三个名字上成立(`test/context-host-contract.test.js` 的「the resource server directory states the operations the step delivers, not the composition」用 `when` 和真实装配钉住它,`test/capability-environment.test.js` 的「a step that delivers no resource operation leaves the server directory nothing to name」与「a directory this step cannot use leaves even when no composition states the environment」钉住判据本身)。仍然只跟记录走的是这一段之外的归属问题:`mcp:<server>` 说明在管理关闭的会话里没有行可以归属,行集为空时那句话仍可能是宿主对 server 说的话;收窄它要改的是宿主自己的段落归属,而不是这条判据。`supplied` 仍然只是「本会话还有没有」,准入只作用在投影上,所以统计与面板派生的行不受影响。
131
+
132
+ **8.12 一次 server 的关闭用的是同一个名字。** 记录为某个 MCP server 写下关闭时,它写的是 server 名(`mcpServers.<server>`),不是那个 server 的任何成员名;所以这条决定要沿同一个名字解析到它拥有的每一行与每一个成员:`mcp__<server>__*` 工具行、派生的 `mcp.<server>` 行、该行依赖的 `mcp:<server>` 说明,以及把这个 server 列成 `server` 参数候选的目录条目。四者读的是同一判据的两种写法——策略层的 `mcp:` 规则与记录层的 server 集合,`capabilityRule` 与 `recordCloses` 各自按成员所属的 server 解析,装配侧不需要为其中某个成员再写一条规则;退化路径(还没组成方案、注册表仍持有这些成员)由同一解析回答,所以一份比会话更宽的注册表视图不会把它们留在声明、成员或可探索行里。仍然点名这个 server 的东西都不是「模型能调用或发现」的主张:本页那一行(重新打开它的入口)、记录本身、关闭之前投递的历史消息,以及关闭之后的方案里那条 `selection: 'closed'` 的行——方案陈述的是这个决定,不是假装它从未存在(`test/capability-environment.test.js` 的「a record that closes a server withdraws its members and its resource directory before the composition catches up」钉住的正是组合还没追上的那个窗口,`test/context-host-contract.test.js` 的「a recorded server closure withdraws the rows, the guidance and the directory the server owns」用真实装配钉住这四者,并留两个非空洞对照:注册表视图在关闭后仍列出那个成员,方案在关闭前把那一行写成 `host`)。
133
+
package/docs/client-ui.md CHANGED
@@ -27,21 +27,23 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
27
27
  当前 Host half 的 `Config` 文档由 DSH 公共 `settings` 服务按 owning Loader entry 的 profile ID 寻址;更早 section installer 兼容支仍注册 `ptc-plus` 命名空间。失败补偿由 settings compatibility owner 绑定同一写入身份,不把固定 namespace 当作 profile entry ID。字段清单、默认值和校验来自 `internal/config-spec.js`,
28
28
  由 `index.js` 的 `Config` schema 与设置注册共用;client half 构建时把同一份字段清单打进 bundle,不在 UI 中复制默认值。`CONFIG_MODULES` 与 `CONFIG_GROUPS` 独立拥有功能模块和展示顺序:核心工作区(REPL 语法、状态与恢复)、扩展与容错(工具扩展、调用容错)、界面与资源(界面显示、资源限制)、实验性(能力与上下文)。配置页与弹窗将总开关与导航顶部的 PTC Plus 标题合成无描边的一行,整行标题可点击,开关状态代替重复的已启用标签;静态模块标题使用小字与分隔线,导航项使用图标、箭头和选中标记,正文不重复总开关;旧折叠卡片保留置顶的总开关。设置工作台在宽屏下使用左侧分区导航与右侧内容双列布局,小屏回退为横向导航与独立正文;官方插件配置页使用独立留白和以实际容器宽度决定的分栏,正文有界滚动,小容器导航变为横向列表;弹窗导航和正文分别滚动,正文滚轮与分区导航都不移动左侧导航或共享弹窗容器;桌面导航的高度受实际正文视口约束,短窗口中独立滚动以显示键盘焦点;窄且极短的弹窗将标题开关与横向导航合成一行,进一步压缩头部和标题留白,保留正文视口。键盘焦点只在自有横向导航列表内展开,分区定位按实际正文高度保留可用留白。分区导航只设置插件自有正文的滚动位置,不调用会连带移动外层页面的 `scrollIntoView()`;每个字段只展示一次,各组使用独立标题、留白与分隔线;能力与上下文内部的当前会话能力方案显示有效选择与待刷新状态。
29
29
 
30
- 能力列表通过能力 Remote 的只读 `catalog` 操作观察 code agent 的当前公共工具、Skill inventory 和已捕获的 MCP server 目录,与 `inspect` 返回的冻结方案分开。分组标题旁的总开关保存 `capabilityContextEnabled`,整体暂停而不改写子项;控制仍可编辑,配置库和冻结来源复制保留该维度。重新开启恢复保存组合,仍遵守新会话与明确刷新边界。`src/client-capabilities-view.js` 拥有能力配置、提示设置、使用统计和配置方案四个页签;页签支持方向键与 Home/End,字段仍由原配置 owner 保存。能力页首先显示搜索、类型按钮和能力清单;每行分别展示名称与精确 ID、类型、来源、保存规则的启停结果和上下文提供方式。名称下方不使用 provider 原始介绍。只有公共目录证明 MCP 来源时才标记 MCP,不从工具名称猜测服务器。Skill 来源使用公开 provider/source,冲突显示未确认。
30
+ 能力面通过能力 Remote 的只读 `session-catalog` 操作读取一份与会话相关的供给,两个入口读的是同一条读:调用方指名会话时,工作目录取自该会话的 header,供给来自该会话作用域自己的声明(或该会话记录的冻结面)+ 已保存配置 + 该会话自己的日志;未指名时只读 `hostSupply({})`,那是宿主在进程作用域的声明(不含 preset 在 agent 作用域注册的条目),不是任何会话的陈述,且这样一次读不列出绑定行——绑定采纳没有保存地址。指名会话的分支与 `inspect` 返回的冻结方案分开。分组标题旁的总开关保存 `capabilityContextEnabled`,整体暂停而不改写子项;页面的取值不随之改变,配置库和冻结来源复制保留该维度。`src/client-capabilities-view.js` 拥有能力配置、提示设置、使用统计、提示文本和配置方案五个页签;页签支持方向键与 Home/End,字段仍由原配置 owner 保存。能力页挂的是唯一能力面:搜索、类别与来源筛选在工具条上,表身按供给顺序列出对象、类型、来源与两个保存格(保存·启用/保存·披露),会话入口再列出两个本会话格(本会话·启用/本会话·披露)并加一列回执;设置入口固定新会话默认,那三列在它上面整列不存在,不是空着也不是禁用。保存格只陈述这份记录**为这个对象**写下的那一维:它能写下这一维就照写,没写下就写「自动」;分类规则、成员行上的 server 规则与文档底层会在运行时为它作答,但那是解析,不上屏、不改值,也不撤掉控件(见 [能力面:概念契约](capability-surface.md) §8.1c)。页面因此也没有「未设置」这种写法;本会话格陈述本会话的记录,没有记录时写「继承」。名称下方不使用 provider 原始介绍。只有公共目录证明 MCP 来源时才标记 MCP,不从工具名称猜测服务器。Skill 来源使用公开 provider/source,Skill 调用资格取该次供给的声明。这份清单是宿主对这个会话的声明,不需要本会话有可刷新的运行时:工具来自该会话作用域的工具注册表视图(含 preset 在 agent 作用域注册的工具),Skill 来自该作用域解析出的目录层,MCP 服务与资源服务来自该作用域贡献的 prompt sections;会话的 agent 已不在时,清单读会话自己记录的冻结方案,不拿宿主平面顶替;记录没有冻结过面时(没有方案、方案损坏、组合时没有要求库存)这次读失败并说明缺的是哪条记录,不画成一张空表。目录取自会话头,不取运行时的当前工作目录。某一来源读不出时整次读失败,不做部分成功的响应:页面在表格上方报告这次读取失败并给出原始错误与重试,上一次成功结果保留;不画错误块,也不把没读到的供给画成空表。清单没有任何条目时它说「宿主没有声明任何能力条目」,读成功而筛选无匹配时说「没有匹配的能力」,两者不互相顶替。默认、类别与 MCP 来源三层的持久规则在设置入口的「继承规则」窗口里编辑,与行上的决定分开;对象层规则的移除就是保存格选「自动」:这一维随记录撤销,记录为空时条目一起消失,不需要第二个入口(见 [能力面:概念契约](capability-surface.md) §8.2)。
31
31
 
32
- 行内启停只修改 availability;上下文入口打开独立小窗编辑。该小窗不使用折叠入口:可用性与说明两个下拉并排、常用基线为带说明的开关、能力说明与来源规则、所选会话方案全部平铺。保留 availability/disclosure 的独立继承、常用集、Skill 调用资格、完整目录描述及已证明来源规则。来源关闭优先于子项,但子项偏好仍保留。缺失、未知和能力配置未开启分别显示,保存规则不冒充会话实际状态。清单支持勾选多个条目(表头复选框选择当前筛选结果),批量设置使用独立的一次性小弹窗且只对所选条目生效;筛选可组合来源、已保存启停、已保存说明、常用项和库存状态,活跃条件显示摘要并可清除。类型切换清除不兼容来源,五列表头三态排序保留同值项的默认相对顺序,列表独立滚动。默认不打开单项或选取首个会话;详情中的冻结方案只供明确目标观察。目录失败保留最后观察内容并标为未确认,已保存的缺失项仍可编辑或移除。基础 REPL 公共能力不列为受管设置项。
32
+ 筛选不再另开小窗:搜索、能力类别与能力来源在同一条工具条上收窄同一张表,一个筛选的取值在另一个维度里不再匹配时被撤回,而不是把表清空;表身默认按供给顺序列出,每个能比较值的列表头都提供排序:点一次升序、再点降序、第三次回到供给顺序,比较的是这一列显示的词而不是它由哪个字段派生(`src/client-capability-sort.js` 拥有这三态,页面只交出显示值);回执列每行是一整句话,因此不参与排序。排序是显示决定:不写保存格、不写本会话记录,切换会话即回到供给顺序。清单逐行勾选多个条目,表头不提供全选;批量设置只对已勾选的能力行生效(服务行由它自己的保存格编辑那条规则,批量不写它),把每个目标的一个维度写成一条记录、一条回执,两维都选「不更改」时不写入而页脚仍给出这一句结果。来源关闭优先于子项,但子项偏好仍保留。绑定组只在会话入口出现,没有条目时也是一张零行空表。基础 REPL 公共能力不列为受管设置项。
33
33
 
34
34
  提示设置页使用固定功能导航与单项编辑的两栏结构,导航仅包含“初始提示”“提示恢复”“输出节选”,没有编号或新增条目动作。名称旁与摘要复用同一保存状态判定:已选用、未选用、已暂停、沿用 DSH 或未确认。初始提示随能力配置应用,提示恢复与输出节选各有独立开关;总开关关闭时保留选择并显示暂停;状态与导航选中高亮分开,不断言现有会话已同步。短名称作为可访问名,状态作为可访问描述;窄容器使用三条全宽紧凑功能行,名称在左、状态在右。能力说明设置默认提供方式,常用集、使用统计与预算各自选用,分配依据、额度与只读分配预览直接展示。分配只影响 adaptive,显式完整说明不会被预算降级。提示恢复和输出节选分别有独立开关,关闭不清除额度,不依赖能力管理。统计页先选择观察会话作为观察锚点,统计表与预算预览都按它的能力清单展示,统计范围切换该会话的当前工作区或全部工作区;已有记录但家族尚未结算显示“已有记录待结算”,尚无记录显示“暂无样本”,两者显示破折号而不是零;只有可计量的窗口才显示数字(真实的 0/N 与 0% 保持数字),窗口证据不完整或容量超限同样显示破折号和状态。采集开关独立于统计消费,窗口、最低样本数和百分比阈值放在“统计设置”中;保存前校验正整数窗口、最低样本不超过窗口与 0–100% 阈值,无效数字草稿不阻止关闭采集。
35
35
 
36
36
  配置页采用左配置库、右详情;唯一“保存当前设置”与导入、配置库更多操作位于列表下方。命名保存、重命名与会话复制仅在对应动作后展开;列表可在只读状态浏览,写入遵循公共 settings 资格。详情显示可复用设置摘要与应用按钮,配置库更多导出全部、详情更多导出所选,导入仅加入库。应用用一次原子 mutation 更新保存设置,读回冲突不能显示成功;从会话复制只读取已证明的 frozen.configuration,不复制统计、变量或执行状态。已有会话观察和明确刷新位于独立折叠入口。异步导入遇到只读、关闭插件或卸载永久失效,即使资格恢复也不提交迟到内容。详见 [ADR 0040](adr/0040-separate-capability-configurations-from-session-observations.md)。
37
37
 
38
- 页内保存状态来自真实 pending/status 和 settings 资格,说明保存设置供新会话采用;已有会话保留冻结环境,需要明确刷新。任一能力与上下文功能选用时可观察冻结来源,全部关闭时取消方案读取;目录观察与手动配置独立。插件关闭、设置关闭与 transport 释放取消请求,迟到响应不能恢复旧状态。所有开关使用 DSH 尺寸与主题 token,按钮文字居中,边框轻量;六列清单在窄容器中分行,配置页堆叠。
38
+ 页内保存状态来自真实 pending/status 和 settings 资格,说明保存设置供新会话采用;已有会话保留冻结环境,需要明确刷新。任一能力与上下文功能选用时可观察冻结来源,全部关闭时取消方案读取;目录观察与手动配置独立。插件关闭、设置关闭与 transport 释放取消请求,迟到响应不能恢复旧状态。所有开关使用 DSH 尺寸与主题 token,按钮文字居中,边框轻量;会话能力面板的八格清单(对象、类型、来源、两个保存格、两个本会话格与回执)在窄容器中分行,配置页堆叠。
39
39
 
40
40
  能力与上下文提供独立的“刷新会话能力”操作,必须明确选择活跃 PTC 会话;“重新读取目录/方案”只观察状态。星光菜单的同名操作与“编写新绑定”“修改绑定”共用输入框保护,只将 `/capabilities refresh` 填入空输入框并关闭菜单,由用户发送;已有草稿保留。设置按钮通过宿主 `commands.execute` 提交命令,不发起模型任务。关闭能力管理后仍可主动同步关闭配置,此时回执报出能力关闭并说明会话沿用宿主能力,不声称会话能力已更新;回执区分“能力与上下文”总开关与能力管理开关两种关闭原因。冻结方案观察跟随各独立功能的选用状态。关闭 Global User Bindings 只隐藏绑定操作,保留星光设置与刷新。未确认目标、命令不可用、只读设置或插件关闭时不能刷新;取消、断线、preset 改变、切换会话或卸载使迟到回执失效。Host 回执区分已接受、通知待首次接受、能力关闭与失败,取消只停止等待,需重读状态确认实际效果。
41
41
 
42
- 会话能力工作台使用一份待应用更改,不先切换生效范围。底部提供“放弃更改”“应用到会话”和“应用到全局”:分别清空草稿、写入会话临时选择、保存全局默认并更新当前会话;页脚以“应用到会话”为主操作,“应用到全局”作为显式保存全局默认的次要操作,不存在默认发生的全局修改;“批量设置”入口位于同一页脚操作组的右端并显示已选数量,未选择条目时禁用。维度选择按结果命名:“不改动(当前:值)”不产生本会话临时修改,已有临时修改时同一位置显示“撤销本会话修改(恢复为:值)”,该撤销只允许“应用到会话”,不能把 `inherit` 写入全局设置;“由上一级规则决定”只在会话来源对该维度确有显式规则或该值已是当前选择时提供;可用性与说明方式的值选项直接写作“启用”“关闭”等动作。每个维度选择下方用“本会话生效:值 · 来源”预览当前草稿的结果,暂存后标注“待应用”。勾选多个条目后“批量设置”在一次性小窗中为所选条目暂存同一维度选择,或清除其本会话修改;暂存不发送命令,仍由底部按钮决定应用到会话或全局,“放弃更改”清空。已确认的批量提交拥有独立生命周期:逐条命令进行期间关闭按钮禁用且关闭路径拒绝执行,可用性或设置的瞬时重算不会取消在途命令;成功、失败或中止后都在同一收尾路径清理“正在应用”状态并核对已确认草稿。全局提交只有重新读取到对应保存选择且该项临时覆盖已清除才从草稿移除;部分失败和无法确认的更改仍可重试。行内“是否启用”和“上下文”单元格显示实际生效值;该维度的生效值来自会话临时选择时附加“(临时)”,与冻结继承的相同取值区分。设置中的“能力与上下文”总开关或能力管理开关关闭时,即使会话仍冻结着已启用方案,工作台也整体只读,并以警示横幅显示对应关闭原因与恢复路径,重新开启并刷新后才能修改会话选择;冻结事实仍可查看。详情区使用独立的 13px/20px 正文与紧凑的状态信息,来源、全局设置、冻结继承、临时覆盖和实际生效分别显示;冻结来源未知时不从全局值猜测。整行都可选中:任意单元格(含空白处)与名称按钮一样打开该条目详情,可用性与上下文单元格保留各自的维度焦点;行首复选框只切换批量目标,不打开详情。共享 Select 使用居中的 SVG 箭头,Radix 继续拥有键盘、焦点与独立 Portal。
42
+ 会话能力面板直接写,不暂存:能力行的本会话·启用格与本会话·披露格各是一个下拉(值列写这一格自己的记录;由 server 层记录作答的那一维写 `继承`,回执列点名那一层,见 [§4](capability-surface.md#4-页面形状与入口)),一格一个决定,点选一个与当前记录**写下的字**不同的值即向本会话日志追加一条 `/capabilities set session <id> <dimension> <choice>` 记录(同一个字不写;记录写 `automatic` 时值列也写 `automatic`,改回别的字就是要写),写不进去时命令通道的拒绝原文成为底栏回执(`src/client-capabilities-view.js` 的 `record`;[§5 写通道](panel-concept.md#5-写通道))。行不可展开,七列分别陈述两个地址的四个维度,外加一列回执;保存两格在会话入口是只读文本,不提供控件。本会话这一列先由样式陈述状态、再由词陈述:行左缘的色条、启用格里的圆点标记与控件自身的填充和边框,共同给出 `enabled`(成功色实心点,下拉控件的填充与边框取成功色)、`closed`(错误色斜线点,该行的名称与来源同时降级显示)、`automatic`(业务色实心点,同取业务色)、`inherit`(中性空心点、次要文字色,控件不带状态填充)四种读法;词保持标签文字色且不加粗,状态色只落在控件外观上,所以状态不靠给文字染色;绑定行同一格按 `use`/`skip`/`damaged` 使用同一套标记,`use` 的开关取成功色填充与边框。披露格只用主/次文字色区分「这一格自己记录了决定」与「继承自上层」,服务行的「各成员自定」保持次要色。行、格与标记携带同一个状态值(`data-session-state`、`data-state`),状态因此既是读得出的画面,也是可断言的 DOM 事实(`src/client-capabilities-view.js` 的 `sessionStateOf` 与 `sessionAvailabilityCell`;`src/client-styles.js` 的本会话状态规则)。保存·启用格也陈述它自己那一个字并带同一个状态值:会话入口这一格只有这个词,渲染成与状态同色调的胶囊标签;设置入口这一格是下拉控件,填充与边框取成功/错误/业务色而文字保持标签色,于是没有本会话列的设置入口同样看得出这份记录把哪些对象写成关闭,而「保存·关闭+本会话·继承」这一行因此读得出「关」。保存·披露格陈述五种披露字之一,不带状态值:没有一个选择器按它上色,加一个没人观察的状态值不陈述任何东西。保存列的色调只让保存列自己的词更快被读出,不表示这一行在本会话里得到什么:保存条目、类别规则与 `mcpServers.<server>` 规则在运行时谁压住谁属于解析(capability-surface §8.1b、§8.1c),既不上屏也不上色。工具栏放搜索、类型筛选、来源筛选与“批量设置”入口:入口显示已选数量,未选择条目时它仍可点,弹窗按 0 个目标打开,确认写入 0 条并由底栏给出这次批量的回执。底栏只放最近一次写入的回执。绑定行提交时那一行标 `aria-busy`;能力行的本会话·启用与本会话·披露各是一个下拉、各占一格,服务行只有本会话·启用一个下拉,披露格写「各成员自定」,提交不改动其他控件,每次写入各自持有取消信号;会话切换使在途写入与迟到回执失效。面板没有整块只读区、不禁用控件、不画警示横幅:能力与上下文暂停或能力管理未启用时行与控件不变,命令通道的拒绝原因成为回执。绑定行不属于这套能力选择:全局绑定开关只决定供给里有没有绑定条目,绑定组本身恒在;控件没有可写性分支,`/binding` 未在本会话列出时行仍照常可点,命令通道的拒绝原因成为回执。共享 Select 使用居中的 SVG 箭头,Radix 继续拥有键盘、焦点与独立 Portal。
43
43
 
44
- `/capabilities refresh` 与结构化状态回执使用独立的 13px/20px 单行提示,只显示当前界面的结果文案,不显示命令标题、重复状态或原始结果入口。运行、待生效、能力关闭和失败保留各自的真实文案,长错误可以换行;历史刷新回执的已记录通知文本同样转换为简短提示。能力查询保留命令卡片。`ptc-capability-catalog/v1` 结果默认显示条目数,展开后以有高度上限的可滚动表格显示列表;其他 JSON 显示详情入口,不直接铺在正文里。查询的原始结果单独折叠,在展开时显示完整原文,既不改写历史结果也不把成功回执当作完整值或模型投递的新证明。
44
+ 工作台的绑定组列出全局目录供给的绑定条目和本会话对每条的取用状态,每行一个控件,只有三种读法:“使用”“不使用”“记录损坏”,三种都可点击;某一行提交中时只有那一行标 `aria-busy`,其余行照常可点,每次写入各自持有取消信号,互不打断已经提交的命令(`src/client-capabilities-view.js` 的 `record`、`sessionAvailabilityCell` 与 `sessionDisclosureCell`;`test/client-runtime.spec.js` 的「binding rows record their adoption through the `/binding` command, including a damaged record」与「a session capability write in flight leaves every other control usable」)。控件不另开写通道:点击提交的就是人类输入的同一条 `/binding use|skip <id>` 命令,之后按同一份会话能力目录回读。绑定组恒在:行可以为零,零行就是空表,不配一句解释(`src/client-capabilities-view.js` 的绑定组 section;`test/client-runtime.spec.js` 的「the binding group is always rendered, with the same columns and possibly no rows」)。`/binding` 未在本会话的命令目录列出时,行仍照常列出,控件照样可点:命令通道自己报出的拒绝原因成为底栏回执(`src/client-transport.js` 的 `createCommandAccess` 在命令不可用时抛出 `/${name} is unavailable in this session`,`src/client-capabilities-view.js` 的 `record` 把它渲染成 `capabilities.quick.writeError`),面板不预先禁用任何控件——控件没有失败分支,见 [§5 写通道](panel-concept.md#5-写通道)。提交后 `/binding` 命令返回的回执原文渲染在面板底栏(`src/client-capabilities-view.js` 的 `.ptcPlusSessionCapabilityFooter`,经 `capabilityCommandText` 保持原文),其中 `Whether the worker installed the entries this session still uses is reported with the next accepted cell, not by this receipt.` 照原文显示,不被丢弃(该回执是 `/binding` 返回的英文原文,面板不翻译)。
45
+
46
+ `/capabilities refresh` 与不带写入记录的状态回执使用独立的 13px/20px 单行提示,只显示当前界面的结果文案,不显示命令标题、重复状态或原始结果入口。运行、待生效、能力关闭和失败保留各自的真实文案,长错误可以换行;历史刷新回执的已记录通知文本同样转换为简短提示。带写入记录的回执(`/capabilities set …`)不是一条单行提示,而是一张卡片(`.ptcPlusCapabilityCommandNotice[data-kind=writes]`):抬头按这次运行的条数陈述(`capabilities.card.writes`),下面逐行列出每条记录;同一窗口内相邻的写入只在最后一条上画这一张卡,中间隔着别的消息就各自成卡,找不到邻居的那一条仍画自己那一行。写入回执不受「首条人类消息之前隐藏」约束,刷新与发表类回执仍受它约束,空会话两类都不显示。能力查询保留命令卡片。`ptc-capability-catalog/v1` 结果默认显示条目数,展开后以有高度上限的可滚动表格显示列表;两列逐行重述面板的保存列与本会话的启用、披露两列(能力行两维、服务行只有启用;记录没写下的维度,保存列写 `automatic`、本会话列写 `inherit`),0.5.4 及更早的单选择词与独立规则形态仍按原样可读,词表外的形态不渲染表格;其他 JSON 显示详情入口,不直接铺在正文里。查询的原始结果单独折叠,在展开时显示完整原文,既不改写历史结果也不把成功回执当作完整值或模型投递的新证明。
45
47
 
46
48
  ## 可用设置
47
49
 
@@ -66,7 +68,7 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
66
68
  | 界面与资源 | 资源限制 | `startupProbeMs` / `executionSeamTimeoutMs` | worker 启动探针上限;等待宿主执行入口的上限(只在插件激活或重载时读取)。 |
67
69
  | 界面与资源 | 资源限制 | `maxValueNodes` / `maxValueEdges` / `maxValueArrayLength` / `maxValueBigIntDigits` | Value Graph 与大数组、BigInt 的返回上限;数组长度限制同时约束单数组和一份 graph 的累计槽位。 |
68
70
  | 实验性 | 能力与上下文 | `capabilityManagementEnabled` | 默认关闭;开启实验性能力管理,冻结新会话的能力方案。 |
69
- | 实验性 | 能力与上下文 | `capabilityBaseline` / `capabilityPolicy` | 可搜索的能力列表、常用勾选、独立可用性与说明规则;默认/类别/来源/单项覆盖,分配依据及预算分别选择。 |
71
+ | 实验性 | 能力与上下文 | `capabilityBaseline` / `capabilityPolicy` | 可搜索的能力列表与独立可用性/说明规则;常用集 `capabilityBaseline` 在页面上没有编辑器,只在配置摘要里只读陈述,随配置文档变化;默认/类别/来源/单项覆盖,分配依据及预算分别选择。 |
70
72
  | 实验性 | 能力与上下文 | `capabilityStatistics` | 实际使用统计与采集开关及样本窗口、最低样本数、完整披露百分比输入;无效输入不提交,关闭或无可用样本时保留手动基线。 |
71
73
  | 实验性 | 能力与上下文 | `capabilityProfiles` | 最多 100 份命名能力配置;保存、重命名、删除、文件导入导出、原子切换与读取会话源设置。 |
72
74
  | 实验性 | 能力与上下文 | `capabilityBudgetBytes` / `capabilityDirectoryBytes` / `capabilityRecoveryEnabled` / `capabilityRecoveryBytes` | 完整契约、导航及压缩后说明恢复的 UTF-8 字节预算;显式完整契约不截断。 |
@@ -74,7 +76,7 @@ Client 按数据、传输、注册与视图分文件,沿用既有 `createX(Rea
74
76
 
75
77
  旧配置的五个开关(`looseTopLevelRedeclarations`、`looseTopLevelFunctionClassRedeclarations`、`autoRewriteImports`、`autoStripExports`、`autoSplitRedeclarations`)先由共享 resolver 迁移。完整策略映射到 `stateful` 或 `protected`;混合选择保留显式兼容态,只有该状态才显示旧控件。兼容态的统一策略控件显示“沿用旧版设置(尚未迁移)”,可直接选择“允许重声明和覆盖”或“启用名称保护”;选择后一次写入同时保存 `bindingUpdates` 并清除兼容标记,随后执行和模型指引采用相同的新语言策略,设置页恢复统一开关。仅查看设置不触发写入。
76
78
 
77
- 能力配置通过可搜索列表、常用勾选与独立可用性/说明方式选择编辑;默认、类别、MCP 来源、单项分别按维度覆盖。“不单独设置”撤销当前维度的显式选择,“按依据分配”独立选用常用集、统计和预算。使用统计、提示恢复与输出节选分别设置,Client 负责序列化。统计数字输入保留未完成或无效草稿,失焦时仅保存有效组合;无效草稿显示错误,统计开关仍可独立保存并恢复最近有效的数字组合。方案展示通过公共能力 RPC 读取当前会话的选择原因、覆盖率、预算超额和待刷新状态,保存配置本身不等于旧会话已更新。
79
+ 能力配置通过可搜索列表与独立可用性/说明方式选择编辑;默认、类别、MCP 来源、单项分别按维度覆盖。“由上一层”撤销当前维度的显式选择,“按依据分配”独立选用常用集、统计和预算。使用统计、提示恢复与输出节选分别设置,Client 负责序列化。统计数字输入保留未完成或无效草稿,失焦时仅保存有效组合;无效草稿显示错误,统计开关仍可独立保存并恢复最近有效的数字组合。方案展示通过公共能力 RPC 读取当前会话的选择原因、覆盖率、预算超额和待刷新状态,保存配置本身不等于旧会话已更新。
78
80
 
79
81
  ## enabled 开关与正文功能标记
80
82
 
@@ -143,7 +145,7 @@ PTC session 的头部弹窗在功能启用时增加 Session 与 Global 页签。
143
145
 
144
146
  ## REPL 顶级页签
145
147
 
146
- Client 通过公开 `conversation.view` 注册 `ptc-plus-repl`(标签 `REPL`,order 20),与对话、轨迹同级。注册作用域订阅 `sessions.list` 的当前会话及其 `agentPreset` projection face:插件与 `replViewEnabled` 开启且当前 preset 为 `ptc` 或 `code` 时注册,其余情况注销。会话切换、preset 改变、设置关闭和 provider/plugin 释放都会清理对应订阅与注册。DSH 拥有页签选择与注销后的回退;列表属于当前 browser Client,插件不创建多会话导航器。空会话的页签可见性仍由宿主 shell 决定。
148
+ Client 通过公开 `conversation.view` 注册 `ptc-plus-repl`(标签 `REPL`,order 50,排在宿主自己的页签之后:宿主对话为 0、实验性统计为 40,插件页签因此落在它们之后,不再插在原生页签之间)。注册作用域订阅 `sessions.list` 的当前会话及其 `agentPreset` projection face:插件与 `replViewEnabled` 开启且当前 preset 为 `ptc` 或 `code` 时注册,其余情况注销。会话切换、preset 改变、设置关闭和 provider/plugin 释放都会清理对应订阅与注册。DSH 拥有页签选择与注销后的回退;列表属于当前 browser Client,插件不创建多会话导航器。空会话的页签可见性仍由宿主 shell 决定。
147
149
 
148
150
  REPL 根元素使用官方轨迹页同样的 `data-conversation-composer-overlay` 布局标记,由宿主提供满高视口并禁用对话宽度拖拽条;工作区内部滚动。仅在该页挂载期间,通过公开 `conversation.composer` chain 注册当前 session 专属的空替代项,隐藏普通消息输入框。宿主 overlay 保留原输入框与草稿,离开 REPL、关闭插件或释放 provider 时恢复。存在 `pendingInteraction` 时替代项不参与选择,审批、提问等宿主交互保持优先。插件不查询或改写宿主 DOM,不覆盖宿主 CSS。
149
151
 
@@ -165,25 +167,25 @@ REPL 是单页工作区,上方为“会话绑定”,下方直接展示完整
165
167
 
166
168
  live 配置若因宿主能力缺失或 runtime 安装/重配置失败,会先回滚所有已创建或更新的 owner,再把持久设置回写为上一次已应用值;回滚写入失败时 Host 记录 activation diagnostic,避免静默把配置显示成不存在的 runtime。
167
169
 
168
- ## 能力列表与批量操作
170
+ ## 能力面与批量操作
169
171
 
170
- 设置与会话能力工作台均提供能力、类型、来源、是否启用、上下文五列。点击表头依次切换升序、降序和默认顺序;切换到另一列从升序开始,同值项保留默认相对顺序。排序只作用于展示,不保存规则或改变当前选中项。窄屏仍保留可操作表头,来源和精确 ID 保持可读。两处清单的整行都可选中:点击任意单元格(含空白处)与点击名称或铅笔等同选择该项;设置清单的可用性开关及其状态标签保持自身启停语义,不触发整行选中,该单元格其余空白同样选择整行。会话工作台以当前生效事实展示这些列,待应用的修改单独显示,不能把草稿当作已生效。
172
+ 能力面只有一个渲染器([`src/client-capabilities-view.js`](../src/client-capabilities-view.js) 的 `createCapabilitySurfaceView`),两个入口都挂它:会话入口固定本会话记录,设置入口固定新会话默认。列、词、控件与回执由该页声明,入口只决定写权、「本会话」两列与回执列是否存在——设置入口上这三列整列不存在。完整形状见 [能力面:概念契约](capability-surface.md)。
171
173
 
172
- 会话的能力与上下文暂停或能力管理未启用时,工作台明确标注该状态并关闭暂存与提交;清单每行显示沿用宿主的事实,不再显示无法收敛的待生效。只有已启用管理、但尚未刷新折入方案的宿主动态成员才显示待生效。
174
+ 会话入口陈述七列(对象、类型、来源、保存·启用、保存·披露、本会话·启用、本会话·披露)并加一列回执;设置入口只有前五列。保存两格在会话入口是陈述、在设置入口是控件(服务行的保存·披露格例外:它陈述 `各成员自定`,没有控件,§8.1a);本会话两格只在会话入口出现,是控件。设置不可用或插件总开关关闭时,设置入口的控件禁用而格子仍在;会话入口不这样:行与控件不随开关变化,写不进去由命令通道的回执说明。
173
175
 
174
- “批量设置”只对清单中已勾选的行生效,未选择任何行时按钮不可用;表头复选框把当前筛选结果加入选择,选择不随筛选或排序变化而丢失。弹窗对所选真实可用目标执行一次单项变更,选中但当前不可用的目标单独计数并排除。可用性和说明方式独立选择,初始均为不更改;确认前只保留临时草稿,取消不写入。确认使用最新配置,仅改目标单项的所选维度,保留非目标项、其他维度及继承规则;目标失效或保存失败时显示错误,不能显示成功。默认、类别和 MCP 来源的持久继承规则通过“继承规则”入口编辑,与批量操作分开。保存选择仍只在新会话或明确刷新后生效。
176
+ “批量设置”是同一页的同一批决定:它把所选行各自被改的维度逐个写成记录——一行一个维度一条写入、一条回执——两维都选“不更改”时不写入,页脚仍给出这一句结果。默认与类别两层的持久规则不在行上,由设置入口的“继承规则”入口编辑;MCP 来源那一层由服务行自己的保存格写(它编辑同一份文档里的 `mcpServers.<server>`),继承规则窗口对已经存在的来源条目做同样的编辑。行的决定与这三层分开,保存选择只在新会话或明确刷新后生效。
175
177
 
176
178
  提示设置的三个侧栏项在选用状态旁显示具体配置摘要,分别来自默认说明方式及其分配依据、恢复额度和输出额度;总开关暂停和未知配置保持明确标识。分配依据、额度与当前能力分配直接展示,统计设置同样直接展示。观察会话旁以灰色说明其只读统计与预算预览用途,窄屏可自然换行。
177
179
 
178
180
  ## 能力组合摘要与会话对照
179
181
 
180
- “新会话设置”在四个页签上方持续显示,按能力配置、初始提示、提示恢复、输出节选、使用统计排列。五个四字名称与编辑入口相同,按能力、提示、统计三个职责分组,宽屏为1:3:1,窄屏按组纵排。初始提示对应现有首轮能力说明、常用集与预算,不编辑完整宿主 system prompt;其应用依赖能力配置,不新增独立开关。五个状态按钮只导航到已有编辑区,不增加互斥模式或保存来源。提示固定栏目选择由同一 Workbench 拥有,摘要的 aria-controls 直接关联具体编辑 pane。保存反馈由 settings owner 发布,读取不到配置时不把默认值标成已保存选择。总开关只暂停有效输入,摘要沿 `effectiveCapabilitySettings` 显示保留选择与暂停的区别。
182
+ “新会话设置”在五个页签上方持续显示,按能力配置、初始提示、提示恢复、输出节选、使用统计、提示文本六项排列。六个四字名称与编辑入口相同,同在一个容器里等宽排列:宽屏按 `repeat(auto-fit,minmax(150px,1fr))` 均分,720px 及以下单列(`src/client-styles.js` 的 `.ptcPlusCombinationChoices`)。初始提示对应现有首轮能力说明、常用集与预算,不编辑完整宿主 system prompt;其应用依赖能力配置,不新增独立开关。六个状态按钮只导航到已有编辑区,不增加互斥模式或保存来源。提示固定栏目选择由同一 Workbench 拥有,摘要的 aria-controls 直接关联具体编辑 pane。保存反馈由 settings owner 发布,读取不到配置时不把默认值标成已保存选择。总开关只暂停有效输入,摘要沿 `effectiveCapabilitySettings` 显示保留选择与暂停的区别。
181
183
 
182
184
  “对照已有会话”复用唯一目标与正式刷新入口,不默认选中首个会话。计划观察不依赖子功能开启,只读设置也允许选择目标和重新读取。`describeSessions()` 用持有的实际 Session 沿 `planCommitted` 返回 `publication`;已记录仅证明方案消息已进入记录,不能证明模型已消费通知。界面分别显示冻结来源、临时覆盖、待接受通知与保存差异。历史方案缺少总选择时保持缺失并沿原代际解释恢复/预览,不以当前默认补齐。没有方案或读不到事实不计为零。
183
185
 
184
186
  读取生命周期记录 pending、error 和对应保存配置身份。保存配置变化、刷新开始或读取失败使上次观察不能证明当前一致;旧观察可保留,但明确标为上次读取。取消与失败后可重新读取,迟到响应不能恢复已中止的读取;目标切换仅消费同一身份的方案。刷新仍通过 DSH 正式命令执行,重新读取不启动任务、执行计算或自动刷新。逐项方案仅显示明确目标。
185
187
 
186
- 选择旁的条件说明区分能力可用性与说明方式、采集与历史统计消费,以及保存偏好与实际参与分配。按需仍可发现和使用,分配只作用于最终 adaptive 且当前可用的能力,不关闭能力、不降级显式完整契约。来源关闭压过子项开启但保留偏好;管理关闭时显示未应用并允许编辑偏好。恢复与预览独立,分别保留近期有效已展开 API/无 Skill 正文及完整 canonical 值/执行结果的边界;详细条件按需展开。
188
+ 选择旁的条件说明区分能力可用性与说明方式、采集与历史统计消费,以及保存偏好与实际参与分配。按需仍可发现和使用,分配只作用于最终 adaptive 且当前可用的能力,不关闭能力、不降级显式完整契约。来源关闭压过子项开启但保留偏好;管理关闭时页面照常陈述两列,偏好仍可编辑,只是新的决定要到下一次启用后才改变运行结果。恢复与预览独立,分别保留近期有效已展开 API/无 Skill 正文及完整 canonical 值/执行结果的边界;详细条件按需展开。
187
189
 
188
190
  ## Client bundle
189
191
 
@@ -204,4 +206,4 @@ npm run build
204
206
  如果 DSH settings service 不可用,Host half 不会因缺少设置服务而加载失败:设置卡片不可用时直接回退为 composition `config`,
205
207
  `enabled` 默认开启,运行时按 composition config 工作。
206
208
 
207
- MCP 列表按 server 分组,来源可用性与说明方式使用和单项一致的独立选择器,均可撤销为不单独设置。来源显式关闭是外层移除,优先于子项启用;默认关闭仍可由子项启用覆盖,二者不混同。会话详情显示保存选择、临时规则、冻结来源结果及生效的维度来源,空规则显示不单独设置或无覆盖。目录分别保留当前保存设置与冻结会话各自代际的事实;新保存规则不能把历史 scalar 来源改写成空结构规则。已证明的冻结 `managementEnabled` 决定是否预测来源关闭;管理未选用时保留关闭偏好、显示实际 Host 可用,不报待关闭。待应用的来源关闭会在子项详情预告;正式提交和重新读取确认之后才改变生效状态。
209
+ 回退载体渲染同一个能力面:没有第二份清单、没有按 server 分组的列表、没有来源或策略选择器、没有单项详情。来源显式关闭是外层移除,优先于子项启用;默认关闭仍可由子项启用覆盖,二者不混同。回退载体挂的是设置入口,所以每一行只陈述它固定的那一个地址(没有本会话两列,也没有回执列);默认、类别与来源三层的规则由「继承规则」窗口编辑。目录分别保留当前保存设置与冻结会话各自代际的事实;新保存规则不能把历史 scalar 来源改写成空结构规则。已证明的冻结 `managementEnabled` 决定是否预测来源关闭;管理未选用时保留关闭偏好、显示实际 Host 可用,不报待关闭。待应用的来源关闭由继承规则窗口陈述(页面没有子项详情);正式提交和重新读取确认之后才改变生效状态。