docs(engagement): Phase 11b — the seed API, the in-universe voice, the governor's letter #196

Merged
whitlocktech merged 1 commits from docs/engagement-phase-11b into edge 2026-09-01 06:18:54 +00:00
Member

The design of record for Phase 11b. Pairs with website#178 (the seed API) and Module-uo#23 (the bodies).

Four decisions settled by the org lead before any 11b code, plus MODULE_API 1.9.0 and what building it found.

The four decisions

Question Decision
7 a module cannot ship a template or a rule — core's seeders are core's add api.registerEngagementSeeds({ templates, ruleGroups }); MODULE_API_VERSION1.9.0
8 the register the game-powered bodies are written in in-universe, with a per-family in-fiction sender — the crown writes about the crown's business, and nothing else
9 which bodies stay plain the nine security and operational ones; the other sixteen go in-universe
10 the newly-elected governor is addressable and receives no letter add uo.governor.appointed — a 25th trigger, owner-audienced, beside the existing broadcast

Decision 7 is the one 11a could not have discovered, because 11a seeded nothing. The plan's own sentence — "24 rules, all enabled = 0; bespoke template bodies" — described work with no mechanism to land in. Reaching engagement_templates through the ctx.query a module already holds was considered and rejected: it would re-implement seedOne's customized skip, its seed_version comparison and its block validation outside the file that owns them.

Decision 8 is also why the bodies had to be the module's. "A letter from Lord Blackthorn" is Britannian canon and §5.2's rule is that core stays ignorant of every word of a module's domain. check:modules would not have caught it — it reads identifiers, imports and route literals, never prose, and says so in its own header — which is precisely the argument for taking the boundary seriously here rather than leaning on the checker.

Decision 10 corrects a fact the plan had wrong by omission. §8.6 records that uo.points.rank_changed cannot address a person, and the same reasoning was silently assumed to cover the governor. city.update's governor is written by BridgeJson.Actor(), which emits serial, name, acct and webId — the new governor is addressable today, no protocol change. Widening the existing trigger to two audiences was refused: one trigger means one rule means one template, and the town's bulletin and the governor's letter are not the same text.

What building it found

