3 · Playbooks

How a run works, end to end

A playbook is a run: a piece of work broken into steps, with your approval needed before anything is written. They all work the same way. This section covers that shape first, then walks through three of them, screen by screen.

What every run does

Whatever a playbook is for, it goes through the same steps.

StepWhat happens
It states its scopeBefore it starts, the run tells you what it covers and what it will not do. Saying what is out of scope is what stops the work spreading once it is under way.
It asks what the code cannot tell itA short set of questions, each one saying what your answer will cost you. See the next topic.
You approve the contextEvery answer on one page, next to the analysis it was read against. Nothing is planned until you press Start planning.
You approve the planThe full plan before a single file is written: every project, every change, every task in order.
One commit per taskEach task edits a group of files, compiles them, and commits. If one fails the damage stops there, and you can stop and pick it up again rather than start over.
It re-reads what it wroteThe same pass runs over the generated code, so you review the output the way you reviewed the input.
It accounts for itselfWhich of its own checks passed and which it could not confirm, your answers listed back, where the time went, and what it cost.

Where there is no toolchain to compile against, tasks are committed and marked ungated rather than reported as a clean build. There is an example in Building an application from a description.

The questions a run asks first

Before it plans anything, a run asks you the things the code cannot tell it. Each question says what each answer will cost you.

Take the one that decides how a monolith gets cut up — the screen is further down, in Splitting a monolith into services. It offers Domain-driven (bounded contexts), Fine-grained subdomains, or Technical layers (API / core / data). Each one says what it costs: smaller services mean more network hops, and horizontal slices are "rarely the right first cut". The recommended option is not a default. It is worked out from the entity and unit-of-work clusters already in your code, which is what its own line says.

Why it asks at all

Take "reason for splitting". The code genuinely cannot answer it. Splitting so teams can deploy independently gives you different boundaries from splitting so one failure cannot take down the rest. Only your team knows which one you are buying, so the run asks. Once you have answered, it holds you to that answer for every decision after it.

Every question also offers Skip section and Sensible defaults for the rest, so you can answer the ones you care about and let the run take its recommendation on the others.

Upgrading a .NET application in place

This run moves an application onto a current .NET without redesigning it. Every screen it shows you, in order.

The brief

The playbook brief. It states the whole scope before you start, including the things it will not do.
The playbook brief. It states the whole scope before you start, including the things it will not do.

Bump every NuGet package, swap deprecated packages for their replacements, patch vulnerable ones, convert packages.config to PackageReference and legacy project files to SDK-style, turn on nullable and implicit usings. Then the limits: a version and dependency upgrade only, no decomposition, no refactoring, behaviour preserved. .NET Framework System.Web and WCF web apps are flagged because they need a real port, not quietly upgraded.

Where the work lands

Four places the upgraded code can go. Each one says what happens to your original code.
Four places the upgraded code can go. Each one says what happens to your original code.

Keep main as it is and put the upgrade on a new branch, which is the recommended default. Make the upgrade main and archive the old code. Export to a brand-new repository. Or commit straight onto the current branch. Nothing here is destructive: the original is always reachable, on an untouched branch, an archive branch, or a frozen source branch.

Target framework

The target framework, with the reason you would pick each one.
The target framework, with the reason you would pick each one.

.NET 10 is the current long-term-support release and the recommended default, with three years of support. .NET 9 is standard-term support and worth picking only if a dependency or platform has not certified on 10 yet. .NET 8 is the previous LTS, for when you have to stay on the prior line.

Vulnerable packages

Whether a package with a known advisory gets forced to its first fixed version.
Whether a package with a known advisory gets forced to its first fixed version.

With this on, any package with a known advisory is moved to the first fixed version, even when that is a bigger jump than a routine update. The question explains why it recommends yes: a vulnerable dependency is treated as a blocker to a clean upgrade.

Language settings

Nullable reference types: on, off, or left exactly as each project already declares them.
Nullable reference types: on, off, or left exactly as each project already declares them.

Turning nullable on adds compile-time warnings about null safety and changes nothing at runtime. The option says so, so you are not guessing at the risk.

Project format

Whether old project files get rewritten to the modern SDK-style format.
Whether old project files get rewritten to the modern SDK-style format.

Old project files list every source file and carry reference hint paths. The SDK-style format does neither, and you normally have to convert to it before a legacy project can target modern .NET at all.

Dependency format

Whether projects still using packages.config move to PackageReference.
Whether projects still using packages.config move to PackageReference.

PackageReference resolves transitive dependencies for you, and SDK-style projects require it.

Verification

Whether the last step runs your test suite after the release build.
Whether the last step runs your test suite after the release build.

