| name | nf-metro-gate-triage |
| description | Run a routing gate-arm triage slice on nf-metro - give every un-exercised branch arm in a layout/routing module a verdict (reachable -> author a fixture, defensive, candidate-dead, or reachable-but-defective -> file a bug). Use when the user wants to triage routing gate arms, close coverage-matrix gaps, work a |
nf-metro gate-arm triage
Every if/while in layout/routing/ is a gate whose arms a novel pipeline
can hit untested, producing a visual defect. The scripts/routing_gate_coverage.py
matrix enumerates which corpus fixtures reach each arm; this skill works the
un-exercised arms of one module to zero open gaps.
The methodology is documented in full at
docs/dev/routing_gate_triage.md.
Read it first - it is the source of truth for the four verdicts, the artifacts,
the workflow, and the hard-won gotchas. This skill is the thin operational
wrapper; it does not restate the detail.
Conventions (substitute if your setup differs):
- Local nf-metro checkout:
~/projects/nf-metro; upstream seqeralabs/nf-metro.
- Render preview:
seqeralabs.github.io/nf-metro/_pr/<N>/.
- This skill builds on
fix-issue for worktree/env/PR hygiene - follow that
skill's setup and additive-only rules.
What this skill does
Drives one module slice (or a cluster of tiny modules) end-to-end: from a
worktree off origin/main, through per-arm classification, the human visual
verdict, a regenerated matrix, to a reviewable PR. It ships verdicts and
fixtures only - never engine behaviour changes.
Steps
-
Scope. Confirm which module (or tiny-module cluster) this slice covers.
Re-run python scripts/routing_gate_coverage.py in a fresh worktree to get
that module's live un-exercised arms - gap counts drift, so never trust a
number from an issue body. If a per-module issue exists (the #727-#733 family,
#748), it carries the arm list; reconfirm it against the live matrix.
-
Classify every arm into exactly one of the four verdicts from the doc:
reachable (author a minimal fixture, wire GALLERY_ENTRIES, verify the arm
flipped via the coverage script - the oracle), reachable-but-defective
(file a bug, park needs-review, do NOT commit/distort the fixture),
defensive (annotate why no valid topology takes it), candidate-dead
(flag with reachability evidence, do NOT delete - that is the #689 pass).
Opus drives; fan the reachable lane out to sonnet sub-agents, each confirming
its flip with the coverage script. Append a triage-JSON card per fixture.
Watch the two traps the doc calls out: phantom arcs (multi-line
condition/literal/ternary mis-attribution - tooling noise, see #746, do not
hand-classify as defensive) and "corpus doesn't hit it" ≠ defensive (a
correction-pass arm with zero hits is usually reachable - author a fixture).
-
Human visual verdict before PR-open. Build the review page and get a
verdict on every new fixture - the validator has blind spots the eyeball
catches:
source ~/.local/bin/mm-activate nf-metro && export PYTHONPATH="$PWD/src"
python .claude/skills/nf-metro-layout-triage/build_review.py --worktree "$PWD" \
--output-dir /tmp/gate-triage-out --violations /tmp/gate-triage-<module>.json
cd /tmp/gate-triage-out && python -m http.server 8765
Any Bug verdict not already classified defective: pull the fixture from
GALLERY_ENTRIES, file an issue with the repro, park its arm needs-review
linked to that issue. Nothing flagged gets silently dropped.
-
Regenerate + ratchet. Run the script with --write to regenerate
docs/dev/routing_gate_coverage.md + the baseline. Keep the three ratchet
tests in tests/test_routing_gate_coverage.py green (they skip off the pinned
CPython - regenerate only under BASELINE_PYTHON). The stale-key test means a
removed gap needs its triage entry removed in the same PR.
-
Ship per fix-issue hygiene. Invariant-test-first where a fixture asserts a
layout property, validator pass, /simplify as its own commit, full CI lint
(ruff format --check + ruff check + mypy), additive commits only, no
force-push, verify origin after each push. Stop at PR-open against main.
Done when the module shows zero blank-Triage rows in the matrix and the PR is
open for review. The slice carries no engine behaviour change; any bug it
surfaced is filed separately (the reachable-but-defective lane).
Mid-campaign merges
If another PR lands while this slice is in flight, resolve the shared coverage
files by union: start from main's triage JSON, add only this module's keys,
then regenerate the doc + baseline. Never hand-merge the generated files.