Skip to content
rlsbl.commands.monorepo.mirror_cmd
On this page

The mirror reconciler: converges a subtree mirror's branch to its derived state, materializes every released version's tag, and refuses foreign commits.

#rlsbl.commands.monorepo.mirror_cmd

#rlsbl.commands.monorepo.mirror_cmd

Monorepo mirror reconciler.

The subtree mirror of a monorepo project is a TOOL-OWNED, derived artifact. Nothing is ever authored on it by hand -- it is regenerated from the monorepo whenever the project's history advances. Force-push (with lease) is the routine write, not an exceptional one.

The command is an observe-then-converge reconciler:

  • rlsbl monorepo mirror <project> -- observe, then converge (apply).
  • rlsbl monorepo mirror <project> --dry-run -- observe and report a plan only

(zero writes beyond the loose objects a branchless git subtree split leaves in the monorepo object store).

Desired state of the mirror's main:

  • its tip is exactly one scaffold commit atop the CURRENT split-ancestry commit,

where the split-ancestry commit equals the deterministic branchless subtree split of the project's current history, and

  • the scaffold commit touches only scaffold-owned paths.

One path is swept out of the mirror on every convergence regardless of where it came from: a publish workflow under .github/workflows/. A mirror never releases itself -- its tags and Releases are written by the monorepo's release flow through :mod:rlsbl.mirror_publication, and a publish workflow on the mirror would be a second, unsynchronized publisher of the same versions, triggered by the reconciler's own pushes. Scaffold's publish_mode: "none" covers the workflow scaffold would have rendered; the sweep covers the two it cannot see -- a leftover from an older scaffold layer, and one that rode in through the subtree split because the member's own directory carries it. A member that genuinely carries a publish workflow KEEPS IT IN THE MONOREPO, where it is that member's CI; only the mirror's copy is swept. A tip that still carries one is classified scaffold_stale rather than converged, so the next apply rebuilds the layer without it.

A tripwire enforces the contract with no heuristics: the remote tip must be EITHER a bare split-ancestry commit (the current split SHA or an older one -- covers pre-scaffold-layer mirrors) OR exactly one commit atop a split-ancestry commit whose changed paths are all scaffold-owned. Anything else is a foreign commit -- a contract violation -- and is a hard error that touches nothing.

The tripwire's walk asks an ancestry question per commit, and that question has three answers. "No" and "cannot tell" both keep the walk moving, because a commit above the split boundary normally CANNOT be answered: its objects live on the mirror, not in the monorepo. The difference shows up only when the walk reaches the end of the tip's history without ever finding a split-ancestry commit. If every answer along the way was a definite "no", the mirror really does hold unrelated work: contract_violated. If any answer was "cannot tell", the honest verdict is ancestry_undetermined -- also a refusal that touches nothing, but one that names a git that could not answer (pruned or unfetched objects) instead of accusing an operator of authoring on the mirror.

The mirror's TAGS are a second dimension of the same reconciler. Every version the release record records shipped from a monorepo commit, and the mirror carries that version under its own standalone tag name at the subtree split of that commit. A mirror can be converged on main and still be missing every one of those tags -- a mirror bound after the fact, a tag push that failed at release time, a mirror that was reset -- so the preview names each missing version and an apply materializes it from the release record through :mod:rlsbl.mirror_publication.

The observe/preview/apply machinery itself is not this module's: it comes from :mod:rlsbl.preview_apply. A mirror judges the branch and one subject per released version, so its preview is the keyed verdict list of that module and its plan output is composed by that module's single renderer.

#scaffold_owned_files

python
def scaffold_owned_files()

The scaffold-owned root files: the pinned set plus identity manifests.

#MirrorError

A hard error in the mirror reconciler (contract violation, auth, etc.).

#MirrorPlan

The observed state of a mirror relative to its monorepo source.

state is one of: * "converged" -- scaffold commit atop the current split; nothing to do. * "scaffold_stale" -- a scaffold layer atop the CURRENT split, but the tip carries something the current scaffold would not leave there: a publish workflow (see :func:is_publish_workflow). Re-scaffolding sweeps it. * "behind" -- a scaffold layer exists atop an OLDER split; a new split is available. * "scaffold_missing" -- the tip is a bare split-ancestry commit (no scaffold layer). May also be behind (older split). * "contract_violated" -- a foreign commit exists on the mirror. * "ancestry_undetermined" -- the walk never reached a split-ancestry commit AND at least one ancestry question was unanswerable, so whether the mirror is foreign was never established. * "virgin" -- the remote is missing or empty.

#split_push_needed

python
def split_push_needed(self) -> bool

Whether converging requires pushing a fresh bare split to main.

scaffold_stale needs one even though the ancestry is already the current split: the layer to be swept IS the tip, so it is discarded by re-pushing the bare split and rebuilding the layer on top -- which is also what keeps the result exactly one commit above the boundary.

#_git

python
def _git(args, cwd=None, timeout=180)

Run a git command, returning the CompletedProcess (never raises).

#_git_ok

python
def _git_ok(args, cwd=None, timeout=180)

