Adopt Partition on an existing project

Your repository already runs. It has years of code, contracts it serves, systems it calls, and a domain the team carries in its head and in a few documents. Adopting Partition on it happens in two phases, and the line between them is firm: first, once, you gather the sources of the repository with an AI assistant, outside the package; then Partition takes them from there, exactly as on a project that starts today. The code you have is kept: its spec leads from then on, and the code follows on the next change that touches it.

Why the method works this way is in Why Partition; where each document of this article goes is in the repository map. This article does not repeat the journeys it reuses: it says what is different when the code exists, and links to the rest.

The situation

You want the assistant to work from one durable spec per bounded context on a repository that has none, or only an old specification nobody keeps up to date. Nobody on the team has time to write a PRD of what the code already does. You want the specs to say what is true of the domain, the boundaries to be drawn by your architect, and nothing in your code to move because a tool decided it should.

Partition is the companion of one repository with one business domain. The adoption describes this repository: what it owns and what it only calls. It does not model the estate around it, the other systems of your company or a whole ERP or CRM: what Partition is not says why.

The two phases

  Before Partition, outside the package With Partition
When Once, possibly before the package is installed From the install on, as on any project
Who works You and an AI assistant of your choice, in one session The assistant with the partition-* skills, and you
What it produces Sources only: the contracts the repository exposes, a description of the domain, the architecture decisions settled now, an existing diagram when there is one, and the perimeter Everything Partition normally produces: docs/partition.yml, the specs, the area files, the invariant register, the C4 model, the rule files
Who validates The owner of each source, who commits it alone You, at each stop the skills make, as in every other journey

The first phase is not a Partition skill. No skill of the package runs it, and the package gives no procedure for it: it is a working session you hold with an assistant to put on paper what your repository is. Partition starts reading at the second phase, from the files the first one left.

What you bring

Before Partition: the sources, and the perimeter

The aim of the session is the most complete picture of the repository that can be identified, written as sources Partition knows how to read. Each one goes where the repository map puts it.

The perimeter. What this repository owns, the business it decides, and what it only calls, each other system by its name and what it is called for. It is the line that tells the assistant what belongs here. It goes into the description of the domain, as a section of its own. The Perimeter section only gives context: it is not a unit, so it is not decomposed. A system you only call is named there, and weighs in the decision only as a third party the source names; an unnamed one never counts.

The contracts the repository exposes. One OpenAPI file per API the code serves, as it serves it today, under a stable name. A contract you already keep is a source as it is, read where it lives: generated next to the code, in an API module or in a shared folder, it is not moved. One you write now goes, by default, to docs/contracts/ (the repository map). The contract of a system the repository only calls is not one of them: it is never decomposed, as the bounded contexts below says.

A description of the domain. A Markdown file, by default in docs/sources/, under a stable name (the repository map), written so that partition-shape can read it:

An existing diagram, when your team has one: a hand-drawn .drawio file, kept as it is. In the guide it sits at docs/architecture/<diagram>.drawio, an example, not a convention.

An existing specification, when your team wrote one before Partition, and any other document that explains what the project does: it is not rewritten in this session, and not moved. It stays where it lives, whatever its folder. Its owner validates it as the source, saying it still describes what the system must do, and commits it alone; Partition decomposes it in the second phase like any other source (the repository map).

Before you commit, the owner of each source reads it, corrects it and keeps on Rule: only the sentences the team confirms. Then each source is committed alone, as every source of the guide is: the decomposition records the commit of a source, and every later version is compared from it.

What the session does not write. No docs/partition.yml, no spec, no area file, no invariant register, no C4 model, no rule file. Each of them is created with Partition, in the second phase, by the skill that owns it and with your validation. A document written outside the package would skip the stops where a person decides: the boundary, the business rules, the scope of a rule.

With Partition: what you bring to each journey

The same entries as on any project, with the existing code as one more thing the people answer from:

What you say

Before Partition: an example prompt

This prompt is written for this article. It is not a Partition skill and calls none; use it, or your own, with any assistant, in the repository:

Read this repository and help me describe it, so that my team can validate the description. Change no code. Write only the files I list here, and nothing else.

  1. docs/contracts/<name>.openapi.json: one OpenAPI file per API this code serves, as it serves it today. Where an existing contract and the code differ, list the differences; do not choose.
  2. docs/sources/<name>.md: a description of the domain. Start it with Version 1.0. Then:
    • a section Perimeter: what this repository owns, the business it decides; and what it only calls, each other system by its name, with what it calls it for;
    • the business entities, one name each, in the words the code and the team use; when the code uses two words for one thing, say so and ask me;
    • one requirement per behaviour the code implements, each under its own identifier, REQ-1, REQ-2, in order;
    • each condition the code enforces, as a sentence after Candidate rule:, with the file and the line that enforce it on the next line; I will decide which ones are rules;
    • the architecture decisions you can see settled, each with its reason when the code or a document gives one, otherwise as a question;
    • every question you cannot answer from the code, one per line.
  3. If a hand-drawn diagram of the architecture exists in the repository, tell me where; do not draw one.

Do not group the requirements, and propose no structure: how the domain splits is decided later, by the architect. Invent nothing: what the code does not show is a question to me.

The Candidate rule: lines, drafted from the code, are for a project that no spec or other document explains. When one does, it is the source of the rules: it is decomposed as it is, and a rule is drafted from the code for none of its parts.

Then read what came back with the people who own each part: the product owner for the requirements, the architect for the contracts and the decisions. The Candidate rule: lines were drafted outside the package, from what the code enforces. A condition the code enforces may be a bug: the spec will lead, not the code. A line becomes a rule only on your team’s word, as a rule of the domain. Turn each one your team confirms into Rule:; delete the others, or turn them into questions. Leave no Candidate rule: line in a source you commit. Then commit each source alone.

