Commit Graph

87 Commits

Author SHA1 Message Date
fa53526079 docs(rust): record the org lead's answers to the step-3 plan (D188-D198)
Groups are per server unless an admin shares them (D189); an in-game
change affects that server only, as an exception or a split (D190);
ZoneDomes stays, made safe by a domes helper (D194); presets are the
admins' own (D195); zone and reward messages get the popup choice
(D193); the NPC spike tries both routes (D197). The rest confirm the
plan: D188, D191, D192, D196, D198.

Refs RunicGateway/Module-Rust#21

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-27 03:56:43 -05:00
a430666f94 docs(rust): plan the six step-3 redesigns in one document
PLAN_REDESIGNS.md plans PLAN_FIXES §6 step 3 in detail, before any code:
the permission manager, the event step editor and kit weekend, zones and
domes, map marker types, the 23 title conditions, and NPCs. Checked on
both rigs first: the public owner lookup for permissions, the mission
hooks both frameworks already raise, and ZoneDomes' null-player throw.
Eleven questions for the org lead (§10) become D188 onward.

Refs RunicGateway/Module-Rust#21

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-27 03:45:44 -05:00
1891f4f6fd docs(rust): the step-2 player walk, and D186-D187
PLAYER_WALK's step-2 rows 3-9 walked with the org lead in the game on
both rigs (2026-09-27). Records the results, corrects four rows (the
helper is unloaded, not deleted; no enter message can show; sleepers do
not score; ZoneManager's own entry counted the player anyway), and adds
D186 (a link code's second pass skips servers known down) and D187 (no
permission sync to a server the poll saw go away) with F6, F7 and F12's
as-walked notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-27 03:18:40 -05:00
383f3bdbe5 docs(rust): the step-2 site walk, and the run it found stuck pending
Walked on a core running Module-Rust#22 on website#209 against rust-oxide:
F8, F13/F14, F7, F5/F6 and the helper's state all pass. The expiry walk found
a run left cleanup-pending for ever when its last resource expires while it
runs; website#209 now settles it, and EVENTS.md §L says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-27 01:05:35 -05:00
a199823513 docs(rust): say which half of the step-2 walk rows was walked
Rows 1-2 of PLAYER_WALK's step-2 section had their game side walked on both
rigs; their site side (the servers-page warning, a grant landing within a
minute) needs a walk core running Module-Rust#22 on website#209, which the
first commit claimed as walked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 21:48:18 -05:00
1a7f52743f docs(rust): protocol 13 step 2 — expiry, plugin loads, the zone helper, the tally (§19.4-19.8, MODULE_API 1.11.0)
The spec for PLAN_FIXES §6 step 2, as built (D181-D185):

- PROTOCOL.md §19.4 world.expired's `what` and the website recording an
  expiry (amends §15's "maps it to nothing"); §19.5 plugin.loaded /
  plugin.unloaded with the permission diff; §19.6 the ZoneManager helper and
  `zoneHelper` at hello; §19.7 what the tally counts (F1, F3, F4); §19.8 the
  website (F7 hold, F5/F6 link fleet, F2 names).
- MODULE_API.md 1.11.0 and ctx.events.expired; EVENTS.md §L the `expired`
  status, terminal and green, and `resource.expired`.
- rust-link/INSTALL.md: the helper in the tarball, by hand, and in doctor.
- PLAYER_WALK.md: events step 6 can pass now; a step-2 section whose rows 1-2
  were walked on both rigs without a player and 3-9 need one.
- PLAN_FIXES §6: step 2 as built, with its PRs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 21:47:42 -05:00
e7551cbf8f docs(rust): plan fixes — D181-D185, how step 2 is built
Step 2 of PLAN_FIXES §6 had four open choices; the org lead answered them
before any code:

- D181/D182: F12 is a ZoneManager helper that Harmony-patches
  Zone.InitializeZone, ships in the overlay, and the bridge falls back to
  IsPositionInZone for scoring without it.
- D183: F14's expiry is core's: an `expired` ledger status and
  ctx.events.expired (MODULE_API 1.11.0), without disturbing Module-uo.
- D184: F8 is plugin.loaded / plugin.unloaded with the permission diff.
- D185: F2 is the site's labels; no wire change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 20:41:08 -05:00
b8d9740ed0 docs(rust): protocol 13 — the reload as the rigs showed it (W1-W5, D180)
PROTOCOL.md §19.1: how the reload is asked for (Carbon: c.reload on the
server console), which log is read (Carbon.Core.log on Carbon), the pinned
failure lines on both frameworks, a load confirmed by a log read, and the
compiler's give-up retried once. PLAYER_WALK.md: the Carbon reload path and
failure words as walked. PLAN_FIXES.md: D180.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 20:21:26 -05:00
d72ccd56dd docs(rust): plan fixes — D176-D179, how step 1 is built
F15 waits for protocol 13 (D176); F9 and F10 open that bump on edge in all
three repos (D177); a reload fails on the log's evidence under a 30 s
ceiling with a loaded check before any restore (D178); the configuration
page polls the write until it settles (D179).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 16:55:23 -05:00
0319f6b26e docs(rust): plan fixes — D175 titles are defaults admins can replace
The twenty-three title names in §4.6 are the module's defaults. An admin
can set their own title per category, once for the site, and it
supersedes the default on every server; clearing it restores the
default. A rule's own text still wins over both. §4.6 describes the
three layers on top of phase 17's rust_title_rules (stat grows from
three values to the twenty-three categories).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 16:34:54 -05:00
7743cec1fb docs(rust): plan fixes — D173 quests are Rust's own missions, D174 title rules
D173: "Quests completed" (Wayfarer) counts the missions Rust's NPCs
already hand out; no quest plugin. uMod's catalogue names no mission
hook and CARBON.md lists none, so the detailed plan starts with a rig
spike: a framework hook if one exists at build time, else reading the
player's mission list at each tally flush, else a D168 helper patch.
D174 adopts §4.6's recommended title rules (best columns for kill
distance, weapon-class kills count every credited kill, killing-blow
credit for APC/heli, heals of others only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 16:32:38 -05:00
7834ef1a88 docs(rust): plan fixes — D169-D172, the org lead's answers
D169 every fix and redesign lands before Module-Rust's cutover. D170 an
expired zone is marked expired on the site (F14 moves from "by design"
to a fix, amending D96). D171 Steam sign-in moves to the website's own
plan as part of the base website. D172 chat titles use all twenty-three
listed conditions under new names: §4.6 is now a table of condition,
title and the hook that feeds it, plus what the detailed plan must
settle (best-value columns, weapon classes, vehicle-kill credit, heals
of others, quests). PLAN.md §35 and the rust README follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 16:27:52 -05:00
c0d6cab0e9 docs(rust): plan fixes — the first player walk's findings, gating the cutover
PLAN_FIXES.md plans what the Oxide pass of PLAYER_WALK.md found on
2026-09-26: fifteen fixes (F1-F15, F15 corrupts every non-ASCII
site-to-game string including config saves; F9 rolls back valid config
edits on a cold compile), the interface and walk-doc corrections, and the
org lead's decisions D159-D168 (D160 reverses D31: the site owns every
permission and group). Recommends the fixes land before Module-Rust's
cutover (phase 19) and the redesigns follow it.

