createGSDToolsRuntime accepted opts.workstream and forwarded it to the
QuerySubprocessAdapter (line 38) but the QueryNativeDirectAdapter's
dispatch closure dropped it:
dispatch: (registryCommand, registryArgs) =>
registry.dispatch(registryCommand, registryArgs, opts.projectDir)
`registry.dispatch(command, args, projectDir, workstream?)` accepts a
4th workstream argument and forwards it to handlers. When a GSDTools
instance was created with a workstream, the native fast-path silently
routed planning-path queries to the root `.planning/` tree instead of
`.planning/workstreams/<name>/`. Subprocess dispatch correctly carried
the workstream; native dispatch did not — runtime-bridge mode parity
broke for any workstream-aware GSDTools consumer using the native path.
One-line fix: pass opts.workstream as the 4th arg to registry.dispatch.
Regression test exercises three paths:
1. Constructor-seam unit test: spy on QueryNativeDirectAdapter,
capture the dispatch closure, verify it reaches a registry that
reports the unknown-command error message.
2. Back-compat: same with workstream omitted — closure still reaches
the registry.
3. End-to-end: spy on createRegistry to inject a probe registry with a
registered handler that records its args. Invoke through
runtime.bridge.dispatchHotpath(). Assert the handler observed
workstream='frontend-ws' as its 3rd arg.
RED verified: end-to-end probe fails on pre-fix tree with
`expected undefined to be 'frontend-ws'`. GREEN after the fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>