diff --git a/README.md b/README.md
index 2ee0933..3ec95a4 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@ AI skills for test management workflows with [Testomat.io](https://testomat.io).
| Skill | Description |
| ---------------------- | -------------------------------------------------------------------------------------------- |
| `generate-test-cases` | Generate test cases and checklists from requirements, tickets, or feature descriptions |
+| `create-test-cases` | Deep, feature-first manual test-case authoring with UI exploration, AC baselines, self-review gates, and worked examples |
| `improve-test-cases` | Analyze and improve existing markdown test cases for clarity |
| `find-duplicate-cases` | Find duplicate, near-duplicate, and overlapping test cases |
| `sync-cases` | Synchronize Markdown test scenarios between local project and Testomat.io |
diff --git a/plugins/test-management/skills/create-test-cases b/plugins/test-management/skills/create-test-cases
new file mode 120000
index 0000000..ee54280
--- /dev/null
+++ b/plugins/test-management/skills/create-test-cases
@@ -0,0 +1 @@
+../../../skills/create-test-cases
\ No newline at end of file
diff --git a/skills/create-test-cases/SKILL.md b/skills/create-test-cases/SKILL.md
new file mode 100644
index 0000000..13f57f1
--- /dev/null
+++ b/skills/create-test-cases/SKILL.md
@@ -0,0 +1,174 @@
+---
+name: create-test-cases
+description: Create manual test cases as local MD files (does not publish). MUST USE when asked to "create test cases", "cover feature with tests", "write test cases", generate checklist, or expand test coverage. Two-phase flow: feature phase runs once (gathers shared UI + AC baseline + destructuring map), sub-feature phase runs per suite (generates deep-coverage test cases). After generation, user publishes with a separate skill (e.g. `sync-cases`, or the local `/publish-test-cases-batch`).
+license: MIT
+metadata:
+ author: Testomat.io
+allowed-tools: Read Grep Glob Write Bash Agent ToolSearch mcp__playwright__* mcp__testomatio__* mcp__github__*
+effort: max
+---
+
+# CREATE-TEST-CASES SKILL
+
+Creates manual test cases as local MD files. **Does not publish** — publishing is a separate skill (`/publish-test-cases-batch` — local for now, not yet part of this repo; alternatively use [`sync-cases`](../sync-cases/SKILL.md)) invoked after MD is approved.
+
+**Argument:** $ARGUMENTS — Testomat suite URL or feature name
+
+**References:** [intake-questionnaire.md](intake-questionnaire.md) | [artifacts.md](references/artifacts.md) | [testing-strategy.md](references/testing-strategy.md) | [test-case-format.md](references/test-case-format.md) | [self-review-checks.md](references/self-review-checks.md) | [product-context.md](references/product-context.md) | [destructuring.md](references/destructuring.md) (feature-phase procedure) | [troubleshooting.md](references/troubleshooting.md)
+
+**Step contract template** — every step file declares this block so you can see at a glance what must exist before, what is produced, and whether it's safe to re-run:
+- **Precondition:** artifacts that must exist and validate (refers to IDs in [artifacts.md](references/artifacts.md))
+- **Input:** values consumed from earlier artifacts / user
+- **Output:** artifacts written (with ID)
+- **Postcondition:** invariant that must hold after the step completes
+- **Idempotent:** yes / no — can this step be re-run safely?
+- **Retry policy:** what to do on transient failure; when to escalate
+
+---
+
+## Hierarchy Model — Feature-First
+
+| Concept | Testomat Entity | Example | Branch |
+|---------|----------------|---------|--------|
+| **Feature** (main functionality) | Folder | Manual Test Execution | — |
+| **Sub-feature** (part of feature) | Suite | Environment Configuration | `tc/{feature}/{suite-slug}` |
+| **Sub-feature section** (mandatory when 2+ natural sections of ≥3 tests exist) | Nested suite | CRUD Operations (inside Environment Configuration) | same branch |
+| **Test case** | Test | Select custom environment for a run | inside suite branch |
+
+**Feature-first architecture:** heavy gather-info runs ONCE per feature (Step 1 Feature Phase) and produces shared artifacts (`_ac-baseline.md`, `_shared-ui.md`, `_existing-steps.md`, `destructuring.md`). Each sub-feature then runs in its own conversation as a thin slice (Step 2) + generation (Step 3) + report (Step 4). This eliminates the AC/UI duplication that previously happened across sub-features.
+
+**Key rules:**
+- **Folder = feature.** One folder per feature. The folder is created at publish time by your publisher of choice (e.g. local `/publish-test-cases-batch`, or [`sync-cases`](../sync-cases/SKILL.md)) — this skill only lays out the local `test-cases/{feature}/` directory.
+- **Suite = sub-feature.** Each suite is a self-contained area of the feature with **full, deep coverage** at the depth chosen by Q2. See § Suite Depth Expectation.
+- **Nested suites** are used when a sub-feature has multiple logical sections. Full rule: [self-review-checks.md § 8](references/self-review-checks.md#8-sub-suite-distribution).
+- **Two-phase flow (always):** the feature phase (Step 1) runs once and HARD STOPs. Each sub-feature then runs the sub-feature phase (Steps 2-4) in a separate conversation. There is no "single-suite mode" — even a feature with one sub-feature runs the feature phase first, because the `_shared-ui.md` and `_ac-baseline.md` artifacts carry value even for a single suite.
+- **MD only — publishing is a separate skill.** This skill never pushes to Testomat. After Step 4 the user runs the publisher (local `/publish-test-cases-batch` — not yet part of this repo; or [`sync-cases`](../sync-cases/SKILL.md)) with the saved path.
+- **Whole-feature publish:** when all sub-feature checkboxes in `destructuring.md` flip to `[x]`, the user runs `/publish-test-cases-batch test-cases/{feature}/` (or equivalent) to push everything (one branch per suite: `tc/{feature}/{suite-slug}`).
+- **Style carryover.** After the FIRST sub-feature is approved, Step 4 writes `test-cases/{F}/_style.md`. Subsequent sub-features read it FIRST in Step 3 Phase 2 so the whole feature stays stylistically consistent. See [references/artifacts.md § A-style](references/artifacts.md).
+
+### Sub-suite Distribution Rule
+
+Applied at end of Phase 1 Grouping pass — fully automatic, no user prompt. **Full rule, matrix, anti-patterns, and "what counts as a natural section":** [self-review-checks.md § 8](references/self-review-checks.md#8-sub-suite-distribution) (single source of truth).
+
+Short version: if **≥ 2 natural sections of ≥ 3 tests each** exist (after auto-merging undersized sections) → MUST be nested (directory of MD files). Otherwise flat. Total test count is not part of the decision.
+
+### Suite Depth Expectation
+
+Each sub-feature must receive full, deep coverage — not a thin slice. The feature phase (Step 1) provides `_ac-baseline.md` and `_shared-ui.md`. Each sub-feature phase adds its AC delta (Step 2.1), UI delta (Step 2.2), and generates tests (Step 3) that satisfy:
+
+- **AC coverage:** every AC in the combined pool — baseline ACs applicable to this sub-feature ∪ delta ACs — has ≥ 1 test citing it via `source:` (Gate 1, blocking)
+- **Cross-cutting coverage:** every concern in destructuring.md that affects this sub-feature has ≥ 1 dedicated test (Gate 1b, blocking)
+- **UI element coverage:** ≥ 80% cataloged elements (across shared + delta) appear in action steps (not only preconditions)
+- **Scenario balance:** negative ≥ 20%, boundary ≥ 10%, happy ≤ 50% — thresholds are **shapes**, not quotas
+- **Q2 shape:** smoke = happy paths only; balanced = + negatives + key edges; regression = + boundaries + state transitions + role combos
+
+**Test count is driven by coverage, not by a range.** Do NOT pad to hit a number. Do NOT cap to stay under a number. If a balanced sub-feature naturally produces 8 tests or 40 tests — both are correct as long as the points above are satisfied. Q2 picks the **shape** of coverage, not the size.
+
+---
+
+## Checklist & Dispatch Table
+
+Every step lives in its own file under `steps/`. SKILL.md is a router: Resume Detector below determines the entry point; then load the step file for the current step only.
+
+| # | Step | File | Key output | Phase |
+|---|---|---|---|---|
+| ☐ | **Resume Detector** (below) | this file | `$RESUME_FROM` step pointer | — |
+| 0 | Intake Questionnaire | [steps/00-intake.md](steps/00-intake.md) | A1 intake.md | feature |
+| 1 | Feature Phase (heavy gather once) | [steps/01-feature-phase.md](steps/01-feature-phase.md) | A-shared-ui + A-base + A-steps + A2 | feature |
+| 2 | Sub-feature Slice (thin) | [steps/10-sub-feature-slice.md](steps/10-sub-feature-slice.md) | A3 + A4 + A5 | sub-feature |
+| 3 | Generate & Approve Test Cases | [steps/20-generate.md](steps/20-generate.md) | A6 test-cases.md | sub-feature |
+| 4 | Final Report & Handoff | [steps/40-report.md](steps/40-report.md) | report printed; A2 progress updated; A-style captured on first approval; publish handoff | sub-feature |
+
+**HARD STOPs:** Step 1 ends with HARD STOP (feature phase → new conversation for first sub-feature). Step 4 ends with HARD STOP (sub-feature done → new conversation for next sub-feature).
+
+**Publishing is NOT part of this skill.** After Step 4, run your publisher — local `/publish-test-cases-batch {path}` (separate skill — not yet part of this repo) or [`sync-cases`](../sync-cases/SKILL.md).
+
+**Loading rule:** Read only the step file for the step you're currently executing, plus any referenced `references/*.md` files needed by its contract. Do NOT eagerly Read all step files at start of run.
+
+**Section-map loading (mandatory for large refs):** `references/testing-strategy.md`, `references/self-review-checks.md`, and `references/artifacts.md` each begin with a `## Section map` table listing the **START/END anchor patterns** (regex) for every section. When you need ONE section (e.g. "§ 2.3 balance thresholds" or "Gate 11"):
+
+```bash
+awk '/^START_PATTERN/,/^END_PATTERN/' path/to/ref.md
+```
+
+Copy the two patterns from the section map, paste into the awk one-liner, run via Bash. This is the primary context-window savings in Step 2. **Never Read the whole file** when one section is enough. Anchors are immune to line-number drift — the section map stays valid as long as section headers keep their text.
+
+---
+
+## Pre-step: Resume Detector
+
+Runs BEFORE Step 0 on every invocation. Single authoritative check replacing scattered "if exists skip" mentions elsewhere.
+
+### Contract
+- **Precondition:** none
+- **Input:** `$ARGUMENTS` (feature and optionally sub-feature); current working directory has `test-cases/` root
+- **Output:** detector table printed to user; `$RESUME_FROM` step pointer in working memory
+- **Postcondition:** user has seen which artifacts exist + chosen resume / restart / change path
+- **Idempotent:** yes — pure read-only probe
+- **Retry policy:** none — read errors bubble up as "artifact unreadable"
+
+### Procedure
+
+1. Derive `F` (feature-slug) and, if known from $ARGUMENTS, `S` (suite-slug from destructuring map)
+2. Run the cheap validation commands from [artifacts.md](references/artifacts.md) for each artifact. **Do NOT Read the bodies** — only `head -20` or grep-based checks
+3. Compute state via this decision tree (top-down, first match wins):
+
+| State | Trigger | Route |
+|---|---|---|
+| `empty` | A1 missing | Step 0 intake |
+| `feature-partial` | A1 valid but any of A-shared-ui / A-base / A2 missing or invalid | Step 1 (feature phase) — resume at first missing substep |
+| `feature-done, no sub-feature picked` | All feature artifacts valid, no `S` given and no unchecked sub-feature selected | Ask user which sub-feature to start (show map) |
+| `feature-done, all sub-features [x]` | A2 has all rows `[x]` | Suggest `/publish-test-cases-batch test-cases/{F}/` |
+| `sub-feature-partial` | `S` resolved; some of A3 / A4 / A5 missing or invalid | Step 2 — resume at first missing substep |
+| `sub-feature-ready` | A3-A5 valid, A6 missing | Step 3 (generate) |
+| `sub-feature-done` | A6 exists and valid | Ask: regenerate / next sub-feature / stop |
+
+4. Emit a **two-section** table to the user — feature-level + sub-feature-level:
+
+```
+Resume Detector — test-cases/{F} (sub-feature: {S or "—"})
+
+Feature level:
+| Artifact | Exists | Valid |
+|---------------------------|--------|-------|
+| A1 intake.md | Y | Y |
+| A-shared-ui _shared-ui.md | Y | Y |
+| A-base _ac-baseline.md | Y | Y |
+| A-steps _existing-steps.md| Y | Y |
+| A2 destructuring.md | Y | Y |
+| A-style _style.md | - | - |
+
+Sub-feature level (S={S}):
+| Artifact | Exists | Valid |
+|-----------------------|--------|-------|
+| A3 {S}-ac-delta.md | Y | Y |
+| A4 {S}-ui-delta.md | Y | Y |
+| A5 {S}-scope.md | Y | Y |
+| A6 {S}-test-cases.md | N | - |
+| A7 {S}-review.md | - | - |
+
+Suggested resume point: Step 3 (generate)
+ • feature + sub-feature slice complete — A6 missing
+```
+
+5. Ask user (one line):
+```
+[Y] Resume from Step {N} [R] Restart from Step 0 [P] Pick a different sub-feature [B] Abort
+```
+
+6. Route:
+ - `Y` → Read the step file for Step {N} and continue
+ - `R` → DANGEROUS. Ask user what scope of reset:
+ - `sub-feature` → delete A3-A7 under `test-cases/{F}/` for the current `S` only (keeps feature artifacts)
+ - `feature` → delete everything under `test-cases/{F}/` (asks explicit confirmation naming the path)
+ Only run `rm` after explicit confirmation.
+ - `P` → ask which sub-feature from A2 map, set new `S`, re-run detector
+ - `B` → exit skill
+
+**Auto-advance rule:** if feature is complete, `S` is unambiguously determined (argument matches a sub-feature in A2), and sub-feature-ready state applies → skip confirmation prompt and auto-resume at Step 3. Log: `Auto-resumed at Step 3 — baselines + delta + scope present.`
+
+---
+
+## Error Handling
+
+On any error (Playwright, push, MCP, partial run resume, blocking conditions) → see [troubleshooting.md](references/troubleshooting.md). It consolidates recoverable/blocking error matrix + Playwright browser traps + nested-suite parser gotchas. Load on demand, not eagerly.
diff --git a/skills/create-test-cases/intake-examples.md b/skills/create-test-cases/intake-examples.md
new file mode 100644
index 0000000..30ab83c
--- /dev/null
+++ b/skills/create-test-cases/intake-examples.md
@@ -0,0 +1,56 @@
+# Intake Questionnaire — Example Filled Intakes
+
+Reference examples for [intake-questionnaire.md](intake-questionnaire.md) Part 3 template.
+
+---
+
+## Example A — Minimal (all defaults)
+
+User argument: `"покрити labels"`
+User answered: `"use defaults"`
+
+```markdown
+# Intake: labels
+
+**Date:** 2026-04-10
+
+## Answers
+
+| # | Question | Answer |
+|---|----------|--------|
+| Q1 | Feature / scope | labels (from argument) |
+| Q1.1 | Feature location | Settings → Labels & Fields |
+| Q1.2 | Sub-feature hint (optional) | pick after map |
+| Q2 | Coverage depth | balanced |
+| Q3 | Sources | UI only |
+| Q4 | Special focus | none |
+
+## Defaults applied
+All questions (user said "use defaults"). Step 1 will produce the sub-feature map; user picks `S` from it before Step 2.
+```
+
+---
+
+## Example B — Full interview
+
+User argument: `"cover the new label-filter feature"`
+
+```markdown
+# Intake: label-filter
+
+**Date:** 2026-04-10
+
+## Answers
+
+| # | Question | Answer |
+|---|----------|--------|
+| Q1 | Feature / scope | new label-filter in tests list |
+| Q1.1 | Feature location | Tests page → top filter bar (next to Tags filter) |
+| Q1.2 | Sub-feature hint (optional) | label-filter (verified against Step 1 map before Step 2) |
+| Q2 | Coverage depth | balanced |
+| Q3 | Sources | https://github.com/testomatio/docs/pull/412, https://figma.com/file/abc123/label-filter |
+| Q4 | Special focus | validation, edge cases |
+
+## Defaults applied
+none
+```
diff --git a/skills/create-test-cases/intake-questionnaire.md b/skills/create-test-cases/intake-questionnaire.md
new file mode 100644
index 0000000..c545da1
--- /dev/null
+++ b/skills/create-test-cases/intake-questionnaire.md
@@ -0,0 +1,177 @@
+# Intake Questionnaire
+
+Front-loaded interview that replaces scattered gates in Steps 2-3. Runs as Step 0 of the skill, before any gathering.
+
+**See also:** [intake-examples.md](intake-examples.md) — filled-in intake samples to learn the expected shape before running.
+
+**Purpose:**
+- Collect all preferences in one sitting so the skill runs without interruption until Step 3
+- Build an audit trail in `test-cases/{feature-slug}/intake.md`
+- Let the skill adapt its behavior based on user answers (sources, depth, focus, language)
+
+**Language rule:** questions are in English, user may answer in any language (English / Ukrainian / mix). Skill interprets natural answers.
+
+---
+
+## Part 1: Flow Rules
+
+### Core rules
+- Run once per invocation, before Step 1, after reading argument + memory
+- Ask **one question at a time** — wait for answer, then ask next
+- If a previous answer makes a later question unnecessary → skip silently
+- `"use defaults"` / `"за замовчуванням"` / `"just go"` → skip all, use defaults
+- `"not sure"` / `"не знаю"` → take the default silently, do NOT re-prompt
+
+### Smart-skip (fill defaults silently)
+
+| Skip | When |
+|---|---|
+| Q1 | Argument is a Testomat suite URL or clear feature name |
+| Q1.1 | Argument is an app URL, or memory has `project_{feature}_*.md` with a path |
+| Q1.2 | Argument names a specific sub-feature (e.g., "Manual Test Execution → Environment Configuration") — record as preferred starting point; still verified against map after Step 1 |
+| Q3 | User's argument already contains resource links |
+
+### Re-run handling
+If `test-cases/{feature-slug}/intake.md` exists, show summary and ask:
+
+```
+I found previous intake for {feature-name}:
+
+ Feature: {Q1} Coverage: {Q2}
+ Focus: {Q4} Sources: {Q3 links or "UI only"}
+ Saved: {file mtime}
+
+Use these answers? [Y] Reuse [N] Start fresh [E] Edit specific
+```
+
+---
+
+## Part 2: Questions
+
+### Q1: Feature / scope
+**Type:** free text
+**Default:** from argument if present
+**Prompt:**
+```
+Q1. What feature or scope are we covering?
+ (feature name, Testomat suite URL, or short description)
+```
+
+---
+
+### Q1.1: Feature location in the product
+**Type:** free text | **Default:** none — always ask unless argument is a URL
+**Prompt:**
+```
+Q1.1. Where in the product is this feature located?
+ (menu path, URL, or short navigation hint — e.g.
+ "Settings → Labels & Fields", "/projects/{slug}/runs", "right sidebar of test detail page")
+```
+Accept any form: menu path, URL, screen name. Multiple screens → comma-separated. Unknown → start from dashboard.
+
+---
+
+### Q1.2: Sub-feature (suite) hint (optional)
+**Type:** free text | **Default:** `pick after map` — Step 1 (feature phase) will produce a sub-feature map and you can choose from it
+**Prompt:**
+```
+Q1.2. Do you have a specific sub-feature in mind for the FIRST run? (optional)
+ (I'll run the feature phase first and produce a sub-feature map + shared artifacts.
+ After the map is approved, you pick ONE sub-feature per conversation — example:
+ "Environment Configuration".)
+
+ Answer with the sub-feature name, or "pick after map" / "не знаю" to decide later.
+```
+- `pick after map` / `suggest` / `не знаю` / empty → proceed to Step 1 (feature phase) and let the map drive the choice
+- A specific sub-feature name → recorded as a preferred starting point; still verified against the Step 1 map before Step 2 begins
+- Feature-first is always on — the feature phase produces `_shared-ui.md` + `_ac-baseline.md` + destructuring map even when the user knows which sub-feature they want, because those artifacts are reused by every subsequent sub-feature conversation
+
+---
+
+### Q2: Coverage depth
+**Type:** single choice | **Default:** `balanced`
+**Prompt:**
+```
+Q2. Coverage depth?
+ [1] Smoke — only happy paths, skip negatives and edge cases
+ [2] Balanced — happy + negatives + key edge cases, skip rare boundaries (default)
+ [3] Regression — everything incl. boundaries, state transitions, role combos
+ [4] Custom — tell me specifics
+
+ Q2 picks the SHAPE of coverage, not a target count. Each skill run covers ONE sub-feature in depth.
+```
+
+On `[4]` → ask: *"Describe what to include/exclude in 1-2 sentences."*
+
+Test count is driven by what's needed to fully cover the sub-feature (all ACs, scenario balance thresholds, UI elements in action steps) — there is no target range. If balanced naturally produces 8 tests or 40 tests, both are correct. Focus on what's included/excluded, not on hitting a count.
+
+---
+
+### Q3: Sources of truth
+
+**Type:** single open question
+**Default:** UI exploration only (Playwright MCP)
+**Prompt:**
+```
+Q3. Any docs or specs I should use as input?
+ Paste links (GitHub docs, Jira, Figma, Confluence — comma-separated), or "no" for UI-only.
+ UI exploration via Playwright is always included unless you say "no UI".
+```
+
+**Rules:**
+- UI exploration (Playwright) is always on by default — user must explicitly say "no UI" to disable
+- Record each provided link in the intake file
+- Fetch each link in Step 1.1 before AC extraction
+- If user provides no links and says "no UI" → prompt: *"I need at least one source. Can I at least explore the UI?"*
+
+---
+
+### Q4: Special focus
+**Type:** multi-select
+**Default:** none (balanced output)
+**Prompt:**
+```
+Q4. Any special focus areas? (pick 0 or more)
+ [1] Security & permissions — role checks, unauthorized access, data leaks
+ [2] Validation & error messages — exact texts, boundary values, required fields
+ [3] Edge cases & race conditions — double-clicks, concurrent actions, network drops
+ [4] Data persistence — survives refresh, re-login, navigate away and back
+ [5] Bulk operations — multi-select, bulk actions, large selections
+ [6] UI / UX — visual states, empty states, loading states
+ [7] None — balanced (default)
+
+ Answer with comma-separated numbers (e.g. "1, 2") or "none".
+```
+
+Multi-select is fine — multiple focus areas add emphasis to the generated checklist without excluding anything else.
+
+**Slug rules** (for suite directory naming): lowercase, spaces → hyphens, strip special chars.
+
+---
+
+## Part 3: Output Template
+
+Save to `test-cases/{feature-slug}/intake.md`:
+
+```markdown
+# Intake: {feature-name}
+
+**Date:** YYYY-MM-DD
+
+## Answers
+
+| # | Question | Answer |
+|---|----------|--------|
+| Q1 | Feature / scope | {free text} |
+| Q1.1 | Feature location | {menu path / URL / screen name(s)} |
+| Q1.2 | Sub-feature hint (optional) | {sub-feature name or "pick after map"} |
+| Q2 | Coverage depth | smoke (happy only) / balanced (+ negatives + key edges) / regression (+ boundaries + state + roles) / custom: "{text}" |
+| Q3 | Sources | {links or "UI only"} |
+| Q4 | Special focus | {list or "none"} |
+
+## Defaults applied
+{List defaults applied silently, or "none"}
+```
+
+Examples: [intake-examples.md](intake-examples.md)
+
diff --git a/skills/create-test-cases/references/artifacts.md b/skills/create-test-cases/references/artifacts.md
new file mode 100644
index 0000000..fd85ba5
--- /dev/null
+++ b/skills/create-test-cases/references/artifacts.md
@@ -0,0 +1,750 @@
+# Artifact State Machine
+
+Canonical source of truth for every file the skill produces and consumes. Every step in SKILL.md references this file instead of restating schemas.
+
+**Loading rule:** loaded by Step 0 Resume Detector once per run. Other steps may Read only the frontmatter of an artifact for cheap validation — do NOT re-Read this file per step.
+
+## Section map (anchor-based — stable across edits)
+
+Extract ONE section via a single `awk` call — never Read the whole file:
+
+```bash
+awk '/^START_PATTERN/,/^END_PATTERN/' .claude/skills/create-test-cases/references/artifacts.md
+```
+
+| Section | START pattern | END pattern (exclusive) |
+|---|---|---|
+| Artifact list (feature-level + sub-feature-level) | `^## Artifact list` | `^## A1 ` |
+| A1 intake.md (feature) | `^## A1 ` | `^## A2 ` |
+| A2 destructuring.md (feature) | `^## A2 ` | `^## A-base ` |
+| A-base _ac-baseline.md (feature) | `^## A-base ` | `^## A-shared-ui ` |
+| A-shared-ui _shared-ui.md (feature) | `^## A-shared-ui ` | `^## A-steps ` |
+| A-steps _existing-steps.md (feature) | `^## A-steps ` | `^## A3 ` |
+| A3 {S}-ac-delta.md (sub-feature) | `^## A3 ` | `^## A4 ` |
+| A4 {S}-ui-delta.md (sub-feature) | `^## A4 ` | `^## A5 ` |
+| A5 {S}-scope.md (sub-feature) | `^## A5 ` | `^## A6 ` |
+| A6 {S}-test-cases.md / {S}/*.md (sub-feature) | `^## A6 ` | `^## A7 ` |
+| A7 {S}-review.md (sub-feature) | `^## A7 ` | `^## A-style ` |
+| A-style _style.md (feature, captured after first approval) | `^## A-style ` | `^## State transitions` |
+| State transitions | `^## State transitions` | `^## Phase 3a gate-check` |
+| Phase 3a gate-check recipes (intro + vars) | `^## Phase 3a gate-check` | `^### Gate 1 ` |
+| Gate 1 AC coverage | `^### Gate 1 ` | `^### Gate 2 ` |
+| Gate 2 Priority pyramid | `^### Gate 2 ` | `^### Gate 3 ` |
+| Gate 3 Automation classification | `^### Gate 3 ` | `^### Gate 4 ` |
+| Gate 4 Manual-only rate | `^### Gate 4 ` | `^### Gate 5 ` |
+| Gate 5 Forbidden metadata | `^### Gate 5 ` | `^### Gate 6 ` |
+| Gate 6 Scope compliance | `^### Gate 6 ` | `^### Gate 7 ` |
+| Gate 7 Role names | `^### Gate 7 ` | `^### Gate 8 ` |
+| Gate 8 Min step count | `^### Gate 8 ` | `^### Gate 9 ` |
+| Gate 9 Forbidden `id:` | `^### Gate 9 ` | `^### Gate 10 ` |
+| Gate 10 Sub-suite distribution | `^### Gate 10 ` | `^### Gate 11 ` |
+| Gate 11 Impl leakage | `^### Gate 11 ` | `^### Gate 12 ` |
+| Gate 12 Parameterized `${col}` | `^### Gate 12 ` | `^## Resume Detector` |
+| Resume Detector input | `^## Resume Detector` | end-of-file (use `awk '/^## Resume Detector/{p=1} p'`) |
+
+---
+
+## Artifact list
+
+All paths are relative to repo root. `{F}` = feature-slug, `{S}` = suite-slug.
+
+**Feature-level** (`_` prefix = shared across sub-features). Produced once by the Feature Phase (Step 1). Consumed by every Sub-feature Phase run in the same feature.
+
+| # | Path | Producer | Consumers | Required? | Lifecycle |
+|---|------|----------|-----------|-----------|-----------|
+| A1 | `test-cases/{F}/intake.md` | Step 0 | all later steps | **Yes** | Read-only after Step 0. Re-written only on explicit user "start fresh" |
+| A2 | `test-cases/{F}/destructuring.md` | Step 1.1 (feature phase, ui-explorer mode: feature-baseline) | Step 2 (picks sub-feature row), Step 3 Phase 0 (cross-cutting), Step 4 (toggle `[x]`) | **Yes** | **Mutable** — Step 4 toggles `- [ ]` → `- [x]` per approved sub-feature |
+| A-base | `test-cases/{F}/_ac-baseline.md` | Step 1.2 (docs fetch) | Step 2.1 (filter applicable), Step 3 Phase 1 (checklist), test-case-reviewer Gate 1 | **Yes** | Read-only after Step 1.2. Can be manually expanded by user before proceeding |
+| A-shared-ui | `test-cases/{F}/_shared-ui.md` | Step 1.1 (ui-explorer mode: feature-baseline) | Step 2.2 (delta exploration baseline), Step 3 Phase 3b (ui-validator), Gate 11 impl-leak check | **Yes** | Read-only after Step 1.1. May be manually edited if user spots missing shared element |
+| A-steps | `test-cases/{F}/_existing-steps.md` | Step 1.3 (Testomat MCP) | Step 3 Phase 2 (test generation — reuses existing steps) | No (optional; skipped if Testomat MCP unavailable) | Read-only after Step 1.3 |
+| A-style | `test-cases/{F}/_style.md` | Step 4 (FIRST approved sub-feature only) | Step 3 Phase 2 of every SUBSEQUENT sub-feature in the same feature | No (only exists after at least 1 sub-feature approved) | Written once; NOT overwritten on subsequent approvals (user-editable) |
+
+**Sub-feature-level** — produced per sub-feature. Written under `test-cases/{F}/` with `{S}-` prefix (flat) or under a nested directory `test-cases/{F}/{S}/` (nested layout).
+
+| # | Path | Producer | Consumers | Required? | Lifecycle |
+|---|------|----------|-----------|-----------|-----------|
+| A3 | `test-cases/{F}/{S}-ac-delta.md` | Step 2.1 | Step 3 Phase 1 (checklist), Step 3 Phase 3a Gate 1 (combined with A-base) | **Yes** | Read-only after Step 2.1 |
+| A4 | `test-cases/{F}/{S}-ui-delta.md` | Step 2.2 (ui-explorer mode: sub-feature-delta) | Step 3 Phase 1/2, Step 3 Phase 3b (ui-validator, combined with A-shared-ui) | **Yes** | May be **appended** by gap-focused ui-explorer re-invocation (Step 2.x retry) |
+| A5 | `test-cases/{F}/{S}-scope.md` | Step 2.3 | Step 3 Phase 3a (scope compliance), test-case-reviewer subagent | **Yes** | Read-only after Step 2.3 |
+| A6 | `test-cases/{F}/{S}-test-cases.md` **OR** `test-cases/{F}/{S}/*.md` | Step 3 Phase 2 | Step 3 Phase 3a (mechanical), Phase 3b (ui-validator), Step 4, handoff to `/publish-test-cases-batch` | **Yes** | **Mutable** — Phase 3a auto-fix, Phase 3b in-place fixes, Phase 4 iteration |
+| A7 | `test-cases/{F}/{S}-review.md` | test-case-reviewer subagent (suites ≥15) | Phase 4 presentation | Only for ≥15-test suites | Read-only after subagent run |
+
+---
+
+## A1 — intake.md
+
+**Schema:** see [intake-questionnaire.md § Part 3 Output Template](../intake-questionnaire.md).
+
+**Cheap validation** (used by Resume Detector):
+```bash
+grep -q '^| Q1 |' test-cases/{F}/intake.md && \
+grep -q '^| Q1.2 |' test-cases/{F}/intake.md && \
+grep -q '^| Q2 |' test-cases/{F}/intake.md
+```
+All three must match. If any missing → intake is incomplete, re-run Step 0 with "Edit specific".
+
+**Sub-feature hint:** Q1.2 may contain a named starting sub-feature or `pick after map`. Either way, Step 1 (feature phase) runs first and Step 2 resolves `S` against the approved map.
+
+---
+
+## A2 — destructuring.md
+
+**Schema:** see [destructuring.md § Procedure step 4 & step 9](destructuring.md).
+
+**Producer:** Step 1.1 (feature phase). `ui-explorer` invoked with `mode: feature-baseline` traverses the feature holistically and returns BOTH `_shared-ui.md` (A-shared-ui) AND the sub-feature map written here. Cross-cutting concerns section is added in Step 1.4.
+
+**Cheap validation:**
+```bash
+grep -q '^## Cross-cutting concerns' test-cases/{F}/destructuring.md && \
+grep -q '^- \[[x ]\]' test-cases/{F}/destructuring.md
+```
+
+**Mutability:** Step 4 toggles `- [ ]` → `- [x]` for the just-completed sub-feature. Never edit anything else.
+
+**Terminal state:** all lines match `^- \[x\]` → user can run `/publish-test-cases-batch test-cases/{F}/` to push the whole feature.
+
+---
+
+## A-base — _ac-baseline.md (feature-level)
+
+**Purpose:** flat list of ACs extracted once from product docs/help center for the entire feature. Each sub-feature later references applicable AC IDs without re-extracting. Replaces per-sub-feature `{S}-ac-list.md` full body with a shared source.
+
+**Path:** `test-cases/{F}/_ac-baseline.md`
+
+**Producer:** Step 1.2 (feature phase, after UI baseline exists). Docs are fetched with WebFetch; inferred ACs come from product knowledge if docs are thin.
+
+**Consumers:** Step 2.1 (filter baseline ACs applicable to a sub-feature), Step 3 Phase 1 checklist, Gate 1 AC coverage (combined with `{S}-ac-delta.md`).
+
+**Schema (frontmatter required):**
+```yaml
+---
+feature: {feature-slug}
+source: docs | inferred | mixed
+sources:
+ - {url or doc path}
+ - ...
+ac_count: N
+generated_at: {ISO8601}
+---
+
+AC-1: {verifiable requirement}
+AC-2: ...
+```
+
+Body is a flat list of `AC-N: ...` lines. IDs are **feature-global** — `AC-17` in baseline is the same AC-17 for every sub-feature. `UNCLEAR` items keep `AC-N: UNCLEAR — {question}`.
+
+**Cheap validation:**
+```bash
+head -10 test-cases/{F}/_ac-baseline.md | grep -q '^ac_count:' && \
+ actual=$(grep -cE '^AC-[0-9]+:' test-cases/{F}/_ac-baseline.md) && \
+ [ "$actual" -ge 1 ]
+```
+
+**Mutability:** read-only after Step 1.2. User may manually append/clarify ACs before Step 1.5 approval. Never written by any sub-feature phase.
+
+---
+
+## A-shared-ui — _shared-ui.md (feature-level)
+
+**Purpose:** catalog of UI elements shared across the feature (top nav, breadcrumbs, sidebar, feature-wide toolbars, common modals, bulk-action bars, global toasts). Explored once in Step 1.1; each sub-feature delta references but never re-catalogs these.
+
+**Path:** `test-cases/{F}/_shared-ui.md`
+
+**Producer:** Step 1.1 (feature phase). `ui-explorer` subagent invoked with `mode: feature-baseline` — walks the feature's main surfaces at a breadth-first level, identifies candidate sub-features, catalogs shared chrome.
+
+**Consumers:** Step 2.2 (ui-explorer `sub-feature-delta` mode receives this path as `shared_catalog_path` to avoid re-cataloging), Step 3 Phase 3b ui-validator (combined with `{S}-ui-delta.md`), Gate 11 implementation-leak check.
+
+**Schema:** same format as [ui-catalog-format.md](ui-catalog-format.md), with feature-baseline frontmatter:
+
+```yaml
+---
+feature: {F}
+scope: feature-baseline
+entry_url: {url}
+explored_at: {ISO8601}
+explored_by: ui-explorer
+mode: feature-baseline
+shared_surfaces: N # count of surfaces cataloged (nav, sidebar, modals, etc.)
+candidate_sub_features: M # count of sub-features identified for destructuring
+gaps: count
+---
+```
+
+**Cheap validation:**
+```bash
+head -20 test-cases/{F}/_shared-ui.md | \
+ awk '/^mode: feature-baseline/{m=1} /^shared_surfaces: [1-9]/{s=1} END{exit !(m && s)}'
+```
+
+**Mutability:** read-only after Step 1.1. User may manually add a missed shared element before Step 1.5 approval.
+
+---
+
+## A-steps — _existing-steps.md (feature-level)
+
+**Purpose:** reusable step phrases already defined in Testomat.io for this feature's suite(s) — so Step 3 Phase 2 can prefer matching wording over inventing new phrasings and avoid step-library churn.
+
+**Path:** `test-cases/{F}/_existing-steps.md`
+
+**Producer:** Step 1.3 (feature phase). Uses Testomat MCP (`mcp__testomatio__steps_list` / `steps_search`) to fetch steps tagged or linked to this feature. Optional — skip if MCP unavailable or feature has no prior coverage.
+
+**Consumers:** Step 3 Phase 2 (test generation — reuses existing step phrases when semantically equivalent).
+
+**Schema:**
+```markdown
+---
+feature: {F}
+fetched_at: {ISO8601}
+step_count: N
+source: testomatio-mcp
+---
+
+## Existing step phrases
+
+- I log in as ${role}
+- I open Settings → Labels
+- ...
+```
+
+**Cheap validation:**
+```bash
+test ! -f test-cases/{F}/_existing-steps.md || \
+ (head -10 test-cases/{F}/_existing-steps.md | grep -q '^step_count:')
+```
+(Artifact is optional — validation passes if file absent OR if present with frontmatter.)
+
+**Mutability:** read-only after Step 1.3. Stale after long periods — can be regenerated manually via Testomat MCP if needed.
+
+---
+
+## A3 — {S}-ac-delta.md (sub-feature)
+
+**Purpose:** sub-feature-specific AC layer. Instead of re-listing all feature ACs, records (a) which baseline ACs apply to this sub-feature and (b) additional ACs that emerged from sub-feature-specific exploration or docs.
+
+**Path:** `test-cases/{F}/{S}-ac-delta.md`
+
+**Producer:** Step 2.1 (sub-feature slice). Reads `_ac-baseline.md`, filters applicable IDs, adds delta.
+
+**Consumers:** Step 3 Phase 1 checklist (merged with baseline), Phase 3a Gate 1 AC coverage (combined pool = `baseline_acs_applicable` + delta `AC-*`).
+
+**Schema (frontmatter required):**
+```yaml
+---
+feature: {feature-slug}
+suite: {suite-slug}
+references: _ac-baseline.md
+baseline_acs_applicable: [AC-3, AC-7, AC-12] # IDs from _ac-baseline.md that this sub-feature must cover
+delta_ac_count: N # count of NEW ACs below (ac-delta-*)
+source: inferred | docs | mixed
+---
+
+## Baseline ACs applicable to {S}
+- AC-3 (baseline)
+- AC-7 (baseline)
+- AC-12 (baseline)
+
+## Delta ACs (sub-feature-specific)
+
+ac-delta-1: {new verifiable requirement found only in this sub-feature}
+ac-delta-2: ...
+```
+
+Delta AC IDs use `ac-delta-N` prefix to keep them visually distinct from feature-global `AC-N`. If a sub-feature has zero delta, `delta_ac_count: 0` and the Delta ACs section is empty but the heading remains.
+
+**Cheap validation:**
+```bash
+head -15 test-cases/{F}/{S}-ac-delta.md | grep -q '^references: _ac-baseline.md' && \
+ head -15 test-cases/{F}/{S}-ac-delta.md | grep -qE '^baseline_acs_applicable: \[' && \
+ grep -qE '^## Baseline ACs applicable' test-cases/{F}/{S}-ac-delta.md
+```
+At least one baseline AC must be applicable (sub-features that touch zero baseline ACs suggest destructuring error — flag to user).
+
+**Mutability:** read-only after Step 2.1.
+
+---
+
+## A4 — {S}-ui-delta.md (sub-feature)
+
+**Purpose:** UI elements **specific** to this sub-feature that are NOT in `_shared-ui.md`. Avoids re-cataloging feature-wide chrome (nav, sidebar, common modals).
+
+**Path:** `test-cases/{F}/{S}-ui-delta.md`
+
+**Producer:** Step 2.2 (sub-feature slice). `ui-explorer` invoked with `mode: sub-feature-delta` and `shared_catalog_path: test-cases/{F}/_shared-ui.md`. Subagent reads the shared catalog first, then explores this sub-feature's unique surfaces and writes ONLY the delta.
+
+**Consumers:** Step 3 Phase 1/2 (generation references both shared + delta), Phase 3b ui-validator (combined view), Gate 11 impl-leak check.
+
+**Schema:** same format as [ui-catalog-format.md](ui-catalog-format.md), with delta frontmatter:
+
+```yaml
+---
+feature: {F}
+suite: {S}
+scope: sub-feature-delta
+references: _shared-ui.md
+entry_url: {sub-feature url}
+explored_at: {ISO8601}
+explored_by: ui-explorer
+mode: sub-feature-delta
+delta_elements: N # NEW elements added here (excluding anything in _shared-ui.md)
+verified_flows: K # sub-feature-specific flows
+gaps: count
+---
+```
+
+Body contains ONLY elements not already in `_shared-ui.md`. If an element visible in this sub-feature also appears in shared (e.g., global Save toolbar), it is NOT repeated — consumers read both files.
+
+**Cheap validation:**
+```bash
+head -20 test-cases/{F}/{S}-ui-delta.md | \
+ awk '/^mode: sub-feature-delta/{m=1} /^references: _shared-ui.md/{r=1} /^delta_elements: [0-9]+/{d=1} END{exit !(m && r && d)}'
+```
+`delta_elements: 0` is allowed (sub-feature has no unique elements, lives entirely on shared surfaces) but rare — flag to user for confirmation when this happens.
+
+**Mutability:** `ui-explorer` may append a "Gap-focused follow-up" section on retry. Frontmatter `gaps` count is updated in place.
+
+---
+
+## A5 — {S}-scope.md
+
+**Schema:**
+```markdown
+# Scope: {feature} / {suite}
+
+**Date:** YYYY-MM-DD
+
+## In Scope
+- {item} — covers AC-N
+- ...
+
+## Out of Scope
+- {item} — reason: {justification}
+- ...
+
+## Unclear ACs
+- AC-N: {question} — {resolution or "deferred"}
+
+## Sources Used
+- {source link or "UI catalog only"}
+```
+
+**Cheap validation:**
+```bash
+for h in '^## In Scope' '^## Out of Scope' '^## Unclear ACs' '^## Sources Used'; do
+ grep -q "$h" test-cases/{F}/{S}-scope.md || { echo "missing: $h"; exit 1; }
+done
+```
+All four headings must exist.
+
+---
+
+## A6 — {S}-test-cases.md / {S}/*.md
+
+**Schema:** see [test-case-format.md](test-case-format.md).
+
+**Flat vs nested decision:** single file if Phase 1 Grouping wrote `Output: flat`; directory if `Output: nested`. Mismatch = Phase 3a violation.
+
+**Cheap validation:**
+```bash
+# flat
+test -f "test-cases/{F}/{S}-test-cases.md" && \
+ grep -cE '^## ' "test-cases/{F}/{S}-test-cases.md"
+# nested
+test -d "test-cases/{F}/{S}" && \
+ find "test-cases/{F}/{S}" -name '*.md' -type f | wc -l
+```
+
+Test count must equal number of `^## ` lines (minus 1 for `## Steps` inside each test — grep for `^## (?!Steps)` is more precise; use `grep -cE '^## ' file | awk '{print $1 - N_steps_headings}'`).
+
+See [Phase 3a gate-check recipes](#phase-3a-gate-check-recipes) below for the canonical counting commands.
+
+**Mutability:**
+- Phase 3a mechanical: test-case-reviewer auto-fixes (scope compliance, role names, step quality)
+- Phase 3b ui-validator: in-place fixes for element names, toast text, step mechanics
+- Phase 4: regeneration on user reject (overwrites)
+
+---
+
+## A7 — {S}-review.md
+
+Produced by `test-case-reviewer` subagent for suites ≥15 tests. Free-form violations report.
+
+**Cheap validation:**
+```bash
+test -f test-cases/{F}/{S}-review.md && \
+ grep -q '^violations:' test-cases/{F}/{S}-review.md
+```
+
+---
+
+## A8 — {S}-validation-log.md (sub-feature)
+
+**Purpose:** audit trail written by the `ui-validator` subagent during Step 3 Phase 3b. Captures which tests were walked in the real UI, which `_Expected_:` mismatches were fixed, and which gaps (unresolvable element names, missing UI surfaces) remain. **Not published to Testomat.io.**
+
+**Path:** `test-cases/{F}/{S}-validation-log.md` — sub-feature-level aggregate. For nested suites, ALL section files (e.g. `dialog-lifecycle.md`, `form-fields.md`) share a single log file; each validation run appends a new `## Section: {section_label}` block.
+
+**Why separate from A6 test MD:** Testomat.io's markdown parser treats top-level `##` headings as suite/test boundaries. Appending a `## Validation Log` section inside the test MD creates a phantom test or breaks the nested-suite structure. Regression detected 2026-04-20: 20 test files had `## Validation Log` leaked from Phase 3b and had to be stripped retroactively.
+
+**Schema:**
+```markdown
+# Validation Log: {suite_slug}
+
+Aggregated audit trail written by ui-validator subagent during Step 3 Phase 3b. Not published to Testomat.io.
+
+## Section: {section_label}
+
+**Validated by:** ui-validator (subagent)
+**Validated at:** {ISO8601}
+**Test MD:** {relative path}
+**Tests walked:** {test titles}
+**Mismatches fixed:** {count}
+**Gaps:** {count} — {one-line per gap}
+
+{Optional free-form notes: actual UI strings verified, discrepancies with catalog, etc.}
+```
+
+**Producer:** `ui-validator` subagent (Step 3 Phase 3b). Creates file on first validation; appends new `## Section:` block on subsequent validations within the same sub-feature.
+
+**Consumer:** humans reviewing what changed; Step 4 report (can reference `Mismatches fixed: N` in the final sub-feature report); future audits / retrospectives.
+
+**Cheap validation:**
+```bash
+test -f test-cases/{F}/{S}-validation-log.md && \
+ grep -qE '^(# Validation Log|## Section:)' test-cases/{F}/{S}-validation-log.md
+```
+
+**Mutability:** skill appends; user may manually prune old entries. Never deleted by the skill automatically.
+
+**Edge cases:**
+- **Zero mismatches, zero gaps** — still write a section entry with `Mismatches fixed: 0 | Gaps: 0` so the audit trail records that validation happened. Silence would be ambiguous ("didn't run" vs "ran clean").
+- **Sub-feature is flat (single MD file)** — `section_label` equals the suite slug itself; file name still follows `{S}-validation-log.md`.
+
+---
+
+## A-style — _style.md (feature-level)
+
+**Purpose:** capture style patterns from the FIRST approved sub-feature of a feature so every subsequent sub-feature stays stylistically consistent (preconditions phrasing, step granularity, voice, title pattern, tags, automation defaults). Prevents drift between sub-feature #1 and #5 when each is generated in a separate conversation (context-isolated).
+
+**Path:** `test-cases/{F}/_style.md` — `_` prefix signals feature-level shared artifact (not suite-scoped).
+
+**Schema:** see template in [steps/40-report.md § step 3 Style capture](../steps/40-report.md).
+
+**Producer:** Step 4, only on the FIRST sub-feature to flip from `[ ]` to `[x]` in destructuring.md. On subsequent approvals Step 4 checks existence and **skips write** — the user may have edited the file manually and the skill must not clobber their edits.
+
+**Consumer:** Step 3 Phase 2 of every subsequent sub-feature in the same feature. The Phase 2 header instructs: "if `_style.md` exists → Read it FIRST, match conventions exactly".
+
+**Cheap validation:**
+```bash
+test -f test-cases/{F}/_style.md && \
+ grep -qE '^## (Preconditions|Steps|Titles|Tags)' test-cases/{F}/_style.md
+```
+At least one of the four section headers must be present. If validation fails → treat as absent (do not read); Step 3 of the next approved sub-feature will overwrite.
+
+**Mutability:** write-once by the skill; user-editable thereafter. If the user wants to reset the style (e.g., they realize after #2 that #1's style was wrong), they manually delete `_style.md` → next approval re-captures from the new reference.
+
+**Edge cases:**
+- **Single-sub-feature feature (only one row in destructuring.md):** file is still created on first approval — harmless, since there's no "next" sub-feature to reuse it; it simply documents style for future additions
+- **Style contradicts current sub-feature's needs:** generator should still match `_style.md`; if a Phase 3 gate fails because of the style constraint → surface to user with option "accept one-off deviation for this sub-feature" vs "update `_style.md` going forward"
+
+---
+
+## State transitions
+
+```
+FEATURE PHASE (one conversation, HARD STOP at end)
+
+ (empty) ──Step 0──▶ A1 intake
+ │
+ ├─Step 1.1─▶ A-shared-ui + A2 (map) (ui-explorer: feature-baseline)
+ ├─Step 1.2─▶ A-base (_ac-baseline.md) (docs fetch)
+ ├─Step 1.3─▶ A-steps (optional) (Testomat MCP)
+ └─Step 1.4─▶ A2 cross-cutting section added
+ [HARD STOP — user approves map + baselines]
+
+SUB-FEATURE PHASE (one conversation per sub-feature, repeats N times)
+
+ A1 + A2 + A-base + A-shared-ui (+ A-steps)
+ │
+ ├─Step 2.1─▶ A3 {S}-ac-delta (references A-base)
+ ├─Step 2.2─▶ A4 {S}-ui-delta (ui-explorer: sub-feature-delta, references A-shared-ui)
+ └─Step 2.3─▶ A5 {S}-scope
+ │
+ └─Step 3 Phase 2─▶ A6 test-cases
+ │
+ ├─Phase 3a/3b (mutates A6, may produce A7)
+ │
+ └─Step 4─▶ toggles A2 [x]; on FIRST approval writes A-style (_style.md)
+ [HARD STOP — next sub-feature starts fresh conversation]
+```
+
+Publishing (branch creation, push, label application, batch) is owned by `/publish-test-cases-batch` — outside this state machine.
+
+---
+
+## Phase 3a gate-check recipes
+
+Every check below exits 0 on pass, non-zero on fail. SKILL.md Phase 3a runs these as a batch — any non-zero exit blocks Phase 4 and routes back to regeneration.
+
+**Convention in this section:** bash vars `F` = feature-slug, `S` = suite-slug, `MD` = A6 path (flat file **or** concatenation of nested files).
+
+### Set up variables for a run
+
+```bash
+F="manual-tests-execution"
+S="time-tracking"
+# Resolve A6 path
+if [ -f "test-cases/$F/$S-test-cases.md" ]; then
+ MD="test-cases/$F/$S-test-cases.md"
+ MDS=("$MD")
+elif [ -d "test-cases/$F/$S" ]; then
+ MDS=(test-cases/$F/$S/*.md)
+ MD="${MDS[0]}" # primary for header checks
+else
+ echo "A6 missing"; exit 1
+fi
+```
+
+### Gate 1 — Every AC has ≥1 test
+
+AC pool = (baseline ACs applicable to this sub-feature) ∪ (delta ACs from `{S}-ac-delta.md`).
+
+```bash
+# Applicable baseline ACs come from the frontmatter list `baseline_acs_applicable: [AC-3, AC-7, ...]`
+base_acs=$(awk '/^baseline_acs_applicable:/{
+ sub(/^baseline_acs_applicable: *\[/, ""); sub(/\].*$/, "");
+ gsub(/,/, " "); gsub(/ +/, " "); print; exit
+}' "test-cases/$F/$S-ac-delta.md")
+delta_acs=$(grep -oE '^ac-delta-[0-9]+' "test-cases/$F/$S-ac-delta.md" | sort -u)
+ac_ids="$base_acs $delta_acs"
+missing=0
+for ac in $ac_ids; do
+ [ -z "$ac" ] && continue
+ if ! grep -qE "^source:.*\b$ac\b" "${MDS[@]}"; then
+ echo "uncovered: $ac"
+ missing=$((missing+1))
+ fi
+done
+[ $missing -eq 0 ]
+```
+
+### Gate 2 — Priority pyramid in bounds
+
+```bash
+total=$(grep -cE '^priority:' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+crit=$(grep -cE '^priority: critical' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+high=$(grep -cE '^priority: high' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+norm=$(grep -cE '^priority: normal' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+low=$(grep -cE '^priority: low' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+# Advisory for <15 tests, blocking for ≥15
+if [ $total -ge 15 ]; then
+ awk -v c=$crit -v h=$high -v n=$norm -v l=$low -v t=$total 'BEGIN{
+ if (c/t > 0.15) { print "critical > 15%"; exit 1 }
+ if (h/t > 0.35) { print "high > 35%"; exit 1 }
+ if (n/t < 0.35) { print "normal < 35%"; exit 1 }
+ if (l/t < 0.05) { print "low < 5%"; exit 1 }
+ }'
+fi
+```
+
+### Gate 3 — Automation classification present on every test
+
+```bash
+tests=$(grep -cE '^## ' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+# subtract "## Steps" headings
+steps=$(grep -cE '^## Steps$' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+real_tests=$((tests - steps))
+auto=$(grep -cE '^automation: (candidate|deferred|manual-only)' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+[ "$auto" -eq "$real_tests" ]
+```
+
+### Gate 4 — Manual-only rate ≤30%
+
+```bash
+manual=$(grep -cE '^automation: manual-only' "${MDS[@]}" | awk -F: '{s+=$NF} END{print s}')
+awk -v m=$manual -v t=$real_tests 'BEGIN{exit !(t==0 || m/t <= 0.30)}'
+```
+
+### Gate 5 — No forbidden metadata fields (break push)
+
+```bash
+! grep -qE '^(tags|labels):' "${MDS[@]}"
+```
+
+### Gate 6 — Scope compliance (no OUT OF SCOPE items leaked in)
+
+```bash
+# OUT OF SCOPE item lines look like "- {item} — reason: ..."
+oos=$(awk '/^## Out of Scope/{flag=1;next} /^## /{flag=0} flag && /^- /{sub(/ *— *reason.*/,""); sub(/^- /,""); print}' \
+ "test-cases/$F/$S-scope.md")
+leak=0
+while IFS= read -r item; do
+ [ -z "$item" ] && continue
+ if grep -qiF "$item" "${MDS[@]}"; then
+ echo "scope leak: $item"
+ leak=$((leak+1))
+ fi
+done <<< "$oos"
+[ $leak -eq 0 ]
+```
+
+This is a text-match heuristic — if OUT OF SCOPE items have descriptive names that naturally appear in prose ("Dashboard"), the check over-flags. In that case the reviewer must manually confirm. Gate 6 is advisory only when the suite has short out-of-scope labels — blocking otherwise. See SKILL.md Phase 3a for the escalation hook.
+
+### Gate 7 — Role names match product-context.md § User Roles
+
+```bash
+! grep -E '^\*\*Preconditions:\*\*.*(mainUser|qaUser|managerUser|readonlyUser)' "${MDS[@]}"
+```
+
+### Gate 8 — Minimum step count per standalone test (blocking if >20%)
+
+```bash
+# Count steps per test: for each "## Title" block, count "^- " bullets under "## Steps"
+# Short script: awk pass that tracks current test and step count
+short=$(awk '
+ /^## / && !/^## Steps$/ { if (test && count < 3) short++; test=$0; count=0; next }
+ /^## Steps$/ { in_steps=1; next }
+ /^## / { in_steps=0; next }
+ in_steps && /^[-*] / { count++ }
+ END { if (test && count < 3) short++; print short+0 }
+' "${MDS[@]}")
+awk -v s=$short -v t=$real_tests 'BEGIN{exit !(t==0 || s/t <= 0.20)}'
+```
+
+### Gate 9 — Forbidden `id:` field (server-generated only)
+
+```bash
+! grep -qE '^id: @[ST]' "${MDS[@]}"
+```
+
+### Gate 10 — Sub-suite distribution consistency
+
+If the Phase 1 header says `Output: nested` → A6 must be a directory. If `Output: flat` → A6 must be a single file. See [self-review-checks.md § 8](self-review-checks.md#8-sub-suite-distribution).
+
+```bash
+header=$(head -5 "$MD" | grep -oE '^Output: (nested|flat)' | awk '{print $2}')
+case "$header" in
+ nested) [ -d "test-cases/$F/$S" ] ;;
+ flat) [ -f "test-cases/$F/$S-test-cases.md" ] ;;
+ *) echo "missing Phase 1 Output: header"; exit 1 ;;
+esac
+```
+
+### Gate 11 — No implementation leakage in Step / Expected text
+
+Forbidden in Steps and `_Expected_:` lines: CSS class names, MDI icon class names, `data-test-id`, `aria-describedby`, `aria-labelledby`, raw ``, `
`) | Noise in a manual checklist; testers can't visually parse escaping from raw markup | Describe in prose: "a message containing HTML/script markup (e.g. a `