Running the tests checks behaviour rather than just compilation. What the run recommends depends on whether your test project builds against the new framework yet.

The plan, before anything is applied

Every project with its current and target framework, the package changes, anything deprecated or vulnerable, and how many places in the code the change touches.
Every project with its current and target framework, the package changes, anything deprecated or vulnerable, and how many places in the code the change touches.

Nothing is applied until you approve this, and the approval says what it covers: "Apply this plan across 2 tasks? Each change is compiled and committed before the next."

The report at the end

The run report: its own checks, your answers listed back, where the time went by step, and what the run cost.
The run report: its own checks, your answers listed back, where the time went by step, and what the run cost.

Three things on that screen are worth pointing at.

  • Twelve checks passed, and the ones it could not confirm say so. "Cannot independently confirm the verification gate is green from excerpts alone" is written into the report rather than rounded up to a pass.
  • Your answers are listed back as the values actually used: dotnet_version net10.0, git_strategy archive-and-adopt, nullable enable, and the rest. Months later you can still see what produced this result.
  • Where the time went. 450 seconds in total, 439.5 of them in one step, migrating the marked API seams file by file. The other seven steps took nine seconds between them.
Watch the whole run

Splitting a monolith into services

A .NET healthcare monolith becomes six services. Every screen, in order.

It reads the code first

The monolith, read before anything is proposed: seven domains, twelve end-to-end flows, twenty-five database calls, ten hotspots, and no unreachable files.
The monolith, read before anything is proposed: seven domains, twelve end-to-end flows, twenty-five database calls, ten hotspots, and no unreachable files.

Every later step works from this. It is why the plan can name specific files instead of describing them in general terms.

The brief

The run states its scope before it starts: understand the monolith, plan the split, then generate and compile each service.
The run states its scope before it starts: understand the monolith, plan the split, then generate and compile each service.

Where the work lands

Four destinations for the generated services. In all of them the monolith history stays reachable.
Four destinations for the generated services. In all of them the monolith history stays reachable.

The monolith branch stays untouched and the services go to a new branch. The services become main and the monolith is archived. Everything moves to one new repository. Or every service gets a repository of its own.

Why you are splitting

The one question the code cannot answer: what you are buying with the split.
The one question the code cannot answer: what you are buying with the split.

Splitting so teams can deploy independently produces different boundaries from splitting so one failure cannot take down the rest. The run asks rather than assuming.

How to draw the boundaries

Domain-driven, finer-grained subdomains, or technical layers, with the consequence of each and a recommendation computed from the code.
Domain-driven, finer-grained subdomains, or technical layers, with the consequence of each and a recommendation computed from the code.

How to cut over

Strangler fig is the default: one part at a time, behind a gateway, while the monolith keeps serving the rest.
Strangler fig is the default: one part at a time, behind a gateway, while the monolith keeps serving the rest.

Parallel run and big-bang are both available, with their risk written down rather than implied.

You approve the context

All 32 answers on one page, next to the analysis they were read against. Planning starts when you press Start planning.
All 32 answers on one page, next to the analysis they were read against. Planning starts when you press Start planning.

Azure. .NET 10. A database per service. Postgres. JWT through Keycloak. GitHub CI. Kubernetes manifests. Everything the plan will be built on, in one place, before the plan exists.

You approve the map

The proposed services: how many tables each owns, which tables, and which monolith files each was carved from.
The proposed services: how many tables each owns, which tables, and which monolith files each was carved from.

Under the table, Refine the split takes a change in plain English and re-plans the map. Its own examples are "pull authentication into its own service", "split functional vs non-functional services", "merge inventory into orders". The gate states the whole commitment in one sentence: "Generate 6 services across 29 tasks? Each file is generated, compiled, and committed before the next."

This is the part that matters. The map is the decision and the code follows from it. Getting the boundaries wrong is expensive to undo once the code exists, and free to fix on this screen.

It runs, task by task

The run in progress, numbered by phase. One commit per task, and the structural index is refreshed as it goes.
The run in progress, numbered by phase. One commit per task, and the structural index is refreshed as it goes.

"Working on target-master — one commit per green task." Each task takes one service, edits its whole group of files, compiles once, then refines. A task that fails does not take the rest with it, and you can close the app and resume from the welcome screen.

Every service gets its deployment files

The generated Kubernetes files for one service, and the config map open in the editor.
The generated Kubernetes files for one service, and the config map open in the editor.

Each service gets its own config map, deployment, autoscaler, secret and service manifests, built from the environment, authentication and telemetry answers you gave earlier. The values are real: the OTLP endpoint, the service name, the Keycloak authority.