With Partition: the same prompts as on any project

Install the package as Set up a project shows, then, in a fresh session, from the README’s The first day:

Set up Partition for this project.

Measure the context budget.

Our rules load in every session, fix that.

Then the bounded contexts, one area at a time, as the README does:

Decompose docs/sources/<name>.md into bounded contexts, area <area>.

or, from a contract: “Decompose docs/contracts/<name>.openapi.json into bounded contexts, area <area>.” A source is named at its path, wherever it lives. For a specification your team wrote before Partition, as for any source:

Decompose docs/legacy/<file>.md into bounded contexts, area <area>.

For the architecture, from the README’s Day to day: “Turn our draw.io into the model.”, then “Check the architecture.” once the hexagons have their form.

To see where the existing code and its new spec disagree, without a change in hand, from the README’s Day to day:

Audit <bounded-context> against its spec.

And when a change meets a disagreement: “The code and the spec disagree.”

What comes back

Phase 1: nothing from Partition

The first phase leaves files you wrote and validated, by default in docs/contracts/ and docs/sources/, beside the specs and contracts you already had, where they live; each committed alone. Installing the package afterwards writes nothing under docs/ (Set up a project), so your sources are never overwritten: Partition reads them when you ask, and not before.

The setup: as on any project

partition-budget creates docs/partition.yml with you, from the template it ships. It asks for no bounded context and does not guess one from your folder tree: they come from a source, and contexts: stays absent or empty until partition-shape declares them. The first measure is the baseline. On a repository that has lived for years, the entry file your assistant loads in every session is often long: partition-rules lists the rules without a scope, proposes one file per topic with the files each really concerns, waits for your validation, and moves the text without rewriting it. When you ask it to start rules for a topic that has none, it answers each question from two sources only, the code as it is and your answers, quoting the file that shows a convention and asking you when the code shows two. All of it is in Set up a project.

The bounded contexts: from your sources, through partition-shape

partition-shape reads each source you name, inventories its units, weighs each against the six written criteria and asks the architect how to decide the boundary: a workshop or a proposal. Then the hard stop: the writing plan, and a new bounded context validated by name. Once you validate, it writes one spec per bounded context, pointing to the parts of the source it owns, the rules your source states copied word for word under a “TO VALIDATE” banner, and the context declared in docs/partition.yml with its area and, once given, its code paths. A person confirms the rules; until the banner comes off, the context is not fit for design. Every detail is in Create a bounded context.

Four points matter more on an existing repository:

A specification your team wrote before Partition is decomposed the same way, read where it lives and never changed. Its owner has validated it as the source; the reader’s preconditions and inventory report what it leaves unsettled; the architect decides the boundaries; a person confirms each copied rule. A rule another spec already holds is reported, never moved: a person names its owner. Its history of rulings, a section on how code is written and a file of invariants are read as Create a bounded context says.

The architecture: the C4 model, and the code checked against the map

partition-c4 writes docs/architecture/model.yml from your hand-drawn diagram, read once, or from its template. An element enters only when a source establishes it: the code, a decision, the owner. A container guessed from a folder name is an invention, and a box whose kind or parent is left open is a question to you.

partition-hexagon chooses the form of each hexagon from the Business rules of its spec, not from the code, and the layer map is written with the owner from the project’s architecture rule, never inferred from the folders. Then, asked to check, it reads the existing code against the map and reports every dependency that is not allowed, with file:line and the two layers, and one hexagon importing from another instead of going through a contract. It changes nothing while checking. A finding is fixed through a plan; when the code departs from the map beyond the scope of the current change, it points it out and asks before refactoring.

The existing code: kept, and led by its spec

Once a bounded context has its spec, the spec is the source of truth and the code implements it. Nothing is rewritten to adopt Partition. The code follows the spec on the next change that touches it, through the plan of that change, delivered as in Deliver through a plan.

Where code and spec disagree, it is the case of step 05 of the guide: the spec moves first. partition-spec says which side is wrong and why: a spec incomplete, outdated or ambiguous, or the code a bug; when it cannot tell, it asks. It never edits the spec to match the code because the code is what runs. When the spec is wrong, it corrects it, shows the change and gets it validated, and only then does the code follow, through a plan; when the code is wrong, the spec stays and the code is fixed through a plan. A rule copied from your source changes only through your source. The whole case is in Change at any moment.

You look for those disagreements before any change: once the rules of each new bounded context are confirmed, run the spec-auditor agent on it. It reads the code of that bounded context against its spec, as a reader who did not write the code, and reports each gap with its evidence and which side is wrong; the spec moves first. It changes nothing.

Where the code does not respect a boundary, a dependency that crosses between two bounded contexts without an interface, it is a reshape, and the architect decides it. Partition never decides a boundary: before one moves, the assistant tells the architect the decision is theirs and asks the way, a workshop or a proposal. When it prepares a workshop, partition-reshape lists the dependencies that do not go through an interface today, with file:line: they are the price of the move, paid before it. A missing precondition is its own piece of work, with its own plan, before the move; each move is validated by name before it starts, and is carried out through a plan (partition-plan), the specs changing in the same plan as the code, and proven a move after it. The whole order is in Reshape when it grows, and the move in its plan.

Then: a project like any other

Once its sources are decomposed and its rules confirmed, an adopted project is where a decomposition leaves any project. Every other journey applies to it unchanged: deliver through a plan, change at any moment, reshape when it grows.

What you decide

Before Partition:

With Partition, as on any project:

On the existing code:

Go deeper

The guide has no step for a codebase without a spec; these steps show the mechanics this article relies on.

Back to the series.