dsh-ptc-plus 0.4.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.en.md +61 -123
  2. package/README.md +61 -123
  3. package/assets/dsh-ptc-plus-banner-en.webp +0 -0
  4. package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
  5. package/assets/ptc-plus-repl-workspace-en.png +0 -0
  6. package/assets/ptc-plus-repl-workspace-zh.png +0 -0
  7. package/assets/ptc-plus-settings-en.png +0 -0
  8. package/assets/ptc-plus-settings-zh.png +0 -0
  9. package/client.cjs +42336 -0
  10. package/cordis.patch.yml +13 -2
  11. package/docs/README.md +7 -2
  12. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +31 -179
  13. package/docs/adr/0008-define-agent-operating-contract.md +5 -1
  14. package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -2
  15. package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
  16. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +2 -2
  17. package/docs/adr/0019-plugin-settings-and-kill-switch.md +14 -3
  18. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
  19. package/docs/adr/0022-stage-npm-releases-with-oidc.md +4 -2
  20. package/docs/adr/0023-global-user-bindings.md +3 -1
  21. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +2 -0
  22. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +101 -35
  23. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +3 -3
  24. package/docs/adr/0031-close-semantic-obligations-by-owner.md +1 -1
  25. package/docs/adr/0032-own-session-log-facts-in-a-host-only-projection.md +27 -0
  26. package/docs/adr/0033-gate-client-visual-usability-in-a-browser.md +23 -0
  27. package/docs/adr/0034-keep-program-values-separate-from-output-projections.md +29 -0
  28. package/docs/adr/0035-run-coverage-only-before-a-new-release.md +27 -0
  29. package/docs/adr/0036-separate-focused-development-from-delivery-verification.md +29 -0
  30. package/docs/adr/0037-keep-tool-hover-previews-passive.md +52 -0
  31. package/docs/adr/0038-freeze-session-capability-plans.md +71 -0
  32. package/docs/adr/0039-verify-documentation-without-runtime-suites.md +29 -0
  33. package/docs/adr/0040-separate-capability-configurations-from-session-observations.md +39 -0
  34. package/docs/adr/0041-record-cell-execution-directories.md +65 -0
  35. package/docs/adr/0042-persist-provider-availability-and-handback.md +41 -0
  36. package/docs/adr/0043-compose-capability-and-context-policies.md +37 -0
  37. package/docs/adr/README.md +6 -0
  38. package/docs/architecture.md +25 -27
  39. package/docs/binding-review-placement-design.md +29 -21
  40. package/docs/capability-planning-components.md +93 -0
  41. package/docs/capability-projection.md +7 -0
  42. package/docs/client-ui.md +88 -29
  43. package/docs/client-visual-contract.md +65 -0
  44. package/docs/context-management.md +22 -0
  45. package/docs/context-optimization-plan.md +353 -0
  46. package/docs/context-public-interface-coverage.md +25 -0
  47. package/docs/durability-design.md +31 -14
  48. package/docs/evaluation.md +41 -6
  49. package/docs/evaluations/command-goat-deepseek-v4.1-flash-20261006.md +126 -0
  50. package/docs/evaluations/command-goat-deepseek-v4.1-flash.md +281 -0
  51. package/docs/installation.md +50 -8
  52. package/docs/program-data-plane.md +5 -3
  53. package/docs/publishing.md +5 -5
  54. package/docs/release-coverage.md +73 -0
  55. package/docs/release-notes.md +1 -1
  56. package/docs/review-procedure.md +56 -0
  57. package/docs/runtime-reference.md +48 -16
  58. package/docs/semantic-validation.md +14 -2
  59. package/docs/stateful-binding-updates-proposal.md +2 -2
  60. package/docs/user-bindings.en.md +2 -2
  61. package/docs/user-bindings.md +3 -3
  62. package/docs/value-wire.md +11 -1
  63. package/docs/verification-optimization-work.md +52 -15
  64. package/docs/verification.md +30 -86
  65. package/index.js +147 -23
  66. package/internal/binding-toggle-receipt.js +24 -0
  67. package/internal/capability-command-receipt.js +29 -0
  68. package/internal/capability-environment.js +1247 -0
  69. package/internal/capability-plan.js +285 -0
  70. package/internal/capability-policy.js +96 -0
  71. package/internal/capability-statistics-store.js +180 -0
  72. package/internal/capability-statistics.js +210 -0
  73. package/internal/compiler-platform.js +5 -3
  74. package/internal/compiler-service.js +2 -9
  75. package/internal/config-spec.js +79 -9
  76. package/internal/cordis-tools-owner.js +22 -19
  77. package/internal/direct-surface-owner.js +29 -29
  78. package/internal/dynamic-environment-runtime.js +9 -9
  79. package/internal/edit-transport-owner.js +183 -139
  80. package/internal/execution-provider-owner.js +160 -0
  81. package/internal/execution-seam-compat.js +76 -120
  82. package/internal/isolated-worker.js +12 -8
  83. package/internal/kernel-worker.js +104 -32
  84. package/internal/native-root-dynamic.js +12 -13
  85. package/internal/program-bindings.js +190 -0
  86. package/internal/recovery-tips.js +53 -23
  87. package/internal/rejected-cell-editor.js +8 -8
  88. package/internal/repl-observation-interest.js +11 -3
  89. package/internal/rpc-contract.js +1 -0
  90. package/internal/runtime-bridge-owner.js +351 -82
  91. package/internal/runtime-config.js +58 -0
  92. package/internal/runtime-contexts.js +85 -16
  93. package/internal/runtime-intrinsics.js +1 -0
  94. package/internal/runtime-messages.js +41 -0
  95. package/internal/sdk-projection.js +10 -82
  96. package/internal/session-cell-executor.js +42 -19
  97. package/internal/session-events.js +74 -4
  98. package/internal/session-journal-recovery.js +904 -184
  99. package/internal/session-journal-schema.js +6 -3
  100. package/internal/session-journal.js +31 -2
  101. package/internal/session-log-view.js +189 -43
  102. package/internal/session-runtime.js +175 -23
  103. package/internal/settings-compat.js +23 -6
  104. package/internal/stateful-module-compiler.js +3 -2
  105. package/internal/stateful-module-runtime.js +7 -3
  106. package/internal/stateful-root-runtime.js +9 -4
  107. package/internal/user-binding-authoring.js +2 -7
  108. package/internal/user-bindings-owner.js +47 -7
  109. package/internal/validated-parse-repair.js +1 -1
  110. package/internal/value-wire.js +68 -21
  111. package/internal/worker-cwd-virtualization.js +20 -18
  112. package/internal/worker-realm-surfaces.js +3 -3
  113. package/locale/en.json +6 -0
  114. package/locale/zh.json +6 -0
  115. package/package.json +55 -38
  116. package/src/client-authoring-view.js +286 -168
  117. package/src/client-binding-review.js +4 -1
  118. package/src/client-binding-toggle.js +18 -0
  119. package/src/client-capabilities-view.js +1341 -0
  120. package/src/client-capability-sort.js +29 -0
  121. package/src/client-code-editor.js +6 -0
  122. package/src/client-copy.js +881 -8
  123. package/src/client-feature-gates.js +15 -5
  124. package/src/client-host-compat.js +23 -2
  125. package/src/client-indicator-view.js +4 -6
  126. package/src/client-primitives.js +280 -0
  127. package/src/client-repl-view.js +23 -16
  128. package/src/client-settings-view.js +412 -69
  129. package/src/client-styles.js +193 -41
  130. package/src/client-tool-hover.js +185 -0
  131. package/src/client-tool-view.js +45 -11
  132. package/src/client-transport.js +44 -9
  133. package/src/client-workbench.js +9 -10
  134. package/src/client.js +148 -68
  135. package/assets/ptc-plus-bindings-en.png +0 -0
  136. package/assets/ptc-plus-bindings-zh.png +0 -0
  137. package/assets/ptc-plus-repair-en.png +0 -0
  138. package/assets/ptc-plus-repair-zh.png +0 -0
  139. package/client.js +0 -31857
@@ -1,6 +1,6 @@
1
1
  # Installation
2
2
 
3
- PTC Plus requires Node.js `^22.19.0 || >=24.0.0` and targets the latest available DSH release with TypeScript PTC mode. Compatibility with the preceding Host contract is retained through public capability detection; when both generations expose competing presentation evidence, the current DSH contract wins. Compatibility follows those live extension surfaces rather than a version allowlist.
3
+ PTC Plus requires Node.js `^22.19.0 || >=24.0.0` and targets the latest available DSH release with TypeScript PTC mode. Historical interface branches are retained through capability detection, without promising a fully verified earlier Host installation; when both generations expose competing presentation evidence, the current DSH contract wins. Compatibility follows those live extension surfaces rather than a version allowlist.
4
4
 
