Skip to content

loadConfig() falls back to ~/.gsd/defaults.json when no project config exists#1699

Open
rodzved wants to merge 2 commits intogsd-build:mainfrom
rodzved:enhancement/loadconfig-defaults-fallback
Open

loadConfig() falls back to ~/.gsd/defaults.json when no project config exists#1699
rodzved wants to merge 2 commits intogsd-build:mainfrom
rodzved:enhancement/loadconfig-defaults-fallback

Conversation

@rodzved
Copy link
Copy Markdown

@rodzved rodzved commented Apr 4, 2026

Enhancement PR


Linked Issue

Closes #1683


What this enhancement improves

loadConfig() in core.cjs — the central config resolution used by all GSD commands.

Before / After

Before:
When .planning/config.json is missing, loadConfig() returns hardcoded defaults. ~/.gsd/defaults.json is never consulted. Pre-project commands like map-codebase ignore user globals entirely.

.planning/config.json → if missing → hardcoded defaults

After:
When .planning/config.json is missing, loadConfig() reads ~/.gsd/defaults.json as an intermediate fallback before falling back to hardcoded defaults.

hardcoded defaults ← ~/.gsd/defaults.json ← .planning/config.json

How it was implemented

  • get-shit-done/bin/lib/core.cjs — In the catch block of loadConfig(), added ~/.gsd/defaults.json reading with the same merge pattern used by buildNewProjectConfig() in config.cjs. Supports both flat keys (model_profile) and nested keys (git.branching_strategy, workflow.research). Includes depthgranularity migration.
  • docs/CONFIGURATION.md — Updated Global Defaults section to clarify defaults.json applies to all commands, not just /gsd-new-project. Added merge order documentation.
  • tests/core.test.cjs — Added 3 new tests: defaults.json fallback, no-defaults.json fallback, nested key support. Sandboxed HOME in loadConfig describe block to isolate from developer's real ~/.gsd/defaults.json.
  • tests/commands.test.cjs — Sandboxed HOME in resolve-model describe block for test isolation.
  • tests/config.test.cjs ��� Sandboxed HOME for config-ensure-section test.

Testing

How I verified the enhancement works

  • All 2159 existing tests pass
  • 3 new tests verify:
    1. defaults.json values override hardcoded defaults when no config.json exists
    2. Hardcoded defaults are returned when neither config.json nor defaults.json exists
    3. Nested keys (git.*, workflow.*) are correctly resolved from defaults.json

Platforms tested

  • macOS
  • Windows (including backslash path handling)
  • Linux
  • N/A (not platform-specific)

Runtimes tested

  • Claude Code
  • Gemini CLI
  • OpenCode
  • Other: ___
  • N/A (not runtime-specific)

Scope confirmation

  • The implementation matches the scope approved in the linked issue — no additions or removals
  • If scope changed during implementation, I updated the issue and got re-approval before continuing

Checklist

  • Issue linked above with Closes #NNNPR will be auto-closed if missing
  • Linked issue has the approved-enhancement label — PR will be closed if missing
  • Changes are scoped to the approved enhancement — nothing extra included
  • All existing tests pass (npm test)
  • New or updated tests cover the enhanced behavior
  • CHANGELOG.md updated
  • Documentation updated if behavior or output changed
  • No unnecessary dependencies added

Breaking changes

None. The merge order is additive — existing .planning/config.json files take full precedence as before. Only the "no config.json exists" path changes, and that path currently returns hardcoded defaults which have no user-facing contract.

@rodzved rodzved requested a review from glittercowboy as a code owner April 4, 2026 19:51
@rodzved
Copy link
Copy Markdown
Author

rodzved commented Apr 4, 2026

Update: Refactored the catch fallback in loadConfig() to use a flat merge loop instead of duplicating every key individually.

Before: Each config key was listed explicitly in the return object (29 lines), meaning any new key added to loadConfig() would need to be duplicated in the fallback path — a maintenance trap.

After: The fallback iterates over userDefaults entries, flattens nested sections (git.*, workflow.*) to top-level keys, and merges them into the defaults object. New keys added to defaults are automatically picked up without changes to the fallback path.

All 2159 tests still pass.

@trek-e
Copy link
Copy Markdown
Collaborator

trek-e commented Apr 4, 2026

This PR needs a rebase onto main. PR #1708 just merged, which refactored loadConfig() defaults into CONFIG_DEFAULTS — the same function this PR modifies. After rebase, the catch block should reference CONFIG_DEFAULTS instead of the local defaults object (which no longer exists).

CI checks are also missing — likely due to the stale base.

@trek-e trek-e added the needs merge fixes CI failing or merge conflicts need resolution label Apr 4, 2026
rodzved added 2 commits April 5, 2026 04:59
Avoids maintenance trap where new config keys added to the try block
would need to be duplicated in the catch fallback path.
@rodzved rodzved force-pushed the enhancement/loadconfig-defaults-fallback branch from 994d675 to f7878f4 Compare April 4, 2026 21:00
@rodzved
Copy link
Copy Markdown
Author

rodzved commented Apr 4, 2026

Rebased onto main to pick up #1708 (CONFIG_DEFAULTS refactor). The catch block's { ...defaults } now spreads CONFIG_DEFAULTS via const defaults = CONFIG_DEFAULTS. All 2164 tests pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs merge fixes CI failing or merge conflicts need resolution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Apply ~/.gsd/defaults.json as fallback for pre-project commands

2 participants