| name | implement-workflow |
| description | Execute a cold implementation session from an externally authored plan, handoff, task-register entry, or build prompt. Enforce slice arming, consultation, blocking user-chat HALTs, test-first commit order, repository gates, one worktree/branch/PR, cold-review handoff, and stop-without-merge. Use when the user asks to implement or execute a plan written elsewhere. Do not use to author plans or resolve builder HALTs (`delegate`), review completed PRs (`review-workflow`), or apply a review punch list (`fix-workflow`).
|
Executing a plan written by someone else
An architect writes the plan. You execute it. A human merges it. You and the author never share a context window, so when the plan underdetermines the work you cannot ask them — you stop and ask the human who can rule.
What is enforced, and what is judgement
Most of this workflow's failure modes are things a model talks itself out of at 2am with a warm context. Those are enforced mechanically. The rest is genuinely judgement, and no amount of bold text makes it otherwise.
Two enforcement tiers, and the difference matters: the hook fires on every Bash call whether you remember it or not; the scripts enforce their verdict only when you run them — the phase gates below say when, and skipping the run is the one bypass the machinery can't catch.
| Invariant | Enforced by | Tier | You cannot bypass it by |
|---|
| Never merge; never push to the default branch | hooks/guard.py (PreToolUse, denies the call) | hook | deciding it's fine this once |
| Never commit on the default branch (worktree-scoped: covers the armed worktree; merge/push blocks are repo-wide) | hooks/guard.py | hook | committing "just this once" from the slice |
| Never review your own PR | hooks/guard.py denies gh pr review | hook | approving "just to unblock" |
| Test lands with or before its implementation | scripts/check_commit_order.py (exit 1) | script | asserting you did TDD |
| Working tree clean, no whitespace damage, repo gates green | scripts/verify_pr_ready.py (exit 1) | script | running a different command |
| Gate commands are the repo's own | verify_pr_ready.py exits 2 when unknown | script | inventing one you like better |
| The PR is reviewable by a cold session | scripts/make_review_prompt.py exits 2 when the body lacks what/evidence/gates/deviations | script | promising to explain it in chat |
The guard is inert until scripts/slice_start.py arms it, and it arms only the worktree you're in. Nothing changes in any other project.
What stays judgement: when to consult, when a fork is a HALT, and what counts as exercising the code live. The phases tell you how to decide; they cannot decide for you.
Phases
Run in order. Each ends in a gate that either exits 0 or tells you what to fix. phases/ holds the detail — read the file when you enter the phase, not before.
| # | Phase | Gate |
|---|
| 0 | phases/00-ingest.md — read the plan; extract the return contract | The plan's fence and "done" definition are quoted in your notes |
| 1 | phases/01-orient.md — read the chain, open every seam. No edits | scripts/slice_start.py --slice <slug> --plan <path> --gates ... → exit 0 (arms the guard) |
| 2 | phases/02-consult.md — advisor before you design | An advisor (or fallback) response exists in the transcript |
| 3 | phases/03-halt.md — ambiguity → ask the user in chat, then close it at its source | A ruling exists, and it is written back into the governing doc |
| 4 | phases/04-tdd.md — red (captured) → green → refactor | scripts/check_commit_order.py → exit 0 |
| 5 | phases/05-gates.md — repo gates + exercise the change live | scripts/verify_pr_ready.py → exit 0 |
| 6 | phases/06-pr.md — one PR whose body is the durable record | gh pr create succeeds; scripts/checkpoint.py --sync-pr <n> |
| 7 | phases/07-stop.md — hand off to a cold reviewer, report the URL, stop | scripts/make_review_prompt.py --pr <n> → exit 0; scripts/slice_end.py --pr <n> |
Phase 3 fires whenever an ambiguity appears, not only after phase 2.
You never review your own work. A builder cannot see what it cannot see about itself: its suite is green because it wrote the tests, and the paths it forgot to test are exactly the paths its tests don't cover. Phase 7 generates a self-contained prompt for a separate, cold session running the review-workflow skill. The guard denies gh pr review so this cannot be quietly skipped.
Because that session starts with none of your context — and because your own context may be cleared mid-slice — the PR body is the only durable store. checkpoint.py folds phase-by-phase progress into it; make_review_prompt.py refuses to emit a handoff until the body can stand alone.
Resolve the project's specifics first — never carry them over
This skill is stack-agnostic; the plan is not.
| What | Where |
|---|
| Gate commands (build/test/lint) | CONTRIBUTING.md, CLAUDE.md, .github/workflows/* |
| The governing doc chain, and which doc wins a conflict | CLAUDE.md, the plan's own read order |
| The register/spec this slice implements + its out-of-scope fence | named in the plan |
| Worktree/branch/commit conventions | CONTRIBUTING.md, git log |
Pin the gates once per repo in .implement/config.json ({"gates": ["...", "..."]}) or pass them to slice_start.py. The commands the repo names are the gates. verify_pr_ready.py refuses to run rather than guess, because an unknown gate is not a passed gate.
Authority, when advice conflicts
| Tier | Source | Weight |
|---|
| 1 | advisor tool (sees your whole transcript) | Primary |
| 2 | A peer LLM, packaged self-contained (e.g. spec-driven-collaboration) — the fallback when advisor is unavailable | Advisory |
| 3 | A ruling from the plan's author or the human owner | Binding |
Authority is a property of the source, not of how persuasive the answer sounds. When a tier-2 opinion contradicts a tier-3 ruling, surface the conflict; do not silently switch. Being close to the code is not authority either.
When to stop and ask
| Situation | Action |
|---|
| The answer is in a file you haven't opened | Open it. Research, not a HALT |
| A conventional default exists for a decision the plan already scoped | Decide, say so, proceed |
| Two readings, same artifact | Decide. It doesn't matter |
| Two readings, different artifacts | HALT |
| The plan names an artifact, field, or output that does not exist in the code | HALT |
| Plan contradicts spec, or spec contradicts code | HALT |
| SDK/endpoint/path needed by an acceptance criterion is unavailable | HALT. Never weaken a test to route around it |
Inventing an output is never a default
The trap has a specific shape, and it is the one builders actually fall into. A clause says "record a reason in whatever artifact the limiter writes" — and the limiter writes no artifact. The word "whatever" reads like delegated latitude, so you pick an in-memory list, or a log file, or a JSON sidecar, and ship it behind a green suite you wrote yourself.
It isn't latitude. If satisfying a clause requires creating a file, field, table, endpoint, or record shape the plan never named, that is a design decision, not a default. The reader of that clause and the writer of it did not have the same object in mind. In the real slice this rule comes from, the owner's ruling was "no standalone artifact — put the marker on the things that already exist." A builder that guessed would have shipped output the register never asked for.
Two tells, both mechanical:
- The clause references something (
the artifact, the log, the response) that a grep shows does not exist.
- Your candidate readings would produce different files on disk, or different public shapes.
Either tell → HALT. Consulting an advisor does not substitute: it can bless a reading, but it cannot know which one the plan's author meant.
HALTing on something you could have looked up teaches the human your questions aren't load-bearing, and the next real HALT gets waved through. See phases/03-halt.md for the payload shape.
Two facts that cost real time when forgotten
A red gate is a claim, not a fact. Root-cause a failure before believing its message. Error handlers routinely assert causes they never established — a real one: git diff --check HEAD~1 HEAD on a shallow clone printed fatal: ambiguous argument 'HEAD~1', and a || echo '::error::whitespace errors' wrapper relabelled it as a whitespace failure. It false-failed every merge for weeks. There was never any whitespace.
A green signal proves nothing about a thing whose job is to say no. When the change is a check, guard, validator, or fallback, feed it bad input and watch it fail. Passing on good input is what the broken version did too.
Files
hooks/guard.py — PreToolUse guard (merge / default-branch / self-review / bare --force), shared with fix-workflow. Matches by token position, not substring, so gh pr comment --body "…git merge…" is allowed and bash -c 'git merge' is not. hooks/test_guard.py self-tests it (52 cases, incl. that git merge-base and gh pr comment are not blocked).
hooks/settings-snippet.json — registration for ~/.codex/hooks.json.
scripts/ — slice_start · checkpoint · check_commit_order · verify_pr_ready · make_review_prompt · slice_end · common.
references/worked-examples.md — four real slices: a ruling that added the edge cases, a bug caught before it reached a PR, a HALT closed in the register, a CI gate that never ran.
references/pr-body-template.md — the evidence table; use the repo's own template if it has one.