docs(link): protocol 6 part b -- leases, participation, and what the walk found

Six files. `v6.md` gains sections 7-10: one version with two halves, the lease
plane, the participation ledger, and 11b's verification.

Three corrections to what the plan and the design of record assumed.

Phase 11b is FIVE repos, not four, and in the opposite direction from 11a's
correction: a lease's ledger row had no reconcile path anywhere, because the step
that made it names `core.lease` and that is core's own action. `website` joins.

EVENTS.md's §D frames the 258 `Config.Get` call sites as splitting into two
patterns. Measured on 57.4: of the 158 non-Bridge sites in `Scripts/`, roughly
eight are read live. The allowlist is not a curated subset of a large pool, it is
nearly the whole of what exists. And `Config.Set` has exactly one caller in the
entire tree, so on a stock shard a GM cannot drift a configuration lease even
deliberately -- which is why proving `drifted` needed a scaffolding verb.

§G's "participation attribution is now the largest piece of new UO work" closes,
and the live-config-lease row goes to built-with-one-key.

§10.1 records the defect the phase's own deferral found in 11a's shipped code:
`bridge.busy` answered 200 instead of 425 because the frame carried two `kind`
fields and parsers take the last. Unreachable in 11a by construction; produced on
the first collision here.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-09-04 19:32:11 -05:00
parent 1521c5af7e
commit eabaf2635f
6 changed files with 546 additions and 23 deletions

View File

@@ -114,6 +114,7 @@ api.registerEventLeases([{
async read() { return { ok: true, value: 1.0 } },
async apply(v, until) { return { ok: true } },
async restore(baseline, { expected }) { return { ok: true } },
async inForce() { return { ok: true, held: true } }, // optional
}])
```
@@ -129,6 +130,17 @@ field:
showing what it had, because staleness is cheap, whereas an action that half-ran and was recorded
as done is a world change nothing will ever come back for. `retry` is opted OUT of — a module that
means "this will never work" says `retry: false`.
- **`inForce()` is a fourth question, not a fourth spelling of `read()`.** Optional, and answering
`{ ok: true, held: false }` is the only thing that takes a lease's ledger row out — everything
else, including a throw and a lease that declares no `inForce()` at all, leaves the row alone.
Core needs it because a reconcile after an outage asks *"does the game side still have any record
of this hold?"*, and none of the other three answers that: a value that DIFFERS from what the run
applied is drift, which `restore()` reports so the row lands `drifted` with the current value
beside it, and a reconcile that inferred absence from a changed value would orphan the row first
and tell the operator the lease vanished rather than that somebody moved it. The two questions
have different answers on purpose. Without it a lease row has no reconcile path at all — a lease's
step names `core.lease`, which is core's own action, so there is nowhere else a module could hang
the answer.
- **A module cannot spend a budget it did not declare.** A `cost()` naming a dimension no module
registered is REFUSED — at save, at the dry run and at dispatch, with its own refusal code, because
the fix is a module's declaration and not a deployment's cap. Declaring a dimension is not the same
@@ -652,7 +664,7 @@ api.registerAudiences([{ id, label, params, ceiling, resolve }]) //
api.registerEngagementSeeds({ templates, ruleGroups }) // 1.9.0
api.registerEventActions([{ id, label, risk, reversible, cost, params, perform, revert, reconcile }]) // 1.10.0
api.registerEventBudgets([{ id, label, unit }]) // 1.10.0
api.registerEventLeases([{ id, label, type, min, max, maxDurationMs, read, apply, restore }]) // 1.10.0
api.registerEventLeases([{ id, label, type, min, max, maxDurationMs, read, apply, restore, inForce }]) // 1.10.0
api.registerEventOptionSources([{ id, label, resolve }]) // 1.10.0
api.onBoot(async (ctx) => {})
api.onShutdown(async () => {})