CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

ship

Use when the user asks to take a new task all the way: plan, implement, review, commit and push. Not when a ready task file already exists. Self-contained — execute the inlined steps directly, do NOT invoke other skills via the Skill tool.

59

Quality

74%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

Fix and improve this skill with Tessl

tessl review fix ./plugins/flowai/skills/ship/SKILL.md
SKILL.md
Quality
Evals
Security

Task: Full-Cycle Ship — Plan, Implement, Review, Commit, Push

Overview

Single user-invoked command that drives a task end-to-end and reaches the remote in one invocation:

  1. Plan Phase — write a committed plan under the tasks role resolved from AGENTS.md.
  2. Implement Phase — execute the Solution under TDD (RED → GREEN → REFACTOR → CHECK).
  3. Review Phase — QA + lead-engineer review of the diff with a structured verdict.
  4. Commit Phase — targeted documentation sync + Conventional Commits + task-status auto-flip.
  5. Push Phase — safe git push with upstream and divergence gates.
  6. Reflect Phase — audit the session, criticise the findings, apply the corrective edits to the instruction files, show them, commit them, and ask whether to push that commit.

Four explicit gates between phases:

  • Plan → Implement — user MUST have selected a variant. If not, STOP.
  • Implement → Review — project check MUST exit 0 AND git status MUST be non-empty.
  • Review → Commit — verdict MUST be Approve. Request Changes / Needs Discussion / crash → STOP.
  • Commit → Push — git status --porcelain MUST be empty, untracked files included, AND if pushing main/master with remote-ahead, the Push Phase will ask before pushing.
  • Push → Reflect — the push report does NOT end the run; the Reflect Phase follows in the same turn, whether the push succeeded or the user declined it. Reached only by a run that got this far: a STOP at an earlier gate ends the run and skips it.

Context

ship is the terminal composite of the SDLC: by the time the agent exits, work either reached the remote or the user has explicit visibility into why it did not. Each phase is FULLY INLINED below; the Push Phase's safety contract (no --force, per-push authorization for --force-with-lease, upstream-on-first-push, protected-branch divergence) is the canonical safety boundary between this session and shared infrastructure. Maintainer note (NOT for runtime): generated by `scripts/generate-skill-composites.ts` from `framework/composites.yaml`. Source-of-truth bookkeeping only.

Rules & Constraints

1. **No skill re-entry**: All five phases are FULLY INLINED below. Execute the steps directly. Do NOT invoke any plan, implement, review, commit, or push skill via the Skill tool — they would re-enter without the composite's gate logic and the workflow would silently exit between phases. This forbids re-entering a phase through a skill, NOT the worker dispatch a phase prescribes: the Review Phase's Parallel Delegation subagents (e.g. `console-expert` via Task / Agent / `spawn_agent`) MUST still be dispatched exactly as that step says — the rule is about skills, not agents. 2. **Six Phases, Strict Order**: Execute Plan fully, then Implement, then Review, then Commit, then Push, then Reflect. Never interleave; never skip a gate. 3. **Plan → Implement Gate**: User MUST select a variant. Decline / abort → STOP. 4. **Implement → Review Gate**: project check MUST exit 0 AND `git status` MUST be non-empty. Otherwise STOP. 5. **Verdict Gate**: only Approve proceeds to Commit. Request Changes / Needs Discussion / crash → STOP. Phase output is reported regardless. 6. **Commit → Push → Reflect Gates**: `git status --porcelain` MUST be empty before the push — untracked files count, and Session Scope does not exempt them. Push Phase's safety contract handles upstream + divergence + force decisions. The push report is not the end of the run — the Reflect Phase follows it. 7. **No partial commit — and a STOP ends the run**: any earlier-phase failure (errors, crash, gate violation) STOPs the workflow. **STOP means the run is over.** No later phase runs after it — the Reflect Phase included. A stopped run is not a finished run, so nothing downstream of the stop is owed: do not audit the session, do not edit instruction files, do not commit, do not push. Report which gate stopped you and why, then hand control back to the user and wait. 8. **Transparency**: each phase reports its artefact (Plan path, Implement test results, Review verdict, Commit SHAs, Push remote ref). 9. **Planning**: use a task management tool (e.g. `todo_write`, `todowrite`, `Task`) to track all five phases as a single plan. 10. **Session Scope**: for Review, Commit, and Push, exclude files already modified/untracked at session start (compare to git-status snapshot from system context). Files created during Implement Phase ARE in scope. If unsure, ask before staging.

Instructions

Plan Phase

