loadEnvConfig discards any parsed env value that is falsy, so boolean env overrides to false never apply. Env vars are the highest-precedence config layer below argv, but they can only turn booleans ON, never OFF. Found in v0.81.0 (main @ 6de37e0).
Failure scenario
~/.gitconfig [coco] sets verbose = true (or conventionalCommits = true, includeBranchName = true, openInEditor = true).
- CI job runs
COCO_VERBOSE=false coco commit expecting quiet logs → parseEnvValue coerces 'false' to boolean false, then the loader drops it, and the gitconfig true wins. Same for COCO_CONVENTIONAL_COMMITS=false, etc. Documented precedence (env > git config, src/lib/config/utils/loadConfig.ts:45-53) is violated for every boolean-off override.
Root cause
src/lib/config/services/env.ts:88-90:
if (key === 'service' || !envValue) {
return
}
!envValue was presumably meant to skip empty strings, but after parseEnvValue has already converted 'false' → false (env.ts:225-226) it also drops legitimate boolean false (and would drop a numeric 0 for any future numeric top-level key).
Affected files
src/lib/config/services/env.ts (defect)
src/lib/config/utils/loadConfig.ts (precedence contract this breaks)
Suggested fix
Replace the falsy check with an explicit empty check: if (key === 'service' || envValue === undefined || envValue === '') return. parseEnvValue already returns undefined for unset vars, so false/0 flow through and override lower layers as documented.
Testing notes
Existing env tests only assert truthy overrides. Regression test: config layer with verbose: true + process.env.COCO_VERBOSE = 'false' → loadEnvConfig result has verbose === false (and active: true in the returnSource variant).
loadEnvConfigdiscards any parsed env value that is falsy, so boolean env overrides tofalsenever apply. Env vars are the highest-precedence config layer below argv, but they can only turn booleans ON, never OFF. Found in v0.81.0 (main @ 6de37e0).Failure scenario
~/.gitconfig[coco]setsverbose = true(orconventionalCommits = true,includeBranchName = true,openInEditor = true).COCO_VERBOSE=false coco commitexpecting quiet logs →parseEnvValuecoerces'false'to booleanfalse, then the loader drops it, and the gitconfigtruewins. Same forCOCO_CONVENTIONAL_COMMITS=false, etc. Documented precedence (env > git config,src/lib/config/utils/loadConfig.ts:45-53) is violated for every boolean-off override.Root cause
src/lib/config/services/env.ts:88-90:!envValuewas presumably meant to skip empty strings, but afterparseEnvValuehas already converted'false'→false(env.ts:225-226) it also drops legitimate booleanfalse(and would drop a numeric0for any future numeric top-level key).Affected files
src/lib/config/services/env.ts(defect)src/lib/config/utils/loadConfig.ts(precedence contract this breaks)Suggested fix
Replace the falsy check with an explicit empty check:
if (key === 'service' || envValue === undefined || envValue === '') return.parseEnvValuealready returnsundefinedfor unset vars, sofalse/0flow through and override lower layers as documented.Testing notes
Existing env tests only assert truthy overrides. Regression test: config layer with
verbose: true+process.env.COCO_VERBOSE = 'false'→loadEnvConfigresult hasverbose === false(andactive: truein the returnSource variant).