PLAN.md gains a pointer in its status line and §35; the rust README lists
the new file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 16:20:42 -05:00
7505ee9ba7 docs(rust): §34.5 — step 6 on Carbon and step 7 on Debian 12, both on releases
Rust-Link v0.1.3 (bundle 2026.09.26.5) walked on the egg-carbon server by a
REGEN reinstall; installer v0.3.1 walked on Debian 12. Records installer#34.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 10:10:35 -05:00
85d52c69dc docs(rust): §34.5 — steps 6-7, the Carbon launcher, and the glibc floor (D158)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 04:47:49 -05:00
42419c1bfa docs(rust): PLAN §34.5 — as built, D154-D157, and what the walk found
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-26 04:14:13 -05:00
9e4b7bcbbd docs(rust): phase 18 plan of record — the installer and the egg (PLAN §34, D145–D153)
Rust-Link and Rust-Plugins release and cut over here; bundle schema 2 for
both games beside schema 1; named Rust instances in the installer; a
Windows service for the sidecar; the plugin's server id from the
environment; the egg with a wipe guard and a pinnable bundle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 22:33:58 -05:00
a5d918207b docs(rust): phase 17 as built and walked — protocol 12, D144 (PLAN §33.5-§33.7, M19)
- PLAN.md §33.5 as built (D144: the plugin keeps its titles on disk, after
  the walk found a hot reload emptied them), §33.6 the walk on both rigs,
  §33.7 findings; the phase row marked built.
- PROTOCOL.md §18: titles.set, a group's BetterChat style on perm.sync,
  chat.say delivery and format, integrations, rg.titles, POST /titles. The
  header's current version moves from a stale 10 to 12.
- PLAYER_WALK.md: the steps that need a person in the game.
- android/PLAN.md M19 as built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 18:25:43 -05:00
06c06e7bcb docs(rust): phase 17 plan of record — BetterChat and popups (PLAN.md §33, M19)
The optional-integration tier (R15), with the org lead's decisions D134-D143:
BetterChat titles from operator rules (also on the web and in the app), all
twelve chat fields on a site-authored group under R2's drift posture, that
style as the voice of news and event lines, and PopupNotifications made
optional as a delivery choice. Protocol 12.

The uMod Clans adapter is dropped (D134). R5's claim that the plugin has no
read API is corrected (a second grep artefact), and D54's promised
leadership sharpening is withdrawn: OnClanUpdate is the plugin's own clans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-09-25 14:53:07 -05:00
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
5274d5a744 docs(modules): phase 2 as built — packaging, release and the frozen manifest
PLAN.md gains §15 and the phase-2 row is marked done.

What the phase found worth recording:

- The starting position was worse than the row implied: phase 1 built five
  guards and ran every one by hand, because the repo had no .gitea/workflows at
  all. So the org lead widened the phase to include the gate, not only the
  release (D4), and the frozen-manifest job shipped with it rather than waiting.
