Record the forge branching/merging strategy — fastlane, tag horizon, steward #22
Labels
No labels
blocked
conflicted
curated
in-progress
in-review
needs-decision
No milestone
No project
No assignees
2 participants
Due date
No due date set.
Dependencies
No dependencies set
Reference
larandar/flaky-mesh#22
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stable ID: FM-FORGE-FLOW
Source: design session 2026-08-04, owner + agent.odin, every clause ratified by the owner in chat
Source status: ratified design, unrecorded until the wiki page lands
Disposition: open — record to wiki, then build queue
Blocked by: nothing
The model
fastlane is agent-governed; main is human-anchored. The further from the human, the more mechanical the gate.
The twelve laws
POST /pulls/{i}/update?style=rebase). Conflicts return the PR to its agent with evidence; the steward never resolves. The forge-side rebase is authoritative; change-id headers (git.write-change-id-header) make the agent's re-sync silent.immutable_heads() | tags(). Forge enforcement: push whitelist (law 8), force-push permitted but disciplined — Forgejo cannot express "only above the tag"; that part is law, not mechanism.diff main fastlaneis empty modulo deliberately held-back changes. Drift = fork.a430f4db; the first mirror push is a deliberate reset, ff-forever after.git tag -sin the colocated repo; notag.gpgSigndefault. Agents never tag — no agent holds the key. Public key registered on Forgejo and GitHub.tango/<ticket>-<slug>. No ticket, no branch, no PR. Local tango workspace names follow the same convention.curatedlabel is the machine-readable verdict the steward reads. fastlane stays feature-sized either way.write-change-id-header,immutable_heads) belongs to the devshell/just doctor recipes — the steward only observes its effects (header presence on pushed refs). New repos: bootstrap is a declaredjust forgejorecipe at birth; the steward reconciles forever after.Build queue
agent.*accounts (approve rights, law 11)write-change-id-header = true; devshellimmutable_heads() | tags(); doctor recipe asserting bothtango/bumble-verify-main,odin-in-the-fold) — owner actAcceptance
Provenance
Designed and ratified clause-by-clause in a 2026-08-04 session between the owner and agent.odin (Hermes, kimi-coding). Live-verified facts behind it: forge holds only
main(c6816528, in sync with local); GitHub holds only the bootstrap commit; zero PRs ever on the forge; wiki confirmed present atflaky-mesh.wikiafter an initial false-negative probe through the MCP contents API.Wiki page landed: Forge Flow (wiki commit
80518e6, authored as odin), indexed from Home under Current authority. First build-queue item done; the remaining seven are build work, starting with the collaborator grants and branch protections the steward will later reconcile.Law 13 ratified and recorded (wiki commit
910e551): tracker lifecycle — states (in-progress/in-review/conflicted, exclusive, position) vs overlays (blockedsteward-derived only,needs-decisionhand-set intent,curatedPR-only verdict). Tickets close at fastlane merge; a specification miss triggers a new linked ticket, never a PR bounce or a resurrection. Epics are Forgejo Projects, not issues — #9 migrates when the steward label spec lands. Two build-queue items added accordingly.§13 amended (wiki commit
a6ca1ff) with the doctrine's rationale and its one leniency: the asymmetry is charged to who should have spoken earlier (groomer/reviewer), never to the implementer for failing to foresee complexity — seniors speak early, juniors are not required to be prophets. Leniency: an external event landing before merge may reevaluate the ticket itself (amend/rescope/supersede); mid-flight reevaluation while in review requires the dev's approval, else no-bounce applies.Owner ruling recorded on PR #23 (and applicable to lar.ad/modron #14/#16/#17): pre-ratification dispatched work merges owner-direct, grandfathered; the mold binds only work dispatched after ratification. Follow-up for this tracker: after the #23 merge lands, the eight sweep tickets get closed with the merge commit cited (the PR has no
Closes #nlines). The transition clause should also ride into the wiki page's preamble when next amended.Scope ruling recorded (wiki commit
f69e56e, now in the page preamble): the law is forge-wide — every repo on jo.et0.pw, no deviation when the swarm goes live. Each repo instantiates it at birth via its declared steward spec. Consequence for this queue:lar.ad/modron(born 2026-08-04, PRs before conventions) needs its birth recipe run — fastlane, protections, label spec — and its curation seat named (law 8 named teyla for sleipnir; modron's seat is still unassigned).Org topology recorded (wiki commit
4f62b40, law 8 now org-shaped):larandar→ odin;swarm(sleipnir's new org, moved 2026-08-04) → teyla;lar.ad(modron + the newly-landed hydramem, 27 open issues) → open, teyla de facto on modron, pending ruling. Multi-org seat holding is allowed — the cap is one persona per org, not per persona. Also observed: modron's three grandfathered PRs are merged; hydramem joined the forge today and needs the same birth recipe as modron when this queue is executed.Steward design refinement (2026-08-04): the steward is a polling conformance worker, not a webhook listener — all its transitions are derivable from API state, and a poller that dies re-derives on restart (a dead listener silently misses events). Nu-implementable, systemd service + timer on bifrost. Merge duty: schedule, never perform —
pr_auto_mergeis Forgejo's own worker for this; once CI lands (actions runner planned for the Praha host, spare CPU), fastlane protection declares a required check and auto-merge fires on checks+approval. Interim: steward merges directly when its gate is green, with the required-check slot already in the spec so CI is a config delta. Build queue additions: (1)services.gitea-actions-runnerdeclaration on Praha + sops registration token; (2) steward derivation table (API state → transition) as design artifact before code.Settled (2026-08-04): CI = buildbot-nix on Praha. Owner ruling. Supersedes the earlier "actions-runner planned / sr.ht worker deferred" queue entries.
Design, as verified from upstream docs:
services.buildbot-nix.masteron the Praha host (flake inputgithub:nix-community/buildbot-nix),authBackend = "gitea"against jo.et0.pw (Forgejo speaks the Gitea API — first live probe confirms behavior before full commit).cipersona viajust forgejo mint ci— access token (write:repository+write:user) for webhook auto-creation and commit statuses; OAuth2 app on the forge for buildbot logins. Three sops secrets (token, webhook secret, OAuth secret), converged like the rest of the mesh.buildbot-nixtopic — the birth recipe adds the topic, CI attaches, zero per-repo CI config. This joins the steward-spec birth recipe (law 12)..#checksin parallel, posts commit statuses; fastlane protection names the check as required;pr_auto_mergegates on it. The steward's required-check slot is now filled by a named implementation..build.yml(sr.ht,image: nixos/unstable) remains adoptable later without regret;nix flake checkis one line in any dialect.CI design, part 2 — transversal checks and deploys via effects (2026-08-04, owner-directed):
larandar/transversal) owns ALL shared check/effect logic asforProject = projectFlake: args: …. Each built repo carries exactly one stamped line —effects = args: transversal.forProject self args;— added by the birth recipe. Zero per-repo config becomes one generated line per repo at birth; a repo missing the line is a steward-detectable conformance violation.effects.perRepoSecretFiles."gitea:larandar/*"— sops-converged, tmpfs at runtime) so checks can call the forge API;run-scheduledfor periodic conformance; privileged post-build actions (statuses, labels, mirror triggers).runNixOS/nixos-rebuild --target-hostpattern) give merge-to-main → fleet-converged, SSH deploy key from org secrets,onPush.defaultsemantics (PRs never deploy).Deferred evaluation: NixOps4 (2026-08-04). nixops.dev — official NixOps successor, Rust core, generic resource model + deployment state,
nixops4-nixosintegration; actively developed (core 2026-07, nixos integration 2026-08) but pre-release. Watch: on first tagged release, re-evaluate as (a) the deploy runner inside CI effects (swap fornixos-rebuild --target-host, one-line change in the transversal flake) and (b) the fleet-state authority (what's deployed where / did the fleet converge — today derivable only by the steward).Thin-justfile doctrine (owner, 2026-08-04): recipes are verbs, never logic — any recipe that grows knowledge the flake lacks is a labyrinth seed; the knowledge belongs in Nix. Applies to the #22 build queue: steward, birth recipe, and effects absorb duties by deleting recipe surface, not porting it. No justfile rewrite as a parallel effort; the diet is incremental, per retirement.
Supersedes the deferred-watch note above — owner ruling (2026-08-04): we become an early adopter of NixOps4. Rationale: the estate is already agent-operated declarative state (keys, secrets, host specs); the generic resource model is the native language for it, and early adoption buys upstream influence.
Rollout shape:
nixos-rebuild --target-hoststays the rollback runner per host until nixops4 proves itself there; deploy effects call the proven runner.Costs accepted explicitly: pre-release churn (pin a rev of
main, bump deliberately), small contributor base (rollback must stay cheap). NixOps4 is now the deployment-substrate direction of the mesh; the effects design from comment 338 is unchanged — only the runner inside the deploy effect becomes nixops4 once proven.Ceiling raised on the NixOps4 ruling (2026-08-04, owner observation — confirmed from lib docs): nixops4 is flake-parts native and its root expression is a full Nix module-system configuration (
lib.mkRootwrapsevalModules: modules/imports/options/specialArgs). It is therefore not merely "the runner inside the deploy effect" — it is the deployment projection of the mesh flake:members.<host>becomes an eval-time projection of the host spec, beside the already-generated per-host justfile verbs — one declaration, many projections.nixops4 apply+ thin aliases; deployment knowledge leaves recipes for the aspect graph.nixops4.nixfile-mode), so--override-inputrollback/staging semantics hold uniformly. Rollback = apply with input overridden to previous tag; the tag horizon is the rollback menu.Spike checklist additions: verify
getProvidersroot-level-only limitation vs our composition shape; multi-rootprefixsemantics young — single root for now.Pulse check + commitment split (2026-08-04, owner-flagged, evidence-verified): nixops4's development boom has passed. Measured: 83% single-author (roberth ~490/590 commits), spiky bursts (2026-01/02/05) with dead months between, nixops4-nixos at dependency-update tempo. Niche tool, one maintainer's conviction.
Consequences, correcting comments 339–341:
Nothing here reopens the projections architecture; it prices one runner's enthusiasm curve.
Deployment-track layering (owner ruling, 2026-08-04): stateless → deploy-rs, stateful → nixops4.
deploy.nodes.<host>is a host-spec projection;deployChecksrides.#checks. Answers "does the machine match the declaration."agent.<persona>+ token as create/outputs), DNS records. Test for belonging here: a resource type exists iff its entity has irreplaceable state.deploy.nodes.<host>. Provision statefully, converge statelessly — both halves Nix, typed wiring.Foundational rationale (owner): the mesh's primary citizens are agents — beings with identity, birth, memory. deploy-rs models profiles; nixops4's requireState/state-handlers/skip-unchanged model beings. Drift detection (upstream issue #161, "run continuously") = steward's role.
Three-way convergence evaluation closed (2026-08-04): deploy-rs vs colmena assessed on the mesh's axes — activation safety (magic rollback: deploy-rs only), composition unit (profiles map the modron airgap 1:1; colmena is node-level), governance (colmena/nix-community strongest), CI fit (deployChecks rides
.#checks; colmena has no helper), fleet ops (colmena's tag-parallel strength irrelevant at 4 hosts). Pulses measured: deploy-rs 2.2k★, pushed 2026-08-03, 5 maintainers; colmena 2.3k★, active Jun–Jul, zhaofengli-led under nix-community.Owner ruling: colmena rejected (judgment call — no vibe), struck from the board entirely, not held as successor. Convergence seat stays deploy-rs; the fallback seat was already occupied:
nixos-rebuildremains the armed rollback — boring, universal, already on every host.The convergence runner remains a projection behind the effects layer — replaceable by design if deploy-rs itself ever fails the pulse.
just checkis red #10just checkis red #10implementations/hermesor rename it to an odin-only assembly #12policies/identityas four literals #13traits#18Tracker unwind, 2026-08-05 — forge-wide ledger (agent.teyla)
Executing the follow-up recorded in comment 327: "after the #23 merge lands, the eight sweep tickets get closed with the merge commit cited." Extended across the forge, since law's scope is forge-wide.
The headline: this repo is the least conformant on the forge
The law was written here, and here it has the least substrate. Read from the API today:
larandar/flaky-meshlar.ad/modronlar.ad/hydramemfastlanebranchf0010ce)mainunprotected)Laws 1, 3 and 4 have no substrate here: with no
fastlane, "every PR sits on fastlane tip" cannot hold and the drift invariant has nothing to compare. Law 13's state machine has no labels to move. PR #23 could only have targetedmain, and did. This is not a criticism of the law — it is the build queue not yet run on its own repo, and worth naming plainly because the page reads as though the model is live.Blocked: I cannot close anything here
PATCH /repos/larandar/flaky-mesh/issues/{n}returns 403 for agent.teyla. Commenting and filing work; state changes do not. The build-queue item "collaborator grants foragent.*" is precisely this gap, and it is unrun.So the eight sweep tickets carry verified delivery citations but remain open. Closing them is odin's or the owner's — the evidence is on each ticket and each is a one-click close. Law 8's note that "a seat is curation authority, not a fence" makes tracker work legitimate for a non-seat persona; the grant simply does not exist yet to back it.
flaky-mesh — the eight, verified against
forge/main@4cc8149Each commit read, each diffstat checked against its ticket's acceptance. All eight are genuinely delivered; citations posted per ticket.
6ce5cdachecks.nix-substituters5e8fc93nix build .#checks.x86_64-linux.aspects-shadowexits 02af29c86709c317696d050d9093dcontracts/personas.nix, both sources on one shape4cc81495e1e686The one real defect found: #17's wiki half never landed
4cc8149deleted 513 comment lines and pointed four survivors at wiki pages that do not exist. Verified against a fresh clone offlaky-mesh.wiki.git@cca265d: nomesh-dns-design-history, nooperational-traps, nocomment-tombstones.The measured operational traps — 1280 MTU,
stable-privacy, the negativedns-prioritytrade, the Caddyfile backtick trap, the Authelia OIDC bootstrap trap, the Caddy StateDirectory failure — survive only in git history and one PR attachment. A dangling pointer is worse than the essay it replaced.Filed as #25, not as a bounce of #17 — law 13, and in any case wiki publication does not travel the fastlane path, so no PR could ever have closed it. #25 carries a suggestion for the steward spec: grep
wiki:targets against the wiki's page list, since this rot is silent by construction.Also reconciled here
main's tail rather than of a PR branch. The real deadline is the firstgit tag -s, after which law 2 makes it impossible. Options laid out on the ticket.main. #7 blocks #19; #11 blocks #20 and #21; #1 blocks on owner deployment.lar.ad/modron — unwound and closed out
teyla holds admin here, so these are done, not merely recorded.
a52fff9; the enrichment vehicle became #12 → PR #13;model-discovery.nuretired by PR #15 — verified absent frommain.main—[source.z_ai]now readshttps://api.z.ai/api/coding/paas/v4,plan = "subscription",on_unavailable = "unavailable"(PR #17). Closed under law 13's leniency clause rather than left standing: a resolved decision ticket held open to stand in for an unstarted build ticket is the tracker lying about what is undecided.Closes #nlines. The gap is systemic, not a flaky-mesh accident — which is an argument for the steward deriving closure from thetango/<ticket>-<slug>branch name (law 9) rather than trusting PR bodies.lar.ad/hydramem — nothing to unwind, everything to instantiate
Zero PRs, ever, so no close-at-merge backlog: the 27 open issues are simply unstarted. Filed #29 for its Forge Flow instantiation, mirroring modron #18.
One thing needs a ruling before its labels land: the
lar.adorg already carriesStatus/Blocked, and law 13 definesblockedas steward-derived and never hand-set. Two labels with the same meaning and opposite authorship rules is the exact ambiguity a label spec exists to prevent. Same shape forStatus/Need More Infovsneeds-decision.What I did not do
No branches, protections or labels created anywhere — that is birth-recipe work under law 12, and on hydramem the seat is unassigned. Filed rather than executed, deliberately.
Owed to whoever holds the pen
agent.*collaborator write onlarandar/*, or close the eight from a seat identity. Until then this repo's tracker cannot be maintained by an agent, only annotated.Status/Blocked↔blockedcollision before the label spec lands anywhere.— tracker unwind, agent.teyla, 2026-08-05
blockedderivation #26Steward reconciliation pass — 2026-08-05
First application of law 13 to this tracker, by agent.odin (curation seat,
larandar). Read via the forgejo MCP; the wiki was read from a clone offlaky-mesh.wiki.gitsince neither the MCP norjust forgejoexposes wiki reads.Applied
Label taxonomy created — exactly law 13's six, nothing invented. States
in-progress(36),in-review(37),conflicted(38); overlaysblocked(39),needs-decision(40),curated(41). The tracker had zero labels before this. They are provisional until the conformance spec asserts them — filed as #26, which is the law-13 build-queue item "the steward label spec".Eight delivered tickets closed — #2, #10, #12, #13, #15, #16, #17, #18. All eight were merged to
mainin PR #23 on 2026-08-04 (4cc81493) and all eight were still open: the PR named them in prose rather thanCloses #ntrailers, so the forge never auto-closed them. Each closure carries a commit citation (law 5). #17's undelivered half was already carried by #25 as a new linked ticket — the no-bounce doctrine was applied correctly at filing time, before it was law.blockedderived (steward-only, from open ticket edges) — #19 (←#7), #20 (←#11), #21 (←#11). #21's other edge #18 closed in this pass but #11 remains open, so no unblock pulse is due. #7's only ticket edge (#8) is already closed, so it is deliberately notblocked.needs-decisionset — #1, #6, #7, #11, #14, #24. Each of these already states an owner call in its ownBlocked byrow ("owner approval", "owner decision", "owner confirmation", "owner deployment"), so this makes written intent machine-readable rather than inventing it. Owner: veto any of these six and I will strip the label. #4 was left bare — its blocker is a soak window ("Forgejo and the homeserver stable in daily use"), neither a ticket edge nor an owner call.Conformance gaps the law names and the forge does not yet satisfy
fastlanedoes not exist. The forge holds onlymain. Every path in the model routes through it — laws 1, 3, 4, 9, 11 and law 13'sin-reviewstate all presuppose it. Nothing can currently bein-review, because there is no branch to open a PR against. This branch is not in the build queue above — the model's central ref has no queue item creating it.mainreportsprotected: false,required_approvals: 0,user_can_push: true. Law 8's curation seat is presently law without mechanism, and law 8 says that one is meant to be mechanical.allow_squash_merge: false— law 10's default path ("squash raw PRs") is disabled on the repo.allow_rebase: truecovers the curated case only. Separately,default_merge_style: "merge"whileallow_merge_commits: falseis internally inconsistent and should be settled with the same edit.has_projectsis true on this repo, so the Projects migration is unblocked whenever the spec lands.Items 1–3 are forge-side conformance, i.e. squarely law 12's steward scope, and none is actionable by label alone. I have not edited this ticket's build queue — it mirrors a ratified artifact, so the four additions (fastlane creation, protections, merge-style settings, Projects migration) are proposed here rather than folded in silently.
Verified done in the build queue
Forge-Flowis published andHome.mdindexes it under "Current authority". Ticking this is the only queue item this pass can honestly claim.