docs(cli): record and accept ADR-0067 on the exit codes as a published contract - #397
Merged
Merged
Conversation
Naming the exit codes was a habit; declaring the set closed is a decision, because it binds every command added after it. ADR-0067 records that. @Reefact took the decision and asked for the status flip to be made on their behalf, so the record lands accepted; it names them as the decision maker, which is what it named as a draft. Writing it surfaced a fact worth more than the record. The set is already published — the catalog-versioning reference carries an exit-code table per command, and the CI guide's pipelines branch on the code — so the promise exists whether or not it is written down. But the set is not closed today: command-line parsing is delegated to Spectre.Console.Cli, and an unknown subcommand exits -1 (255 to a POSIX shell) writing nothing to either stream. That fifth value is in no table, was chosen by a dependency, and the 2026-07-20 architecture audit had already flagged it. Verified against the built binary, not inferred. So the ADR corrects a claim rather than restating one: PR #396 described the set as closed, and it is not. Closing it is listed as a follow-up rather than decided here — which value an unparseable line should return is its own trade-off, and that is specification. The record also states what it cannot do: nothing checks the rule, a future command can return 3 and compile. That is the arrangement ADR-0056 warns about, accepted here because the surface is small and reviewed, and written into Risks rather than left for a reader to discover. Per ADR-0057 the header carries both states: Proposed stays and Accepted is added below it, never overwriting. Both dates read 2026-07-31 because both happened today — the log's way of saying a decision was ratified on sight rather than that one date stands for two unknowns. Indexed in the ADR README, English and French twins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SuSBsGG7wMPMnSeTHKZAom
Reefact
force-pushed
the
claude/anyarray-distinct-nameof-8m5won
branch
from
July 31, 2026 08:27
f2c7962 to
018397a
Compare
This was referenced Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follows #396, which introduced
ExitCodesand raised the question of whether the CLI's exit-code set is a compatibility promise. ADR-0067 records that it is. It was draftedProposed; @Reefact took the decision and asked for the status flip to be made on their behalf, so it lands hereAccepted.Writing it turned up something worth more than the record itself: the set is already published, and it is not actually closed. The catalog-versioning reference carries an exit-code table per command and the CI guide's example pipelines branch on the code — so the promise exists whether or not it is written down. But command-line parsing is delegated to Spectre.Console.Cli, and an unknown subcommand exits
-1(255 to a POSIX shell) writing nothing to either stream. That fifth value appears in no table and was chosen by a dependency. The 2026-07-20 architecture and design audit had already flagged it.Verified against the built binary rather than inferred:
So this ADR corrects a claim rather than restating one: #396's description called the set closed, and it is not.
Type of change
Changes
ADR-0067 | Treat the CLI's exit codes as a closed, published contract, with its French twin, following the template and the banner convention.Proposed:line is untouched andAccepted:is added below it. Both dates read 2026-07-31 because both states happened today — the log's way of saying a decision was ratified on sight, not that one date stands for two unknowns.Accepted.Two choices inside the record worth flagging:
-1hole is a follow-up, not part of the decision. Which value an unparseable command line should return — reuse1, or reserve a distinct code so a pipeline can tell a bad invocation from a failed run — is its own trade-off, and that is specification rather than decision.3and compile, and no test or analyzer will object. That is the arrangement ADR-0056 warns about, accepted here because the surface is small and reviewed — written intoRisksrather than left for a reader to find out.Numbering note: this was drafted as 0066, which a merge took in the meantime; renumbered to 0067 with both filenames, both banners and the index updated.
Testing
dotnet build FirstClassErrors.slndotnet test FirstClassErrors.slnFirstClassErrors.Analyzers.UnitTests)Documentation-only: no code changed, so no build or test was run for this branch. The CLI behaviour quoted above was observed on the binary built from
mainat40505c7.Documentation
doc/updateddoc/handwritten/for-users/README.fr.md) updated if user-facing behavior changedThe pull request is the documentation change — an ADR pair plus its index entry. No user-facing behavior changed, so the user documentation is untouched; the exit-code tables it already carries are what the ADR records as the published contract.
Architecture decisions
Proposed: ADR-0067Drafted
Proposedand flipped toAcceptedonly on @Reefact's explicit instruction in this session — the decision is theirs and the record names them as the decision maker. The merge stays with them.Related issues
None. Follows #395 and #396.