5
5
  The worker uses the Host's Node executable. Startup verifies native REPL framing, imports, syntax failures, synchronous throws, awaited rejections, and original return values. The adapter combines public eval callbacks with domain error events before REPL formatting; a source-end witness distinguishes empty completion from falsy rejection. A failed or timed-out probe reports a runtime prerequisite failure before user code executes. The engine range follows DSH; CI exercises Node 22.19, 24, and 26, without claiming that untested future releases have already passed.
6
6
 
@@ -18,20 +18,41 @@ Install the plugin into the profile that actually runs the target DSH surface. D
18
18
 
19
19
  `danger-full-access` is the primary supported experience. The worker isolates the REPL lifecycle; it is not a malicious-code sandbox. DSH continues to own native-tool scope, policy, approval, cancellation, sandboxing, and scheduling. Narrower profiles expose only their available capabilities; PTC Plus does not simulate missing authority or add another permission system.
20
20
 
21
- The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime services. PTC Plus declares the shared service packages as unrestricted required peers instead of installing private runtime copies. For a pathless preset it asks the Host's `pluginPackages.packageOf` service for the active generation's official preset package and requires the exact `cordis-plugin-development/SKILL.md` before mounting it; an older generation with no package service may resolve only its historical plural preset package relative to the Host's `ctx.baseUrl`. This compatibility path is disabled whenever `pluginPackages` exists, so packages merely reachable from the plugin profile cannot override an active Host result. Runtime capability validation owns compatibility, and CI loads the packed plugin against frozen official `latest` and `next` DSH graphs. That load step mounts the pathless Cordis companion from a separated active-host resource while a resolvable stale package is present beside the packed plugin, runs `scripts/dsh-execution-seam-smoke.mjs` to read and take over the execution service the installed tool runtime uses, and runs `scripts/dsh-rpc-contract-smoke.mjs` to register the packed Remote descriptors with the installed TYPERT registry and evaluate the decoder that generation reads ([ADR 0030](adr/0030-serve-both-typert-codec-generations-from-one-codec.md)); an import alone cannot distinguish a loaded plugin from one whose injection is unsatisfied, because Cordis leaves the latter pending without an error, and it cannot show that the Host accepts a wire contract it validates only at registration. The same suite round-trips argument diagnostics through the selected Host's compressed JSONL Session persistence. Service packages retain the dependency graph selected by their Host distribution rather than independently selecting each service's release tag. DSH's profile module fallback must resolve the peers, while `pluginPackages` identifies the official preset resource from an active installation that publishes the service. Do not copy `SKILL.md` or add the Cordis preset's Skill directory to global roots. If the host surface is incomplete, plugin activation or enabling the setting fails instead of loading a second DSH core.
21
+ The optional `cordisToolsEnabled` integration requires the current DSH installation to provide its shipped `cordis` preset plus the public preset, Skill, Cordis, settings, and tool-runtime services. PTC Plus declares the shared service packages as unrestricted required peers instead of installing private runtime copies. For a pathless preset it asks the Host's `pluginPackages.packageOf` service for the active generation's official preset package and requires the exact `cordis-plugin-development/SKILL.md` before mounting it; an older generation with no package service may resolve only its historical plural preset package relative to the Host's `ctx.baseUrl`. This compatibility path is disabled whenever `pluginPackages` exists, so packages merely reachable from the plugin profile cannot override an active Host result. Runtime capability validation owns compatibility, and CI checks the packed plugin against frozen official `latest`, `next`, and newest published release graphs. Each result applies only to the tested cohort. That load step mounts the pathless Cordis companion from a separated active-host resource while a resolvable stale package is present beside the packed plugin, runs `scripts/dsh-execution-seam-smoke.mjs` to exercise public provider composition around the execution service the installed tool runtime uses, and runs `scripts/dsh-rpc-contract-smoke.mjs` to register the packed Remote descriptors with the installed TYPERT registry and evaluate the decoder that generation reads ([ADR 0030](adr/0030-serve-both-typert-codec-generations-from-one-codec.md)); an import alone cannot distinguish a loaded plugin from one whose injection is unsatisfied, because Cordis leaves the latter pending without an error, and it cannot show that the Host accepts a wire contract it validates only at registration. The same suite round-trips argument diagnostics through the selected Host's compressed JSONL Session persistence. Service packages retain the dependency graph selected by their Host distribution rather than independently selecting each service's release tag. DSH's profile module fallback must resolve the peers, while `pluginPackages` identifies the official preset resource from an active installation that publishes the service. Do not copy `SKILL.md` or add the Cordis preset's Skill directory to global roots. If the host surface is incomplete, plugin activation or enabling the setting fails instead of loading a second DSH core.
22
22
 
23
23
  The plugin attaches to whichever program-execution service the installed DSH registers, and it presents the capabilities of the execution it performs ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)). Cells run in the session kernel under the session's configured budgets, so `run_code` advertises neither a per-call deadline nor a file sandbox, and DSH rejects `timeoutMs` and `sandbox_permissions` with its own message instead of the plugin accepting an input it would then ignore.
24
24
 
