Summary
In the scan command, when environments are passed as positional directory arguments, each environment label is derived with Path(d).stem. .stem strips the final dotted segment of the directory name, so any directory whose name contains a . is truncated — and two such directories can silently collide onto the same environment key.
Location
src/configdrift/cli.py, scan() (positional-dirs branch, ~line 270):
for d in dirs:
env_name = Path(d).stem # <-- drops everything after the first dot
dir_mapping[env_name] = d
Reproduction
configdrift scan ./envs/prod.us ./envs/prod.eu --baseline prod.us
Path("./envs/prod.us").stem == "prod" and Path("./envs/prod.eu").stem == "prod".
- Both directories map to the key
prod, so dir_mapping["prod"] is overwritten — only prod.eu survives. One environment is dropped with no warning.
--baseline prod.us then fails to match (the key is prod), so the command also errors with Baseline environment 'prod.us' not found.
Observed mapping (verified):
.stem: {'prod': './envs/prod.eu'} # 2 dirs -> 1 env (silent loss)
.name: {'prod.us': './envs/prod.us', 'prod.eu': ...} # 2 dirs -> 2 envs (correct)
Other examples: v1.2 -> v1, prod.config -> prod.
Impact
Silent loss of an environment and broken --baseline matching for any directory whose name contains a dot. Region/version-suffixed env directories (prod.us, prod.eu, v1.2) are realistic real-world names.
Suggested fix
Use Path(d).name (the full directory name) instead of Path(d).stem for directory-derived environment labels. The --config path (explicit environments: mapping) is unaffected.
Filed by the automated repo-improver maintenance rotation — surfacing only, no code change made.
Summary
In the
scancommand, when environments are passed as positional directory arguments, each environment label is derived withPath(d).stem..stemstrips the final dotted segment of the directory name, so any directory whose name contains a.is truncated — and two such directories can silently collide onto the same environment key.Location
src/configdrift/cli.py,scan()(positional-dirsbranch, ~line 270):Reproduction
Path("./envs/prod.us").stem == "prod"andPath("./envs/prod.eu").stem == "prod".prod, sodir_mapping["prod"]is overwritten — onlyprod.eusurvives. One environment is dropped with no warning.--baseline prod.usthen fails to match (the key isprod), so the command also errors withBaseline environment 'prod.us' not found.Observed mapping (verified):
Other examples:
v1.2->v1,prod.config->prod.Impact
Silent loss of an environment and broken
--baselinematching for any directory whose name contains a dot. Region/version-suffixed env directories (prod.us,prod.eu,v1.2) are realistic real-world names.Suggested fix
Use
Path(d).name(the full directory name) instead ofPath(d).stemfor directory-derived environment labels. The--configpath (explicitenvironments:mapping) is unaffected.Filed by the automated repo-improver maintenance rotation — surfacing only, no code change made.