Skip to content

fix(config): one bad [[patches.agent]] target no longer bricks config load; add gc config lint (vc-quqf) - #84

Merged
bourgois merged 1 commit into
mainfrom
gc/vc-quqf
Jul 17, 2026
Merged

fix(config): one bad [[patches.agent]] target no longer bricks config load; add gc config lint (vc-quqf)#84
bourgois merged 1 commit into
mainfrom
gc/vc-quqf

Conversation

@bourgois

Copy link
Copy Markdown
Collaborator

What

  • Graceful degrade: composition now degrades an unresolvable [[patches.agent]] {dir,name} target to a warning — naming the offending patches.agent[N] index plus dir/name — skips that patch, and applies the rest. The warning is classified emit-worthy on the standard loadCityConfig path, so every gc command prints it; the skip is never silent.
  • Strictness preserved elsewhere: malformed entries (empty name) and typos in the other patch kinds ([[patches.rigs]], [[patches.providers]], [[patches.named_session]], [[patches.github_pr_monitor]]) keep the hard-error contract, as does any direct ApplyPatches caller.
  • New gc config lint: loads the fully resolved config (includes, packs, patches, overrides, --config extras), prints every composition warning, and exits non-zero on any unresolved agent-patch target or hard load error — wire into pre-commit/CI so the typo still blocks before merge.

Why

Incident vc-9wa (2026-06-30): a single [[patches.agent]] entry whose {dir,name} resolved to no agent in the merged config hard-failed LoadWithIncludes, so every gc command (hook/rig/bd-via-gc/scale) died at patches.agent[N] ... not found in merged config — one typo took the whole city down. This moves the loud-failure contract from load time (fatal, city-wide) to lint time (pre-commit/CI), per bead vc-quqf (voxist-city store; defense-in-depth follow-up to vc-9wa).

Validation

  • New tests: internal/config/unresolved_agent_patch_test.go, cmd/gc/cmd_config_lint_test.go, TestEmitLoadCityConfigWarningsIncludesUnresolvedAgentPatch (all written red-first)
  • go test ./internal/config/ green; targeted cmd/gc lint/emitter tests green; full make test-fast-parallel green (pre-push gate, all 8 jobs)
  • End-to-end smoke on the real binary in a scratch city: bad target → patches.agent[1]: agent "ghost-rig/platform-engineer" not found in merged config; patch skipped (dir=... name=...) printed, gc agent list exit 0, sibling patch still applied; gc config lint exit 1 naming the entry; clean config lint exit 0
  • CHANGELOG.md + docs/reference/cli.md updated

Reviewer: voxist.platform-architect gates this pre-merge (executor↔reviewer loop).

… load; add gc config lint (vc-quqf)

Incident vc-9wa (2026-06-30): a single [[patches.agent]] entry whose
{dir,name} resolved to no agent in the merged config hard-failed
LoadWithIncludes, so every gc command (hook/rig/bd-via-gc/scale) died at
"patches.agent[N] ... not found in merged config" — one typo took the
whole city down.

Composition now degrades that case to a warning naming the offending
patches.agent[N] index plus dir/name, skips the patch, and applies the
rest. The warning is classified emit-worthy on the standard
loadCityConfig path, so every gc command prints it — the skip is never
silent. Malformed entries (empty name) and typos in the other patch
kinds ([[patches.rigs]], [[patches.providers]], [[patches.named_session]],
[[patches.github_pr_monitor]]) keep the strict hard-error contract, as
does any direct ApplyPatches caller.

The loud-failure contract moves to the new `gc config lint`: it loads
the fully resolved config (includes, packs, patches, overrides,
--config extras), prints every composition warning, and exits non-zero
on any unresolved agent-patch target or hard load error — wire it into
pre-commit/CI so the typo still blocks before merge.
@bourgois
bourgois merged commit 182e993 into main Jul 17, 2026
2 checks passed
bourgois added a commit that referenced this pull request Jul 22, 2026
…int (vp-naxf)

PR #84 (182e993) added the 'gc config lint' command but did not
regenerate the productmetrics command census. The committed manifest
had no config-lint entry, so TestProductMetricsCommandCensusMatches-
ProductionBuiltins (and the Classify/Lifecycle tests deriving from it)
failed with census-mismatch on every push — the repo pre-push hook
runs the full cmd/gc suite, so this blocked ALL pushes to gascity.

Regenerate via 'go run ./cmd/gen-command-census': manifest gains
gc config lint (id 198), typed runtime table + decode catalog +
schema enum regenerated, test expected count 193->194. 'gen-command-
census --check' now passes; build + vet clean.
bourgois added a commit that referenced this pull request Jul 23, 2026
…I) (#102)

gc config lint (added by #84, 182e993) is a live command but was never
registered in the product-metrics command census manifest. Because
applyProductionProductMetricsCommandCensus is fail-closed, the uncovered live
command made validateProductMetricsCommandCensus return
'live command "gc config lint" is missing', which dropped ALL product-metrics
annotations and failed every product-metrics test (structural +
lifecycle + tagged-binary) on the real command tree.

This made Voxist/main chronically red in CI — both the Linux PR lane
('cmd/gc process' shards + 'CI / required' gate) and the Mac nightly lane,
daily since ~2026-07-20 — blocking every cmd/gc PR (e.g. #101). It only passed
on stale local checkouts that predated the command.

Add the manifest entry (id 198, classification config-lint, modeled on the
sibling gc config show/explain runnable leaves), bump next_id -> 199, and
regenerate the artifacts via gen-command-census. The id ledger appends
config-lint append-only (respects ValidateEvolution).

Verified in a clean Voxist/main worktree (reproduced the exact CI failure first):
- go run ./cmd/gen-command-census -check -> clean
- go test ./cmd/gc/ -run TestProductMetrics -count=1 -> ok (incl. tagged-binary)
bourgois added a commit that referenced this pull request Jul 26, 2026
…int (vp-naxf)

PR #84 (182e993) added the 'gc config lint' command but did not
regenerate the productmetrics command census. The committed manifest
had no config-lint entry, so TestProductMetricsCommandCensusMatches-
ProductionBuiltins (and the Classify/Lifecycle tests deriving from it)
failed with census-mismatch on every push — the repo pre-push hook
runs the full cmd/gc suite, so this blocked ALL pushes to gascity.

Regenerate via 'go run ./cmd/gen-command-census': manifest gains
gc config lint (id 198), typed runtime table + decode catalog +
schema enum regenerated, test expected count 193->194. 'gen-command-
census --check' now passes; build + vet clean.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant