docs/new-lane-template.md
70 lines · 3.2 KB
New Lane Checklist
Every lane in this suite keeps five machine-checked promises: row contract,
skip coherence, transport purity, measurement_source honesty, and catalog
membership. tests/test_lane_contract.py enforces them over
scripts/oakbench/lane_contract.py:LANE_TABLE; a lane missing its entry
fails CI by design. Work the list top to bottom.
1. Name the lane
-
Pick a short, stable lane name (e.g.
fleet-sync). Names are identity (ADR-0005): renames are new lanes, never silent changes. -
Decide where rows are written: through
ResultsStore(results, lane=...)so the row contract is validated at write time, not in a dashboard.
2. Declare the row contract
-
Add the lane to
scripts/oakbench/rows.py:LANESplus aLANE_REQUIRED_KEYSentry listing only keys EVERY row carries β including skip and diagnostic rows (that is why token fields are not required at this layer). If the lane deliberately reuses another lane's keys (netshape usescore), say so in the emitter's docstring instead.
3. Add the LANE_TABLE entry
-
One
LaneContractinscripts/oakbench/lane_contract.py: lane name,validate_lane(rows.py key orNone+universal_keys), a puresample_rows_buildermirroring your real emitter (measured row, total/ derived row if any, skip row),allowed_sources,catalog_path, and any catalog exemptions β documented reality, never wildcards. -
If the lane has no rows.py entry yet, add its name to
DE_FACTO_LANES.
4. Scenario YAML with immutable names
-
If the lane has a declared operation vocabulary, put it in
scenarios/<lane>.yaml(anoperation_catalog:map or per-scenariooperations:lists). Scenario and operation names are immutable; parameters belong in the name (poll_until_merged_i10s).
5. Skip-row honesty
-
Anything unmeasurable emits a returncode-77 row with
skipped: trueand askip_reasonnaming the exact fix (env var, platform, privilege). Skips are work items, not absences (ADR-0002). Never a fabricated zero.
6. Transport declaration
-
Every remote-touching row carries
remote_repo,remote_transport,remote_server(useoakbench.remotesβ do not hand-roll). One (subject, scenario, operation) never mixes transports; shaped rows must carrynetshape_profileand compare same-pipe only.
7. measurement_source
-
State how each value was obtained. Top-level for whole-row sources,
nested per metric block (agent/contention style) for composite rows.
Whatever you emit, encode it in the entry's
allowed_sources.
8. Devloop in or out
- Decide whether the lane runs in devloop. Lanes with external variance (hosted platforms, real networks) stay out so changeset verdicts are never poisoned; record the decision in the lane script's docstring.
9. Tests with fake transports
-
Lane tests construct rows via your row builders with fake/local
transports (bare repos, loopback servers) β never live credentials.
Run
python3 -m unittest tests.test_lane_contractand confirm your lane passes all five checks and the negative cases still have teeth.