dsh-ptc-plus 0.5.2 → 0.5.4

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 (72) hide show
  1. package/README.en.md +4 -2
  2. package/README.md +4 -2
  3. package/client.cjs +3392 -2811
  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/0017-track-the-latest-dsh-public-surface.md +4 -2
  8. package/docs/adr/0019-plugin-settings-and-kill-switch.md +2 -2
  9. package/docs/adr/0023-global-user-bindings.md +12 -0
  10. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +1 -1
  11. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +2 -2
  12. package/docs/adr/0044-coexist-with-the-official-persistent-repl.md +4 -4
  13. package/docs/adr/0046-gate-the-commit-with-the-semantic-evidence-tier.md +1 -1
  14. package/docs/adr/0048-supersede-a-rewritten-cell.md +48 -0
  15. package/docs/adr/0049-prove-a-settlement-against-its-published-record.md +53 -0
  16. package/docs/adr/0050-read-host-surfaces-through-their-published-contract.md +48 -0
  17. package/docs/adr/README.md +7 -1
  18. package/docs/architecture.md +1 -1
  19. package/docs/capability-planning-components.md +6 -6
  20. package/docs/capability-projection.md +1 -1
  21. package/docs/capability-surface.md +133 -0
  22. package/docs/client-ui.md +17 -15
  23. package/docs/client-visual-contract.md +7 -7
  24. package/docs/durability-design.md +9 -2
  25. package/docs/installation.md +17 -10
  26. package/docs/panel-concept.md +171 -0
  27. package/docs/releases/v0.5.2.md +26 -14
  28. package/docs/releases/v0.5.3.md +77 -0
  29. package/docs/releases/v0.5.4.md +75 -0
  30. package/docs/runtime-reference.md +21 -1
  31. package/docs/user-bindings.en.md +15 -0
  32. package/docs/user-bindings.md +15 -0
  33. package/docs/v0.5.3-goals.md +117 -0
  34. package/docs/verification.md +4 -4
  35. package/index.js +176 -41
  36. package/internal/binding-adoption.js +228 -0
  37. package/internal/capability-command-receipt.js +106 -8
  38. package/internal/capability-environment.js +1109 -312
  39. package/internal/capability-plan.js +18 -2
  40. package/internal/capability-policy.js +13 -0
  41. package/internal/capability-selection.js +330 -0
  42. package/internal/config-spec.js +14 -5
  43. package/internal/cordis-tools-owner.js +2 -1
  44. package/internal/direct-surface-owner.js +44 -17
  45. package/internal/edit-transport-owner.js +6 -5
  46. package/internal/execution-provider-owner.js +6 -0
  47. package/internal/execution-seam-compat.js +25 -0
  48. package/internal/host-tool-sdk.js +308 -0
  49. package/internal/message-sources.js +21 -0
  50. package/internal/official-repl-priority.js +31 -10
  51. package/internal/program-bindings.js +25 -5
  52. package/internal/repl-memory-projection.js +21 -2
  53. package/internal/runtime-bridge-owner.js +118 -9
  54. package/internal/runtime-config.js +10 -0
  55. package/internal/runtime-messages.js +5 -0
  56. package/internal/session-journal-recovery.js +210 -32
  57. package/internal/session-journal-schema.js +3 -0
  58. package/internal/session-journal.js +46 -9
  59. package/internal/session-log-view.js +69 -7
  60. package/internal/session-runtime.js +106 -39
  61. package/internal/settings-compat.js +6 -0
  62. package/internal/user-bindings-owner.js +126 -6
  63. package/package.json +59 -37
  64. package/src/client-authoring-view.js +7 -8
  65. package/src/client-capabilities-view.js +874 -909
  66. package/src/client-capability-sort.js +22 -9
  67. package/src/client-copy.js +118 -272
  68. package/src/client-indicator-view.js +2 -1
  69. package/src/client-repl-view.js +35 -16
  70. package/src/client-settings-view.js +90 -33
  71. package/src/client-styles.js +67 -19
  72. package/src/client.js +49 -22
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.
@@ -10,9 +10,11 @@ PTC Plus must remain independently installable on unmodified official DSH distri
10
10
 
11
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.
12
12
 
13
- Release discovery is separated from candidate verification. The root manifest declares the official `next` channel for the DSH packages used by development and freezes the resolved cohort in the root lockfile. `compat/latest` declares only the official DSH meta-package on `latest` and freezes that complete graph in its own lockfile. Resolved versions in these generated lock snapshots are reproducibility evidence selected by the channel declarations; they are not compatibility allowlists or runtime branches. `compat/current` separately freezes the cohort of the newest published official GitHub release, including prereleases. Its generated manifest selects the matching official npm channel, and `release.json` records the discovery provenance. This published-release identity, rather than a fixed list of channel names, owns the current target. Ordinary `verify` and the full branch of `check` make no registry request and fail quickly when the installed root graph differs from the root lock; they also validate the published cohort against its frozen provenance.
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.
14
14
 
15
- The scheduled baseline refresh queries the official registry. It also queries official GitHub releases and matches the newest non-draft DSH release to the official meta-package dist-tags. A missing distribution fails discovery instead of silently using an older Host. When either channel or the published-release cohort moves, it updates the affected lock snapshots on an automation-owned branch, opens or updates one pull request, and dispatches the normal CI workflow once for that frozen 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 neither tag nor the published-release cohort moved, it does not resolve or install the dependency graph. The Host contract suite tests the packed plugin against the root `next` graph and creates a repository-external consumer from the tracked `latest` lock. That consumer exposes the public packages from the selected Host graph to the plugin and runs the execution-seam, RPC-codec, and compressed Session persistence contracts. The suite also creates a repository-external consumer from `compat/current` and tests the packed plugin on that unmodified published graph. `npm run test:host-contract -- current` selects this object alone. No compatibility run independently selects tags for DSH service packages, because their dist-tags need not move as one cohort.
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
+
17
+ The development-lock move is a mechanical convenience with one known limit. `host:channels:graph` re-pins the DSH declarations in `package.json` and then asks npm to resolve the graph, which works when the cohort already moved together in the lock. A development graph that still carries a large previous-release cohort (the lock holds far more `@deepseek-ai/dsh-*` packages than the manifest declares) makes npm reject the half-moved peer graph with `ERESOLVE`; the command then throws, and both `package.json` and `package-lock.json` are restored to the bytes the command found, so no partly moved graph is left behind. Because that command runs before the refresh workflow commits, a channel move waits for a maintainer to install the whole cohort and re-run the check, and `host:channels:verify` keeps reporting the drift until then. This limit touches release tooling only: the plugin's behaviour, its install proof and the compatibility claim a consumer reads are unaffected, and every gate that ships the package reads the tracked manifest rather than the development lock.
16
18
 
