/flow-next:qa graduates from a user-invoked skill into an opt-in, config-gated pilot stage that runs one live-app pass at all-tasks-done, before make-pr. It augments — never replaces — CI/staging/manual QA.pipeline.qa (default off) inserts a qa stage at all-tasks-done. The app is already up on the dev's machine during work — so run a cheap first live pass before a human opens the PR./flow-next:qa executor.work's recorded evidence and subtracts only AC proven by a deterministic re-runnable check (mapped to the R-ID) — always live-running runtime/UI/integration AC even when work narrated it done.head_sha freshness gate runs it at most once per head); routes on qa_outcome (not the Ralph verdict projection). SHIP/NA/BLOCKED advance; NEEDS_WORK still advances to the draft PR + surfaces findings. Merge stays human + land.| R-ID | Criterion | Task | Commit |
|---|---|---|---|
R1 | Config gate pipeline.qa (default off) inserts qa at all-done | .2 | 116603e |
R1b | Idempotent — classify qa only when no fresh qa_verdict receipt (id + head_sha) | .2 | 116603e |
R2 | Lean+agentic — no new flowctl subcommand/engine (one config default), no artifact | .1 | 8c945e9 |
R3 | Reverses "QA never a stage" only under the gate; other five stay forbidden | .2 | 116603e |
R4 | Evidence-aware — subtract only mapped+deterministic AC; runtime/UI always live | .1 | 8c945e9 |
R5 | SHIP needs captured live evidence; work narration never counts | .1 | 8c945e9 |
R6 | Augmenting, local-dev scope; BLOCKED/NA advance; not a CI/staging/manual replacement | .2 | 116603e |
R7 | Verdict surfaced not loop-blocked — routes on qa_outcome; NEEDS_WORK → draft PR | .2 | 116603e |
R8 | Receipts only at hand-off — existing qa_verdict gains additive fields, no new artifact | .1 | 8c945e9 |
R9 | Autonomy-safe + full doc sweep (4 repos) + Codex mirror | .3 | 3540744 |
9/9 covered — no uncovered acceptance criteria.
| File | Intent | Churn |
|---|---|---|
skills/flow-next-qa/workflow.md | Evidence-aware subtraction + autonomous-mode + receipt writer — read first | +124/−30 |
skills/flow-next-pilot/workflow.md | The qa stage: classify / idempotence / dispatch / verify | +84/−1 |
skills/flow-next-make-pr/workflow.md | New ## Live QA section reads the receipt into the PR body | +68/−2 |
scripts/flowctl.py (×2 copies) | The one flowctl touch — pipeline.qa config default | +14 |
tests/test_pipeline_qa_config.py NEW + test_qa_receipt.py | Regression: gate default, routing, receipt fields | +321 |
codex/skills/… | Codex mirror (sync-codex.sh) | regen |
docs/ralph.md, docs/README.md, README.md, CHANGELOG.md, docs/flowctl.md | Pipeline docs + ## Unreleased entry | +17 |
qa_outcome, NOT verdict — the qa workflow projects BLOCKED→verdict=NEEDS_WORK for Ralph; the pilot gate must read qa_outcome so BLOCKED advances. Confirm in pilot/workflow.md classify/verify.qa classified only when no fresh qa_verdict (receipt.id == spec AND head_sha == spec-branch head AND terminal qa_outcome); a fresh receipt falls through to make-pr. Single-tick pilot would otherwise re-classify forever.qa/workflow.md §2.0) — only an AC whose R-ID is satisfies-mapped AND covered by a deterministic re-runnable test is dropped; verification_summary/commits/files never subtract.## Live QA — reads .flow/review-receipts/qa-<id>.json (guarded), surfaces qa_outcome + open_p0p1 objects + rid_coverage. jq-read only, no shell-JSON interpolation.pipeline.qa: "off" (string enum, not bool) in get_default_config(); both flowctl.py copies in lockstep (dual-copy invariant).NEEDS_WORK still ships the draft PR with the findings surfaced; BLOCKED (no live app) advances cleanly. The loop never hard-stalls on QA (DORA: advisory > blocking gates).## Unreleased; flow-next.dev / AI×SDLC / GF microsite committed but not pushed (batched with fn-71's docs).