Skip to content

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 memory
src-tauri/src/services/license_* — license activation and persistence
src-tauri/src/bin/handlers/ai_chat.rs — daemon chat handler
src/store/use*Store.ts — frontend state stores

The smoke pattern looks like:

  1. Action A — perform the first stateful operation (e.g. send message, activate license)
  2. Assert intermediate state is correct
  3. Action B — perform a second operation that depends on Action A (e.g. send follow-up, restart and query)
  4. 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 for src/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 evidence heading 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.