25
+ Install the complete `cordis.patch.yml` bundle, not only its main plugin row. The bundle preserves the original `ptc-runtime` module and configuration, isolates its `ptcRuntime` service as `ptc-plus-original`, and adds the independent `dsh-ptc-plus/execution-provider` row before the main row. A custom composition must set that provider row's `originalEntryId` to its actual source row ID relative to the provider row's Loader tree (the profile Include subtree in standard installations) and its `isolation` to the same value as the source row's `isolate[serviceName]`; set `serviceName` to the source service (`codeRuntime` for request-only execution, `ptcRuntime` for the resolved-spec contract); keep PTC Plus runtime settings on the main row. The adapter registers its own public provider and never writes to the original instance. Disabling the main row restores native delegation through the adapter; removing the complete bundle also restores the original global service. An uncomposed original produces an explicit composition diagnostic rather than a mutation fallback.
26
+
25
27
  Supported installations use an unmodified official DSH release. Local plugin development packages this checkout. The release development launcher uses the published Host; the opt-in [upstream source launcher](#upstream-source-development-launcher-windows) builds the unmodified official repository for testing unreleased changes. Neither path patches the Host. Missing public layout interfaces remain a feature limitation, not an instruction to customize DSH. See [ADR 0017](adr/0017-track-the-latest-dsh-public-surface.md) for distribution and acceptance requirements.
26
28
 
27
- The Client root requires `slots`, `locale`, `connection`, and `remote`; it resolves whichever public settings transport the installed Host exposes (`configForms` or `settingsScope`) through an optional injection. Contributions wait for their public slots and consume the supplied session hooks; the composer action additionally requires `remote.commands`. Neither an unused `ui-session` module nor a renamed conversation registry gates activation. Preset selection prefers `agentPreset` projection evidence, falling back only to the preceding public session summary field when that projection is absent. Binding values and draft capabilities always require their own projections. No private store or raw-log fallback is used. Slot and provider disposal withdraw the contributions they own.
29
+ The Client root requires `slots`, `locale`, `connection`, and `remote`; it adopts whichever public settings transport the installed Host exposes (`configForms` or `settingsScope`) through an optional injection and keeps its shipped `CONFIG_FIELDS` defaults while neither is available, so a renamed or withdrawn transport degrades the settings surface instead of suspending activation. Feature eligibility follows those defaults: only an explicit `enabled: false` withdraws a contribution. Contributions wait for their public slots and consume the supplied session hooks; the composer action additionally requires `remote.commands`. Neither an unused `ui-session` module nor a renamed conversation registry gates activation. Preset selection prefers `agentPreset` projection evidence, falling back only to a historical public session summary field when that projection is absent. Binding values and draft capabilities always require their own projections. No private store or raw-log fallback is used. Slot and provider disposal withdraw the contributions they own.
30
+
31
+ ### Compatibility Evidence
32
+
33
+ The frozen dependency graphs are installation cohorts, not proof of distinct capability generations. `compat/latest/package-lock.json`, the root `package-lock.json`, and `compat/current/package-lock.json` record the latest-tag, next-tag, and newest published-release cohorts respectively; their recorded provenance does not prove live registry availability or untested compatibility. The latest/next cohorts exercise `ptcRuntime`, `configForms`, `plugins.row.config`, volatile configuration and `codec.create()`. `npm run host:baseline:verify` checks frozen graph consistency, not every historical fallback or current registry availability.
34
+
35
+ | Retained interface | Evidence and consequence of removal |
36
+ | --- | --- |
37
+ | `retainedBy.mainView`, `plugins.row.config`, volatile updates, `codec.create()`, composer props carrying their own `sessionId` | Required by the frozen graphs; these are current paths, not optional historical fallbacks. |
38
+ | `settingsScope`, `settings.plugin.item`, section-installer variants | Historical, unfrozen Host shapes, covered with fixtures. Removal loses their live settings, card seat or reconfiguration path. |
39
+ | `snapshot.current`, bare summary `agentPreset` | Historical, unfrozen selection and preset shapes. Removal can strand their session-specific views or PTC eligibility. Binding and draft evidence never use the preset fallback. |
40
+ | Historical icon names and missing primitives | Fixtures establish component fallback, not a complete earlier Client. Removal of icon candidates loses native glyphs; usable text/component fallbacks must remain. |
41
+ | Menu without a `children` region | Rendering probe plus a plugin-owned fallback. Removal makes binding actions unreachable on that historical primitive; JSX is not passed through the Host's string-only label field. |
42
+ | `codec.schema` | Historical, unfrozen registry shape. Removal rejects Remote registration on schema-only Hosts. The factory and schema share one decoder. |
43
+ | `codeRuntime.run(request)` | Explicit request-only composition support. Public Loader tests preserve request identity, reload and removal; the default bundle and current official base profile use the resolved-spec `ptcRuntime` contract. |
44
+ | Plural preset-package layout and Host-anchored resolution | Historical Hosts without `pluginPackages` need this companion-resource path. Removal breaks their Cordis companion; it must never override an available active-Host package service. |
45
+ | `sessionQuery.observeSession` and host-only `sessionProjections` | Current history and presentation owners; missing services are diagnosed, not treated as empty recovery evidence. The projection publishes no Client wire view. |
46
+ | Legacy session event arrays and V0 boundary migration | Read-only fixtures preserve historical ancestry and file conversion through the shared event transition. Removal can discard reconstructable older sessions; malformed arrays are diagnosed, and format conversion does not prove a complete older Host's live behavior. |
47
+
48
+ Capabilities select behavior, never a release number. Historical fixture success is not packed-Host evidence. Full Host smoke is bounded to its selected graph, and a clean build is not live browser activation. Public provider composition supports frozen original execution instances without changing their descriptors. The result bridge requires mutable registered tool definitions ([ADR 0028](adr/0028-attach-to-the-host-ptc-execution-seam.md)); frozen tool definitions remain unsupported. The public admission boundary uses DSH's published `ptc` mode: `run_code` is the sole top-level transport, and the agent-scoped editor is invoked through `tools.edit_run_code` inside a program ([ADR 0005](adr/0005-temporary-rejected-cell-edit-transport.md#public-integration-status)). Packed lifecycle evidence covers actual nested admission, derived execution, persisted recovery and provider handback on its frozen official Host graph; an internal fixture or provider seam probe alone does not establish that compatibility. Proven native miscalls are normalized before Host dispatch; an unnormalized root call can reach approval before the plugin rejects it.
28
49
 
29
50
  ## npm Release
30
51
 
31
52
  Use this form after the selected version is available from the npm registry:
32
53
 
33
54
  ```sh
34
- dsh plugin --profile <profile> add dsh-ptc-plus@0.4.8
55
+ dsh plugin --profile <profile> add dsh-ptc-plus@0.5.0
35
56
  dsh --profile <profile> --dump-config
36
57
  ```
37
58
 
@@ -68,7 +89,7 @@ pnpm dsh --profile <profile> --dump-config
68
89
 
69
90
  ```sh
70
91
  npm pack
71
- dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.4.8.tgz
92
+ dsh plugin --profile <profile> add /absolute/path/to/dsh-ptc-plus-0.5.0.tgz
72
93
  dsh --profile <profile> --dump-config
73
94
  ```
74
95
 
@@ -78,6 +99,10 @@ Windows development checkouts can create and install an immutable content-addres
78
99
  scripts\install-dev.cmd <profile>
79
100
  ```
80
101
 
102
+ `install-dev.cmd`, `run-dev-dsh.cmd`, and `run-upstream-dsh.cmd` share a Windows dependency check before packing. The check validates installed direct dependencies against `package-lock.json`, checks that resolvable module entries and declared CLI executables exist in their local installed packages, and executes esbuild with the selected Windows Node. Executable-only packages and packages without an exported require root remain valid. A working checkout uses its existing dependencies. If they are missing, stale, or contain a Linux binary installed by WSL, the scripts automatically run Windows `npm ci` in the Git-ignored `win_node_modules` directory. That directory holds a refreshed copy of package inputs and prepack scripts alongside its own standard `node_modules`, so both ESM imports and bundler resolution use the Windows dependencies. The original checkout's `node_modules` is untouched.
103
+
104
+ Unchanged manifest, lockfile, Node runtime, and process registry settings reuse the cached dependencies after the dependency check. Changed inputs or detected dependency damage trigger a fresh isolated installation. Failed installation leaves no successful-install marker and can be retried. Failed packing in the cache also clears that marker, preserving the original failure and requiring a clean installation on retry if prepack exposed damage beyond the probe. Concurrent packing in the same cache stops with a clear diagnostic. Source inputs refresh on every pack, and stale generated bundles still fail `build:check` rather than being rebuilt silently. You can remove `win_node_modules` while these scripts are stopped to reclaim the cache; the next fallback recreates it.
105
+
81
106
  Installation and a successful Host import do not prove browser activation. Run the model-free packed Web smoke from this checkout with the latest DSH installed, its `pnpm` available, and a Playwright browser:
82
107
 
83
108
  ```sh
@@ -87,9 +112,17 @@ npm run test:client:web -- --dsh-entry /absolute/path/to/dsh/lib/bin.js
87
112
 
88
113
  On Windows, `--browser-channel msedge` can use the existing Edge installation. The script packs the current source, installs the tarball through `dsh plugin` into a temporary `DSH_HOME`, starts Web on a free loopback port, and opens the conversation and PTC Plus settings surfaces. It closes its browser/Host and removes the temporary profile; screenshots and release evidence remain under ignored `artifacts/client-web-smoke/`. It makes no model request and does not use or update the normal profile. `npm run test:client` supplies the deterministic provider, renderer, projection, and disposal tests included in `verify`/`check`.
89
114
 
115
+ The README's bilingual interface screenshots come from the same prerequisites. Refresh them from the current candidate instead of capturing by hand:
116
+
117
+ ```sh
118
+ npm run readme:screenshots -- --dsh-entry /absolute/path/to/dsh/lib/bin.js
119
+ ```
120
+
121
+ `scripts/readme-screenshots.mjs` packs the checkout, installs the tarball into a temporary `DSH_HOME`, boots the official Web Host with the deterministic `scripts/readme-screenshots-fixture.mjs` provider, runs one PTC session per locale — each session's title is that locale's prompt — plus the plugin settings dialog, and writes `assets/ptc-plus-repl-workspace-<locale>.png` and `assets/ptc-plus-settings-<locale>.png` at 1.5× pixel density. The settings frame photographs the dialog at the width the product gives it on a wide window; the REPL frame photographs the window with its sidebar collapsed. `--out <directory>` stages the frames elsewhere for review and `--locale zh` or `--locale en` refreshes one language. The run makes no model request and leaves the operator's profile untouched. Each capture confirms its surface while photographing into a staging directory — surface present, REPL observation settled, layout photographable — and all frames reach the output directory only after the whole run, including its page-error assertion, passes, so a broken candidate cannot replace a README image. A headless runner needs a font covering both locales (`fonts-noto-cjk` on Debian and Ubuntu images); without one the frames render missing-glyph boxes.
122
+
90
123
  ## Isolated latest-DSH development launcher
91
124
 
92
- To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It orders all published DSH releases by semantic version, prereleases included, and selects the newest release whose complete dependency cohort npm can install, rather than following a dist-tag that a release can leave behind. If a newly published root package still has missing exact-version dependencies, the launcher warns and tries the preceding release; an explicit `DSH_DEV_VERSION` remains exact and fails instead of falling back. It installs only when the selected cached version changes, creates the shipped `web` profile inside an isolated `DSH_HOME`, installs this checkout, and starts DSH. When no port is supplied, the default Web profile reuses its cached loopback port while that port is available; an invalid cache entry or occupied port is replaced with a free port. This keeps browser authentication stable across ordinary restarts without blocking another DSH on port 3080. The launched Host receives a 64 KiB HTTP request-header limit while retaining existing Node options to accommodate development authentication cookies and the combined Client plugin request during Web boot. The launcher does not modify the repository or your normal DSH home.
125
+ To test this checkout in a separate DSH installation, double-click `scripts\run-dev-dsh.cmd`. It orders all published DSH releases by semantic version, prereleases included, and selects the newest release whose complete dependency cohort npm can install, rather than following a dist-tag that a release can leave behind. If a newly published root package still has missing exact-version dependencies, the launcher warns and tries the preceding release; an explicit `DSH_DEV_VERSION` remains exact and fails instead of falling back. It installs only when the selected cached version changes, creates the shipped `web` profile inside an isolated `DSH_HOME`, installs this checkout, and starts DSH. When no port is supplied, the default Web profile reuses its cached loopback port while that port is available; an invalid cache entry or occupied port is replaced with a free port. This keeps browser authentication stable across ordinary restarts without blocking another DSH on port 3080. The launched Host receives a 64 KiB HTTP request-header limit while retaining existing Node options to accommodate development authentication cookies and the combined Client plugin request during Web boot. The launcher does not modify tracked repository files, the checkout dependency directory, or your normal DSH home.
93
126
 
94
127
  The launcher defaults to `https://registry.npmjs.org/` for version queries, npm installs and DSH's pnpm subprocesses, including the `@deepseek-ai` scope. This avoids mirror synchronization gaps where a new DSH package is available before its dependencies. It prints the selected registry and refreshes version metadata online; an unavailable version query can still reuse the previously cached version. Set `DSH_DEV_REGISTRY` to an absolute HTTP(S) registry URL to select another source explicitly. The choice applies only to the launcher process and its children; npm configuration files and persistent environment settings are unchanged. Other explicitly configured package scopes retain their own registries.
95
128
 
@@ -124,11 +157,20 @@ dsh plugin add github:muyuanjin/dsh-ptc-plus#main
124
157
  dsh --dump-config
125
158
  ```
126
159
 
127
- After an npm release, the package spec may instead be `dsh-ptc-plus@0.4.8`. For a local package, use its absolute tarball path. Restart DSH Desktop after installation. Linux Desktop is not a current DSH Desktop release target; use DSH CLI/Web on Linux.
160
+ After an npm release, the package spec may instead be `dsh-ptc-plus@0.5.0`. For a local package, use its absolute tarball path. Restart DSH Desktop after installation. Linux Desktop is not a current DSH Desktop release target; use DSH CLI/Web on Linux.
128
161
 
129
162
  ## Upgrades
130
163
 
131
- PTC Plus upgrades independently of the host. Replace the installed package with the new release the same way it was installed — `npm install dsh-ptc-plus@latest`, a new tarball, or an updated pinned Git revision in the profile patch — and restart the host so every profile reloads the plugin. The plugin never patches DSH and never requires a custom host build, so a host upgrade keeps the plugin working as long as the public surfaces it needs are still published.
164
+ PTC Plus upgrades through the official profile package transaction. From any working directory, explicitly target the installed profile:
165
+
166
+ ```sh
167
+ dsh plugin --profile <profile> add dsh-ptc-plus@latest
168
+ dsh --profile <profile> --dump-config
169
+ ```
170
+
171
+ For a tarball or a different pinned Git revision, replace the `add` argument with the absolute tarball path or `github:muyuanjin/dsh-ptc-plus#COMMIT_SHA`. This updates the profile dependency spec; the Loader module name remains `dsh-ptc-plus`. `dsh plugin --profile <profile> update dsh-ptc-plus` updates within its saved dependency constraint, so it cannot move an exact pinned revision to a different revision. Bare commands in Desktop's **Open DSH Terminal** target its active profile.
172
+
173
+ Restart the selected Host after the package transaction and verify its selected package and full bundle in the plugin page and `--dump-config`; installing dependencies alone does not replace already loaded JavaScript. Preserve the bundle's existing enabled/disabled choice. A source-checkout `npm ci` only prepares developer dependencies, and Windows build-cache preparation only prepares a tarball: neither upgrades a profile. Avoid `npm install` in an unrelated shell directory and do not edit Loader module names to encode revisions. The plugin never patches DSH or requires a custom Host build. Compatibility claims require the current published cohort's packed acceptance evidence.
132
174
 
133
175
  Your settings document and session logs are not rewritten by an upgrade. A release that adds a configuration field applies its documented default until you choose a value. A release that raises the Session format generation requires the migration below before an older log is opened by the new Host; the plugin reports that condition instead of rewriting history on its own.
134
176
 
@@ -4,11 +4,11 @@
4
4
 
5
5
  ## Typed tools
6
6
 
7
- 浏览、搜索和 DSH 服务调用使用当前 scope 的 native `tools.*`。canonical result 直接进入 cell,不经过 PTC 参数翻译或结果裁剪。对完全省略参数的 native call,runtime 只在 DSH 的 live object schema 验证 `{}` 合法时把 omission 规范为 `{}`;该值随后统一进入 encoding、dispatch、journal 和 replay comparison。`tools.cordis_inspect_list()` 因而等价于显式传入 `{}`,但显式 `undefined`、需要输入的工具、`capabilities.*` 和 owner-provided namespace 不受影响。具体结果可能 complete、bounded、incremental、open-world 或 unknown;模型/UI rendering 的裁剪不能反推 program value 的完整性。
7
+ 浏览、搜索和 DSH 服务调用使用当前 scope 的 native `tools.*`。canonical result 经 PTC graph IPC 进入 cell,不经过参数翻译或结果裁剪;IPC 支持域不扩展 native 工具的 JSON schema 与 lossless JSON 校验。参数编码拒绝发生在 dispatch 前;调用完成后的结果编码拒绝不能声称工具未执行,也不会自动重试。对完全省略参数的 native call,runtime 只在 DSH 的 live object schema 验证 `{}` 合法时把 omission 规范为 `{}`;该值随后统一进入 encoding、dispatch、journal 和 replay comparison。`tools.cordis_inspect_list()` 因而等价于显式传入 `{}`,但显式 `undefined`、需要输入的工具、`capabilities.*` 和 owner-provided namespace 不受影响。具体结果可能 complete、bounded、incremental、open-world 或 unknown;模型/UI rendering 的裁剪不能反推 program value 的完整性。
8
8
 
9
- PTC 模式的 code-only direct-tool projection 只声明模型直接调用真实注册的 `run_code` 与 `edit_run_code`。模型误发的顶层 native call 不属于这个合法 direct protocol;当 live schema 能唯一证明该工具时,transport normalization 将它包装为 `run_code`,cell 再调用同一 `tools.*` member。canonicalizer 先解析并校验一次原始 JSON:普通参数原样嵌入 JavaScript,含 own `__proto__` 的值改用安全字面量;因此派生 cell 不需要 `JSON.parse`,同时保持参数执行语义。规范化不向模型暴露 provenance、纠错提示或额外标记。参数仍由 DSH owner contract 正式验证,未知、畸形或不一致调用原样交给宿主诊断。该历史规范化只适用于无效的 out-of-surface call,不适用于已经合法声明的 `edit_run_code`。
9
+ PTC 模式的 code-only direct-tool projection 只声明顶层 `run_code`。真实注册的 editor 从首轮 program SDK 通过 `tools.edit_run_code` 调用。模型误发的顶层 native call 只有在 live schema 唯一证明该工具时才可规范为调用同一 member 的 `run_code`;editor 不由这条修复路径取得执行资格。canonicalizer 保留原始 JSON 参数,含 own `__proto__` 的值使用安全字面量,超过 TypeScript parser 安全深度的 JSON 使用浅层 `JSON.parse` 表达式。DSH 仍拥有正式 validation、authority 和 result semantics。
10
10
 
11
- `edit_run_code` 是宿主 composite tool:外层 result 向模型返回精简的编辑状态、值与日志,完整物化源码和 journal 只进入标记为 derived 的私有 metadata。cold replay 消费该记录,不把完整源码重新投影给模型,也不把派生 `run_code` 归因给 assistant。
11
+ `tools.edit_run_code` 返回接受或拒绝收据;接受安排完整修订源码在当前外层 cell 结束后经 DSH 正式工具流水线执行。根结果保留外层 canonical return/error,并转发派生执行的正式展示内容。完整派生源码、journal 和 nested 来源关系进入根结果的私有 metadata。cold replay 验证该证据并返回 recorded program-call 值,不重新派发 editor,不把派生 `run_code` 归因给 assistant。参见 [编辑与结算契约](adr/0005-temporary-rejected-cell-edit-transport.md)。
12
12
 
13
13
  每次调用进入 journal:
14
14
 
@@ -20,6 +20,8 @@ DSH authority/policy -> native dispatch -> canonical result
20
20
 
21
21
  cold replay 校验相同的调用序列并返回 recorded value,不重新执行工具。这保证 REPL 计算状态可重建,但不声称外部 effect 可逆或仍与历史相同。Cordis Plugin、Run 和 Inspect observation 属于进程内实时状态;恢复出的 Cordis value 只作为历史数据保留,后续状态性决策必须先按恢复 context 执行新的 live Inspect。
22
22
 
23
+ 插件自有隔离 `code.run` 向父程序返回 canonical completion 的值图,模型展示投影仅用于外层;native 委托保持其 owner-defined result。父子 binding 保持隔离,显式 undefined 与无 return 有区别;历史 recorded-value 字符串不被重新解释。详见 [值契约](value-wire.md)。
24
+
23
25
  同一 settlement 规则适用于当前 request 中的全部 program binding,包括 owner-provided namespace 与 `code.run`。已结算的 value/error 可进入 durable transcript;若取消、超时或 worker failure 发生时调用仍未结算,cell heap 回滚,discarded journal 以实际 `global.member` 保留 possible-effect boundary。分类来自可观察生命周期,不来自 capability 名称表。
24
26
 
25
27
  直接 Node/OS 输入没有 binding transcript。worker 首次观察到这类 volatile 边界时立即通知主线程;即使 cell 随后 hard abort、timeout 或 worker exit,discarded journal 仍保留已观察原因。该恢复事实不作为普通成功任务的模型可见警告。
@@ -20,7 +20,7 @@
20
20
 
21
21
  npm 发布遵循 [ADR 0022](adr/0022-stage-npm-releases-with-oidc.md),使用 `.github/workflows/release.yml` 声明的 Trusted Publisher,不向 GitHub 保存 npm write token。npm package settings 必须把 publisher 精确绑定到 `muyuanjin/dsh-ptc-plus`、workflow filename `release.yml` 和 environment `npm-release`,且只允许 `npm stage publish`。Publishing access 选择页面中最严格且标记为 recommended 的 2FA 选项;npm 文档称其为 `Require two-factor authentication and disallow tokens`,当前 npm 页面也可能显示 `Require two-factor authentication and disallow bypass 2fa tokens (recommended)`。不要从滚动变化的标签推断账户中已不存在传统 token。OIDC 只把经过验证的 tarball 放入 npm staging,维护者仍须在 npm CLI 或 npmjs.com 检查 staged package 并以 2FA approve,包才会进入公开 registry。
22
22
 
23
- 普通 `CI` 只在 `main` push 或 pull request 包含非纯文档变更时运行:只改动 `**.md`、`assets/**` 或 `LICENSE` 的提交不触发矩阵。发布 commit 因包含 `package.json` 与 `package-lock.json` 变更必然产生一次 `main` push run,Release workflow 仍要求该 commit 有成功的 run 才继续。发布前创建 annotated `v<package.version>` tag,原子推送 release commit 与 tag,等待该 commit 的 `CI` 成功,然后以该 tag 作为 ref 显式运行 `Release` workflow。workflow 不接受另一个 tag input,并会重新证明 dispatch 的 `GITHUB_REF`、`GITHUB_SHA`、annotated tag target、checkout HEAD、manifest 版本和成功 CI 的 SHA 完全一致;release job 使用 GitHub-hosted Node `24.15.0`、npm `12.0.2`、无 package-manager cache 和最小 `id-token: write` 权限,构建一个 tarball、执行 clean-consumer smoke,再对同一文件执行 `npm stage publish`。`package.json#allowScripts` 显式拒绝当前不需要的 `esbuild` install script;`replace-registry-host=always` 让 release install 将 lockfile 中的 registry tarball 路由到显式 npm 官方 registry,而不放宽 npm 12 的 Git/remote dependency 默认拒绝。
23
+ 普通 `CI` 只在 `main` push 或 pull request 包含非纯文档变更时运行:只改动 `**.md`、`assets/**` 或 `LICENSE` 的提交不触发矩阵。发布 commit 因包含 `package.json` 与 `package-lock.json` 变更必然产生一次 `main` push run,Release workflow 仍要求该 commit 有成功的 run 才继续。发布前创建 annotated `v<package.version>` tag,原子推送 release commit 与 tag,等待该 commit 的 `CI` 成功,然后以该 tag 作为 ref 显式运行 `Release` workflow。workflow 不接受另一个 tag input,并会重新证明 dispatch 的 `GITHUB_REF`、`GITHUB_SHA`、annotated tag target、checkout HEAD、manifest 版本和成功 CI 的 SHA 完全一致;release job 使用 GitHub-hosted Node `24.15.0`、npm `12.0.2`、无 package-manager cache 和最小 `id-token: write` 权限,构建一个 tarball、执行使用同一冻结宿主 peer 图的 clean-consumer smoke,再对同一文件执行 `npm stage publish`。`package.json#allowScripts` 显式拒绝当前不需要的 `esbuild` install script;`replace-registry-host=always` 让 release install 将 lockfile 中的 registry tarball 路由到显式 npm 官方 registry,而不放宽 npm 12 的 Git/remote dependency 默认拒绝。
24
24
 
25
25
  ```powershell
26
26
  git tag -a "v$((Get-Content package.json | ConvertFrom-Json).version)" -m "v$((Get-Content package.json | ConvertFrom-Json).version)"
@@ -42,11 +42,11 @@ npm.cmd stage approve '<stage-id>' --registry=https://registry.npmjs.org/
42
42
 
43
43
  ## Release checklist
44
44
 
45
- 1. 提交前在稳定工作树上运行完整 `npm run check`,生成 coverage 与 review proof。仓库 CI 在 Linux Node `22.19.0`、24.x、26.x,以及 Windows 与 macOS Node 24.x 的干净安装上运行 `npm run verify:ci`,检查构建、Client 与跨平台关键运行契约;Ubuntu Node 24.x 另运行打包后的 `latest` / `next` Host contracts。CI 不重复收集 coverage 或执行穷尽式后端套件。
46
- 2. 运行 `npm audit --omit=dev`、`npx publint`、`git diff --check`、Markdown local-link check 和 `npm pack --silent --dry-run --json`。audit 检查随包安装的 production 依赖图;宿主 DSH 及其开发依赖不进入插件 tarball,由冻结宿主契约和 CI 单独验证。确认 tarball 只包含发布白名单内的运行时代码、文档和展示资产,不含凭据、本地路径、开发脚本或测试夹具,并从 tarball 安装到空目录执行 ESM import smoke。机器读取 `npm pack --json` 时保持 `--silent`,避免 lifecycle 输出混入 JSON stream。
45
+ 1. 提交前在稳定工作树上运行完整 `npm run check`,执行无覆盖插桩的完整普通后端测试并生成 review proof。覆盖率只在准备发布新版本时运行;Release workflow 在打包与 npm staging 前对 release tag 执行 `npm run coverage`,要求行与函数覆盖率 100%、分支覆盖率至少 95%。发布准备期间可在本地运行同一命令,并用 `npm run coverage:focus` 诊断覆盖率缺口;日常开发、审查与提交不运行覆盖率专用套件、采集探针或插桩分支;这些测试由 `test/coverage/` 和发布入口的显式标记拥有。仓库 CI 在 Linux Node `22.19.0`、24.x、26.x,以及 Windows 与 macOS Node 24.x 的干净安装上运行 `npm run verify:ci`,检查构建、Client 与跨平台关键运行契约;Ubuntu Node 24.x 另运行打包后的 `latest` / `next` Host contracts。普通 CI 不收集 coverage 或执行穷尽式后端套件。
46
+ 2. 运行 `npm audit --omit=dev`、`npx publint`、`git diff --check`、Markdown local-link check 和 `npm pack --silent --dry-run --json`。audit 检查随包安装的 production 依赖图;宿主 DSH 及其开发依赖不进入插件 tarball,由冻结宿主契约和 CI 单独验证。确认 tarball 只包含发布白名单内的运行时代码、文档和展示资产,不含凭据、本地路径、开发脚本或测试夹具,并执行 `npm run test:package:consumer -- <tarball>`:入口先校验当前安装的宿主与其 lock 一致,再将宿主实际提供的 peer 版本与 tarball 放在同一次 npm 安装事务中,在空目录执行 ESM import、内置编译器栈与内核 worker 加载 smoke。不能让 npm 对各宿主 peer 分别选用 dist-tag;插件继续声明不限制版本的 required peers,不私装宿主服务副本。机器读取 `npm pack --json` 时保持 `--silent`,避免 lifecycle 输出混入 JSON stream。
47
47
  3. 更新到最新可用 DSH release 并记录 `dsh --version`。分别从 npm 包、固定 Git commit、源码 checkout 和 tarball 安装到临时 profile,再执行 `dsh --profile <profile> --dump-config`,确认只新增 `ptc-plus` row。每个上游 release 都重新验证公共扩展面、CLI/Web 集成和 profile 装配,不设置版本白名单。
48
- 4. 在 Windows 与 Linux 运行无模型调用的 `npm run test:client:web -- --dsh-entry <latest-installed-dsh/lib/bin.js>`,验证 tarball 安装后的真实 Web Client、设置与对话 surface;浏览器前置条件见 [安装指南](installation.md)。`build:check`、Host ESM import 和 factory smoke 均不能替代浏览器激活验收。macOS 由原生 runner 验证 CLI/Web;Windows 与 macOS Desktop 从托盘打开当前 profile 的 DSH Terminal 安装,重启 Desktop 后做一次 PTC 模式 smoke。Desktop 当前发布平台不包括 Linux。
49
- 5. 只有在明确授权模型消耗后才运行 `npm run test:expensive` 与 `npm run test:ab`。发布结论以结构化测试结果为准,不把一次模型样本推广为普遍保证。
48
+ 4. 在 Windows 与 Linux 运行无模型调用的 `npm run test:client:web -- --dsh-entry <latest-installed-dsh/lib/bin.js>`,验证 tarball 安装后的真实 Web Client、设置与对话 surface;浏览器前置条件见 [安装指南](installation.md)。`build:check`、Host ESM import 和 factory smoke 均不能替代浏览器激活验收。macOS 由原生 runner 验证 CLI/Web;Windows 与 macOS Desktop 从托盘打开当前 profile 的 DSH Terminal 安装,重启 Desktop 后做一次 PTC 模式 smoke。Desktop 当前发布平台不包括 Linux。界面有变化时用同一前置条件刷新 README 截图:`npm run readme:screenshots -- --dsh-entry <latest-installed-dsh/lib/bin.js>` 从当前打包候选各写回一帧中英文 REPL 工作台与设置窗口;先用 `--out <directory>` 落到别处检查,命令、前置条件与失败边界见 [安装指南](installation.md)。
49
+ 5. 只有在明确授权模型消耗后才运行 `npm run test:expensive` 与 `npm run test:ab`;发布候选还要用 `DSH_PTC_ACCEPTANCE_SCENARIOS=managed-adaptive-surface,managed-session-resume,managed-surface-change,subagent-continuity` 追加托管能力面、会话恢复、宿主表面变化与子代理场景(运行方式、预算与版本差异判别见[评估](evaluation.md#managed-session-continuity-cohort))。发布结论以结构化测试结果为准,不把一次模型样本推广为普遍保证。
50
50
  6. 确认 npm 包名可用、待发布版本高于 registry 版本、README 截图来自真实 DSH 会话,并核对 repository、homepage、bugs、license 与 `dsh-plugin` topic。
51
51
  7. 最后检查 `npm pack --silent --json` 的名称、版本、大小与文件列表,创建 annotated release tag,并确认 tag commit 已通过 `CI`。运行 `Release` workflow 将同一源码产生的 tarball送入 npm staging;人工检查并以 2FA approve 后,等待 registry 扫描完成,再创建 GitHub Release。Release notes 的内容取舍与风格由 [release-notes.md](release-notes.md) 拥有。
52
52
 
@@ -0,0 +1,73 @@
1
+ # Release coverage and verification internals
2
+
3
+ Read the coverage procedures only when preparing a new version. The implementation notes also support focused work on verification performance and instrumentation; they do not require an ordinary development task to run coverage.
4
+
5
+ ## Release coverage
6
+
7
+ [Focused Verification](verification-optimization-work.md) owns the bounded release coverage diagnostic contract. Keep transient run state, findings, and delivery progress out of that design reference.
8
+
9
+ The Release workflow runs `npm run coverage` against the annotated release tag before packing and staging. This includes the ordinary suite, coverage-only suites under `test/coverage/`, and mixed instrumented cases. Coverage-specific regression tests must not be run as development or review diagnostics outside new-version release preparation. During new-version release preparation, the same command may be run locally. It requires 100% lines and functions and at least 95% branches, including compiler source remapping. The graded merge additionally asserts that the plugin-source closure it claims — `index.js` and every `internal/*.js` owner — appears in the merged report, so a module no instrumented process loads fails the gate instead of silently leaving it. Generated artifacts stay outside that closure: the root `compiler-*.cjs` bundles and the `internal/*.cjs` shims are remapped onto their original `internal/` sources or verified by the bundle checks, and `scripts/migrate-session-log.mjs` is verified by its own migration suite.
10
+
11
+ Use focused coverage only during release preparation after the release coverage gate identifies a narrow coverage failure. Select every source whose threshold matters and the smallest test set that can distinguish the correction:
12
+
13
+ ```bash
14
+ npm run coverage:focus -- \
15
+ --source internal/source-position-map.js \
16
+ --test test/source-position-map.test.js \
17
+ --test test/compiler-memory-facts.test.js \
18
+ --test test/stateful-source-line-mapping.test.js
19
+ ```
20
+
21
+ Repeat `--source` and `--test` as needed. Paths must exist inside the checkout; sources must belong to the full coverage gate, and tests must be `.test.js` files under `test/`. Arguments after a standalone `--` are forwarded as Node test options. The focused runner uses the same compiler bytecode preparation, mock-dependent grouping, real Worker coverage instrumentation, source-map filtering, and 100% line/function plus 95% branch thresholds as the full runner. It includes selected but unexecuted sources as uncovered, so an empty report cannot pass. Its evidence and retained TAP diagnostics use the ignored `coverage/` directory.
22
+
23
+ Focused coverage establishes only the selected source-and-test relation. It does not establish full-suite compatibility and never replaces the full release coverage gate or the final `verify` or `check`. Ordinary development and commit preparation use selected behavioral tests without coverage. A failed full gate must be diagnosed with the smallest check that reproduces its failure before another full run. Because the full branch of `check` already invokes `verify`, running both consecutively against an unchanged tree repeats the full suite without adding evidence.
24
+
25
+ Source fingerprints use Git with temporary administrative files, an index and an object directory. Configuration includes and repository attributes preserve canonical content, and newly computed objects stay in the temporary directory. One tagged file inventory identifies tracked, missing, untracked and sparse entries without repeatedly starting Git for each category. The temporary files are written directly, avoiding repeated Git initialization and configuration processes; explicit Git command arguments preserve isolation across Windows/WSL command forwarders.
26
+
27
+ Set `DSH_PTC_TEST_CONCURRENCY` to a positive integer to override the backend process count. Use `1` for serial diagnosis or when CPU/memory contention affects timing-sensitive tests. This changes scheduling, not runtime compute budgets, test selection, or coverage thresholds. For example:
28
+
29
+ ```bash
30
+ DSH_PTC_TEST_CONCURRENCY=1 npm run verify
31
+ ```
32
+
33
+ ```powershell
34
+ $env:DSH_PTC_TEST_CONCURRENCY = '1'
35
+ npm run verify
36
+ Remove-Item Env:DSH_PTC_TEST_CONCURRENCY
37
+ ```
38
+
39
+ Coverage runs additionally set `DSH_PTC_TEST_WORKER_COVERAGE=1` and load `scripts/instrument-worker-coverage.mjs` through Node's `--import`; that test-only seam adds the coverage variable to the helper's inner-Worker launch environment so real kernel, console, and candidate worker branches are measured. Production never sets the marker and continues to project `NODE_V8_COVERAGE` out of the user Worker environment. Because some transport tests install module mocks before importing the real transport, the runner executes two backend groups into the same coverage directory: the mock-dependent files run without the preload, and the remaining files run with it. Each group writes its own `run-*-mock.tap` or `run-*-instrumented.tap` diagnostic, both managed by the same retention and cleanup lifecycle. Test arguments such as `--test-name-pattern` are placed before the selected file list so Node applies them to test selection rather than treating them as file inputs.
40
+
41
+ `npm run coverage` and `npm run coverage:focus` print their current stage and total elapsed time. Each invocation collects worker coverage in its own temporary directory under `coverage/`, removed after c8 finishes reporting, so simultaneous runs cannot erase or combine each other's evidence. The default report is printed to the terminal. A separate `coverage/run-*.tap` log retains Node's test diagnostics, including process exit codes and signals that the concise terminal reporter can omit. An explicit Node test reporter option replaces these default reporters. Source changes during verification still invalidate a `check` proof; separate coverage directories do not make concurrent source edits safe.
42
+
43
+ Windows Node 24 and 26 reproductions and stacks identify a cppgc finalizer (`node::contextify::ContextifyScript`, or `ContextifyContext` when coverage was enabled) running after the environment that owned its private realm was gone, which wrote through a dangling `node::Realm` during isolate teardown. The reproduction ended the whole DSH process when an in-host session worker was terminated; macOS runners also observed whole-file aborts under coverage, but the available evidence does not establish that those aborts came from the same Windows stack or that the same cause applies across platforms. The session kernel now runs in a plugin-owned helper process (`internal/kernel-child.js`); `IsolatedWorker` sends a cooperative shutdown and, if the helper does not leave within its bound, kills only that helper. DSH is no longer the worker-teardown target on any supported host, so a wedged kernel is contained as a helper failure rather than a host-native crash. The former file-level retry wrapper is gone, and any failing CI smoke or local exhaustive test fails its run. This boundary removes the plugin's in-host kill exposure; it neither repairs the upstream Node path nor proves the macOS abort shared the Windows cause.
44
+
45
+ Native oracle workers and external Windows command fixtures explicitly disable inherited `NODE_V8_COVERAGE`; they execute no code included by the plugin coverage gate. Subprocesses testing plugin implementations still collect coverage. PowerShell semantic-version observations share one invocation, and Windows registry fixtures read the three effective registry values with one real npm configuration query. Each retains its original inputs and assertions.
46
+
47
+ The reporting adapter filters script records before c8 merges them. It reads source-map metadata once per input file, retains maps that lead to selected original sources, and leaves unknown or malformed maps to c8. Dependency-only compiler artifacts can be excluded before remapping; mixed compiler bundles retain their original coverage records. c8 still owns merging, remapping, counters, reporting and threshold checks. This uses an isolated adapter for c8's normalization method; dependency upgrades must pass the comparison with ordinary c8, including uncovered counters and mapped sources. The raw V8 reports are not rewritten.
48
+
49
+ Runtime Workers defer parsing the compiler bundle until their first compiler operation. Ordinary cells already prepared by the host avoid that startup work. Once an uninstrumented host has initialized its compiler, it snapshots V8 compiler bytecode for subsequent session kernel Workers. Coverage runs prepare that snapshot once in a separate uninstrumented process and pass its temporary file through `DSH_PTC_COMPILER_BYTECODE`; instrumented compiler instances neither produce nor consume bytecode. The runner owns this variable and removes the file after the tests. Workers receive private bytes through their initialization data and do not inherit the temporary file setting.
50
+
51
+ A Worker uses a snapshot only when its complete compiler source matches; V8 checks bytecode compatibility and recompiles when it rejects the snapshot. Workers still initialize independent compiler realms and session state. The host retains one snapshot in memory, and each Worker discards its private copy after consumption; bytecode contains no saved program values. The bundle source, VM constructor and options are captured or isolated from source-owned mutations before execution.
52
+
53
+ Repeated Global User Binding validation reuses export descriptions and durability analysis inside the private compiler realm. Each cache keys the complete source and transform generation, retains at most 64 entries and 512 Ki characters of serialized keys, and returns fresh data to its caller. Snapshot fields, fingerprints and publication evidence still undergo validation on each request. This cache contains source-derived metadata, never executed values or module state, and is rebuilt for every compiler realm.
54
+
55
+ Cell preparation carries its successful native JavaScript parse proof into scope normalization, as module preparation already does. Decorator and resource transforms consume their feature scan's existing syntax tree through Babel's AST API. Recovered invalid decorator input retains the original parser diagnostic path. Intrinsic binding skips its source scan when the compiler recorded no bindings to replace. These changes remove repeated preparation work without changing execution budgets or coverage collection.
56
+
57
+ Nested callable reflection reuses completed ordinary function recipes inside enclosing recipes. A source-position index selects the outermost reusable descendants, and syntax inspection skips their complete AST subtrees. Each reused function already contains its generated helper dependencies; class and method definition recipes keep their separate lowering paths. If all non-native syntax is inside those substituted functions, the surrounding recipe needs no additional type-erasure pass. Enclosing type syntax and resource declarations still undergo their own lowering. Callable marker emission uses cumulative edit offsets and binary searches to retain exact source boundaries without rescanning all edits for each mapping point. Declaration analysis groups at most 64 declarations into each shared ancestry witness, so Babel assigns ownership without repeatedly walking the same ancestors or retaining a full expression graph.
58
+
59
+ Dynamic eval and Function preparation reuse source-derived compilation results within their private compiler realm. The key includes the complete source and syntax options. Every hit rechecks the original-source facts consulted by that compilation; a changed fact requires compilation again. The cache holds at most 64 entries and 2 Mi characters of serialized keys, results and source facts. Callers receive fresh metadata, and each execution still declares its variables and creates a new activation against the current environment. Cell operation plans remain with their existing compiler owner.
60
+
61
+ Optional-chain transforms allocate temporary names through the complete compilation unit's allocator. A scoped Babel adapter retains Babel's UID reservations and restores its original method when the transform completes or throws. This avoids a subsequent whole-scope rename for every generated temporary while preserving uniqueness across module regions.
62
+
63
+ Callable catalogs compress windows containing referenced source ranges. Ranges separated by at most one source block share a window, preserving compression across nearby functions; large unreferenced gaps and unused buffers are omitted. Empty catalogs retain no source buffers. Entries keep their registration order and exact UTF-16 text in the existing catalog format.
64
+
65
+ Cell preparation traverses parsed trees and edit mappings without allocating a
66
+ temporary object per unit of work. The namespace walk reads a node's own keys
67
+ once and indexes node arrays directly instead of materializing an entry pair
68
+ per property; the source-map builder validates and writes its four offsets
69
+ positionally, and replacement runs reach that builder through a direct emitter
70
+ instead of a generator and a per-run segment object. Rehomed compiler messages
71
+ write their owned data descriptor directly rather than copying a generic
72
+ descriptor first. Every one of these paths produced identical output before and
73
+ after the change; only the immediately discarded allocations are gone.
@@ -96,7 +96,7 @@ Full Changelog: https://github.com/muyuanjin/dsh-ptc-plus/compare/<上一个 tag
96
96
 
97
97
  * 适配 DSH 0.1.7 的公共扩展面:设置卡片注册到宿主的插件配置座位(侧栏 **插件 → 已安装** 的 `plugins.row.config`),星光入口的四个动作进入公共 `Menu` 的 `children` 区域
98
98
  * 不渲染 `children` 的宿主同样可用:同一套插件自有动作区由 pinned 区域承载,上一代设置座位 `settings.plugin.item` 继续生效
99
- * 兼容性由公共能力探测决定:探测只记录一次已挂载观测,支持 `children` 的宿主不会重复渲染
99
+ * 兼容性由公共能力探测决定:支持 `children` 的宿主不会重复渲染
100
100
  ````
101
101
 
102
102
  同一版的 `feat(review)`、`chore(release)` 等内部提交不进入 notes;测试夹具修复属于交付记录,不作为用户条目。
@@ -0,0 +1,56 @@
1
+ # Findings and independent review
2
+
3
+ Read this procedure before findings, independent review or review-state commands. [Verification](verification.md) selects the checks appropriate to the candidate; this procedure owns review evidence and commit authorization.
4
+
5
+ ## Findings ledger
6
+
7
+ `REVIEW_FINDINGS.md` is checkout-local and must never be staged or committed. Create it only with `npm run review:new`; [the tracked template](../.agents/templates/REVIEW_FINDINGS.md) owns its schema and `scripts/review-findings.mjs` owns its lifecycle. `REVIEW_PLAN.json` is also checkout-local and must never be staged or committed; its creation and recording procedure is below.
8
+
9
+ Keep `requiredOutcome` as the stable acceptance condition. Before implementing a captured finding, use `implementationPlan` to explain why the failure is reachable, which owners and dependents must change, and what observation would distinguish the correction from the existing failure. Update the plan before continuing when evidence changes the diagnosis or scope. Put completed observations and their results in `resolutionEvidence`, not a restatement of intended work.
10
+
11
+ The ledger validator checks structure and required evidence fields; it cannot establish that the recorded diagnosis or evidence is sound. Each disposition must remain independently verifiable from its cited sources and executed observations. Do not turn the ledger into a chronological transcript. An accepted finding's local `dispositionRef` must name one exact tracked file present in the source candidate being verified, not merely an index entry, missing file, directory, or pathspec match.
12
+
13
+ A finding becomes terminal when its root cause and dependents are corrected and relevant verification passes, or when evidence establishes `invalid` or a durable tracked owner records `accepted`. An accepted limitation remains a limitation. Set `ledgerStatus: resolved` only when every finding is terminal; this status alone does not establish implementation completeness or a clean independent review. Let `npm run check` archive a terminal ledger under checkout-local Git metadata; do not manually delete it.
14
+
15
+ Install the tracked pre-commit hook explicitly with `npm run hooks:install`. Hook installation must not replace another hook owner or occur as a package-install side effect.
16
+
17
+ ## Incremental independent review
18
+
19
+ After focused checks pass, partition independent review and freeze the recorded plan before starting reviewers in parallel. Create the ignored working plan, replace every placeholder, then record it against the commit that defines the change scope:
20
+
21
+ ```bash
22
+ npm run review:plan:new
23
+ npm run review:plan -- --base <base-commit>
24
+ ```
25
+
26
+ The plan uses `dsh-review-plan/v1`, and the ignored root `REVIEW_PLAN.json` is its only active source. All five standard obligations from the template must remain present. Each standard or change-specific obligation is assigned to a lane or excluded with a concrete reason. A lane declares semantic scope, exact file paths or directory prefixes, upstream lanes, owners, consumers, and counterexamples. `.` selects the complete checkout. Paths only determine content inputs and changed-path coverage; they do not replace the semantic declarations. A lane fingerprint covers that declaration, its assigned obligations, selected raw Git entry identities, persistent invalidation generation, and upstream fingerprints. Dependencies must form a DAG. The plan command refuses missing standard obligations, placeholders, unknown obligations, dependency cycles, a non-ancestor base, and changed paths outside every lane.
27
+
28
+ The plan command prints one `review-lane <id> <head> <fingerprint>` line per lane. Reviewers use focused diagnostics; review alone does not start another complete gate. `npm run review:status` prints one current overall `HEAD` and each lane's content fingerprint; it does not invent a per-lane capture head for an incomplete lane. A recorded clean lane also includes the `HEAD` captured for that review. Record each clean external report with the identity captured before that review:
29
+
30
+ ```bash
31
+ npm run review:lane -- \
32
+ --lane <id> \
33
+ --evidence <report-path> \
34
+ --expect-head <head> \
35
+ --expect-fingerprint <lane-fingerprint>
36
+ ```
37
+
38
+ Give a reviewer its declared semantic boundary and normal project context. The candidate is the working tree it is given: a reviewer environment that cannot run repository Git must read those working-tree files directly. Historical copies under `.git/` and generated `artifacts/` are not candidate sources. Keep reports outside the checkout or ignored. A lane declares only paths covered by the gate's source inventory; checkout-local exclusions are not candidate input or review evidence. Every path changed from the base must belong to at least one lane. Define lanes by semantic responsibility, not file count.
39
+
40
+ A coverage gap, insufficient evidence, or interrupted review ends with `VERDICT: INCOMPLETE`. Do not silently expand or reassign a lane when review exposes a missing owner, consumer, dependency, counterexample, obligation, or changed path; revise and record the plan before continuing.
41
+
42
+ A clean report's last non-empty line must be `VERDICT: NO FINDINGS`. A readable findings or incomplete report retires the named lane and every declared dependent from the recorded plan before checking whether the current candidate drifted; restoring an earlier tree therefore cannot revive evidence that the report rejected. An unreadable or missing report path is a command-input error and does not retire valid evidence. Unrelated lanes remain effective. A clean report retains the captured `HEAD` as provenance; an unrelated concurrent edit or `HEAD` advance does not prevent recording. Direct input, upstream fingerprint, scope, obligation, owner, consumer, counterexample, or dependency changes do. Put findings in `REVIEW_FINDINGS.md`, fix them, and rerun only the incomplete lanes shown by `npm run review:status`.
43
+
44
+ Review-state mutations and authorization decisions use one atomic lock under checkout-local Git metadata. These mutations and authorization decisions must use this lock; parallel script variants must not establish a separate mutation path. Plan recording, clean or negative lane recording, finalization, clearing, and pre-commit therefore have one observable order. A negative report queued behind an older clean recorder advances the reported lane's persistent invalidation `{epoch, revision}`, including while that lane is temporarily absent from the current plan, before retiring its current dependent closure. Advancement increments the revision normally and rotates to a new random epoch with revision zero at `Number.MAX_SAFE_INTEGER`, so a valid tuple never becomes unretirable. A temporarily absent lane must already have a retained tuple; unknown or mistyped lane IDs are rejected rather than creating state. Every active lane must have an explicit tuple. The tuple participates in the lane fingerprint and propagates through dependency fingerprints, so an older clean report cannot be submitted after re-addition. It survives normal `review:clear` and temporary lane removal; only a review captured after retirement can authorize the repaired fingerprint. Missing, partial, or malformed generation state blocks status and authorization. Explicit clear preserves valid generations but removes damaged generation state; plan recording then creates a new random epoch, so old reports still cannot match. The lock records a PID and unique release token and bounds acquisition, but never reclaims another owner automatically. If a command crashed, confirm that no review-state command is active, obtain the exact checkout-local path with `git rev-parse --git-path review-findings/state.lock`, remove only that directory, and retry. `review:status` remains a diagnostic snapshot and does not grant authorization. Finalization and pre-commit also re-read the active plan, candidate, proof, lane records, and evidence before they persist or return a decision, so edits made outside the review commands fail closed.
45
+
46
+ Do not mutate a recorded boundary implicitly. Every status, clean lane verdict, finalization, and commit decision compares the normalized active file with the recorded plan. Missing, malformed, or semantically changed active content blocks clean authorization; it does not block a findings or incomplete report from retiring the recorded lane closure. Whitespace and object-key formatting alone do not change plan identity. When evidence reveals a missing path or semantic dependency, edit `REVIEW_PLAN.json` and run `npm run review:plan` without another `--base`; the command reuses the recorded base. The new plan hash invalidates its aggregate verdict, but clean lane records survive when their base, complete declaration, selected Git entries, upstream fingerprints, and evidence hashes are unchanged.
47
+
48
+ When delivery/commit finalization is requested and `review:status` reports `clean`, run the candidate-appropriate check once (or reuse its still-matching proof) and bind the composite verdict to it:
49
+
50
+ ```bash
51
+ npm run check
52
+ npm run review:finalize
53
+ git diff --check HEAD --
54
+ ```
55
+
56
+ The `check` proof binds verification to the source and current `HEAD` while requiring the source tree and active ledger to remain unchanged through verification; a resolved active ledger is archived only after those checks and before the proof is published. `check` itself does not prove the semantic obligations assigned to independent lanes or compare a prospective index. The final verdict uses `dsh-review-verdict/v2`. `review:finalize` verifies the recorded plan, lane fingerprints and evidence against that proof. Pre-commit separately verifies the whole source fingerprint, `HEAD` and prospective index. A later `HEAD` change retires the proof and aggregate verdict. Source or index drift blocks the gate while it differs; restoring the exact finalized candidate preserves those records, while keeping a changed candidate requires another `check` and `review:finalize`. Only lanes whose effective inputs changed need another independent review. `npm run review:clear` abandons the recorded plan, lane records, aggregate verdict, and verification proof while leaving the working `REVIEW_PLAN.json` available for revision; persistent invalidation generations remain so pre-retirement reports cannot revive in a rebuilt plan. Clearing is not a normal retry step. The prior single-report `verdict` command and `dsh-review-verdict/v1` records are not accepted. Both documentation and full checks require the same ledger readiness and source-bound proof; independent review is enforced afterward by `review:finalize`, and prospective-index equality afterward by pre-commit. The proof records which verification scope ran; documentation evidence does not claim runtime validation. Once the proof, effective review, prospective index and `git diff --check HEAD --` agree, an explicitly authorized commit needs no additional complete-tree review. Only an invalidated lane, changed plan boundary, changed content, new counter-evidence, or invalidated proof reopens the corresponding gate.