Green is a checkpoint - name done outside the pipeline
Chat says "CI green" while customers still cannot complete checkout because staging flags never flipped. Teams that treat the badge as finished accumulate inventory: open PRs, long-lived branches, and standups full of "almost done."
Thesis: finished work is an outcome someone can rely on. Green pipeline is one gate. Write done criteria in the ticket before coding - pipeline, merge, env/config, verification, people/residue - and speak finish state at shutdown, not badge mood. Example finish line: "Staging checkout uses new tax service; sample orders 4412 and 4413 verified with finance spreadsheet."
Green CI only means the commit survived automated checks. It does not mean a user path works, staging matches reality, product accepted the behavior, ops can roll back, or support has an answer.
Definition of done checklist for remote PRs
Write done criteria in the ticket before coding. Use this checklist as a GetToWork template - tick only what applies; do not invent theater gates.
Pipeline - [ ] Local tests relevant to the change pass - [ ] CI green on the latest commit (flakes noted, not ignored)
Review and merge - [ ] Review complete with meaningful comments addressed - [ ] Merged to the integration branch (or explicitly waiting on named review with date) - [ ] Conflicts with main resolved; rebase note if needed
Environment and config - [ ] Staging (or named env) deployed or deploy ticket opened - [ ] Feature flag state documented (off / on / percentage) and who can flip it - [ ] Secrets / config / migrations applied where required - [ ] Sample data or accounts used for verify listed in the ticket
Verification - [ ] Manual or scripted verify steps run; before/after observation pasted - [ ] Observables for internal-only work named (latency, error rate, memory) if no user surface - [ ] Rollback path noted (flag, migration down, previous tag)
People and residue - [ ] Product / requester acceptance if customer-visible - [ ] Support one-liner or runbook update if operators will get questions - [ ] Release / train date noted if merge waits a schedule - [ ] Security / compliance sign-off if required for your org
Developers optimize for signals they control. If CI is the only named finish line, CI becomes the finish line in behavior even when everyone verbally agrees users matter.
Checkpoint table
| Checkpoint | What it proves | What it does not prove |
|---|---|---|
| Local tests pass | Fast feedback survived | Behavior in real config |
| CI green | Team standards on that snapshot | Product acceptance |
| Merged to main | Code lives in integration branch | Users see it |
| Staging verified | Realistic env exercise | Production safety |
| Flag flipped / released | Users affected | Incident-free operation |
A green branch waiting days for review is work-in-progress inventory, not throughput. It rots: main moves, conflicts appear, context fades. Cap WIP before adding more green branches (plan a developer day with review and feature work). More green without merge capacity is theatre.
Staging, flags, and trains - where green dies quietly
Many "done" bugs are config or data problems CI never sees. Idempotency works in tests with a clean database; production has duplicate rows from years ago. Verification notes belong in the ticket: account used, flag state, before and after observation.
"Merged behind flag" is not finished for the customer until the flag flips with monitoring and rollback noted. Green branches waiting for a weekly release train are still inventory - the ticket should say merged and waits train date so standup does not confuse CI with customer value.
Example: CI green Tuesday; production still broken Wednesday because merge waited for freeze lift. Green inventory during freeze needs a release owner and explicit date.
Example: Pull request merged Friday, feature flag off, no staging verification. Team celebrates green main while support still gets old-behavior tickets. Done includes what the client or user can observe, not only what Git shows.
Standup language and personal shutdown habit
Replace "tests pass" with "what can someone do now that they could not yesterday?" If the answer is nothing external, you are tracking motion (busy versus finishing work). For internal-only work, answer with observables: "Main branch no longer calls deprecated API; deploy pipeline step removed."
End the day with finish state, not mood:
- Weak: "Branch green; feels done"
- Strong: "Merged; staging verified orders 4412-4413; prod release ticket 901 open; flag tax_service_v1 still off"
Before standup, update the ticket finish state in one sentence so green branches do not masquerade as shipped work.
Red CI is not failure of character; it is feedback. Green CI is not victory; it is permission to proceed to the next gate. Teams that punish red and celebrate green without asking about merge and verify train people to game checks: skip flaky tests, shrink coverage, avoid hard integration scenarios.
Freelance, managers, and meeting cost
Clients hear "tests pass" and assume invoice time. Clarify in writing what green means in your contract: delivered to staging, accepted on checklist, deployed to production. Example: client cares about a staging URL with test steps, not PHPUnit. Done is the link they can click.
Managers: counting green builds rewards starting work. Counting verified releases rewards finishing. Align incentives with the second count (developer productivity without fake busyness).
Meeting-heavy days that prevent merge turn green into guilt. Protect integration windows the same way you protect composition (fewer better remote meetings). Passing tests while waiting on a deploy slot or manual QA is still inventory - work while build runs is for using wait time well, not calling wait time done.
Example refactor: team celebrates green CI; production behavior unchanged because deploy is next week. Ticket stays in progress until deploy and monitor window complete.
Green CI is necessary. It is not the finish line. Name done where users and operators live, verify there, and treat passing checks as the checkpoint they are.
Pasteable ticket footer
Add this footer to feature tickets so "done" is not renegotiated at standup:
Done when:
- [ ] CI green on merge commit
- [ ] Merged to main (or waiting on: NAME / DATE)
- [ ] Staging verified: steps ____ / accounts ____ / flags ____
- [ ] Rollback: ____
- [ ] Support/runbook: updated / N/A
- [ ] User-visible or observable result: ____
Fill the blanks before coding starts. At shutdown, update which boxes are true. If only CI is checked, say "not finished" out loud. Paste the footer into every feature ticket so standup cannot renegotiate done after the fact.
Operating rule: no "done" without the ticket footer filled - CI, merge state, staging verify steps, rollback, and a user-visible or observable result. Reviewers ask which boxes are still open; approval without a verify plan is how green inventory piles up while customers wait. Pair finish language with busy versus finishing work when the team confuses motion for delivery.