Problem
The CLI's command/operation counts are the same fact duplicated by hand across
many files. Only the code-side count is guarded by a test; every doc copy is
updated manually and rots silently.
Removing thread.delete (branch feat/remove-thread-delete) required editing
7 files just to keep the counts consistent. The domain heading in
docs/octo-cli-design.md (## Domain 4: thread (... 9 commands)) was nearly
missed — even a careful Linus-style review of the diff failed to catch it, and
it was only found by a follow-up grep. Every future add/remove of an operation
will eventually drift one of these copies.
Where the count lives today
internal/registry/loader_test.go — per-domain + total op counts. ✅ The only
test-guarded copy; effectively the code-side source of truth.
CLAUDE.md — ## Command Structure (7 domains, NN operations / NN commands ...)
README.md — the command tree — NN operations across 7 domains
CHANGELOG.md — per-release operation counts in the release notes
docs/octo-cli-design.md — three independent copies: domain headings
(Domain N: x (M commands)), the per-command numbered table (#1..N, where
deleting one row forces renumbering every later row), and the summary table
(Total / per-domain / App-blocked counts / percentages)
skills/octo-messaging/SKILL.md — ## 3. \thread` — N commands`
Why it matters
The single source of truth is the embedded OpenAPI specs
(internal/registry/specs/*.json). registry already derives these counts at
runtime (ListOperations, EnabledOperations, ServiceDisabled). The numbers
hand-copied into prose/docs are derived data with no guard, so they drift the
moment someone forgets one of the 6+ sites.
Proposed direction (open to alternatives)
- Drop the hard-coded numbers from prose where they add no value (e.g. README
/ domain headings don't need an exact count). Cheapest, removes most copies.
- Add a CI/test guard that diffs the documented counts against
registry
output, failing the build on drift. Keeps the numbers, kills silent rot.
- Generate the count-bearing sections (design-doc tables, domain headings)
from the specs. Removes the duplication entirely, highest effort.
Option 2 is the smallest guard; option 1+2 together is probably the sweet spot.
Notes
- Surfaced while removing
thread.delete to align the CLI with the "bots get no
destructive operations" convention (branch feat/remove-thread-delete).
- The numbered command table in
octo-cli-design.md is the most brittle piece:
it encodes a global 1..N ordering that must be re-sequenced on any removal.
Problem
The CLI's command/operation counts are the same fact duplicated by hand across
many files. Only the code-side count is guarded by a test; every doc copy is
updated manually and rots silently.
Removing
thread.delete(branchfeat/remove-thread-delete) required editing7 files just to keep the counts consistent. The domain heading in
docs/octo-cli-design.md(## Domain 4: thread (... 9 commands)) was nearlymissed — even a careful Linus-style review of the diff failed to catch it, and
it was only found by a follow-up grep. Every future add/remove of an operation
will eventually drift one of these copies.
Where the count lives today
internal/registry/loader_test.go— per-domain + total op counts. ✅ The onlytest-guarded copy; effectively the code-side source of truth.
CLAUDE.md—## Command Structure (7 domains, NN operations / NN commands ...)README.md—the command tree — NN operations across 7 domainsCHANGELOG.md— per-release operation counts in the release notesdocs/octo-cli-design.md— three independent copies: domain headings(
Domain N: x (M commands)), the per-command numbered table (#1..N, wheredeleting one row forces renumbering every later row), and the summary table
(Total / per-domain / App-blocked counts / percentages)
skills/octo-messaging/SKILL.md—## 3. \thread` — N commands`Why it matters
The single source of truth is the embedded OpenAPI specs
(
internal/registry/specs/*.json).registryalready derives these counts atruntime (
ListOperations,EnabledOperations,ServiceDisabled). The numbershand-copied into prose/docs are derived data with no guard, so they drift the
moment someone forgets one of the 6+ sites.
Proposed direction (open to alternatives)
/ domain headings don't need an exact count). Cheapest, removes most copies.
registryoutput, failing the build on drift. Keeps the numbers, kills silent rot.
from the specs. Removes the duplication entirely, highest effort.
Option 2 is the smallest guard; option 1+2 together is probably the sweet spot.
Notes
thread.deleteto align the CLI with the "bots get nodestructive operations" convention (branch
feat/remove-thread-delete).octo-cli-design.mdis the most brittle piece:it encodes a global 1..N ordering that must be re-sequenced on any removal.