Build Me — Implement, One Commit at a Time
Your job is to turn an already-decided solution into working Laravel code. The thinking is done. Don't redesign it — build it.
Input
You need a solution write-up before starting. Accept it as:
- A path to a markdown file (typically the file
/solve-meproduced atdocs/solutions/<topic>.md), or - The solution details pasted directly into the conversation.
Also read the matching problem write-up (docs/grilling/<topic>.md)
if it exists — that's where the numbered requirements (R1, R2, …) and
the out-of-scope list live. You need them to explain why each commit
exists and to avoid building something that was explicitly ruled out.
If you don't have one, ask for it. Don't invent a solution yourself —
that's what /grill-me and /solve-me are for. If the write-up looks
thin, contradictory, missing a clear recommendation for a sub-problem, or
lists anything under "Open trade-offs", stop and say so instead of
guessing — ask the developer to rule on each open trade-off before
writing the plan.
Use the option that was already picked. Every sub-problem in the
solve-me file has a line like **Recommended: Option B**. That's the
default — the developer ratifies it at ship-me's solution gate or,
failing that, when they approve this commit plan. Build that one, not
the one you personally think is best. If you genuinely believe a
different option would be better, say so out loud and wait for a
decision. Never silently swap it.
Step 1 — Learn how this project already does things
Before writing anything, look at how similar things are already built in this codebase: naming, folder placement, how classes are structured (actions, requests, resources, jobs, policies, etc.), how validation is done, how tests are written, how errors are handled. Use CodeGraph or search the codebase for the closest existing example to each sub-problem you're about to build.
New code should look like it was written by the same person who wrote the rest of the app — same conventions, same idioms, same file locations. Don't introduce a new pattern when an existing one already covers the case.
Step 2 — Cut the work into commits, write the plan down, get it approved
Deciding the commit boundaries is this phase's job — /solve-me
deliberately doesn't do it. Its sub-problems are units of thinking; you turn
them into units of committing, against the real codebase.
Use the sub-problems from the solve-me file as your starting point — don't re-split the problem itself. Commit order follows the sub-problem order — commit 1 comes from sub-problem 1, and so on. Use the "How the sub-problems fit together" section only to sanity-check that this order is buildable; if it isn't, that's the stop-and-ask case below, not a license to reorder. A sub-problem may be split into several commits (1a, 1b), but sub-problems are never resequenced.
Keep commits small: one commit should be reviewable in a few minutes, and should leave the app in a working state.
Write the plan to docs/build/<same-slug>.md (create the folder if
needed), then show it in the conversation. If no ship-me solution gate
happened before this (a hand-run pipeline), say above the plan that
approving it also ratifies the option picks listed under Builds:.
# Commit plan — <topic>
Solution: docs/solutions/<slug>.md
Problem: docs/grilling/<slug>.md
## Commit 1 — <short imperative title>
- **From:** sub-problem 1 of the solution
- **Builds:** Option <X> of sub-problem 1 — <one-line reason it won>
- **Serves:** R2, R5
- **Why we need it:** <one or two plain sentences, straight from the
requirement — what the app can't do without this>
- **Touches:** <files / areas — prose is fine here; this line gets
rewritten with real paths once the commit is built>
- **Done when:** <the observable thing that is true afterwards>
- **Unplanned:** _(filled in after the commit is built — leave it)_
## Commit 2 — …
The plan is also the only durable record of what happened, so two of those lines get rewritten later rather than staying as they were approved — see Step 4.
Once the plan file exists, refresh the map (see below) — at this stage it catches an approved requirement the plan doesn't cover, before a line of code is written.
Then stop and ask the developer to approve the plan — approve, reorder, merge, split, or drop commits. Do not write a single line of code before they've said yes. If they change it, update the file before starting.
If the plan is a single commit, fold the two gates into one: present the plan and ask "approve and build it?" — one yes covers both.
If a commit genuinely can't be built in its slot because it needs something a later sub-problem creates, say so now, name what it needs, and let the developer decide — never resolve it silently mid-build.
Step 3 — Build one commit
For the current commit only:
Open with two or three sentences: what this commit does and why we need it, quoting the requirement numbers it serves (R2, R5) from the grill-me file. If you can't tie it to a requirement, don't build it — ask the developer what it's for.
Write the code needed for that commit, following this project's existing patterns (see Step 1) and standard Laravel best practices.
Above or beside any non-obvious piece of logic, leave a short comment in plain, easy language explaining two things: what this code does, and why this approach was picked over the alternatives from the solve-me file. Keep it to one or two short lines. Prefix every one of these with
// WHY:(or the equivalent comment syntax for the file type) so they're easy to find and delete later. Example:// WHY: checks the confirm token before saving, so a stale link // can never overwrite a newer email change.These comments are scaffolding for review, not permanent documentation — the developer will delete them once they've read and understood the code. Don't write normal doc comments in addition to these; the WHY comment is enough.
Do not touch files outside this commit's scope.
Do not start the next commit yet.
Step 4 — Wrap up the commit
Once the commit's code is written:
Briefly tell the developer what you built and where (file paths), and restate in one or two plain sentences why this was needed — which requirement (R-number) it satisfies and what the app can now do that it couldn't before. Short: three lines, not an essay.
Go back to
docs/build/<slug>.mdand update this commit's section. Two lines change:Touches:— replace the plan's prose with the real files you actually changed, each in backticks, comma-separated, as paths relative to the repo root:- **Touches:** `app/Models/ExportRequest.php`, `app/Http/Controllers/ExportController.php`Backticked paths are what makes this commit linkable to the files it changed. Prose here is unlinkable, so the connection is lost.
Unplanned:— every decision you made while writing this commit that the solve-me file didn't already settle. One line each, nested under the field. Writenoneonly when there genuinely were none:- **Unplanned:** - Sorted by created date rather than name — the solution never said, and the list looked random without it. - Kept the old column instead of dropping it; dropping it would have broken the report page, which is out of scope.This is the important one. Every other decision in this pipeline went through a gate the developer approved. These didn't — they were made while the code was being written, and if they only get said in chat they're gone. Small ones count. "I had to pick something and this is what I picked" is exactly the kind of entry that belongs here.
Refresh the map (see below). This is the step that matters most — it is where the file paths and the mid-build decisions you just wrote actually enter the graph.
Say the same unplanned decisions out loud to the developer too, and flag anything you're unsure about.
Suggest a commit message for this commit, matching this repo's existing commit style (check
git logif unsure). Present it as a suggestion only — do not rungit commityourself unless the developer explicitly asks you to.Stop. Wait for the developer to review, edit, or approve before moving to the next commit. Never chain commits on your own initiative, even if the plan is long. If the developer explicitly pre-approves a named range ("build 3 through 5 without stopping"), honor it: build them in sequence, keep the per-commit WHY comments and R-number framing, and give the per-commit summaries together at the end of the range.
When the developer comes back (possibly with edits, possibly just "next"), pick up with the next commit in the plan, re-checking Step 1's conventions against anything they changed.
Refresh the map
You just wrote something the map is built from, so bring it up to date before moving on:
node ~/.claude/skills/map-me/map-me.mjs --brief
(If the skills were installed into this project rather than your home
directory, that's .claude/skills/map-me/map-me.mjs. If neither path
exists, /map-me isn't installed here — skip this step silently and
say nothing about it.)
--brief prints nothing at all unless something changed. When it does
print, relay those lines to the developer as they are — one line per
hole that opened or closed — and carry on.
It is never a gate. Don't stop, don't re-plan, don't rewrite the artifact and don't touch code because of what it says. It is a running account of what the written record does and doesn't cover, and the developer decides what to do about it.
Rules
- Build the recommended option from solve-me, exactly as chosen. Flag disagreements; don't act on them unilaterally.
- The commit plan is written to
docs/build/<slug>.mdand explicitly approved by the developer before any code is written. - Every commit names the requirement(s) it serves, before and after it's built. A commit that serves no requirement doesn't get built.
- After every commit,
docs/build/<slug>.mdgets updated: real backticked file paths inTouches:, and anUnplanned:list (ornone). Never leave a built commit carrying the plan's guesses. - Never write
Unplanned: noneto save a step. An empty list and a missing record look identical later and mean opposite things. - Refresh the map after writing the plan and after every commit. It is a report, never a gate — it does not pause the build or change what gets built.
- Nothing on the out-of-scope list gets built, however small or convenient it looks while you're already in the file.
- One commit, one stop, by default. Never chain commits on your own initiative — but if the developer explicitly names a range to batch, that's their pace to set, and every per-commit artifact (WHY comments, R-framing, summary, suggested message) still gets made.
- Every non-obvious piece of logic gets a
// WHY:comment in plain language. Skip it only for code so simple the reasoning is obvious (e.g. a straightforward getter). - Match existing project conventions over generic "best practice" when the two conflict — consistency with the codebase wins.
- Never commit, push, or run destructive commands on your own — only suggest the commit message.
- Don't add extra features, refactors, or cleanup beyond what the current commit needs.
- Don't write unit tests or feature tests, even if that's normally
best practice for this kind of change.
/verify-mechecks the build against the real app afterward and lists what tests are actually needed — writing them here would duplicate that work.
Done means
- The commit plan exists at
docs/build/<slug>.mdand was approved by the developer before building started. - Every commit from the plan has been built, reviewed, and approved.
- Every commit paused for review before the next one started.
- Every commit was introduced and closed with a short plain-language reason tied to a requirement number.
- All non-obvious logic has a short
// WHY:comment in plain language, tied to the choice made in the solve-me file. - Every built commit's section in
docs/build/<slug>.mdcarries the real file paths it touched, in backticks, and anUnplanned:list of what got decided mid-build (ornone). - The map was refreshed after the plan was written and after every commit, and anything it reported was passed on rather than acted on.
- A commit message was suggested for every commit.
- No option was implemented other than the one already recommended in the solve-me file, unless the developer explicitly changed it.