launch-quickly
Patterns

The software factory

The pipeline from a brief to a merged pull request — the label states, which command runs at each one, and when to stay in the driver's seat instead. Use when planning work or wondering how a ticket should move.

Generated from .claude/skills/software-factory/SKILL.md, which ships in every project created from this template. Your agent loads it on demand; this page is the same text. Edit the skill, not this page.

A way of working, not a robot. The pipeline is the same one every engineering team already follows; what is different is that each step has a command and a definition of done, so the process is consistent whoever — or whatever — runs it.

brief ─────/spec─────▶ issues ─────────────┐
                                            ├──▶ ready ──/task-to-pr──▶ PR ──human──▶ merged
a report, a note ────▶ issue ──/triage─────┘

/triage is a side entrance, not a stage. A ticket /spec wrote is already in the right shape and goes straight to /task-to-pr; running /triage on one is a no-op that costs tokens. /triage exists for the issues that arrive from somewhere else — a user report, a note to self, a colleague — which in a live project is most of them.

The analogy worth holding is CI/CD. Deployments used to be manual, stressful and inconsistent; putting them in a pipeline did not make anyone a better engineer, it made the floor the same height for everyone. This is that, one stage earlier.

The states

Labels, because GitHub already has them and a second tracker is a second thing to drift.

labelmeanswhat moves it on
factory:ready-for-specintake — vague, not yet buildable/triage <n>
factory:ready-to-implementacceptance criteria are real/task-to-pr <n>
factory:implementingan agent holds itthe PR opening
factory:needs-humanan agent stopped, and said whyyou

factory:needs-human is a success. An agent that stops and explains has saved you the cost of reviewing forty minutes of confident wrong work.

The commands

  • /spec — a brief becomes scoped issues. Read the codebase first; a ticket that ignores what exists produces a second way of doing something already done.
  • /triage — a vague issue becomes buildable. This is the step everything else depends on: an agent given a one-line ticket builds the wrong thing confidently.
  • /task-to-pr — an issue becomes a pull request, through a worktree, with lq check, tests and a self-review against the acceptance criteria. It never merges.

Two things that bite, both found by running a real ticket through:

Read an issue with gh issue view <n> --json number,title,body,labels,state. The bare form asks GitHub for repository.issue.projectCards, which is deprecated: it prints the deprecation notice, exits 0, and prints no issue. An empty ticket and a success code look exactly like a ticket somebody forgot to fill in.

A new worktree needs pnpm install and a copy of .env.local before any check will run in it. It is a checkout of tracked files, and .env.local is gitignored, so pnpm test there fails against a database it has no credentials for — an error that reads like a broken checkout rather than a missing step.

Acceptance criteria are the whole thing

Everything above is scaffolding around one idea: work an agent can verify itself is work an agent can do.

Handle deletion sensibly.

produces nothing. Whereas:

Deleting is allowed only for draft invoices. The server enforces it — a request for a sent invoice returns FORBIDDEN even if the UI is bypassed.

produces a policy module and a test, because it can be checked.

If you write nothing else carefully, write these.

When NOT to use this

This is the part people skip, and it is the part that decides whether the pipeline helps or produces a pile of plausible pull requests.

Use it for mechanical, well-specified work: a slice whose shape is known, a bug with a reproduction, a migration, a dependency bump, a rule applied across many files.

Stay in the driver's seat for anything where the interesting part is the decision rather than the typing:

  • the tenancy or auth model
  • a schema change you cannot reverse
  • anything where you would struggle to write the acceptance criteria — that difficulty is the signal, not an obstacle to push through
  • the first slice of a new product area, where the pattern is being set rather than followed

A ticket you cannot specify is a ticket you have not finished thinking about. Handing it to an agent does not finish the thinking; it just moves where you discover that.

Automating it

/spec, /triage and /task-to-pr run in your own session and cost nothing beyond the tokens. That is the whole pipeline and it works today.

.github/workflows/factory.yml runs the same steps in CI, triggered by the labels, so tickets move without you present. It is disabled by default and needs an API key in repository secrets. Turn it on when you have watched the manual path enough to trust it — not before, and not because it is there.

On this page