fix(sidecar): protocol 13 — a configuration write no longer waits for its reload (F9)
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 3m48s

The plugin now answers config.write once the files are on disk and reports
the reload as a config.outcome event, which this process files and feeds by
its type like any other event. The reload window no longer has to fit
inside REPLY_TIMEOUT, so CONFIG_RELOAD_WINDOW and the test that asserted
the pairing are gone, and the 504 body stops pointing at a rollback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-09-26 17:08:37 -05:00
parent e9b6778b78
commit 522187ddd1
2 changed files with 27 additions and 46 deletions

View File

@@ -101,11 +101,9 @@ use tracing_subscriber::EnvFilter;
/// for the reload to announce itself, and **puts the old files back automatically** if it does
/// not.
///
/// Two things about that reach this process. The write is the only route here that causes a write
/// on the game host, and it is the only one whose reply routinely spends seconds rather than
/// milliseconds — the plugin holds the correlation open across a reload and, at worst, across a
/// rollback as well. `web::CONFIG_RELOAD_WINDOW` is that budget, mirrored from the plugin, and a
/// test asserts the pairing rather than trusting it.
/// The write is the only route here that causes a write on the game host. Since protocol 13 its
/// reply comes back as soon as the files are on disk, marked `pending`; how the reload went follows
/// later as a `config.outcome` event, which this process files and feeds like any other.
///
/// # Protocol 6 — first-party clans
///
@@ -165,10 +163,19 @@ use tracing_subscriber::EnvFilter;
/// keeps it, and positions are asked for while somebody is looking and never touch the database
/// (D111). Which layer a viewer may see is decided on the website, never here.
///
/// # Protocol 13 — the first player walk's fixes
///
/// Opened by the configuration save (the module's PLAN_FIXES.md F9, D177): `POST /config/write`
/// answers `pending` at once instead of holding the RPC across a reload, and the outcome arrives
/// as a `config.outcome` event. Nothing new to route — an event is filed and fed by its `type`,
/// whatever its kind — so what changes here is what no longer has to fit: the reload window that
/// had to sit inside [`rpc::REPLY_TIMEOUT`] is gone.
///
/// `docs/rust-link/PROTOCOL.md` is the specification — §8 the read path, §9 identity, §10 the
/// mirror, §11 configuration, §12 clans, §13 the raid frame, §14 the leases, §15 the world verbs,
/// §16 the rewards, §17 the map, §18 the optional mods; this constant is one of its four declaration sites.
pub const PROTOCOL_VERSION: u32 = 12;
/// §16 the rewards, §17 the map, §18 the optional mods, §19 the walk's fixes; this constant is one
/// of its four declaration sites.
pub const PROTOCOL_VERSION: u32 = 13;
fn main() -> anyhow::Result<()> {
let args = match cli::parse(std::env::args().skip(1)) {