<step_by_step>

  1. Initialize

    • Use a task management tool (e.g., todo_write, todowrite) to create a plan based on these steps.
    • Compute today's date in YYYY-MM-DD format (e.g. via date +%Y-%m-%d or your environment's date primitive). Hold it as <DATE>. Derive <YYYY> and <MM> (zero-padded). Resolve the tasks role from AGENTS.md and then derive the eventual task file path from that role's layout.
  2. Deep Context & Uncertainty Resolution

    • Resolve SRS and SDS from AGENTS.md. If you don't know their current content, read the resolved files now.
    • Load related committed tasks: glob recursively under the resolved tasks role. For each found file, parse its YAML frontmatter implements: field. Keep only tasks whose implements: set has a non-empty intersection with the FR-IDs you are about to put in the new task's implements:. Cap at 10 by recency (newest first by frontmatter date); if more match, list IDs in chat without bodies and ask the user which to expand. Read the full body of each kept task before drafting the new task's body. List the loaded tasks in chat (one bullet per task: file path + matched FR-IDs + one-line summary). That list is the KEPT set and nothing else. Opening a candidate's frontmatter to test the intersection is not loading it: a task whose implements: shares no FR with yours must not appear in the list, must not be summarised, and must not reach related_tasks: — a rejected candidate presented as loaded context is the failure this filter exists to prevent. Name rejected candidates, if at all, in one separate line after the list (Checked, shares no FR: <path>), never as a list bullet. If no related tasks exist, say "No prior tasks share FRs with this one — drafting from scratch."
    • Follow Proactive Resolution from AGENTS.md: analyze prompt, codebase, search for gaps.
    • Use search tools (e.g., glob, grep, ripgrep, search, webfetch) for unknowns.
    • Affected-surface enumeration (only when the request has a definite outcome set — stated behaviors, named acceptance conditions, a deliverable list): enumerate what the change touches — code: callers and duplicated/parallel logic; infrastructure: environments, regions, dependent services and scheduled jobs; process/non-IT: affected people and downstream steps. Depth proportional to blast radius: for wide surfaces, group into classes. Each item (or class) is either covered by the plan or explicitly excluded with inspected (not assumed) evidence. For open-ended/exploratory requests, skip and route ambiguity to the clarifying questions below.
    • Independent surface pass (surface-scout): when the enumeration above ran AND your environment provides the pre-declared surface-scout agent, dispatch it now via your subagent tool (e.g. Task, Agent, task; on Codex the tool is spawn_agent — pass agent_type="surface-scout" and fork_turns="none" (a full-history fork cannot carry an agent type), then collect with wait_agent), naming surface-scout as the agent type. A generic exploration or search agent your host offers (Explore, general-purpose, and the like) is NOT a substitute: the cross-check's value comes from that agent's own instructions, and swapping it for a generic one silently turns the independent pass into an ordinary search. Input: the user's request text VERBATIM (plus quoted user clarification turns, if any) — NOTHING else. Do NOT include your own enumeration, your restatement of the request, a suspected fix location, or a preferred approach: the scout's value is independence, and seeding it with your framing destroys the cross-check. Ask for the report, not a launch — many subagent tools dispatch in the background by default and answer with a handle (an agent id plus token/duration counters) instead of the scout's findings. When your tool offers a foreground or blocking mode (a run_in_background: false parameter or equivalent), set it, so the call returns the report itself. If you nevertheless get back only a handle, CONTINUE THAT AGENT by its id — send it a message or resume it and ask it to state its findings — and use what it answers. Do NOT feed an agent id to a background-task polling tool: an agent id and a background-task id are different things, and the poll answers No task found with ID: <id> however long you give it. Redeeming that handle is a step you owe, not an option: a dispatch you launched and never collected has cost turns and bought nothing, and the pull to shrug and enumerate the tree yourself is strongest exactly there. Hold the collected report for step 3. You may quote the scout only from a message you can point to. If no message ever carried its text, write no quotation — say in one line that the report did not arrive, and let your own enumeration stand under your own name. Your enumeration is welcome in the surface list; it is a forgery under the scout's byline. Establish availability by LOOKING, never by assuming — list the agent directories (ls .claude/agents/ .cursor/agents/ .opencode/agent/ "${CODEX_HOME:-$HOME/.codex}/agents/" 2>/dev/null); a surface-scout file there — .md for most hosts, surface-scout.toml under the Codex home — means the agent is installed, so dispatch it. Running inside a sandbox or an automated harness is NOT evidence of missing subagents; decide from the listing, not from where you think you are. Doing the pass inline instead is the one outcome this step exists to prevent. Only an empty listing, or a dispatch that actually failed, skips it; step 3 then records the degradation visibly.
    • If uncertainties remain: ask user clarifying questions. STOP and wait. Never stop here with nothing written. Only ambiguity that blocks stating the Goal may halt you at this step; everything else — which library, which storage, which rollout order — is a question the variants in step 4 exist to frame, and the user answers it by picking one. So if you can state what the change is for, go on to step 3, write the task file, produce the variants, and put the open questions next to them. A request that already names its constraints and its candidate approaches is answered with variants, not with a questionnaire.
  3. Draft Framework (G-O-D)

    • Create the resolved task file's parent directories (use mkdir -p or your environment's equivalent).
    • Write the resolved task file with:
      • Frontmatter containing ALL FIVE required keys, in this exact order, every key present even when its value is empty: date: YYYY-MM-DD, status: to do, implements: [FR-..., ...] (or []), tags: [...] (or []), related_tasks: [...] (or []). Write the empty list, never omit the key. Eliding one is a defect, and the two that get elided in practice are tags and related_tasks — the task-file example the accepted format carries shows only implements:, so a file copied from it looks finished while missing two keys.
      • Body sections per the project's accepted task format: ## Goal, ## Overview (with ### Context, ### Current State, ### Constraints), ## Definition of Done — seed one bullet per outcome the request states (behaviors, examples, acceptance conditions, deliverables), in the request's own terms; preserve stated expected results exactly (no paraphrase). Related outcomes may collapse into one bullet when a single acceptance check proves them all. No discrete outcomes stated → leave placeholder bullets. Acceptance tuples are added in step 5a.
      • For async/callback conversions, include an explicit error-handling DoD item or constraint before variant selection: how callback errors map to Promise rejection / try-catch, and which tests prove error propagation is preserved.
      • ### Affected Surface under ## Overview (only when the affected-surface enumeration ran): FIRST the scout's collected report as a clearly delimited VERBATIM block (fenced, unedited — this is the raw record plan-critic, review, and the human recompute the divergence from). Only text the scout actually returned may go in that block: labelling your own enumeration as the scout's output is a fabricated quotation and a worse defect than having none — when you did not collect a report, omit the block and name the reason in one line instead. Copy it, do not retype it. Tidying is what breaks this in practice, and it does not read as tidying at the time: shortening absolute paths to repo-relative ones, dropping the scout's evidence lines because the bullet above already says it, merging two of its bullets, reflowing its headings. Each of those makes the block disagree with what the scout sent, and the whole point of the block is that a later reader can hold it against the scout's own words. Too long is not a reason to trim — a long block is the record working. If you find yourself improving the text, you are writing your own enumeration under someone else's byline. THEN one PLAIN bullet per surface item/class from the UNION of your list and the scout's — every row of the scout block gets its own bullet here, INCLUDING the rows the scout itself already marked not affected (copy its evidence into your bullet; the fenced block is the scout's record, the disposition list is yours, and a row present only inside the block has no disposition — observed 2026-09-06, plan-affected-surface-scout: the two scout rows for documents/ and .codex/ had no bullet and the critical item failed) — - <item> — <disposition>, where the disposition is one of: covered-by <DoD item / planned step>; not affected — <inspected evidence> (evidence forms by domain: code = path/lines; infrastructure = environment/service + config key; process = document/step/owner); deferred — human choice. Checkbox bullets (- [ ]/- [x]) are FORBIDDEN in this subsection — they would corrupt automatic task-status derivation. Items you are unsure about default to deferred — human choice and are surfaced at variant selection. Write the real content the moment you create the heading: a promise such as (surface enumeration will be added after variant analysis) is a FORBIDDEN placeholder — an empty heading reads as "nothing affected" to every downstream reader. Nothing to enumerate → omit the heading entirely rather than stub it.
      • Degradation line (write it before moving on) — legitimate ONLY after you actually TRIED to dispatch and the attempt failed, or your environment offers no subagent facility at all. Doing the surface pass yourself because it seemed quicker, or assuming the agent is not installed without issuing the call, is NOT degradation: it is the cross-check silently skipped, and this line would then assert something false. Neither is a handle you have not tried to redeem: a dispatch that answered with only an agent id means the report is still to be fetched — go back and collect it (step 2) before deciding anything. Whenever the cross-check did not actually happen, this line goes in — no exception. Three cases put it there: the agent directory holds no surface-scout file; the dispatch errored outright; or the dispatch ran but you could not obtain the scout's findings by any route. In every one of them the task file MUST carry, under ## Follow-ups, the line Surface cross-check (surface-scout) did not run — no subagent support in this environment. This is not optional bookkeeping: it is the only trace that the cross-check is missing, and its absence claims a verification that never happened. Create ## Follow-ups if the file has no such section yet.
    • CRITICAL: Do NOT fill ## Solution section yet.
  4. Strategic Analysis & Variant Selection

    • Generate variants in chat following Variant Analysis from AGENTS.md.
    • For non-obvious tasks, the variant set MUST cover three distinct archetypes (the agent MAY add more, e.g. a defer/do-nothing option):
      • Quick fix — minimal change that solves the core problem fastest; may incur tech debt. "Minimal" is measured against the core problem, NOT against the request's full constraint set: this variant is allowed to defer a stated non-functional constraint — a scale target, an ops-hardening item, full compliance coverage — and deferring one is usually what makes it the quick one. When it cannot meet a stated hard constraint, title it — partial: drops <constraint> and say the constraint is deferred rather than met. Name the debt in this variant's Cons in so many words — what it defers, and what it will cost to undo when the deferral runs out. "Simplest" and "fewest dependencies" are not that: they describe the build, not the bill, and a reader cannot weigh a cost nobody stated. Widening it until it needs no such marker deletes the archetype: the set then holds three correct designs and no fast one, and the trade-off the user was meant to weigh never reaches them.
      • Architecturally-correct — correct design within the task's current constraints/scope (not merely the fastest).
      • Best long-term — strategic; optimizes maintainability over the horizon, may exceed current scope (refactor/investment).
    • If two archetypes collapse into the same option for a given task, state that explicitly and still surface a distinct third — never silently drop below the three without noting the collapse.
    • Present the whole set as ONE numbered question, and nothing else. Each variant is a labelled option of that question (A., B., C., …); the option's own Essence, Pros, Cons, Risks and Best For sit under it, each on its own labelled line, in the layout the Question Format block above prescribes — never merged into one paragraph, and never folded into a single line. There is no separate variant write-up anywhere before the question — no ### Variant N sections, no bolded option headers followed later by a bare "which do you prefer?". Describing a variant twice is the defect this rule exists to prevent: the copies drift, and the reader reads the same thing twice to answer once.
    • The question's own text states what is being decided and what the answer changes, so it is answerable from itself and its options alone, without scrolling back up the transcript. A bare "Which variant do you prefer?" with nothing restated is a defect.
    • Across all variants, analyze Trade-offs: security vs complexity, performance vs maintainability, cost vs features. These belong directly under the option list, inside the same question — they compare the options and are not an option themselves. Every other option set in the reply, two-option sets included, ends with its own Trade-offs block.
    • The variant list includes the root helper: when the report names the function or module where the wrong value originates (a shared helper that returns undefined for an input class), one variant MUST fix THAT helper — return the correct value for the input it mishandles — even when a team note discourages touching shared code. The note is an input to the ranking below, not a filter on the list: a plan that offers only consumer-side patches has already decided the question the user is asked to decide. (2026-09-06: plan-recommends-root-over-symptom offered three DB-side variants and none touched getTimezoneName().)
    • Recommendation ranking (root-cause fidelity first): When you recommend a variant AND the variants differ in root-cause fidelity, rank "fixes the named root cause / matches the issue's own causal description" ABOVE "smallest diff" and "lowest speculative risk". The recommendation MUST (a) name the root cause it addresses, (b) state why the recommended variant fixes THAT cause, and (c) if a root-cause variant exists but is NOT recommended, justify the rejection with EVIDENCE — callers/usages you actually inspected — NOT a speculative "might break X". A cited risk used to down-rank the root-cause variant MUST be verified against the real callers before it counts; an un-inspected fear is not a valid reason to prefer a symptom patch.
    • Scope-cut transparency: outcome coverage is a heading-level property of a variant, not an ordinary Con. When the request has a stated outcome set, every variant's title MUST end with a scope marker: — full scope when the variant covers all stated outcomes, or — partial: drops <dropped outcome(s)> when it does not. If the dropped list is too long for a title, use a count in the title (— partial: covers 2 of 4 stated outcomes) and name every dropped outcome in the variant's Cons. A bare partial marker without named outcomes or a count is a defect. Dropped outcomes MUST also be named in the variant's Cons. A stated outcome must appear in ≥1 variant or be explicitly named as deferred at selection time — a silent drop is a planning defect. The scope choice is made at variant selection on this visible information; after selection, record the chosen variant's dropped outcomes under ## Follow-ups in the task file. A partial marker is this rule working, not a defect it reports. Two things are defects: dropping an outcome silently, and enlarging a variant until it covers everything so that no marker is needed. The second one does not feel like a defect while you write it — it feels like refusing to offer a broken option — which is why it has to be named here. It deletes the choice the user was supposed to make, and it deletes it invisibly, because a set of uniformly full-scope variants still looks complete.
    • Exception — single variant: Only offer 1 variant when the task has an obvious path (e.g., "create a text file", "add a config line") with no meaningful trade-offs. Briefly explain why alternatives don't apply. The exception cuts the number of options, never the wait — one variant is still presented as a choice and still waits for the answer.
    • Wait for the user's answer. Invoking the command is not the selection. The request that started this workflow authorized planning, not any particular variant, so the forward-motion rule (no re-confirming inside an authorized plan) starts applying only AFTER the user picks one. Until then this step is the authorization, and skipping it means the user never chose.
    • When user selects a variant, immediately proceed to fill the Solution section (Step 5). Do NOT stop after receiving the selection.
  5. Detail Solution (S) — execute immediately after user selects a variant

    • Re-read the task file you created in Step 3.
    • Overwrite the ## Solution section placeholder with concrete implementation steps for the selected variant (follow the project's accepted task format).
    • The Solution section MUST contain: files to create/modify, implementation approach, code structure, dependencies, error handling strategy (especially for async/callback conversions), and verification commands.
    • CRITICAL: You MUST write the updated content to the task file. Never leave Solution as a placeholder or comment.
    • When ### Affected Surface exists: update its dispositions to the SELECTED variant — every covered-by must point at a step or DoD item of the chosen variant's Solution; items the chosen variant drops become deferred — human choice with a matching ## Follow-ups entry. 5a. Acceptance Tuple Check — execute immediately, no permission needed
    • Walk every entry in ## Definition of Done. For each, confirm the tuple (FR-ID, Test path or Benchmark id, Evidence command) is present and concrete (no FR-ID for a requirement whose text is recorded nowhere — rule 8) (no placeholders like <TBD> or TODO). manual — <reviewer> is acceptable only with an explicit reviewer name.
    • If any DoD item lacks the tuple, edit the task file to add it. Prefer reusing an existing FR (for bug fixes and small refactors) over coining a new one. Only introduce a new FR for user-visible or contract-level changes, and only once its text has a place to live (rule 8).
    • If new FRs appear in implements: that are absent from the resolved SRS, the task MUST contain an explicit DoD entry "add FR-XXX section to SRS with **Acceptance:** field filled".
    • Do NOT create the test files themselves — that is the develop phase's RED step. This skill only FIXES the test location contract. 5c. Write SRS-inline **Tasks:** Back-Pointer (FR-DOC-TASK-LINK) — execute immediately, no permission needed. This is a write step.
    • For each FR-ID in the task's implements: frontmatter, locate the heading ### <FR-ID>: in the resolved SRS.
    • If the heading does not exist (new FR introduced by the same task), SKIP this FR for now and emit a chat note: "FR-XXX SRS section pending — task back-pointer deferred." The develop/commit phase will add the section AND the back-pointer atomically.
    • If the heading exists, find the section's existing **Description:** bullet (- **Description:** ...). Look at the line(s) immediately following it within the same section.
      • If a - **Tasks:** [...] bullet already exists: append , [REF:task:<YYYY>-<MM>-<slug> | <slug>] to the comma-separated list. Idempotency: if the exact SALP REF is already in the list, do nothing for that FR.
      • If no **Tasks:** bullet exists yet: insert a new line - **Tasks:** [REF:task:<YYYY>-<MM>-<slug> | <slug>] immediately AFTER the **Description:** bullet (before any other bullets in the section). The task: namespace id is <YYYY>-<MM>-<slug> (e.g. 2026-06-adopt-salp-anchors), derived from the task file's path.
    • Surgical edit only: the rest of the SRS file MUST remain byte-identical. Do not re-format, do not touch other sections, do not adjust whitespace anywhere except the inserted/extended line.

