Files
msd-core/.changeset/archived/3577-adr-violations-and-validation-port.md
Tom Boucher 8616839cab chore: archive 463 shipped changeset fragments before wiring render (#714)
CHANGELOG promotion was a manual operator step that was never run, so 463
fragments for work already shipped in <=1.3.1 accumulated in .changeset/.
Their notes were already hand-curated into the dated [1.2.0]/[1.3.0]/[1.3.1]
CHANGELOG sections (#690 backfill, PR #694). Rendering them now would
duplicate and mis-attribute shipped work.

Move them to .changeset/archived/ (read non-recursively by all changeset
tooling, so never rendered), keeping only the 3 genuinely-unreleased
fragments at the top level. Prep for wiring `render` into the release
finalize job (#690 follow-up).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 14:53:17 -04:00

4.3 KiB

type, pr
type pr
Fixed 3577

Phase 6 ADR/PRD compliance: out-of-seam Modules removed from SDK catalog; CJS-only verbs dispatch direct — verify.codebase-drift and the eight intel.* verbs were wrongly bound in the SDK catalog/manifests, in violation of docs/adr/3524-cjs-sdk-hard-seam.md §3 and docs/prd/3524-cjs-sdk-hard-seam.md L160 which list drift, intel, graphify, gsd2-import, schema-detect, fallow-runner, installer-migrations as CJS-only ("...keep their in-process CJS implementations because no SDK counterpart exists"). The verifyCodebaseDrift SDK stub then execFileSync'd back to gsd-tools verify codebase-drift, which the router routed back through the SDK bridge — an infinite recursion that forked hundreds of node processes on the remote 64 GiB docker host before manual kill. All wrongly-bound entries removed; the CJS router and gsd-tools.cjs already had direct CJS dispatch paths for these verbs that are now the only path.

Phase 6 config-ensure-section cutover via catalog rebind, not CJS fallback — restored the legacy "no-arg full default config.json init" contract on the SDK path by binding the catalog entry 'config-ensure-section' to configNewProject (whose no-args branch produces the same shape as the legacy ensureConfigFile → buildNewProjectConfig chain). The original Phase 6 binding to the new configEnsureSection handler (single-section ensure, requires args[0]=sectionName) broke every CLI caller, which all invoke the no-arg form.

configNewProject defaults sourced from canonical Configuration Module manifest — replaced the hardcoded duplicate defaults object with a derivation from sdk/shared/config-defaults.manifest.json (exported as CONFIG_DEFAULTS from sdk/src/configuration/index.ts). The previous duplicate had drifted from the manifest — omitted workflow.{ai_integration_phase, tdd_mode, human_verify_mode, pattern_mapper, plan_bounce*, auto_prune_state, subagent_timeout, security_*, post_planning_gaps}, git.create_tag, claude_md_path, planning.*, graphify.*, mode, resolve_model_ids, context_window. Closes the same DEFECT.PORT-DRIFT.cjs-sdk family the ADR was written to prevent.

SDK configSet value-validation port from CJS cmdConfigSet — added the missing enum/shape validators that the CJS handler enforced: workflow.drift_action (warn|auto-remap), workflow.drift_threshold (positive integer), workflow.human_verify_mode (mid-flight|end-of-phase), statusline.context_position (front|end), code_quality.fallow.scope (phase|repo), code_quality.fallow.profile (minimal|standard|strict), and review.default_reviewers (array of slug strings matching ^[a-zA-Z0-9_-]+$, normalized to lowercase-unique, with the normalized value persisted to disk).

Init handlers honor --tdd flag and workflow.subagent_timeout — initExecutePhase and initPlanPhase now parse the --tdd boolean override (matching parseNamedArgs(args, [], ['validate', 'tdd']) in the CJS router and options.tdd || config.tdd_mode || false in the CJS handler), and initMapCodebase reads subagent_timeout from the canonical workflow.subagent_timeout location with the manifest-mandated 300000 default instead of an undefined fallback.

roadmap.analyze surfaces mode per phase — extracts the same **Mode:** field that roadmapGetPhase already parses, so consumers can read MVP-mode flagging from either query handler without divergence.

SDK phaseComplete performs auto-prune of STATE.md when configured — ported the workflow.auto_prune_state === true branch from CJS cmdPhaseComplete, calling statePrune(['--keep-recent', '3', '--silent'], ...) so completing phase N actually removes stale [Phase 1..N-3] decisions instead of leaving them forever. (#2087)

SDK initRemoveWorkspace errors via thrown GSDError — returning { data: { error } } was treated as success by the CLI output path; the no-name and workspace-not-found branches now throw GSDError(..., ErrorClassification.Validation) so the CLI returns non-zero and writes the message to stderr.

SDK frontmatterGet parses --field <name> — the CLI invocation frontmatter get <file> --field phase was passing args = [file, '--field', 'phase']; the handler treated args[1] as the field name and saw the literal string --field. Now handles both --field <name> and positional args[1].