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 +`