Fixtures โ
Small, deliberately awkward inputs for calibrating the agenda workflows without touching the operator's real board.
Why does this exist? โ
The real agenda directory is about 275KB across three files, and the agenda reader supplies roughly 62 of the 74 candidates a run works with. That single input drives both expensive phases, so a real-board run costs about 25 minutes and every prompt change costs another 25 to evaluate.
This fixture is 16KB and carries about a dozen candidates. It makes the ten iterations between real runs affordable.
How do I use it? โ
Copy it out first. Never point agendaDir at this folder. Runs write to ../runs/, one folder per run, in the project folder.
mkdir -p <checkout>/docs/projects/agent-workflow-hierarchy/runs/<label>
cp <checkout>/docs/projects/agent-workflow-hierarchy/fixtures/agenda/*.md \
<checkout>/docs/projects/agent-workflow-hierarchy/runs/<label>/
args: repoRoot = <checkout>
agendaDir = <checkout>/docs/projects/agent-workflow-hierarchy/runs/<label>
focus = <whatever you are calibrating against>
trigger = operator-status-request (agenda-status only)A run's Record phase WRITES today's file into agendaDir, so aiming it at this folder drops output into the input set. That already happened once and the output got committed, where it sat in the old format under today's date: a later run would have found today's file already present, appended instead of created, and read the previous run's shape as if it were the fixture.
Restore between arms. IS_SCRATCH_RUN stops the syncing, not the writing. Comparing two runs means restoring the scratch copy between them, or the second run reads the first one's output.
What is the limit? โ
It calibrates logic, not scale. It will tell you whether the focus filters, whether a ghost row reaches ranked, whether the format is written correctly. It will not tell you that a 275KB agenda and 177 open issues behave the same way.
It does not replace an occasional real run. A fixture that quietly becomes the only test is how a thing passes every day and breaks on the real board.
A warning about these rows โ
Two of them named Check A and Check B, phases that were deleted when the workflow was simplified. A tester judging those defects was pointed at machinery that no longer exists, which cost real time. The rows now describe the OBSERVABLE, not the phase that used to produce it.
Worth generalising: a fixture's own README goes stale the same way a test plan does, and it is easier to miss because nobody re-reads it.
What is deliberately wrong with it? โ
Every one of these is planted. A clean fixture tests the happy path and nothing else, and the rows that caught real bugs on 2026-08-22 were all the odd ones.
| Planted | Where | What it probes |
|---|---|---|
| An ask nobody ever made | "Decide the retention window", parked all three days | Does it surface a decision that has been silently waiting four days, or does it copy the parked row forward again? |
| A park whose condition already fired | "Second-source the geocoder": parked pending the geocoder failing twice, and the 08-20 log records exactly that | Does anything notice a parked row that should have been unparked by its own stated condition? |
| Confirmed, unfixed, and unowned | "Fix the webhook retry loop" on 08-21 | Carried work whose owner no longer exists. Does it get reported as in progress, as unowned, or quietly re-ranked as fresh work? |
| A task with no project and no issue | "Tidy the settings screen spacing" | Whether being unfiled reaches the agenda at all. The carry reader does capture it; a run that cuts the row on other grounds and never mentions it is a miss, not a pass |
| Work carried across three days | The webhook thread, 08-19 through 08-21 | The format requires a FRESH block written out in full, never a pointer back to an earlier agenda file |
| A real decision on a task block | "Needs from you" on the webhook fix: replay or accept as lost | It must stay on its task block. There is no top-level asks table, and a run that invents one is writing the retired format |
| Nothing the launch plan lists | All of it. None of this work exists in the plan | Whether anything says NOT LISTED rather than quietly finding something that looks close. NOT LISTED is a real answer and its absence from the output is the failure |
What was wrong with it by accident? โ
One thing, caught by the operator on 2026-08-22 before the fixture was ever used: all three files were missing the Frustration Counter Report, which the format's EOD state requires. That is an error, not a planted defect, and it is fixed.
Worth recording because of what it would have cost. A fixture that silently omits a required section teaches every run that the section is optional, and nobody would have noticed: the reader would not have found one, the ranker would not have missed one, and the test would have passed. A mock that does not match its own format is worse than no mock, because it is confidently wrong.
The planted defects below are deliberate. This was not.
What is NOT in here? โ
Repo state and open PRs, which cannot be mocked from a directory. The launch-plan reader also runs live against the tree, so a fixture run carries real candidates alongside the fixture's dozen. Worth knowing when you read a candidate count.
Why are the field names out of date? โ
These files use Required Skills, Context / Content and Link to project. The format now says Skills, Context and Project, has an emoji vocabulary, checkbox focus blocks and a four-line handoff prompt, and none of that appears here.
That is not obviously wrong, and it is worth a decision rather than a tidy-up. Two readings:
- Keep them stale on purpose. The writer is supposed to follow the format skill, not mirror its input, and an input in the retired shape is the only thing that actually tests that. Scenario 8's tripwire exists for exactly this, and a previous run passed it with retired-format wording present in the ranker's input.
- Modernise them. A fixture that does not match the current format is the same defect as the missing Frustration Counter Report above: a mock that disagrees with its own format teaches the wrong shape.
They differ in what they protect, so the answer is not obvious. Until it is ruled on, do NOT quietly modernise these files: doing so deletes the tripwire without anyone deciding to.