Fix config precedence: piloop-config.yaml should outrank env vars (CLI > YAML > env > defaults) #282
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
pi-loop's configuration precedence is currently
CLI flag > env var > YAML (piloop-config.yaml) > built-in defaults(ADR-013). Testing has shown this ordering is a mistake: env vars are meant to be a global fallback (machine/CI-wide),piloop-config.yamlis meant to be the project override (committed, PR-reviewed, team-shared), and CLI flags are the user's per-invocation override. The project override should rank above the global default, not below it.Fix: change the precedence to:
CI/machine environments that need to force a value can use a CLI
--flag(which stays top priority under both orderings) instead of relying on an ambient env var to override a committed YAML value.Background
ADR-013 (
docs/adr/013-piloop-config-yaml.md) explicitly considered and rejected this exact ordering under "Alternatives Considered":That tradeoff is no longer accepted — CI can force a value via
--flaginstead. This is being treated as correcting a testing-discovered mistake, not a recorded historical pivot:CHANGELOG.md,## Unreleased→### Fixed) to warn CI operators that env-var overrides ofpiloop-config.yamlwill stop working after this change.Scope — settings affected
The reorder only has real effect on settings present in both
piloop-config.yamland an env var. Apply the new precedence uniformly across all of them (no per-key hybrid — mirrors ADR-013's own rejection of per-key hybrid precedence as unnecessary complexity):modelPILOOP_MODELthinking-levelPILOOP_THINKING_LEVELauto-merge.enabledPILOOP_AUTO_MERGEauto-merge.timeout-msPILOOP_AUTO_MERGE_TIMEOUT_MSauto-merge.poll-msPILOOP_AUTO_MERGE_POLL_MSbash.default-timeoutPILOOP_BASH_DEFAULT_TIMEOUT_Sbash.max-timeoutPILOOP_BASH_MAX_TIMEOUT_Sjira.acceptance-criteria-field-idJIRA_ACCEPTANCE_CRITERIA_FIELD_IDgitlab.base-urlGITLAB_BASE_URLforgejo.base-urlFORGEJO_BASE_URLNot affected (confirmed via code search — no env-var counterpart exists):
source,git-host,label,max-issues(CLI/YAML-only settings)docs:section (glob lists, no env-var counterpart)Implementation details
src/config/services/configLoader.ts— invertmergeEnvSources.Currently:
This must invert to: YAML values win over env when YAML sets them (non-empty); env only fills keys YAML left unset. Update the associated docblocks (this function, the
EnvSourcetype doc, andloadConfig's doc) which currently describe "env wins over yamlEnv" — they need rewriting to describe the new precedence.src/cli/services/runCli.ts— rewritemodelSourcedetection (ADR-010 interaction).Current logic:
This assumes "YAML only wins when env is unset" (today's order). Once YAML outranks env,
modelSourcemust report'yaml'whenever YAML setsPILOOP_MODEL— regardless of whether env also sets it. Update the associated comment referencing ADR-010/ADR-013 precedence wording.Docs to update
docs/adr/013-piloop-config-yaml.md— edit Decision, Rationale, and Alternatives Considered sections in place to reflectCLI > YAML > env > defaults. Remove/replace the now-obsolete "File as repo source of truth" rejected-alternative entry (it's now the chosen design) and any "12-factor precedence" / "CI/machine env able to override the repo baseline" rationale language.docs/adr/010-per-run-model-override.md— check and update any wording describing YAML/env/flag precedence for--model.docs/adr/014-research-stage.md,docs/adr/015-documentation-sync-stage.md— check for precedence mentions and update if present.README.md,AGENTS.md,DESIGN.md,IMPLEMENTATION_PLAN.md— update the documented precedence chain (CLI flag > env var > YAML > built-in defaults→CLI flag > YAML > env var > built-in defaults).piloop-config.example.yaml— check/update any precedence-related comments.docs/design-auto-merge.md,docs/plan-B1-vertex-anthropic-provider.md— check for precedence mentions and update if present.(
.reviews/*.mdare historical review notes — out of scope, do not touch.)Changelog
Add a bullet to
CHANGELOG.mdunder## Unreleased→### Fixed, e.g.:Test plan
src/config/services/configLoader.test.ts— updatemergeEnvSourcesprecedence test cases to assert YAML wins over env when both are set; keep/extend the case where env fills a gap YAML leaves unset.src/cli/services/runCli.tsmodel-source tests — update to assertmodelSource === 'yaml'when both YAML and env setPILOOP_MODEL(previously asserted'env'in that case).npm run lint && npm testmust pass.Acceptance criteria
mergeEnvSourcesinverted so YAML values win over env values insrc/config/services/configLoader.ts; associated docblocks updated.modelSourcedetection insrc/cli/services/runCli.tsrewritten to report'yaml'when both YAML and env setPILOOP_MODEL.docs/adr/013-piloop-config-yaml.mdedited in place (Decision/Rationale/Alternatives Considered) — no new ADR, no supersession note.docs/adr/010-per-run-model-override.md,docs/adr/014-research-stage.md,docs/adr/015-documentation-sync-stage.mdchecked and updated if they reference the old precedence.README.md,AGENTS.md,DESIGN.md,IMPLEMENTATION_PLAN.md,piloop-config.example.yamlupdated to state the new precedence.docs/design-auto-merge.md,docs/plan-B1-vertex-anthropic-provider.mdchecked and updated if applicable.CHANGELOG.mdupdated with a new bullet under## Unreleased→### Fixed.configLoader.test.tsandrunCli.tsmodel-source tests updated to assert the new precedence.npm run lint && npm testpass.pi-loop opened and merged a pull request for this issue: #283