feat(fs-search): spawn the packaged ripgrep binary through the subprocess seam

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).
This commit is contained in:
Huanqi Cao
2026-08-01 18:04:38 +08:00
parent de520bee24
commit 18700f428d
32 changed files with 923 additions and 699 deletions

View File

@@ -49,10 +49,10 @@ const EXPECTED_TOOLS = [
]
/**
* `glob` and `grep` come from `dsh-tool-fs-search`, which probes `command -v rg`
* through the mounted bash executor at load and registers neither tool when
* ripgrep is absent. That is a host dependency, not a composition decision, so the
* pair is asserted separately — present together or absent together.
* `glob` and `grep` come from `dsh-tool-fs-search`, which spawns the PACKAGED
* ripgrep binary (`@vscode/ripgrep`) through the subprocess seam, so the pair
* is always present on every host — asserted as fixed members, not a host
* dependency.
*/
const RIPGREP_TOOLS = ['glob', 'grep']
@@ -67,7 +67,9 @@ it('assembles the shipped Web catalog and keeps its access default', async () =>
scaffold = await launchWebScaffold()
const names = scaffold.ctx.tools.schemas().map(schema => schema.name).sort()
expect(names.filter(name => !RIPGREP_TOOLS.includes(name))).toEqual(EXPECTED_TOOLS)
expect([[], RIPGREP_TOOLS]).toContainEqual(names.filter(name => RIPGREP_TOOLS.includes(name)))
// The packaged ripgrep binary ships with the dependency, so the pair is a
// fixed roster member on every host.
expect(names.filter(name => RIPGREP_TOOLS.includes(name))).toEqual(RIPGREP_TOOLS)
// `workspace-write` is not "the workspace and nothing else": the shared roots
// helper always admits the temp directories too. Pinning it against an
// explicit mode keeps the claim independent of this surface's default, and