Repository navigation
integration: verify the reviewed November 2 issue fixes together - #557
Merged
Merged
Conversation
Complete the evidence layer #103 started: #103 compared two worker binaries on disposable synthetic fixtures, so it could not see host dispatch, the official tools, or a real source/runtime tree. This adds `node bench/cli.mjs calls`, which measures official `grep`/`glob` versus OPS, or two OPS builds in one process, over a real corpus. Bench-only: lib/ and native/ are untouched. Each corpus manifest declares a shape range that the runner checks before it measures, and records a content identity and per-arm coverage (scanned files, truncation, matched observed/total, displayed items). Reports are created exclusively and never overwrite evidence. Timings are manual evidence and never gate CI. Four corpora ship as recipes rather than a downloader: a pinned harness client checkout, an installed CPython stdlib, a rustup toolchain, and the checkout's own installed @deepseek-ai packages. The in-budget corpora carry eight cases, including the #384 exact/bounded pair at limits 5 and 50; the over-budget rust toolchain carries the coverage cases only, because a full count never completes there. Automatic materialization and the independent npm fixture stay out of this change; the operator prepares the tree. Validation: 22 bench suites pass, check-file-size (476 files, all <= 1000 lines), validate-manifest (83 checks), and the browser/settings suites still pass after rebuild.
The shipped bundle mounts one `dsh-ops` row and retires the legacy per-component rows (`file`, `shell`, `ptc`); mounting `lib/components/file/index.js` directly therefore became a no-op, and every candidate call failed as `unknown tool "ops_<name>"` — the deterministic tests never boot a host, so they could not see it. The harness now opts into the plugin's documented verification path (`DSH_OPS_LEGACY_ROWS=1`) before it imports those rows. Shipped behaviour is unchanged: the variable only affects a process that mounts the retired rows itself. Verified on main@3882e69 with the real host: python-stdlib glob-name candidate 494.1 ms (scanned 4120, complete) and a ten-repo workspace glob-ts candidate 751.6 ms (scanned 10,000, scan-budget), with no errors; 22 bench suites still pass.
Every publication hook re-assembles after next() when it retires its own tools, and that rebuild re-enters the same waterfall. When two hooks both wanted to withdraw in one request they re-assembled in turns, so the request never settled - the spin behind an idle Host at 94% CPU reported in #445/#509. claimPresentationRebuild() in publication/presentation.ts gives the first withdrawal in a request its rebuild and tells every later hook to keep the assembly it already holds. The three publication hooks (ptc, native, discovery controller) use it instead of assembling unconditionally. The session shell hook no longer waits through reconciles queued after its own assembly started, and answers an inspection instead of waiting for a publication an inspection cannot change. Tests: test/presentation-rebuild.test.mjs covers the per-request budget and that two withdrawing hooks settle at two passes each.
… probe A host that emits `tools/change` without a scope payload (the official 0.2.1-rc.4 contract is deliberately unfiltered) made every live session re-probe, each probe costing a full prompt assembly. At 198 live sessions this measured 23,143ms and 1,393 assemblies per session creation. Two changes: - publication/changes.ts: read the scope payload newer hosts attach, falling back to our own `withToolChange` window when the payload is empty or absent. An empty payload must not override our attribution with "global", or our own publications would be misread as global. The callback also learns who spoke: `'host'` when the payload named a scope, `'local'` when our own window supplied it. A local declaration is authoritative about changing something unrelated to any tracked session, while an unrecognized host scope is host state this row has not admitted yet and must stay conservative. - discovery/controller.ts: on an unattributed change, probe one representative session (satisfying the probe-memo "at least once" contract) and lazily invalidate the rest. `system-prompt/change` takes the same path, since a prompt change moves presentation only. Publication-set changes (modes, runtime, configuration) keep using `refresh`, which must visit every entry to withdraw stale registrations. Three details carry the difference between "one probe" and "one probe that is actually useful": - The representative is chosen through the same `coordinable` predicate the reconcile loop uses, so the "at least one probe" contract cannot silently degrade to zero probes, including on an external-only mount where no sandbox policy is injected. - `reconcile` walks the representative's whole scope family, and it does so on a later microtask. Invalidate the siblings before that walk and the family is re-probed member by member, the per-session cost this change exists to remove, one family at a time. The siblings therefore go stale only after the representative's probe has run. - A named scope that sits on no tracked session's chain still moved the registry, so a host-attributed change with no matching session falls back to the conservative path instead of being dropped. Refs #490
The pinned packages move to 0.2.1-rc.5 and Cordis to 4.0.5. Three host changes reach this plugin: ToolPresentationMode drops `both`, so every presentation list and loader description names only `native` and `ptc`; ConfigFormSnapshot drops `mode`, so a Client form is editable when it is ready and writable; and run_code asks the host for the directory it executes in, which the test hosts provide only where a suite runs code. The test fixtures follow rc.5 as well: invoke names its PeerScope, a user message carries its source, and the gateway client is resolved through its condition exports.
A restricted (read-only / workspace-write) ops_bash call that cannot prepare the private Bash runtime used to answer with one parameterless catch: the caller was told the runtime was "unavailable or incompatible" and told "Do not retry", whatever the actual stage was - a missing payload, an IPC receipt mismatch, an interrupted staging copy, or a lifecycle lock left by a dead host. The staging path is recoverable by design (verify -> quarantine -> stage again), so the blanket advice was wrong for exactly the failures another call repairs. - Add src/bash-runtime-failure.ts: named stages plus the retry and next-action advice rendered for the model. - Name the stage at every preparation failure in bash-ipc.ts and keep the message (stage + reason + remedy) through shells/session-execution.ts. - Report the recorded lock owner and the recovery command when a lifecycle lock is left behind. - Reclaim interrupted stage-* copies older than one hour, count them in the reported reclaimable bytes, and remove them all with a confirmed bash-runtime clean-cache. - Document the symptom, diagnosis and recovery in both languages, and add regression tests: reverting the session layer turns the integration test red. This changes diagnostics and cache lifecycle only: no payload byte, no tool schema, no approval path and no hashed artefact changes.
- docs: name only native and ptc (native-ptc, ptc-cost, ptc-sdk-loading,
result-budgets, discovery and their Chinese twins); drop the hybrid row
- diagnostics: stop suggesting the removed Native/both presentation
- test: replace presentAs('both')/mint('both') with real presentations;
retire the discovery-incremental case that needed a mixed scope
- settings-ui: drop the dead mode fixture field and assert that a ready
document refusing writes stays uneditable
- fixtures: share workingDirectoryOver and ownerPeer, resolve both client
entries through package condition exports, document withWorkingDirectory
- deps: remove the unreferenced dsh-working-directory devDependency
…ery session A bare tools/change cannot move a presentation mode: the collapsed section text and the wire projection depend on the mode alone. Only a system-prompt/change since the last re-derivation can have flipped one, so that is what spends the probe now; a probe a superseded publish still owes is spent rather than dropped, and the assembly guard publishes before a PTC-only prompt is served. One unattributed change over 198 live sessions drops from 198 assemblies to 0. The republish itself is never skipped. A restriction or a scoped shadow moves what a Native session sees while the probed surface stays identical, so the queued request still drives the publication and only the verdict is carried over for the next real probe at pre-step. Refs #490
Three scripts that measure the session-creation cost the issue reports, so the numbers in the issue can be re-derived rather than trusted. `probe-490-curve.mjs` measures assemblies per event against the live session count, with `create-only` as the control that separates creation cost from the change that follows it. `probe-490-epoch.mjs` answers which host action emits `system-prompt/change` — the fact the PTC deferral rests on. `probe-490-surface.mjs` records a ruled-out hypothesis: the per-session surface read is about 0.03ms, so the remaining cost is not there. They sit in `bench/probes/` because `bench/` keeps only CLI entry points at its root and groups everything else by purpose. Not part of the default gate.
…bling A bare registration cannot move a presentation mode, and a scope whose registry mode already resolves to `native` renders the collapsed section empty. Reading that mode from the scope chain is the same source the section itself reads, so the verdict it can return is the one already held: the assembly is skipped instead of paid. On a 12-agent Native fleet one unattributed `tools/change` drops from 12 assemblies to 0; a single flip to PTC costs 1 instead of 23.
# Conflicts: # docs/CHANGELOG.md
Merge fix/490-upstream, fix/490-ptc-lazy-verdict and fix/490-provider-scan into a single change set so the maintainers can review one ordering instead of three branches that rewrite the same files. The PTC side takes the provider-scan branch's later state, which already contains the lazy-verdict deferral, and regains the registry mode precheck the merge would otherwise have dropped: a scope whose `modeFor` is not `ptc` answers from the scope chain instead of assembling. The discovery side keeps the upstream bounded representative probe, whose change-attribution file now also carries the host-payload origin that both later branches rely on. The lazy-invalidation assertion gains the PTC claim: in a PTC deployment the discovery component answers from an exact PTC surface claim, so an unattributed change assembles nothing at all rather than one representative.
The deleted suite appended the PTC section from its own assemble hook, so its assertion measured the injection rather than the lazy invalidation it named. The behaviour it claimed to cover is already locked by the representative-probe suites, which fail when the boundary is removed. Also delete the probe option the host fixture never accepted, and say where a lazily invalidated scope re-observes its presentation: agent/pre-step and tool execution check freshly regardless of cached state.
…6a2-8c35-9c371a16--rc5-compat-integrated # Conflicts: # docs/CHANGELOG.md
…ooks The #524 report filed a pnpm `ERR_PNPM_UNKNOWN` against this plugin, but the failure is pnpm failing to `open` a file while unpacking a *different* plugin from a Git tarball into its own store; no dsh-ops code path calls a package manager. The part of that report this repository does own is the Git channel: `git+https` cannot produce a loadable plugin, because `lib/` and `runtime/` are gitignored and `prepack` never stages the native worker. - Document the unmapped Windows `open` error as a local store/volume condition, in both languages, with the store-prune, security-software and store-dir steps a reader can execute, and the instruction not to relax supply-chain checks. - State the install-channel contract in usage/README/CONTRIBUTING: the registry tarball is the only channel; a source checkout needs `npm ci && npm run build && npm run build:ptc && npm pack`. - Refuse `prepare` and `postinstall` in `scripts/validate-manifest.mjs`, so "fix the Git channel with `prepare`" cannot land silently: `prepare` would compile `lib/` for every Git install and still leave `runtime/` empty. - Prove both facts: a new `install-channel` suite runs the shipped gate against a staged package and fails when a hook is injected, and `docs-facts` requires the bilingual troubleshooting entry.
The gate refuses every `(pre|post)?(prepare|install)` script, but its label named only `prepare`/`postinstall`, so an author adding an unrelated `preinstall` would read a rule that does not match what fails. The failure text also pointed at a step in an uncommitted internal plan, leaving a reference that resolves nowhere outside the author's tree. Name the rule after its actual scope, keep only the public `docs/upgrading.md` reference plus the fact, and align the English and Chinese install-channel docs and the changelog with the broader contract. The suite now asserts an unrelated `preinstall` is refused too, so the wording cannot narrow again without failing.
A component that registers or restricts while `system-prompt/assemble` runs — issue #526's dsh-better-goal shape — made discovery treat its own probe's side effect as an external change. The probe emitted `tools/change`, the listener invalidated every entry and reconciled again, and the next probe emitted again: one external activation became 3001 prompt assemblies and 3000 `tools.restrict()` records in 1.1 s, with RSS climbing from 77 to 156 MB while the host was still booting. Attribute a notification to the probe that caused it instead of widening the `mutating` window, which cannot bound an asynchronous third-party handler: - Track probe depth per asynchronous flow in `publication/presentation.ts` (`AsyncLocalStorage`), so an unrelated change during a slow assembly is still external and a nested assembly stays attributed to its outermost probe. A process-wide counter regresses `probe-isolation`'s late-probe cases. - In `discovery/controller.ts`, count changes observed inside a probe and apply them at most once, after the probe returns, as a trailing reconciliation. A genuine external change re-arms that budget; a component that keeps mutating during assembly has its trailing change dropped and is named once in a warning, because reassembling to observe it is the loop itself. `test/discovery-feedback-loop.test.mjs` pins the observable behaviour: one external change costs one traversal (two with a one-off in-assembly change), a real presentation change still withdraws and restores the surface, and 50 activations stay inside their per-activation budget. Reverting the attribution turns three of its five checks red. Closes #526
…iewed-integration-20261102 # Conflicts: # docs/CHANGELOG.md
…iewed-integration-20261102 # Conflicts: # docs/CHANGELOG.md
# Conflicts: # docs/CHANGELOG.md
…iewed-integration-20261102
…iewed-integration-20261102 # Conflicts: # docs/CHANGELOG.md
…iewed-integration-20261102 # Conflicts: # docs/CHANGELOG.md # native/crates/ops-search/src/scan.rs
…iewed-integration-20261102
…iewed-integration-20261102 # Conflicts: # docs/CHANGELOG.md
This was referenced Nov 1, 2026
Haoming9527
marked this pull request as ready for review
November 1, 2026 19:16
This was referenced Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Review order and deferred validation: #556.
Combined integration of the individually reviewable November 2 fixes. No GitHub PR has been merged. Review the source slices in #556 before merging this combined tree.
Preserves all 22 reviewed source heads from #503, #520, #538–#552, #554, #558, #559, #561, #562 and #572 except the separate release/0.4.4 PR #546. Independent PRs remain the review units. The alpha.2 compatibility investigation #555 and later alternative contributor PRs #563–#571 are excluded; their scope comparisons and review findings are linked in #556.
Additive changelog conflicts retain both entries. The benchmark/publication dependency conflict retains the documented rc2 development graph and matching timeout-policy, alongside existing isolated rc5 evidence; it keeps the download-guard exports and all reviewed implementation changes. The search merge retains both profiling and WSL Windows-path restrictions. No compatibility range is widened.
Evidence
After: a clean combined tree preserves each contributor head and the intended behavior of both sides.
8d0f503: all nine executed CI jobs passed, including Windows, Linux, both macOS architectures and the Node floor; the optional benchmark job was skipped (run).3ff70c2includes those follow-ups and the npm 12 release fix; all nine executed CI jobs pass (run), with only the optional benchmark skipped. Fresh native/IPC builds, source-size and 86 manifest checks pass. Ten focused suites (55 checks) pass across the new CLI/build/search/security/packaging changes.d81fa602includes WSL and the capability inventory; all nine executed CI jobs pass (run). Fresh build/typecheck/native staging pass; 32 Rust tests pass with one existing UNC test ignored locally, and seven file/security/search suites pass 45 checks. The final manifest/docs run passes 21 checks across two suites; manifest validation passes 89 checks.0bb2230changes only the WSL acceptance script and bilingual documentation. It preserves fix(cache): avoid workspace preparation in full-access sessions #544's intentional full-access cache refusal on legacy hosts: when the cache-only capability is absent, delegated fallback must have no storage authority and exactly match the opt-out Windows bounded result. When that capability exists, a missing reference remains a failure. The original failed assertion and captured absent-storage envelopes are retained as evidence of the corrected fixture assumption, not a production capture regression. All five real Windows cache-contract checks pass, including private ACL spill/paging/cleanup.0bb2230: workspace-write 12/12 and danger-full-access 12/12, zero skipped/failed, on the locked rc.2 graph. Both observe the Linux worker PID/start time and its absence after cancellation. Windows payload SHA-2563d97ad84dc57dc464e2e231580b9fdfb6f698b59586a7ad76a71b165f5fce17f; the Linux payload comes from the successfuld81fa602integration CI, whose entire production/Rust/dependency tree is unchanged by the final four-file test/docs follow-up. Final-head CI: all nine executed jobs passed, including Windows and both macOS architectures; only optionalbench-smokeskipped. Actual job conclusions were inspected, including the Windows job that permits continue-on-error.tarrejected Unicode filenames. GNU tar 1.35 extracted the same artifact successfully; its Unicode document matches commit8d0f503, and the packed native runtime closure passes. No system configuration was changed and no damaged artifact was accepted as a full extraction.Merge Danger
Door: two-way
This branch contains reviewed slices rather than a new combined feature design. Review each linked PR before accepting the integration, and rerun checks if main or a contributing head changes. The development graph resolution needs the combined benchmark and publication checks.
Blast Radius: integration
File permissions, publication lifetimes, shell diagnostics and optional prompt guidance interact here. #546 remains a separate release branch; unsupported alpha.2 work is deliberately not included.