What you end up with

The generated platform: six services, each with its own test project, plus the solution, compose file, Azure descriptor, contract lock and architecture documentation.
The generated platform: six services, each with its own test project, plus the solution, compose file, Azure descriptor, contract lock and architecture documentation.

It reads its own output

The same structural pass, run again over the generated code. Call graph, entry points, reachability, data access.
The same structural pass, run again over the generated code. Call graph, entry points, reachability, data access.

The output is reviewed exactly the way the original codebase was, using the same screens.

Watch the whole run

Building an application from a description

This run starts with nothing but a description of what you want. No repository, no scaffold, no template to fill in. Here it builds an equities trading desk.

Your description becomes a spec

Your description written back as a spec, with the goal, the constraints, the acceptance criteria and what is out of scope.
Your description written back as a spec, with the goal, the constraints, the acceptance criteria and what is out of scope.

The card is headed What I understood. Out of scope earns its place: a goal with nothing ruled out cannot be checked at the end, and it cannot stop the run from growing. The button says what approving means: Approve — start planning.

Which areas of the desk are in scope

The desk areas. Each one says what it covers and how much of it would be built rather than declared.
The desk areas. Each one says what it covers and how much of it would be built rather than declared.

Trading and Markets and analytics are picked here. Securities finance, Risk and position, Post-trade, Compliance and Client and advisory are left out. Each area tells you the split before you choose: Trading is "2 built, 6 declared".

Which capabilities inside them

Choosing what to build inside each area. What you tick is built end to end against a reference screen; the rest is registered and marked as declared.
Choosing what to build inside each area. What you tick is built end to end against a reference screen; the rest is registered and marked as declared.

Trade Entry, Order Matching, Stock Lending and Borrowing, Order Management, Execution Management, Algo Control, Basket and Program Trading, Block and Dark Liquidity. Three of them are built end to end in this run, each against a reference screen someone designed. The rest are declared rather than built: still registered in the application and marked as declared, so anyone opening the result later can tell what is real.

Which theme

The same blotter shown in each theme, so you choose by looking at it rather than by name.
The same blotter shown in each theme, so you choose by looking at it rather than by name.

Dark desk, light operations, or high contrast. The choice sets brightness and contrast only. It does not decide buy and sell, and it does not decide market direction.

Which way is up

The colour convention for price and P&L direction, previewed on a live market monitor.
The colour convention for price and P&L direction, previewed on a live market monitor.

Blue up and orange down is the recommended default, because it separates the two directions strongly without using the red that risk needs. Green up / red down and red up / green down are both there. Whichever you pick, every value also carries a sign and a glyph, so colour is never the only cue.

Which screen it opens on

The default workflow, with a live preview of each option before you choose.
The default workflow, with a live preview of each option before you choose.

The plan, task by task

The build resolved into an ordered list of scoped file edits, shown in full before a single file is written.
The build resolved into an ordered list of scoped file edits, shown in full before a single file is written.

It runs as numbered phases

The phases: create the project files, plan the app, break it into precise tasks, then build.
The phases: create the project files, plan the app, break it into precise tasks, then build.

One line here is worth reading twice: "Domain template selected 56 exact-file logic tasks; no planning model call was used." The plan came from a template, not from a model, so it costs nothing and cannot vary between runs.

Building

Each task edits its files, refreshes the index, and commits before the next one starts. The activity list on the left fills in as the files are written.
Each task edits its files, refreshes the index, and commits before the next one starts. The activity list on the left fills in as the files are written.

The cost sits at the bottom of the screen the whole time.

The report says what did not happen

The summary at the end. It finished, it lists the phases and answers, and it says in a box of its own that nothing was compiled.
The summary at the end. It finished, it lists the phases and answers, and it says in a box of its own that nothing was compiled.

Completed in 6,629 seconds. Eleven phases ran, 49 answers captured. Then, in a box of its own: 56 of 56 tasks committed without a compile gate, because there was no toolchain available when each was committed. Every task below it carries an ungated badge.

The notice also tells you what to do about it. Tasks finished in an earlier run keep their original status, so you either reset the branch and run it again to compile them, or build the project yourself to check. A warning that does not tell you the fix is only half a warning.

The application, running

The generated desk on localhost: an execution blotter with working, partial and exception states, an order ticket with smart routing, and level-two market depth.
The generated desk on localhost: an execution blotter with working, partial and exception states, an order ticket with smart routing, and level-two market depth.

Why that box matters

An application that compiles and an application that was never compiled look exactly the same in a file listing. Only the report can tell you which one you have, and only if it is willing to say so.

Watch the whole run