docs(events): Phase 0 — the eleven decisions, and the two documents they reach into

Closes the second half of EVENTS_PLAN.md Phase 0. All of EVENTS.md §N1–N11 were
answered by the org lead on 2026-09-01, before any code, which lifts the ⚠ gate
from P11 and P12 and unblocks P1.

Nine went the way §N recommended. Two did not, and each changes a phase:

- N2 — publishing a version and starting a run are `admin` only; a moderator
  keeps live control of a run already in flight (cancel, abort) and nothing
  more. Start and stop are deliberately not the same gate: starting commits the
  deployment to everything a definition contains, unattended, while cancelling
  is incident response. §K's table and the API surface table are updated, and
  P3 and P6 carry it.
- N4 — this deployment is single-instance and not planned to change, so P2 does
  not build the `--scale app=2` test. Every claim path in §E is built exactly as
  specified regardless — the unique index and the CAS equally protect a tick
  that overruns into the next one, and the lease and its reclaim recover a step
  whose process died mid-dispatch. §E records what to build first if this
  deployment is ever scaled.

N1 was taken in full, item grants included, which is a reversal of two separate
lines in ADMIN_CONTROLS.md §8 rather than one. §8's cut list names "item/gold
grants" explicitly and separately from world building, so the new §8a amendment
says both out loud rather than letting the grant ride along on the creation
reopening. §8's bullet is left standing verbatim — it is the decision that was
actually taken — with a pointer to the amendment, and §1's thesis paragraph gets
the same pointer. Loot-table changes and arbitrary [set / [get / [add stay
permanently excluded, along with the rest of the Tier-H moderation verbs.

N3 gives ENGAGEMENT.md §7.1 Q6's "no evaluator yet" an owner: the Event System
runner becomes the `kind: 'scheduled'` evaluator, built in that workstream's P2.
Nothing in the engagement contract changes.

One consequence was derived rather than decided and is flagged for review:
POST /admin/events/:id/verify moves to `admin, editor` rather than staying with
`start`. A dry run dispatches nothing, and the author who wrote the definition
is who should price it against the caps before asking an admin to publish.

Verified: every relative link and anchor in the four touched files resolves,
including the renamed §N anchor (#n--decisions) and the new #8a. The docs repo
has no CI workflow, so the plan's "docs CI link check" was run by hand.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-01 20:52:37 -05:00
parent cda5325ab4
commit cc6775e20b
4 changed files with 274 additions and 32 deletions

View File

@@ -6,11 +6,13 @@ is proved. It re-specifies nothing — where this and `EVENTS.md` disagree, `EVE
file is the one with the bug.
**Seventeen phases, P0P16.** Every phase is independently shippable and leaves the site working.
**Two are gated** on the open question `EVENTS.md` §N1 (the `ADMIN_CONTROLS.md` §8 amendment) and are
deliberately late: P11 and P12. Everything else — the engine, the scheduler, the calendar, the
conditions, the caps, the module contract, the ledger, the first wave of UO actions, the integrations,
the authoring UI, the public surface — needs no decision beyond P0. Those fourteen phases reach the
game only to *announce*, over verbs the write plane already carries; nothing in them creates or
**No phase is gated any more.** P11 and P12 hung on `EVENTS.md` §N1 (the `ADMIN_CONTROLS.md` §8
amendment); §N1 and the other ten **were answered by the org lead on 2026-09-01**, which closes P0
and lifts the gate. They stay deliberately late all the same — they are the phases that reach into
the world, and they belong after the ledger that makes them safe. Everything else — the engine, the
scheduler, the calendar, the conditions, the caps, the module contract, the ledger, the first wave of
UO actions, the integrations, the authoring UI, the public surface — needed no decision beyond P0.
Those fourteen phases reach the game only to *announce*, over verbs the write plane already carries; nothing in them creates or
changes a thing in the world.
---
@@ -96,9 +98,9 @@ early on purpose.
### Phase 0 — Design of record (`docs`)
> **Half-done.** The pull request that introduced this file and `EVENTS.md` discharges the first
> half — the design of record exists. What remains is the decisions, and they are the part that
> gates P11 and P12.
> **Complete, in two pull requests.** The first introduced this file and `EVENTS.md`; the second
> recorded the eleven decisions and amended the two documents they reach into. **All of §N1N11
> were answered by the org lead on 2026-09-01**, before any code, so nothing below is gated.
Land `docs/website/EVENTS.md`, and answer §N1N11. Two of those answers have consequences outside this
document and should be written where they will be found:
@@ -113,6 +115,24 @@ document and should be written where they will be found:
**Ships:** the design of record, and two documents that stop contradicting each other.
**Verify:** `docs` CI link check; every relative link resolves.
> **As answered, 2026-09-01.** Nine of the eleven went the way `EVENTS.md` §N recommended. **Two did
> not, and each changes a phase below.**
>
> - **N2 — starting a run is `admin` only.** A moderator gets live control of a run already in
> flight — cancel and abort — and nothing more. Starting commits the deployment to everything a
> definition contains, unattended; cancelling is incident response, and gating the stop button on
> the same role as the start button would behave badly in exactly the case moderators exist for.
> **P3 and P6 carry this**, and `EVENTS.md` §K's table is the normative statement of it.
> - **N4 — this deployment is single-instance, and not planned to change.** **P2 does not build the
> `--scale app=2` test.** Every claim path is built exactly as specified regardless: the unique
> index and the CAS equally protect a tick that overruns into the next one, and the lease and its
> reclaim recover a step whose process died mid-dispatch. The multi-instance property becomes
> true-by-construction rather than proved; `EVENTS.md` §E records what to build first if this
> deployment is ever scaled or acquires a rolling deploy.
>
> **N1 was taken in full, item grants included** — a reversal of *two* separate lines in
> `ADMIN_CONTROLS.md` §8 rather than one, and the amendment at §8a says both out loud.
---
### Phase 1 — Schema, CRUD and the core action registry (`website` + `docs`)
@@ -155,8 +175,11 @@ Also here: `missed` and the grace window, the lease and its reclaim, `concurrenc
run params, and `health` as a column separate from `status`.
**Ships:** a manually started event that broadcasts, waits, and completes. Demoable over curl.
**Verify:** `npm test`, including a **deliberate two-instance test** — the claim paths are the whole
point of this phase and a single-process test proves nothing about them.
**Verify:** `npm test`. **No two-instance test** — §N4 settled this deployment as single-instance, so
the `--scale app=2` rig the engagement workstream used is not built here. The claim paths are still
built exactly as `EVENTS.md` §E specifies, and they are still the point of the phase: they are what
protects a tick that overruns into the next one, and what recovers a step whose process died
mid-dispatch. Test both in-process. The decision is not licence to drop a CAS.
**Two traps, both already paid for once in this codebase.**
- **A reclaim must not reset `attempts`.** Engagement Phase 14's defect: a sweep that returned every
@@ -173,6 +196,11 @@ point of this phase and a single-process test proves nothing about them.
A list with state and next occurrence; a create/edit form; publish; start now; cancel; and a run
console showing the phase, the step list with status and attempts, and the log.
**Publish and start now are `admin` only from this phase, not from P6** (§N2). Cancel is `admin` +
`moderator`. The routes get their real gates here even though the switchboard they will eventually
consult does not exist yet — a button that is admin-only later and open now is a gate nobody
notices was missing.
The spec is edited as **structured fields for the parts that exist** (name, description, schedule,
phases with their steps) and the step's params as a raw JSON field — a deliberate placeholder that P13
replaces with the schema-driven editor. Say so in the UI, so it does not read as the finished thing.
@@ -247,7 +275,10 @@ error, not an outage.
enablement, cap, and the shard's own switch. Not for tidiness — it is what keeps an EM-style
delegation model a later option rather than a redesign.
The role split from `EVENTS.md` §K is applied to the routes here.
The role split from `EVENTS.md` §K is applied to the routes here — completing what P3 started, and
including §N2's departure from the module-uo shape: **publishing and starting are `admin` only,
while cancelling and aborting a run in flight are `admin` + `moderator`**. Start and stop are
deliberately not the same gate.
**Ships:** an admin switchboard, and a system that cannot be made to do an unbounded amount of
anything.
@@ -344,9 +375,9 @@ push; the ceiling on `run.failed` proved to exclude a moderator.
---
### Phase 11 — Protocol: idempotency, lease deadlines, participation (`servuo-plugins` + `link` + `module-uo` + `installer` + `docs`)
### Phase 11 — Protocol: idempotency, lease deadlines, participation (`servuo-plugins` + `link` + `module-uo` + `installer` + `docs`)
**Gated on §N1.** A five-repo protocol bump, and the shape TEAMS Phase 1 already walked.
**§N1 answered 2026-09-01 — no longer gated.** A five-repo protocol bump, and the shape TEAMS Phase 1 already walked.
- **Plugin:** an idempotency key on every inbound command with a bounded recent-key set that answers a
repeat with the original result; a lease deadline timer that restores baseline **without being
@@ -366,9 +397,10 @@ proving baseline returns anyway.
---
### Phase 12 — UO wave 2: the world verbs (`servuo-plugins` + `link` + `module-uo` + `docs`)
### Phase 12 — UO wave 2: the world verbs (`servuo-plugins` + `link` + `module-uo` + `docs`)
**Gated on §N1.** The capability set the two UO programs demonstrate, each cap-bounded, ledgered, and
**§N1 answered 2026-09-01 — no longer gated**, and taken in full, so the item grant row below
stands. The capability set the two UO programs demonstrate, each cap-bounded, ledgered, and
either owned or borrowed:
| Verb | Owned or borrowed | Cap dimension |
@@ -493,9 +525,9 @@ flowchart TD
P8 --> P9["P9 · UO wave 1<br/>no protocol change"]
P5 --> P10["P10 · integrations"]
P9 --> P10
P0 -.->|"§N1"| P11["P11 · protocol bump"]
P0 -.->|"§N1 answered"| P11["P11 · protocol bump"]
P8 --> P11
P11 --> P12["P12 · UO world verbs"]
P11 --> P12["P12 · UO world verbs"]
P7 --> P13["P13 · authoring UI"]
P4 --> P13
P10 --> P14["P14 · public + mobile"]
@@ -523,7 +555,8 @@ change. This is a real product and it is roughly a third of the work.
**Stop after P10** — everything above plus the module seam, the ledger, the first UO actions and every
notification channel. The website orchestrates and announces; a GM does the target-driven parts
in-client, exactly as `ADMIN_CONTROLS.md` §8 argued they should. **This is the recommended minimum
viable scope**, and it requires no answer to §N1 at all.
viable scope**, and it was the scope that required no answer to §N1 at all. §N1 has since been
answered in full, so this is now a scope choice rather than a way around an open decision.
**Stop after P14** — everything, including the world verbs and the public calendar. P15 and P16 are
not optional if anything ships to `main`; they are the cost of the `edge` discipline.