From 80284c0a2e65c8078894dafc81a94a07dbb5f4f2 Mon Sep 17 00:00:00 2001 From: wtclaude Date: Fri, 28 Aug 2026 18:53:51 -0500 Subject: [PATCH] docs(website): add the branching model, per-phase docs, and the site phases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three additions the org lead called for, all in ENGAGEMENT.md. The branching model (new §6.0a). Every phase PR in every repo targets `edge`; `main` is touched exactly once, by the cutover. Two blocking findings checked on 2026-08-28: every existing `edge` is stale (0 ahead of `main`, behind by 16 docs / 9 module-uo / 7 installer / 7 servuo-plugins / 5 website / 3 link) and must be fast-forwarded before the first phase PR, and three repos have no `edge` at all — android-app, runicgateway.com and Integration-kit. Also records that android-app's pr-checks.yml triggers only on PRs into `main`, so Phase 8 lands with no CI and the cutover is its first real build, as happened to all nine M12 phase PRs. Documentation as a phase deliverable (new §6.0b). A phase-by-phase table assigning the specific docs each phase owes, in `docs/` and in every other repo, so nothing is deferred to a cleanup pass. §7.4 becomes the inventory that table draws from rather than a list of things to do at the end. Two new phases. Phase 12 is runicgateway.com, which is not optional polish: scripts/checkFacts.mjs fetches each fact's authority from the source repo's `main`, so `protocol` 4 to 5 and `moduleApi` 1.6.0 to 1.7.0 fail its build on their own. The site also currently documents the opposite of what Phase 1 ships — notifications-and-email.mdx carries a "There is no SMTP option" aside — its capabilities list claims a web notification channel that will not exist until Phase 7, and PLAY_DATA_SAFETY.md and /privacy generate from one inventory that an engagement mailer materially changes. Because checkFacts reads `main`, the site stays green through the whole `edge` period and breaks at the cutover, so Phase 12 must be written before Phase 13 and merged in the same window. Phase 13 is the cutover itself, ordered rather than per-repo-independent: docs, then servuo-plugins and link together (a protocol bump has three declaration sites and a `main` holding a v5 sidecar with a v4 overlay cannot pair), then website, module-uo, Integration-kit, android-app, and runicgateway.com last because every fact it fetches has to be true on `main` first. Adds an eighth open question (fix the Android CI trigger, or accept the cutover as its first build) and a Phase -1 to the sequencing diagram for the edge fast-forward. Co-Authored-By: Claude --- website/ENGAGEMENT.md | 204 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 193 insertions(+), 11 deletions(-) diff --git a/website/ENGAGEMENT.md b/website/ENGAGEMENT.md index bb71204..696d34f 100644 --- a/website/ENGAGEMENT.md +++ b/website/ENGAGEMENT.md @@ -1,9 +1,13 @@ # The Engagement System — findings and plan **Status:** design of record for the next workstream. No code written yet. The five scope decisions below -are settled; the seven questions in §7.1 are open and none of them block Phase 1 or Phase 2. Per CLAUDE.md +are settled; the eight questions in §7.1 are open and none of them block Phase 1 or Phase 2. Per CLAUDE.md § Conventions, no implementation starts without the org lead's approval of the phase it belongs to. +**Branching:** every phase lands on **`edge`** in its repo; `main` is touched once, by the cutover +(Phase 13). §6.0a records the blocking precondition — every existing `edge` is stale and three repos +have none. + **Scope decisions, settled by the org lead (2026-08-28):** 1. **The in-app channel is in scope.** It does not exist today and has to be built, not adapted. @@ -1006,14 +1010,71 @@ Knock-on obligations: ## Part 6 — The phased plan Same shape as the API v2 router-split plan: grouped, reviewable increments, one acceptance check per -phase, and an explicit note on which guardrails apply. **Every phase carries the standing obligations** -— `npm test --prefix server` green, `npm run swagger` regenerated when a route changes, -`npm run routes:manifest -- --check` clean, `npm run check:modules` clean, a matching `docs/` edit, -Conventional Commits, the AI-disclosure trailer, and a branch cut from a freshly-pulled `main`. +phase, and an explicit note on which guardrails apply. + +**Every phase carries the standing obligations** — `npm test --prefix server` green, `npm run swagger` +regenerated when a route changes, `npm run routes:manifest -- --check` clean, `npm run check:modules` +clean, **the documentation edits §6.0b assigns it**, Conventional Commits, the AI-disclosure trailer, +and a branch cut from a freshly-pulled base. **Stage A (1–2) is prerequisite. Stage B (3–6) is the engagement system. Stage C (7–8) is the in-app channel. Stage D (9) is deliverability. Stage E (10–11) is the shard enrichment and runs in parallel -from day one.** +from day one. Stage F (12–13) is the public site and the cutover.** + +### 6.0a The branching model — everything lands on `edge`, then one cutover to `main` + +**Every phase PR in every repo targets `edge`. `main` is touched exactly once, by the cutover +(Phase 13).** This is the model the module system, protocol v3, Teams and the M12 theming workstream +each used, and it is the right one here for a specific reason: this workstream changes a wire protocol, +a module API version and the mail path simultaneously, and those three land in different repos on +different days. `main` must never hold a half-applied set of them. + +**Two operational findings, both checked on 2026-08-28 and both blocking before Phase 1:** + +1. **Every existing `edge` is stale.** `git rev-list --left-right --count origin/main...origin/edge` + says `edge` is **0 ahead** and behind `main` by: `docs` 16, `module-uo` 9, `installer` 7, + `servuo-plugins` 7, `website` 5, `link` 3. They are leftovers from previous cutovers that were never + refreshed after merging. **Fast-forward each `edge` to `main` before the first phase PR** — it is + lossless (0 ahead), and skipping it means the cutover diff carries stale content or conflicts that + have nothing to do with this workstream. +2. **Three repos have no `edge` at all** and need one cut from `main`: `android-app` (its M12 branch + was deleted after that cutover), `runicgateway.com`, and `Integration-kit`. + +**Android CI does not run on `edge`.** `android-app/.gitea/workflows/pr-checks.yml` triggers only on +PRs into `main`, so every Phase 8 PR lands with **zero CI** and the cutover is the first real run. That +was true of all nine M12 phase PRs and it is true again here. Either fix the trigger as Phase 8's first +commit or budget for the cutover being the first honest build — decide deliberately rather than +discovering it. + +**The cutover is per-repo but not independent.** Phase 13 names the order, because a `main` that has the +v5 sidecar and the v4 overlay is a shard that cannot pair. + +### 6.0b Documentation is a phase deliverable, not an appendix + +Every phase below owes specific documentation, and the phase is **not done until it lands in the same +PR** (or, for cross-repo docs, a companion PR in the same review window). CLAUDE.md's rule — "a code +change is not complete until `docs/` reflects it" — is the floor; this table is the assignment. + +| Phase | `docs/` | Other repos | +| --- | --- | --- | +| **1** Remove Gmail OAuth2, SMTP | `website/BACKEND_DESIGN.md` §7 **rewritten** (not amended — it documents Gmail OAuth2 as *the* mechanism); route tables lose `/admin/email/connect/*` | `website/README.md` + `.env.example` wherever they point at Connect Gmail · **`runicgateway.com`**: `notifications-and-email.mdx` (its "There is no SMTP option" aside is now false), `configuration.mdx:62`, `troubleshooting.mdx:101`, `system-architecture.mdx:117` · a release note | +| **2** Trigger registry | `website/MODULE_API.md` §1.1 (**1.7.0** + correct the stale "1.6.0 has only ever been on `edge`" paragraph), §2.3 (`ctx.events`, `ctx.inbox`), §2.4 (`registerEventTriggers`), §7.3's dormant-rule note · `website/ENGAGEMENT.md` §4.3 kept true | `Integration-kit`: `ci/core-ref.json` re-pinned (the equality check goes red **on purpose**) + chapter 2 gains a "registering a trigger" section · **`runicgateway.com`**: `platform.json.moduleApi` → 1.7.0 | +| **3** Channel preferences | `website/BACKEND_DESIGN.md` route table · `android/PLAN.md` §11 | — | +| **4** Engine | `website/ENGAGEMENT.md` (rules/cooldown/outbox as built) · `BACKEND_DESIGN.md` table inventory | — | +| **5a/5b** Templates + editor | `website/ENGAGEMENT.md` §4.6 · a template-authoring section in `BACKEND_DESIGN.md` or its own doc | **`runicgateway.com`**: a new admin docs page for the template editor | +| **6** Email channel + Teams migration | `website/TEAMS.md` §6.3/§6.4 **rewritten** — the Team pipeline it describes no longer exists as its own thing | **`runicgateway.com`**: `administration/teams.mdx` notification section | +| **7** In-app channel (core+web) | `website/BACKEND_DESIGN.md` routes + tables · `website/ENGAGEMENT.md` | **`runicgateway.com`**: `notifications-and-email.mdx` gains the in-app channel | +| **8** In-app (Android) | `android/PLAN.md` | `android-app/README.md` | +| **9** Deliverability | `website/BACKEND_DESIGN.md` §7 · a suppression/bounce operator section | **`runicgateway.com`**: `troubleshooting.mdx` gains bounce/suppression · **`PLAY_DATA_SAFETY.md` + `/privacy`** — see Phase 12 | +| **10** Protocol bump | `link/INTEGRATION.md` §Housing (table + example) · `link/PLAN.md` §5/§7 · a `link/v5.md` if the bump earns its own design doc, as v3 and v4 did | `servuo-plugins/overlay.toml` · **`runicgateway.com`**: `platform.json.protocol` → 5, `bundle.*`, `architecture/protocol-versions.mdx` | +| **11** module-uo triggers | `modules/uo/API.md` · `modules/uo/README.md` | `module-uo/README.md` | +| **12** Public site | — | **`runicgateway.com`**, in full — see the phase | +| **13** Cutover | `README.md` index rows · every doc's status line | `.profile/README.md` if this is a headline capability | + +**One thing this table is protecting against.** `runicgateway.com` appears in eight rows, and it is the +only repo here whose checks are *fetching* these values rather than being told them — see Phase 12. + + --- @@ -1221,29 +1282,132 @@ until the v5 overlay is deployed, which the `required: false` declaration alread `Greatly` on the live rig produces one email to the linked owner and nothing to anyone else; a second transition inside the cooldown produces nothing; a refresh back to `LikeNew` inside the delay window cancels the pending mail. -**Guardrails:** `check:modules` proves core gained no UO identifier across all eleven phases. +**Guardrails:** `check:modules` proves core gained no UO identifier across every phase to this point. + +--- + +### Phase 12 — `runicgateway.com`: the public site and the docs journey + +**This phase is not optional polish, and it is not "update the marketing copy". Two of its checks +will fail the build on their own**, and they read from `main`, which fixes exactly when this has to +land (see the timing note below). + +**The mechanical half — the site's own checks go red at cutover.** `scripts/checkFacts.mjs` fetches +each value's authority from the **`main` branch of the source repo** and fails the build on any +disagreement (`link main:sidecar/src/main.rs`, `servuo-plugins main:overlay.toml`, +`website main:server/src/modules/version.js`, `Module-uo main:module.json`, and the `bundles` branch). +So `src/data/platform.json` needs: + +- `protocol: 4` → **5** (Phase 10) — asserted three times over: the sidecar, the overlay, the bundle. +- `moduleApi: "1.6.0"` → **"1.7.0"** (Phase 2). +- `bundle.tag` / `bundle.sidecar` / `bundle.overlay` — whatever Phase 10's republished bundle carries. +- `verifiedOn` moved, and the page that quotes each value re-read rather than the JSON edited to make + the check pass — which is what the file's own header comment tells you in as many words. + +**The content half — the site currently documents the opposite of what Phase 1 ships.** +`src/content/docs/docs/administration/notifications-and-email.mdx` carries an +`