contract/issue-codes.json registers two codes twice, and one pair disagrees on severity:
bootstrap.adopted-venv-unusable :804 "severity": "warning"
bootstrap.adopted-venv-unusable :844 "severity": "error"
bootstrap.venv-recreated :820 (duplicate of :852)
Introduced by a6563d7 / f3208e1. Not a regression of any current work — found while reviewing the tan-cli#464 stage-2 commit.
Why it matters
The registry is a published contract. alp-sdk-vscode hard-asserts every entry's shape, and consumers key off severity to decide whether an issue is advisory or blocking. With a duplicate key, JSON parsing is last-wins, so the effective severity of bootstrap.adopted-venv-unusable is whichever entry happens to be later in the file — today error, silently overriding the warning someone wrote at :804. Reorder the file and the contract changes with no diff to any code.
Nothing catches it
tests/gates/test_every_issue_code_is_registered.py checks that every emitted code is registered and test_issue_code_registry_shape.py checks each entry's shape, but neither asserts key uniqueness — a duplicate key is invisible to both because json.load collapses it before the tests ever see it. All 292 codes match ISSUE_CODE_SHAPE = /^[a-z][a-z0-9-]*\.[a-z0-9-]+$/; the shape is fine, the multiplicity is not.
Fix
- Resolve each duplicate to one entry, deciding deliberately which severity is correct for
bootstrap.adopted-venv-unusable — the two entries were written for different situations and the answer is not automatically "the later one".
- Add a gate that reads the file with a duplicate-key-rejecting hook (e.g.
json.load(f, object_pairs_hook=...) raising on a repeated key) so the next duplicate fails loudly instead of silently winning.
The gate is the point. Without it this recurs the moment two changes append entries independently, which is exactly how these two arrived.
contract/issue-codes.jsonregisters two codes twice, and one pair disagrees on severity:Introduced by
a6563d7/f3208e1. Not a regression of any current work — found while reviewing the tan-cli#464 stage-2 commit.Why it matters
The registry is a published contract.
alp-sdk-vscodehard-asserts every entry's shape, and consumers key offseverityto decide whether an issue is advisory or blocking. With a duplicate key, JSON parsing is last-wins, so the effective severity ofbootstrap.adopted-venv-unusableis whichever entry happens to be later in the file — todayerror, silently overriding thewarningsomeone wrote at:804. Reorder the file and the contract changes with no diff to any code.Nothing catches it
tests/gates/test_every_issue_code_is_registered.pychecks that every emitted code is registered andtest_issue_code_registry_shape.pychecks each entry's shape, but neither asserts key uniqueness — a duplicate key is invisible to both becausejson.loadcollapses it before the tests ever see it. All 292 codes matchISSUE_CODE_SHAPE = /^[a-z][a-z0-9-]*\.[a-z0-9-]+$/; the shape is fine, the multiplicity is not.Fix
bootstrap.adopted-venv-unusable— the two entries were written for different situations and the answer is not automatically "the later one".json.load(f, object_pairs_hook=...)raising on a repeated key) so the next duplicate fails loudly instead of silently winning.The gate is the point. Without it this recurs the moment two changes append entries independently, which is exactly how these two arrived.