Severity: medium. Found by an adversarial-operator user test. Pre-existing, but it contradicts the exit-code contract #24 tightened.
--on-empty typo is only validated if a removal happens to empty an owner set. Otherwise it is accepted silently.
Repro
cot sync --on-empty typo --op 'remove_owner(*, @org/a)' --dry-run # repo base: exit 0
cot sync --on-empty typo --op 'remove_owner(*, @org/a)' --dry-run # repo crlf: exit 2
cot sync --on-empty typo --op 'remove_owner(*, @org/a)' --dry-run # repo three: exit 0
When it does fire: error: unknown --on-empty policy "typo" (governing file: .github/CODEOWNERS) at exit 2 — "this repo needs a human", naming a file that has nothing to do with the mistake.
The policy-file equivalent is handled exactly right, up front, exit 3, with a located message:
cot check --policy p.json # {"on_empty": "maybe"}
error: p.json:1:24: field "on_empty" has unknown value "maybe"; legal values are "error", "inherit", "unowned" # exit 3
A flag value is decidable from the arguments alone, so per CONTRIBUTING.md and docs/REFERENCE.md it belongs in the exit-3 class — the same class the policy field is already in. Today the two input paths disagree, and the flag path can quietly run a whole fleet with a meaningless value.
Suggested fix
Validate --on-empty at parse time in sync (and plan), before the repository is opened.
Severity: medium. Found by an adversarial-operator user test. Pre-existing, but it contradicts the exit-code contract #24 tightened.
--on-empty typois only validated if a removal happens to empty an owner set. Otherwise it is accepted silently.Repro
When it does fire:
error: unknown --on-empty policy "typo" (governing file: .github/CODEOWNERS)at exit 2 — "this repo needs a human", naming a file that has nothing to do with the mistake.The policy-file equivalent is handled exactly right, up front, exit 3, with a located message:
A flag value is decidable from the arguments alone, so per
CONTRIBUTING.mdanddocs/REFERENCE.mdit belongs in the exit-3 class — the same class the policy field is already in. Today the two input paths disagree, and the flag path can quietly run a whole fleet with a meaningless value.Suggested fix
Validate
--on-emptyat parse time insync(andplan), before the repository is opened.