T-LN0B-orchestrator-tick-race-fixture
Status: closed/obsoleted · Impact: low · Complexity: medium
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
/sdlc:task-close-out Step 4 mitigates the “two orchestrator
ticks fire close-out for the same task concurrently” race via
git pull --rebase --autostash before git push. The mitigation
is currently spec-only — there’s no integration test that
demonstrates the race is actually contained. Once T-FQCN-self-driving-orchestrator-loop’s
orchestrator starts dispatching close-outs autonomously the race
becomes reachable, and the cost of discovering it broken in
production (a mangled commit on main, or a push rejection that
leaves the task half-closed) is higher than the cost of a small
fixture today. Closing this gap turns a load-bearing prose claim
into a verified property.
From the originating post-mortem:
Step 4’s “race against concurrent orchestrator ticks via
pull --rebase --autostash” remains spec-only. There’s no integration test for the race itself; we’re trustinggit’s well-known semantics. Worth a small fixture once the orchestrator is shipping ticks.
plugin/skills/task-close-out/SKILL.md Step 4 pins the
--rebase --autostash invocation as load-bearing, but no test
in the repo (eval harness, project-check, or otherwise)
exercises the race. The closest signal is the invariants linter
checking for the literal phrase in the SKILL.md body.
Proposed
Section titled “Proposed”A new case in plugin/skills/task-close-out/tests/run_evals.py
(the established eval-harness shape across the plugin — see
plugin/skills/entities-migrate/tests/entities_migrate.test.ts etc. for
precedent) that:
- Spins up a throwaway bare repo and two working clones acting as “tick A” and “tick B.”
- Has both clones run the Step 4 sequence (edit frontmatter,
commit,
pull --rebase --autostash, push) against the same task file at nearly the same time. - Asserts that exactly one push succeeds, the loser’s
pull --rebase --autostashreconciles cleanly, and the final state of the task file on the bare repo matches the expected closed-out frontmatter with no merge conflict markers.
The case lives alongside whatever existing cases the file
contains. The runner already runs as part of the plugin’s
quality-checks pipeline via sdlc.yaml.
Approach
Section titled “Approach”- Create or extend
plugin/skills/task-close-out/tests/run_evals.pyto add the race-condition case. Follow the established(name, expected_exit, expected_substrings)shape from sibling eval-suite runners. - The case builds a bare-repo + two-clone fixture in
tmp_pathwith deterministic ordering (file-based sync points, not wall-clock timing). Run both Step-4 sequences, assert the three properties above. - Mark the case as the canonical regression for Step 4’s
race-mitigation claim — name it
race_orchestrator_concurrent_ticksso it’s findable.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
plugin/skills/task-close-out/tests/run_evals.py | new | *(new file |
plugin/skills/task-close-out/invariants.yaml | modify | optional |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: A new case
race_orchestrator_concurrent_ticksinplugin/skills/task-close-out/tests/run_evals.pyexercises two simultaneous Step-4 sequences against a shared bare repo. The case is picked up by the existing eval-suite runner. - AC-2: The case asserts: exactly one push succeeds on the first attempt; the loser’s rebase reconciles without conflict; the final ref on the bare repo contains both close-out edits in a linear history. (auto)
- AC-3: Deliberately breaking Step 4 (e.g. removing
--autostash) makes the case fail. Verified manually once during PR review by mutating the harness and re-running.
Out of scope
Section titled “Out of scope”- Exercising the race against the real GitHub remote. The bare repo is enough — we’re testing git semantics, not GitHub’s.
- Generalizing the harness to other skills’ race-mitigation claims. Start with close-out; extend later if useful.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-RDKI-extract-task-close-out-skill on 2026-05-20.