The shipped-roster change made @deepseek-ai/dsh-tool-session-query a
default row of the shared base.cordis.yml, so the TUI and Web surfaces
put the five session-search tools in front of the model. That
contradicts the recorded opt-in stance for the model-facing session
query consumer; the ACP example remains the mounted reference.
Remove the row from the shared base, the now-dangling disabled patch in
the opt-in core-web profile, and the workspace dependency. The
ctx.sessionQuery index stays: the TUI's /resume and the Web content
search consume it directly. Both shipped-composition tests now pin the
20-tool catalog.
ds-review-bot round 1 on the repository-plugin runtime:
- a manifest-declared skill root absent or non-directory in the installed
package now fails the plugin load (skill-local treats a missing root as
legitimately empty, which silently mounted a skill-less plugin)
- includeDefaultRoots: false no longer inherits $DSH_BUNDLED_SKILL_DIR, so
isolated repository providers see only their explicit roots
- prepared wrapper baseUrl schema requires the file: scheme, failing hostile
URLs at the declared validation boundary
- preparedPath reuses format.ts's isOutside; SERVER_NAME_PATTERN is exported
and pinned equal to dsh-mcp-client's, with the restatement justified (the
prepare bin keeps a zod-only module graph); the unexplained `as never`
cast now carries its schemastery rationale
- the import-free wrapper assertion also rejects dynamic import(
- the headless fixture wrapper is regenerated by the real prepareDshPlugin
and a drift test pins fixture == generator output
- prepareDshPlugin JSDoc states the non-atomic publish repair contract
- inline the collect() identity wrapper now that both streams use the
seam's diagnostic-tail shape
- resolve the packaged rg path lazily at the first call (memoized):
@vscode/ripgrep resolves its platform package at module evaluation, so a
static import turned a missing/corrupt platform package into a Loader
composition failure instead of the documented per-call SEARCH_FAILED
- classify synchronous spawn-creation throws (a NUL in argv, an abort
racing the pre-check, a rejected resolution) into SEARCH_FAILED /
SEARCH_ABORTED instead of leaking raw errors
- correct the stderrMaxBytes contract: the stderr excerpt is embedded in
SEARCH_* error messages, not hidden from the model
- export virtualManifest and pin its three acceptance paths (prefix hit,
pnpm-11 truncated-name content-scan fallback, both miss) with fixture
unit tests
Tests: rg-path.spec.ts (resolution failure + memoized rejection),
tools.spec.ts spawn-creation classification, notices spec virtualManifest.
Merges master (default-workspace-write-ui, installer-adopt-checkout,
remove-scoped-bash, goal-clear-single-flight, frontend-plugin-loader,
install-interface-choice, …).
Conflict resolutions:
- apps/cli/tests/shipped-composition.e2e.ts: keep the fixed glob/grep
roster assertion; master's workspace-write composition now confines
tool-bash, so the escalation pair is pinned present (my earlier
absence pin is superseded) together with master's permission facts.
- even-out-shipped-tool-rosters note: both sides edited it; the merged
text keeps both sets of changes and the pair is re-recorded.
- delete the singleQuote shell-quoting helper and its bash-spawning tests
(no in-repo consumers; no shell layer exists anymore)
- drop spill from both collect streams: the tool never reads a raw spill
path, and a lossy stdout read is a pure SEARCH_RAW_OUTPUT_OVERFLOW error
- prepend --no-config so a host RIPGREP_CONFIG_PATH cannot inject a --pre
preprocessor into the unconfined spawn
- promote graceMs and stderrMaxBytes to validated Config fields (defaults
SEARCH_GRACE_MS / SEARCH_STDERR_MAX_BYTES) instead of inheriting
bash-local's config
- correct the grep tool's JSDoc seam reference (bash -> subprocess)
- drop the dead exit-127/command-not-found classification branch
Windows-native execution foundation: PwshLocalExecutor implements the bash
executor seam over ctx.subprocess (pwsh -NoLogo -NoProfile -NonInteractive
-Command, one argv element, no quoting layer; resolvePwshPath probes
PowerShell 7 / PATH / Windows PowerShell 5.1 as a pure function), and
tool-pwsh is the minimal PowerShell-dialect model-facing tool over ctx.bash
(foreground only, managed DSH_* env, timeout/signal/exit markers, terminal
and generic presenters). Both packages carry full suites (real pwsh,
self-skipping without it) at per-file 100% coverage; vitest's Windows
exclusion narrows from packages/bash/* to the bash-requiring packages so the
pwsh suites run natively on Windows too. The CLI gains the workspace deps
and tsconfig projects without mounting either plugin; the Windows-default
roadmap is recorded as a proposed Agent Note.
glob/grep now run the @vscode/ripgrep binary via ctx.subprocess with a plain
argv vector: no system rg install, no shell layer, unconditional registration.
The load-time command -v rg probe and the bash-seam coupling are removed;
timeouts ride the cooperative exec.signal plus the seam's terminate
escalation. The fs-glob-sampling ACP snapshot executes the real packaged
binary against an mtime-pinned fixture. Adds the packaged-ripgrep-search
Agent Note, updates the roster-note facts and both shipped-composition e2es,
and regenerates the doc catalogs and third-party notices (surfacing
pre-existing manifest drift plus the new @vscode/ripgrep row; the notices
generator also learns pnpm 11's truncated virtual-store names).
The comments and Agent Note blamed macOS resolving /var through
private/var. That is only how the mismatch surfaced in temp fixtures, since
mktemp hands back a /var path there.
The real condition is broader: Git always reports resolved paths, so
comparing one against an unresolved path disagrees whenever a symlink sits
anywhere above the checkout. A symlinked home directory alone triggers it —
reproduced with no /var involved — which is common wherever homes live
behind a symlink or on a network mount.
Naming the cause correctly keeps a reader from dismissing resolve_dir as
macOS-only defensiveness.
Review flagged the resolve_dir comment: it claimed `x=$(cmd) || fallback`
never fires "because the assignment succeeds even when the substitution
fails." That is wrong — command substitution propagates exit status and the
fallback does fire, confirmed in sh, bash, dash, and zsh.
Reproducing the original code shows the fallback also worked, so the second
"recurrence" the Agent Note described never existed. Both real defects were
the same one: comparing a resolved path against an unresolved one. The note
now says that instead of inventing a mechanism.
resolve_dir keeps its `|| printf` because it makes every caller a plain
assignment, so no site can compare against an empty path by forgetting its
own fallback — the reason is now stated accurately.
Also from review: REPO_COMMON is now resolved on both branches, matching
REPO_ROOT, and _repo_root notes why it is already physical without its own
resolve_dir call.
Nothing read it. The launcher, dsh-upgrade, and the installer's own re-run
all ignored the file, and the diagnostic it was meant to feed was never
built, so it was write-only state.
Git already owns the fact it recorded: a staging worktree's .git file names
the repository path, and `git worktree list` in that clone enumerates every
worktree depending on it. An installer-written copy only adds state that can
go stale while nothing validates it.
The containment caveat it documented is real and stays in the script header
and the Agent Note, now pointing at git's own records.