5b. Update Documentation Index (FR-DOC-INDEX) — execute immediately, no permission needed. This is a write step, not a planning step.

  • Resolve index from AGENTS.md. For every FR-ID in the task's implements: frontmatter, register a row there.
  • If the resolved index file does not exist, create it with a ## FR heading (additional sections like ## SDS, ## NFR may be added by other skills; do not pre-scaffold them here).
  • Within ## FR, ensure exactly one row per FR-ID. Row format (SALP): - [REF:fr:<id> | <FR-ID>] — <one-line summary> — <status>
    • <id> — lower-kebab of the FR mnemonic (strip FR- prefix, lowercase, preserve . for hierarchical IDs like FR-DIST.MARKETPLACE → dist.marketplace). The reference resolves against the [ANC:fr:<id>] token next to the SRS heading. If the SRS section does not yet exist, write the REF anyway — develop/commit will add the matching ANC when the SRS section is added, at which point scripts/check-salp.ts will resolve it.
    • <one-line summary> — pull from the SRS **Description:** first sentence if the section exists, otherwise reuse the task title (or a short paraphrase ≤80 chars).
    • <status> — mirror the SRS **Status:** value if present, else [ ].
  • Sort rows alphabetically by FR-ID inside ## FR before writing.
  • Idempotent: if a row already exists for the FR-ID, only update its summary or status if the existing one is now stale; do NOT duplicate.
  • This step is REQUIRED — it is part of execution, not the plan's Solution section. Skipping it leaves the index out of date and breaks the project's Interconnectedness Principle.
  1. Critique — execute immediately, no permission needed
    • Independent critique (plan-critic): when the task file contains a ### Affected Surface scout block OR step 4 presented 2+ variants, AND your environment provides the pre-declared plan-critic agent — dispatch it via your subagent tool with the task file path as input (on Codex the tool is spawn_agent — pass agent_type="plan-critic" and fork_turns="none" (a full-history fork cannot carry an agent type), then collect with wait_agent), then COLLECT its report the same way as the scout in step 2 — ask for a foreground/blocking dispatch where the tool offers one, and if you get back only an agent id, continue that agent by its id rather than polling it as a background task. Present its returned objection list in chat VERBATIM as the critique for step 7. A fresh context is the point: do not summarize, soften, or pre-filter its objections. If the dispatch fails or the agent is not installed, fall back to self-critique below AND write one line under ## Follow-ups: Independent critique (plan-critic) did not run — no subagent support in this environment.
    • Otherwise (trivial single-variant plan with no scout block, or the fallback above): critically analyze the plan yourself for risks, gaps, missing edge cases, over-engineering, and unclear steps. Present critique in chat as a numbered list.
  2. Triage & Auto-Apply Refinements — execute immediately, no permission needed
    • For EACH critique item from step 6, classify in chat with an explicit label (one of):
      • apply — fold into the task file now.
      • discard — over-engineering / speculative; one-sentence why.
      • defer — out of scope for this plan; record under a "Follow-ups" section.
    • Edit the task file to incorporate every apply item (update Solution, DoD, Overview, or Follow-ups as appropriate). The edit MUST happen AFTER the critique was emitted.
    • Do NOT ask the user which items to address — the triage IS the answer. Do NOT prompt with phrases like "which would you like addressed", "should I apply", "do you want me to incorporate".
    • Completeness check (after triage): every outcome seeded in Step 3 and every affected-surface item/class from Step 2 maps to a DoD item, a Solution step, or a ## Follow-ups entry naming the deferral reason; additionally, every covered-by pointer in ### Affected Surface resolves to an existing Solution step or DoD item (no dangling pointers). Complements Rule 8 (items↔tuples); this check ensures nothing stated in the request is missing. The task file, not the chat, is the record.
    • Report the applied/discarded/deferred counts in chat so the user can override any classification on their next turn.
  3. Hand off to the next phase
    • Announce the resolved task path and: "Entering the next phase."
    • Do NOT issue a TOTAL STOP. Continue immediately into the next phase of the composite workflow.

</step_by_step>

Plan → Implement Gate

  • User did NOT select a variant in the Plan Phase OR aborted → STOP. Do not enter Implement Phase.
  • Task file was not written or is missing required frontmatter → STOP. Report the error.
  • Otherwise → enter Implement Phase.

Implement Phase

<step_by_step>

  1. Re-read the Task File

    • Read the user-provided task file from disk (do NOT rely on memory). If the user gives only an identifier, resolve the tasks role from AGENTS.md and locate the matching task there. The user MUST provide either a path or an unambiguous task identifier; if it is missing, ask once.
    • Extract the ## Solution section. The implementation steps listed there are authoritative.
    • Re-plan the todo list with the Solution's concrete steps. One todo item per RED/GREEN/REFACTOR/CHECK iteration is acceptable, but ensure every Solution bullet is represented.
  2. Determine the Project Check Command

    • Priority: AGENTS.md / CLAUDE.md documented check command → manifest detection (deno.json/deno.jsonc → deno task check; package.json → npm run check/test/lint; Makefile check target → make check; pyproject.toml → pytest / ruff check .; go.mod → go vet ./... && go test ./...) → "no automated checks configured".
    • MUST NOT run a stack-specific command when its manifest is absent (any deno * creates deno.lock, any npm * resolves dependencies, etc.). Pre-flight artifacts in the working tree after verification are a bug.
  3. TDD Loop (per Solution step)

    • RED: write a single failing test for the new/changed behaviour. Run the project test command (or the focused test if the runner supports it). It MUST fail with a message that points at the missing functionality. A test that passes immediately is not RED — revise the test until it fails for the right reason.
    • GREEN: write the minimal production code that makes the failing test pass. Do NOT add features or speculative code paths beyond what the test demands.
    • REFACTOR: improve names, structure, duplication, and tests without changing observable behaviour. Re-run the tests after each refactor — they MUST still pass. If refactor breaks a test, STOP and decide: is the test wrong, or did the refactor change behaviour? Revert the refactor if behaviour drifted.
    • CHECK: run the project check command from step 2. It MUST exit 0. If it fails:
      • Within Solution scope: fix the root cause. Do NOT disable lint rules or silence formatter output. On a second fix attempt that also fails, STOP and emit STOP-ANALYSIS REPORT per AGENTS.md "Diagnosing Failures".
      • Pre-existing / out-of-scope: surface as "out-of-scope finding"; do NOT fix here.
  4. Repeat per Solution step

    • After CHECK is green for the current Solution step, return to RED for the next step. Update the todo list status.
    • When all Solution steps are implemented and CHECK is green, proceed to the final step.
  5. Final Verification

    • Run the project check command one last time on the full project (not just the changed file). It MUST exit 0.
    • Confirm git status is non-empty (otherwise the Solution was a no-op — surface that and STOP).
    • Confirm no scope creep: every changed file maps to a Solution bullet.
  6. **6. Hand off to the next phase

    • Narrate the result UPWARD, not as a diff: (a) requirements / Solution steps satisfied; (b) the class/method structure you produced or changed — names, responsibilities, relationships — in prose the human can follow WITHOUT reading the code; (c) every above-class/method decision you made or surfaced (or "none — purely local"); (d) final check result.
    • Announce: "Implementation complete; entering the next phase of the composite workflow."
    • Do NOT issue a TOTAL STOP. Continue immediately into the next phase.**

