dsh-ptc-plus 0.4.2 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +170 -76
- package/README.md +171 -77
- package/assets/dsh-ptc-plus-banner-en.webp +0 -0
- package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
- package/assets/ptc-plus-icon.svg +5 -0
- package/client.js +599 -310
- package/compiler-core.cjs +162 -160
- package/compiler-core.cjs.map +3 -3
- package/docs/README.md +4 -1
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +49 -11
- package/docs/adr/0008-define-agent-operating-contract.md +2 -2
- package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
- package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +5 -1
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +3 -1
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
- package/docs/adr/0023-global-user-bindings.md +1 -1
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +4 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +2 -2
- package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
- package/docs/adr/README.md +4 -4
- package/docs/architecture.md +8 -5
- package/docs/binding-review-placement-design.md +1 -1
- package/docs/client-ui.md +8 -4
- package/docs/durability-design.md +7 -7
- package/docs/installation.md +48 -12
- package/docs/publishing.md +4 -4
- package/docs/release-notes.md +109 -0
- package/docs/runtime-reference.md +25 -12
- package/docs/semantic-validation.md +7 -3
- package/docs/user-bindings.en.md +7 -6
- package/docs/user-bindings.md +6 -5
- package/docs/value-wire.md +1 -1
- package/docs/verification.md +43 -2
- package/index.js +39 -34
- package/internal/async-local-storage-intrinsics.js +12 -7
- package/internal/callable-source-facts.js +37 -1
- package/internal/cell-analysis.js +64 -9
- package/internal/config-spec.js +1 -1
- package/internal/cordis-tools-owner.js +81 -15
- package/internal/direct-surface-owner.js +331 -7
- package/internal/edit-transport-owner.js +80 -20
- package/internal/execution-seam-compat.js +192 -30
- package/internal/kernel-worker.js +162 -72
- package/internal/message-sources.js +14 -0
- package/internal/module-compilation.js +2 -1
- package/internal/rejected-cell-editor.js +11 -21
- package/internal/repl-memory-projection.js +10 -0
- package/internal/repl-scope-normalizer.js +72 -35
- package/internal/repl-value-observer.js +141 -45
- package/internal/runtime-config.js +62 -2
- package/internal/runtime-intrinsics.js +3 -0
- package/internal/runtime-messages.js +6 -4
- package/internal/session-cell-executor.js +24 -1
- package/internal/session-journal-recovery.js +267 -67
- package/internal/session-journal.js +466 -40
- package/internal/session-log-view.js +5 -4
- package/internal/session-runtime.js +45 -21
- package/internal/session-state.js +7 -29
- package/internal/settings-compat.js +66 -1
- package/internal/source-position-map.js +19 -0
- package/internal/user-binding-console-worker.js +23 -9
- package/internal/user-binding-draft-projection.js +3 -2
- package/internal/user-bindings-owner.js +2 -1
- package/internal/user-bindings.js +6 -1
- package/internal/validated-parse-repair.js +6 -2
- package/internal/value-wire.js +95 -30
- package/internal/worker-client.js +99 -8
- package/internal/worker-cwd-virtualization.js +10 -9
- package/internal/worker-output-capture.js +187 -0
- package/internal/worker-output-fence.js +26 -0
- package/internal/worker-realm-surfaces.js +197 -0
- package/internal/worker-repl-realm.js +10 -4
- package/package.json +42 -4
- package/src/client-activity.js +4 -1
- package/src/client-authoring-view.js +121 -62
- package/src/client-console.js +4 -2
- package/src/client-copy.js +4 -2
- package/src/client-feature-gates.js +7 -9
- package/src/client-host-compat.js +104 -27
- package/src/client-repl-view.js +3 -1
- package/src/client-styles.js +12 -1
- package/src/client-tool-view.js +3 -1
- package/src/client-transport.js +2 -2
- package/src/client-workbench.js +10 -7
- package/src/client.js +56 -17
package/docs/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Getting Started
|
|
4
4
|
|
|
5
|
-
- [Installation](installation.md): npm, Git, source, tarball, development snapshot, and Desktop installation.
|
|
5
|
+
- [Installation](installation.md): npm, Git, source, tarball, development snapshot, and Desktop installation, plus upgrades, troubleshooting, and Session format migration.
|
|
6
6
|
- [Global binding guide](user-bindings.en.md) ([中文](user-bindings.md)): author, review, save, configure, and test reusable helpers.
|
|
7
7
|
- [Runtime Reference](runtime-reference.md): cell behavior, capability discovery, configuration, diagnostics, and limits.
|
|
8
8
|
- [Evaluation](evaluation.md): paired ordinary-task protocol, metrics, configuration, and limitations.
|
|
@@ -17,12 +17,15 @@
|
|
|
17
17
|
- [Global User Bindings](adr/0023-global-user-bindings.md): persistent helper ownership, model projection, runtime activation, recovery, and Agent-assisted authoring.
|
|
18
18
|
- [Binding Review Placement](binding-review-placement-design.md): the implemented full draft panel above the current composer, using the published input dock and one review controller.
|
|
19
19
|
- [Logical Binding Identities](adr/0025-use-versioned-logical-binding-identities.md): stateful declarations, scope, candidate publication and language generations.
|
|
20
|
+
- [Stateful Binding Updates](stateful-binding-updates-proposal.md): target stateful-computation semantics and their acceptance boundaries.
|
|
20
21
|
- [Architecture Decisions](adr/): stable design constraints and their consequences.
|
|
21
22
|
|
|
22
23
|
## Maintenance
|
|
23
24
|
|
|
24
25
|
- [Deterministic Verification](verification.md): complete checks, backend test concurrency, coverage, and focused diagnostics.
|
|
26
|
+
- [Incremental Review Verdict](adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md): predeclared parallel lanes, dependency-scoped invalidation, and the composite commit verdict.
|
|
25
27
|
- [Focused Verification](verification-optimization-work.md): bounded coverage diagnostics and their relationship to the final verification gate.
|
|
26
28
|
- [Semantic Validation](semantic-validation.md): pinned Test262 cases, dialect contracts, native differential matrices and their limits.
|
|
27
29
|
- [Publishing](publishing.md): release checks, package contents, permissions, and platform validation.
|
|
30
|
+
- [GitHub Release Notes](release-notes.md): user-perspective priority order, required sections, bilingual style, and a worked example for release notes.
|
|
28
31
|
- [Client UI](client-ui.md): current UI boundary and reevaluation criteria.
|
|
@@ -23,9 +23,10 @@ edit_run_code({
|
|
|
23
23
|
|
|
24
24
|
PTC mode requests using the code-only direct-tool projection expose `[run_code, edit_run_code]` in
|
|
25
25
|
that order. The first conclusive prompt assembly creates one per-agent composition owner before any
|
|
26
|
-
plugin-owned presentation effect changes the nearest DSH scope. A non-empty `tools:
|
|
27
|
-
section proves `
|
|
28
|
-
|
|
26
|
+
plugin-owned presentation effect changes the nearest DSH scope. A non-empty `tools:ptc-only`
|
|
27
|
+
section proves `ptc`, an empty section proves `both`, and the preceding generation's
|
|
28
|
+
`tools:code-only` alias proves the same composition; the current section wins when both appear, and
|
|
29
|
+
only a missing owner signal permits a tool-shape inference. For a code composition, the same owner
|
|
29
30
|
registers `edit_run_code` through `agent.ctx.tools.register()` and uses the same scope's
|
|
30
31
|
`tools.presentAs('both')` to admit both direct calls. It retains both exact disposers and releases
|
|
31
32
|
registration and presentation together with the owning session, agent, or plugin. Native-mode and unrelated agent
|
|
@@ -67,8 +68,10 @@ session-log projection captures the eligible target at the edit call event and a
|
|
|
67
68
|
source only when its target sequence matches that snapshot and its journal is valid and non-noop,
|
|
68
69
|
so live and recovered eligibility derive from the same persisted relation.
|
|
69
70
|
|
|
70
|
-
The
|
|
71
|
-
`expected_target_call_seq`
|
|
71
|
+
The public schema is one closed object with optional `edits`, `regex_edits`, and
|
|
72
|
+
`expected_target_call_seq` properties, avoiding duplicated object alternatives in the provider
|
|
73
|
+
prompt. Runtime validation still requires exactly one of `edits` or `regex_edits`, plus an optional
|
|
74
|
+
non-negative `expected_target_call_seq` precondition. The precondition must equal the call sequence of the target
|
|
72
75
|
captured for the persisted edit event; a mismatch returns an unedited result before derived
|
|
73
76
|
dispatch. Ordinary model-authored edits omit it and retain latest-target selection. Exact edits
|
|
74
77
|
contain at most 16 items; each
|
|
@@ -94,21 +97,53 @@ tool/result: { edited: true, value?, error?, logs }
|
|
|
94
97
|
The complete derived source, its journal, and its target call sequence are stored only in private tool-result metadata, including
|
|
95
98
|
when the derived cell fails after entering the runtime. Cold
|
|
96
99
|
recovery folds that explicitly marked derived run into the durable REPL history. The source is not
|
|
97
|
-
copied into the model-visible edit result
|
|
100
|
+
copied into the model-visible edit result. Valid assistant stream chunks for the two declared
|
|
98
101
|
transports pass through unchanged.
|
|
99
102
|
Consequently the UI and later model requests do not attribute a generated `run_code` call to the
|
|
100
103
|
model.
|
|
101
104
|
|
|
105
|
+
The stream owner handles one bounded provider protocol failure before DSH assembles the assistant
|
|
106
|
+
message. It buffers tool-call material until the terminal event. If the response reports the exact
|
|
107
|
+
invalid-tool-JSON `MALFORMED_RESPONSE` as a terminal chunk or stream exception, it changes that
|
|
108
|
+
terminal reason to `tool-calls`.
|
|
109
|
+
DSH's existing Agent Loop
|
|
110
|
+
then preserves an unparseable argument as a string and routes it through ordinary tool validation,
|
|
111
|
+
execution, and result recording, after which the model receives another step. A malformed tool argument therefore
|
|
112
|
+
cannot become a turn-ending provider failure merely because this adapter parses it earlier than the
|
|
113
|
+
Agent Loop.
|
|
114
|
+
|
|
115
|
+
The stream owner preserves calls only when the buffered body consists entirely of
|
|
116
|
+
tool-call-specific framing plus at most one `usage` event. When that trusted body contains exactly
|
|
117
|
+
one complete, internally consistent declared `run_code` or `edit_run_code` block, the stream owner
|
|
118
|
+
first considers one correction: delete exactly one final `}`. The block index, call ID, name,
|
|
119
|
+
concatenated deltas, and final arguments must agree, and the candidate must parse as an object
|
|
120
|
+
accepted by that request's live direct-tool schema. A successful correction changes the final delta
|
|
121
|
+
and final block arguments before the same `tool-calls` settlement. Without that proof, trusted
|
|
122
|
+
internally consistent complete blocks retain their original identity and argument bytes for the
|
|
123
|
+
ordinary tool-error path. The owner re-emits those calls with canonical
|
|
124
|
+
`block-start`, full-argument delta, and `block-end` framing so provider variants tolerated by the
|
|
125
|
+
assembler also satisfy DSH's stream invariant. A final `block-end` is canonical even when the
|
|
126
|
+
provider emitted no deltas; when deltas exist, their supplied identity fields and accumulated
|
|
127
|
+
arguments must agree with it. An already visible open text or reasoning block is closed from its
|
|
128
|
+
accumulated content before the synthetic call. If any tool block is incomplete or inconsistent, or no tool block was
|
|
129
|
+
emitted, more than one usage event appears, or any other event occurs in the buffered body, the owner
|
|
130
|
+
removes unsafe block and unknown events, retains at most the first protocol-valid `usage`, and emits
|
|
131
|
+
one deterministic `run_code` call with an argument string that cannot parse as a JSON object. That
|
|
132
|
+
call can only fail DSH's ordinary schema
|
|
133
|
+
validation, so no untrusted partial call executes and the model still receives another step. Valid streams and every
|
|
134
|
+
other provider failure pass through unchanged. The rule does not insert missing delimiters, search
|
|
135
|
+
arbitrary edits, reinterpret native calls, or retry effects.
|
|
136
|
+
|
|
102
137
|
No edit-specific runtime context is emitted. The truthful call/result pair already carries the
|
|
103
138
|
operation and outcome; changing an aggregate runtime-context snapshot merely to restate that fact
|
|
104
139
|
would repeat unrelated policy context. Rewrite feedback and unrelated recovery tips retain their
|
|
105
140
|
own independently justified lifecycles.
|
|
106
141
|
|
|
107
142
|
A live `PTC-C001` at the exact source EOF may carry a validated one-call repair. The analyzer tries
|
|
108
|
-
only the
|
|
109
|
-
bindings, redeclaration mode, rewrite policy, and import state as the
|
|
110
|
-
candidate must complete preparation without a binding
|
|
111
|
-
must be able to express it from a bounded unique source suffix. The rejected call must also have a
|
|
143
|
+
only the 12 suffixes of one or two closing tokens drawn from `}`, `)`, and `]` against the same
|
|
144
|
+
binding catalog, reserved bindings, redeclaration mode, rewrite policy, and import state as the
|
|
145
|
+
rejected cell. Exactly one candidate across both lengths must complete preparation without a binding
|
|
146
|
+
collision, and the existing exact editor must be able to express it from a bounded unique source suffix. The rejected call must also have a
|
|
112
147
|
persistent event sequence. The diagnostic then renders those already-validated
|
|
113
148
|
`edit_run_code({ edits: [...], expected_target_call_seq })` arguments on one help line. At dispatch,
|
|
114
149
|
the precondition binds the proof to that rejected cell even if another matching source has become
|
|
@@ -139,7 +174,10 @@ claim that the earlier execution was undone or idempotent.
|
|
|
139
174
|
out-of-surface call are different protocol facts. Rewriting a real `edit_run_code` destroys a valid
|
|
140
175
|
identity; normalizing a live-schema-proven native miscall to the declared `run_code` transport gives
|
|
141
176
|
an otherwise invalid call its executable representation. Native-call canonicalization therefore
|
|
142
|
-
remains available
|
|
177
|
+
remains available. The bounded malformed-input correction likewise retains a declared call's identity.
|
|
178
|
+
Fallback settlement preserves arguments for trusted complete internally consistent blocks. Unsafe,
|
|
179
|
+
partial, or mixed buffered material is replaced by a validation-rejected `run_code` call only after
|
|
180
|
+
the provider itself reports the exact terminal protocol failure.
|
|
143
181
|
|
|
144
182
|
## Consequences
|
|
145
183
|
|
|
@@ -6,11 +6,11 @@ PTC Plus needs a tracked instruction surface for product boundaries, source owne
|
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
|
-
`AGENTS.md` contains only obligations whose subject is PTC Plus: DSH authority, runtime and journal invariants, public source ownership,
|
|
9
|
+
`AGENTS.md` contains only obligations whose subject is PTC Plus: DSH authority, runtime and journal invariants, public source ownership, checkout-local review state, deterministic verification, documentation parity, generated-material exclusions, and delivery safety. It links the canonical product and architecture documents rather than duplicating their detailed behavior.
|
|
10
10
|
|
|
11
11
|
Reusable maintenance methods remain outside tracked project sources. Local editor state and branch topology also remain checkout-owned. They may guide an individual maintainer, but project code, tests, hooks, and acceptance do not require their names, installation, or presence.
|
|
12
12
|
|
|
13
|
-
The tracked ledger
|
|
13
|
+
The tracked findings-ledger and review-plan templates and their lifecycle script remain because they enforce repository-specific commit invariants: unresolved findings cannot be committed, changed paths need declared semantic coverage, lane evidence follows dependency-scoped invalidation, and a verified source tree must match the prospective Git tree. The tracked hook is limited to those invariants and is installed explicitly.
|
|
14
14
|
|
|
15
15
|
## Alternatives considered
|
|
16
16
|
|
|
@@ -7,6 +7,13 @@ The persistent REPL contract must stay short enough for every request, while som
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
9
|
PTC-owned dynamic information uses independently sourced, accepted DSH messages.
|
|
10
|
+
All newly emitted PTC messages, including authoring instructions and binding-action
|
|
11
|
+
receipts, use `source.kind: 'plugin:ptc-plus'`, the producer identity assigned by
|
|
12
|
+
DSH's official source migration. They never emit the retired `kind: 'plugin'`
|
|
13
|
+
wrapper. Readers retain that historical wrapper and recognize current Host
|
|
14
|
+
`runtime-context` sources as well as historical system-prompt sources. Source
|
|
15
|
+
admission is tested through the official persistence codec; an in-memory Session
|
|
16
|
+
alone does not establish that a message can be saved or resumed.
|
|
10
17
|
Unproved rewrite completion and Cordis recovery form a bounded `ptc-plus`
|
|
11
18
|
`snapshot` with named sections. Configured Global User Binding documentation uses
|
|
12
19
|
DSH's existing `catalog` form, independently of transient recovery state. A recovery tip is a `ptc-plus` `notice` whose
|
|
@@ -6,11 +6,11 @@ An ignored root `REVIEW_FINDINGS.md` prevents unresolved review findings from be
|
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
|
-
`.agents/templates/REVIEW_FINDINGS.md` is the tracked schema owner for local review ledgers. Schema `dsh-review-findings/v3` separates each finding's stable required outcome, current implementation plan, accumulated resolution evidence, and optional accepted-disposition owner. A finding can be captured before diagnosis produces a plan; once a concrete correction is selected, the plan is recorded before implementation and kept synchronized when evidence changes the diagnosis, ownership, affected artifacts, or verification path. `resolutionEvidence` records completed facts rather than a chronological work transcript. A finding marked `resolved` retains its implemented plan. A finding marked `accepted` names a tracked document or HTTPS issue in `dispositionRef`; the local ledger cannot be the only copy of an intentionally retained limitation.
|
|
9
|
+
`.agents/templates/REVIEW_FINDINGS.md` is the tracked schema owner for local review ledgers. Schema `dsh-review-findings/v3` separates each finding's stable required outcome, current implementation plan, accumulated resolution evidence, and optional accepted-disposition owner. A finding can be captured before diagnosis produces a plan; once a concrete correction is selected, the plan is recorded before implementation and kept synchronized when evidence changes the diagnosis, ownership, affected artifacts, or verification path. `resolutionEvidence` records completed facts rather than a chronological work transcript. A finding marked `resolved` retains its implemented plan. A finding marked `accepted` names a tracked document or HTTPS issue in `dispositionRef`; a local reference must be one exact tracked file that remains present in the source candidate, not a directory, pathspec match, or index entry deleted from the checkout. The local ledger cannot be the only copy of an intentionally retained limitation. The separate `.agents/templates/REVIEW_PLAN.json` owns the independent-review partition described by ADR 0026; a review plan routes verification work and invalidation, while the findings ledger owns discovered defects and their resolution.
|
|
10
10
|
|
|
11
11
|
Review output and ledger mutation follow task authority. A read-only review reports records in the ledger's semantic fields without writing checkout state. Every implementation preserves an active ledger, but an ordinary change with no finding does not create one. `npm run review:new` creates the ignored root ledger only when a task authorizes capture or resolution of at least one finding; implementation imports those findings before editing their fixes. Archives move under Git's local `review-findings/archive` metadata path, so they cannot enter a commit and remain associated with the checkout.
|
|
12
12
|
|
|
13
|
-
Ledger validation, readiness, deterministic verification, archive, and commit proof are distinct states with one implementation. `npm run review:validate` checks schema and tracked-file safety while accepting a valid open ledger. `npm run review:gate` is read-only: it blocks an open ledger, validates durable owners for accepted findings, and never archives. `npm run verify` performs schema validation before syntax and coverage checks, so open-ledger work can collect evidence. `npm run check` applies the readiness gate first, then materializes the current tracked and non-ignored checkout through Git's clean and index semantics in a temporary Git administrative directory. Git selects that directory's default index through `--git-dir` and reads the target checkout through `--work-tree`; it never receives an alternate-index environment path that could fall back to the real repository index. The temporary object database reads the repository's objects through a relative alternates entry and stores new fingerprint objects locally. The resulting tree object ID includes canonical blobs, symlink identity, and file modes while remaining independent of staged content. Sparse checkouts retain skip-worktree paths from the `HEAD` baseline and apply clean conversion only to materialized paths, so an absent out-of-cone file is neither lost nor mistaken for a deletion. Every path discovered by Git is reapplied through NUL-delimited literal input. The command separately snapshots the ignored ledger, runs `verify`, rejects changed source or ledger state, and refreshes the proof before archiving a resolved ledger. Repository scripts that launch npm as a child use one command resolver: an invoking npm process supplies its CLI path and Node executable, while direct script invocation falls back to the platform npm executable. A successful later check without an active ledger also refreshes an older proof. The pre-commit hook rejects open and unverified resolved ledgers, requires a verification proof for the current `HEAD`, requires equal source and index tree fingerprints, and requires
|
|
13
|
+
Ledger validation, readiness, deterministic verification, archive, and commit proof are distinct states with one implementation. `npm run review:validate` checks schema and tracked-file safety while accepting a valid open ledger. `npm run review:gate` is read-only: it blocks an open ledger, validates durable owners for accepted findings, and never archives. `npm run verify` performs schema validation before syntax and coverage checks, so open-ledger work can collect evidence. `npm run check` applies the readiness gate first, then materializes the current tracked and non-ignored checkout through Git's clean and index semantics in a temporary Git administrative directory. Git selects that directory's default index through `--git-dir` and reads the target checkout through `--work-tree`; it never receives an alternate-index environment path that could fall back to the real repository index. The temporary object database reads the repository's objects through a relative alternates entry and stores new fingerprint objects locally. The resulting tree object ID includes canonical blobs, symlink identity, and file modes while remaining independent of staged content. Sparse checkouts retain skip-worktree paths from the `HEAD` baseline and apply clean conversion only to materialized paths, so an absent out-of-cone file is neither lost nor mistaken for a deletion. Every path discovered by Git is reapplied through NUL-delimited literal input. The command separately snapshots the ignored ledger, runs `verify`, rejects changed source or ledger state, and refreshes the proof before archiving a resolved ledger. Repository scripts that launch npm as a child use one command resolver: an invoking npm process supplies its CLI path and Node executable, while direct script invocation falls back to the platform npm executable. A successful later check without an active ledger also refreshes an older proof. The pre-commit hook rejects open and unverified resolved ledgers, requires a verification proof for the current `HEAD`, requires equal source and index tree fingerprints, and requires the composite independent-review plan, lane verdicts, and final verdict defined by ADR 0026. Staging the complete verified tree permits repeated commit attempts; partial staging, additional staged content, mode-only changes, later checkout changes, uncovered paths, or invalidated lane dependencies require reconciliation before commit.
|
|
14
14
|
|
|
15
15
|
Hook installation is explicit. `npm run hooks:install` selects the tracked hook path only when the effective `core.hooksPath` is unset or already `.githooks`. Before the first switch from Git's default hooks directory, installation rejects any non-sample hook file there; it also rejects an incompatible configured path instead of disabling another hook owner. Dependency installation has no Git-configuration side effect.
|
|
16
16
|
|
|
@@ -40,4 +40,4 @@ Hook installation is explicit. `npm run hooks:install` selects the tracked hook
|
|
|
40
40
|
|
|
41
41
|
## Consequences
|
|
42
42
|
|
|
43
|
-
Review findings have an explicit `reported -> authorized capture -> planned -> implemented and verified -> proof and archive -> matching commit -> proof retirement` lifecycle while retaining `open` and `resolved` as file-level states. An open ledger uses `verify` for deterministic evidence collection and fails `check` before its full gate runs; it also blocks commits. A resolved ledger remains active until verification succeeds against an unchanged source fingerprint, and commit readiness additionally requires the prospective index to match that fingerprint.
|
|
43
|
+
Review findings have an explicit `reported -> authorized capture -> planned -> implemented and verified -> proof and archive -> matching commit -> proof retirement` lifecycle while retaining `open` and `resolved` as file-level states. An open ledger uses `verify` for deterministic evidence collection and fails `check` before its full gate runs; it also blocks commits. A resolved ledger remains active until verification succeeds against an unchanged source fingerprint, and commit readiness additionally requires the prospective index to match that fingerprint. Independent review lanes have their own `plan -> parallel review -> dependency-scoped retry -> deterministic proof -> composite verdict` lifecycle and do not replace finding disposition. Both local records stay outside source history; accepted limitations and durable architecture remain in tracked owners. Hook installation is an explicit checkout setup decision rather than a dependency-install side effect.
|
|
@@ -10,6 +10,10 @@ 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. Ordinary `verify` and `check` runs make no registry request and fail quickly when the installed root graph differs from the root lock.
|
|
14
|
+
|
|
15
|
+
The scheduled baseline refresh queries the official registry. When either channel moves, it updates both 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 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. No compatibility run independently selects tags for DSH service packages, because their dist-tags need not move as one cohort.
|
|
16
|
+
|
|
13
17
|
Preceding public contracts remain supported where capability detection is
|
|
14
18
|
unambiguous. Tools presentation is selected by the installed public schema;
|
|
15
19
|
Client contributions depend on their slots and supplied hooks rather than unused
|
|
@@ -69,4 +73,4 @@ capability, storage and observation rules independently of transport.
|
|
|
69
73
|
|
|
70
74
|
Feature completion requires evidence from the actual packaged plugin running on the selected unmodified Host, including the affected user flow. Component fixtures and public-interface unit tests validate narrower properties; they do not prove that a required renderer exists or is loaded in that distribution. A clean code review and passing deterministic checks are separate from product acceptance. Both must cover the final change before a feature is described as delivered; commit and publish authorization remain separate user decisions.
|
|
71
75
|
|
|
72
|
-
Each upstream DSH release becomes the immediate compatibility target and must pass the public-surface, packaging, and model-backed checks appropriate to the change. Users are not blocked by stale version metadata. Historical reports remain attributable through generated runtime metadata or source comments, while a passing older run never substitutes for validation against the latest release.
|
|
76
|
+
Each upstream DSH release becomes the immediate compatibility target and must pass the public-surface, packaging, and model-backed checks appropriate to the change. The automated pull request makes an upstream tag movement an explicit source candidate; the lockfile and CI result keep its proof reproducible after the registry moves again. Users are not blocked by stale version metadata. Historical reports remain attributable through generated runtime metadata or source comments, while a passing older run never substitutes for validation against the latest release.
|
|
@@ -8,17 +8,17 @@ Accepted
|
|
|
8
8
|
|
|
9
9
|
## Context
|
|
10
10
|
|
|
11
|
-
PTC Plus 0.1.0 deliberately had no Client UI. The runtime surface was the DSH PTC mode `run_code`/`edit_run_code` transport, and adding a settings bundle was judged not to improve the core REPL path. The plugin also lacked a user-facing way to disable its runtime without removing the Cordis entry, and enabling/disabling state was invisible outside the session log. PTC Plus requires a plugin settings UI containing every Host Config field, a kill switch, and an explicit enabled marker. DSH's public settings service registers a namespace
|
|
11
|
+
PTC Plus 0.1.0 deliberately had no Client UI. The runtime surface was the DSH PTC mode `run_code`/`edit_run_code` transport, and adding a settings bundle was judged not to improve the core REPL path. The plugin also lacked a user-facing way to disable its runtime without removing the Cordis entry, and enabling/disabling state was invisible outside the session log. PTC Plus requires a plugin settings UI containing every Host Config field, a kill switch, and an explicit enabled marker. DSH's public settings service registers a namespace; the browser half contributes a card through the generation's settings seat, and the client reads whichever public settings transport the installed Host exposes (`configForms` or `settingsScope`).
|
|
12
12
|
|
|
13
13
|
## Decision
|
|
14
14
|
|
|
15
15
|
PTC Plus registers one DSH settings namespace `ptc-plus` with the same field list, defaults and validation as the Host Config schema. The field definitions live once in `internal/config-spec.js`; `index.js` builds the Cordis Config schema from it, and the esbuild client bundle imports the same module so the UI does not copy defaults or validation.
|
|
16
16
|
|
|
17
|
-
The settings card
|
|
17
|
+
The settings card belongs to plugin configuration. Current DSH renders a bundle's own configuration on the sidebar Plugins → Installed page through `plugins.row.config` (keyed, root) as `<bundle package name>#<row id>` and reserves `plugins.item` for the host-plane pages DSH itself ships. Preceding Hosts use `settings.plugin.item` (keyed, root) in the Settings panel, keyed by the served namespace. `src/client-host-compat.js` publishes to these plugin configuration seats through `ctx.slots.inject`, which waits until the owning page declares its slot. General settings may coexist with plugin configuration and is not a seat for this card. The composer shortcut opens an application-modal rendering of the same complete form, so direct access does not depend on a host page's component-local navigation state; its hover hint names the observed native plugin configuration seat. The package's top-level `icon` field points to a packaged SVG; DSH owns loading and displaying it on the installed bundle and row pages.
|
|
18
18
|
|
|
19
19
|
The settings card places the plugin switch first, then groups controls by purpose: tool call tolerance, REPL syntax, state and recovery, tool extensions, interface display, and resource limits. Recovery tips and their thresholds stay together, and global binding management appears directly below its enable switch. `CONFIG_GROUPS` owns this presentation order independently of Host schema field order and defaults. `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.
|
|
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 newest settings generation exposes 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 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
|
Every settings-card and PTC Plus tool-row string is registered into the DSH client locale namespace `settings.ptcPlus` and follows the active DSH client locale. Field copy exists in both locales from the single `internal/config-spec.js` source (`label`/`labelEn`, `description`/`descriptionEn`); display chrome copy is owned by the Client half. The stable REPL guidance remains plugin-owned protocol text without UI branding. The transport names remain `run_code`/`edit_run_code`; DSH owns their identity.
|
|
24
24
|
|
|
@@ -14,7 +14,7 @@ Tool registration must finish before the prompt assembly returned to the agent;
|
|
|
14
14
|
|
|
15
15
|
## Decision
|
|
16
16
|
|
|
17
|
-
Add `cordisToolsEnabled: boolean`, default `false`, as a live PTC Plus setting. When enabled, PTC Plus mounts the official `@deepseek-ai/dsh-tool-cordis` plugin and a maintained `@deepseek-ai/dsh-skill-filesystem` provider in each agent scope that exposes every surface the mount publishes through: `run_code`, the `skill` tool, and the public `agentPresets` and `skills` services; disabling it disposes both fibers immediately. The provider resolves the shipped `cordis` preset through the public `agentPresets` service and reads its sibling `skills` root without including default roots. At the public `skills.registerProvider` seam, PTC Plus transparently filters discovery and loading to exactly `cordis-plugin-development`; the maintained filesystem provider still owns parsing, resource bases,
|
|
17
|
+
Add `cordisToolsEnabled: boolean`, default `false`, as a live PTC Plus setting. When enabled, PTC Plus mounts the official `@deepseek-ai/dsh-tool-cordis` plugin and a maintained `@deepseek-ai/dsh-skill-filesystem` provider in each agent scope that exposes every surface the mount publishes through: `run_code`, the `skill` tool, and the public `agentPresets` and `skills` services; disabling it disposes both fibers immediately. The provider resolves the shipped `cordis` preset through the public `agentPresets` service and reads its sibling `skills` root as an immutable bundled Host resource without including default roots or watching the packaged directory. At the public `skills.registerProvider` seam, PTC Plus transparently filters discovery and loading to exactly `cordis-plugin-development`; the maintained filesystem provider still owns parsing, resource bases, incomplete observations, and body loading. This prevents unrelated or obsolete sibling Skills from silently enlarging the PTC surface without copying the companion content or switching the current preset. A scope that omits one of those surfaces is not an error: the owner keeps the agent pending, publishes nothing there, and retries on the DSH tools-change signal or the next prompt assembly, because a later registration or provided service can supply the missing member ([ADR 0029](0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md)).
|
|
18
18
|
|
|
19
19
|
The Skill provider and official Cordis child fiber form one reversible mount. Both must settle, and the scoped `skills` service must prove that `cordis-plugin-development` resolves from the added provider as model-invocable and loadable, before the first prompt assembly is returned. A prepended public `system-prompt/assemble` waterfall listener is the final race barrier: if collection began before the mount settled, it waits for readiness, discards that stale assembly, and invokes public assembly again so DSH recollects the official providers. It does not synthesize or mutate Cordis schemas or guidance. The Cordis fiber's resolved `inject` declaration is the authoritative required-service list, and its live registrations are the authoritative tool names, schemas, and guidance. A scope whose exposed preset, Skill service/tool, declared service, publication, or child fiber contradicts the DSH contract is a configuration error and rolls back every contribution; an absent surface only defers the mount. An unusable scope reached through the host's own calls — `agent/created` and the prepended waterfall — withdraws and reports one warning instead of failing the host operation that created the scope ([ADR 0029](0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md)).
|
|
20
20
|
|
|
@@ -24,6 +24,8 @@ Cordis tools remain native program bindings under `tools.*`. The PTC code-only d
|
|
|
24
24
|
|
|
25
25
|
Cordis definitions and Runs are process-local, while PTC journals replay every settled program binding as a recorded value without redispatch. On the first prompt for an agent or a new Cordis enable generation, PTC Plus derives whether normalized journals contain a Cordis transcript. If they do, it emits the fixed `tools:ptc-plus-cordis-recovery` runtime context: recorded values remain journal data, but the model must perform a live read-only Cordis Inspect before relying on prior IDs, state, approvals, or capability observations. The context remains until a newly settled successful `cordis_inspect*` call appears in the session log. It neither asserts that live state was lost nor reruns a mutating call.
|
|
26
26
|
|
|
27
|
+
Companion Skill resolution is capability-based. A generation that publishes an absolute composition path for the shipped `cordis` preset uses its sibling `skills` root. For a pathless generation, PTC Plus asks the Host's public `pluginPackages.packageOf` service for the active installation's `@deepseek-ai/dsh-agent-preset` or `@deepseek-ai/dsh-agent-presets` resource, then selects that generation's known Skill layout. Older generations that do not publish `pluginPackages` may resolve only the historical plural package from the Host's `ctx.baseUrl`; this compatibility path is disabled whenever the service exists, including when it returns no package. It never uses plugin-anchored ambient Node lookup, because a profile or Desktop installation may contain a stale package from another Host generation. PTC Plus accepts a root only when it contains the exact `cordis-plugin-development/SKILL.md`; it does not infer support from a package name or directory alone. An unusable preset (`broken`) is reported as unavailable before path or package resolution, while an invalid published path remains a host contradiction rather than falling through to a different generation.
|
|
28
|
+
|
|
27
29
|
## Alternatives Considered
|
|
28
30
|
|
|
29
31
|
1. Add the Cordis row to the PTC preset. Rejected: PTC Plus is installed as a host plugin and does not own or fork DSH's shipped preset files; a plugin setting keeps the optional mount within the plugin's ownership boundary.
|
|
@@ -28,12 +28,23 @@ artifact rewrite API when one exists. Until then, PTC Plus must not rewrite
|
|
|
28
28
|
files obtained from private storage paths or race the persistence provider's
|
|
29
29
|
append/flush queue. Legacy `ptc-plus/recovery-boundary` artifacts therefore
|
|
30
30
|
remain an explicit, startup-before-restore migration concern rather than a
|
|
31
|
-
runtime event handler concern.
|
|
31
|
+
runtime event handler concern. The dedicated retired-event converter accepts
|
|
32
|
+
only a Session format 0 artifact with a contiguous zero-based source identity graph, removes the retired events
|
|
33
|
+
and rewrites every supported Host and PTC sequence relation through one closed
|
|
34
|
+
old-to-new map. Before writing, it validates current-surface replacement and
|
|
35
|
+
compaction ranges, provenance, command and title sources, and complete
|
|
36
|
+
recovery-boundary application; invalid or unknown relations fail closed. If a
|
|
37
|
+
header records a seeded session, the converter also maps its exact inherited-
|
|
38
|
+
event cut across removed boundary events so child-owned events cannot become
|
|
39
|
+
inherited.
|
|
32
40
|
|
|
33
41
|
Host format upgrades are also explicit pre-restore work. The migration CLI may
|
|
34
42
|
resolve the selected Host's public Session format catalog and use its strict
|
|
35
|
-
conversion and current validation.
|
|
36
|
-
|
|
43
|
+
conversion and current validation. When the selected catalog requires
|
|
44
|
+
parent-specific child evidence, the caller supplies the complete direct-child
|
|
45
|
+
facts or explicitly declares that the artifact has no children; the CLI does
|
|
46
|
+
not infer an empty child set. PTC result metadata remains opaque to that catalog.
|
|
47
|
+
The CLI therefore proves an ordered one-to-one relation between the
|
|
37
48
|
unchanged tool records, remaps only PTC-owned sequence references, and validates
|
|
38
49
|
the resulting timeline. Original call arguments and recorded effects are never
|
|
39
50
|
rewritten or executed. Ambiguous records, invalid PTC evidence and mixed retired
|
|
@@ -6,7 +6,7 @@ Repeated project helpers are useful across sessions, but ordinary REPL bindings
|
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
|
-
Global User Bindings is
|
|
9
|
+
Global User Bindings is a PTC Plus capability controlled by `userBindingsEnabled`, which defaults to `true` so its management and authoring entry points are available on installation. An explicit `false` remains authoritative, including across upgrades; omission uses the current default. This feature switch does not change any saved entry's enabled state, create helpers, or save Agent drafts automatically. Disabled mode does not read storage, inject values or new declarations, register management RPC or commands, or render management UI. The next permitted accepted step can withdraw a previously delivered declaration through the PTC binding catalog contract in [ADR 0010](0010-session-log-derived-recovery-tips.md). Enabling the capability does not change DSH authority, approval, scheduling, cancellation, sandbox, or the code-only direct-tool projection.
|
|
10
10
|
|
|
11
11
|
Each entry is a TypeScript module with named value exports, a stable ID, display/call name, `namespace` or `top-level` scope, selected symbols, purpose, enabled state, and optional `modelContext`. Omitted symbol selection derives every named value export; an explicit selection limits the exposed API. One strict normalizer derives body-free declarations, binding kinds and durability from source, fingerprints the complete stored entry, and rejects any supplied derivative that disagrees. Activated entries are ordinary writable REPL bindings; a model redeclaration follows the configured binding policy and shadows the default only for that session.
|
|
12
12
|
|
|
@@ -1,21 +1,37 @@
|
|
|
1
|
-
# Persist
|
|
1
|
+
# Persist incremental review lanes against the verified candidate
|
|
2
2
|
|
|
3
3
|
## Problem
|
|
4
4
|
|
|
5
|
-
A complete-tree independent review
|
|
5
|
+
A single complete-tree independent review bound a clean conclusion to one tree, but every correction invalidated the whole conclusion. Earlier parallel reviews remained diagnostic transcripts even when a fix could not affect their owners, inputs, assumptions, or consumers. This forced repeated complete review, discouraged early parallelism, and allowed review boundaries to drift during execution without a machine-visible plan. Retaining every earlier conclusion without dependency information would be unsound for the opposite reason: a change to a shared owner can invalidate consumers whose own files did not change.
|
|
6
6
|
|
|
7
7
|
## Decision
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Independent review starts from a checkout-local `REVIEW_PLAN.json`, created from `.agents/templates/REVIEW_PLAN.json` and recorded under Git metadata before reviewers run. This root file is the sole active plan source. Schema `dsh-review-plan/v1` declares obligations and semantic lanes. The five standard obligation IDs remain mandatory; a plan may add change-specific obligations but cannot replace the standard review surface. Each lane has a stable ID, scope, exact file or directory-prefix inputs, upstream lane dependencies, assigned obligations, owners, consumers, and discriminating counterexamples. Obligations are either covered by at least one lane or explicitly excluded with a non-applicability reason. Every path changed between the plan base and the current source tree must match at least one lane; the implementation never silently expands a lane to absorb an unplanned path.
|
|
10
|
+
|
|
11
|
+
The recorded plan resolves its base to a commit that is an ancestor of current `HEAD`. Before review state can use or record a clean conclusion, it parses the active file and compares its canonical hash with the recorded plan. Missing, malformed, or semantically different active content fails closed before an old clean conclusion can authorize delivery; JSON formatting alone is immaterial. Negative review disposition is fail-closed in the other direction: it can retire recorded authorization even while the active plan or current source has drifted. A revision reuses the recorded base unless a base is explicitly supplied. A lane fingerprint hashes the lane declaration, its persistent invalidation `{epoch, revision}`, the canonical Git mode and blob identity including raw pathname bytes of every current source-tree entry selected by that lane's path rules, and the fingerprints of all declared upstream lanes. Plan path rules match those raw bytes as UTF-8 encoded exact names or directory prefixes; diagnostics encode undecodable paths reversibly rather than confusing their identities. The dependency graph must be acyclic. A change to one lane's declaration, generation, or selected content changes that lane fingerprint and recursively changes every dependent fingerprint, while unrelated lanes retain their identity. Re-recording a revised plan preserves only lane verdicts whose base, lane identity, evidence identity, and resulting fingerprint still match; this makes a boundary revision explicit without discarding unrelated evidence.
|
|
12
|
+
|
|
13
|
+
Reviewers may run concurrently from the fingerprints printed by `review:plan` or `review:status`. `recordReviewLaneVerdict` retains the captured `HEAD` as provenance and accepts a clean report when the captured lane fingerprint still matches. An unrelated concurrent edit or `HEAD` advance therefore does not reject the report. A changed direct or upstream input does reject it. A report ending in findings or `VERDICT: INCOMPLETE` is inspected before current-candidate equality and retires that lane and its declared dependent closure from the recorded plan, not unrelated lanes. Temporary source or active-plan drift therefore cannot make rejected evidence effective again after restoring the earlier candidate. Each accepted report is copied under `review-findings/evidence`, hashed, and referenced by a `dsh-review-lane-verdict/v1` record whose internal lane ID and evidence name must match its declared lane and fingerprint.
|
|
14
|
+
|
|
15
|
+
Plan recording, lane verdict recording or retirement, aggregate finalization, clearing, and pre-commit authorization are serialized by one atomic repository-local lock under Git metadata. The lock records the owner PID and a unique release token and bounds acquisition; it never automatically reclaims an owner because no portable pathname operation can prove and remove that exact generation without an ABA race. Crash recovery is an explicit operator action after confirming no review-state command is active, scoped to the exact `review-findings/state.lock` path resolved by Git. A negative report ordered after an older clean recorder advances a persistent per-lane invalidation revision within a random epoch even if the lane is temporarily absent from the current plan, before retiring its current closure. Reaching `Number.MAX_SAFE_INTEGER` rotates to a different random epoch at revision zero, preserving both invalidation and future progress. The absent lane must already have a retained tuple; an unknown ID cannot create one, and every active lane requires an explicit tuple. The tuple is part of that lane's fingerprint and therefore every dependent fingerprint; reports captured before retirement cannot overwrite it after the lane is re-added. Generations survive normal clearing and lane removal. Missing, partial, or malformed generation state blocks authorization; clear preserves valid state but removes damaged state, and explicit plan reconstruction creates a new epoch so a damaged lifecycle cannot restore an older authorization identity. A new clean review captured after retirement remains valid. Status is diagnostic and need not hold the mutation lock. Because the active plan, source tree, index, proof, and evidence can also be changed outside these commands, finalization and pre-commit obtain a stable final observation of their relevant identities before persisting or returning authorization.
|
|
16
|
+
|
|
17
|
+
After all lanes are effective, `npm run check` produces the existing whole-source verification proof for current `{HEAD, fingerprint}`. `review:finalize` writes `dsh-review-verdict/v2`, containing that whole-tree identity, the base, the complete plan hash, and every effective lane fingerprint and evidence hash. The pre-commit hook separately requires an absent or terminal findings ledger, a proof for current `HEAD`, equal source and index fingerprints, complete changed-path coverage, an effective verdict for every lane, intact evidence, and a composite verdict exactly matching that plan and proof. Advancing `HEAD` retires the proof and aggregate verdict. Source or index drift makes both records ineffective while the mismatch remains; restoring their exact candidate identity makes them effective again, while accepting a changed candidate requires another deterministic proof and aggregate finalization. Lane evidence remains reusable when its semantic declaration, direct inputs, upstream fingerprints, base ancestry, and evidence hash still hold.
|
|
18
|
+
|
|
19
|
+
`REVIEW_FINDINGS.md`, `REVIEW_PLAN.json`, reports, lane records, plans, proofs, and aggregate verdicts remain checkout-local. The two root working files are installed into `.git/info/exclude`; reports must stay outside the checkout or be ignored. The old `dsh-review-verdict/v1` single-report format and `verdict` command are rejected rather than treated as composite evidence.
|
|
10
20
|
|
|
11
21
|
## Alternatives considered
|
|
12
22
|
|
|
13
|
-
**
|
|
23
|
+
**Repeat one complete-tree review after every fix.** This binds review to exact bytes but discards unaffected independent evidence and serializes work that has explicit semantic boundaries.
|
|
24
|
+
|
|
25
|
+
**Partition only by changed file paths.** File ownership is mechanically convenient, but intrinsic handling, declaration publication, callable reconstruction, module contracts, and recovery cross file boundaries. Paths select fingerprint inputs; semantic scope, dependencies, owners, consumers, and counterexamples define what the reviewer must establish.
|
|
26
|
+
|
|
27
|
+
**Keep every clean lane unless one of its own files changes.** This misses shared-owner and contract changes. Upstream lane fingerprints enter dependent fingerprints so invalidation follows the declared semantic graph.
|
|
28
|
+
|
|
29
|
+
**Never permit plan changes after review starts.** A fixed incorrect boundary would preserve a known coverage gap. Plan revisions are allowed but versioned by content, must cover every changed path, and invalidate only lanes whose declarations or dependency inputs changed.
|
|
14
30
|
|
|
15
|
-
**
|
|
31
|
+
**Automatically add uncovered paths to a nearby lane.** This avoids stopping the workflow, but a file path does not prove semantic ownership. The gate reports uncovered paths and requires an explicit plan revision.
|
|
16
32
|
|
|
17
|
-
**Store
|
|
33
|
+
**Store lane evidence without a final whole-tree proof.** Lane fingerprints establish review inputs, not deterministic test success or exact prospective commit contents. The composite verdict therefore remains paired with `npm run check` and the index-tree gate.
|
|
18
34
|
|
|
19
35
|
## Consequences
|
|
20
36
|
|
|
21
|
-
|
|
37
|
+
Independent review can begin in parallel after focused checks, and a correction normally reruns only the failed lane and its dependency closure. A small change may use one lane, so partition overhead remains proportional to the work. The plan author must identify semantic dependencies accurately; automation proves declared coverage and evidence identity, not that the declarations are intellectually complete. A newly discovered dependency is a plan defect that must be recorded before review continues. Finalization still requires one stable-tree `npm run check`, but it no longer requires another reviewer to repeat every already effective lane.
|
|
@@ -16,6 +16,10 @@ Caller and helper environment boundaries are explicit. Each creation site projec
|
|
|
16
16
|
|
|
17
17
|
The helper answers an on-demand utilization-sample request from its own loop, and `IsolatedWorker` exposes `sampleUtilization()`. `SessionCellExecutor` starts the wall bound at request submission, awaits that fresh baseline, then starts the compute interval before it posts the prepare or run frame, so work completed before submission is excluded while prepare blocking remains counted. The exception owned by [ADR 0024](0024-repl-console-observation.md) is a confirmed unfinished observation on the same worker: the executor may post prepare before starting budgets so the observation can finish, and the matching observation-completion/readiness acknowledgement starts them. A sample that times out, cannot be sent, disconnects, or exits is a bounded worker-exit failure: pending requests are cleared and no prepare/run frame is dispatched. The ready handshake still contributes an additional startup sample, but it is not the per-cell baseline and it does not reset or defer budgets.
|
|
18
18
|
|
|
19
|
+
Helper stdout and stderr are part of cell settlement, not unowned process noise. For every run, the Host chooses a nonce and arms one output round before posting source. The kernel writes nonce-bearing start markers to both native descriptors and waits for the Host to observe both before executing the cell. It writes matching end markers after evaluation, pending program calls and value encoding settle, but before posting `done`. The Host releases `done` only after both end markers arrive. Bytes between those fences, including direct fd 1/2 writes and inherited child stdio, belong to that physical run and share its aggregate output budget. Structured console logs retain their own order; stdout and stderr each retain pipe order, but the merged presentation does not claim a total chronology across the independent control and descriptor channels.
|
|
20
|
+
|
|
21
|
+
Bytes before a new start fence prove that a settled run still produced descriptor output, so the new run is rejected and the worker is reset rather than attaching those bytes to it. A structured console or stream callback keeps its scheduling execution identity through the worker's private async-local store; output after that execution closes sends a `late-output` control event and likewise rejects any affected run. Bare descriptor bytes carry no scheduling identity, so bytes that actually arrive between a later run's acknowledged start and end fences follow the physical-arrival rule instead of being attributed to an unknowable callback. Fence mismatch, overlap, excess output or out-of-round output is an explicit output-attribution failure and resets the transport. The first idle out-of-round chunk closes capture and starts reset immediately; when no request is active, the Host retains one failure for the next execution instead of continuing to drain an unbounded producer without a diagnostic.
|
|
22
|
+
|
|
19
23
|
## Alternatives considered
|
|
20
24
|
|
|
21
25
|
**Keep the worker in the DSH process and only improve cooperative shutdown.** Asking user code to release its own realms cannot bound a wedged kernel, and any fallback in-host kill reaches the same upstream teardown path that ends DSH.
|
|
@@ -30,12 +30,23 @@ generation is.
|
|
|
30
30
|
**Selection is a live capability.** The plugin's static injection names only the
|
|
31
31
|
services both generations provide; the seam owner waits through `inject` for
|
|
32
32
|
whichever execution service the host registers, in a scope that also requires the
|
|
33
|
-
plugin's own services, and
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
plugin's own services, and owns one live attachment at a time. When both are registered, the current
|
|
34
|
+
generation wins, including when it appears after a preceding-generation attachment.
|
|
35
|
+
That transition first disposes the legacy injected fiber and its complete effect
|
|
36
|
+
tree, then attaches in the current service's scope; cleanup from the retired scope
|
|
37
|
+
cannot clear the new owner. If that attach fails, the owner marks the current
|
|
38
|
+
service object unusable, re-arms the preceding-generation attachment
|
|
39
|
+
immediately, and reports the failure instead of leaving the plugin with no
|
|
40
|
+
execution seam; the failed object is never retried, while a replacement current
|
|
41
|
+
service supersedes the restored attachment. The preceding generation therefore
|
|
42
|
+
attaches only when the current one is absent or is the recorded unusable object.
|
|
43
|
+
Attachment runs in the injected scope, so
|
|
36
44
|
the plugin is unloaded when the host unregisters that service and reattaches when
|
|
37
45
|
it is registered again. A service that satisfies the name but not the contract
|
|
38
|
-
(`run` or `resolve` missing) is reported as a load
|
|
46
|
+
(`run` or `resolve` missing) follows the same path and is reported as a load
|
|
47
|
+
failure naming the service; when a preceding-generation attachment exists, the
|
|
48
|
+
report accompanies its restoration so `run_code` never silently returns to the
|
|
49
|
+
host provider.
|
|
39
50
|
|
|
40
51
|
**Execution is one neutral call shape.** The owner publishes `invokeUpstream`,
|
|
41
52
|
which reproduces each generation's own call shape — directly for
|
|
@@ -93,8 +104,17 @@ escalation it thinks it is offering.
|
|
|
93
104
|
The plugin activates on both the current and the preceding host generation, and
|
|
94
105
|
one test owner covers the selection rules, the neutral call shape, the descriptor
|
|
95
106
|
takeover, and the release semantics for both. A host that registers neither
|
|
96
|
-
execution service
|
|
97
|
-
|
|
107
|
+
execution service cannot be served, and its activation settles with a bounded
|
|
108
|
+
diagnostic naming the missing seam — `no host execution seam (ptcRuntime or
|
|
109
|
+
codeRuntime) is registered` — after the attachment window instead of staying
|
|
110
|
+
pending: the host awaits loader settlement before it becomes usable, so an
|
|
111
|
+
unbounded wait would park every agent, native tool, and unrelated plugin rather
|
|
112
|
+
than failing this entry.
|
|
113
|
+
|
|
114
|
+
A current-generation service that fails to attach cannot leave the plugin
|
|
115
|
+
unattached while the preceding service is still registered: the preceding
|
|
116
|
+
attachment is restored and the failure is reported through the plugin's own
|
|
117
|
+
logger in addition to the injected fiber's activation result.
|
|
98
118
|
|
|
99
119
|
`run_code` on the current host no longer advertises a per-call deadline or file
|
|
100
120
|
sandbox, and DSH rejects those arguments with its own message instead of the
|
|
@@ -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
|
|
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`), so a generation that changes this validation fails the packaging check instead of reaching users.
|
|
16
16
|
|
|
17
17
|
## Alternatives Considered
|
|
18
18
|
|
|
@@ -24,4 +24,4 @@ CI registers the packed contract with the installed host's own registry on both
|
|
|
24
24
|
|
|
25
25
|
## Consequences
|
|
26
26
|
|
|
27
|
-
One plugin build serves the
|
|
27
|
+
One plugin build serves the preceding and current public codec generations for this surface, 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.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Close semantic obligations by owner
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
Focused tests and coverage can prove their selected examples executed, but they cannot show that every plugin-owned semantic transformation or execution boundary has an owner, contract and independent oracle. Adding more examples to a single compiler or realm matrix leaves module, transport, recovery, host and client boundaries outside that matrix, while treating all Node behavior as one fidelity surface erases intentional PTC differences and bounded external assumptions. An unregistered source boundary therefore needs a deterministic failure before review, not a reviewer remembering to extend a list.
|
|
6
|
+
|
|
7
|
+
## Decision
|
|
8
|
+
|
|
9
|
+
`semantic-obligations.json` is the tracked graph of plugin-owned semantic boundaries. Each obligation records one semantic owner, exact implementation files, disposition, owning contract, preserved observables or declared differences, execution entries, lifecycle states, language or data generations, platform bounds, consumers, oracle, executable evidence and upstream obligations. Dispositions distinguish behavior preserved from an external owner, intentional PTC differences and bounded external surfaces; an omitted or uncertain obligation is unknown and fails validation rather than being relabeled as preserved.
|
|
10
|
+
|
|
11
|
+
`scripts/semantic-obligations.mjs` validates the graph before build and coverage in `npm run verify`. The exact inventory covers every JavaScript implementation file in `internal/` and `src/`, the public `index.js` and `client.js` entries, and the journal migration entry, with exactly one semantic owner per file. Adding, removing or assigning a source twice fails closed until the graph changes. Contract and evidence files must exist, every obligation needs executable test evidence, dependencies must resolve without cycles, journal versions must remain a contiguous recorded range, and declared language and module generations must equal their executable owners. The command emits counts for preserved, intentional-difference, bounded-external and unknown obligations; zero unknown means closure over the declared plugin source boundary, not equivalence with all current or future Node or DSH behavior.
|
|
12
|
+
|
|
13
|
+
The graph complements, rather than replaces, focused tests, coverage and independent review lanes. A boundary-specific registry can enforce a stronger relation where the implementation supplies one: worker realm mutations use their classified installation entry and AST check, journal generations use their closed schema, and language/module generations use exported sets. Other records bind exact owner files and evidence so a new boundary cannot enter the tracked source inventory silently; review still evaluates whether an edit inside an existing owner changes its obligation or dependencies.
|
|
14
|
+
|
|
15
|
+
`docs/semantic-validation.md` explains how to choose an oracle and extend evidence. `REVIEW_PLAN.json` remains the checkout-local snapshot partition: its lanes may split or combine tracked obligations for review cost, but must preserve the graph's owner dependencies and changed-path coverage. A clean graph report establishes declared coverage only; deterministic verification and clean independent lane verdicts remain separate delivery requirements.
|
|
16
|
+
|
|
17
|
+
## Alternatives considered
|
|
18
|
+
|
|
19
|
+
**Expand the Test262 or compiler matrix until it appears comprehensive.** Those matrices are strong independent oracles for selected language behavior, but they do not own worker transport, program bindings, journals, host integration or client projection and cannot detect an omitted entry outside their axes.
|
|
20
|
+
|
|
21
|
+
**Use line and function coverage as the global model.** Coverage shows code execution, not which observable must be preserved, whether a difference is contractual, or whether the expected value came from an independent source.
|
|
22
|
+
|
|
23
|
+
**Make the worker realm inventory the global registry.** Realm mutation is only one boundary. Folding compiler, module, wire, recovery and host behavior into Node surface rows would obscure their owners and recreate a manually sampled API matrix.
|
|
24
|
+
|
|
25
|
+
**Derive ownership only from each temporary review plan.** Review plans are candidate-specific and checkout-local. They cannot serve as the durable source inventory or contract graph required before a plan exists.
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
New implementation files and generation changes require an explicit obligation update, and stale evidence blocks the normal gate early. The graph is intentionally bounded to plugin-owned JavaScript sources and declared platform contracts; dependency internals, arbitrary Node APIs and future DSH behavior remain outside the equivalence claim. Exact file assignment adds maintenance cost, but makes source growth and ownership movement reviewable instead of silent.
|
package/docs/adr/README.md
CHANGED
|
@@ -5,14 +5,14 @@ This directory records stable design constraints for PTC Plus. An ADR states a d
|
|
|
5
5
|
## Rules
|
|
6
6
|
|
|
7
7
|
- **A new or changed durable decision updates or adds an ADR** in the same change. Record architecture, public or cross-module contracts, persisted or wire formats, and process or tooling choices that a maintainer may reasonably revisit. A difficult or non-trivial implementation of an existing decision does not by itself require an ADR.
|
|
8
|
-
- **`## Alternatives considered` is mandatory.** Name each genuine alternative and why it lost, one bold-led paragraph per alternative. A decision recorded without what it beat invites re-litigation.
|
|
8
|
+
- **`## Alternatives considered` is mandatory for a new or changed ADR.** Name each genuine alternative and why it lost, one bold-led paragraph per alternative. A decision recorded without what it beat invites re-litigation. Entries written before this rule may use the shorter `## Alternatives` heading; repair them when they are next touched.
|
|
9
9
|
- **Naming.** Files follow `NNNN-kebab-case-title.md`. Keep the number sequence monotonic; never reuse a number.
|
|
10
|
-
- **Format.** One physical line per paragraph:
|
|
10
|
+
- **Format.** One physical line per paragraph in new entries, or the entry's own consistent wrapping when it already wraps; the headings and their order are what make an ADR readable:
|
|
11
11
|
- `# <title>` — the decision in one line
|
|
12
|
-
- `## Problem` — the motivation, written to stand without the solution
|
|
12
|
+
- `## Problem` or `## Context` — the motivation, written to stand without the solution
|
|
13
13
|
- `## Decision` — shipped reality in the present tense; keep it current with what actually shipped
|
|
14
14
|
- bespoke technical sections as needed
|
|
15
15
|
- `## Alternatives considered` — mandatory
|
|
16
|
-
- `## Consequences` — what the trade-off cost and bought
|
|
16
|
+
- `## Consequences` — what the trade-off cost and bought; older entries may carry `## Verification` instead or omit it
|
|
17
17
|
- **Supersession.** When a later decision replaces an ADR, fold every unique rationale, alternative, and consequence into the current owner and repair inbound links before deleting the old file. Partial supersession keeps both files cross-linked. Git history is not the only copy of rationale.
|
|
18
18
|
- **Kept current.** When the code later moves a file, renames a surface, or changes a default, update the owning ADR in the same change (facts only, not the decision itself).
|