docs(website): the engagement admin surface as built (Phase 4b) #184

Merged
whitlocktech merged 2 commits from docs/engagement-rules-admin into edge 2026-08-29 17:29:08 +00:00
Member

Companion to website#171 (engagement Phase 4b). §6.0b assigns this phase two documents; both land here.

ENGAGEMENT.md — "As built — 4b"

The four decisions the org lead settled before any code, and the arguments behind the two that are not taste:

  • The enable switch is its own route because a PUT re-validates against the registries as they are now — so the rules a re-validating toggle cannot switch off are exactly the three an operator most wants stopped: a rule whose module was uninstalled, one naming a channel that is gone, and one whose trigger has since narrowed its ceiling under a saved audience.
  • The reach preview is a count and nothing else, with capped / reason / permitted each recorded as a way the bare number would otherwise be a lie.

And the two defects the live walk found, both in Phase 4a's code rather than 4b's:

  1. A rule pointing at a dormant segment read as healthy. The annotation asked only whether the segment row existed (§7.3's case). The other shape of the same failure is §5.1a rule 4's — the row is exactly where it was and every audience in it belongs to an uninstalled module. Uninstalling a module under an enabled rule produced a rule the screen showed as on and firing.
  2. "1 rule still use this segment" — the delete refusal pluralised the noun and not the verb, in the sentence an operator reads when being told no.

Plus the rig that made the walk possible at all, which is worth not re-deriving: core declares no audiences (it knows no game vocabulary) and module-uo 0.3.0 declares none either, so on a stock local stack the entire §5.1a arithmetic is untestable. A ~20-line throwaway module in modules/ (gitignored) declaring four audiences at three ceilings makes all of it walkable — with the two registry rules that cost a restart each to discover: an audience id must contain a dot, and must be namespaced to the declaring module's own id.

ENGAGEMENT.md §5.1a — the composition UI

The section named a composition UI everywhere and described none. It now records: its own nav entry rather than a tab; "exclude" offered only under "all of" (switching the group to "any of" drops exclusions rather than composing a tree the server will refuse); the stored ceiling displayed beside the live count and never chosen; and a tree nested deeper than the composer renders shown read-only rather than flattened.

BACKEND_DESIGN.md — the route table

The twelve routes, with the reasoning that is not recoverable from the paths: why the enable switch is a PATCH of one column, why the trigger is not updatable, why deleting a segment in use is a 409 rather than a cascade, and what capped / permitted mean on the preview.


  • AI-assisted: written with Claude Code (Opus)

🤖 Generated with Claude Code

Companion to **website#171** (engagement Phase 4b). §6.0b assigns this phase two documents; both land here. ## `ENGAGEMENT.md` — "As built — 4b" The four decisions the org lead settled before any code, and the arguments behind the two that are not taste: - **The enable switch is its own route** because a `PUT` re-validates against the registries *as they are now* — so the rules a re-validating toggle cannot switch off are exactly the three an operator most wants stopped: a rule whose module was uninstalled, one naming a channel that is gone, and one whose trigger has since narrowed its ceiling under a saved audience. - **The reach preview is a count and nothing else**, with `capped` / `reason` / `permitted` each recorded as a way the bare number would otherwise be a lie. And the two defects the live walk found, both in **Phase 4a's** code rather than 4b's: 1. **A rule pointing at a dormant segment read as healthy.** The annotation asked only whether the segment *row* existed (§7.3's case). The other shape of the same failure is §5.1a rule 4's — the row is exactly where it was and every audience in it belongs to an uninstalled module. Uninstalling a module under an enabled rule produced a rule the screen showed as on and firing. 2. **"1 rule still use this segment"** — the delete refusal pluralised the noun and not the verb, in the sentence an operator reads when being told no. Plus the rig that made the walk possible at all, which is worth not re-deriving: **core declares no audiences** (it knows no game vocabulary) and `module-uo` 0.3.0 declares none either, so on a stock local stack the entire §5.1a arithmetic is untestable. A ~20-line throwaway module in `modules/` (gitignored) declaring four audiences at three ceilings makes all of it walkable — with the two registry rules that cost a restart each to discover: an audience id must contain a dot, and must be namespaced to the declaring module's own id. ## `ENGAGEMENT.md` §5.1a — the composition UI The section named a composition UI everywhere and described none. It now records: its own nav entry rather than a tab; "exclude" offered **only** under "all of" (switching the group to "any of" drops exclusions rather than composing a tree the server will refuse); the stored ceiling displayed beside the live count and never chosen; and a tree nested deeper than the composer renders shown read-only rather than flattened. ## `BACKEND_DESIGN.md` — the route table The twelve routes, with the reasoning that is not recoverable from the paths: why the enable switch is a `PATCH` of one column, why the trigger is not updatable, why deleting a segment in use is a `409` rather than a cascade, and what `capped` / `permitted` mean on the preview. --- - [x] AI-assisted: written with Claude Code (Opus) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
wtclaude added 1 commit 2026-08-29 17:11:42 +00:00
Companion to website#171.

ENGAGEMENT.md gains an "As built - 4b" section: the four decisions the org lead
settled, the correctness argument behind the standalone enable route, the three
honesty fields on the reach preview, and the two defects the live walk found in
Phase 4a's own code (a rule pointing at a dormant segment reading as healthy,
and the delete refusal's "1 rule still use"). It also records the throwaway
module rig that made the whole segment half walkable at all - core declares no
audiences, so on a stock local stack none of the §5.1a arithmetic can be
exercised without one.

§5.1a gains the composition UI it was owed: its own nav entry rather than a tab,
"exclude" offered only under "all of", the stored ceiling displayed and never
chosen, and a tree nested deeper than the composer renders shown read-only
rather than flattened.

BACKEND_DESIGN.md's route table gains the twelve routes, including why the
enable switch is a PATCH of one column and why deleting a segment in use is a
409 rather than a cascade.

- [x] AI-assisted: written with Claude Code (Opus)

Co-Authored-By: Claude <noreply@anthropic.com>
wtclaude added 1 commit 2026-08-29 17:26:49 +00:00
Six defects that only driving the two screens in a browser could find, plus two
environment facts worth not re-deriving:

  - rebuilding client/dist while the server is running blanks the whole SPA. The
    HTML shell resolves core's hashed bundle filename at boot, so after a
    rebuild it points at a file that no longer exists; core's bundle 404s,
    window.__rg is never published, and modules/uo/entry.js throws MODULE_API.md
    §3.1's "core did not publish its shared dependencies" into a blank page. The
    error names core, and core is not at fault. Restart after every build.
  - a window.confirm blocks CDP entirely, so the two destructive actions cannot
    be driven from a script and a session that opens one is stuck until a human
    dismisses it. Exercise those paths over the API.

- [x] AI-assisted: written with Claude Code (Opus)

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 315a7c7fca into edge 2026-08-29 17:29:08 +00:00
whitlocktech deleted branch docs/engagement-rules-admin 2026-08-29 17:29:08 +00:00
Sign in to join this conversation.
No description provided.