refactor(#184): migrate init composer handlers to sdk/src/handlers/init

This commit is contained in:
Tom Boucher
2026-05-24 21:58:44 -04:00
parent 5e8e677328
commit 01cd00c080
8 changed files with 28 additions and 29 deletions

View File

@@ -59,7 +59,7 @@ Canonical command normalization and resolution Interface (`query-command-resolut
Module owning command resolution, policy projection (`mutation`, `output_mode`), unknown-command diagnosis, and handler Adapter binding at one seam for query dispatch.
### Init Command Module
SDK Module owning the `init.*` family of query handlers that compose atomic SDK queries into the flat JSON bundles consumed by init workflows (`/gsd-execute-phase`, `/gsd-plan-phase`, `/gsd-verify-work`, `/gsd-new-project`, `/gsd-manager`, `/gsd-progress`, `/gsd-resume`, etc.). Divided into two source files: `sdk/src/query/init.ts` (13 basic handlers plus `withProjectRoot` project-identity injection) and `sdk/src/query/init-complex.ts` (the 3 heavyweight handlers: `initNewProject`, `initProgress`, `initManager`). All handlers return `{ data: <flat JSON> }` aligned with the CJS `bin/lib/init.cjs` surface. Test seams: `sdk/src/query/init.test.ts` (basic handlers + withProjectRoot precedence), `sdk/src/query/init-complex.test.ts` (complex handlers + progress/manager precedence regression #2674 + workstream scoping regression #3196), `sdk/src/query/init-workstream-milestone-op.test.ts` (initMilestoneOp + roadmapAnalyze + resolveQueryRuntimeContext workstream fallback). CJS CLI surface tested in `tests/init.test.cjs` and `tests/init-manager.test.cjs` (includes cross-milestone dependency regression #2267).
SDK Module owning the `init.*` family of query handlers that compose atomic SDK queries into the flat JSON bundles consumed by init workflows (`/gsd-execute-phase`, `/gsd-plan-phase`, `/gsd-verify-work`, `/gsd-new-project`, `/gsd-manager`, `/gsd-progress`, `/gsd-resume`, etc.). Divided into two source files: `sdk/src/handlers/init/composer.ts` (13 basic handlers plus `withProjectRoot` project-identity injection) and `sdk/src/handlers/init/complex.ts` (the 3 heavyweight handlers: `initNewProject`, `initProgress`, `initManager`). All handlers return `{ data: <flat JSON> }` aligned with the CJS `bin/lib/init.cjs` surface. Test seams: `sdk/src/query/init.test.ts` (basic handlers + withProjectRoot precedence), `sdk/src/query/init-complex.test.ts` (complex handlers + progress/manager precedence regression #2674 + workstream scoping regression #3196), `sdk/src/query/init-workstream-milestone-op.test.ts` (initMilestoneOp + roadmapAnalyze + resolveQueryRuntimeContext workstream fallback). CJS CLI surface tested in `tests/init.test.cjs` and `tests/init-manager.test.cjs` (includes cross-milestone dependency regression #2267).
### CJS Command Router Adapter Module
Compatibility Adapter Module for `gsd-tools.cjs` command families. Uses generated command metadata plus small argument shapers to route to CJS handlers, rather than calling SDK Command Topology directly. Preserves CJS compatibility startup while reducing hand-written router drift. Per-family migration to call the **Sync Runtime Bridge Module**'s `executeForCjs` in-process — eliminating the remaining parallel CJS handler implementations — is the active work of #3524 Phase 5; the primitive itself ships in #3555, with each canonical command family (`state.*`, `verify.*`, `init.*`, `phase.*`, `phases.*`, `validate.*`, `roadmap.*`, `frontmatter.*`, `config.*`) routing through `executeForCjs` in its own follow-up enhancement.

View File

@@ -11,7 +11,7 @@
*
* @example
* ```typescript
* import { initProgress, initManager } from './init-complex.js';
* import { initProgress, initManager } from './complex.js';
*
* const result = await initProgress([], '/project');
* // { data: { phases: [...], milestone_version: 'v3.0', ... } }
@@ -24,8 +24,8 @@ import { readFile } from 'node:fs/promises';
import { join, relative } from 'node:path';
import { homedir } from 'node:os';
import { loadConfig } from '../config.js';
import { resolveModel } from './config-query.js';
import { loadConfig } from '../../config.js';
import { resolveModel } from '../../query/config-query.js';
import {
detectRuntime,
planningPaths,
@@ -33,16 +33,16 @@ import {
phaseTokenMatches,
resolveAgentsDir,
toPosixPath,
} from './helpers.js';
} from '../../query/helpers.js';
import {
getMilestoneInfo,
extractCurrentMilestone,
extractNextMilestoneSection,
extractPhasesFromSection,
} from './roadmap.js';
import { agentSkills } from './skills.js';
import { withProjectRoot } from './init.js';
import type { QueryHandler } from './utils.js';
} from '../../query/roadmap.js';
import { agentSkills } from '../../query/skills.js';
import { withProjectRoot } from './composer.js';
import type { QueryHandler } from '../../query/utils.js';
// ─── Internal helpers ──────────────────────────────────────────────────────

View File

@@ -6,11 +6,11 @@
* follows the QueryHandler signature and returns { data: <flat JSON> }.
*
* Port of get-shit-done/bin/lib/init.cjs (13 of 16 handlers).
* The 3 complex handlers (new-project, progress, manager) are in init-complex.ts.
* The 3 complex handlers (new-project, progress, manager) are in complex.ts.
*
* @example
* ```typescript
* import { initExecutePhase, withProjectRoot } from './init.js';
* import { initExecutePhase, withProjectRoot } from './composer.js';
*
* const result = await initExecutePhase(['9'], '/project');
* // { data: { executor_model: 'opus', phase_found: true, ... } }
@@ -22,18 +22,18 @@ import { readFile, readdir } from 'node:fs/promises';
import { join, relative, basename } from 'node:path';
import { execSync } from 'node:child_process';
import { homedir } from 'node:os';
import { GSDError, ErrorClassification } from '../errors.js';
import { GSDError, ErrorClassification } from '../../errors.js';
import { loadConfig, type GSDConfig } from '../config.js';
import { resolveModel, MODEL_PROFILES } from './config-query.js';
import { maskIfSecret } from './secrets.js';
import { findPhase } from './phase.js';
import { getMilestonePhaseFilter } from './state.js';
import { roadmapGetPhase, getMilestoneInfo, extractCurrentMilestone, extractPhasesFromSection } from './roadmap.js';
import { determinePhaseStatus } from './progress.js';
import { planningPaths, normalizePhaseName, toPosixPath, resolveAgentsDir, detectRuntime } from './helpers.js';
import { generatePhaseSlug, assertSafeProjectCode } from './phase-lifecycle-policy.js';
import type { QueryHandler } from './utils.js';
import { loadConfig, type GSDConfig } from '../../config.js';
import { resolveModel, MODEL_PROFILES } from '../../query/config-query.js';
import { maskIfSecret } from '../../query/secrets.js';
import { findPhase } from '../../query/phase.js';
import { getMilestonePhaseFilter } from '../../query/state.js';
import { roadmapGetPhase, getMilestoneInfo, extractCurrentMilestone, extractPhasesFromSection } from '../../query/roadmap.js';
import { determinePhaseStatus } from '../../query/progress.js';
import { planningPaths, normalizePhaseName, toPosixPath, resolveAgentsDir, detectRuntime } from '../../query/helpers.js';
import { generatePhaseSlug, assertSafeProjectCode } from '../../query/phase-lifecycle-policy.js';
import type { QueryHandler } from '../../query/utils.js';
// ─── Internal helpers ──────────────────────────────────────────────────────

View File

@@ -34,8 +34,8 @@ import {
initIngestDocs, initResume, initVerifyWork, initPhaseOp, initTodos,
initMilestoneOp, initMapCodebase, initNewWorkspace,
initListWorkspaces, initRemoveWorkspace,
} from './init.js';
import { initNewProject, initProgress, initManager } from './init-complex.js';
} from '../handlers/init/composer.js';
import { initNewProject, initProgress, initManager } from '../handlers/init/complex.js';
export const FAMILY_HANDLERS: Record<string, Readonly<Record<string, QueryHandler>>> = {
state: {

View File

@@ -9,7 +9,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtemp, writeFile, mkdir, rm } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { initNewProject, initProgress, initManager } from './init-complex.js';
import { initNewProject, initProgress, initManager } from '../handlers/init/complex.js';
let tmpDir: string;
let previousGsdAgentsDir: string | undefined;

View File

@@ -11,7 +11,7 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { initMilestoneOp } from './init.js';
import { initMilestoneOp } from '../handlers/init/composer.js';
import { roadmapAnalyze } from './roadmap.js';
import { resolveQueryRuntimeContext } from './query-runtime-context.js';

View File

@@ -25,7 +25,7 @@ import {
initListWorkspaces,
initRemoveWorkspace,
initIngestDocs,
} from './init.js';
} from '../handlers/init/composer.js';
let tmpDir: string;

View File

@@ -1,6 +1,6 @@
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { SUPPORTED_RUNTIMES, type Runtime } from './model-catalog.js';
import { SUPPORTED_RUNTIMES, type Runtime } from '../model-catalog.js';
interface RuntimeAliasManifest {
[canonicalRuntime: string]: string[];
@@ -29,4 +29,3 @@ export function canonicalizeRuntimeName(value: unknown): Runtime | null {
if (typeof value !== 'string') return null;
return aliasToCanonical.get(normalizeRuntimeToken(value)) ?? null;
}