fix(bridge): the last fixes' bridge half (W3, W9, W12) #43

Merged
whitlocktech merged 1 commits from fix/last-fixes-bridge into edge 2026-10-21 19:35:51 -05:00
Member

What & why

Stage 3 of docs/modules/rust/PLAN_LAST_FIXES.md (docs#366): the bridge's fixes. W3's module half is already in Module-Rust#55.

# Fix
W3 Calling the Travelling Vendor while one is on the map answers world.error with reason already-out ("a Travelling Vendor is already out, and the game runs one at a time; nothing was called"). Before, it answered "called 1" and spawned nothing. The refusal is not counted against the run's world-call budget and is not kept under its key, so a retry checks again. Module-Rust#55 reads it as called: 0 with a note.
W9 A rolled-back RaidableBases profile write now carries RaidableBases' own log entry for the file instead of the last 8 KB of the server log. The bridge marks the log's position when the write starts. On rollback it reads from that mark, picks RaidableBases' entries that name the failed profile, and keeps the path and the exception's message without the stack. Both log formats are read: Oxide's 06:50 [Info] [RaidableBases] … and Carbon's [2026.10.21 18:54:35] [INFO] [RaidableBases] …. If no entry names the profile, its other entries since the write are used. If it logged nothing, the log is empty and the reason line stands alone. A reload that misses the 30 s ceiling also reads RaidableBases' entries, not the tail. Ordinary config writes still use the tail.
W12 raid.ended carries the base's id, and its runId and key, when a run made it, as PROTOCOL §20.12 already says. When RaidableBases ends a run's base itself, the record supplies them. A teardown takes the base off the record before its despawn raises Ended, so the live base now keeps its run and key too (set at Started, and at a hotload's re-seed).

No protocol bump. W3's reason is a new value of an existing field, and W12 sends fields PROTOCOL already lists. The docs (PROTOCOL's already-out, and the plan's status) come in stage 5, as the plan says. Rust-Link needs nothing: it forwards the reply as it is.

How it was tested

Builds: Rust 25902425, Oxide 2.0.7830, Carbon 2.0.262 (each the latest today). This branch compiled and loaded on both rigs. The walk site at :3270 was used, still on Module-Rust stage 1.

  • node scripts/checkPlugin.js: protocol 14, 89 hooks, all void and listed. checkPlugin.test.js passes.
  • W3, Oxide (run 78): two vendor steps in one phase. The first called 1. The second got already-out with the message above. The walk site still runs stage 1's module, so it retried instead of reading called: 0. Stage 2 has that half and is merged, but it is not loaded on the walk site.
  • W3, Carbon (run 81): a vendor was already out, so the first step got already-out at once.
  • W9, both rigs: a site save of Easy Bases with "Difficulty Level": "not a number" was rolled back and restored. The outcome's log is now exactly RaidableBases' entry:
    18:54 [Info] [RaidableBases] /home/container/oxide/data/RaidableBases/Profiles/Easy Bases.json
    Newtonsoft.Json.JsonReaderException: Could not convert string to integer: not a number. Path '['Difficulty Level']', line 3, position 36.
    Carbon's is the same, with its own timestamp.
  • W12, Oxide, teardown (run 79): a run's Easy base opened, then the run was cancelled. The cleanup reverted it, and the stored raid.ended carries id: raid-1792608907103-1, runId: "79" and the key. Bases no run made still carry none.
  • W12, Oxide, its own timer (run 80): a run's Easy base with a one-minute despawn. RaidableBases ended it, and the bridge sent world.expired (what: raidbase) and then raid.ended, both with id: raid-1792609042245-2, runId: "80" and the key. The run log shows resource.expired.

Both rigs still run this branch. It is edge plus these three fixes.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • No AI tools were used to produce this contribution.
  • AI tools were used. Tool(s): Claude Code (Claude Opus 5.5). I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a Co-Authored-By / Assisted-By trailer.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY

## What & why Stage 3 of [`docs/modules/rust/PLAN_LAST_FIXES.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/modules/rust/PLAN_LAST_FIXES.md) (docs#366): the bridge's fixes. W3's module half is already in Module-Rust#55. | # | Fix | |---|---| | **W3** | Calling the Travelling Vendor while one is on the map answers `world.error` with reason **`already-out`** ("a Travelling Vendor is already out, and the game runs one at a time; nothing was called"). Before, it answered "called 1" and spawned nothing. The refusal is not counted against the run's world-call budget and is not kept under its key, so a retry checks again. Module-Rust#55 reads it as `called: 0` with a note. | | **W9** | A rolled-back RaidableBases profile write now carries **RaidableBases' own log entry** for the file instead of the last 8 KB of the server log. The bridge marks the log's position when the write starts. On rollback it reads from that mark, picks RaidableBases' entries that name the failed profile, and keeps the path and the exception's message without the stack. Both log formats are read: Oxide's `06:50 [Info] [RaidableBases] …` and Carbon's `[2026.10.21 18:54:35] [INFO] [RaidableBases] …`. If no entry names the profile, its other entries since the write are used. If it logged nothing, the log is empty and the reason line stands alone. A reload that misses the 30 s ceiling also reads RaidableBases' entries, not the tail. Ordinary config writes still use the tail. | | **W12** | `raid.ended` carries the base's `id`, and its `runId` and `key`, when a run made it, as PROTOCOL §20.12 already says. When RaidableBases ends a run's base itself, the record supplies them. A teardown takes the base off the record *before* its despawn raises `Ended`, so the live base now keeps its run and key too (set at `Started`, and at a hotload's re-seed). | **No protocol bump.** W3's reason is a new value of an existing field, and W12 sends fields PROTOCOL already lists. The docs (PROTOCOL's `already-out`, and the plan's status) come in stage 5, as the plan says. Rust-Link needs nothing: it forwards the reply as it is. ## How it was tested Builds: Rust 25902425, Oxide 2.0.7830, Carbon 2.0.262 (each the latest today). This branch compiled and loaded on both rigs. The walk site at `:3270` was used, still on Module-Rust stage 1. - `node scripts/checkPlugin.js`: protocol 14, 89 hooks, all void and listed. `checkPlugin.test.js` passes. - **W3, Oxide (run 78):** two vendor steps in one phase. The first called 1. The second got `already-out` with the message above. The walk site still runs stage 1's module, so it retried instead of reading `called: 0`. Stage 2 has that half and is merged, but it is not loaded on the walk site. - **W3, Carbon (run 81):** a vendor was already out, so the first step got `already-out` at once. - **W9, both rigs:** a site save of `Easy Bases` with `"Difficulty Level": "not a number"` was rolled back and restored. The outcome's `log` is now exactly RaidableBases' entry: `18:54 [Info] [RaidableBases] /home/container/oxide/data/RaidableBases/Profiles/Easy Bases.json` `Newtonsoft.Json.JsonReaderException: Could not convert string to integer: not a number. Path '['Difficulty Level']', line 3, position 36.` Carbon's is the same, with its own timestamp. - **W12, Oxide, teardown (run 79):** a run's Easy base opened, then the run was cancelled. The cleanup reverted it, and the stored `raid.ended` carries `id: raid-1792608907103-1`, `runId: "79"` and the key. Bases no run made still carry none. - **W12, Oxide, its own timer (run 80):** a run's Easy base with a one-minute despawn. RaidableBases ended it, and the bridge sent `world.expired` (`what: raidbase`) and then `raid.ended`, both with `id: raid-1792609042245-2`, `runId: "80"` and the key. The run log shows `resource.expired`. Both rigs still run this branch. It is `edge` plus these three fixes. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [ ] No AI tools were used to produce this contribution. - [x] AI tools were used. Tool(s): `Claude Code (Claude Opus 5.5)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` / `Assisted-By` trailer. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
wtclaude added 1 commit 2026-10-21 13:59:44 -05:00
fix(bridge): the last fixes' bridge half (W3, W9, W12)
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 14s
38f854d580
Stage 3 of docs/modules/rust/PLAN_LAST_FIXES.md.

- W3: a Travelling Vendor call while one is on the map answers world.error
  reason `already-out` instead of "called 1" with nothing spawned. Not
  counted against the run's budget and not kept under its key, so a retry
  looks again. Module-Rust#55 reads it as called 0.
- W9: a rolled-back RaidableBases profile write carries RaidableBases' own
  log entry for the file (its path and the exception's message, without the
  stack), read from the log since the write began, instead of the last 8 KB
  of the server log. Its other entries since the write stand in when none
  names the profile, and nothing when it said nothing.
- W12: raid.ended carries the base's id, and its runId and key, when a run
  made it, as PROTOCOL §20.12 says. A teardown takes the base off the record
  before its despawn raises Ended, so the live base keeps its run and key too.

No protocol change: W3's reason is a new value of an existing field, and W12
sends the fields PROTOCOL already lists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
whitlocktech merged commit 3c0fcb0003 into edge 2026-10-21 19:35:51 -05:00
whitlocktech deleted branch fix/last-fixes-bridge 2026-10-21 19:35:52 -05:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/Rust-Plugins#43
No description provided.