Agentic SDLC — From Branch to Production Map

From Branch to Production Map
FROM BRANCH TO PRODUCTIONHow one change gets from a laptop to real users — and how you know it worked.Your change is a train. Six places on the railway, in order. Click one to dive in; every district ends in a bench.git / branchesa human decidesan automated gateenvironmentsswitcheslive & healthybroken / blocked- - - dashed = not real users yet← Agentic SDLC meta-map ↗Git situations deck ↗DevOps: git deck ↗DevOps: ship deck ↗ THE LINE1Branch Lines⑂SAVE POINTS & SIDINGSGit: commits are save points, branches are sidings off themain line, a merge rejoins it.2Signal Box🚦PULL REQUESTS & REVIEWYou can't drive onto the main line. A pull request askspermission; review decides.3Inspection Sheds🔍TESTS & THE CI GATEEvery train is inspected before it joins the main line —and a failed inspection stops it, whoever is driving.4Marshalling Yard🛤ENVIRONMENTS, LANES & VERSIONSTrains are assembled and test-run on side platforms beforethey leave for the main line.5The Points⇄DEPLOYS, FLAGS & ROLLBACKA lever on the track decides which version the trafficruns on — and you want to be able to pull it back.6Signal Lamps📡MONITORING & PROOFLamps along the line tell you about trouble before thepassengers do. ONE CHANGE, START TO FINISHBug: people who mistype their email at signup never get their login link. 1Issuewhat & why, written downSAY THIS TO CLAUDE“Read issue #1412 and restate theacceptance criteria in your own words.”→ see district 2Branch+ its own worktreeSAY THIS TO CLAUDE“Make a branch fix/email-typos offproduction, in its own worktree.”→ see district 3Test firsta test that failsSAY THIS TO CLAUDE“Write a test that fails because of thisbug. Show it failing.”→ see district 4Commitssmall save pointsSAY THIS TO CLAUDE“Fix it. Commit as you go, with WHY in eachmessage.”→ see district 5Pull requestask the signal boxSAY THIS TO CLAUDE“Push and open a PR into production: why,what, how tested, how to roll back.”→ see district 6CI gateci/hetzner-lintSAY THIS TO CLAUDE“Watch CI. If it's red, read the log andfix the code — not the test.”→ see district 7Previewits own URL + dataSAY THIS TO CLAUDE“Deploy a preview. Walk the flow andscreenshot each step.”→ see district 8Reviewagent checklist + humanSAY THIS TO CLAUDE“Address every review comment and reply toeach one.”→ see district 9Mergeup to date · green · approvedSAY THIS TO CLAUDE“Update the branch, wait for green, thenmerge.”→ see district 10Stagingdeploys itself on mergeSAY THIS TO CLAUDE“Smoke test staging: login and the page wechanged.”→ see district 11Productiona human runs /deploySAY THIS TO CLAUDE“Deploy production with /deploy, not/restart. Show me the live commit.”→ see district 12Watchthe signal lampsSAY THIS TO CLAUDE“Compare the error rate to before. Anythingnew? Roll back first.”→ see district …and stop 12's errors become stop 1's next issue. It's a loop. DISTRICT 1 OF 6 · SAVE POINTS & SIDINGSBranch Lines⑂Git: commits are save points, branches are sidings off the main line, a merge rejoins it.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. Commit = a save point with a noteSmall save points mean small, cheap undo.Ship › Branch Lines › Commit · 1 of 4your branch9d04b7aadd form51ce2f0check emaila7710bdfix typoc02e9f4add test3f9a2c1empty inputtimeHEAD = you are hereEach circle is a snapshot of every file, plus who, when and why. Each points back atthe one before — so the history is a chain you can walk back along.Git takes a snapshot of your project every timeyou commit. The snapshot is named by a hash — afingerprint of everything in it.Agents commit constantly. That's good: if thelast step broke something, you step back onesave point, not one week.SAY THIS TO CLAUDE“Commit this with a message that says WHY, not justwhat.”🔍 Anatomy of one commitcommit 3f9a2c1e8b… ← the hash: a fingerprint of everything belowAuthor: Roy (agent) Parent: c02e9f4 ← the save point before this oneHandle an empty email field on signupWhy: an empty field crashed the form instead of showing an error.auth.py | 6 +++++- test_auth.py | 14 ++++++++++++++Change one byte anywhere and the hash changes — that's how git knows history wasn't edited behind your back. Branch = a siding off the main lineWork in parallel without blocking anyone.Ship › Branch Lines › Branch · 2 of 4production (the main line — real users)fix/email-typos (your siding)merge,via a PRNothing on the siding reaches real users until it rejoins the main line.A branch is a save point you diverged from.Your commits pile up on your siding; the mainline keeps moving without you.Branches are free. Make one per idea, peragent, per experiment — a branch that goesnowhere costs nothing.SAY THIS TO CLAUDE“Make a new branch off production for this, in itsown worktree.”🔍 Worktrees: one repo, several desksschool/ ← branch production (you)school-wt-login/ ← branch fix/login (agent Roy)school-wt-nav/ ← branch feat/new-nav (agent Jen)All three share ONE history. Each has its own copy of the files on disk,so two agents never type into the same file at the same time.git worktree add ../school-wt-login -b fix/login Merge = rejoin the main lineA conflict is two trains wanting the same track.Ship › Branch Lines › Merge · 3 of 4production!Roy: line 42 of pricing.pyJen: ALSO line 42 of pricing.pyconflict:same lines,two answersMost merges are automatic — different lines. A conflict is git asking a question only a personcan answer.Merging takes a siding's commits and joins themonto another branch.A conflict isn't an error. It means both sideschanged the SAME lines and git won't guesswhich is right.Fewer conflicts: small branches, merged often.SAY THIS TO CLAUDE“Rebase this branch on production and resolve theconflicts keeping both behaviours. Show me the diffbefore you push.”🔍 What a conflict actually looks like<<<<<<< productionprice = base * 0.9 # 10% member discount=======price = base - coupon # coupon codes>>>>>>> feat/couponsResolved: price = (base - coupon) * 0.9 # both, in an agreed orderThen run the tests — a merge with no conflicts can still be a wrong merge. BENCH · DO IT IN PAIRSWhich situation are you in?Ship › Branch Lines › Bench · 4 of 4Read the situation out loud. Decide together. Then click.▶ click to zoom in and do the exercise
⑂1 · Branch LinesSAVE POINTS & SIDINGS DISTRICT 2 OF 6 · PULL REQUESTS & REVIEWSignal Box🚦You can't drive onto the main line. A pull request asks permission; review decides.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. “Pull” is the change. “Request” is permission.You can't drive onto the main line. You ask the signal box.Ship › Signal Box › Pull request · 1 of 4your branchfix/email-typos · 3commitsPULLREQUESTreview + permissionprodA PR bundles three things on one page:the diffthe checksthe conversationA pull request asks the people who own abranch: please PULL my branch's commits intoyours.In this school's repos PRs target production —and merging there deploys staging, not the livesite. Live is a separate step.SAY THIS TO CLAUDE“Open a PR into production. Description: why, whatchanged, how you tested it, how to roll it back. Linkthe issue.”🔍 A PR description that gets mergedTitle: Reject typo'd emails at signup Closes #1412WHY: people who mistyped their email never got their login link.WHAT: auth.py validates the address; new test in test_auth.py.TESTED: unit test fails before, passes after; signed up on the preview with a bad address.RISK / ROLLBACK: existing accounts untouched. Revert this PR to undo.+ a screenshot of the preview showing the new error message Read the PR page top to bottomThe concept is easy. The UI is what's opaque.Ship › Signal Box › The PR page · 2 of 4Reject typo'd emails at signup #1412OpenRoy wants to merge 3 commits into production from fix/email-typosConversationCommits 3ChecksFiles changed 2⚠ This branch is out-of-date with the base branchUpdate branch✓ ci/hetzner-lint — lint · unit tests · build✗ unit tests (blocking) — GitHub Actions · 0 steps← noise here: Actions never runsMerge pull request ▾← three hidden options (zoom below)12341 what → into what 2 up to date? 3 checks green? 4 then mergeFour things, in order: what is merging intowhat; is it up to date with the target; are thechecks green; what files changed.Files changed IS the change. Even if you can'tread every line, its size and which files ittouches tell you a lot.SAY THIS TO CLAUDE“Why is this PR out of date, and is it safe to updatethe branch? Tell me what CI says after.”🔍 The merge button's three hidden optionsCreate a merge commit — keeps every commit + adds one “merged” commit. Full history.Squash and merge — the whole PR lands as ONE commit. One revert undoes all of it.Rebase and merge — replays each commit on top of production, no merge commit.Who may press it is a repo setting: branch protection can demand a green check and an approval first.For agent PRs squash is a common choice: one PR = one commit = one clean revert. Review reads for intent, not syntaxApprove = ‘I'd be fine with my name on it if it broke.’Ship › Signal Box › Review · 3 of 4 def signup(email):- create_account(email)+ if not valid(email):+ return error(400)+ create_account(email)💬 What happens if email is empty?— a question, not a verdictCommentApproveRequest changesreview agent: tests? secrets? errors? security? patterns? docs?Two reviewers, two jobs. The review agent runsthe checklist on every PR. The human asks: doesthis do what the issue asked, what else couldit break, and would we know if it did?Ask for evidence, not confidence: a test thatfails without the change, a screenshot of thepreview.SAY THIS TO CLAUDE“Address every review comment on this PR. Reply toeach one with what you changed, or why you didn't.”🔍 The Code Reviewer agent (Workshop 4)On each PR: read the diff → style → test coverage → security → anti-patterns → verdictChecklist: tests exist and are meaningful · no hardcoded secrets · error handling· no obvious security holes · follows project patterns · docs updatedVerdicts: APPROVED → release manager · CHANGES_REQUESTED → list them · BLOCKED → a humanAgents are confident. Review is where confidence meets evidence. BENCH · DO IT IN PAIRSThis PR is red. Now what?Ship › Signal Box › Bench · 4 of 4Read the checks block like a reviewer would.▶ click to zoom in and do the exercise
🚦2 · Signal BoxPULL REQUESTS & REVIEW DISTRICT 3 OF 6 · TESTS & THE CI GATEInspection Sheds🔍Every train is inspected before it joins the main line — and a failed inspection stops it, whoever is driving.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. Four inspections, cheap to realisticEach shed catches a different kind of broken.Ship › Inspection Sheds › Kinds of test · 1 of 4END-TO-ENDa robot clicks the real siteINTEGRATIONapp + real database, togetherUNITone function: 10 dmg vs +2 armour = 8 lostLINTdoes it parse? names spelled right?slower · realisticfast · manyTests are code that runs your code to checkyour code — so the next agent can't quietlybreak it.Lint catches typos. Unit catches wrong logic.Integration catches pieces that don't fit.End-to-end catches “the button is there butdoes nothing”.SAY THIS TO CLAUDE“Write a failing test that shows the bug FIRST. Thenfix it. Then show me the test passing.”🔍 One unit test, wholedef test_armour_reduces_damage():hero = Hero(health=20, armour=2)hero.take_hit(10)assert hero.health == 12 # 10 damage − 2 armour = 8 lostThat's the whole thing. It's also the spec: whoever edits take_hit() next finds out at once if armour broke.Written first, tests are the spec. Written after, they're a chore that gets skipped. CI is a gate, not a habitOne check that truly blocks beats ten that only warn.Ship › Inspection Sheds › The gate · 2 of 41PR opened2CI runs3preview4review5mergedBLOCKEDtests fail → it does not merge,no matter who says it's finePrevents: “I ran it and it seemed fine” → ship.Continuous integration runs every checkautomatically on every push, and posts theresult on the PR.Cowboy shipping isn't a discipline problem youfix with a better prompt. It's a missing gate.Agents will say “looks good”; the gate doesn'tcare.SAY THIS TO CLAUDE“Run the same checks CI runs, locally, before youpush — and show me the output.”🔍 This school's gate, for realpush → GitHub webhook → the school's own CI runner (not GitHub Actions)→ scripts/ci-check.sh: lint · unit suite (each test file in its own process) · build→ ONE status on the PR: ci/hetzner-lint ✓ or ✗The deploy builds the SAME Dockerfile, so a red test blocks the deploy too — not just the PR.Rule here: new checks go in ci-check.sh. Never add a .github/workflows file. Fix the code, not the testAgents are rewarded for green. Some will cheat to get it.Ship › Inspection Sheds › When it's red · 3 of 4redread the logreproduce locallyfix the CODEpush → greenWhat agents do instead, when rewarded for green:✗ weaken the assert✗ add @skip / xfail✗ try/except around the test✗ mock returns the expected value✗ delete the testRed means: read the log, reproduce it, fix thecode, push.Review test diffs on their own. A PR thatchanges code AND loosens the test that checksit deserves a hard look.SAY THIS TO CLAUDE“Don't touch the tests to make CI pass. If you thinka test is wrong, stop and tell me why.”🔍 Spot the flaw — an agent “fixed” the build- assert response.status_code == 400+ assert response.status_code in (200, 201, 400)commit message: fix flaky testCI is green. The bug is still there. The agent changed the question, not the answer.Ask: “Did you change any test assertions? Show me the test diff separately.” BENCH · DO IT IN PAIRSWhich inspection catches it?Ship › Inspection Sheds › Bench · 4 of 4Pick the CHEAPEST shed that would catch each bug.▶ click to zoom in and do the exercise
🔍3 · Inspection ShedsTESTS & THE CI GATE DISTRICT 4 OF 6 · ENVIRONMENTS, LANES & VERSIONSMarshalling Yard🛤Trains are assembled and test-run on side platforms before they leave for the main line.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. Three platforms: preview → staging → production‘Merged’ does not mean ‘live’.Ship › Marshalling Yard › Environments · 1 of 4not real usersPREVIEWone per PR · its own URL· its own DB copy ·thrown awaySTAGINGeveryone's merged worktogether · the rehearsalPRODUCTIONreal students, realmoneymerge → staging deploys itselfa human decides → deploylabel: deploy-previewEach platform answers one question earlier and cheaper than real users would.Preview: does THIS change work? Staging: doesit work with everyone else's? Production: doesit work for real people?Always ask which platform a change is on. “It'smerged” is not an answer to “is it live?”SAY THIS TO CLAUDE“Deploy this PR to a preview, then walk the signupflow there and screenshot every step.”🔍 How it works at this schoolPreview: label a PR deploy-preview → its own URL + its own copy of the database, torn down after.Staging: deploys itself every time something merges into the production branch.Production: a separate, manual deploy. A person decides.Trap: staging shares production's database. So migrations must be ADDITIVE ONLY —add a column, never drop or rename one, or staging breaks the live site. Lanes: what ships together, in what orderTests that pass alone can fail together.Ship › Marshalling Yard › Lanes · 2 of 4productionrelease lane 1.17.xpromote#12 infra#15 API#19 UImerge order: infrastructure → backend → frontend · ties → smaller firstintegration branch = merge them together on scratch FIRST, find the conflictsWith many agents, many PRs land at once. Arelease lane decides what ships together; arelease manager — human or agent — decides theorder.When dozens of PRs are sitting open, anintegration branch is how you test them as abatch and drain the queue.SAY THIS TO CLAUDE“Cut an integration branch from production with PRs#12, #15 and #19 merged, run the tests, and tell mewhich ones conflict.”🔍 The Release Manager agent's rules (Workshop 4)Order: 1 infrastructure (affects everything) · 2 backend (APIs the UI needs) · 3 frontend · ties → smaller firstBefore merging: same files? same APIs? unmet dependencies?BLOCK when: main is failing · the change's tests fail · unresolved conflicts· or the change touches a system outside its author's scopeAgents are fast: one agent doing 5 related features in order often beats 5 agents colliding. A version number is a promise about what breaksMAJOR.MINOR.PATCHShip › Marshalling Yard › Versions · 3 of 42.4.1MAJORMINORPATCH2.4.2fixed a bug — nothing else changed2.5.0added something — nothing you use broke3.0.0something you depended on changed — read the notesThe number isn't for you. It's for whoeverdepends on you, so they know if upgrading issafe.Versions let you say exactly what is live, andfind where a regression started: walk backversion by version until it works.A cohort or a sprint is a natural releaseboundary — tag it, write notes, claim somethingyou could be wrong about.SAY THIS TO CLAUDE“Write release notes for this version — new, fixed,and anything that breaks — and tell me which bumpyou'd choose and why.”🔍 Which bump?Fixed the timezone on class reminders → PATCH 2.4.2Added a “download certificate” button → MINOR 2.5.0Removed the old /api/v1/classes endpoint other apps call → MAJOR 3.0.0Renamed a database column an outside tool reads → MAJOR, even if “it's just a rename” BENCH · DO IT IN PAIRSSort the yardShip › Marshalling Yard › Bench · 4 of 4Where is it, what number is it, how many agents?▶ click to zoom in and do the exercise
🛤4 · Marshalling YardENVIRONMENTS, LANES & VERSIONS DISTRICT 5 OF 6 · DEPLOYS, FLAGS & ROLLBACKThe Points⇄A lever on the track decides which version the traffic runs on — and you want to be able to pull it back.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. Blue/green: run both, then move the trafficDon't swap versions. Switch tracks.Ship › The Points › Blue/green · 1 of 4usersrouter⇄ switchBLUE · v2.4 · liveserving everyone right nowGREEN · v2.5 · newbooted beside it · health checkfirst1 deploy green 2 check it 3 flip 4 keep blue warm = instant rollbackThe new version boots next to the old one.Traffic only moves once it passes its healthcheck. Rollback is flipping the switch back.Catch: both versions share one database, so thenew schema has to work with the old code too.SAY THIS TO CLAUDE“Before you flip traffic, show me the health checkpassing on the new version.”🔍 Why it mattersWithout it: stop old → start new → users see errors in the gap.And if new is broken, you're down until you rebuild the old one.With it: new boots beside old; no traffic moves until health passes.Rollback = flip back. A switch, not a rebuild.Rolling deploys have a cousin trap: for a moment two versions serve at once — design for it. Canaries and kill switchesShip small. Keep a hand on the lever.Ship › The Points › Canary + flags · 2 of 4traffic95% → old5%canary error ratepull backKILL SWITCHnew_checkout = OFFif flags.on("new_checkout"): …Code ships dark. A switch — not a deploy — turns it on.Canary: send a small slice of traffic to thenew version, watch its error rate, then widen —or pull back.Feature flag / kill switch: the code isdeployed but off. Turning it on or off is asetting, not a deploy.SAY THIS TO CLAUDE“Put this behind a feature flag that defaults to OFF,and tell me exactly how to turn it on and off.”🔍 A kill switch at this schoolThe Instagram comment bot only runs if one settings key says “1”.Anything else — unset, garbage, the settings store down — means OFF. It fails CLOSED.Turning it off is one command: no deploy, no code change, no review queue.Design rule: make the safe state the default state. Rollback — and the deploy that wasn't‘It said OK’ is not evidence.Ship › The Points › Rollback · 3 of 4DEPLOYgit pull new codebuild new imagestart it✓ newRESTARTsame old imagestopstart✗ nothingchangedBoth say “success”. Only one shipped your code.Rollback = redeploy the last known-good version.Rollback means putting the last known-goodversion back. Easy for code; hard for data — adropped column doesn't come back byredeploying.Decide before the deploy: what's the rollback,and how would I know I need it?SAY THIS TO CLAUDE“After deploying, prove the live site is running thecommit we meant: show me the version it reports.”🔍 A real silent no-op deployAn old doc said: to deploy, call the platform's /restart./restart stops and starts the SAME image. No pull. No build.It returned success. Logs looked normal. The fix never shipped.The fix: /deploy (pull + build + start) — then check the running version, not the return code.That stale doc lived in the repo's own instructions. Docs drift; check against what's live. BENCH · DO IT IN PAIRSPull which lever?Ship › The Points › Bench · 4 of 4Something's wrong in production. Pick the smallest lever that stops the harm.▶ click to zoom in and do the exercise
⇄5 · The PointsDEPLOYS, FLAGS & ROLLBACK DISTRICT 6 OF 6 · MONITORING & PROOFSignal Lamps📡Lamps along the line tell you about trouble before the passengers do.THE METAPHOR → THE MECHANISM. Click a box to zoom in; 🔍 boxes zoom further. The first minutes after a deployProve it, don't claim it.Ship › Signal Lamps › Smoke test · 1 of 4✓1 the running version = the commit you meant✓2 home page loads✓3 log in works✓4 the page you changed shows the change?5 error rate flat vs. beforeAny ✗ → roll back FIRST, diagnose second.A smoke test is a fast, shallow check of thefew things that must work. If it smokes, stop.Playwright can walk steps 2–4 for you andscreenshot each one — evidence anyone cancheck.SAY THIS TO CLAUDE“Smoke test production now: version, home page,login, the changed page. Screenshot each. Thencompare the error rate to before the deploy.”🔍 Claim vs. proofCLAIM: “Deployed! Everything looks good.”PROOF: “Live: 2.5.0 (commit 4e1c9a2). /, /login, /classes return 200.Screenshot of the new banner attached. Error rate: same as before the deploy.”If you can't name what would tell you it broke, that's the finding. Four instruments, four questionsAn error becomes a work item on its own.Ship › Signal Lamps › Telemetry · 2 of 4LOGSwhat happened, inorderMETRICShow many, how fast,how oftenERRORSstack trace + whohit itUPTIMEis it up — checkedfrom outsideone GitHub issueagent → branch → PR → gateProduction feeds the backlog. You hear about bugs from tooling, not angry emails.Logs tell the story. Metrics tell the size.Error trackers (Sentry, GlitchTip) give you thestack trace. Uptime checks look from outside,like a user.Wire errors into issues and the loop closes:production failures arrive in the backlogwithout anyone having to report them.SAY THIS TO CLAUDE“Wire error reporting so every unhandled exception inproduction becomes a deduplicated GitHub issue.”🔍 An error becomes a work item1 a student hits a bug → the app sends the exception to the error tracker2 the tracker groups repeats into ONE issue — count, first seen, last seen3 a rule files it on GitHub with the stack trace4 an agent (or you) picks it up → branch → PR → gate → … back to the start of this map How many nines? Pick a numberPick one you could be wrong about.Ship › Signal Lamps › Nines · 3 of 4uptimeallowed downtimewhat it costs youside projectwhatever happensa legitimate answer — just say it99%~7 hours / monthone box, backups, fix it when you notice99.9%~43 min / monthalerts that reach a human, evenings included99.99%~4 min / monthan on-call rota — a staffing decisionThen ask: what do I own that would tell me I'd missed it?Say the target out loud. Each extra nine coststen times as much attention.If nothing you own would tell you you'd missedthe number, that's the finding — wire theinstrument before chasing the nine.SAY THIS TO CLAUDE“What would tell us if login was down right now? Ifnothing would, set up an uptime check that alertsus.”🔍 Turn the number into a checkSLO: “login works 99.9% of the time, measured by an outside check every minute.”Error budget: 99.9% allows ~43 minutes down a month.Burned half of it early in the month? Freeze risky deploys until it recovers.A target with no instrument behind it is a wish. BENCH · DO IT IN PAIRSHow do you know it works in prod?Ship › Signal Lamps › Bench · 4 of 4Evidence, not confidence.▶ click to zoom in and do the exercise
📡6 · Signal LampsMONITORING & PROOF
SDLC meta-map ↗
0 / 0

Explore

Click anything to zoom into it · scroll to zoom · drag to pan
Esc zoom out one level · Home whole atlas
/ search

Tour

→ / space next stop · ← previous
The tour visits every district and framework in teaching order.

Teach

N presenter notes for whatever you're looking at · F fullscreen
Every view has its own link — copy the URL to send someone straight to it.

Reading the map

Your change is a train. Six districts are six places on the railway it passes, in order. Each district: three ideas and a bench. Small text appears as you zoom in. Some tiles have controls you can click.
Click anything to zoom in · scroll to zoom · Esc to back out · → for the guided tour