Run a git command, returning stdout stripped; raise MirrorError on failure.

#split_ancestry_answer

python
def split_ancestry_answer(commit, split_sha, cwd)

Is commit the current split commit or one of its ancestors?

Returns the :class:Ancestry verdict rather than a bool, because the reconciler needs all three answers, not two:

  • TRUE -- the split boundary; the walk stops here.
  • FALSE -- git checked: this commit is not part of the split ancestry.
  • INDETERMINABLE -- git could not check. This is the ORDINARY answer

for a commit above the boundary: the mirror's scaffold layer exists only on the remote, so the monorepo has no object to walk. It is also what a pruned or never-fetched split commit produces, which is why the walk keeps it and the caller uses it only where the difference is real (see :func:observe).

The walk's fail-closed direction is "not ancestry" for BOTH non-TRUE answers: a commit whose ancestry was never established is never treated as a boundary, so the reconciler refuses rather than force-pushing over something it cannot account for.

#classify_remote

python
def classify_remote(remote, cwd)

Classify the remote via git ls-remote.

Returns a tuple (kind, tip, detail) where kind is one of: * "missing" -- ls-remote failed and stderr does not look like auth. * "auth" -- ls-remote failed with an authentication/authorization error. * "empty" -- ls-remote succeeded but the remote has no refs. * "no_main" -- the remote has refs but no refs/heads/main. * "populated" -- refs/heads/main exists; tip is its SHA.

#classify_result

python
def classify_result(r)

:func:classify_remote's classification of an already-run ls-remote.

Returns (kind, tip, detail, refs_text). The raw output is carried out with the verdict so the tags dimension can read the mirror's TAG refs from the same listing that decided the branch's state -- one call to the remote, two questions answered from it.

#compute_split_sha

python
def compute_split_sha(root, project_path)

Deterministic branchless subtree split of project_path.

Runs git subtree split --prefix <path> WITHOUT -b: it prints the resulting commit SHA to stdout, creates no refs, and materializes the whole synthetic split ancestry as loose objects in the monorepo (so later ancestry checks against older split commits resolve locally).

--prefix and the path are SEPARATE tokens on purpose: that is the spelling the observe allowlist pins (git subtree split --prefix), and the stuck form --prefix=<path> -- which git accepts identically -- would match no prefix, so under --dry-run this run would be recorded instead of observed and the whole preview would truncate on its result.

#_clone_main

python
def _clone_main(remote, dest)

Full single-branch clone of main so the whole tip layer is inspectable.

#_first_parent_chain

python
def _first_parent_chain(clone_dir, tip)

First-parent commit chain from tip (newest first).

#_changed_paths

python
def _changed_paths(clone_dir, base, tip)

Paths changed between base and tip (name-only).

#_commit_paths

python
def _commit_paths(clone_dir, commit)

Paths changed by a single commit (vs its first parent).

#is_publish_workflow

python
def is_publish_workflow(path)

Whether path is a publish workflow under .github/workflows/.

Named, not sniffed: a workflow file whose NAME says publish. That is every spelling rlsbl itself renders (publish.yml, docker-publish.yml) and the spellings a hand-written one uses. Reading a workflow's body to decide whether it publishes would be a heuristic; a name is a fact.

#publish_workflows_in

python
def publish_workflows_in(tree_dir)

The publish workflows present in a checked-out tree, as repo paths.

#_load_owned_predicate

python
def _load_owned_predicate(clone_dir)

Build the is scaffold-owned? predicate for this mirror.

Reads the clone's .rlsbl/managed-files.json (if present) and unions its keys with the pinned prefixes/files.

#observe

python
def observe(remote, root, project_path)

Observe the mirror and return a :class:MirrorPlan.

Mutation-free apart from the loose objects the branchless split leaves in the monorepo object store.

#MirrorTagPlan

One released version's presence on the mirror.

