Context
Found during the wf fast-path audit (2026-06-24). The decision logic in
wf_core.py is well covered — 86 offline tests, all green — and they
are deliberately pure (no git, no gh, no I/O). But that means wf.py,
the entire git/gh I/O shell, has no automated coverage: gh argument
construction, JSON parsing, the status-emission contract
(ok/no-candidates/all-blocked/error/unsupported), the atomic claim
push, board GraphQL mutations, sprint narrowing, and checkout/branch logic.
This glue runs on every real workflow invocation but has no regression
net — a refactor or a gh output-shape change could silently break a fast
path with no test failing. (Two real shape bugs already left scars in the
code: the closingIssuesReferences flat-list-vs-nodes crash, and the
-F digit-coercion of single-select option ids — see the comments at
wf.py:95 and wf_core.closing_issue_numbers.)
The atomic claim CAS was proven correct against the live remote during
the audit (create → won; different object same ref → non-fast-forward
rejection = lost; ls-remote probe distinguishes lost from error), so this
is about locking that behavior in with a repeatable test, not discovering
whether it works.
Requirements (acceptance criteria)
Savings goal
No token saving — reliability ratchet. Goal: the git fast paths and the
status contract cannot silently regress. Success = deliberately breaking
the claim push or a status emission makes a test fail.
Notes
Companion to the all-blocked consumer-side [BUG]. Foundational: the
context-optimization stories (#136 lazy prewarm, #140 wf review-finish) push
more logic into wf — landing this coverage first de-risks all of them.
Context
Found during the
wffast-path audit (2026-06-24). The decision logic inwf_core.pyis well covered — 86 offline tests, all green — and theyare deliberately pure (no git, no
gh, no I/O). But that meanswf.py,the entire git/
ghI/O shell, has no automated coverage:ghargumentconstruction, JSON parsing, the status-emission contract
(
ok/no-candidates/all-blocked/error/unsupported), the atomic claimpush, board GraphQL mutations, sprint narrowing, and checkout/branch logic.
This glue runs on every real workflow invocation but has no regression
net — a refactor or a
ghoutput-shape change could silently break a fastpath with no test failing. (Two real shape bugs already left scars in the
code: the
closingIssuesReferencesflat-list-vs-nodescrash, and the-Fdigit-coercion of single-select option ids — see the comments atwf.py:95andwf_core.closing_issue_numbers.)The atomic claim CAS was proven correct against the live remote during
the audit (create → won; different object same ref → non-fast-forward
rejection = lost;
ls-remoteprobe distinguishes lost from error), so thisis about locking that behavior in with a repeatable test, not discovering
whether it works.
Requirements (acceptance criteria)
tests/test_decision_logic.py) that exerciseswf.py's I/O shell withouthitting GitHub.
bare remote (no network): assert create→
won, a second distinctobject to the same ref is rejected →
lost, an absent-ref push failure →error, andrelease_claimremoves the ref. This is the highest-valuecase and needs only local git.
gh/gitstubbed (a fakerun()ora PATH shim returning recorded fixtures), assert each command emits the
right
status+ exit code for: empty pool →no-candidates; allclaimed/blocked/resolved →
all-blocked;board-column/bothready-gate→
unsupported; type-capable + non-story mode →unsupported; missingconfig →
error.closing_issue_numberson both the flat-list and{nodes:[…]}shapes,and
_graphql_argskeeping a digit-only id as-f(string) while a realint goes through
-F.run-tests.sh/run-tests.ps1and CI sothey run alongside the existing suite.
detects the interpreter).
Savings goal
No token saving — reliability ratchet. Goal: the git fast paths and the
status contract cannot silently regress. Success = deliberately breaking
the claim push or a status emission makes a test fail.
Notes
Companion to the
all-blockedconsumer-side [BUG]. Foundational: thecontext-optimization stories (#136 lazy prewarm, #140 wf review-finish) push
more logic into
wf— landing this coverage first de-risks all of them.