Quality gate: two-action smoke required for stateful surfaces
Quality gate: two-action smoke required for stateful surfaces
Status: Delivered
CAS: CAS-2733
Delivered: 2026-05-14
PRs: #724
What’s new
Any PR that touches a stateful surface — AI conversation, license activation, frontend stores — must now include a smoke test that performs two sequential user-shaped actions and asserts that state survives between them. The single-action check (“send a message, assert a reply”) is no longer sufficient: the gate now requires that a second action, dependent on the first, succeeds correctly. This catches the second-turn collapses and restart-persistence failures that single-action tests miss.
How to use it
For engineers: When your PR touches any of the following globs, the backend-quality and frontend-quality skills will flag a missing two-action smoke:
src-tauri/src/services/ai/** — AI chat and conversation memorysrc-tauri/src/services/license_* — license activation and persistencesrc-tauri/src/bin/handlers/ai_chat.rs — daemon chat handlersrc/store/use*Store.ts — frontend state storesThe smoke pattern looks like:
- Action A — perform the first stateful operation (e.g. send message, activate license)
- Assert intermediate state is correct
- Action B — perform a second operation that depends on Action A (e.g. send follow-up, restart and query)
- Assert final state reflects both actions correctly
Evidence in the PR: Include the smoke output as a code block in the PR description under ## Smoke evidence. The request-review script enforces this gate and will block the handoff if the heading is absent.
At close: The check-ready-to-close script also verifies the evidence heading is present for any PR that touched the stateful globs.
What changed under the hood
.agents/skills/casaconomy-backend-quality/SKILL.md— “Two-action smoke required” rule added for the five stateful glob patterns; includes rationale and example test structure..agents/skills/casaconomy-frontend-quality/SKILL.md— Same rule forsrc/store/use*Store.ts; dispatch-assert-dispatch-assert pattern documented..agents/skills/casaconomy-task-worktree/scripts/request-review.sh— Gate: if the PR touches stateful globs and## Smoke evidenceheading is absent from the PR body, handoff is blocked with a clear error..agents/skills/casaconomy-task-worktree/scripts/check-ready-to-close.sh— Same evidence check added to the pre-close gate.
Why we built it
The iOS bug-report arc surfaced a recurring failure shape: an engineer’s own-layer tests passed, but a second sequential action (a follow-up message, a restart, a re-query) exposed state that had silently reset or corrupted. Single-action smokes are easy to write and easy to pass while the bug hides. The two-action minimum forces engineers to actually exercise the statefulness of stateful code — the thing that makes these surfaces different from stateless request handlers.
Known limitations / follow-on work
- The smoke test helpers (
chat_smoke_harness,license_smoke_harness) scoped in the original epic were deferred; the gate is enforced at skill/review level, not by a shared test fixture yet. - The glob list covers the known high-risk surfaces; new stateful services added in future epics need to be added to the list.