docs(plans): refactor-to-next merge plan and lead decision 66 (sage)

Jason's 2026-10-08 rulings via Mos (thread 1eba59e5). R10: next stays
the trunk; the plan pins refactor b8db39cf and next 2101c9b4, finds a
clean merge-tree, and names the CI gate, approval identity, frozen
next-lane publishing, root .mosaic/repo.json, 13 stale v1 PRs and the
hardcoded ledger branch as the work. Nothing merged.

R8: Path A on the new estate Vikunja meets slice 1 and replaces
decision 61's Path B. The runbook's Path A text names the estate
instance and the share-only isolation rule.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-08 16:53:57 -05:00
co-authored by Claude Opus 5.5
parent b8db39cf1e
commit ba51c8d867
4 changed files with 212 additions and 0 deletions
+37
View File
@@ -1140,3 +1140,40 @@ which stay with him. Each item names who decided it and what happened.
the policy can express. Role authority has no per-target entries,
so the broker classifies `message.send` by the sender's role
alone. S2c does that, and that's the rule.
66. **Jason's 2026-10-08 rulings for the stack: `next` stays the trunk,
Mosaic Stack uses the estate Vikunja, and non-gated defaults apply
at their deadline (2026-10-08).** Source: Mos, thread 1eba59e5,
relaying Jason's rulings R1, R5, R8, R10 and R17. Mos's lane state
file holds the full list.
- R10: the trunk stays `next`, and `refactor` merges into it. The
plan is `docs/plans/2026-10-08_refactor-to-next-merge-plan.md`.
Nothing is merged. `next`'s `.mosaic/repo.json` already names
`next` as the integration trunk, so no record contradicts the
ruling. `refactor` has no root `.mosaic/`; the plan adds one.
- R8: one new estate Vikunja 2.7.x instance serves Mosaic Stack,
Launchpad, personal and system projects. SetSpark stays on
tasks.setspark.io. Path A on that instance meets slice 1, so row
35 uses Path A there, and this replaces decision 61's Path B
bullet. Decision 61 chose Path B to keep slice 1 off SetSpark's
instance, and R8 keeps that separation.
- Isolation comes from shares. A bot sees only projects shared
with it, and the runbook shares only `mosaic-stack`. The bot
names, `bot-mosaic-stack-<role>`, already avoid collisions with
a second business on the same instance.
- S3's probes still run on a scratch container, never the estate
instance. Its first probe, which labels `GET /labels` shows a
bot, has to show nothing from an unshared project before the PM
bot runs on the estate instance.
- S3's one live run writes into the `mosaic-stack` project only.
- The bundled path stays in S3 as the REQ-TASK-3 option for other
installs.
- R1 and R5: when a non-gated item's deadline passes, its
recommended default applies and is logged. Gated items wait for
Jason: money, credentials and legal; prod infra and prod data;
anything sent to people outside the fleet. Product and UX
direction isn't gated.
- R17: Jason runs `docs/guides/slice-1-identities.md` on 2026-10-09
at about 10:30 Central. If the estate instance isn't serving by
then, he runs section 1 (Gitea) and leaves sections 2 to 4 for
when it is. Don't start Path B as a stopgap, because that makes
two Vikunjas and mints bot tokens twice.
@@ -0,0 +1,154 @@
# Merge plan: `refactor` into `next`
Jason's ruling R10 (2026-10-08, relayed by Mos in thread 1eba59e5): the
stack trunk stays `next`, and `refactor` merges into it. Sage writes the
plan. Nothing in this file has been executed. No merge has happened.
## Pinned measurement (2026-10-08)
| Ref | SHA |
|---|---|
| `origin/refactor` | `b8db39cf1ec9ffc8958d7966b63f04710e70cb75` |
| `origin/next` | `2101c9b4468b22f57b2f02bb2c9da12067225819` |
| merge base | `5d2770002612a09ae0cadc129b4ea30619133e8a` |
| `origin/main` (not part of this plan) | `7102ccb93e007d98faab3994ea552d03f522ad2c` |
The merge base is the old v1 head. The 2026-09-07 conversion merged it in
as the second parent and moved its tree under `v1/`
(`docs/plans/2026-09-07_repository-consolidation-completed.md`).
- `refactor` is 371 commits ahead of the base. `next` is 1 commit ahead:
`2101c9b4`, fred, 2026-09-11, `fix(git-tools): issue-comment.sh resolves
API base without monolith GITEA_URL (#1502)`. It changes two files under
`packages/mosaic/framework/tools/git/`.
- `git diff -M origin/next origin/refactor`: 5,520 paths. 3,491 are v1
files renamed into `v1/`, 16 are added under `v1/`, 1,997 are added at
the root, 7 root files are renamed and 9 are modified.
- `git merge-tree --write-tree origin/next origin/refactor` exits 0 with no
conflicts. Result tree `095ce6f8949149f664ab6915cf631fb294871a0c`
differs from `refactor`'s tree in exactly the two #1502 files, now at
`v1/packages/mosaic/framework/tools/git/`. Rename detection carries the
fix into the archive where it belongs.
The text merge is trivial. The work is everything around it.
## Conflict areas
1. **The merge gate can't pass as things stand.** `next` is protected: no
direct push, one approval, and the required status
`ci/woodpecker/pr/ci`. Woodpecker reads `.woodpecker/` from the PR's
head tree. `refactor` has no root `.woodpecker/`, so a PR from it never
posts that status. The PR would sit unmergeable unless an admin
overrides the check.
2. **Approval identity.** Every seat writes to Gitea as `jarvis`. Gitea
doesn't count an approval from the PR's author, so if `jarvis` opens
the PR, a seat review can't satisfy the one-approval rule. Jason's
approval can, and later the slice 1 Gitea reviewer bot can.
3. **`next`'s pipelines go quiet.** After the merge `next`'s root has
no `.woodpecker/`. Pushes to `next` stop publishing
`@mosaicstack/mosaic@next` and the next-lane gateway, web and
appservice sha images. Nothing fails. The dist-tag and images freeze
at the last v1 build. Anything that auto-deploys next-lane images
stops updating. That's prod infra, so Jason confirms nothing live
depends on it before the merge.
4. **`.mosaic/repo.json` moves.** On `next` it sits at the root and says
`integration_trunk: next`, `release_branch: main`,
`flow: trunk-release`. `refactor` has it only at `v1/.mosaic/`. Nothing
in it contradicts R10, so there's nothing to correct. But R14's
enforcers read `<repo>/.mosaic/repo.json`, and after the merge `next`
has none at the root. The landing order adds one.
5. **Thirteen open PRs go stale.** Twelve target `next` and one targets
`main`. All are on the v1 tree, the newest from 2026-09-11. After the
merge their paths no longer exist at the root.
| PR | Author | Title (short) |
|---|---|---|
| #1491 | orch-01 | PRD rev1 ratification |
| #1469 | code-be-01 | config minimal-subset |
| #1431 | fred | gateway bootstrap advisory lock |
| #1370 | code-infra-01 | credentials Gitea seat slots |
| #1367 | fred | mint-seat-credential.sh |
| #1315 | fargo | RI-050 release evidence |
| #1291 | fargo | identity-first principal resolution |
| #1281 | Ghost | vetted user store (W-F4) |
| #1268 | Ghost | unattended identity first start |
| #1259 | Ghost | enumeration guard scope |
| #1213 | Ghost | HARNESS-HOMES fleet MVP |
| #1192 | Ghost | fail closed on invalid launch inputs |
| #1054 | Ghost | installer state machine (base `main`) |
6. **Hardcoded `refactor`.** `packages/ledger/src/ledger.mjs:37` reads
`git log refactor`. Prose in `AGENTS.md`, `docs/plans/CONDUCTOR.md`,
`docs/plans/CURRENT.md` and the queue's genesis log names `refactor`
as the working branch. The genesis log is append-only history and
stays as written. The rest changes in the cutover commit.
## Landing order
Each step is a separate act. Steps 1 to 3 happen on `refactor` under my
existing push authority. Steps 4 and 5 are Jason's.
1. **Add PR CI to `refactor`.** A `.woodpecker/ci.yml` triggered on
`pull_request` and `manual`, so its status context is
`ci/woodpecker/pr/ci`. It uses a digest-pinned `node:26` image, runs
`npm ci`, every `node --test packages/*/tests/*.test.mjs` and the
`scripts/test-*.sh` suites that need no Docker or provider login. The
two live-provider assertions in `test-task.sh` skip under an explicit
flag that CI sets and the suite reports as a skip. New queue row,
Darkwing reviews.
2. **Add root `.mosaic/repo.json`.** Same content as `next`'s, with the
notes updated to cite R10. Hold this step until the T235 enforcer
lands and its handling of a repo with this file is checked. An
enforcer that reads `integration_trunk: next` while `refactor` is
still the working branch must not block step 3.
3. **Back-merge `origin/next` into `refactor`.** One merge commit,
proven clean above. Re-run `merge-tree` against the then-current
`origin/next` first, since `next` can still move. Full integration
gate, then push. After this, `refactor` contains all of `next`.
4. **PR `refactor` into `next`, fast-forward only.** `refactor` already
contains `next`, so the fast-forward style applies. `next`'s head
becomes a SHA that passed our gate, with no new commit. Every SHA
cited in run records, review records and queue rounds keeps
resolving. Squash and rebase are ruled out because they would break
those citations. Jason approves and merges (R2).
5. **Dispose of the thirteen v1 PRs.** Recommended default: close each
with a comment pointing to `v1/` and this plan. Closing them changes
nothing outside the fleet, so under R1 the default applies at its
deadline unless Jason rules otherwise.
6. **Cutover commit, first PR on the new trunk.** Point the ledger at
the trunk named in `.mosaic/repo.json`, not a hardcoded branch.
Update `AGENTS.md`, `CONDUCTOR.md` and `CURRENT.md`. Freeze
`refactor`: keep the ref, push nothing more to it.
## How slice 1 rows retarget
- Open rows: 35 (SR, waiting on Jason), 38 (S3), 39 (S4), 40 (S5), 41
(S6), 42 (S7). Also row 13 (ledger queue section, in review).
- Before step 4: rows land on `refactor` exactly as they do today. A row
in review when step 3 starts finishes on `refactor` first, so nothing
straddles the cutover.
- After step 4: each row's candidate lands on a branch `slice1/<row>-<slug>`
cut from `next`, opened as a PR into `next`. The seat review stays on
the row's issue as now. The PR adds CI and Jason's approval and merge.
Briefs, issues and queue rows don't change. Packet base SHAs stay valid
because `next` contains `refactor`'s history.
- S7 needs this anyway. Its coder bot opens pull requests against the
integration trunk, and `.mosaic/repo.json` names `next`. Step 4 has to
land before S7 starts.
- Cost: every row after the cutover needs a Jason merge. That's five
merges for S3 to S7, plus fix rounds. Decision 62 already gates each
S7 coder-bot merge, so S7 adds no new kind of ask.
## What Jason decides
- When to merge (step 4), and the approval and merge themselves.
- Whether anything live consumes next-lane images or the `@next`
dist-tag (conflict 3). Prod infra, gated under R5.
- Push authority for `slice1/*` feature branches as `jarvis`. Today I
may push only to `refactor`.
- If he'd rather not wait for step 1, an admin override of the missing
status check instead. I don't recommend it. It merges 371 commits with
no CI run on the protected branch.
`main` is out of scope. It stays the v1 release branch until a separate
release ruling.