* refactor(sdk): extract gsdtools transport seam with per-command policy * refactor(query): centralize registry command catalog wiring * refactor(query): unify command resolution seam across sdk callers * fix(sdk): address CodeRabbit transport policy and timeout findings * refactor(query): extract mutation event mapper seam * refactor(query): converge mutation and transport policy data * refactor(query): share fallback orchestration across cli and sdk * refactor(query): split static registry catalog by domain clusters * refactor(query): extract mutation event emission decorator seam * refactor(query): extract alias-family handler catalog module * refactor(query): extract cjs fallback execution adapter * refactor(query): deepen command semantics seam * refactor(query): extract deep dispatch seam * refactor(query): deepen cjs fallback execution seam * refactor(query): merge routing plan into dispatch seam * fix(query): address CodeRabbit review findings on PR #3060 Critical: prevent double-execution race by checking timeout errors before subprocess fallback (gsd-transport.ts). Major: fix execRaw() to respect transport policy outputMode instead of hardcoding 'raw' (gsd-tools.ts). Major: add explicit 30s timeout to subprocess fallback execution (query-fallback-executor.ts). Major: remove raw args from stderr banner to prevent secret leakage (query-fallback-executor.ts). Minor: ensure native text output has trailing newline for CLI parity (query-dispatch.ts). Update gsd-tools.test.ts to match new execRaw() behavior. * fix(tests): update CLI integration tests for catalog-based registration The refactoring moved handler registration from inline registry.register() calls to catalog-based registration (registerStaticCatalog/registerAliasCatalog). - gsd-sdk-query-registry-integration.test.cjs: collectRegisteredNames() now also scans catalog files for handler names registered via the new system. - bug-2492-context-coverage-gate.test.cjs: checks for catalog-based registration (DECISION_ROUTING_STATIC_CATALOG) instead of inline strings. - bug-2524-sdk-query-ws-flag.test.cjs: checks for dispatchNative callback pattern instead of direct registry.dispatch() call. * fix(query): address remaining CodeRabbit review findings - query-command-semantics.ts: guard stats/progress rewrite so option tokens (e.g. --pick) are not turned into subcommands, preserving the top-level handler dispatch. - query-dispatch.ts: formatOutput now skips --pick for text-format responses (matching CJS fallback behavior) and surfaces a proper error when extractField returns undefined instead of silently producing 'undefined'. - query-dispatch.ts: fix backwards error message — 'registered' is the restrictive policy that disables fallback, not enables it. - tests/bug-2492-context-coverage-gate.test.cjs: check VERIFY_DECISION_STATIC_CATALOG (the correct catalog for plan-gate handlers) instead of DECISION_ROUTING_STATIC_CATALOG. - tests/gsd-sdk-query-registry-integration.test.cjs: resolve catalog variable before loading entries so the drift guard checks each referenced catalog individually. * refactor(query): deepen registry assembly module with strict invariants - extract registry assembly into dedicated module - split build vs mutation decoration internals - add strict assembly invariants: 1) no duplicate keys 2) alias canonicals must have handlers 3) mutation commands must be registered 4) raw-output policy commands must be registered - slim query index to thin re-export seam - add focused registry assembly tests - update drift-guard tests to target new seam * test(query): add thin-seam coverage for query index re-exports * fix(query): return structured native dispatch errors + tighten decisions.parse guard - runQueryDispatch native path now catches adapter errors and returns QueryDispatchResult.error instead of throwing. - preserve legacy CLI exit contract by using code=1 for native dispatch failures. - strengthen bug-2492 guard: decisions.parse assertion now checks VERIFY_DECISION_STATIC_CATALOG OR explicit command token.
121 lines
5.3 KiB
TypeScript
121 lines
5.3 KiB
TypeScript
import { QueryRegistry } from './registry.js';
|
|
import {
|
|
STATE_COMMAND_ALIASES,
|
|
VERIFY_COMMAND_ALIASES,
|
|
INIT_COMMAND_ALIASES,
|
|
PHASE_COMMAND_ALIASES,
|
|
PHASES_COMMAND_ALIASES,
|
|
VALIDATE_COMMAND_ALIASES,
|
|
ROADMAP_COMMAND_ALIASES,
|
|
} from './command-aliases.generated.js';
|
|
import { GSDEventStream } from '../event-stream.js';
|
|
import type { QueryHandler } from './utils.js';
|
|
import { registerAliasCatalog, registerStaticCatalog } from './command-catalog.js';
|
|
import {
|
|
FOUNDATION_STATIC_CATALOG,
|
|
STATE_SUPPORT_STATIC_CATALOG,
|
|
MUTATION_SURFACES_STATIC_CATALOG,
|
|
VERIFY_DECISION_STATIC_CATALOG,
|
|
DECISION_ROUTING_STATIC_CATALOG,
|
|
} from './command-static-catalog-foundation.js';
|
|
import { DOMAIN_STATIC_CATALOG } from './command-static-catalog-domain.js';
|
|
import { QUERY_MUTATION_COMMAND_LIST, TRANSPORT_RAW_COMMANDS } from './policy-convergence.js';
|
|
import { decorateMutationsWithEvents } from './mutation-event-decorator.js';
|
|
import { FAMILY_HANDLERS } from './command-family-handlers.js';
|
|
import {
|
|
assertAliasCanonicalsHaveHandlers,
|
|
assertMutationCommandsRegistered,
|
|
assertNoDuplicateRegisteredCommands,
|
|
assertRawOutputPolicyCommandsRegistered,
|
|
type RegistryAssemblyAliasGroup,
|
|
type RegistryAssemblyStaticGroup,
|
|
} from './registry-assembly-invariants.js';
|
|
|
|
/**
|
|
* Command names that perform durable writes (disk, git, or global profile store).
|
|
*/
|
|
export const QUERY_MUTATION_COMMANDS = new Set<string>(QUERY_MUTATION_COMMAND_LIST);
|
|
|
|
const STATIC_CATALOG_GROUPS: readonly RegistryAssemblyStaticGroup[] = [
|
|
{ name: 'FOUNDATION_STATIC_CATALOG', entries: FOUNDATION_STATIC_CATALOG },
|
|
{ name: 'STATE_SUPPORT_STATIC_CATALOG', entries: STATE_SUPPORT_STATIC_CATALOG },
|
|
{ name: 'MUTATION_SURFACES_STATIC_CATALOG', entries: MUTATION_SURFACES_STATIC_CATALOG },
|
|
{ name: 'VERIFY_DECISION_STATIC_CATALOG', entries: VERIFY_DECISION_STATIC_CATALOG },
|
|
{ name: 'DECISION_ROUTING_STATIC_CATALOG', entries: DECISION_ROUTING_STATIC_CATALOG },
|
|
{ name: 'DOMAIN_STATIC_CATALOG', entries: DOMAIN_STATIC_CATALOG },
|
|
] as const;
|
|
|
|
const ALIAS_GROUPS: readonly RegistryAssemblyAliasGroup[] = [
|
|
{ family: 'state', aliases: STATE_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.state as Record<string, QueryHandler> },
|
|
{ family: 'roadmap', aliases: ROADMAP_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.roadmap as Record<string, QueryHandler> },
|
|
{ family: 'verify', aliases: VERIFY_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.verify as Record<string, QueryHandler> },
|
|
{ family: 'validate', aliases: VALIDATE_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.validate as Record<string, QueryHandler> },
|
|
{ family: 'phase', aliases: PHASE_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.phase as Record<string, QueryHandler> },
|
|
{ family: 'phases', aliases: PHASES_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.phases as Record<string, QueryHandler> },
|
|
{ family: 'init', aliases: INIT_COMMAND_ALIASES, handlers: FAMILY_HANDLERS.init as Record<string, QueryHandler> },
|
|
] as const;
|
|
|
|
export function buildRegistry(): QueryRegistry {
|
|
assertAliasCanonicalsHaveHandlers({
|
|
staticGroups: STATIC_CATALOG_GROUPS,
|
|
aliasGroups: ALIAS_GROUPS,
|
|
mutationCommands: QUERY_MUTATION_COMMANDS,
|
|
rawOutputPolicyCommands: TRANSPORT_RAW_COMMANDS,
|
|
});
|
|
assertNoDuplicateRegisteredCommands({
|
|
staticGroups: STATIC_CATALOG_GROUPS,
|
|
aliasGroups: ALIAS_GROUPS,
|
|
mutationCommands: QUERY_MUTATION_COMMANDS,
|
|
rawOutputPolicyCommands: TRANSPORT_RAW_COMMANDS,
|
|
});
|
|
|
|
const registry = new QueryRegistry();
|
|
|
|
registerStaticCatalog(registry, FOUNDATION_STATIC_CATALOG);
|
|
registerAliasCatalog(registry, STATE_COMMAND_ALIASES, FAMILY_HANDLERS.state as Record<string, QueryHandler>);
|
|
|
|
registerStaticCatalog(registry, STATE_SUPPORT_STATIC_CATALOG);
|
|
registerAliasCatalog(registry, ROADMAP_COMMAND_ALIASES, FAMILY_HANDLERS.roadmap as Record<string, QueryHandler>);
|
|
|
|
registerStaticCatalog(registry, MUTATION_SURFACES_STATIC_CATALOG);
|
|
|
|
registerAliasCatalog(registry, VERIFY_COMMAND_ALIASES, FAMILY_HANDLERS.verify as Record<string, QueryHandler>);
|
|
|
|
registerStaticCatalog(registry, VERIFY_DECISION_STATIC_CATALOG);
|
|
registerAliasCatalog(registry, VALIDATE_COMMAND_ALIASES, FAMILY_HANDLERS.validate as Record<string, QueryHandler>);
|
|
|
|
registerStaticCatalog(registry, DECISION_ROUTING_STATIC_CATALOG);
|
|
|
|
registerAliasCatalog(registry, PHASE_COMMAND_ALIASES, FAMILY_HANDLERS.phase as Record<string, QueryHandler>);
|
|
|
|
registerAliasCatalog(registry, PHASES_COMMAND_ALIASES, FAMILY_HANDLERS.phases as Record<string, QueryHandler>);
|
|
|
|
registerAliasCatalog(registry, INIT_COMMAND_ALIASES, FAMILY_HANDLERS.init as Record<string, QueryHandler>);
|
|
|
|
registerStaticCatalog(registry, DOMAIN_STATIC_CATALOG);
|
|
|
|
assertMutationCommandsRegistered(registry, QUERY_MUTATION_COMMANDS);
|
|
assertRawOutputPolicyCommandsRegistered(registry, TRANSPORT_RAW_COMMANDS);
|
|
|
|
return registry;
|
|
}
|
|
|
|
export function decorateRegistryMutations(
|
|
registry: QueryRegistry,
|
|
eventStream?: GSDEventStream,
|
|
correlationSessionId?: string,
|
|
): void {
|
|
if (!eventStream) return;
|
|
const mutationSessionId = correlationSessionId ?? '';
|
|
decorateMutationsWithEvents(registry, QUERY_MUTATION_COMMANDS, eventStream, mutationSessionId);
|
|
}
|
|
|
|
export function createRegistry(
|
|
eventStream?: GSDEventStream,
|
|
correlationSessionId?: string,
|
|
): QueryRegistry {
|
|
const registry = buildRegistry();
|
|
decorateRegistryMutations(registry, eventStream, correlationSessionId);
|
|
return registry;
|
|
}
|