* feat(#703): add --granularity override flag to /gsd:plan-phase Add a `--granularity <coarse|standard|fine>` flag to /gsd:plan-phase that overrides the configured planning granularity for a single invocation. The override is a new highest-priority tier above the existing precedence chain (granularities[phaseType] -> granularity -> planning.granularity -> 'standard') in resolveGranularityInternal; when the flag is absent, resolution is byte-for-byte unchanged. cmdInitPlanPhase now resolves with phaseType 'planning' so granularities.planning participates, and emits the resolved value in the init JSON, which the plan-phase workflow forwards to the planner prompt. Invalid values are rejected at the CLI boundary via a shared assertValidGranularityOverride helper. Closes #703 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#703): set changeset pr to 750 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ const {
|
||||
getRoadmapPhaseInternal,
|
||||
extractPhaseToken,
|
||||
resolveGranularityInternal,
|
||||
assertValidGranularityOverride,
|
||||
} = core;
|
||||
import { renderEffortForRuntime, RUNTIMES_WITH_FAST_MODE } from './model-catalog.cjs';
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
@@ -340,11 +341,12 @@ function cmdResolveModel(cwd: string, agentType: string | undefined, raw: boolea
|
||||
output(result, raw, model);
|
||||
}
|
||||
|
||||
function cmdResolveGranularity(cwd: string, phaseType: string | undefined, raw: boolean): void {
|
||||
function cmdResolveGranularity(cwd: string, phaseType: string | undefined, raw: boolean, override?: string): void {
|
||||
if (!phaseType) {
|
||||
error('phase-type required');
|
||||
}
|
||||
const granularity = resolveGranularityInternal(cwd, phaseType);
|
||||
assertValidGranularityOverride(override, error);
|
||||
const granularity = resolveGranularityInternal(cwd, phaseType, override);
|
||||
const result = (VALID_PHASE_TYPES).has(phaseType!)
|
||||
? { granularity, phase_type: phaseType }
|
||||
: { granularity, phase_type: phaseType, unknown_phase_type: true };
|
||||
|
||||
21
src/core.cts
21
src/core.cts
@@ -1590,7 +1590,12 @@ const VALID_GRANULARITIES = new Set(['coarse', 'standard', 'fine']);
|
||||
/**
|
||||
* Resolve the planning granularity for a phase type (#68).
|
||||
*/
|
||||
function resolveGranularityInternal(cwd: string, phaseType: string | null | undefined): string {
|
||||
function resolveGranularityInternal(cwd: string, phaseType: string | null | undefined, override?: string | null): string {
|
||||
if (override !== undefined && override !== null && override !== '') {
|
||||
if (VALID_GRANULARITIES.has(override)) {
|
||||
return override;
|
||||
}
|
||||
}
|
||||
const config = loadConfig(cwd);
|
||||
const configGranularities = config['granularities'] as Record<string, string> | null | undefined;
|
||||
const perPhase = (phaseType && configGranularities && typeof configGranularities === 'object')
|
||||
@@ -1610,6 +1615,19 @@ function resolveGranularityInternal(cwd: string, phaseType: string | null | unde
|
||||
return 'standard';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a CLI granularity override at the command boundary. Empty/null/undefined
|
||||
* are treated as "no override" (no-op). An invalid non-empty value calls `fail`.
|
||||
*/
|
||||
function assertValidGranularityOverride(
|
||||
override: string | null | undefined,
|
||||
fail: (msg: string) => never,
|
||||
): void {
|
||||
if (override !== undefined && override !== null && override !== '' && !VALID_GRANULARITIES.has(override)) {
|
||||
fail(`invalid granularity '${override}' (valid: ${[...VALID_GRANULARITIES].join(', ')})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* #3024 — Resolve a model for a specific dynamic-routing attempt.
|
||||
*/
|
||||
@@ -2200,6 +2218,7 @@ export = {
|
||||
resolveModelForTier,
|
||||
resolveGranularityInternal,
|
||||
VALID_GRANULARITIES,
|
||||
assertValidGranularityOverride,
|
||||
resolveEffortInternal,
|
||||
resolveFastModeInternal,
|
||||
resolveEffortForTier,
|
||||
|
||||
@@ -66,8 +66,8 @@ function routeInitCommand({ init, args, cwd, raw, error }: RouteInitCommandOptio
|
||||
init.cmdInitExecutePhase(cwd, args[2], raw, { validate: namedArgs['validate'], tdd: namedArgs['tdd'] });
|
||||
},
|
||||
'plan-phase': () => {
|
||||
const namedArgs = parseNamedArgs(args, [], ['validate', 'tdd']);
|
||||
init.cmdInitPlanPhase(cwd, args[2], raw, { validate: namedArgs['validate'], tdd: namedArgs['tdd'] });
|
||||
const namedArgs = parseNamedArgs(args, ['granularity'], ['validate', 'tdd']);
|
||||
init.cmdInitPlanPhase(cwd, args[2], raw, { validate: namedArgs['validate'], tdd: namedArgs['tdd'], granularity: namedArgs['granularity'] });
|
||||
},
|
||||
'new-project': () => init.cmdInitNewProject(cwd, raw),
|
||||
'new-milestone': () => init.cmdInitNewMilestone(cwd, raw),
|
||||
|
||||
@@ -29,6 +29,8 @@ import frontmatterMod = require('./frontmatter.cjs');
|
||||
const {
|
||||
loadConfig,
|
||||
resolveModelInternal,
|
||||
resolveGranularityInternal,
|
||||
assertValidGranularityOverride,
|
||||
findPhaseInternal,
|
||||
getRoadmapPhaseInternal,
|
||||
pathExistsInternal,
|
||||
@@ -375,12 +377,17 @@ function cmdInitPlanPhase(
|
||||
}
|
||||
}
|
||||
|
||||
const granularityOverride = options['granularity'] as string | undefined;
|
||||
assertValidGranularityOverride(granularityOverride, error);
|
||||
const granularity = resolveGranularityInternal(cwd, 'planning', granularityOverride || undefined);
|
||||
|
||||
const result: Record<string, unknown> = {
|
||||
researcher_model: resolveModelInternal(cwd, 'gsd-phase-researcher'),
|
||||
planner_model: resolveModelInternal(cwd, 'gsd-planner'),
|
||||
checker_model: resolveModelInternal(cwd, 'gsd-plan-checker'),
|
||||
|
||||
tdd_mode: options['tdd'] || config.tdd_mode || false,
|
||||
granularity,
|
||||
research_enabled: config.research,
|
||||
plan_checker_enabled: config.plan_checker,
|
||||
nyquist_validation_enabled: config.nyquist_validation,
|
||||
|
||||
Reference in New Issue
Block a user