17
19
  Preceding public contracts remain supported where capability detection is
18
20
  unambiguous. Tools presentation is selected by the installed public schema;
@@ -18,7 +18,7 @@ The settings card belongs to plugin configuration. Current DSH renders a bundle'
18
18
 
19
19
  The settings form groups controls into core workspace (REPL syntax, state and recovery), extensions and tolerance (tool extensions, tool call tolerance), interface and resources (interface display, resource limits), and experimental (capabilities and context). Page and dialog navigation integrate the single main switch into a borderless PTC Plus title row without a duplicate enabled badge; static module captions differ from section links with icons, arrows and selected markers. The legacy disclosure card retains its first switch section. Experimental controls remain last and carry an explicit marker. The wide settings dialog presents the groups as a two-column workbench with independently scrolling navigation and content; settings wheel scrolling and section selection leave the rail and shared modal frame in place. Narrow viewports use horizontal navigation above independently scrolling content. Recovery tips and their thresholds stay together, and global binding management appears directly below its enable switch. `CONFIG_MODULES` and `CONFIG_GROUPS` own this presentation grouping and order independently of Host schema field order and defaults. The session capability-plan section inside capabilities and context shows effective selections and pending configuration changes only while capability management is enabled; disabling it cancels plan inspection and discards stale replies while manual configuration and catalog reads remain available. Capabilities and context uses four tabs for manual preferences, statistics, budgets and session plans. MCP lists group tools/resources under a server master switch; closing the server preserves child strategies and takes precedence when the frozen plan is derived. Typed catalog rows keep common preferences, manual strategies and selected frozen-session results separate, with source/strategy/common/availability filters and stable within-group sorting. Display names and source metadata belong only to the catalog RPC view: Skill provider/source and public MCP server directory and captured MCP owner sections supply evidence, while ordinary tools are attributed to the Host registry without guessing their package origin. Catalog errors preserve last-observed entries as unconfirmed, and unavailable saved preferences remain editable/removable. The core execution surface is read-only. Capability controls serialize structured selections and retain invalid numeric drafts without committing them; saving capability settings affects new sessions, while existing sessions retain their frozen plan until `/capabilities refresh` as defined by [ADR 0038](0038-freeze-session-capability-plans.md). The sparkle menu refreshes its current session through the authenticated Host command; settings require an explicit target from a read-only active-PTC identity view. This identity view does not prepare or inspect plans and remains available with capability management off so users can synchronize the disabled configuration. Reloading catalog/plans is read-only. Global binding disablement hides binding actions while settings and capability refresh remain accessible; the plugin switch and configured sparkle visibility still gate the menu. Refresh receipts preserve Host outcomes, and cancellation stops waiting without claiming rollback. `autoDescribeRunCode` defaults to true and controls only a request-bound local execution policy. When enabled, a call that omits the outer `description` uses derived arguments for local DSH validation, and the fallback summary enters presentation metadata only; when disabled, DSH validates the original arguments. Both states produce byte-stable model-visible tool schemas, order, and system sections with the required `description` declaration. Original call arguments, explicit summaries, cell source, and nested native-tool arguments remain unchanged.
20
20
 
21
- The configurable set is the Host runtime configuration plus `enabled: boolean` (default true). `enabled` is the kill switch: when false the Host keeps the settings namespace, client card, and passive message cleanup defined in [ADR 0010](0010-session-log-derived-recovery-tips.md). The next permitted accepted step may clear earlier PTC declarations. It does not install the runtime bridge, edit transport, direct-surface owner, system prompt section, tool registrations, or execution hooks, and does not read binding storage. When true the same runtime as pre-settings PTC Plus is installed. On the generations that expose a section installer, every field is live when its owner can reconcile it: the Host observes the settings scope and installs, uninstalls, or reconfigures owners without replacing existing session-bound bindings. The volatile-only settings shape exposed by both frozen Host graphs has no section installer and serves only fields marked volatile in the plugin's exported `Config`; the Host provides the form and commits volatile-only changes into the live references, notifying the owning fiber through the public `loader/volatile-update` event. The plugin subscribes and reconciles through its existing update path instead of running a per-field settings watch. Node fixes a worker's V8 `maxOldGenerationSizeMb` limit at construction, so changing that field while a session worker is active or a submitted cell is preparing to execute is rejected and the settings provider is restored to the previous value; other reconfiguration failures use the same compensation path. The TypeScript language check occurs at activation, allowing disabled settings to load on a host using another code runtime while rejecting and rolling back an enable attempt. If the settings service is absent, the Host falls back to composition config and enables the runtime.
21
+ The configurable set is the Host runtime configuration plus `enabled: boolean` (default true). `enabled` is the kill switch: when false the Host keeps the settings namespace, client card, and passive message cleanup defined in [ADR 0010](0010-session-log-derived-recovery-tips.md). The next permitted accepted step may clear earlier PTC declarations. It does not install the runtime bridge, edit transport, direct-surface owner, system prompt section, tool registrations, or execution hooks, and does not read binding storage. When true the same runtime as pre-settings PTC Plus is installed. On the generations that expose a section installer, every field is live when its owner can reconcile it: the Host observes the settings scope and installs, uninstalls, or reconfigures owners without replacing existing session-bound bindings. The volatile-only settings shape exposed by both installed channel graphs has no section installer and serves only fields marked volatile in the plugin's exported `Config`; the Host provides the form and commits volatile-only changes into the live references, notifying the owning fiber through the public `loader/volatile-update` event. The plugin subscribes and reconciles through its existing update path instead of running a per-field settings watch. Node fixes a worker's V8 `maxOldGenerationSizeMb` limit at construction, so changing that field while a session worker is active or a submitted cell is preparing to execute is rejected and the settings provider is restored to the previous value; other reconfiguration failures use the same compensation path. The TypeScript language check occurs at activation, allowing disabled settings to load on a host using another code runtime while rejecting and rolling back an enable attempt. If the settings service is absent, the Host falls back to composition config and enables the runtime.
22
22
 
