feat(config): add HARPER_CONFIG as the recommended way to set config from the environment - #1238
Conversation
…nv var HARPER_CONFIG takes a JSON config object and applies it as a merge on top of the existing configuration: it sets exactly the keys it names (at any depth), reasserts them on every boot (winning over the config file, user edits, and HARPER_DEFAULT_CONFIG), and yields only to HARPER_SET_CONFIG. Precedence ladder (later wins): HARPER_DEFAULT_CONFIG < config file / user edits < HARPER_CONFIG < HARPER_SET_CONFIG Omitted keys are restored to their pre-override originals via the existing snapshot machinery (same as DEFAULT/SET). Individual HARPER_* env vars still win over HARPER_CONFIG (arg filtering remains SET-only). The $union array directive works through HARPER_CONFIG via the shared apply path. Closes #1214 (sub-issue of #1097) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Reviewed; no blockers found. |
|
Cross-model review status for this PR: the outside-model legs were rate-limited this round —
So a genuine non-Claude review did not land this round. Happy to re-run a Gemini/Codex pass once the limits reset (Gemini ~24h) before merge if you'd like that belt-and-suspenders — otherwise this is resting on the domain pass + clean Claude-bot pass + your human review. 🤖 Posted by Claude on Nathan's behalf |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
…or apply The applyRuntimeEnvVarConfig wrapper short-circuited whenever no config env vars were set, returning before applyRuntimeEnvConfig could run its snapshot-based cleanup. So removing all three vars after a prior boot left the last-applied values persisted and the snapshot uncleared (pre-existing for DEFAULT/SET; HARPER_CONFIG makes removal routine). Add hasPersistedEnvConfigState(rootPath) and only short-circuit when no env vars AND no prior state; otherwise delegate so originals are restored and the snapshot cleared. Resolve rootPath before the guard (warn only when there is config to apply). Raised by Codex review on PR #1238. Refs #1214 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Re: the Codex review — nice catch on the state-unaware early return in Fixed in 826a3a6: the wrapper now skips only when there are no config env vars and 🤖 Posted by Claude on Nathan's behalf |
Summary
Adds
HARPER_CONFIGas the recommended environment variable for setting Harper configuration. It takes a JSON config object and applies it as a merge on top of the existing configuration: it sets exactly the keys it names (at any depth), reasserts them on every boot, and yields only toHARPER_SET_CONFIG.Closes #1214 (sub-issue of #1097). Builds on the
$uniondirective from #1213.Precedence (later wins)
HARPER_CONFIG(recommended)HARPER_DEFAULT_CONFIGHARPER_SET_CONFIGBehavior (the four decisions, confirmed with @heskew)
DEFAULT.HARPER_CONFIGrestores the pre-override original (or deletes the key ifHARPER_CONFIGintroduced it), via the existing snapshot machinery — symmetric withDEFAULT/SET.HARPER_*env vars win overHARPER_CONFIGfor the keys they name (filterArgsAgainstRuntimeConfigstays SET-only — unchanged).Implementation
'HARPER_CONFIG'ConfigSource+ snapshot slot; applied viaapplyConfigLayerwithrespectSources: ['HARPER_SET_CONFIG']+storeOriginals, same at install and runtime.applyRuntimeEnvConfig,composeConfigFromEnv(clone/pre-install), theconfigUtils.jsearly-return guard, and the restore-original deletion/cleanup paths.$unionflows throughHARPER_CONFIGfor free via the shared apply path.Where to look
applyRuntimeEnvConfig) — this PR moves all removed-var cleanups ahead of the applies. A domain review caught that the original apply-then-cleanup order gave a one-boot window where removingHARPER_SET_CONFIG(whileHARPER_CONFIGstill named the path) dropped the value to the file original for one boot before self-healing. Reordering makesHARPER_CONFIGreclaim the path the same boot. Behavior is unchanged for present-var and DEFAULT/SET-only cases (a removed var's own apply is a no-op). New regression test: "reclaims a path the SAME boot HARPER_SET_CONFIG is removed".HARPER_CONFIGandHARPER_SET_CONFIGname the same path in one boot,HARPER_CONFIG's snapshot records the value it set beforeSEToverrode it, whilesources[path]ends upHARPER_SET_CONFIG. No data loss — deletion paths gate on current source ownership (verified) — but the snapshot is momentarily not authoritative for that path. Left as-is to avoid complicatingbuildSnapshot; flagging for the reviewer.Testing
13 new unit tests in
unitTests/config/harperConfigEnvVars-config.test.js: merge/sibling preservation, source+original tracking,$union, all four precedence relationships (file, user-edit reassert, DEFAULT, SET incl. not stealing SET-owned paths), the SET→CONFIG same-boot hand-back, drop-key restore, var-removal cleanup, introduced-key deletion, SET-only arg filtering, and four-layercomposeConfigFromEnvordering. FullunitTests/config/**suite green (174 passing); build + lint + format clean.Review note
Cross-model review was domain-only this round: Codex hit its weekly session limit and the local Gemini (
agy) leg hangs in this environment. The Harper-domain pass (which found the ordering issue above) ran; the GitHub Gemini Code Assist + Claude review bots will provide the outside-model legs on this PR.🤖 Generated with Claude Code (agent: Claude Opus 4.8)