</step_by_step>

Implement → Review Gate

  • Project check did NOT exit 0 → STOP. Do not enter Review Phase.
  • git status is clean (no diff after Implement) → STOP. Nothing to review. Report "Implement Phase produced no changes — task may be doc-only or no-op; nothing to commit or push."
  • git status shows changes outside Solution scope (tooling, formatting, unrelated docs) → STOP. Revert the out-of-scope edits and report.
  • Otherwise → enter Review Phase.

Review Phase

<step_by_step>

  1. Empty Diff Guard — git diff --stat, git diff --cached --stat, git status --short. STOP only when ALL THREE are empty. A ?? entry in git status --short IS a change: two empty git diff --stat outputs plus one untracked file mean a non-empty review, so proceed. System gitStatus snapshot can be stale (hooks / parallel processes); if live status shows unauthored files clean per snapshot, ask user before staging.

  2. Pre-flight Project Check

    • Pick the check/test command: AGENTS.md/CLAUDE.md declares it → manifest detection (deno.json → deno task check/test; package.json → check/lint/test script; Makefile check → make check; pyproject.toml → pytest/ruff check .; go.mod → go vet ./... && go test ./...) → else "No automated checks configured" in the report and JiT subset disables (Rule 10). Do NOT guess. "Declares it" means the instructions record an invocation — a command line, or a task or script name that a manifest in the repository defines. A section that only names an interface (a "Standard Interface" list saying a check command exists) while the sections meant for the actual commands are empty declares nothing; fall through to manifest detection.
    • The project check needs its manifest. Do not pick a stack-specific project-wide command when the stack's manifest is absent: no deno task check without deno.json, no npm test without package.json, no make check without a Makefile. This rule chooses the PROJECT CHECK only. It does not stop step 4b from running a located test module with the runner that module is written for — deno test utils_test.ts, python -m pytest tests/test_x.py, go test ./pkg — whether or not a manifest exists.
    • Leave nothing behind. Note what is untracked before you run anything; afterwards remove every artefact a run created that was not there before (deno.lock, node_modules/, __pycache__/, .pytest_cache/). A leftover gets swept into the commit.
    • 2a (current revision): run on working tree. Skip only if no code files changed since the last successful check in this session. On failure: report immediately as [critical] and continue review. A command that never ran has not failed: exit 127, command not found, or a missing task or script name means the project declares no runnable check. Report it as [skipped] <command> — not runnable: <error> under Automated Checks, say "No automated checks configured", disable the JiT subset (Rule 10), and raise no [critical] for it.
    • 2b (parent baseline — JiT): identify parent (unstaged/staged → HEAD; commit-range → <range-start>^). Prefer git worktree add <SCRATCH>/jit-parent-<sid> <parent-sha> (full runnable tree); use git show <parent-sha>:<path> fallback ONLY if worktree-add fails. BEFORE any JiT synthesis, run the SAME project test/check command from 2a inside the parent worktree to verify baseline is green. Two things do NOT satisfy this and are the usual substitutes: the run of that command you already did on the DIFF side (it says nothing about the parent), and running only your synthesized JiT probes against the parent (they are not the project's suite). The evidence this step wants is one invocation of the project's own command whose working directory is the parent tree. Fallback path OR red baseline → "JiT disabled — parent baseline unavailable/red" in Degradation Notes; review continues without the JiT subset.
  3. Gather Context

    • First: resolve SRS, SDS, and tasks from AGENTS.md; read the resolved SRS/SDS files if their content is not already in context. A required role missing → report it and continue only with review steps that do not depend on that role. AGENTS.md is the FIRST document you open, and no conventional location is probed before it. The doc layout you have seen most often is one project's convention, not the shape of every project; a speculative cat <guessed-path> 2>/dev/null batched alongside the AGENTS.md read is still reading the wrong file first, and discarding its output afterwards does not undo that. Projects that keep their SRS and SDS somewhere else entirely exist, and they are exactly the ones this step is for.
    • Create a review plan in the task management tool.
    • Collect the diff: git diff (unstaged), git diff --cached (staged), or git log --oneline <base>..HEAD + git diff <base>..HEAD for branch-based changes.
    • Untracked files: git diff does NOT show them — read each untracked file from step 1's git status and include it in scope.
    • Read the original user request and the plan (task file under the resolved tasks role / task list).
    • Note project conventions from linter/formatter configs and patterns visible in the diff and surrounding code.
    • 3d (intent hints — JiT): collect intent-author hints for the JiT subset: git log -1 --pretty=%B <parent-sha>..HEAD (or commit messages of the range). Optionally gh pr view --json body IF gh is available AND the branch has a PR; on missing/error proceed silently — PR body is a bonus.
    • 3e (intent inference — JiT): derive a list of ≤5 explicit intents for the diff in the form "the author tried to do X; invariants Y should hold". Pull from (a) the task file's DoD items, (b) commit messages from 3d, and (c) the diff hunks. >5 candidates → merge related or drop the least-risky. Skip if the JiT subset is disabled (Rule 10).

    Parallel Delegation (after gathering context):

    • Small diff shortcut: skip delegation only when the change set is under 50 lines IN TOTAL — git diff --stat plus git diff --cached --stat plus wc -l over every untracked file from step 1. Count the lines before deciding; git diff --stat alone reports 0 for an untracked-only change set, and file COUNT is not the threshold (one 173-line file is a large diff, not a small one).
    • Otherwise, delegate 2 independent tasks in parallel to SEPARATE agent contexts — a subagent or a background task (e.g. Task, Agent, task; on Codex the tool is spawn_agent — pass agent_type="console-expert" and fork_turns="none" (a full-history fork cannot carry an agent type), then collect with wait_agent), each returning its result to you. Batching several tool calls in your own thread is NOT delegation: the point is to keep the check output out of your context, which only a separate context achieves. Establish availability by LOOKING, never by assuming: list the agent directories (ls .claude/agents/ .cursor/agents/ .opencode/agent/ "${CODEX_HOME:-$HOME/.codex}/agents/" 2>/dev/null). A file there — .md for most hosts, <name>.toml under the Codex home — means that agent is installed and dispatchable — dispatch it by name. Running inside a sandbox, a test harness, or an automated run is NOT evidence of missing subagents and is never a reason to skip: decide from the listing, not from where you think you are. Run the listing BEFORE any inline check, and quote its output in ### Degradation Notes whenever you claim delegation was unavailable. The claim is a factual report about this machine, and without the command's output behind it you are stating something you did not check: a review that ran the checks inline and wrote Parallel delegation unavailable on top of an installed agent directory reported a fact that was false. Inline is permitted only when the listing came back empty AND no subagent tool is in your toolset — both verified, not assumed. Do not silently call a batch of your own tool calls a delegation. Speed is not one of the two conditions. "Faster than spinning up a subagent", "the file is only 181 lines", "I have already read it" — none of these reopen the shortcut, which is decided once, by the line count in step 1, and not revisited per task. The point of delegation is to keep the check output out of YOUR context; doing the work yourself because it is quick spends exactly what the step exists to save. And it is per task, not per review: SA1 and SA2 are two dispatches, so delegating one and running the other inline is a partial degradation that must be recorded as such — it is not delegation performed.
      • SA1: skip if pre-flight check (step 2a) already ran. Otherwise run the project check command chosen via the same manifest-detection rule from step 2 (never stack-specific commands without the manifest). Delegate to a console/shell-capable agent (e.g., console-expert); return pass/fail + full output.
      • SA2: hygiene grep scan on the diff — TODO, FIXME, HACK, XXX, console.log, temp_*, *.tmp, *.bak, hardcoded-secret patterns. Same delegation; return findings list.
    • Collect what you dispatched: many subagent tools dispatch in the background by default and answer with a handle (an agent id plus token/duration counters) instead of the result. When your tool offers a foreground or blocking mode (a run_in_background: false parameter or equivalent), set it. If you still get back only a handle, continue that agent by its id — send it a message or resume it and ask for its result. Do NOT feed an agent id to a background-task polling tool: the two id kinds are different, and the poll answers No task found with ID: <id> however long you give it. Never write a delegated finding you did not actually receive. And never end your turn while a dispatch is outstanding. Sitting idle until a notification arrives is not waiting — the turn closes, the session ends there, and the review produces no verdict, no report and no findings at all: strictly worse than the inline run you were avoiding. Collecting is an action you take, not an event you receive.
    • Fallback rule: a delegated task genuinely fails, or is still unfinished when you have exhausted the collection budget → the main agent performs that step inline and says so in ### Degradation Notes. No hard dependency on delegation success.
    • Continue with steps 4, 6, 7, 8 (main agent review) while delegated tasks run — then collect before writing the report.
  4. QA: Task Completion

    • Map each requirement/plan item to concrete changes in the diff.
    • Flag requirements with no corresponding changes as [critical] Missing.
    • Flag plan items marked "done" but not present in diff as [critical] Phantom completion.
    • Check for regressions: do changed files break existing functionality?
    • Doc drift: for each changed source path, read the docs that describe it (the Documentation Map in AGENTS.md when present, else the resolved SRS / SDS / README). A doc still describing behaviour the diff removed or changed → [warning] Doc drift naming the doc file:line and the contradicting hunk. Drift alone is NEVER [critical] and never blocks the verdict — the commit phase owns Documentation Sync, so escalating here would stop the workflow before the step that fixes it. Do NOT edit the doc in this review.

4a. FR Coverage Audit (blocking gate — see Requirements Lifecycle in AGENTS.md)

  • Applicability first: this gate encodes a project convention, not a universal rule. It applies ONLY when the project itself declares it — an SRS role resolves from AGENTS.md AND that AGENTS.md mandates FR traceability (acceptance references, [REF:fr:<id>] code markers). Neither present → skip 4a entirely, record FR coverage gate not applicable — project declares no requirements lifecycle in ### Degradation Notes, and NEVER emit a missing code marker / no acceptance reference finding. Inventing the convention for a project that does not use it turns every clean diff into Request Changes. The SRS role resolves but its file does not exist → skip 4a the same way: record FR coverage gate not applicable — <SRS path> does not exist in ### Degradation Notes, and NEVER emit a [critical] (or any blocking) finding for the missing document or for an acceptance reference it would hold. Creating the requirements document is init's job, not this review's; the commit gate reports the same absence in one line and commits.
  • FRs in scope: (a) FR-* in the task file's implements:; (b) FR sections added/modified in the diff to SRS; (c) [REF:fr:<id>] SALP markers touched in the diff.
  • Per FR: (1) SRS has **Acceptance:** with a runnable ref (test path::name, benchmark id, command, or manual — <reviewer>); missing/placeholder → [critical] no acceptance reference. (2) Run the evidence command (or deno run -A scripts/check-fr-coverage.ts FR-<ID>); non-zero / failing / manual without reviewer → [critical] acceptance fails. (3) FR claimed implemented but no [REF:fr:<id>] marker in changed source → [critical] missing code marker. (4) DoD [x] with no evidence run/cached pass → [critical] Phantom completion. (5) Only when the project's AGENTS.md declares the mandatory **Rationale:** field (a Rationale-as-gate rule or an equivalent sentence): every FR section the diff ADDS or MODIFIES in SRS — scope (b) only, never an FR the diff merely cites — carries a non-empty **Rationale:** line saying why the requirement exists; missing or empty → [critical] no rationale, naming the FR. Report it; do not write the rationale yourself.
  • Gate: blocking — verdict cannot be Approve while any FR-gate issue remains.

4b. QA: Existing-Suite Execution (blocking gate — Rule 13)

  • Locate the repository's PRE-EXISTING test module(s) covering the changed symbols: grep the WHOLE repository — not just the directory the change lives in — for each changed symbol AND for its direct CALLERS (importers); transitive coverage often never names the changed symbol. Exclude test files added by this diff.
  • Do these three things before you decide what to run, and say what each returned: (1) grep the whole repository for the changed symbol and for its importers; (2) read AGENTS.md for a section naming test suites kept outside the default check — contract, integration, e2e, acceptance — and how to run them; (3) open the test-runner config and read the check/test task's exclude list and any path it is scoped to. Each one can surface coverage the other two miss, and skipping the last two is how a suite that exists gets reported as absent.
  • The project's check or test command is NOT this search, and running it does not discharge this step. Those commands encode what the project runs on every change; this gate asks what covers the symbols YOU changed, and the two differ by design. A suite the check command deliberately excludes — contract tests, integration tests, anything a config exclude or a scoped path argument skips — is precisely what this gate exists to reach: it was excluded for cost, not because it stopped being coverage. Before deciding what to run, read AGENTS.md for a section naming where such tests live and how to run them, and check the test-runner config for exclude entries and for scoped paths in the check task. If either points at a suite covering your changed symbols, run it. "The project check passed" is not an answer to this step; name the modules you located and the command you ran on each.
  • RUN each located module, scoped per AGENTS.md conventions — never a full-suite run. Any failure → [critical]; verdict cannot be Approve. A pre-existing test that contradicts the diff is a finding under Rule 12, not a file to update. Use the project's scoped test command when it has one; otherwise run the module with the runner it is written for (deno test <file>, python -m pytest <file>, go test ./<pkg>). A missing manifest does not stop this run — the manifest rule of step 2 picks the project check only — and step 2's cleanup applies to whatever the run leaves behind.
  • None found → record "no pre-existing coverage for the changed symbols" (quote the searches that came back empty); Rule 13 is discharged by that record, and the missing prior coverage is reported as a [warning].
  • Module cannot run locally (live service, missing env, its runner not installed) → record module + reason + the command you tried in ### Degradation Notes; never fabricate a pass. The gate stays unsatisfied, yet nothing in the change has been shown wrong, so the verdict is Needs Discussion — not Request Changes and not Approve: the human decides whether to merge without that run.
  • Self-authored tests NEVER satisfy this gate, regardless of how many pass.
  1. QA: Hygiene (use SA2 result if available; else inline)

    • Say in the report that the scan ran, including when it found nothing. A clean scan and a scan that never happened look identical on a page that only lists findings, so a hygiene line is required either way — findings, or Hygiene: clean (N patterns scanned over the diff).
    • SA2 done → dedupe its findings with own Code Review findings and merge.
    • SA2 failed/timed out or skipped (small diff) → scan inline:
    • Temp artifacts: the SA2 pattern list from step 3, plus debug print output and hardcoded secrets or localhost URLs.
    • Unfinished markers: new TODO/FIXME/HACK/XXX introduced in this diff (distinguish from pre-existing ones).
    • Dead code: commented-out blocks, unused imports/variables/functions added in this diff.
    • Deleted directories: diff deletes an entire skill/agent/module directory (not just files) → [warning] Entire directory deleted — confirm intentional; ask the user to verify before proceeding.
  2. Code Review: Design & Architecture

    • Responsibility: each changed file/module stays within its stated responsibility? Flag scope creep.
    • Coupling: new dependencies (imports, API calls) justified? Flag tight coupling and circular dependencies.
    • Abstraction: appropriate level? Flag over-engineering (unnecessary interfaces, premature generalization) and under-engineering (god-functions, duplicated logic).
    • Risk hypotheses (JiT side-channel): while reading each hunk, accumulate ≤3 risk hypotheses per intent (from Step 3e): "if the author, while doing X, had slipped on Y, the code would now fail at Z". Risks MUST be diff-specific — not generic code smells ("null deref") unless the diff directly exposes that risk. Skip if the JiT subset is disabled.
  3. Code Review: Implementation Quality

    • Naming: new identifiers clear and consistent with project conventions?
    • Error handling: explicit? Flag swallowed exceptions, missing error paths, generic catch-all handlers.
    • Edge cases: boundary conditions handled (null, empty, overflow, concurrent access)? An unhandled boundary whose expected result nothing in the project states is a [warning] (Rule 6).
    • Types & contracts: precise signatures? Flag any, untyped parameters, missing return types (where project conventions require).
    • Tests: new/changed behaviors covered? Existing tests updated for changed behavior?
    • Risk hypotheses (JiT side-channel): continue accumulating risks started in Step 6 (see Step 8a for the mutation taxonomy).
  4. Code Review: Readability & Style

    • Consistency: changes follow the project's established patterns (file structure, naming, formatting)?
    • Comments: non-obvious decisions explained? Flag misleading or stale comments.
    • Complexity: flag functions > 40 lines or cyclomatic complexity spikes introduced in this diff.
    • Clarity: flag clarity sacrificed for brevity — nested ternaries, dense one-liners, overly compact expressions. Explicit code is preferred over clever short forms.

8a. Mutant + Catching Test Synthesis (JiT) (skip on pure-deletion diff or JiT-disabled flag)

  • Generate ≤15 mutants total (≤5 intents × ≤3 risks × 1 mutant per risk), each modelling a concrete diff-specific failure mode. Typical mutations: comparator flip, removed guard, inverted return, off-by-one, swapped args, skipped branch.
  • For each mutant, synthesize ONE ephemeral test that:
    1. Compiles / parses in the project's test language.
    2. Passes on the parent revision.
    3. Kills the mutant (fails with the mutation applied; passes on the current diff code iff it preserves the parent behaviour).
  • Write tests to the session-id'd scratch directory (Rule 11). Never colocate next to the file under test in the main test tree.

8b. Dual-Run + Filter (JiT) (skip if Step 8a skipped)

  • (a) parent: run the generated tests against the parent worktree from Step 2b. Any test that FAILS on the parent is an assumption leak — discard it.
  • (b) diff: run the surviving tests against the diff revision. Any test that FAILS here is a Catching JiTTest — record it for the final report with file:line and the assertion output.
  • (c) mutant kill-rate (optional): apply each mutant patch to the diff tree, re-run the matching test, record whether the mutant is killed. SKIP if a single smallest-scope test invocation exceeds 30 s — write Mutant kill-rate skipped — single test invocation exceeded 30 s threshold (recorded N s) in Degradation Notes so the lost signal stays visible.
  • Filter ensemble, in order:
    1. Flaky — rerun each surviving test 3 times; if the result flips, discard.
    2. Assertion duplicates — two tests asserting the same thing on the same input.
    3. Zero-kill — passed on parent, passed on diff, killed no mutant.
  1. Run Automated Checks (collect from step 2 and/or SA1)

    • Pre-flight 2a ran → use its result, do NOT re-run. SA1 broader check → merge.
    • Neither ran (no check command) → note "No automated checks configured" in the report; do not silently skip.
  2. Review Report — verdict on first line. Include JiT sections (Intents, Catching Tests, Uncovered Risks, Degradation Notes) only when the JiT subset ran (or was disabled — Degradation Notes then explains why). Section order:

## Review: [Approve | Request Changes | Needs Discussion]   <!-- count your [critical] findings BEFORE writing this line; zero criticals with no surviving catching test and no unsatisfied applicable gate => Approve -->
### Verdict (plain language) — 2–4 sentences a non-coder acts on, answering ALL four questions explicitly, each in words of its own: (1) is the task complete; (2) is the design sound — say so even with no concern ("the design is sound"); (3) the key risks, or that there are none; (4) the next step. A blocking finding never replaces the design answer: a change can be well designed and still not mergeable. Accept WITHOUT reading the diff. MUST come first.
### Intents (≤5)
### QA Findings — [severity] file:line — description
### Code Review Findings — [severity] file:line — description
### Catching Tests (pass on parent, fail on diff) — name, intent #, mutant killed?, failure, file:line
### Uncovered Risks — risk + reason no test (non-deterministic / I/O / etc.)
### Existing-Suite Check — pre-existing modules (incl. caller tests) + run result, or why not run
### Automated Checks — [pass|fail|skipped] command — summary
### Degradation Notes — which JiT step was skipped and why
### Summary — requirements X/Y; catching tests N; hygiene scan result (findings or `clean`); critical/warning/nit counts
### Diff (optional) — offer diff/details for optional inspection; verdict stands without it; never block (Model B). MUST be the report's last section.

This report is a progress message, not your final answer. The review is one phase of a longer run, and the report closes that phase only. Send it as an intermediate update — on a host that separates progress messages from the final answer, use the progress channel — and keep working in the same turn: finish step 11 — here the save / discard prompt does not pause you: discard the scratch directory without waiting and say in the report that you discarded it — then read the gate that follows this phase and carry on into the next phase. Ending the turn on this report ends the whole run with nothing committed, even after an Approve. Only a verdict the gate sends to STOP ends the run here.

After the verdict the review is over — including when the author asks you to fix what you found. A reviewer who repairs the code then reports on their own work, and the finding that made the verdict disappears with the repair, so nobody can check it afterwards. Answer that the fix is the author's to make, or belongs to a separate implement run that the author starts by invoking that workflow by name. A reply in this conversation — "yes", "go ahead", "fix it", "add the tests", an answer to a question your report asked — is not that invocation, however explicit, and does not hand the fix to you. Leave the verdict where it stands. This holds for production files, for tests, for the requirement documents in the diff, AND for pre-existing tests: when a pre-existing test contradicts the diff, the contradiction IS the finding, and editing either side deletes the evidence rather than resolving it. Continuing to run the project's checks or to explain a fix in words is fine; writing the fix is not.

Verdict selection (decide in this order, first match wins): (1) Request Changes — ≥1 [critical] finding, ≥1 surviving catching test, or an APPLICABLE blocking gate (4a FR coverage where 4a applies at all, 4b existing-suite, Rule 13) still unsatisfied — except a 4b module that could not run locally, which goes to (2). (2) Needs Discussion — no blocker, but a design decision genuinely needs the human before merging, or a located pre-existing module could not run locally (step 4b). (3) Approve — everything else, and this branch is compulsory once reached. [warning] and [nit] findings NEVER force Request Changes on their own: list them, hand them to the author, approve. An Approve carrying warnings is the normal outcome, not a contradiction. Rank findings top-5 by severity × uniqueness. No issues AND zero catching tests → "Changes look good. All requirements covered, no issues found, no behavioural regressions detected." (last clause only when JiT actually ran).

  1. Ephemeral Dispose (JiT) (skip ONLY when you created no scratch directory) — prompt: save <name> / save all / discard all. On save: propose destination beside file-under-test, confirm, git mv, stage. On discard all (default for timeout/ambiguous): delete entire scratch directory, leave no stray files. A scratch directory you made is yours to remove, and the verdict is not the end of the run while one is still on disk. This step goes missing in the same way every time: the report reads finished, the catching test has already done its job, and the leftover directory is invisible to you and permanent to everyone else — a run that names its scratch path in the report and then leaves it there without asking has documented the mess rather than cleaned it. Whether you wait for the answer depends on the report's role, stated right after the report template. Removing the parent worktree is a different cleanup and does not cover this.

</step_by_step>

Verdict Gate

After completing the Review report:

  • Approve → the review report you just sent is not the end of the run. Continue in this same turn with the Commit Phase below and execute its steps in order. DO NOT commit yet — the commit belongs to the Commit Phase's own commit step, after its documentation sync and grouping.
  • Request Changes or Needs Discussion → output the full report and STOP. Do NOT commit or push.
  • Review Phase crashed or produced no verdict → report the error and STOP.

Commit Phase

<step_by_step>

  1. Verify Unchanged State
    • The diff and file list are already in context from the prior phase. Do NOT re-read them.
    • Run only git status -s to confirm nothing changed between phases.
    • If new changes appeared (unexpected), report and STOP.
    • git diff is banned for the rest of this phase — every form of it. Not git diff, not --cached, not --stat, not a single file path, not "just to confirm what I staged" and not "to check the working tree matches the index". You have already read this content; git add moves files between index and working tree and cannot alter what is inside them, so a second read can only return what you already have, at the cost of the context this phase exists to save. git status -s answers every question you legitimately have here, because the only open question is WHICH files are staged.
    • The project's tests and check command are banned here too, for the same reason. Verification belongs to the phase that already ran it, and this phase only ever adds comments, traceability markers and documentation — none of which can change what the code does. "I added a [REF:...] marker, so let me re-run the tests" re-pays the whole cost of the suite to re-confirm a verdict that is already in your context. If an edit in this phase COULD change behaviour, that edit does not belong in this phase.
  2. Documentation Sync (mandatory — do NOT skip)
    • Determine scope: look at the file paths from step 1. Classify the change:
      • Infra-only: ALL changed files are tests (*_test.*, *.test.*), CI (.github/), acceptance tests (acceptance-tests/), formatting, or dev-environment (.devcontainer/). → Skip doc sync. Output: Documentation sync: skipped — infra-only changes (tests/CI/acceptance-tests).
      • Product changes: anything else → proceed with doc sync below.
    • Resolve the documents first: SRS, SDS, and index are ROLES, not filenames. Read ./AGENTS.md and take the path each role is bound to — a project may put its SDS at architecture/system.md or its SRS at specs/product.md, and the mapping below then means those files. Never go looking for design.md / requirements.md by name, and never create a file at the conventional path when the role already points somewhere else: that leaves the real document stale and adds a second one nobody reads. Take the WHOLE list the project declares, not just the three named roles — a documentation hierarchy that also binds, say, an API reference or an operations runbook is naming documents this step must keep in sync, and a change belonging to one of them does not become the SDS's problem because the SDS is the familiar name. A role you cannot resolve → say so in one line and sync only what you can. The same holds for a role whose bound path does not exist on disk: output Documentation sync: <role> → <path> is missing — not created, then continue — nothing in this workflow creates a project document, and a missing document is not a missing input.
    • Find the mapping: check if ./AGENTS.md has a ## Documentation Map section. If yes → use the path→document mapping from there. If no → use the default mapping:
      • New/changed exported functions, classes, types → SDS (component section)
      • New feature, CLI command, skill, agent → SRS (new FR) + SDS (new component section)
      • Removed feature/component → remove from SRS + SDS
      • Changed behavior (fix that alters documented contract) → SDS (update description)
      • Renamed/moved modules → SDS (update paths and structure)
      • Config/build changes → SDS only if architecture section references them
      • Renamed or removed name that documents mention → EVERY document that still prints the old one. A CLI flag, subcommand, option, environment variable, or exported symbol that changed its name is not covered by the "new feature" row, and this is the row that catches it. Do not infer the affected set from the kind of change: grep the OLD string across the resolved documents and README, and take the set from the hits. Searching for the NEW name instead returns nothing, which reads as "docs are fine" — that is how a rename passes this step with every document left stale.
      • README.md → update only for user-facing changes (new install steps, new features, changed API). A rename on the user-facing surface IS a changed API — a CLI flag, subcommand, option, or environment variable that changed its name belongs here.
    • Sync each affected document:
      • For each changed file, identify which document section describes its component (using the mapping).
      • READ that specific section from the document.
      • COMPARE the section text with the actual code after your changes. Ask: "Does this section accurately describe the code as it is NOW?"
      • If inaccurate → update the section. If accurate → no change needed.
      • For new functionality with no corresponding section → add a new section.
      • For removed functionality → remove the section.
      • Renamed or removed identifiers — search by the OLD name, across every resolved document. A flag, command, option, environment variable, function, or path that changed its name leaves the old one printed wherever it was documented, and grepping for the NEW name comes back empty, which reads as "docs are fine" and is how a rename passes this step untouched. Grep the old string verbatim in each resolved document plus README, and fix every hit. One document updated is not the step finished: the same name usually sits in several of them, and stopping at the first is the usual way the rest go stale.
    • Gather change context for commit message and doc updates:
      1. Active task file: If the user referenced a task file in this session, resolve tasks from AGENTS.md and read that file there. Do NOT scan all task files.
      2. Session context: User messages explaining intent, decisions, requirements.
    • Apply Compression Rules to any doc updates:
      • Use combined extractive + abstractive summarization (preserve all facts, minimize words).
      • Compact formats: lists, YAML, Mermaid diagrams.
      • Concise language, abbreviations after first mention.
    • Execute Updates: Edit documents BEFORE proceeding to grouping.
    • Report the sync, one line per document: after the edits, print a Documentation sync: block with one line for EVERY document resolved above — <path>: updated (<section or what changed>) or <path>: no change — <reason>. The block is the step's output, not a courtesy: a closing sentence such as "updated the SRS, SDS and README" does not say which document was checked and why one was left alone, and the user cannot tell a skipped document from an unaffected one. (2026-09-02 and 2026-09-06: commit-doc-sync-gate synced all three documents correctly in both runs and failed the same item both times because the result was reported only as a summary sentence.)
  3. Commit Grouping
    • Review the diff from step 1. Determine the primary business purpose.
    • Default: ALL changes → 1 commit. Only split if: a. Changes serve genuinely different, unrelated purposes (no causal link), OR b. The user explicitly requested a split.
    • Documentation describing a code change → same commit as that code.
    • Tests for a feature → same commit as that feature.
    • If splitting: use appropriate Conventional Commits types for each group.
    • Hunk-level splitting (within a single file) — ONLY when user explicitly requests it.
  4. Commit Execution Loop
    • Iterate through the planned groups:
      1. Stage specific files for the group.
      2. Verify the staged content matches the group's intent — check WHICH files are staged with git status --short. When step 1 reused a diff from a prior phase rather than reading one, that is the whole check: staging moves files, it cannot change content you have already read, so do NOT run git diff in any form (--cached, --stat, per-file) to re-confirm it.
      3. Task Status Lifecycle (FR-DOC-TASK-LIFECYCLE) — for each staged task file under the resolved tasks role with date: frontmatter (skip legacy flat-path), first check frontmatter status:. If it is superseded, require/keep superseded_by: and skip DoD derivation because the stale original DoD no longer maps to current reality. Otherwise count top-level - [ ]/- [x] items in ## Definition of Done. Derive status: K=0→"to do", 0<K<N→"in progress", K=N→"done" (warn if no DoD). Rewrite frontmatter and git add if it differs. Idempotent. Never downgrade done. Warn-only on parse errors.
      4. Commit with a Conventional Commits message (including any task-status frontmatter edit).
  5. Task files are never deleted (only if a task file was used in step 2) — task files of ANY shape (new-shape date: frontmatter or legacy flat-path) are persistent canonical records; commit MUST NOT delete them, regardless of DoD completion. The only lifecycle action is the status derivation in step 4.3; status: superseded records are preserved.
  6. Verify Clean State
    • Run git status to confirm all changes are committed.
    • If uncommitted changes remain, investigate and report to the user. </step_by_step>

Commit → Push Gate

  • git status --porcelain MUST print NOTHING. Modified files, staged files and untracked files all count — an untracked leftover is not an "edit", and reading this gate as edits-only is how it gets passed. Any output → STOP, list the files, and do not push.
  • Session Scope (rule 10) does NOT open this gate. Scope decides what you may COMMIT; it says nothing about whether the tree is fit to push. A file that was already there at session start is correctly excluded from your commit AND still blocks the push — both hold at once, and "not mine to commit" is not a reason to push past it. Say which files you are stopping on and let the user decide what happens to those files — delete, commit, or ignore. That is the whole of what is theirs to decide here: the gate has no "unless the user authorises it" clause, and no answer they can give opens it. An answer that leaves the file where it is leaves the gate shut, and the run ends there. Treating "the user knows about it now" as consent to push is the failure this paragraph exists to prevent.
  • If the current branch is main / master AND the remote is ahead, the Push Phase below will ask the user before pushing (per FR-ATOM-PUSH safety contract); do not pre-empt that gate here.
  • Otherwise → enter Push Phase. If the user explicitly declines the push at the Push Phase's first-push or divergence gate, STOP — the commits remain locally and can be pushed manually later.

Push Phase

<step_by_step>

  1. Identify Target Branch

    • Run git rev-parse --abbrev-ref HEAD to identify the current branch as <CURRENT>.
    • If the user typed a branch name as argument, compare to <CURRENT>. If different, STOP and ask "You typed <typed> but the current branch is <CURRENT>. Push <CURRENT> or check out <typed> first?". Wait for an answer.
    • Otherwise, the push target is <CURRENT>.
  2. Resolve Upstream

    • Run git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null to find the upstream of <CURRENT>.
    • If the command exits non-zero (no upstream), ASK the user: "<CURRENT> has no upstream. Should I run git push --set-upstream origin <CURRENT>?". Wait for an answer.
      • Affirmative → proceed to step 3 with --set-upstream origin <CURRENT>.
      • Negative → STOP. Report "No upstream and user declined to set one — nothing to do."
  3. Safety Checks

    • Protected-branch divergence (HARD REFUSAL — see Rule 4): if the upstream is origin/main or origin/master, run git fetch origin <CURRENT> then git rev-list --left-right --count HEAD...@{u}. If the right count (commits the remote has and local does not) is > 0, ASK the user with EXACTLY two options: "Remote <CURRENT> is ahead by N commit(s) the local branch does not have. Force is REFUSED on protected branches even with explicit authorization. Pull and rebase first, or abort?". --force / --force-with-lease are NOT options — never present them, never run them, even if the user volunteers "force", "overwrite", or "yes I want to overwrite the remote". If the user pushes back, restate the refusal and re-offer pull-rebase / abort.
    • Non-protected branch divergence: if the right count > 0, surface the divergence but proceed with a regular git push (which will fail safely if non-fast-forward). DO NOT proactively suggest force.
    • --force request: if the user has explicitly asked for --force, decline. Explain --force-with-lease and proceed only with per-push user authorization (see Rule 2).
  4. Push

    • Run GIT_PAGER=cat git push [--set-upstream origin <CURRENT>]. Stream stdout + stderr to the user. Do NOT silence error output.
    • On a non-fast-forward error: do NOT retry with --force or --force-with-lease. Surface the failure and STOP.
  5. Post-Push Verification

    • Run git rev-parse @{u} and git rev-parse HEAD. Compare.
    • Equal → push succeeded. Report the remote ref and the pushed SHA.
    • Different → push reported success but upstream did not advance. STOP with "Post-push verification FAILED: @{u} = <remote>, HEAD = <local>. Investigate before retrying."
  6. Await CI (FR-ATOM-PUSH.CI-AWAIT)

    • Read AGENTS.md ## CI/CD section.
      • Absent: output No CI declared in AGENTS.md — skipping CI await. and continue to step 7 (`7. Hand off to the next phase
    • Final report: target branch, upstream, pushed SHA, post-push verification result, CI await result (skipped, green, or not reached — stopped earlier).
    • Announce: "Push complete; entering the next phase of the composite workflow."
    • Do NOT issue a TOTAL STOP, and do NOT wait for the user to tell you to carry on. The push report reads like the end of the work — in ship and ship-task the Reflect Phase follows it, in this same turn.`).
      • Malformed (missing either Provider: or Status command:): STOP with ## CI/CD section is malformed — required keys: Provider, Status command. Found: <list of present keys>. Do NOT silently fall back. Do NOT continue to step 7.
      • Well-formed: continue.
    • Resolve tunables (optional keys in ## CI/CD):
      • Poll interval: — seconds between status polls. Default 60. Accept integer seconds; a value <5 is treated as malformed and STOPs the atom.
      • Wall-clock budget: — soft cap on total await time. Default 1800 (30 min). Accept integer seconds.
      • Compute ITER_CAP = max(1, ceil(<budget> / <poll interval>)). The iteration count — NOT wall-clock — bounds the cap so it stays deterministic across IDE-harness latencies. With defaults, ITER_CAP = 30; a project that sets Poll interval: 10 and Wall-clock budget: 60 gets ITER_CAP = 6.
    • Export the pushed SHA into the environment: export SHA=$(git rev-parse HEAD). All CI commands below inherit $SHA from the agent's shell.
    • Detect run trigger (≤60 s window; sized at ~2× the slowest realistic provider lag, observed ~30 s for GitLab pipelines registering after push): invoke the Status command. Treat:
      • exit 0 or 1 (terminal on first call) → proceed straight to the poll loop branch.
      • exit 2 (in-progress — a run exists) → proceed to the poll loop.
      • any other exit → sleep 5 s and retry. After 12 retries (60 s) with no run detected, STOP with CI declared but no run was triggered by $SHA within 60 s — verify the workflow trigger configuration. Do NOT continue to step 7.
    • Poll loop (max ITER_CAP iterations × <poll interval> s sleep ≈ <wall-clock budget> wall-clock):
      • Invoke the Status command.
      • exit 0 → CI green. Continue to step 7.
      • exit 1 → CI red (terminal failure). Go to Investigate Handoff below.
      • exit 2 → still running. Sleep <poll interval> s. Re-invoke. Increment iteration counter.
      • any other exit → treat as a malformed Status command, STOP with the raw exit code and stderr.
    • Iteration cap (anomaly): if ITER_CAP iterations completed without a terminal status (exit 0 or 1), STOP with a loud single-line message: CI ANOMALY: <ITER_CAP> iterations × <poll interval>s = <budget>s elapsed without a terminal verdict. Run URL: <result of Run URL command if defined, otherwise "not available">. Last status exit: 2 (in-progress). Treat as an incident (hanging job, queue starvation, runner outage) — do NOT continue silently. Do NOT invoke investigate (no failed-job logs to feed it yet — the build is still running, not red). Do NOT continue to step 7. The user owns the next action: extend the budget by re-running the atom after raising Wall-clock budget, cancel the CI run, or investigate the runner.
    • Investigate Handoff (CI red):
      1. If the Logs command is defined in AGENTS.md, execute it. Capture stdout. Truncate to 12 KB (investigate can fetch more via the run URL if it needs to drill deeper).
      2. If the Run URL command is defined, execute it. Capture stdout as the run URL.
      3. Do NOT assume the working tree is clean: @{u} == HEAD (step 5) proves only that the commit reached the remote, and a push leaves uncommitted work in place. The investigation therefore runs in a temporary worktree of the pushed commit, which is clean by construction; the handoff prompt below says so. Do NOT stash, reset, restore or commit the developer's uncommitted files to make the tree clean.
      4. Invoke the investigate skill via the host IDE's skill-invocation primitive (Skill tool / /flowai:investigate slash command / inline expansion of its SKILL.md) with this prompt: CI failed for commit $SHA on branch <CURRENT>. Run URL: <URL or "not available">. Failed-job logs (truncated to 12 KB):\n<LOGS or "not available">\nDiagnose the root cause in a temporary git worktree of $SHA (git worktree add <scratch dir> $SHA), not in the current working tree, and remove that worktree when done. Do not apply a fix; report findings.
      5. After investigate returns its report, STOP. Do NOT continue to step 7 — the push succeeded but the build is broken; the user owns the remediation decision.
  7. **7. Hand off to the next phase

    • Final report: target branch, upstream, pushed SHA, post-push verification result, CI await result (skipped, green, or not reached — stopped earlier).
    • Announce: "Push complete; entering the next phase of the composite workflow."
    • Do NOT issue a TOTAL STOP, and do NOT wait for the user to tell you to carry on. The push report reads like the end of the work — in ship and ship-task the Reflect Phase follows it, in this same turn.**

</step_by_step>

Push → Reflect Gate

  • You are only here if every earlier gate passed. This gate is reached by completing the Push Phase, and by no other route. A STOP at any earlier gate ends the run on the spot (rule 7) and never arrives here, so nothing below applies to a stopped run.
  • The push report is not the end of the run. The Reflect Phase below still has to run, in this same turn, without waiting for the user to ask for it.
  • Enter the Reflect Phase whether the push succeeded or the user declined it. A declined push is still a completed run — the work is done and sitting in local commits — and the session is worth auditing either way, so the phase decides for itself whether it earned a reflection. A run stopped at an earlier gate is a different case entirely and does not reach this line.

Reflect Phase

<step_by_step>

  1. Decide whether this session earned a reflection

    • Scan the conversation and the invocation message for complexity signals:
      • Errors or failed attempts (test failures, lint errors, build errors).
      • The same action retried more than once.
      • The user correcting your approach or output.
      • Workarounds or non-obvious solutions.
      • Explicit descriptors in the invocation message — "rough session", "had to retry", "wrong approach", "failed", "had to correct you". These count on their own.
    • Say the verdict aloud either way — one line: Session complexity: none detected — skipping reflection, or Detected retries and a user correction — reflecting. A silent skip is indistinguishable from a forgotten step.
    • No signals → skip to the final step. Signals → continue.
    • Do NOT ask whether to reflect. That is not the user's call here; the one question in this atom comes at step 6, and it is about pushing.
  2. Audit the session

    • Execution flow: where did the work go wrong, and what did it cost — failed commands, wrong assumptions, rework.
    • Logic patterns: looping (retrying without changing strategy), blindness (ignoring a "file not found" or a linter error), stubbornness (forcing a solution that does not fit).
    • Technical decisions: proportionality, conformance to existing project patterns, abstraction fit, explicit error handling, robustness, obvious inefficiency, input validation, dependency justification, and fallbacks nobody asked for.
    • Context gaps: project docs never opened, related source never read, relevant skills or rules never consulted, verification skipped, ambiguities resolved by guessing instead of asking.
    • Context waste: files read but never used, whole files read for one fragment, the same unchanged file read twice, verbose tool output that added noise.
    • Undocumented discoveries: knowledge gained here that changes how the project is built, run, tested or deployed. Keep what generalises; discard the one-off.
    • Stale instructions: anything the project instructions told you that the repository contradicted — a command or task that does not exist, a path that moved, a convention the code does not follow. Compare the commands the instructions name with the ones the project's manifest defines.
    • Automation opportunities: a repeated multi-step sequence (→ a skill), an undocumented convention (→ a rule), an invariant you checked by hand (→ a hook).
  3. Criticise your own findings — before you touch a file

    • Validity: is each finding backed by something you can quote from this session, or is it inference? Drop or downgrade the inferred.
    • False positives: reading a neighbouring file to learn the pattern is not wasted context; updating a test after a deliberate behaviour change is not test-fitting.
    • Proportionality: a one-off annoyance does not earn a new rule. Simplify anything disproportionate. This limits NEW rules only. A line in an existing instruction file that this session proved wrong is corrected on its first sighting, however rarely it bites: fixing a fact is not adding a rule. A "read-only" marker on AGENTS.md keeps task notes out of it; it does not protect a wrong fact in it.
    • Blind spots: which whole categories did you not look at — security, performance, documentation?
    • Severity: a pattern seen twice with different root causes is not recurring.
    • Say what this pass changed and why. What survives it is what you are about to write into the user's files.
  4. Apply the corrective edits

    • Edit the instruction files directly. Each edit states the rule and the reason it exists, in the voice of the file it lands in.
    • They land in the project's own tracked files, inside the repository working tree — AGENTS.md, **/CLAUDE.md, and the rule or skill files those point at. Confirm it: the path you edited must appear under git status.
    • Your own memory store is not a corrective edit. Writing the lesson into the agent's persistent memory (a memory/ directory under your home, a personal notes file, anything outside the repository) feels like it captures the finding and does not: it is not versioned, it does not reach anyone else working here, and a fresh checkout has none of it. It is also how this step gets silently skipped — measured 2026-08-19, one run in three wrote to memory/ and reported there was nothing to commit. Use it in addition if you like, never instead.
    • One edit per surviving finding. A finding that produces no concrete edit is a report line, not a corrective action — say so and move on.
    • Keep them small and local: tighten an existing rule where one exists, add a new one only where none does.
  5. Show the edits and commit them — no question here

    • List what you changed, file by file: the path, the section, what the rule now says, and which finding it came from. The user must be able to judge the edit from this list without opening a diff.
    • Then commit, in this same turn, without asking. The edits are already written; a commit of what is already on disk adds no risk the edit did not, and both are undone by one git command. Do not offer to commit, do not wait for encouragement.
    • Run git status. Stage ONLY the files you edited in step 4, by explicit path — never git add -A, never .; a working tree you did not touch is not yours to commit.
    • Commit with type agent and a scope naming what you tightened: agent: apply reflect-suggested improvements, or narrower, e.g. agent(commit): tighten the doc-audit gate. The type is agent because the change is to the agent's own instructions — never docs:, chore: or feat:, whatever the file extension says. Never amend an existing commit.
    • Do not skip this step by not editing. If the audit produced findings and you applied none of them, say why in one line — silence here reads as a clean session, and it was not.
  6. Ask whether to push it — and end your turn on the question

    • This commit sits on top of whatever the calling workflow already pushed, so it is local until somebody sends it. That is why the question exists: it is the one thing here that reaches beyond this machine.
    • Ask, in one line, naming the branch: Committed as <sha> on <branch>. Push it? Reply "yes" to push, or "no" to drop the commit and the edits with it.
    • Write nothing after the question until the reply arrives. A question followed in the same breath by "pushing now" is not a question, it is an announcement — the user never got to answer. You may not answer it on the user's behalf: no pre-authorization carries over to a push, whatever the calling workflow already did.
    • On yes: run git push with no flags, then verify git rev-parse @{u} matches HEAD and say so. Never --force, never --force-with-lease, never --set-upstream. If the branch has no upstream, or the remote has commits you do not, do NOT improvise: report it and tell the user to run the project's push workflow, which owns those decisions.
    • On no: the edits are not wanted. Undo the commit and the edits together — a declined improvement left sitting in the branch is the same unwanted change, one git log further away.
      • Check two things first, then it is one command. (a) git rev-parse HEAD still equals the sha you reported — nothing landed on top of your commit. (b) git status --porcelain prints nothing — the tree carries no other work. Both hold by construction here: the earlier phases committed and pushed everything, and you committed your own edits in step 5.
      • Both true → git reset --hard HEAD~1. That is the whole undo: the commit and the file contents go together, and there is nothing to restore by hand.
      • Either check fails → STOP and change nothing. A --hard reset discards uncommitted work outright, and whatever made those checks fail is work you did not put there. Report what you found, leave your commit in place, and let the user decide.
      • Then confirm with git log -1 that your commit is gone, and say in one line what you removed.
  7. TOTAL STOP

    • Report in one line whether the reflection ran, what it changed, under which commit, and whether that commit was pushed. Then stop. </step_by_step>

Final Combined Report

Output a combined summary:

  • Plan: task file path + selected variant.
  • Implement: tests passed, project check result.
  • Review: verdict + key findings (or "no issues found").
  • Commit: files committed, commit message(s).
  • Push: target branch, upstream, pushed SHA, post-push verification.

Verification

[ ] Plan Phase produced a task file under the resolved `tasks` role with required frontmatter. [ ] Plan → Implement gate enforced — Solution section filled only after user picked a variant. [ ] Implement Phase ran TDD (RED → GREEN → REFACTOR → CHECK). [ ] Implement → Review gate enforced: project check exit 0 AND `git status` non-empty. [ ] Review Phase produced structured report with verdict on first line. [ ] Verdict gate enforced: only Approve proceeded to Commit. [ ] Documentation sync performed. [ ] Commits used Conventional Commits format; task status auto-flipped per FR-DOC-TASK-LIFECYCLE. [ ] Commit → Push gate enforced: `git status --porcelain` empty (untracked included) before the Push Phase. [ ] Push → Reflect gate enforced: the Reflect Phase ran after the push report, in the same turn. [ ] No phase ran after a STOP: if an earlier gate stopped the run, the Reflect Phase did NOT run and no instruction-file edit, commit or push happened after the stop. [ ] Push Phase: no `--force` used; `--force-with-lease` only with explicit per-push authorization; first-push gate satisfied; protected-branch divergence handled before push attempt. [ ] Post-push verification: `git rev-parse @{u}` matches `HEAD`. [ ] Plan / Implement / Review / Commit / Push results all reported to user.
Repository

korchasa/flowai-plugins

Path

plugins/flowai/skills/ship/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.