Repository layout · plain-language explainer

Two repos,
one frozen truth.

Keep your planning docs and your product code in two separately version-controlled repositories — linked by a small pin file so the code can only ever be built against docs that were actually frozen.

monosplit— a new dial, alongside profile, tier & delivery mode

The choice

One repo, or two

Repository layout becomes a project axis you declare in 0b_Product_Brief — just like profile, rigor tier, and delivery mode. It changes where things live, never the phases, the freezes, or the gates.

The split

What lives in each repo

The boundary is simple: planning on one side, code on the other. The governance record stays with the planning.

The docs repo — <project>-docs

The DFlow kit plus everything that plans and governs v1:

• The execution set 0a7d and 6e_Increment_Plan
• The UI contract packet (docs/ui/)
• The execution-memory trail (progress, learning log, increment checkpoints, verification reports)
• Every freeze is a tagged commit here

The implementation repo — <project>

The product, built one frozen story at a time:

• Product code, tests, and CI
• Its own Gitflow history and releases
• A .dflow/docs-ref.json pin file locking it to a frozen docs commit
• Reads each story packet from the docs repo at that pinned ref

The link

The pin file ties them together

A small .dflow/docs-ref.json in the implementation repo records exactly which frozen docs commit the code is being built against. In incremental mode it advances one increment at a time.

// <project>/.dflow/docs-ref.json
{
  "docs_repo": "../<project>-docs",   // sibling path or git URL
  "docs_path": "docs/outputs/project",
  "docs_ref":  "inc/I2-freeze",        // frozen tag / SHA
  "freeze": {
    "scope_frozen": true,
    "increment": "I2",
    "increment_freeze_ref": "inc/I2-freeze"
  }
}
docs_repo + docs_path

Where to find the planning set. A relative sibling path for local work, or a git URL with a CI checkout step for pipelines.

docs_ref

The frozen tag or commit the code is pinned to. The story packet's docs/outputs/project/* paths resolve here — never to live, unfrozen docs.

freeze — advances per increment

Each /plan-increment freeze tags the docs repo (e.g. inc/I2-freeze) and bumps the pin before that increment is built. In big-bang mode it is set once at story freeze.

How work moves

Plan in one repo, build in the other

Planning and freezing happen in the docs repo; building happens in the implementation repo against the pinned ref; the learning comes back to the docs repo.

One consequence to know: in split mode a single /execute-story run commits code to the implementation repo and the learning/checkpoint back to the docs repo — two repos, two commits. That is expected, not drift.

Why a pin, not just two folders

The validator guards the freeze

A check runs in the implementation repo (and its CI). It is the whole reason the link is a pin and not a handshake — the code cannot be built against docs that were never frozen, or that have since moved.

1

Pin is present and valid

.dflow/docs-ref.json exists and is well-formed.

2

Points at a real freeze

docs_ref resolves to a docs commit whose scope or increment freeze is actually recorded.

3

Packet has not drifted

The packet the agent uses matches that pinned ref. Unfrozen or moved docs fail the gate.

Reassurance

What stays the same, and the costs

mono is untouched

Single-repo projects (the default) work exactly as before. Split is opt-in.

Same phases & freezes

The lifecycle, the vertical-slice rule, and every gate are unchanged. Only locations and resolution change.

Independent histories

Each repo has its own Gitflow, releases, CI, and access control.

Two commits per story

Code lands in the impl repo; memory/checkpoints land in the docs repo. Documented as expected.

Both repos present at build

The agent needs the docs repo checked out at the pinned ref (sibling clone or CI checkout).

Pin maintenance

One more thing to keep current — mitigated by auto-bumping at each increment freeze and a validator that fails if it is stale.