I0823 — majordomus bench: targets derived from the command registry
Add the bench command: every public command in share/commands.yaml is a target, run against a disposable installed repository, with warmup and samples from the policy, reporting min, p50, p90, p95, p99, max, mean and stddev per target and mode.
DONE wave 1 · p0 · implementation profile · runs alone
Part of M004 — Performance is executable evidence, and the hot path does no canonical work twice.
Objective
Add the bench command: every public command in share/commands.yaml is a target, run against a disposable installed repository, with warmup and samples from the policy, reporting min, p50, p90, p95, p99, max, mean and stddev per target and mode.
Why
A benchmark list kept by hand goes stale the day a command is added; the registry already knows the surface.
Current state
There is no benchmark command; ad hoc timing lives in shells.
Desired state
bench, bench <command>, --mode cold|warm|both, --samples, --warmup, --format json, --list; the JSON carries schema majordomus/benchmark-result/v1, commit, dirty flag, platform, build of bash and the benchmark profile.
Scope
- lib/bench.sh
- bin/majordomus
- share/commands.yaml
- share/allow/policy.txt
- share/skeleton/policy.yaml
- .ai/repo/policy.yaml
- docs/CLI.md
- test/cases/79_bench_command.sh
- test/fixtures/commands/bench.json
Out of scope
- Benchmarking the Rust executable
- A benchmark of commands that mutate the repository outside a disposable fixture
Dependencies
What waits on this
- I0824DONE Bench persists local runs and keeps a latest projection
- I0827DONE The benchmark policy block
- I0830DONE docs/PERFORMANCE.md, README, CONTRIBUTING and CLI reference
Acceptance criteria
- bench --list prints exactly the public commands of the registry
- A run records both modes separately with the eight statistics
- Case 79 proves the target list follows a registry mutation
- The command is registered, covered and documented like every other command
Validation
- bash test/run.sh 79_bench_command
- bin/majordomus bench --format json
Evidence required
- bench_targets_derived
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| bench_targets_derived | test | bash test/run.sh 79_bench_command | lib/bench.sh derives its targets from mj_cmdreg_public minus itself and its scenario per target from the first scenario of test/fixtures/commands/<command>.json; case 79 asserts --list equals the registry public set, that a public command added to a copy of the registry appears in the copy's --list with no edit to the harness, that a read-only run records one cold and N warm results with count, min, p50, p90, p95, p99, max, mean and stddev ordered, and that a state-mutating target records only a cold distribution over fresh repositories; bench is registered in share/commands.yaml, dispatched by bin/majordomus, demonstrated by test/fixtures/commands/bench.json and documented in docs/CLI.md and docs/SCHEMAS.md; the fixture and coverage cases 30, 31, 34 and 15 pass | next |
Risk
Commands that read stdin or need an active task need a fixture per target; the fixtures under test/fixtures/commands already describe one scenario per command and are reused.
Timeline
- started
- 2026-09-05T03:33:10Z
- verified
- 2026-09-05T03:33:10Z
- completed
- 2026-09-05T03:33:10Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I0823.yaml. Read it back with majordomus plan show I0823.