Recorded in a new "What building it found" block under Phase 11b, because four of these are cheap to get wrong from memory:

  • A template has no conditionals, and an in-universe body is a sentence. An unset optional interpolates to the empty string — right for notify.event, wrong for a letter. The two fragment shapes (a label carries a sentence's spine; a trailing fragment leads with its own space) and why the labels stay required: false even though that leaves nothing at runtime to notice a mapper that forgot one.
  • A render sweep over all 32 bodies, twice, is what found the defects — an optional in a subject line, multi-optional detail lines rendering "On hand: gold.", a trailing fragment used as a leading one. None were visible in the source; none were catchable by any existing check.
  • A trigger-bound template could not reference its own unsubscribe link — it rendered correctly and then the save-time check would have refused the first operator who edited one. Nothing had ever taken that path.
  • A trigger id and a template key have different grammars, and uo.champ.boss_up uses the character that separates them.

Files

  • website/ENGAGEMENT.md — the decision block, the amended 11b bullet (25 rules), the findings, and four additions to the acceptance list.
  • website/MODULE_API.md — §1.1 1.9.0 with the full shape and the three prohibitions; registerEngagementSeeds in §2.4.
  • modules/uo/API.md — §5.7 the shipped bodies, §5.8 the presentational fragments; the trigger count and the owner ceiling row updated for the 25th.

AI-assisted: written with Claude Code.

🤖 Generated with Claude Code

The design of record for Phase 11b. Pairs with **website#178** (the seed API) and **Module-uo#23** (the bodies). Four decisions settled by the org lead **before any 11b code**, plus `MODULE_API` 1.9.0 and what building it found. ## The four decisions | | Question | Decision | |---|---|---| | **7** | a module cannot ship a template or a rule — core's seeders are core's | **add `api.registerEngagementSeeds({ templates, ruleGroups })`**; `MODULE_API_VERSION` → **1.9.0** | | **8** | the register the game-powered bodies are written in | **in-universe, with a per-family in-fiction sender** — the crown writes about the crown's business, and nothing else | | **9** | which bodies stay plain | **the nine security and operational ones**; the other sixteen go in-universe | | **10** | the newly-elected governor is addressable and receives no letter | **add `uo.governor.appointed`** — a 25th trigger, `owner`-audienced, beside the existing broadcast | **Decision 7 is the one 11a could not have discovered, because 11a seeded nothing.** The plan's own sentence — *"24 rules, all `enabled = 0`; bespoke template bodies"* — described work with no mechanism to land in. Reaching `engagement_templates` through the `ctx.query` a module already holds was considered and rejected: it would re-implement `seedOne`'s `customized` skip, its `seed_version` comparison and its block validation outside the file that owns them. **Decision 8 is also why the bodies had to be the module's.** *"A letter from Lord Blackthorn"* is Britannian canon and §5.2's rule is that core stays ignorant of every word of a module's domain. `check:modules` would **not** have caught it — it reads identifiers, imports and route literals, never prose, and says so in its own header — which is precisely the argument for taking the boundary seriously here rather than leaning on the checker. **Decision 10 corrects a fact the plan had wrong by omission.** §8.6 records that `uo.points.rank_changed` cannot address a person, and the same reasoning was silently assumed to cover the governor. `city.update`'s `governor` is written by `BridgeJson.Actor()`, which emits `serial`, `name`, **`acct`** and `webId` — the new governor is addressable today, no protocol change. Widening the existing trigger to two audiences was refused: one trigger means one rule means **one template**, and the town's bulletin and the governor's letter are not the same text. ## What building it found Recorded in a new *"What building it found"* block under Phase 11b, because four of these are cheap to get wrong from memory: - **A template has no conditionals, and an in-universe body is a sentence.** An unset optional interpolates to the empty string — right for `notify.event`, wrong for a letter. The two fragment shapes (a **label** carries a sentence's spine; a **trailing fragment** leads with its own space) and why the labels stay `required: false` even though that leaves nothing at runtime to notice a mapper that forgot one. - **A render sweep over all 32 bodies, twice, is what found the defects** — an optional in a subject line, multi-optional detail lines rendering *"On hand: gold."*, a trailing fragment used as a leading one. None were visible in the source; none were catchable by any existing check. - **A trigger-bound template could not reference its own unsubscribe link** — it rendered correctly and then the save-time check would have refused the first operator who edited one. Nothing had ever taken that path. - **A trigger id and a template key have different grammars**, and `uo.champ.boss_up` uses the character that separates them. ## Files - `website/ENGAGEMENT.md` — the decision block, the amended 11b bullet (25 rules), the findings, and four additions to the acceptance list. - `website/MODULE_API.md` — §1.1 **1.9.0** with the full shape and the three prohibitions; `registerEngagementSeeds` in §2.4. - `modules/uo/API.md` — §5.7 the shipped bodies, §5.8 the presentational fragments; the trigger count and the `owner` ceiling row updated for the 25th. --- AI-assisted: written with Claude Code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-09-01 06:16:34 +00:00
Four decisions settled by the org lead before any 11b code, plus MODULE_API
1.9.0 and what building it found.

DECISION 7 is the one 11a could not have discovered, because 11a seeded nothing.
The plan's own sentence — "24 rules, all enabled = 0; bespoke template bodies" —
described work with NO MECHANISM to land in: templateSeeds.js and coreRules.js
are core files with core arrays, and registries.js has no registerTemplates.
Adds api.registerEngagementSeeds({ templates, ruleGroups }). Templates re-ensure
every boot; rule groups are one-shot per named group, which is 11a's seed-key
finding stated as an API rather than as a warning.

DECISION 8: the game-powered families read in-universe, with a per-family sender
rather than one voice. The crown writes about the crown's business and nothing
else. This is also why the bodies had to be the module's: §5.2 says core stays
ignorant of a module's domain, and check:modules reads identifiers, never prose —
so the boundary is honoured deliberately here rather than leaned on.

DECISION 9: nine bodies stay plain. A failed-login notice written as a letter is
indistinguishable in register from the phishing mail it warns about.

DECISION 10 corrects a fact the plan had wrong by omission. §8.6 records that
uo.points.rank_changed cannot address a person, and the same reasoning was
silently assumed to cover the governor. city.update's `governor` is written by
BridgeJson.Actor(), which emits acct and webId — the new governor is addressable
today, no protocol change. uo.governor.appointed is the 25th trigger.

Also records what building it found: the no-conditionals/empty-string collision
that the presentational fragments exist for, the render sweep that found three
defects no check could see (an optional in a subject line, multi-optional detail
lines, a trailing fragment used as a leading one), the trigger-bound template
that could not reference its own unsubscribe link, and the trigger-id/template-key
grammar mismatch.

docs/modules/uo/API.md gains §5.7 and §5.8.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit c9873eff7d into edge 2026-09-01 06:18:54 +00:00
whitlocktech deleted branch docs/engagement-phase-11b 2026-09-01 06:18:55 +00:00
Sign in to join this conversation.
No description provided.