Start here
Every piece of work your developers start and don't finish costs you money and tells you nothing about what will ship.
I run this system with a founder who works with a small contract team. Before the board, the founder handed out work one task at a time, because every shared idea turned into something a developer picked up at random. Now every idea goes on the board, and developers only pull from the top of Ready to build. In one acceptance review, I tested about 20 finished issues and sent many of them back to Ready to build, each with a comment saying what scope was missing. The team picked those up first.
Shaped Kanban is a continuous-pull system for a team that ships small, accepted changes. You, or whoever owns the product, define the problem and its limits. A developer chooses the technical solution after pulling a ready issue. A reviewer checks the code. An accountable person, usually you, checks the outcome. One person can hold more than one of these roles, but each decision still needs its own evidence and its own authority.
Working alone, with AI coding agents and no second reviewer? The stages and limits below still apply; the Solo Shaped Kanban Playbook covers what changes.
Two words come up everywhere below. An issue is one piece of planned work, written down in your tracker. A pull request (PR) is a developer's proposed code change, which someone else reviews before it goes into the product.
The board has one path:
Triage → Ready to build → Being built → In review → In acceptance review → Shipped
Canceled is the end state for work that will not ship. A failed acceptance review sends the issue back to Ready to build; an incomplete one stays in In acceptance review. There is no separate approval gate, design review, or planning column.
| Stage | Entry evidence | Exit decision |
|---|---|---|
Triage | A captured request or observation | A triager writes a build-ready problem boundary and checks its size. |
Ready to build | The boundary and size check pass | A developer pulls the top eligible issue when Build WIP has room. |
Being built | Developer assigned; board moved | The developer plans, builds, verifies, and opens one implementation PR. |
In review | PR and test plan available | Required reviewers approve and checks pass; the author merges. |
In acceptance review | The merged or deployed outcome can be assessed | The accountable reviewer passes it, fails it, or reports incomplete evidence. |
Shipped | Acceptance passed and the release is verified | The outcome is recorded and the issue closes. |
Give each planned piece of delivery its own issue. When one outcome needs several issues, group them under a parent Project. The parent coordinates; it is not a second piece of work, so it never counts toward work limits or throughput.
1. Set up the system
Decide who holds each decision
Write down who decides what before the first card moves, or every decision lands back on you.
| Decision | Who holds it | If you have no technical lead |
|---|---|---|
| Problem boundaries and priority | You, or a product delegate | You |
| Pulling and building work | Developers you trust to work without supervision | Your contractors or the agency's developers |
| Code review | Code owners named in the repository | Your most senior developer or the agency's lead, never the PR's author |
| Outcome acceptance | One accountable person | You |
| Technical escalation: security, privacy, data, compatibility, architecture, and changes you can't undo | A technical owner | Nobody yet. Write the gap down. It's the first one to close. |
Someone you delegate to, person or AI agent, gets a bounded mandate. Delegation doesn't create permissions or skip a gate. Keep each decision, its evidence, and who made it in the issue or the PR, where everyone can see it. The Agent Permissions Playbook explains how to limit what agents can reach.
A team of one to three developers runs one shared board. Four or five developers make a standard team, which works best with senior engineering and design coverage. Split into a second team only when it can own a separate part of the product on its own. Adding people doesn't raise the work limits below.
Configure the board
Keep one board, and treat any work that isn't on it as work that doesn't exist.
The example uses GitHub: GitHub Issues hold the work, and a GitHub Project board shows each issue's Status. Use the seven Status options above. Keep Priority, Effort, and Impact as fields, and add Severity for incidents. Use Due date only for a real external deadline. Don't track start or finish dates by hand; the board's Status history is the evidence.
Create these views:
Ready to pull: issues inReady to buildthat nothing blocks. In GitHub, filter withstatus:"Ready to build" -is:blocked.- A contributor view that also shows blocked work in progress.
- A leadership view of every Status, and a table of all issues.
Management: your parent Projects with their child issues, in priority order.
Every view sorts by a number field called Rank, lowest first, so nobody reorders work by dragging a card by mistake. To move an issue, give it a Rank between its new neighbors: 15 between 10 and 20. Rank is the order. Priority is the coarse urgency.
In the code repository, name code owners in a CODEOWNERS file, and protect the main branch so nothing merges without passing automated checks and an owner's approval. Keep the issue form and PR template in the repository too, so the team uses them without this playbook open. If you can't set this up yourself, ask your lead developer or agency to do it and show you the settings. If you use another tracker, write down its equivalent for each field and view before you start.
Limit work in progress
Every extra thing your team starts pushes back the finish of everything already started. Work in progress (WIP) limits cap how many issues can sit in a stage at once.
| Team | Being built | In review |
|---|---|---|
| Starter team, 1 to 3 developers | 2 | 1 |
| Standard team, 4 to 5 developers | 3 | 2 |
| Larger organization | Per independent team; otherwise keep the standard-team limit | Per independent team |
Count each active issue once. A parent Project takes no slot. Check the live board before moving an issue. If Build is full, finish, review, or unblock existing work first. If Review is full, finish a review before asking for another one, and never raise the limit to hide the queue. These limits assume developers who work with AI coding agents, where review is the bottleneck because the agents make writing code fast. If your team deliberately changes the Build limit, record the decision on the board and set the Review limit to half of Build, rounded up.
Done looks like: the board shows every status, new requests arrive through the issue form, and everyone knows the Build and Review limits.
2. Shape the problem
Capture once; triage before building
Every request becomes one issue before anyone builds it, or you lose track of what was asked and who asked for it.
Customer feedback, incident follow-ups, product requests, and internal maintenance all go into the same issue tracker. Link the original report and don't create duplicates. A chat message or a support conversation can start the request, but the issue is the record. If you copy a support conversation in, copy a short summary and a link, and leave out the customer's private details.
Triage turns a raw request into a build-ready issue. You or your delegate classify it as a Bug, Feature, or Task, check for duplicates and for work it depends on, and write the smallest boundary a developer can build from. Use a Project issue for the parent of a split.
Score Effort and Impact as Low, Medium, or High. If Priority is blank, seed it from this table, and leave it blank when either score is still a guess:
| Effort \ Impact | High | Medium | Low |
|---|---|---|---|
| Low | P0 | P1 | P2 |
| Medium | P1 | P2 | P3 |
| High | P2 | P3 | P4 |
Give a confirmed bug a Severity: SEV1 when the system is down or data is lost, SEV2 when a major feature is broken with no workaround, SEV3 when there is a workaround, and SEV4 for a minor or cosmetic defect. When the evidence is thin, use SEV3.
The issue body has these sections:
## Problem
Who is affected, what happens, and why does it matter now?
## Steps to reproduce
Verified steps for a bug, if available. Never invent them.
## Context
Relevant facts from intake that do not repeat the boundary.
## Constraints
Non-negotiable compatibility, policy, timing, or operational limits.
## No-gos
Meaningful exclusions that protect the scope.
## Sources
Links to the report and material evidence, including the original thread when you have it.
Leave out reproduction steps nobody verified. Aim for about 250 to 350 words of new writing. Keep the technical solution out of the issue: the developer chooses it during planning. Move an issue to Ready to build only when the boundary, fields, dependencies, and size check all pass, and the board shows it in the right place. If a Ready to build issue turns out to have a wrong or missing boundary, correct it there; if the corrected boundary doesn't pass, move it back to Triage. An issue already Being built or later goes back to Ready to build before you correct it. Don't add another refinement stage.
Size every delivery issue the same way
Ask one question: can one developer finish this in a single focused working session with an AI coding agent, then get it through one review? If not, create a parent Project and split the outcome into child issues, each triaged on its own. Don't quietly shrink what was asked just to make the issue pass. A research spike is one session that ends in a written finding and any follow-up issues it reveals.
Example: "Customers can export billing history" may need one child for the export data customers are allowed to see and one for the download itself. The parent names the outcome; each child has its own boundary and acceptance evidence. A child doesn't wait for a sibling just because they share a parent. If one truly needs the other first, record that dependency explicitly.
For the download child, a useful boundary might be: "Account owners cannot download their own billing history for reconciliation. Provide an export of the invoices they can already view; exclude payment methods and invoices from other accounts. The requester and support conversation are linked in Sources." The issue doesn't name a library, an endpoint, or a screen design. The developer plans those after pulling it. Acceptance checks that an authorized owner downloads the expected invoices and that another account's invoices stay out of reach.
Record real blockers
A blocker is real only when one issue truly can't move until another is done. Record it with the tracker's native dependency link (GitHub calls it "blocked by"), and check it right before each Status change. An open prerequisite blocks; a closed one is history. Never infer a blocker from parent order, rank, a label, or a note. If dependency data is missing or looks wrong, stop and fix it first.
For a blocker that isn't another issue, such as waiting on a vendor or a decision, add a blocked label and write the owner and next step in an issue comment. Remove the label only once the condition is resolved. An older board may still use a need-decision label; treat it the same way, but don't apply it to new work. Neither label replaces a dependency link. If child issues must run in a strict order, link each one to the one right before it.
Done looks like: every issue in Ready to build states a problem and its boundary, names no solution, and links its real blockers.
3. Prioritize and pull
Set priority at the roadmap level
You set the priority once, in one place, and your developers never have to guess it.
Set a quarterly direction and a forecast. Then, once a week, reorder the board by changing Rank, and change Priority only when the coarse urgency changes. Reorder your parent Projects in the Management view the same way, then refresh the forecast. Triage fills in a blank Priority from Effort and Impact; leave an existing value alone. When waiting for the weekly review would cause real harm, make the change immediately, the same way. There is no approval step per issue. Compare the forecast with any external Due date; a due date is never an estimate for one issue.
Manual kickoff checklist
Nobody assigns work. A developer pulls it, and this checklist is theirs:
- Pick the top eligible issue in
Ready to pull. Confirm it's open and its boundary still holds. - Read its dependencies. Confirm none is still open, and that it has no
blockedorneed-decisionlabel. - Check how many issues are
Being built. If the limit is reached, help finish existing work instead. - Assign yourself, move the issue to
Being built, and check the board shows it there. - Plan the change before writing production code.
Your part is keeping the top of the queue in the right order.
Done looks like: the top of Ready to build is in the order you want, and nobody pulls work past the Build limit.
4. Plan and build
Once a developer pulls an issue, the technical solution is theirs. You step back in only if the problem itself has to change.
The developer starts by planning: the issue's sources, how the product behaves today, which parts of the system it touches, what can fail, and how to prove it works. They review that plan themselves and ask for specialist help when a risk is beyond their authority. The plan stays in their working session; there is no design document, design PR, or design approval. If the problem boundary has to change, it goes back to whoever triaged it.
The work happens on a short-lived branch for that issue. For production code, the developer writes a failing test first, makes the smallest change that passes it, then cleans up and runs the repository's checks: build, type checks, lint, and tests. They review their own diff for unrelated changes and explain any compatibility or rollout decision in the PR. New behavior sits behind a feature flag named issue_<issue-slug>, off everywhere except on the developer's own machine by default. The developer turns it on where you can test it, such as a staging environment, and releases it to customers on purpose once you accept the outcome.
If the issue turns out to be too big, the developer stops expanding it, writes down what they learned, and splits the rest into new child issues to triage. If an incident interrupts planned work, put it on the board. It will lower throughput, and that's fine; don't hide it in a time budget.
Done looks like: the change lives on a short-lived branch, its tests and checks pass, and new behavior stays behind its feature flag.
5. Review and accept
One implementation PR review
One issue gets one PR. If an issue needs two, it was too big.
When the change is ready, the developer opens one PR that links the issue, says what changed and why, explains the approach, and gives a concrete test plan. This is the first time a reviewer sees the approach. The developer then moves the issue to In review and checks the board. A practical PR body:
## Summary
- What changed and why.
## Test plan
- [ ] Command, endpoint, or user behavior checked.
Review authority follows the code owners and branch protection you set up. An owner reviews their own area; a qualified fallback reviews the rest. Nobody approves their own work or skips the checks, including a delegate. Findings, scope decisions, and the reason for approval go in the PR thread, so they stay on record. Chat is for review requests and status. The author resolves the review threads and merges once approvals and checks pass. A reviewer's preference never quietly rewrites what the issue promised; a real scope change needs whoever owns that decision, recorded in the PR.
Small manager PRs without an issue
A technical manager may open a small, reversible PR without an issue for internal tools, infrastructure code, or tooling off the critical path. Use an issue instead when the change could collide with active work, needs a decision first (production cost, security, availability, or a tool the team must adopt), will be handed off, or takes more than a couple of sittings. If a customer requires every PR to link an issue, that rule wins.
The PR states the problem in a line or two and what changed, plus, for infrastructure, the planned change and how to roll it back. Mark it low priority: "No rush, review when convenient, fine to close if it doesn't fit." It still needs independent approval, passing checks, and the author's merge, and infrastructure changes still go through the pipeline only. These PRs stay off the issue board, throughput, and forecasts; count them separately when you account for the team's time.
Accept the delivered outcome
Merged code proves the code went in, and nothing more. You decide whether the customer's problem is solved.
After the merge or deployment, the developer records the evidence and moves the issue to In acceptance review. You, or the accountable reviewer, test the real user scenarios, constraints, and no-gos against the merged or deployed product, including any integrations it touches. Use the issue's Problem, Constraints, and No-gos as your checklist. Try it yourself on the product, or ask for a short screen recording of each scenario. Code quality was the PR review's job; acceptance only asks whether the promised outcome was delivered.
| Result | Next state |
|---|---|
| Passed, with complete evidence and the required authorization | Verify the release, record the acceptance, move to Shipped, and close the issue. |
| Failed, with a specific unmet criterion | Record what failed and move it back to Ready to build for a fix. |
| Unverified or incomplete: a criterion nobody could check, or a broken step in the process | Leave it open in In acceptance review until the gap is closed. |
A fix after a failed acceptance takes the normal path: pull, build, a linked PR, review, and acceptance again. Correct the issue's boundary first only if what you're asking for has changed. Never mark work shipped because a PR merged. Ask developers to link PRs to issues without GitHub's closing keywords, such as "Fixes" or "Closes", so the issue stays open until you accept it.
Done looks like: every issue in Shipped has a PR reviewed by someone else and your recorded acceptance, with evidence.
6. Communicate and improve
Put work in searchable places
If a decision only happened in a private message, your team can't find it next month.
Use public team channels for anything that isn't sensitive. Keep direct messages for compensation, personal performance, legal matters, and security issues not yet disclosed. This seven-channel example gives every message a home:
| Channel | Use |
|---|---|
#feedback | Stakeholder and customer requests. |
#engineering | Day-to-day engineering coordination and the weekly check-in. |
#pr-review | Review requests, status, and merge coordination; the PR thread keeps the decisions. |
#daily-status | One written update from each developer at the end of a workday. |
#ops-incidents | Incident status and operational alerts. |
#announcements | Releases and weekly stakeholder updates. |
#demos | Product demonstrations. |
The names and the chat tool can change; write down where each kind of message goes before you start. Send operational alerts to a shared email and channel. Page someone immediately for the most severe incidents, and keep lower-severity alerts visible for triage. Incident follow-ups go into the issue tracker. Put each blocker and its owner on the issue itself; a chat message isn't the record.
Replace the daily standup with a written note at the end of each workday that had work in it. It has three parts, Progress, Plans, and Problems. Each Progress item links to a PR, commit, or delivered change you can check. Plans link to the next issues. Problems name a blocker and its owner, or say "None." Keep it short:
**Progress**
- Opened PR #214 for the billing export and verified the download flow.
**Plans**
- Address review feedback on PR #214; then pull Issue #220 if WIP has room.
**Problems**
- None
Inspect flow, then adjust one cause
Change your process because of a trend, never because of one bad week.
Review flow every Friday, and look at 3 to 4 weeks of trend before you change a limit or a rule. These are the numbers that matter:
- Throughput: how many issues reached
Shippedeach week. - Lead time: from when an issue was ready to build until it shipped.
- Cycle time: from when someone started building it until it shipped. Read the median and the 85th percentile together. A widening gap between them means issue sizes are drifting apart.
- Ongoing age: how long work still in progress has been active.
- Dependency delay: time spent waiting on another issue.
- Cancellations and backward moves: abandoned work and rework.
All of them come from the board's Status history, never from today's card positions, close dates, or dates typed by hand. If the history is missing or looks wrong, say so instead of reporting a number that only looks precise. If your board can't show that history yet, start with the simplest one: every Friday, write down how many issues reached Shipped that week.
Forecast from that weekly count. To forecast a set of remaining issues, take the last 8 to 12 weeks of throughput and simulate the future many times by picking a past week at random until the remaining issues are done. Report the date half of the runs beat (50%) and the date 85% of the runs beat. Count every shipped issue, including unplanned work; count child issues, never their parent Projects. With fewer than 4 reliable weeks, the answer is "not enough history yet." Compare the 85% date with any external Due date. If it misses, cut scope or change priority on purpose. The forecast is a range for the whole set; never give its date to a single issue.
Done looks like: a throughput count for every Friday, taken from the board's history, and forecasts stated as a range.
7. Adopt and adapt
Run one real issue through the whole board before you move the rest of the team onto it.
Start with the board, the named decision owners, one issue template, code owners with required checks, and the starter WIP limits. Bring existing work in at Triage, without pretending any of it is already ready. Keep one issue tracker as the source of truth. If you connect a support tool or another intake source later, it should link back to the original request and never create a second backlog.
Before the first pull, check:
- The board has every Status, a visible
Ready to pullview, and the starter Build and Review limits. - The product, building, review, acceptance, and technical escalation owners are named, including any gap.
- The issue form, PR template, code owners, and required checks are in the repository.
- Requests, incident alerts, daily notes, review requests, and stakeholder updates each have a recorded destination.
- One real issue has a linked source, a boundary, a size decision, and shows correctly in
Ready to build. - A developer can check dependencies, labels, WIP, and reviewer availability before pulling.
Triage that one issue, check its boundary and size, let a developer pull it, then walk it through build, PR review, and acceptance. Fix what broke, then open the system to the rest of the team.
Your weekly routine, once it runs:
- Reorder the top of the queue by
Rank. - Accept or fail what's waiting in
In acceptance review. - Read the daily notes for blockers that need you.
- On Friday, record throughput and look at the trend. Change one bottleneck at a time.
With that founder, the priority check is a short Monday message, then part of a weekly call of about 30 minutes that covers other topics too.
Delegate only once the ordinary stage runs well. For each delegated stage, record one Doer, a different accountable Champion, the bounded mandate, the source of truth, the evidence required, and when to escalate. The Doer stops when a control is missing or a decision falls outside the mandate. Check a sample of delegated outcomes yourself; that check adds to the normal gate and never replaces it.
Done looks like: your weekly routine runs without reminders, and each delegated stage has a written mandate.
Working templates
The issue, PR, kickoff, and daily-note templates above are your starting kit. Put the issue and PR forms in the repository next to the code, and keep the board and review ownership configured. Each record has one home: product constraints in the issue, implementation reasoning and verification in the PR, acceptance evidence on the issue, and operational status in the right shared channel.
If your developers use AI coding agents, the agents follow the same board, limits, gates, and evidence. An agent can draft an issue, a plan, or a review, and it can make a decision only inside a mandate you wrote down, with the evidence that decision requires. A named person answers for every outcome, and approves anything outside that mandate.
Start with one issue
Set up the board, name the decision owners, and take one real problem through to an accepted outcome. Use whatever stalls to choose your next improvement.
If your developers still need you to chase every handoff, that's what I fix as a part-time Fractional CTO.