refactor(query): deepen dispatch policy seam with structured result contract (#3066)

* refactor(query): deepen dispatch policy seam with structured result contract

Closes #3065.

- unify query dispatch outcome as typed success/failure union
- include error kind/details + final exit_code in failure path
- align native and fallback paths under one dispatch policy seam
- make CLI query path consume seam result (thin adapter)
- add ADR + context term for Dispatch Policy Module

* refactor(query): strengthen dispatch seam with shared error mapper and typed details

- add query-dispatch-error-mapper module shared by native/fallback paths
- remove ad-hoc inline mapping in dispatch/fallback executors
- lock error-details schema in mapper + dispatch tests
- document structured dispatch contract in QUERY-HANDLERS.md

* fix(query): return structured fallback failure when path resolution throws

- guard resolveGsdToolsPath in cjs dispatch path
- map thrown resolution errors to fallback_failure result
- add regression test for structured failure contract
This commit is contained in:
Tom Boucher
2026-05-03 14:30:27 -04:00
committed by GitHub
parent 5975f06b6a
commit f104dab332
12 changed files with 297 additions and 51 deletions

View File

@@ -2,6 +2,7 @@ import { execFile } from 'node:child_process';
import { readFile } from 'node:fs/promises';
import { extractField } from './registry.js';
import type { QueryDispatchResult } from './query-dispatch-contract.js';
import { mapFallbackDispatchError, toDispatchFailure } from './query-dispatch-error-mapper.js';
interface CjsFallbackQueryResult {
mode: 'json' | 'text';
@@ -99,14 +100,16 @@ export async function runCjsFallbackDispatch(input: RunCjsFallbackDispatchInput)
const fallback = await runCjsFallbackQuery(projectDir, gsdToolsPath, normCmd, normArgs, ws);
if (fallback.stderr.trim()) stderr.push(fallback.stderr.trimEnd());
return {
ok: true,
stderr,
stdout: formatFallbackOutput(fallback.output, fallback.mode, pickField),
stdout: formatFallbackOutput(fallback.output, fallback.mode, pickField) ?? '',
exit_code: 0,
};
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
return {
return toDispatchFailure(
mapFallbackDispatchError(msg, normCmd, normArgs),
stderr,
error: { code: 1, message: `Error: gsd-tools.cjs fallback failed: ${msg}` },
};
);
}
}