Summary
lading/commands/bump_output.py is a dead, divergent duplicate of formatting
logic that lading/commands/bump.py re-implements inline. The two copies have
drifted apart, which has already produced a latent output bug.
Evidence
bump_output.py defines BumpChanges, _build_changes_description,
_format_no_changes_message, _format_header, _format_manifest_path, and
_format_result_message. bump.py defines its own inline copies of every one of
them (bump.py:84-154, 396-425) and uses those. bump_output is imported only
by tests (tests/unit/test_bump_command_internals.py) and is described by
docs/developers-guide.md:93-96 as if it were the real home of the formatting.
The copies have diverged:
bump_output.BumpChanges has 3 fields (manifests, documents, lockfiles);
bump.BumpChanges has 4 (adds transposed_readmes). README transposition was
only ever added to the inline copy.
bump_output._build_changes_description (bump_output.py:73-77) renders 3+
categories with an Oxford comma ("A, B, and C"); bump._build_changes_description
(bump.py:118) uses " and ".join(...), producing "A and B and C and D" for the
now-four categories — grammatically wrong output that the bump_output version was
evidently written to fix but was never wired in.
Fix
Complete the extraction the docs already describe:
- Add
transposed_readmes to bump_output.BumpChanges and _format_result_message,
and port _has_changes.
- Delete the inline copies from
bump.py and import from bump_output.
- Update tests to target the single home.
This removes ~120 lines of duplication and fixes the description grammar.
Canonical implementation mandate
- One canonical home:
lading.commands.bump_output is the sole owner of
BumpChanges and all bump result-message formatting. No other module may
re-declare them.
- Document it: record the canonical home and its responsibility in
docs/developers-guide.md (correct the existing §describing bump_output).
- Property tests (Hypothesis): generate arbitrary combinations of changed
categories (0–4 present, varying counts) and assert the description is
grammatically well-formed (correct Oxford-comma joining for 1, 2, and 3+
categories) and that every changed path appears exactly once with the correct
suffix tag.
- Snapshot assertions (syrupy
.ambr): snapshot the full rendered result
message for representative cases (no changes, single category, all four
categories, dry-run vs apply). Reuse/extend
tests/unit/__snapshots__/test_bump_command_internals.ambr.
- Model checking (CrossHair): applicable to the pure helpers
(_build_changes_description, _format_header, _format_manifest_path);
add contracts and run CrossHair over them.
Acceptance criteria
Summary
lading/commands/bump_output.pyis a dead, divergent duplicate of formattinglogic that
lading/commands/bump.pyre-implements inline. The two copies havedrifted apart, which has already produced a latent output bug.
Evidence
bump_output.pydefinesBumpChanges,_build_changes_description,_format_no_changes_message,_format_header,_format_manifest_path, and_format_result_message.bump.pydefines its own inline copies of every one ofthem (
bump.py:84-154,396-425) and uses those.bump_outputis imported onlyby tests (
tests/unit/test_bump_command_internals.py) and is described bydocs/developers-guide.md:93-96as if it were the real home of the formatting.The copies have diverged:
bump_output.BumpChangeshas 3 fields (manifests,documents,lockfiles);bump.BumpChangeshas 4 (addstransposed_readmes). README transposition wasonly ever added to the inline copy.
bump_output._build_changes_description(bump_output.py:73-77) renders 3+categories with an Oxford comma (
"A, B, and C");bump._build_changes_description(
bump.py:118) uses" and ".join(...), producing"A and B and C and D"for thenow-four categories — grammatically wrong output that the
bump_outputversion wasevidently written to fix but was never wired in.
Fix
Complete the extraction the docs already describe:
transposed_readmestobump_output.BumpChangesand_format_result_message,and port
_has_changes.bump.pyand import frombump_output.This removes ~120 lines of duplication and fixes the description grammar.
Canonical implementation mandate
lading.commands.bump_outputis the sole owner ofBumpChangesand all bump result-message formatting. No other module mayre-declare them.
docs/developers-guide.md(correct the existing §describingbump_output).categories (0–4 present, varying counts) and assert the description is
grammatically well-formed (correct Oxford-comma joining for 1, 2, and 3+
categories) and that every changed path appears exactly once with the correct
suffix tag.
.ambr): snapshot the full rendered resultmessage for representative cases (no changes, single category, all four
categories, dry-run vs apply). Reuse/extend
tests/unit/__snapshots__/test_bump_command_internals.ambr.(
_build_changes_description,_format_header,_format_manifest_path);add contracts and run CrossHair over them.
Acceptance criteria
bump.pycontains no formatting/BumpChangesdefinitions; it imports frombump_output.bump_output.BumpChangesincludestransposed_readmes;_format_result_messagerenders it.docs/developers-guide.mdnamesbump_outputas the canonical home.