feat(#910): federated config merge in config-loader (ADR-857 phase 3b) (#914)

Build the federated config merge: each capability owns its config-key slice
(ADR-857 decision 3 / ADR-894), and loadConfig merges them defensively. The
registry now emits a full configSchema index ({key:{owner,type,default,
description}}, generator-validated); a new src/federated-config.cts resolves
federated keys defensively (skip central keys -> pending-migration warning,
skip malformed slices -> warning never throw, else type-checked user override
?? default, with nested dotted-path lookup and enum validation); and loadConfig
applies the overlay on every return path.

Wired as a provably-empty no-op channel: every UI-pilot key is still central,
so validKeys is empty and loadConfig returns byte-identical output on all paths
(identity return when the overlay is empty; shared CONFIG_DEFAULTS never
mutated). Registry-only; no key is cut over; nothing in the live loop changes.

Closes #910

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-08 23:37:41 -04:00
committed by GitHub
parent 5bf77a527f
commit 6dbd895028
13 changed files with 1981 additions and 9 deletions

View File

@@ -74,6 +74,7 @@ export default tseslint.config(
'gsd-core/bin/lib/config-schema.cjs',
'gsd-core/bin/lib/model-profiles.cjs',
'gsd-core/bin/lib/model-resolver.cjs',
'gsd-core/bin/lib/federated-config.cjs',
'gsd-core/bin/lib/installer-migrations/002-codex-legacy-hooks-json.cjs',
'gsd-core/bin/lib/installer-migrations/003-rename-get-shit-done-to-gsd-core.cjs',
'gsd-core/bin/lib/observability/logger.cjs',