Commit Graph

660 Commits

Author SHA1 Message Date
a38c2da80b docs(rust): phase 16 as built and walked (PLAN.md §32.5-32.7, M18)
D133: the Admin → Rust servers page the plan assumed existed. The as-built
record for the five slash commands and the next wipe, the seven-step walk
(all passed), and the findings. android/PLAN.md M18 marked built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 13:42:59 -05:00
2b9d2d1a75 Merge pull request 'docs(rust): phase 16 plan of record — slash commands and the next wipe (PLAN.md §32)' (#275) from docs/rust-phase-16 into main
Reviewed-on: #275
2026-09-25 18:10:35 +00:00
ec727ef648 docs(rust): phase 16 plan of record — slash commands and the next wipe (PLAN.md §32)
D126-D132: five read-only commands; any answer narrower than public goes
to the caller alone (D127); an operator-set next wipe (rule + one-off
date) shown on the web, in the app and by /wipe; module-uo /guild's
public-answer leak filed as Module-uo#46. Android PLAN gains M18.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 13:02:09 -05:00
57421314b1 Merge pull request 'docs(rust): phase 15 as built — the map and events on a phone (PLAN.md §31.5–§31.7)' (#274) from docs/rust-phase-15-built into main
Reviewed-on: #274
2026-09-25 17:42:56 +00:00
42a0482a9e docs(rust): phase 15 as built — the map and events on a phone (PLAN.md §31.5–§31.7)
- PLAN.md §31.5: what was built in website and Android-app, where the
  build departed from §31.2, and the seven-step emulator walk.
- §31.6: what the walk found: the zoom lost twice (fixed), the tally a
  stand-in cannot feed, the off-grid row the frame clamps, the "wiped
  Dec 31, 1" header, the card that outlives its marker.
- §31.7: what is not proven (a real player, a counted tally, a UO site).
- Phase row 15 and the Android plan's M17 marked built and walked.
- EVENTS.md § API surface: the public calendar's run entries carry
  runId (D125). BACKEND_DESIGN defers event routes to that table.
- PLAYER_WALK.md: the map and events on a phone, for the person-parts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 12:30:49 -05:00
a3fcc42a57 Merge pull request 'docs(rust): phase 15 plan of record — the map and events on a phone (PLAN.md §31)' (#273) from docs/rust-phase-15 into main
Reviewed-on: #273
2026-09-25 12:23:46 +00:00
ed4d9f52d3 docs(rust): phase 15 plan of record — the map and events on a phone (PLAN.md §31)
Android leg D. D121-D125: the map drawn natively in Compose as a fifth
tab gated on `map`, polled every 10 s; a site-event marker opening the
app's own event page, which needs runId on core's public calendar
entries; and M13 walked against a Rust run. Android plan gains M17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 07:22:19 -05:00
f28a098e95 Merge pull request 'docs(rust): phase 14 as built — the live map (PLAN.md §30.6–§30.9, PROTOCOL.md §17)' (#272) from docs/rust-phase-14-built into main
Reviewed-on: #272
2026-09-25 11:59:51 +00:00
6fdb081087 docs(rust): phase 14 as built — the live map (PLAN.md §30.6–§30.9, PROTOCOL.md §17)
- PLAN.md §30.6: D119 (the grid label is the game's own, MapHelper) and D120
  (Leaflet as a lazy chunk), both asked mid-build.
- §30.7: what was built, where it departed from §30.2, and the eight-step
  walk on both rigs against real core.
- §30.8: what the walk found — UserIDString empty for a server-made player,
  the game now renders its map at every boot for Facepunch's map-image
  service, and `app.port -1` reaches the game as `1`.
- §30.9: what needs people in the game.
- PROTOCOL.md §17 for protocol 11, and a note in §8 that `grid` is the game's
  own label from protocol 11 (D119).
- PLAYER_WALK.md: the map walk.
- The phase 14 row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 06:31:54 -05:00
1538b4e9cd Merge pull request 'docs(rust): phase 14 plan of record — the live map (PLAN.md §30)' (#271) from docs/rust-phase-14 into main
Reviewed-on: #271
2026-09-25 05:08:01 +00:00
0222adb49a docs(rust): phase 14 plan of record — the live map (PLAN.md §30)
A rig probe found that R9's .map file is terrain data, not a picture,
and that Rust+ already caches the rendered JPEG, while the game's own
render stalls the main thread for 8.5 s. D109-D118 from the org lead;
R9 amended by D110; phase 14 row updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 23:39:29 -05:00
af0e86e367 Merge pull request 'docs(rust): phase 13b as built — the rewards (PLAN.md §29.6–29.9, PROTOCOL.md §16)' (#270) from docs/rust-phase-13b-built into main
Reviewed-on: #270
2026-09-24 13:01:07 +00:00
86dc0ac804 docs(rust): phase 13b as built — the rewards (PLAN.md §29.6–29.9, PROTOCOL.md §16)
- PLAN.md §29.6: D106 (the news switch is a card on the visibility page),
  D107 (tally.open behind EventsEnabled), D108 (a tally is forgotten seven
  days after it opened).
- §29.7 as built: where the build departed from §29.3 (presence asked of
  ZoneManager, idem_key on the run-grant rows, fixed-choice sources) and
  the walk, on both rigs, without a player.
- §29.8 findings: real core refused a camelCase option-source id; Carbon
  refuses a grant to a Steam id it has never seen; panel-created data
  directories are not game-writable.
- §29.9 what is not proven: the player half, now PLAYER_WALK.md's rewards walk.
- PROTOCOL.md §16: protocol 10 — the tally, kits.list, kit credits on
  perm.sync, chat.say, three bounds, the sidecar's five routes.
- The 13b phase row, and §9/§10 correction notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 07:49:00 -05:00
5777e0757c Merge pull request 'docs(rust): phase 13b plan of record (PLAN.md §29)' (#269) from docs/rust-phase-13b into main
Reviewed-on: #269
2026-09-24 11:33:08 +00:00
fb12b18efc docs(rust): phase 13b plan of record (PLAN.md §29)
The rewards half of phase 13, written before its code: the participation
tally counted by the game, rust.kit.entitle through the site mirror's per-run
rows plus one extra kit use per reward, and rust.announce with the announce
leg. Records D98-D105 (org lead, 2026-09-24), the Kits 4.4.9 facts they rest
on, the catalogue, what each repo builds, the eight-step walk, and four
readings left open for review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 05:31:01 -05:00
37bc06234d Merge pull request 'docs(rust): phase 13 plan, and 13a as built (PLAN.md §28, PROTOCOL.md §15)' (#268) from docs/rust-phase-13 into main
Reviewed-on: #268
2026-09-24 10:07:16 +00:00
a39d860123 docs(rust-link): make the events walk's zone checks runnable
ZoneManager's listing command is `zone_list`, and it has no command that
says who is inside a zone. The zone steps now use `rgp.inzone`, a rig-only
probe command that asks ZoneManager's own IsPlayerInZone for every connected
player. They also no longer claim rg.hooks counts zone entries: the bridge
subscribes to those hooks in 13b.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 04:11:14 -05:00
c385de7155 docs(rust-link): the events player walk, and the permission walk's protocol-9 note
PLAYER_WALK.md gains the events walk: the checks phases 12 and 13a left for a
person on the rig (a kit unlocking under a group-permission lease, standing
in a zone, a zone surviving a restart, looting and killing what an event
placed, a zone expiring around a player, and spawn.max_* with players on).
The permission walk now says it can only pass on protocol 9, because the
phase-7 owner bug made its steps 1-3 impossible on Oxide until then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 04:09:52 -05:00
9c46b06172 docs(rust): phase 13a as built — protocol 9, D96–D97, the walk and its findings
- PLAN.md §28.5–28.8: two more org-lead decisions (D96 required zone minutes
  held by the game; D97 one placing verb per kind, because core infers cap
  boxes from examples), the seven-step walk on both rigs, the defect a
  mid-run restart found (the reconcile asked a world that had not loaded and
  the plugin pruned live crates) and its fix, and what is not proven.
- PROTOCOL.md §15: protocol 9 — the five world commands, the registry keyed
  by the website's key, what a restart and a wipe do, `worldReady`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 03:14:49 -05:00
0de9d7f90d docs(rust): phase 13 plan of record — split 13a/13b, D80–D95 (PLAN.md §28)
Phase 13 splits into 13a (the world verbs, the ownership registry and the
boot/wipe reconcile watch) and 13b (the participation tally, the kit
entitlement and announce). Records the org lead's sixteen decisions and the
rig facts they rest on: monument names repeat, crates keep their net id
across a restart while NPCs do not, and ZoneManager erases a plugin's
temporary zones when that plugin unloads. Also links the three core
findings phase 12 raised, now filed as website#205-#207.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-24 00:36:33 -05:00
68989c247b Merge pull request 'docs(rust): phase 12 — the leases (PLAN.md §27, PROTOCOL.md §14)' (#267) from docs/rust-phase-12 into main
Reviewed-on: #267
2026-09-24 04:02:45 +00:00
5f18097223 docs(rust): phase 12 as built and walked — §27.5-27.7, PROTOCOL.md §14
Walked on both rigs through real core: 21 keys observed live, the game's own deadline with core stopped, drift, reload and restart mid-hold, and the switch. Records two defects fixed in the phase and four found outside it and raised: the phase-7 grant owner bug, core restoring orphaned lease rows over a later run, core.lease dropping retry:false, and the 10s budget squeeze.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 21:14:09 -05:00
46b565ac9b docs(rust): phase 12 plan of record — the leases (PLAN.md §27, D73-D79)
The rig disproved three of §9's rows: vanilla Rust has no gather, craft
or smelt rate convar. core.lease never tells a module which server, so
the target names it. And every scheduled run has the empty scope, so
"caps are per server" holds only for runs an admin starts by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 20:17:23 -05:00
4049abc41a Merge pull request 'docs(rust): phase 11 — a Rust notification on a phone (PLAN.md §26, android M16)' (#266) from docs/rust-phase-11 into main
Reviewed-on: #266
2026-09-23 20:49:14 +00:00
f1b8329540 docs(rust): phase 11 as built and walked — §26.4-26.6, M16
The raid alert reached an emulator through ntfy.sh 19 seconds after a
rig raid, titled from its inbox row; switched off in the app, the next
raid enqueued in-app only. Closes M7's open QA item (on-device delivery
against a live ntfy), and amends the M7 and engagement phase 8 passages
D69 and D70 made stale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 15:40:02 -05:00
83e57e6f47 docs(rust): phase 11 plan of record — a Rust notification on a phone (PLAN.md §26, M16)
Four org-lead decisions (D69-D72): the linked-account check asks the
site's own module and never gates switching off; a tickle is titled
from the inbox item its ref names; /player/rust and ?tab= open
natively; the relay hop is walked on ntfy.sh, closing M7's open QA item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 15:19:05 -05:00
b7d9872fed Merge pull request 'docs(rust): phase 10 — notifications and engagement (PLAN.md §25, PROTOCOL.md §13)' (#265) from docs/rust-phase-10 into main
Reviewed-on: #265
2026-09-23 18:43:14 +00:00
cb8e8853f6 docs(rust): phase 10 as built — protocol 7 and the raid alert
PLAN.md §25.5-25.8: what shipped, the walk that met the criterion on the
Oxide rig, the four things the rig found (every generic notice never
said which server; attackerId null for a spawned player; a disband
roster gone before the disband was read; in-app `subscribers` being
everyone), and what is not proven. PROTOCOL.md §13 specifies protocol 7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 13:41:01 -05:00
aa148adfc6 docs(rust): phase 10 plan of record (PLAN.md §25, D59-D68)
The notifications and engagement phase, as decided by the org lead on
2026-09-23: the raid alert goes to everyone authorised on the tool
cupboard, covers doors and external walls, never names the raider, and
fires online or offline with the choice left to a rule condition.
Nothing reaches the game this phase, which amends R7. Also corrects §10
where core's contract disagreed with it (there is no `self` ceiling).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 05:50:24 -05:00
edff0e3695 Merge pull request 'docs(rust): phase 9 — Teams from first-party clans (PLAN.md §24, PROTOCOL.md §12)' (#264) from docs/rust-phase-9 into main
Reviewed-on: #264
2026-09-23 10:31:35 +00:00
eea4f958b2 docs(rust): phase 9 as built — protocol 6 and first-party clans as Teams
PLAN.md §24.4-24.7: walked on the Oxide rig end to end and on Carbon
hook by hook; what the rig found (the refusal-first reconcile, the
dropped first feed line and its re-offer, core's 40-character dedupe
key, one module per site). R6 amended by D47. PROTOCOL.md §12 specifies
protocol 6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 05:28:16 -05:00
de25ed3276 docs(rust): phase 9 plan of record (PLAN.md §24, D47-D58)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 01:27:35 -05:00
a4c4476c3e Merge pull request 'docs(modules): the presence fix — nothing names who is online by default' (#262) from docs/rust-presence-fix into main
Reviewed-on: #262
2026-09-23 05:36:05 +00:00
3b7b9cca4f docs(modules): the presence fix - nothing names who is online by default
modules/rust/PLAN.md gains §23: the org lead's rule (2026-09-22) that
nothing names who is online by default, the five decisions it needed
(D42-D46), the fourth surface the rule reached (the leaderboard's
lastSeen), the viewer re-read from the users row, and a defect four
phases old that the walk found - every empty state in module-rust
rendered as a blank box, because core's EmptyState renders children and
the Integration Kit's template teaches title/message.

rust-link/PROTOCOL.md reclassifies six §8.4 kinds from public to
presence - public with an operator-chosen audience - with no wire change.

android/PLAN.md records the app's half as an amendment to M14.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-23 00:32:17 -05:00
eb4a8bcafc Merge pull request 'docs(modules): phase 8 as built, and the rig that put the sidecar where the design says it lives' (#261) from docs/rust-phase-8 into main
Reviewed-on: #261
2026-09-23 01:51:51 +00:00
11b8965aa7 docs(modules): phase 8 as built, and the rig that finally put the sidecar where the design says it lives
Three documents:

* `modules/rust/PLAN.md` §22 — the phase as built. Three org-lead decisions
  (D39-D41), what a player is told and what they are not, the refusals on a
  phone, and an honest limit the rig found: a rank can be live while every
  permission it carries resolves nowhere.
* `rust-link/INSTALL_RIG.md` — new. The sidecar runs INSIDE the game
  container now, which is the shape R20 says the egg ships and which retires
  the firewall wall phases 6, 7 and 7b each stopped at. A container's
  127.0.0.1 is genuinely private, so a stock plugin config and a stock
  sidecar find each other with nothing configured at all. Three things in
  the launcher are load-bearing and each is written down with the failure it
  prevents.
* `rust-link/PLAYER_WALK.md` — the account walk on a phone, and a correction:
  7b's "it needs a firewall rule on a development machine" is no longer true.

`android/PLAN.md` gains M15.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-22 20:35:46 -05:00
15d64b28fe Merge pull request 'docs(modules): phase 7b as built — configuration from the site, and the undo that makes it safe' (#260) from docs/rust-phase-7b into main
Reviewed-on: #260
2026-09-22 15:01:26 +00:00
7f008fd1f3 docs(modules): the Carbon rig answers too, and its root is a different directory
R19's byte-identical plugin now carries protocol 5 on both frameworks:
`framework=oxide root=/home/container/oxide/config` on one rig and
`framework=carbon root=/home/container/carbon/configs` on the other, from the
same file. That is R18's amendment proven rather than argued — a literal
`oxide/config/` in this editor would have missed every config on half of all
installs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-22 08:58:21 -05:00
82145d3b4a docs(modules): phase 7b as built — configuration from the site, and the undo that makes it safe
PROTOCOL.md §11 specifies protocol 5: the walk rooted at the framework's own
config directory, the version a write must present back, the set-shaped write,
the watched reload and the automatic restore. PLAN.md §21 is the phase as built
— four org-lead decisions, the float trap and what avoiding it cost, and four
defects a browser found that 179 green tests did not.

PLAYER_WALK.md gains the configuration walk, because the acceptance line needs
the sidecar and the game on one host and the rig cannot reach one yet.
INTEGRATION.md gains the four things an operator should know before they edit a
plugin's settings from a web page.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-22 08:55:39 -05:00
132205f0f4 Merge pull request 'docs(modules): phase 7 as built — the permission mirror, and the set arithmetic behind it' (#259) from docs/rust-phase-7 into main
Reviewed-on: #259
2026-09-22 06:53:00 +00:00
bba2ab04e0 docs(modules): phase 7 as built — the permission mirror, and the set arithmetic behind it
Protocol 4 (`PROTOCOL.md` §10), phase 7 as built (`PLAN.md` §20), what an operator
needs to know about it (`INTEGRATION.md`), and the in-game leg as a walk to run
(`PLAYER_WALK.md`).

**The spec.** One verb carrying the whole desired set, diffed by the plugin
against the live store; a report whose two interesting fields are the ways a push
looks like it worked and did not (`unresolved`, `pending`); drift as a report
rather than an action; and the permission hooks as a live SIGNAL rather than the
record — a hook that stops firing costs latency, not correctness.

**The finding the design turns on, written where it belongs.** A name in the store
that is not in the desired set is either something the site retired or something a
human granted, and those have opposite correct answers. The store records who
granted a permission nowhere, so only the website can tell them apart — which is
why it keeps a ledger of what it pushed, and why revoking a hand edit needed a
table of its own.

**§10.5 is a rule generalising.** "A wedged sidecar must never stall the game"
becomes "nothing the far side sends may cost the main thread unbounded work",
because `perm.sync` is the first command whose work is not bounded by its own
shape. Three bounds, each on the side that can say something useful when it is hit.

**§20.7 says plainly what is not proven**: the acceptance line needs a second,
non-admin Steam account on the rig, and nothing in the plugin has been compiled.
The walk doc carries the seven steps, including the two things to confirm on
Carbon rather than assume.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-21 22:59:24 -05:00
4fe8864939 Merge pull request 'docs(modules): phase 6 as built — identity, and the sentence a player could not see' (#258) from docs/rust-phase-6 into main
Reviewed-on: #258
2026-09-21 22:24:42 +00:00
e35880e713 docs(modules): phase 6 as built — identity, and the sentence a player could not see
Protocol 3 in PROTOCOL.md §9, the identity walk in PLAYER_WALK.md, what an
operator needs in INTEGRATION.md, and PLAN.md §19.

Seven org-lead decisions (§19.0): /link is chat and its reply is private, codes
live in plugin memory as the UO bridge does, an alphabet with no O/0/I/1, a
Steam id another account holds is refused rather than moved, the website asks
EVERY server because a code does not say which one minted it, staff can sever a
link, and the activity-row overflow belongs to core.

§19.3 is the finding worth reading: a slot router is not registered under a tier,
so this repo own OpenAPI generator described two routes fewer than the module
serves — internally consistent, and wrong. The frozen-manifest job catches it,
which was verified by deleting the two paths and watching it fail.

§19.4 is what a browser found and 122 green tests did not. Core request
primitive reads data.message; this module has answered { error } since phase 1,
so every refusal this phase exists to write rendered as Service Unavailable.

The code-from-the-game half is written down rather than claimed: a code reaches
a player and nobody else, so no console can read one (D27).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
2026-09-21 09:06:51 -05:00
54b4059091 Merge pull request 'docs(modules): phase 5 as built — Android leg A, and the capability a client had to be given' (#257) from docs/rust-phase-5 into main
Reviewed-on: #257
2026-09-17 09:21:44 +00:00
dfdb0a3f63 docs(modules): phase 5 as built — Android leg A, and the capability a client had to be given
module-rust's surface gets its second client. `modules/rust/PLAN.md` §18 records
the phase; `android/PLAN.md` M14 records the app's half, as every Android
milestone does.

The decision worth the most words is D16. This module declared five capability
strings and every one named a SURFACE — `servers`, `killfeed`, `leaderboard`,
`presence`, `wipes` — while a client gating a navigation group needs one that
names the MODULE. Core flattens every started module's capabilities into a single
list, so `servers` is a word another module could declare tomorrow and silently
reveal these screens on a site that does not run Rust. Gating on the module `id`
was considered and rejected in as many words: `id` is a mount prefix, §2.9
forbids inferring a route from a capability, and letting a client gate on `id`
makes the two the same value in practice.

Also recorded: D17 (poll while RESUMED — the phone's Page Visibility gate), D18
(the Rust repositories move to `edge`, releases at the cutover), D19 (the drawer
badge, and NavPaths learning `/rust`), why D15's footer slot had to be translated
rather than copied, and §18.4's three defects — none of which a green suite of
644 could see, because each is about what a screen looks like or when a number is
re-read.

§18.6 is deliberately short and honest: the website's own pages have still not
been read at phone width, and the badge's non-zero case was shown with a seeded
count rather than by people playing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-17 03:45:01 -05:00
2f24236993 Merge pull request 'docs(modules): phase 4 as built — the first pages, and the four defects a browser walk found' (#256) from docs/rust-phase-4 into main
Reviewed-on: #256
2026-09-17 02:42:51 +00:00
788100e048 docs(modules): phase 4 as built — the first pages, and the four defects a browser walk found
Records PLAN.md section 17 and marks the phase row done. Four decisions (D12-D15),
what is on the pages, and the four defects only a live walk could find — two of
them in code phase 3 had already shipped: an unreachable refresh that erased the
server's description, and a "last reported" line reading the timestamp of our own
poll rather than of the server's last frame.

Also written down: why core's useAsync cannot poll, the real per-page cost of a
live count in the footer slot, and the test fake that was *nearly* core.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-16 21:40:39 -05:00
a221d4409b Merge pull request 'docs(rust-link): protocol 2 — the read path, and phase 3 as built' (#255) from docs/rust-protocol-2 into main
Reviewed-on: #255
2026-09-16 16:36:42 +00:00
f80b9f95c8 docs(modules): the ingest walk, and the two-writer trap it walked into
The module half exercised against the live rig rather than only its own tests:
the working tree installed into a running core, pointed at the workstation
sidecar with a real Rust server behind it. The fresh-install path logged
`cursor started at the feed tail`, a console banid/unban arrived as two
rust_events rows carrying the wipe id, and the wipe row was created by being
mentioned rather than by any "a wipe started" call.

Then the boundary on real rows: with both ban events in the table, the public
events route answered {"events":[]} — and answered the same when asked for
player.banned BY NAME.

The trap is worth more than the proof. The state row read as online=1 with
hostname=NULL, a shape no code path writes. Two cores shared one database: a
second instance still held the phase 2 release in memory, spoke protocol 1, was
refused 409, and rewrote the row every thirty seconds. Nothing was wrong with
either. What made it look like a defect was two SELECTs in two round trips
assuming the state did not move between them — the same mistake the Pterodactyl
work recorded, and a single atomic read caught the coherent row alternating with
the other writer's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-16 08:52:48 -05:00
30e72adfcf docs(rust-link): protocol 2 — the read path, and phase 3 as built
The specification the other three repositories are held against, plus the phase
record.

`PROTOCOL.md` §8 is the new contract. Its centre is one field: every frame now
carries `type` — `event`, `snapshot`, `reply`, `control` — and the sidecar files
on that and nothing else. That is the dumb-forwarder property made structural
rather than intended: ten new event kinds are zero change in Rust-Link, and only
a version adding an indexed column touches it at all.

Also in §8: the fifteen-kind catalogue and what each frame carries; `wipeId`
derived by the plugin, which REVERSES §3.2's "deriving one is the website's job"
and says why; boards re-sent on connect and on a cadence; the aggregate rule (a
hook that can fire more than once a second per player is a counter, not an
event); the void rule that stops a read-path hook vetoing a death or a login; and
`GET /feed`, a cursor route separate from `/events` because one route with two
orderings serves the wrong one to every caller that forgets the parameter.

§8.5 is the part to read twice. The classification of a kind as public or staff
is NOT on the wire, deliberately: a boundary declared by the sender is one a
compromised or out-of-date game host can widen, so the module holds a
default-deny allowlist and this table is what its test holds it against.

§8.8 corrects a catalogue rather than a defect: PLAN.md §10 sources
`rust.login.denied` from `CanUserLogin`, and that hook fires on every attempt —
the only way to learn of a denial from it is to be the denier. A denial is the
absence of an approval, and protocol 2 emits both facts so phase 10 can pair them.

`PLAYER_WALK.md` is new, and it exists because half this catalogue cannot fire
without somebody holding a mouse. Ten steps, what each one should produce, and
what counts as a pass — written so the walk can be run without watching the
output live, and so the answer afterwards is readable as a transcript.

PLAN.md §16 is phase 3 as built: the four decisions, the two defects only a
server that BOOTED with the plugin could find (a wipe id that was null for every
real session, and a two-second main-thread stall on unload), what was proven and
how, and — stated plainly rather than implied — the three measurements still
queued on the org lead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-16 08:39:27 -05:00