You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Each verb brings its own register(), its argument surface, its handler, its dry-run/plan renderer, and its result formatter. They share a file and almost nothing else.
The catalog-lockstep rule (CLAUDE.md: a new verb must update explain/catalog.py, overview.py's _VERBS, and learn.py together) is enforced by teken cli doctor --strict, but the fourth place — this file's help text — has repeatedly drifted. The false "only elbow_flex wraps inside its travel" claim survived in arm.py's --help after it had been retracted in arm_spec.
Suggested shape (not prescriptive)
One module per verb under arm101/cli/_commands/arm/, each exporting register(sub) and its handler; a thin arm/__init__.py that builds the noun group and calls each in turn. That is already the pattern _build_parser() uses for the top-level verbs — this just applies it one level down.
Two things must survive the split:
parser_class=type(p) on the noun's subparsers, so child parse errors keep routing through the structured error contract instead of argparse's exit 2.
The error/output contracts — CliError never sys.exit, results to stdout and diagnostics to stderr never mixed, --json on every verb. These are enforced by tests and by teken cli doctor --strict; run both.
Prefer rendering help text from arm_spec
The drift above happened because operator-facing prose restated a table instead of rendering from it. Several surfaces now render from arm_spec at import (_ARM_REZERO in the catalog, REZERO_UNKNOWN_HEADLINE). The split is the moment to finish that: help text that quotes a measurement should be an f-string over the source of truth, not a copy of it.
Not urgent, and deliberately not now
Filed rather than done because it surfaced mid-hardware-run with PR #48 green. Sibling to the bus.py refactor.
The state
arm101/cli/_commands/arm.pyis 4140 lines — 8 verbs and 72 functions in one module:overview,read,flex,explore,profile,rezero,setup,limitsEach verb brings its own
register(), its argument surface, its handler, its dry-run/plan renderer, and its result formatter. They share a file and almost nothing else.Why it hurts, concretely
t10= the commit path,t11= the bounds diff) had to be serialised by hand purely because both would have edited this file. That is the dependency graph losing to a filesystem layout. It has bitten before: PR feat: encoder linearity — evict the seam so a linear tick axis is finally true (#35) #40's merge conflict was two branches adding a verb to this same file, and git's conflict regions did not align on function boundaries — the naive union spliced one verb's argument list into another verb's call.explain/catalog.py,overview.py's_VERBS, andlearn.pytogether) is enforced byteken cli doctor --strict, but the fourth place — this file's help text — has repeatedly drifted. The false "only elbow_flex wraps inside its travel" claim survived inarm.py's--helpafter it had been retracted inarm_spec.Suggested shape (not prescriptive)
One module per verb under
arm101/cli/_commands/arm/, each exportingregister(sub)and its handler; a thinarm/__init__.pythat builds the noun group and calls each in turn. That is already the pattern_build_parser()uses for the top-level verbs — this just applies it one level down.Two things must survive the split:
parser_class=type(p)on the noun's subparsers, so child parse errors keep routing through the structured error contract instead of argparse'sexit 2.CliErrorneversys.exit, results to stdout and diagnostics to stderr never mixed,--jsonon every verb. These are enforced by tests and byteken cli doctor --strict; run both.Prefer rendering help text from
arm_specThe drift above happened because operator-facing prose restated a table instead of rendering from it. Several surfaces now render from
arm_specat import (_ARM_REZEROin the catalog,REZERO_UNKNOWN_HEADLINE). The split is the moment to finish that: help text that quotes a measurement should be an f-string over the source of truth, not a copy of it.Not urgent, and deliberately not now
Filed rather than done because it surfaced mid-hardware-run with PR #48 green. Sibling to the
bus.pyrefactor.Related: #43