A phase directory can hold more than one `*-VERIFICATION.md` — an ad-hoc `03-CORRECTION-VERIFICATION.md` worksheet beside the real `03-VERIFICATION.md`. Discovery took the alphabetically-first match, so the worksheet won and the phase could report `missing` while a passing report sat next to it. The issue named two copies. There were seven, in four grammars: two `.sort()[0]` sites in the verification module, three `.find()` over UNSORTED readdir order (phase status, and `verification_path` twice — filesystem-dependent, so two machines on one commit could disagree), and two in shell. All seven now route through one exported `resolveVerificationFile`; the shell copies via a new `verification resolve-file` verb rather than hand-rolling the rule an eighth time. Fixing five of seven would have been worse than fixing none: the verify-work workflow is a WRITER that stamps `status: passed` onto the file it picks, so canonical-aware readers plus an alphabetical writer means the human_needed→passed canonicalization silently no-ops forever while the worksheet gets stamped. That divergence did not exist on next. The first resolver was itself a regression — it preferred ANY canonically-shaped name over the phase's own report, so a stray cross-phase or sentinel-numbered file outranked it. The global-canonical preference was removed rather than narrowed; the rule is pinned to the phase token via `PHASE_NUMBER_TOKEN_SOURCE`, its existing owner. Fixed in passing: the transition workflow's awk guarded on `NR==1` instead of `FNR==1`, so across a multi-file glob it armed only on the first file — a leading worksheet with no frontmatter blocked transition even when the canonical report passed. Also removed a U+00AD soft hyphen introduced earlier on this branch. Five broader-grammar AGGREGATE scans are deliberately out of scope — a different defect class (phase-unscoped scanning), tracked as #3511. Closes #3357 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
59 lines
2.1 KiB
TypeScript
59 lines
2.1 KiB
TypeScript
/**
|
|
* Verification-status subcommand router.
|
|
* Routes `verification.status <phaseDir>` to verification.cmdVerificationStatus.
|
|
*
|
|
* Note: `verification` (reads verifier-emitted status) is distinct from `verify`
|
|
* (runs verification checks like plan-structure/artifacts). Keep them separate.
|
|
*
|
|
* ADR-457 build-at-publish: source in src/verification-command-router.cts,
|
|
* compiled to gsd-core/bin/lib/verification-command-router.cjs (gitignored).
|
|
*/
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
import cjsCommandRouterAdapter = require('./cjs-command-router-adapter.cjs');
|
|
const { routeCjsCommandFamily } = cjsCommandRouterAdapter;
|
|
|
|
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
|
|
interface VerificationModule {
|
|
cmdVerificationStatus(cwd: string, phaseDirArg: string | undefined, raw: boolean): void;
|
|
cmdVerificationResolveFile(cwd: string, phaseDirArg: string | undefined, raw: boolean): void;
|
|
}
|
|
|
|
interface RouteVerificationCommandOptions {
|
|
verification: VerificationModule;
|
|
args: string[];
|
|
cwd: string;
|
|
raw: boolean;
|
|
error: (message: string) => void;
|
|
}
|
|
|
|
// ─── Implementation ───────────────────────────────────────────────────────────
|
|
|
|
const VERIFICATION_SUBCOMMANDS = ['status', 'resolve-file'];
|
|
|
|
function routeVerificationCommand({
|
|
verification,
|
|
args,
|
|
cwd,
|
|
raw,
|
|
error,
|
|
}: RouteVerificationCommandOptions): void {
|
|
routeCjsCommandFamily({
|
|
args,
|
|
subcommands: VERIFICATION_SUBCOMMANDS,
|
|
unsupported: {},
|
|
error,
|
|
unknownMessage: (_subcommand: string, available: string[]) =>
|
|
`Unknown verification subcommand. Available: ${available.join(', ')}`,
|
|
handlers: {
|
|
status: () => verification.cmdVerificationStatus(cwd, args[2], raw),
|
|
'resolve-file': () => verification.cmdVerificationResolveFile(cwd, args[2], raw),
|
|
},
|
|
});
|
|
}
|
|
|
|
export = {
|
|
routeVerificationCommand,
|
|
};
|