From b8d9740ed0e095641b0bc978737723fe2d7f5fac Mon Sep 17 00:00:00 2001 From: wtclaude Date: Sat, 26 Sep 2026 20:21:26 -0500 Subject: [PATCH] =?UTF-8?q?docs(rust):=20protocol=2013=20=E2=80=94=20the?= =?UTF-8?q?=20reload=20as=20the=20rigs=20showed=20it=20(W1-W5,=20D180)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY --- modules/rust/PLAN_FIXES.md | 3 ++- rust-link/PLAYER_WALK.md | 14 +++++++----- rust-link/PROTOCOL.md | 46 ++++++++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/modules/rust/PLAN_FIXES.md b/modules/rust/PLAN_FIXES.md index 05e93f9..20327d7 100644 --- a/modules/rust/PLAN_FIXES.md +++ b/modules/rust/PLAN_FIXES.md @@ -1,7 +1,7 @@ # `module-rust` — plan fixes **Status:** plan, approved 2026-09-26; its open questions were answered the same day (D169–D175), and step 1's -shape was settled as work began (D176–D179). **Everything in it — fixes and redesigns alike — lands before Module-Rust's cutover +shape was settled as work began (D176–D179), and its rig walk's fixes by D180. **Everything in it — fixes and redesigns alike — lands before Module-Rust's cutover (phase 19, [`PLAN.md`](PLAN.md) §34, D145; D169).** Everything here comes from the first walk of [`PLAYER_WALK.md`](../../rust-link/PLAYER_WALK.md) with a real player in the game — the Oxide pass, walked by the org lead on the `rust-oxide` rig with every frame checked on the console, the sidecar and the site's @@ -63,6 +63,7 @@ Taken by the org lead during and straight after the walk. | **D177** | **F9 and F10 open protocol 13.** They are built first, on `edge` in Rust-Plugins, Rust-Link and Module-Rust; the rest of §6 step 2 joins the same bump, and all of it releases together. Rejected: F9 alone as protocol 13 with the rest as 14; and a wider window now as a stop-gap. | | **D178** | **A reload fails on evidence, not on a clock.** While a configuration reload is pending the plugin reads the framework's new log lines each second and rolls back the moment they show the target plugin failing to compile or initialise. The ceiling is 30 s; when it passes, the plugin checks whether the target is loaded (a hook it missed) before restoring anything, and reports what actually loaded (F10). A framework hook for a failed load, if the rig shows one, replaces the log read. Rejected: the clock alone with a longer ceiling, which leaves a broken plugin down for the whole ceiling. | | **D179** | **The configuration page polls the write.** The save is recorded as `reloading`; ingest settles that row from the outcome frame, and the page polls it every couple of seconds until it does. Rejected: pushing the outcome over the admin event stream. | +| **D180** | **The step-1 rig walk's fixes stay inside the bridge, and the console is a fair way in.** The walk (2026-09-26) found Carbon's Oxide-compatible `ReloadPlugin` does not reload (W3), Carbon's log is `Carbon.Core.log` (W4), Carbon loads a plugin whose config threw and raises `Loaded` anyway (W5), Oxide's "Could not initialize plugin" line was missed (W2), and Oxide's idle compiler drops a reload with "Timed out waiting for plugin to be compiled" (W1). All are fixed in `RunicGateway.cs` (PROTOCOL.md §19.1), never by changing a third-party plugin. Running server console commands (`c.reload`) is approved, and so is a helper plugin that hooks and runs console commands where one is needed (D168). | ## 2. Fixes diff --git a/rust-link/PLAYER_WALK.md b/rust-link/PLAYER_WALK.md index ed52699..d82c5a7 100644 --- a/rust-link/PLAYER_WALK.md +++ b/rust-link/PLAYER_WALK.md @@ -218,9 +218,10 @@ other, which is the whole point of putting them in one container. **Run it on both frameworks.** From phase 3, done means done on Oxide and on Carbon (R19/R21), and this phase has two specific things to confirm rather than assume: -- **The reload path.** The plugin asks `Interface.Oxide` for `ReloadPlugin` by reflection and falls - back to a console command — `c.reload` on Carbon, `oxide.reload` on Oxide, chosen by looking for a - Carbon assembly at runtime. A wrong prefix on Carbon prints **nothing at all**, which looks +- **The reload path.** On Oxide the plugin asks `Interface.Oxide` for `ReloadPlugin` by reflection + and falls back to `oxide.reload`; on Carbon it runs `c.reload` on the server console, because + Carbon's Oxide-compatible `ReloadPlugin` unloaded Kits and never brought it back on the 2026-09-26 + walk (W3, PROTOCOL.md §19.1). A wrong prefix on Carbon prints **nothing at all**, which looks exactly like a command that worked (`CARBON.md` §5), so the proof is `OnPluginLoaded` arriving, not the command being accepted. - **`OnPluginLoaded` / `OnPluginUnloaded` firing at all.** They are the rollback's only evidence. If @@ -228,8 +229,11 @@ this phase has two specific things to confirm rather than assume: plugin then has to judge by whether the target is loaded (PROTOCOL.md §19.1). `rg.hooks` at the console is the standing answer: both names are in `ExpectedHooks`, so a framework that never raises one shows a zero. - **The failure words.** Since protocol 13 a broken reload is recognised by the framework's log line - (PROTOCOL.md §19.1). Step 4 on Carbon is what pins Carbon's wording: if it waits the full 30 seconds - before rolling back, the line Carbon printed is not on the list yet. + (PROTOCOL.md §19.1), read from `Carbon.Core.log` on Carbon — `rg.config` prints the file (`log=`). + Step 4 pinned Carbon 2.0.259's wording on 2026-09-26: `[Kits] Failed ILoadConfig (…)`, after which + Carbon loads the plugin **anyway**, broken. The rollback must still happen and the reason must quote + that line; if a save waits the full 30 seconds before rolling back, the line Carbon printed is not on + the list. **What counts as a pass:** a setting typed on the website changes what the running game does; a deliberately broken config leaves the plugin loaded and the operator holding the reason; and no file diff --git a/rust-link/PROTOCOL.md b/rust-link/PROTOCOL.md index e8c2160..6ecf906 100644 --- a/rust-link/PROTOCOL.md +++ b/rust-link/PROTOCOL.md @@ -1987,13 +1987,41 @@ depended on timing (F10). - A second write while one is pending is still refused `busy`. The window is longer now, so `busy` is more likely, and a website should hold its save button while it waits. -**Failing on evidence (D178).** While a reload is pending the plugin reads the framework's newest log -file once a second, from where it stood when the reload was asked for. A line that names the target as -a whole word (`Kits`, `Kits.cs`, `'Kits v4.4.9'`, never `KitsExtended`) beside one of *error while -compiling*, *failed to initialize*, *failed initializing*, *failed to compile*, *failed compiling*, -*failed to load*, *failed loading* or *unable to load* is a failure, and the edit is rolled back at -once. The bridge's own lines are skipped. A slow compile logs nothing until it succeeds, so it is simply -waited for. The Carbon pass of the re-walk pins Carbon's wording. +**How the reload is asked for.** On Oxide, through `Interface.Oxide.ReloadPlugin` (found by reflection), +falling back to `oxide.reload ` on the server console. **On Carbon, always `c.reload ` on the +server console** — the command an operator types at the panel. Carbon 2.0.259's Oxide-compatible +`ReloadPlugin` is not a reload: on the rig one call unloaded Kits and never compiled it again, and the +next did nothing at all (walk finding W3, 2026-09-26). + +**Failing on evidence (D178).** While a reload is pending the plugin reads the framework's log once a +second, from where it stood when the reload was asked for. On Oxide that is the newest `*.txt` in its log +directory; **on Carbon it is `Carbon.Core.log`**, chosen by name — `carbon/logs` holds five `*.log` +files and no `*.txt`, and its Harmony log is the one written most often (W4). `rg.config` prints the +file it follows. A line that names the target as a whole word (`Kits`, `Kits.cs`, `'Kits v4.4.9'`, +never `KitsExtended`) beside one of *error while compiling*, *could not initialize*, *failed to +initialize*, *failed initializing*, *failed to compile*, *failed compiling*, *failed to load*, *failed +loading*, *failed iloadconfig* or *unable to load* is a failure, and the edit is rolled back at once. The +bridge's own lines are skipped. A slow compile logs nothing until it succeeds, so it is simply waited for. + +Pinned on the rigs, for a config whose plugin's `LoadConfig` throws: + +| Framework | The line | Then | +|---|---|---| +| Oxide | `[Error] Could not initialize plugin 'Kits v4.4.9' (JsonReaderException: …)` | "Previous version of plugin failed to load"; the plugin is **not** loaded | +| Carbon 2.0.259 | `[ERRO] [Kits] Failed ILoadConfig (Could not convert string to double: …)` | "Loaded plugin Kits"; the plugin **is** loaded, broken | + +The first line carries the exception, so it is the one the outcome's `reason` quotes (W2). + +**A load is confirmed by a log read, not by the hook (W5).** Carbon loads a plugin whose config it could +not read and raises `OnPluginLoaded` in the same instant it logs the failure. So the hook is noted, and +the job settles on the first log read at least a second after it: a failure found there rolls back; none +found means the reload worked. The cost is about a second on every save. + +**The compiler giving up is not a failure of the file (W1).** Oxide shuts its compiler down after a +minute idle, and a reload asked for in that moment is dropped with `Timed out waiting for plugin to be +compiled: ` while the plugin runs on, loaded, on its old file. On that line the plugin asks for the +reload **once more** under a fresh ceiling (the compiler restarts on demand). A second such line settles +the job at once by what is loaded — the ceiling's judgement below, without waiting for the ceiling. **The ceiling, 30 s per phase (F10).** A reload that says nothing either way is judged by **what is loaded**, not by the clock: @@ -2026,8 +2054,8 @@ plugin is back. - **No outcome follows** if the bridge itself is unloaded while a write is pending. The files stay as written; the website calls the write lost after its deadline and re-reads. -`rg.config` shows a pending write's target, phase (`edit` or `restore`) and the seconds spent of the -ceiling. +`rg.config` shows the log file the plugin follows (`log=`), and a pending write's target, phase (`edit` +or `restore`) and the seconds spent of the ceiling. ### 19.2 The sidecar -- 2.49.1