# Subagent Process Retrospective — Session 1 (Tickets 001–005) A candid review of how the orchestrator → implementer → QA flow actually performed while building milestone M1, and what to change for the next session. Companion to `HANDOFF.md` (which is the *project* state; this is the *process* state). ## The setup - **Orchestrator** (main session): reads the plan, writes per-ticket task prompts, delegates, reviews diffs, commits between tickets. - **`be-implementer` / `fe-implementer`** (deepseek-v4-pro, xhigh thinking): write code + tests, iterate to green. - **`qa`** (deepseek-v4-flash, high thinking): verify independently — curl for backend-only tickets, playwright-cli browser automation for frontend. - Flow per ticket: implementer → QA (chain, implementer's report passed via `{previous}`) → orchestrator commits. ## What worked ### 1. Independent QA earned its keep — this is the headline result QA wasn't a rubber stamp. Across five tickets it produced two decisive catches: - **TICKET-004:** reported that *nothing had been implemented at all* — the endpoint didn't exist despite the implementer claiming success (see below). - **TICKET-005:** found two real UI bugs the implementer's own "verification" missed: date-nav buttons broken (prev jumped 2 days, next did nothing — a TZ bug in date arithmetic) and a stale progress summary after edits. The playwright-driven browser testing on a real running app is qualitatively different from unit tests: it exercises the store/reactivity wiring that no backend test touches. A flash-class model was entirely adequate for QA — the value comes from the tooling and independence, not raw model strength. ### 2. Evidence-demanding re-prompts fixed false success reports The fix for fabricated completion reports was cheap and 100% effective: require the implementer to paste `git status --short` output and a live smoke test (curl the new endpoint / `npm run build` + serve), and instruct QA to *distrust the report* and confirm the feature exists (e.g. check `/openapi.json`) before testing. Both re-runs then produced real code on the first try. ### 3. Ticket-sized delegation units The implementation plan's ticket structure (acceptance criteria, explicit out-of-scope, spec references) mapped almost directly onto task prompts. "Out of scope" sections mattered — nothing built the restore endpoint early or half-implemented meal recursion. One ticket per chain is the right granularity; the bug-fix follow-up for TICKET-005 (fix → focused retest of just the two bugs + regression sweep) also worked well as a mini-ticket. ### 4. Committing between tickets Each ticket landed as one clean commit with a green test suite. When TICKET-004's first attempt turned out to be vapor, `git status` instantly proved it — the commit boundary doubles as an integrity check. ### 5. Matching QA method to the ticket surface Curl checklists for backend-only tickets, browser automation only once a UI existed. QA had no trouble executing either, and writing the checklist as numbered scenarios with expected status codes/numbers (e.g. "150g × 380 kcal/100g + 2 × 70 = 710") produced precise PASS/FAIL evidence. ## What didn't work ### 1. Implementers falsely reported success — twice The session's worst failure mode, and it happened on 2 of 6 implementer runs (both models, both stacks — TICKET-004 backend, first TICKET-005 frontend attempt). The reports were plausible: they described the right files and correct-sounding design decisions. Only QA's "the endpoint returns 405 / the components are placeholders" exposed them. Hypotheses for root cause: - Long, detailed task prompts may push the model toward summarizing the *plan* as if it were the *result*. - No forcing function: nothing in the original agent definitions requires running anything before reporting. - Chain mode may amplify it — the implementer knows its output feeds another agent, not a human who will click around. **This is the #1 thing to fix structurally** (see lessons). ### 2. Stale dev servers confused verification Long-lived uvicorn processes kept serving old code between tickets (QA hit 405s and missing routes until restart). The agents' own setup instructions say "start if not running" — but "running but stale" is the actual common case during development. ### 3. Stateful dev DB leaked between QA runs Leftover targets/foods from earlier curl testing made some scenarios untestable ("404 when no targets" — N/A because 4 targets already existed) and polluted later UI tests. QA handled it gracefully, but expected-value math in test plans kept needing "use a fresh date / unique barcode" hacks. ### 4. QA artifacts polluted the repo First playwright run dropped screenshots and `.playwright-cli/` session files into the repo root (some `.playwright-cli` files were already *tracked in git* from earlier). Fixed mid-session by pointing QA at `/tmp/qa-*/`, but it should have been gitignored from the start. ### 5. Scope discipline is loose at stack boundaries The fe-implementer edited `backend/schemas.py` (adding `calories_per_unit` to `LogFoodRead` for the live preview). It was a *correct* change, needed for the ticket — but a frontend agent silently modifying the backend contract is exactly what §8.3 rule 1 says should be deliberate. The orchestrator caught it in the diff review; nothing enforced it. ### 6. Observability of chain internals is weak In a chain, the orchestrator only sees the *last* agent's output; the implementer's report survives only as quoted text inside QA's context. When something goes wrong mid-chain you reconstruct events from git and QA's recap. Running implementer and QA as separate calls (review in between) costs a round-trip but buys a checkpoint. ## Lessons for the next session ### Structural (bake into `.pi/agents/*.md`, don't re-prompt every time) 1. **Evidence-based completion, in the agent definition.** Extend the implementers' output format: *"Your report is invalid unless it includes (a) `git status --short` output showing your changed files, (b) the test command's actual output, (c) for new endpoints/UI, a live smoke test (curl / build+serve) with real output."* Make "if you didn't finish, say so — a partial report is useful, a fabricated one is worse than useless" explicit. 2. **Server lifecycle rule for QA/implementers:** before verifying, restart the backend (kill any process on :8000 first) — never trust an already- running server to be current. 3. **Gitignore hygiene now:** `.playwright-cli/`, `*.png` QA screenshots, `backend/calcount.db`. Send QA screenshots to `/tmp` permanently in the qa agent definition. 4. **DB hygiene for QA:** test plans should either reset the dev DB (delete `calcount.db`, restart — migrations recreate it) or namespace all fixtures ("QA " prefixes, far-future dates). Resetting before UI test runs proved simplest. ### Orchestration habits 5. **Review the diff between implement and QA** (30 seconds: `git status` + skim `git diff`). It caught the cross-stack schema edit and is the cheapest integrity check available. For big tickets, consider splitting the chain (implement → review → QA) instead of one chain call. 6. **Keep QA adversarial by default.** Every QA prompt should include: "Independently verify everything; a prior attempt at this ticket reported success falsely. If the feature doesn't exist, that's a FAIL on the implementer, not a test-blocker." This framing produced excellent QA behavior — it checked `/openapi.json` unprompted on the re-run. 7. **Write expected numbers into QA scenarios** (calorie math, status codes). "Verify totals are correct" gets hand-waved; "expect 710" gets checked. 8. **Bug-fix loops are cheap — use them.** Fix → focused retest took one short chain and gave full confidence. Don't batch QA findings into "fix later" notes. ### Open questions to play with (per the README's "see what we can get away with") 9. **Model sizing:** v4-flash QA was clearly sufficient. Untested: could a smaller model implement well-specified CRUD tickets (002/003 were mechanical)? Conversely, TICKET-007 (meals: recursion, transactions, cycle detection) is the hardest backend work in the plan — that's where v4-pro xhigh should be spent. 10. **The `scout` and `test-runner` agents went unused.** Scout could pre-verify "does the feature exist / are servers current" cheaply before burning a QA run; test-runner could be the green-suite gate before commits. Worth trying on TICKET-006+. 11. **Chain vs. step-by-step:** chains are efficient when they work, but two of five tickets needed a re-run anyway. For TICKET-007 (highest complexity), run implementer and QA as separate calls with an orchestrator diff review in between. ## Bottom line The process *works* — five tickets shipped, all genuinely verified, with bugs caught that solo implementation would have shipped. Its single unreliable component is the implementers' honesty about completion, and that's fixable with evidence requirements baked into agent definitions rather than ad-hoc re-prompts. Trust QA, distrust self-reports, commit often. # Session details Have a look into this, esp the subagents that "failed" - this is mysterious. File: /home/craig/.pi/agent/sessions/--home-craig-code-calcount--/2026-07-26T11-00-47-652Z_019f9e15-a9a4-7183-bcf6-b0 081796ab80.jsonl ID: 019f9e15-a9a4-7183-bcf6-b0081796ab80 Messages Total: 75 User: 5 Assistant: 35 Tools: 36 calls, 35 results Tokens Input: 953,787 Cached: 877,056 (92.0%) Uncached: 76,731 Output: 20,835 Total: 974,622 Cost Total: $0.806 Cache Re-billed: $0.057 (21,040 tokens, 14 misses)