Finish your software factory: take a bad change back before anyone notices A developer has released Shipping Floor, an open-source example repo that demonstrates an agentic software factory capable of automatically rolling back a bad change without human intervention. The project uses three AI agents that generate electronic music in the browser, with LaunchDarkly guarded rollouts and feature flags controlling agent behavior and validation limits at runtime. The walkthrough shows how a deliberately tightened gain gate causes one agent's output to be rejected while the others continue, illustrating bounded blast radius and automated reversal. Most agentic factory stacks stop at the deploy. They generate, they validate, they ship, and then the instructions turn into a vague "monitor" step, which in practice means a person watching a dashboard. The capability that is actually missing is narrower than monitoring and harder to build: a change that moves the process gets taken back without a person. That is a throughput problem before it is a tooling problem. When a person wrote every change, review was the quality system, and a few changes a day could each be read before they shipped. A factory whose agents deploy continuously has no room for that, and the failures it produces are the kind review misses anyway. One of the two failures here passes every check the build side runs. The other one is the checks, all of them firing correctly while the pipeline quietly stops producing. So a factory without this is not slower than one with it. It is less certain. It ships improvements and degradations at the same rate, reports success both times, and leaves you one lever: a deploy-level rollback that takes back everything else along with the change you wanted gone. What you build here instead is a bounded blast radius while a change proves itself, a verdict that does not depend on who is paying attention, and a reversal that touches one change and leaves the rest of the band playing. The example repo builds an agentic band. Its loop generates, validates, and deploys about eleven times a minute. In this walkthrough, you start the music factory, listen to it, break it on purpose, and watch a guarded rollout https://launchdarkly.com/docs/home/releases/creating-guarded-rollouts put it back. Three agents make up your virtual band: a drummer, a bassist, and a keys player. They generate electronic music in the browser while a conductor keeps tempo and key. Every few bars each agent asks an AI model for the next version of its part. A parser accepts or rejects the result. If the new pattern is well-formed, the next cycle plays it. If it is not, the last good pattern keeps looping. Shipping Floor https://github.com/launchdarkly-labs/shipping-floor contains no musical vocabulary of its own, so personas, gain limits, and groove recipes all come from LaunchDarkly prompt snippets https://launchdarkly.com/docs/home/agentcontrol/snippets at runtime. If LaunchDarkly is unreachable, the band holds and then falls silent. There is no local fallback for this demo. Two things about the band can change without a deploy, and each uses a different LaunchDarkly object. What an agent is , its model, its parameters, and a system message assembled from pinned prompt snippets, is a variation in an AgentControl config https://launchdarkly.com/docs/home/agentcontrol . The code around the agent, including the limit its validator enforces, sits behind a boolean flag. Either one changes what the running band does on its next generation, and neither needs a restart. The parser only asks whether a pattern is well-formed, which is a narrower question than whether the music got better. An agent asked to make its part more interesting can comply by turning itself up. Past the point where the speakers reproduce the mix cleanly the sound stops improving, and every check still passes and reports another good version. That is why a variation carries a gain ceiling, and why a metric https://launchdarkly.com/docs/home/metrics reads the peak gain of what actually shipped. This walkthrough ships that limit as a flag, strict-mix-gate , set tighter than the drummer can satisfy at all. Every pattern it generates is rejected, so hold-last-known-good replays the previous bar while the bassist and keys, whose limits tighten only slightly, keep publishing around it. One instrument is dead, the other two carry the mix, and nothing crashes. You will not hear it. The publish rate will. The correction is not to loosen the gate, since nothing yet tells you the gate is the problem. It is to count the attempt and the success separately, so a rejected candidate contributes a zero instead of contributing nothing, and then to guard the change with the metric that can see its failure shape. That is the whole argument in one line: gate each artifact on an invariant you can compute, measure the process for drift, and let a change that moves the process be taken back without a person. Those are three different clocks, and the last one is a release control rather than a gate, which is why it can catch a change that every individual gate approved. A loud regression and a silent one are not visible to the same instrument, so which metric watches is decided per change. A factory gates in three places, and they run on different clocks. Only the first is a runtime gate: | Layer | Clock | Decides | On failure | Here | |---|---|---|---|---| | Parser and maxGain | Every generation | Is this artifact allowed | Reject and retry | Already in the repo | | Hold-last-known-good | Every generation, on rejection | What plays instead | Replay the previous bar | Already in the repo | | Guarded rollout | One monitoring window | Is this change allowed to continue | Revert the change | You configure it in step 4 | Run this from a directory that is not already a Shipping Floor checkout. Cloning inside an existing clone nests a second copy and fails. Here is the clone: git clone https://github.com/launchdarkly-labs/shipping-floor.git cd shipping-floor npm install If you already have the repo, skip the clone and run npm install in that directory. Do not start the app yet. Until LaunchDarkly is serving prompts, there is nothing for it to play. The application already evaluates a boolean flag called strict-mix-gate and already emits the guardrail metrics. Your job is to create the LaunchDarkly resources the seed lists in a new project, not to edit application code, and not to write into an existing Shipping Floor project. Using the shared demo is not a new implementation. https://mcp.launchdarkly.com/mcp/launchdarkly under the MCP settings or use the claude mcp add configures Claude Code only. list-projects . This real API call is the authentication check. If it returns token expired even after an auth helper reported success, remove the MCP server, add it again, and finish the browser consent flow once more. Here is the equivalent command for Claude Code: claude mcp add --transport http "launchdarkly" \ "https://mcp.launchdarkly.com/mcp/launchdarkly" Cursor may hold production MCP writes behind an approval card. If targeting, metrics, or the rollout appears to stop, approve the card and let the assistant retry. These writes stand up the project; they are not a customer rollout. Connect the application to the new project before bootstrap, so the assistant does not default to an existing shipping-floor project: cp .env.example .env Set these three values in .env : LAUNCHDARKLY PROJECT KEY=