23
23
  The host-only log-fact projection remains owned by the plugin/controller lifecycle when the runtime is disabled, as specified in [ADR 0032](0032-own-session-log-facts-in-a-host-only-projection.md). It supports passive message cleanup without retaining a worker, tool or default model-visible state projection.
24
24
 
@@ -43,7 +43,7 @@ namespace. Enable-failure and live-reconfiguration compensation use that same
43
43
  bound writer, not a fixed namespace substituted for the owning entry. The
44
44
  writer and page policy are released with the settings provider.
45
45
 
46
- Compatibility evidence and the consequences of removing historical branches are bounded by [Installation: Compatibility Evidence](../installation.md#compatibility-evidence). The two frozen graphs do not establish full Host coverage of the section-installer or settingsScope shapes.
46
+ Compatibility evidence and the consequences of removing historical branches are bounded by [Installation: Compatibility Evidence](../installation.md#compatibility-evidence). The two installed channel graphs do not establish full Host coverage of the section-installer or settingsScope shapes.
47
47
 
48
48
  ## Alternatives Considered
49
49
 
@@ -22,6 +22,18 @@ Journal version 6 introduced the required `userBindingsReusePolicy`: new cells w
22
22
 
23
23
  Namespace call names and selected export names must parse as exactly one Identifier whose AST name equals the complete supplied string. Whitespace, comments, binding patterns, extra declarations and escaped spellings cannot change identifier identity between validation, declarations, conflict checks, activation and recovery. Supported Unicode identifiers keep their exact spelling. Top-level entry display names remain separate from callable export names.
24
24
 
25
+ ## Supply, Adoption, Materialization and Proof
26
+
27
+ Global bindings answer four different questions, and each layer may report only its own answer. **Supply** is which entries the global configuration offers; `bindings.json` and each entry's `enabled` switch own it, and an entry disabled there is simply absent from the catalog. **Adoption** is which of those entries one session uses; the session owns it. **Materialization** is which adopted entries the worker actually installed; the activated set and its per-entry failures own it. **Proof** is what the model can check; the tool result, its journal and the diagnostics it names own that.
28
+
29
+ Adoption is a two-state decision per entry plus a default: a session uses an entry unless it declined it. "Adopted explicitly" and "never mentioned" therefore produce the same environment, so they are one state rather than two, and no sentinel value is needed. The capability pane's `automatic` is not borrowed here: that word means "the host derives this value", while a binding has no host-derived value to defer to.
30
+
31
+ Adoption can only withdraw a supplied entry. It cannot add, enable or revive one, because an entry the global configuration disabled does not exist in the catalog for a session to name; `/binding skip <id>` rejects an entry the catalog does not supply instead of recording a decision that would claim authority over supply. No rule forbids "an override revives a deleted entry", because the record has no encoding that could express it.
32
+
33
+ `/binding status|skip <id>|use <id>|reset` states the decision as one `plugin:ptc-plus` `binding-adoption` message, and the session-log projection reads the newest record back. A restart therefore reconstructs the same environment from the log; no second store or process-local map exists to migrate. A session that never states a decision receives exactly the supplied catalog, so the previous release's environment is unchanged.
34
+
35
+ Materialization remains a separate report. A declined entry is never offered to the worker, while an entry the worker could not install is named by its execution diagnostic (`PTC-R002`, and `PTC-R006` for a name that was live and then disappeared). An adoption receipt claims neither delivery nor initialization.
36
+
25
37
  ## Storage and Source Ownership
26
38
 
27
39
  The Host owns one document at `$DSH_HOME/ptc-plus/bindings.json`. The store serializes mutations, holds a file lock, compares the last-read disk bytes, requires an expected revision, and atomically replaces the file with owner-only permissions. The complete enabled declaration budget is validated before replacement; an externally written document that exceeds the same budget is treated as damaged storage. A malformed document remains an explicit error, and stale or external changes require reload instead of blind overwrite. A new Agent draft uses create-only persistence so a concurrent entry with the same ID cannot be replaced.
@@ -163,7 +163,7 @@ escalation it thinks it is offering.
163
163
  ## Consequences
164
164
 
165
165
  The default bundle and current official base profile use the `ptcRuntime`
166
- resolve/run shape, also exercised by the frozen Host graphs. Explicit
166
+ resolve/run shape, also exercised by the installed channel graphs. Explicit
167
167
  `codeRuntime` request-only compositions retain public Loader fixture coverage
168
168
  for request identity, replacement and bundle removal. The evidence boundary is
169
169
  recorded in [Installation](../installation.md#compatibility-evidence).
@@ -12,7 +12,7 @@ PTC Plus publishes its Remote services through DSH's TYPERT registry, and that r
12
12
 
13
13
  Each generation validates only the member it owns and ignores the other, so one published contract serves whichever shape the installed host implements. Compatibility follows the live acceptance behavior of the registry rather than a release version, and the decoder is published once, so a host that reads both members cannot obtain two different decoders for one wire member.
14
14
 
15
- CI registers the packed contract with the installed host's own registry from the frozen official `latest` and `next` graphs (`scripts/dsh-rpc-contract-smoke.mjs`). Both frozen graphs read `create()`; they do not exercise a schema-only Host. Unit fixtures cover `schema.parse`, not a complete historical Host installation. The evidence boundary is [Installation: Compatibility Evidence](../installation.md#compatibility-evidence); passing two graphs must not be reported as packaging verification of both codec shapes.
15
+ CI registers the packed contract with the installed host's own registry from the blocking host channels it resolves on demand from `compat/channels.json` (`scripts/dsh-rpc-contract-smoke.mjs`). Both installed channels read `create()`; they do not exercise a schema-only Host. Unit fixtures cover `schema.parse`, not a complete historical Host installation. The evidence boundary is [Installation: Compatibility Evidence](../installation.md#compatibility-evidence); passing two graphs must not be reported as packaging verification of both codec shapes.
16
16
 
17
17
  ## Alternatives Considered
18
18
 
@@ -24,4 +24,4 @@ CI registers the packed contract with the installed host's own registry from the
24
24
 
25
25
  ## Consequences
26
26
 
27
- One plugin build carries both the historical schema-based and factory-based codec shapes, and the compatibility rule lives in a single module with the decoder published once. A future generation that requires another member, or that rejects a codec carrying a member it does not know, needs this owner updated; the regression test is CI's registration against the installed registry, which fails on the frozen Host graph that changed instead of on the user's machine. The decoder keeps the project's maintained schema runtime, so a host that validates payloads itself still evaluates the same semantics the plugin's own tests exercise through both members.
27
+ One plugin build carries both the historical schema-based and factory-based codec shapes, and the compatibility rule lives in a single module with the decoder published once. A future generation that requires another member, or that rejects a codec carrying a member it does not know, needs this owner updated; the regression test is CI's registration against the installed registry, which fails on the installed channel host graph that changed instead of on the user's machine. The decoder keeps the project's maintained schema runtime, so a host that validates payloads itself still evaluates the same semantics the plugin's own tests exercise through both members.
@@ -6,15 +6,15 @@ DSH added an opt-in official Node execution mode (`executionMode: persistent-in-
6
6
 
7
7
  ## Decision
8
8
 
9
- `internal/execution-seam-compat.js` and `internal/execution-provider-owner.js` forward `programFormat` to the live original generation and `release(owner)` to the originals that served that owner. These describe the provider that actually performs an execution: owner-keyed retained environments and the executed source format belong to the original, which still serves non-session consumers while the plugin owns session cells, and a bounded generation that lacks the members falls back to `'function-body'` and a resolved no-op. Execution retirement does not retire cleanup: the composition retains weak owner-to-original provenance for dispatched `stateOwner` programs, so Agent cleanup through a captured adapter still reaches a surviving original after bundle removal or source replacement. Successful cleanup removes that original from the owner's pending set; failed cleanup remains available for explicit retry, with synchronous and asynchronous failures observable. An owner without recorded dispatch delegates to the live original, or receives a resolved no-op if execution is unavailable. `executionInstructions`, `sandboxMode` and `timeout` keep their existing withholding policy while PTC Plus owns session execution, because those describe the session kernel ([ADR 0028](0028-attach-to-the-host-ptc-execution-seam.md)).
9
+ `internal/execution-seam-compat.js` and `internal/execution-provider-owner.js` forward `programFormat` and the `retainsState` declaration to the live original generation and `release(owner)` to the originals that served that owner. The composed provider answers `retainsState` as the fact about itself: while an installed adapter runs the program it retains a per-session environment, so it reports `true` whatever the original would do; `seam.originalRetainsState` carries the original declaration for the ownership decision. These describe the provider that actually performs an execution: owner-keyed retained environments and the executed source format belong to the original, which still serves non-session consumers while the plugin owns session cells, and a bounded generation that lacks the members falls back to `'function-body'` and a resolved no-op. Execution retirement does not retire cleanup: the composition retains weak owner-to-original provenance for dispatched `stateOwner` programs, so Agent cleanup through a captured adapter still reaches a surviving original after bundle removal or source replacement. Successful cleanup removes that original from the owner's pending set; failed cleanup remains available for explicit retry, with synchronous and asynchronous failures observable. An owner without recorded dispatch delegates to the live original, or receives a resolved no-op if execution is unavailable. `executionInstructions`, `sandboxMode` and `timeout` keep their existing withholding policy while PTC Plus owns session execution, because those describe the session kernel ([ADR 0028](0028-attach-to-the-host-ptc-execution-seam.md)).
10
10
 
11
- `officialReplPriority` (default `false`, State and recovery) selects who owns PTC session execution when the official persistent REPL is live. The decision reads the live capability — `provider.programFormat === 'repl'` — rather than a release number, and is re-evaluated on every configuration and host source change. Execution ownership is an attachment shape: `owned` installs the session runtime, `deferred` installs `internal/official-repl-priority.js`'s runtime record, which owns no execution resources and answers the attachment contract with empty contexts. Changing the shape retires the current attachment, disposing its live kernels, and installs the other shape before later cells; no committed cell mixes the two contracts. While deferred, `run_code` and its descriptors stay with the official provider and the plugin's REPL guidance, session-state semantics, recovery, editor tool, capability SDK, REPL observation and binding workbench are suspended with the attachment, while the settings card, enablement and stored global bindings stay available so the switch can be reversed.
11
+ `officialReplPriority` (default `false`, State and recovery) selects who owns PTC session execution when the official provider retains a program environment per state owner. The decision reads the live capability — the provider's `retainsState` declaration, or the retained source form (`programFormat === 'repl'`) on a generation that predates that declaration — rather than a release number, and is re-evaluated on every configuration and host source change. Retention, not the source form, answers the question: one host line retains state for `script` programs and another runs the same form in a fresh process. Execution ownership is an attachment shape: `owned` installs the session runtime, `deferred` installs `internal/official-repl-priority.js`'s runtime record, which owns no execution resources and answers the attachment contract with empty contexts. Changing the shape retires the current attachment, disposing its live kernels, and installs the other shape before later cells; no committed cell mixes the two contracts. While deferred, `run_code` and its descriptors stay with the official provider and the plugin's REPL guidance, session-state semantics, recovery, editor tool, capability SDK, REPL observation and binding workbench are suspended with the attachment, while the settings card, enablement and stored global bindings stay available so the switch can be reversed.
12
12
 
13
13
  Cells executed under the official mode produce no plugin journal records. They are an unrecorded execution interval: recovery never replays them, and they do not extend plugin state as recovery evidence.
14
14
 
15
15
  ## Alternatives considered
16
16
 
17
- **Gate on the DSH release or on reading the original row's `executionMode` configuration.** The mode is a live runtime capability and a configuration fact outside the plugin's public contract; `programFormat` is the provider-owned proof that a REPL actually retains state, and it degrades safely on older generations that lack it.
17
+ **Gate on the DSH release or on reading the original row's `executionMode` configuration.** The mode is a live runtime capability and a configuration fact outside the plugin's public contract; the provider's own retention declaration is proof that its environment survives between runs, and on older generations that lack the declaration the retained source form is the only evidence they publish.
18
18
 
19
19
  **Keep owning execution unconditionally and only add the missing seam members.** That repairs disposal, but it silently ignores an explicit official mode, cannot honor a user's choice to run the official semantics, and keeps two competing REPL contracts alive for the same session surface.
20
20
 
@@ -26,7 +26,7 @@ Cells executed under the official mode produce no plugin journal records. They a
26
26
 
27
27
  ## Consequences
28
28
 
29
- Agent disposal on the current official host releases cleanly, and both the format and the owner release reach the generation that owns the environment.
29
+ Agent disposal on the current official host releases cleanly, and the source form, the retention declaration and the owner release reach the generation that owns the environment.
30
30
 
31
31
  Leaving plugin ownership disposes its live kernels, and plugin-mode state contraction follows the existing disposal rules. Official in-memory state belongs to DSH's Agent/provider lifecycle and may remain available when priority is switched back to the official provider; the deferred attachment does not clear it. State built during an official interlude is never replayed or claimed by the plugin. After returning to plugin ownership, the session continues from plugin-verifiable evidence only.
32
32
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  The commit gate runs the static prerequisites plus the **semantic-evidence backend tier**; the complete behavioral inventories stay behind `npm run verify`.
10
10
 
11
- - `npm run check` records its proof from `npm run verify:check`: `review:validate`, `host:baseline:verify`, `semantic:check`, `build:check`, the syntax checks and `deterministic-test-groups.mjs --check`.
11
+ - `npm run check` records its proof from `npm run verify:check`: `review:validate`, `host:channels:verify`, `host:shape-check`, `semantic:check`, `build:check`, the syntax checks and `deterministic-test-groups.mjs --check`.
12
12
  - `--check` selects `test:client` plus `test:backend:fast`. The Client units stay in the gate because a change can be covered only by them; leaving them out let a red Client suite pass, which is how the copy-key and layout regressions were first caught. The backend tier is the test files that `semantic-obligations.json` names as evidence for at least one obligation, minus coverage-only paths and the verification-tooling probes that fail by construction outside their own harness. Each obligation keeps at least one executable owner, and the fast tier is derived from the ownership graph rather than a hand-maintained list.
13
13
  - `npm run verify` keeps the complete gate: `test:client:visual` plus the whole ordinary backend inventory. CI runs `verify:ci`, release preparation runs `verify` (and coverage), and any change that touches a semantic owner missing from the graph must extend the graph — which extends the fast tier at the same time.
14
14
  - Browser suites are no longer part of the commit gate. They remain the complete visual contract and run in `verify`, in CI, and on demand.
@@ -0,0 +1,48 @@
1
+ # Supersede a rewritten cell
2
+
3
+ ## Status
4
+
5
+ Accepted (0.5.3).
6
+
7
+ ## Problem
8
+
9
+ An accepted `edit_run_code` receipt schedules a derived execution: after the outer cell settles, the whole target source runs again in its revised form and is recorded as one more cell. The 0.5.2 fold treated both records as environment members, so "append" became the meaning: the edited cell kept building the environment and the revision stacked on top of it.
10
+
11
+ Appending is invisible in the common case, because the revision declares the same names and overwrites the old values. It leaves one state the plugin cannot state: a name the target declared and the revision no longer declares still exists in the environment, while no cell in the log declares it any more. The plugin then has no producible evidence for a name it reports to the model: the source no longer contains that declaration, and a restart removes it by a different rule.
12
+
13
+ ## Decision
14
+
15
+ The edited cell and its revision are related by **supersession**, not by deletion.
16
+
17
+ - The log does not change: the edited cell and the revision both stay recorded, each with its own journal and source.
18
+ - The fold decides the environment: with `editRewritesHistory` on, the revision folds as an ordinary recorded cell and **takes the edited cell's place** — it continues from that cell's parent, and the cells recorded after the edited cell continue from the revision. The superseded cell keeps its node but leaves the head's parent path; the head stays the latest recorded cell.
19
+ - The relation does not depend on how the revision itself settled: a revision that settled volatile is installed from its recorded values and still replaces its target; a revision the fold contracts (its recorded values cannot be installed) is absent from the environment, and the relation the record states still holds, so the target's provable names are still reported as superseded. A contracted revision has no node to continue from, so its successors continue from the superseded cell's parent. A `discarded` settlement is no evidence that the revision ran, so it states no relation and keeps append semantics; a `noop` derived settlement never becomes a record and states none either.
20
+ - The relation is reconstructable from the log: the fold reports `supersessions` (`supersededCallSeq` / `supersedingCallSeq`) and `supersededBindings`, attached to the recovery result like `deletedBindings` and without changing the enumerable shape of §history.
21
+ - Reporting: one relation states `PTC-R007` once per runtime, naming which cell replaced which, together with the names the log can prove and the revision no longer supplies.
22
+ - Off by default. When it is off, the fold keeps 0.5.2's append semantics exactly, so neither existing cases nor the reading of earlier session logs changes.
23
+
24
+ ## What it claims and what it refuses to claim
25
+
26
+ `supersededBindings` contains only names the log can prove: the `values` a volatile settlement recorded, `unrecordedBindings`, and `binding` save operations. A durable cell's declared names are not in its journal — replay produces them by executing the source — so the fold never guesses a name for the model, and `PTC-R007` states only the relation when there is no name to report.
27
+
28
+ The live worker and the durable fold keep their existing division of labour: the environment recovery replays is the environment the supersession applies to, while the live cache keeps the values it executed. This matches how `PTC-R005` (a recorded rewind ended these bindings) is handled: the record states the ending, the notice names it, and the live cache is not described as already emptied.
29
+
30
+ ## Alternatives considered
31
+
32
+ - **Keep append semantics and report the leftover names as lost.** Rejected: the log does contain a cell that declared them, so "lost" would be false, and the model would be told to redeclare a name whose replacement it never saw.
33
+ - **Delete the superseded cell from the log.** Rejected: the session log is append-only evidence, and history replacement belongs to DSH. Supersession is a fold-time relation, and the record has to keep proving what happened.
34
+ - **Refuse the edit unless the revision redeclares every name the target declared.** Rejected: an accepted edit is the user's decision about the cell's source, and a revision that intentionally drops a name is legal JavaScript. Refusing it would make the transport decide the source.
35
+ - **Report the relation on every later fold instead of once per runtime.** Rejected: the relation is a durable fact of the log, not a per-cell event; repeating it on every recovery is noise the model cannot act on twice, and the names it withdraws are reported by their own diagnostics.
36
+ - **Adopt the relation for a `discarded` settlement too.** Rejected: a discarded settlement is not evidence that the revision ran, so claiming it replaced the target would state an execution the log denies.
37
+
38
+ ## Consequences
39
+
40
+ - With the switch on, the set of cells in the environment no longer equals the set of cells in the log; the difference is the supersession relation, not a loss.
41
+ - Later cells read the revised value, and so do they after recovery.
42
+ - A session log written while the switch was off folds under the same relation once it is on, because the relation lives in the log rather than in the configuration.
43
+ - A runtime that supersedes a cell reports `PTC-R007` beside any restore notice the same recovery produces, and each consecutive recovery states the facts it replayed.
44
+
45
+ ## Related
46
+
47
+ - ADR 0025 owns logical binding identity and language generations.
48
+ - [durability-design.md](../durability-design.md) §「日志折叠」 and §「恢复通知」 describe the fold order and the diagnostics.
@@ -0,0 +1,53 @@
1
+ # Prove a settlement against the record it published
2
+
3
+ ## Status
4
+
5
+ Accepted (0.5.3).
6
+
7
+ ## Problem
8
+
9
+ Recovery reads a journal record as evidence for the bindings its cell declared, and the record is the only account of its own cell. Nothing inside it distinguishes "this is what happened" from "this is what someone wrote afterwards".
10
+
11
+ 0.5.2 already checks two things against each other: `completion.error.message` is rendered from the first diagnostic, so a completion that no longer renders from its diagnostic is refused, and `dshPtcPlusDiagnosticWording.digest` covers the facts those diagnostics state. Together they show why internal consistency is not enough. Edit a diagnostic and re-render the completion and the record is consistent again; and the completion's kind and value, and the cell's status, have no second statement anywhere in the record.
12
+
13
+ ## Decision
14
+
15
+ A settlement leaves a digest of its own statement at publication, and the fold recomputes it before treating the record as evidence:
16
+
17
+ - `dshPtcPlusSettlementProof = { version, recordedMessage }`, where `recordedMessage` covers the status, the completion (kind, `hasValue`, the value digest, the error kind and message) and the facts each diagnostic states.
18
+ - `help` and `source` stay out of it because they are presentation: a historical record may be read through an older generation's help wording, and a caret position is re-derived when the diagnostic is rendered.
19
+ - A mismatch means the cell cannot prove its bindings. It establishes a contraction point (`PTC-R002`) beside every other damaged-metadata case. It is not a throw and not a retry: the refusal is the fold's terminal state.
20
+ - A record without the field predates this proof and keeps the 0.5.2 evidence rules. Migration is by absence, and the journal schema version does not change, because the proof is a sibling key rather than a journal field.
21
+
22
+ Alongside it, the Host's `isError` on the same `tool/result` event is a copy this plugin cannot recompute: it comes from what the tool returned, not from the journal. When it is present, the fold requires
23
+
24
+ ```text
25
+ isError === (status === "discarded" || completion.kind === "throw")
26
+ ```
27
+
28
+ which is the relation a nested edit already proves before it publishes a derived settlement. An editor who repairs the proof from their own edited journal therefore still has to agree with the Host's copy of the outcome.
29
+
30
+ ## What the proof does not claim
31
+
32
+ - It is not an unforgeable boundary. Someone who rewrites both the facts and the proof is equivalent to a re-publication; what the proof establishes is that the record was not partially rewritten.
33
+ - The plugin does not own the Host's model-visible text, so it does not compare against it. That text is a projection this plugin cannot reproduce, and treating it as evidence would call a presentation difference tampering, a far more common event than the damage the proof guards against.
34
+ - `dshPtcPlusDiagnosticWording` remains the reading path for records that carry it; a new publication writes one proof rather than two names for one relation.
35
+
36
+ ## Alternatives considered
37
+
38
+ - **Compare against the retained model-visible message text.** Rejected: the plugin cannot recompute the Host's projection, so a renderer or locale change would read as tampering, and every failing cell in a host that projects differently would lose its bindings.
39
+ - **Bump the journal schema version and migrate old records.** Rejected: absence already carries the same information without rewriting historical metadata, and a version bump would make every pre-0.5.3 record unreadable to a generation that has no better evidence to offer.
40
+ - **Keep only the diagnostic wording digest and add a separate completion digest.** Rejected: two digests over one settlement state the same relation twice, and the fold would have to decide which of them wins when they disagree.
41
+ - **Reject a mismatched record by throwing from the fold.** Rejected: a throw turns every retry into the same throw, which is the loop that hung an earlier attempt. The fold registers an unavailable result instead.
42
+
43
+ ## Consequences
44
+
45
+ - An edited record no longer proves its cell's bindings. The fold contracts at that cell, the model reads `PTC-R002` naming the skipped cell, and the source stays in the session log.
46
+ - Both publication paths write the proof: `withJournal` for a `run_code` settlement and the derived edit settlement's metadata.
47
+ - Session logs need no migration: old records lack the field, new records carry it, and the reader branches on its presence.
48
+ - The `isError` agreement only applies where the Host records it. A log without that copy keeps the weaker evidence rather than inventing a claim.
49
+
50
+ ## Related
51
+
52
+ - ADR 0025 owns logical binding identity and language generations.
53
+ - [durability-design.md](../durability-design.md) §「Completion 校验」 describes how the fold uses the proof.
@@ -0,0 +1,48 @@
1
+ # Read and write the host's surface only through the contract it publishes
2
+
3
+ ## Status
4
+
5
+ Accepted (0.5.3).
6
+
7
+ ## Problem
8
+
9
+ Three of this plugin's host interactions cross a boundary the plugin does not own, and each had settled on a proof that is really an assumption about one host implementation:
10
+
11
+ 1. A transport-owning executor keeps the reserved `run_code` definition inside itself. Reading it by probing every zero-argument member identifies the surface by shape, but it *invokes* host code: an executor with `cancel()` and `flush()` had both called during prompt assembly, and an executor that publishes the definition through a reader taking an argument was judged "no executor" with no diagnostic, which silently removed every feature that needs execution.
12
+ 2. A derived edit dispatched as one model batch is handed to a host that assigns the execution identity itself. The relation was proved by comparing the parent token the plugin holds with the token on the execution the host runs — a token the host mints for itself and the batch contract never carries, so the accepted edit was admitted as its own root, the nested result arrived without an execution journal, and the model read "failed after acceptance" while the revision never applied.
13
+ 3. The user's editable `run_code` description and parameter texts were written onto the host's live definition by assignment. On a getter-only definition that write throws, so the text never reached the model and nothing reported it; on a writable one it survived disposal, leaving PTC Plus prose on a host object the plugin no longer owned.
14
+
15
+ ## Decision
16
+
17
+ Each interaction names the fact the plugin owns and the fact the host owns, and proves the relation with the former:
18
+
19
+ - **Reading an executor.** Which member may be invoked is not a shape question. Prompt assembly asks an executor exactly one declaration reader — `describe([])`, which says which reserved names it owns — and then the plugin's three contracted definition readers, `requirePtcTransport`, `requireTransport` and `transport`. No other member of a host executor is ever called. A host that declares the reserved name in `describe()` and publishes no definition through those readers is reported as *declared but unreadable* (an operator warning) instead of being folded into "this host has no executor"; the answer is recorded per executor as a property of the executor, and the readers are asked again on a later assembly because a scope can mount their service afterwards.
20
+ - **A batch-dispatched derived execution.** The dispatch records the submission on the execution object the plugin built, before the host runs it. The relation is then proved by the call id the plugin chose (which the host matches its batch result back to) together with the derived source; the parent token and root call are compared only on the registry contract, where the host runs the very object the plugin built. A batch host's own identity is never required to reproduce a token it never received.
21
+ - **Writing the editable slots.** The plugin installs an owned property definition and records the descriptor it replaced, once per definition. Both the writable and the accessor-only shape therefore carry the delivered text; a definition whose slot cannot be replaced keeps all of its own text rather than half of the plugin's; and disposal restores the recorded descriptors, so the host's own model-facing definition is exactly what it published before the attachment.
22
+
23
+ ## What this does not claim
24
+
25
+ - The reader names are the plugin's published contract with a transport-owning executor. A host that publishes the definition under another name is unreadable to this plugin until that name is added here — reported, not guessed at.
26
+ - Identifying a batch execution by its call id trusts the host to run the call it was given. The plugin already refuses a batch result that does not name the submitted id, so the alternative is refusing to relate the derived edit at all.
27
+ - Restoring a descriptor cannot succeed against a host that made the slot non-configurable after the plugin replaced it. That case keeps the last written text and is not reported as a host fault.
28
+
29
+ ## Alternatives considered
30
+
31
+ - **Probe every zero-argument member, with a denylist of lifecycle names.** Rejected: the denylist is a list of words, not a property of the members actually invoked, so any executor with an unlisted side-effecting member is executed during assembly.
32
+ - **Infer the parent token from the batch payload.** Rejected: it requires the host to adopt a field the batch contract does not define, and a host that ignores it leaves the relation unprovable — the defect returns whenever the optional executor package is a different revision.
33
+ - **Assign the slot and swallow the failure.** Rejected: silently not delivering the text the user edited is worse than a documented limitation, and it is the failure this decision exists to remove.
34
+ - **Restore the slot by writing the host's old text back.** Rejected: a host that published an accessor keeps reading its own state, so writing text back leaves a data property where an accessor was, and the model-visible definition changes shape because the plugin was unloaded.
35
+
36
+ ## Consequences
37
+
38
+ - Prompt assembly no longer invokes any host executor member beyond the declaration reader `describe([])` and the contracted definition readers, and a declared-but-unreadable transport is a visible operator warning rather than a set of features that quietly disappear.
39
+ - A derived edit settles as the root cell's derived execution on both dispatch contracts, so the deferred settlement, the pre-policy projection and the root cell's own durability decision are exercised on a batch host too.
40
+ - Disabling or unloading the plugin leaves the host's `run_code` definition with the text its owner published.
41
+ - `compat/channels.json` records every host package an install receives: a package outside the release train is pinned at the version the release's own dependency range resolves to, with that tarball's integrity, and a package the release neither publishes nor depends on is recorded as absent. A publish inside a declared range is therefore a recorded drift that the channel proof reports.
42
+
43
+ ## Related
44
+
45
+ - ADR 0017 owns tracking the newest published host surface.
46
+ - ADR 0049 owns proving a settlement against the record it published.
47
+ - [docs/runtime-reference.md](../runtime-reference.md) describes the executor reader contract.
48
+ - [docs/installation.md](../installation.md) describes the channel manifest a consumer install is proved against.
@@ -23,4 +23,10 @@ This directory records stable design constraints for PTC Plus. An ADR states a d
23
23
 
24
24
  - [0043: Compose Capability and Context Policies](0043-compose-capability-and-context-policies.md) — independent availability, disclosure, allocation, collection, recovery and presentation inputs with historical replay generations.
25
25
 
26
- - [0044: Coexist With The Official Persistent REPL](0044-coexist-with-the-official-persistent-repl.md) — forwarded owner release and program format, plus live-capability ownership selection between PTC Plus and the official persistent REPL.
26
+ - [0044: Coexist With The Official Persistent REPL](0044-coexist-with-the-official-persistent-repl.md) — forwarded owner release, program format and state retention, plus live-capability ownership selection between PTC Plus and the official persistent REPL.
27
+ - [0045: Customize Model-Visible Prompt Text](0045-customize-model-visible-prompt-text.md) — fixed plugin text becomes a document the user can edit per slot, with read-only segments and drafts.
28
+ - [0046: Gate The Commit With The Semantic Evidence Tier](0046-gate-the-commit-with-the-semantic-evidence-tier.md) — the change gate runs the semantic tier rather than a hand-picked file list.
29
+ - [0047: Store Journal Argument Digests In The Projection](0047-store-journal-argument-digests-in-the-projection.md) — the projection keeps argument digests so admission can reject a rewritten call.
30
+ - [0048: Supersede A Rewritten Cell](0048-supersede-a-rewritten-cell.md) — an edit with the rewrite setting on supersedes its target; the target stays in the log and its names are reported as replaced.
31
+ - [0049: Prove A Settlement Against Its Published Record](0049-prove-a-settlement-against-its-published-record.md) — a settlement carries the digest of what it asserts, so an edited record is not evidence.
32
+ - [0050: Read And Write The Host Surface Only Through Its Published Contract](0050-read-host-surfaces-through-their-published-contract.md) — contracted executor readers, the call id a batch host echoes back, and owned slot descriptors that disposal restores.
@@ -68,7 +68,7 @@ Skill 根在当前 generation 发布绝对 composition path 时取其 sibling;
68
68
 
69
69
  `internal/user-bindings-store.js` 独占 `$DSH_HOME/ptc-plus/bindings.json`。单一 JSON 文档避免源码与 metadata 双源;进程内队列、file lock、磁盘文本比较、expected revision 和 atomic replacement 共同防止并发覆盖。每次 mutation 在替换前验证完整 enabled snapshot 的声明预算;外部写入的超限文档按损坏输入处理。损坏输入保持显式 error,不会被空文档静默覆盖。候选与正式激活的相对 import 都以该文件所在目录为基准,因此 session cwd 不会改变 helper 的依赖解析。
70
70
 
71
- prompt assembly 为每个 PTC request 取得一次当前启用条目快照,作为随后 dispatch 的期望集合。`tools:ptc-plus-user-binding-defaults` 从首轮通过追加的 PTC API catalog 展示条目提示词及按开关选择的源码派生接口,按稳定 ID 排序,只描述配置 API 与执行时初始化契约;组装不执行源码,也不读取激活状态或加入 revision。`/binding` 保存并启用、会话中途启停、删除或修改模型上下文后,下一次宿主允许且接受的步骤追加当前说明或撤销旧说明,无需等待激活。条目变化不改写 system、tool schema、顺序或旧消息;未变说明按已提交日志与公共 ordered surface 去重,重启后继续使用相同证据。停用条目不贡献内容,关闭声明且提示词为空的条目同样省略。
71
+ prompt assembly 为每个 PTC request 取得一次当前启用条目快照,作为随后 dispatch 的期望集合。快照先经该会话的 adoption 决策过滤,再作为期望集合:全局启停拥有 supply(目录里有哪些条目),会话拥有 adoption(这个会话用其中哪些),worker 拥有 materialization(实际装上了哪些),诊断与 journal 拥有 proof。adoption 是每条目的二态决定加一个缺省——未表态即使用目录提供的一切,因此“显式使用”与“从未表态”产生同一环境,是一个状态而不是两个,也不需要借用能力侧的 `automatic`(那个词表示“由宿主推导”)。adoption 只能撤回已供给条目:全局停用的条目不在目录里,会话无从命名,`/binding skip` 直接拒绝,因此“覆盖复活已删除条目”没有编码,也无须规则禁止。决策记录为一条 `binding-adoption` PTC 消息,由 session log projection 读回最新一条,重启即从日志重建,不引入第二存储或进程内缓存。`tools:ptc-plus-user-binding-defaults` 从首轮通过追加的 PTC API catalog 展示条目提示词及按开关选择的源码派生接口,按稳定 ID 排序,只描述配置 API 与执行时初始化契约;组装不执行源码,也不读取激活状态或加入 revision。`/binding` 保存并启用、会话中途启停、删除或修改模型上下文后,下一次宿主允许且接受的步骤追加当前说明或撤销旧说明,无需等待激活。条目变化不改写 system、tool schema、顺序或旧消息;未变说明按已提交日志与公共 ordered surface 去重,重启后继续使用相同证据。停用条目不贡献内容,关闭声明且提示词为空的条目同样省略。
72
72
 
73
73
  配置段是全局绑定提示词与接口的唯一注入来源,不包含实现源码;成功初始化、session-local shadow 和 worker 重建本身不生成活动公告,也不触发相同配置重发。执行结果与诊断拥有实际行为证据;需要验证可用性时只对已知名称做无副作用观察。历史 `tools:ptc-plus-user-bindings` 活动段保留读取支持,下一次允许且接受的快照撤销旧活动声明一次。`tools:sdk` 与 direct-tool schema 不随条目内容改变。配置 API 不证明当前值,也不延长被 compaction 遮蔽的 session-local 状态。runtime 在 cell preflight 前把期望集合映射到 BindingCatalog,再由 worker 激活:当前覆盖粒度为 `per-name`,同名 session-local binding 只覆盖对应全局名称,同条目的其他名称继续激活;v1-v7 历史 cell 保留整条 entry 退出的旧粒度。条目级失败产生诊断并从该 cell 排除,不阻塞独立代码。失败 initializer 一旦发起 program call,整个 cell 进入 volatile,因此只包含成功条目的结果 snapshot 不会被误作该调用的 cold replay source。
74
74
 
@@ -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