- That job answers a question §13 had to take on trust. Core mounts /status and
  /version at a tier root where the loader's collision probe cannot see them, so
  phase 1 could only check /rust by reading. Locally and in CI, against the same
  pinned core: 280 core routes, 6 added, all documented, none of core's moved.
- The bundle carries no node_modules (D5), and checkBundle.js asserts the
  emptiness rather than assuming it — the day a dependency appears is meant to
  be a loud day. Verified by breaking the include list.
- No Sonar for the three Rust repos until phase 19 (D6).
- The criterion is met. v0.1.0 published, downloaded, hashed independently
  (7296c76b… matches the manifest), and installed from its manifest URL through
  Admin → Modules into a core with the phase-1 directory and row torn down
  first. The volume received exactly the twenty files the include list names;
  the row reads started with a source and a sha where phase 1's had nulls; the
  public route answers 200, the player and admin tiers 401, and all five /rust
  paths merged into core's own spec.
- REGISTRY_TOKEN was already configured — the one prerequisite this work could
  not check for itself, since the bot can read no Actions secrets.
- One rig finding: Docker Desktop's Linux engine was found dead and answered
  every call with a bare 500, which presents as the website being broken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-16 05:42:36 -05:00
22159ec78f docs(modules): the Carbon rig, R19 proven, and one refuted claim
rust-carbon (id 18, 87fb1f67) is built on the same egg with FRAMEWORK=carbon,
a clean install rather than a converted one. Install 122s, boot 543s.

R19 is proven. The byte-identical RunicGateway.cs that runs on the Oxide rig,
with no conditional compilation in it at all, loaded on Carbon 2.0.259.0 and
behaved identically - same startup line, same no-stall retry against an absent
sidecar. That contract now holds on three platforms from one source file:
Windows/Mono, Linux/Oxide, Linux/Carbon.

R18's amendment is confirmed the best way it could have been. The plugin's own
config, written by the same Oxide-compat API on both rigs, landed at
oxide/config/RunicGateway.json on one and carbon/configs/RunicGateway.json on
the other. Had the R18 editor used a literal path it would not have found its
own plugin's config on half of all installs, and no test would have caught it.

One claim is REFUTED, and it was wrong about Oxide as well as Carbon. CARBON.md
said Oxide stores permissions as JSON and Carbon as Protobuf or SQLite. Both
rigs say otherwise: both store Protobuf, under IDENTICAL filenames
(oxide.users.data, oxide.groups.data), differing only in directory - Carbon
writes its own data into files named after Oxide. This strengthens R2's
API-only rule rather than weakening it: a file reader would have worked on both
rigs today and broken silently for the one operator who ran c.migrate_perms_sql.

Two things nobody had thought to claim, found by looking. Carbon auto-creates a
third default group, moderator, which R2's full-set push must tolerate or
report drift for ever. And c.plugins exposes per-plugin hook telemetry that is
most of section 6's fired-hook mechanism, free, and only on Carbon.

Also: a wrong console command is indistinguishable from success at the API.
Pterodactyl's command endpoint returns 204 either way and Carbon prints nothing
for an unknown command, so oxide.plugins on Carbon looks exactly like it
worked. Anything driving the console must read a log to know.

CARBON.md gains a scorecard (section 10) and drops its unproven banner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 21:51:11 -05:00
069e715b1b docs(modules): the Pterodactyl rig as built, R22, and a correction
Section 14 records R21's first rig, made with the application key and driven
with the client key. Both work; neither can do the other's job, and there is
no egg-write endpoint at all, so a published egg is a JSON file a human
imports.

The tier-2 loop was run rather than described: phase 1's real RunicGateway.cs
pushed from the working tree, oxide.reload through the client API, the edit
observed in Oxide's own log, source restored. About ten seconds end to end.
Three things worked that were not certain to - files/write creates missing
parents, a plugin placed before Oxide exists survives Oxide arriving, and the
plugin compiles and loads on Linux, which no previous phase had established.

Two findings that change decisions. The image installs the framework on EVERY
boot, Carbon from the rolling production_build tag and Oxide from
releases/latest, so a restart is a framework upgrade and neither is pinnable
through the egg. And R20's "wrapper launches the sidecar then RustDedicated"
does not survive Carbon: the entrypoint prepends LD_PRELOAD to the whole
startup string, so the preload would land on the sidecar and the server would
start cleanly, report nothing, and be silently unmodded.

R22 (org lead): the sidecar's configuration moves into the egg's variables.
Nearly free - rust-link already reads all five keys from the environment with
env-over-file-over-defaults precedence - but the game bind must not be
operator-editable, the web bind must derive from an allocation, and the db
path must not be able to agree with REMOVE_FILES.

Also corrects an earlier claim in this branch. The client key listing zero
servers and includes returning empty were both CORRECT; the servers were
being deleted between reads. A differential diagnosis across two API calls
assumes the state did not move between them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
2026-09-15 21:30:06 -05:00