docs: the orchestrator runbook and the module map #126

Merged
admin_emi merged 2 commits from docs/trunk-flow-runbook into dev 2026-07-26 22:24:03 +00:00
Owner

Adds the two agent-facing documents the trunk-based flow assumes exist. Same
pair lands in centralis (emi/centralis#22), which also carries the forge_*
tools this runbook calls.

.claude/BRANCHING.md

How the flow is actually run: feat/*devmainrelease, one PR per
hop, merges serialised — Forgejo has no native merge queue, so whoever
orchestrates is the queue. Covers the per-PR loop (forge_prs(base="dev")
forge_pr_updateforge_pr_awaitforge_pr_merge), both promotions and
who decides each, and the hotfix down-merge.

Two things it states because getting them wrong is expensive here:

  • CI does not gate PRs into release. pr-build.yml fires only for dev
    and main, so a required status check on release would make every
    production promotion unmergeable with a 405 that names no cause. The runbook
    says so and gives the ordering to close it properly — change the workflow
    first, turn the requirement on second.
  • The chain cannot fast-forward. Every promotion leaves a merge commit on
    the target the source never receives, so the branches are mutually divergent
    by construction (devmain 2 ahead/13 behind, mainrelease 33 ahead/17
    behind as of today). Promotions are merge commits until someone deliberately
    reconciles the branches; the runbook says not to "fix" it with a rebase or a
    force-push.

It also carries the FE/BE consequence: deploy.yml rolls only the domains a
push touched, so a hotfix on one side leaves the other running something older —
check /api/version before calling it live end to end.

.claude/ownership.md

Which tasks may run concurrently, seamed along the four domains — which is a
real seam, since deploy.yml already checks per-leg whether a push touched that
domain. Plus the shared spine that must be serialised: .forgejo/workflows/**
(CI lives only in the root, so every domain routes through the same files),
env-topology.sh, the deploy entry points, the CLAUDE.md files.

Names the recurring collisions rather than leaving them to be rediscovered: a
schema change spans backend/alembic and whatever reads the column, and if the
payload shape moves it is PAYLOAD_VER and the frontend too — one task, not two
concurrent ones. infra/deploy/secrets/ and infra/deploy/ are one owner
between them.

Scope

Documentation only — no code, no workflow, no infra change. Nothing here alters
what deploys or how.

Test evidence

Nothing executable to run. Verified instead that every file the two documents
reference exists on this branch — infra/deploy/env-topology.sh,
.forgejo/workflows/pr-build.yml, .claude/ownership.md — since the root
CLAUDE.md's standing rule is that these files may only name things that are
real. The divergence figures quoted were measured with branch_diff against the
live repo on 2026-07-26, not estimated.

Files touched

.claude/BRANCHING.md (new), .claude/ownership.md (new), CLAUDE.md (a
four-line pointer to both).

Adds the two agent-facing documents the trunk-based flow assumes exist. Same pair lands in `centralis` (emi/centralis#22), which also carries the `forge_*` tools this runbook calls. ## `.claude/BRANCHING.md` How the flow is actually run: `feat/*` → `dev` → `main` → `release`, one PR per hop, merges serialised — Forgejo has no native merge queue, so whoever orchestrates *is* the queue. Covers the per-PR loop (`forge_prs(base="dev")` → `forge_pr_update` → `forge_pr_await` → `forge_pr_merge`), both promotions and who decides each, and the hotfix down-merge. Two things it states because getting them wrong is expensive here: - **CI does not gate PRs into `release`.** `pr-build.yml` fires only for `dev` and `main`, so a required status check on `release` would make every production promotion unmergeable with a 405 that names no cause. The runbook says so and gives the ordering to close it properly — change the workflow first, turn the requirement on second. - **The chain cannot fast-forward.** Every promotion leaves a merge commit on the target the source never receives, so the branches are mutually divergent by construction (`dev`→`main` 2 ahead/13 behind, `main`→`release` 33 ahead/17 behind as of today). Promotions are merge commits until someone deliberately reconciles the branches; the runbook says not to "fix" it with a rebase or a force-push. It also carries the FE/BE consequence: `deploy.yml` rolls only the domains a push touched, so a hotfix on one side leaves the other running something older — check `/api/version` before calling it live end to end. ## `.claude/ownership.md` Which tasks may run concurrently, seamed along the four domains — which is a real seam, since `deploy.yml` already checks per-leg whether a push touched that domain. Plus the shared spine that must be serialised: `.forgejo/workflows/**` (CI lives only in the root, so every domain routes through the same files), `env-topology.sh`, the deploy entry points, the `CLAUDE.md` files. Names the recurring collisions rather than leaving them to be rediscovered: a schema change spans `backend/alembic` and whatever reads the column, and if the payload shape moves it is `PAYLOAD_VER` and the frontend too — one task, not two concurrent ones. `infra/deploy/secrets/` and `infra/deploy/` are one owner between them. ## Scope Documentation only — no code, no workflow, no infra change. Nothing here alters what deploys or how. ## Test evidence Nothing executable to run. Verified instead that every file the two documents reference exists on this branch — `infra/deploy/env-topology.sh`, `.forgejo/workflows/pr-build.yml`, `.claude/ownership.md` — since the root CLAUDE.md's standing rule is that these files may only name things that are real. The divergence figures quoted were measured with `branch_diff` against the live repo on 2026-07-26, not estimated. ## Files touched `.claude/BRANCHING.md` (new), `.claude/ownership.md` (new), `CLAUDE.md` (a four-line pointer to both).
admin_emi added 1 commit 2026-07-26 19:54:03 +00:00
docs: the orchestrator runbook and the module map
All checks were successful
PR build (required check) / changes (pull_request) Successful in 6s
secrets-guard / encrypted (pull_request) Successful in 5s
PR build (required check) / build-backend (pull_request) Has been skipped
shell-lint / shellcheck (pull_request) Successful in 8s
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 1s
890cb4a764
.claude/BRANCHING.md — how the trunk-based flow is actually run: the serialised
merge queue (Forgejo has no native one, so whoever orchestrates is it), the two
promotions and who decides each, and the hotfix down-merge that has to happen in
the same session or it becomes a regression scheduled for the next promotion.

Two things it states because getting them wrong is expensive here. CI does not
gate PRs into `release` — pr-build.yml fires only for dev and main — so a
required check on that branch would make every production promotion unmergeable
with a 405 naming no cause; closing that gap means changing the workflow first
and turning the requirement on second. And the chain cannot fast-forward: every
promotion leaves a merge commit on the target the source never receives, so
promotions are merge commits until someone deliberately reconciles the branches.

.claude/ownership.md — which tasks may run concurrently, seamed along the four
domains, plus the shared spine that has to be serialised: the workflows (CI
lives only in the root .forgejo/), env-topology.sh, the deploy entry points and
the CLAUDE.md files. Names the recurring collisions too — a schema change spans
alembic and whatever reads the column, and if the payload shape moves it is
PAYLOAD_VER and the frontend as well, which is one task and not two.
admin_emi added 1 commit 2026-07-26 22:05:31 +00:00
BRANCHING: the escape hatch, now that apply_to_admins binds the owner too
All checks were successful
secrets-guard / encrypted (pull_request) Successful in 5s
shell-lint / shellcheck (pull_request) Successful in 8s
PR build (required check) / changes (pull_request) Successful in 13s
PR build (required check) / build-backend (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Has been skipped
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / gate (pull_request) Successful in 1s
secrets-guard / encrypted (push) Successful in 5s
shell-lint / shellcheck (push) Successful in 7s
1d4defefb9
Protection an admin walks through is documentation rather than a control, so
apply_to_admins goes on — but that removes the direct-push route for everyone,
including in an emergency, and the way back in should be written down before it
is needed rather than improvised.

There is no force flag; the supported route is lift the rule, act, restore it,
with both halves audited. Names the failure mode that actually justifies it: a
renamed status context makes the required check unsatisfiable, and with
apply_to_admins on that blocks every merge into dev and main with no exemption
for anyone.
admin_emi merged commit 1d4defefb9 into dev 2026-07-26 22:24:03 +00:00
admin_emi deleted branch docs/trunk-flow-runbook 2026-07-26 22:24:04 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Jinemi/thermograph#126
No description provided.