state is one of: * "materialize" -- the mirror has no such tag; the split of the version's recorded release commit is what an apply would push it at. * "present" -- the mirror already carries the tag. * "underivable" -- no mirror commit for this version can be derived. Two ways that happens, and reason says which: the version's archive records no commit at all, or it records one the subtree split cannot answer for (a commit predating the member's directory -- an absorbed-era release -- or one the monorepo no longer has). Reported, never guessed, and never fatal to the rest of the reconciliation. * "never_released" -- the archive records never_released = true: the version NUMBER exists and no release ever used it. Not a failure to derive anything, so it is its own state rather than an underivable one: there is no commit to restore, nothing shipped under this number, and there is nothing for the mirror to carry.

#observe_tags

python
def observe_tags(remote, root, project_path, *, releases_dir, changes_dir, tag_of, remote_refs_text=None)

The mirror's tag state for every version the release record records.

tag_of maps a version to the tag the mirror carries it under (the target's standalone form -- see :func:rlsbl.mirror_publication.mirror_tag).

The subtree split is computed ONLY for a version the mirror is missing: that is the one case where the answer is needed (it is the commit the apply would push at), and splitting once per released version would walk the history once per version for a question already answered by the tag being there.

#tag_verdict_item

python
def tag_verdict_item(plan)

One released version's :class:VerdictItem in the mirror's preview.

#_undetermined_detail

python
def _undetermined_detail(plan, project_path)

Remediation for a walk git could not finish. Never an accusation.

#verdict_item

python
def verdict_item(plan, remote, project_path, project_name)

The mirror's :class:VerdictItem -- one subject, one whole repository.

The shared renderer prints the headline, then the facts, then the actions, then the free-form detail block; the strings below are what it composes.

#_push_bare_split

python
def _push_bare_split(remote, split_sha, expected_tip, root)

Push the bare split commit to main.

Uses force-with-lease against expected_tip when the branch already exists; a plain push when creating the branch on a virgin remote.

#_rewrite_identity

python
def _rewrite_identity(clone_dir, remote, sub_config_path)

Move the clone's identity manifests onto the MIRROR's own identity.

A manifest that names the repository a package lives in is wrong the moment it arrives on a different repository: a mirrored Go package whose go.mod still says host/owner/mono/packages/lib cannot be fetched from the mirror at all. Which manifests those are, and how to rewrite them, is each target's own answer (mirror_identity_files / rewrite_mirror_identity) -- there is no target name here.

A target that cannot derive the mirror's identity raises, and the raise stands: leaving a manifest naming the monorepo would publish a mirror nobody can resolve.

#_run_scaffold

python
def _run_scaffold(clone_dir, sub_config_path, remote)

Copy the project's .rlsbl/config.json into the clone and scaffold.

Runs rlsbl scaffold --no-auto-commit so the reconciler owns the commit. A non-zero scaffold exit is a HARD ERROR (no warn-and-continue).

The copied config declares publish_mode: "none", whatever the monorepo member declares, and that is not a downgrade of the member's own setting -- it is a statement about the MIRROR. A mirror's tags and GitHub Releases are written by the monorepo's release flow through :mod:rlsbl.mirror_publication; a publish workflow on the mirror would be a second, unsynchronized publisher of the same versions, triggered by pushes the reconciler itself makes. Scaffold's own rule for publish_mode: "none" then does the rest: no publish.yml is rendered, and an already-scaffolded one is removed by the orphan sweep.

#_sweep_publish_workflows

python
def _sweep_publish_workflows(clone_dir)

Delete every publish workflow from the mirror clone, whatever its origin.

Scaffold's own orphan sweep removes only what the CURRENT manifest tracks, so it never sees a leftover from an older scaffold layer nor a workflow that rode in through the subtree split from the member's own directory. This one covers the whole .github/workflows/ prefix -- already scaffold territory on a mirror by the tripwire's rules -- because the invariant it serves has nothing to do with who wrote the file: a mirror never releases itself.

Only the MIRROR's copy is swept. A member that genuinely carries a publish workflow in its own subtree keeps it in the monorepo, where it is the member's CI; the deletion happens in the throwaway clone and lands in the scaffold commit.

#_converge

python
def _converge(plan, remote, root, project_path, sub_config_path)

Bring the mirror to the desired state. Idempotent; interrupted runs heal.

#converge_branch

python
def converge_branch(remote, root, project_path, sub_config_path)

Observe one mirror's branch and converge it. The reusable entry point.

Same observation and same convergence the command performs, without the preview: the release flow's mirror step calls this so a release and a rlsbl monorepo mirror bring the branch to exactly the same state by exactly the same code -- including the force-with-lease, the scaffold layer, and the two refusals below.

Returns the observed :class:MirrorPlan. Raises :class:MirrorError when the mirror carries foreign commits or its ancestry could not be established: both touch nothing, and neither is something a release may decide to overwrite.

#_member_target

python
def _member_target(root, project, releasable)

The target whose standalone tag format the mirror's tags use.

The FIRST detected target, which is the same one the release flow's own tag derivation uses for a monorepo member. A member with no detectable target has no tag scheme, and the tags dimension answers nothing for it rather than inventing v{version}.

#_observe_tags

python
def _observe_tags(plan, root, project, releasable, remote)

The tag plans for this mirror, or none when the release record cannot be read.

#_apply_tag

python
def _apply_tag(plan, remote, root, project_path, *, notes_dir)

Materialize one released version's tag and Release on the mirror.

notes_dir is where the Release body's temporary notes file is written -- the releasable's own release state directory, never the directory the command happened to be invoked from, where a stray .rlsbl-notes-*.tmp would show up in somebody's git status.

#_cmd_mirror

python
def _cmd_mirror(flags, project_root)

Observe-then-converge reconciler for a project's subtree mirror.

flags["project"] -- workspace project name. flags["dry-run"] -- plan only (no writes).

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • selfdoc Static Site Generator that builds a project's documentation site directly from its source code, so the docs can never drift from the code they describe, with SEO/AEO, first-class blog, search, and cross-project linking built in
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
  • wesktop A Python framework that turns an ASGI web app into a desktop application, serving it from a local Granian server and displaying it in a native OS window via pywebview
Search