fix(core): the last fixes' core half (W1 W2 W5 W19) #219

Merged
whitlocktech merged 1 commits from fix/last-fixes-core into edge 2026-10-22 01:18:26 -05:00
Member

What & why

Stage 4 of docs/modules/rust/PLAN_LAST_FIXES.md (docs#366): core's fixes, built to the org lead's decisions of 2026-10-22.

# Fix
W19 One module per site at boot, as at install. The first module directory by name holds the site, whether or not it then loads. Every other is recorded startup_failed at the manifest stage before any of its code is required, with the reason: this site already runs the module "rust", and a site runs one module. Remove "uo" or "rust" from the modules directory; the one that sorts first by name is the one that starts. Before, Module-uo and Module-Rust side by side failed the second with "extension slot … is already filled by "rust"". The org lead chose this over a clearer slot-collision message. Loader, lifecycle, schema and event-contract tests that loaded several fixture modules now load each case alone. The two module-against-module collision tests (prefix and table) are gone, because that case can no longer happen. The checks stay in the code as a second line behind the rule.
W1 A reconcile files a resource gone past its until as expired, not orphaned. It writes the same resource.expired line that ctx.events.expired() writes, and a finished run whose last row it was is marked complete. Before its until, or with none, gone is still orphaned. A row past its until that the game still has stays in force. Module-Rust#56 makes zones send until. No MODULE_API bump (org lead): until and reconcile's answer are unchanged.
W5 A dry run that passed on the draft counts for the version published from it. A passing draft dry run is kept with the sha256 of the validated spec's canonical JSON, in three new nullable columns on event_definitions. Publish stamps the new version verified, with that dry run's reviewer and time, when the spec it freezes has the same fingerprint, and writes version.verified on the occurrences it re-pins. An edit to the spec after the dry run means nothing carries over. A title edit does not change the spec, so the pass still carries. POST …/verify answers draftRecorded, and POST …/publish answers verified. The editor says kept, so publishing this draft unchanged makes a verified version and Published as v1. The dry run that passed on this draft counts for it.
W2 The run console says "Why this phase has not advanced" and "Phase p1: steps done, waiting to advance", not "has not started". The editor's hint about phase keys uses the same words.

OpenAPI regenerated (MODULES_DIR empty). It also picks up the Steam provider description from #218, which the committed spec had missed.

Docs come in stage 5, as the plan says: MODULE_API (one module at boot, until read by reconcile), EVENTS §K and §L, and BACKEND_DESIGN's three columns.

How it was tested

  • npm test (server): 2167 pass. routeManifest fails locally because of this machine's website/modules directory, and it fails on plain edge too. It passes with MODULES_DIR empty, which is what CI has. publicVersion failed once at file level in the parallel run and passes alone.
  • npm test (client): 430 pass. npm run build passes.
  • New tests: the one-module rule (refused before require, holds the site even when the first fails, a second never mounts, registers or claims a table, gets a failed row); W1 (past until gone → expired, before → orphaned, past but held → in force, last row completes the run, a later expired() finds nothing); W5 (pass carries, an edit breaks it, a title edit keeps it, findings keep nothing, re-pinned occurrences get the line); the fingerprint ignores key order but not array order.

Walked on the walk site (:3270, DB rustwalk, this branch with Module-Rust edge plus its W1 change), signed in in the browser as the walk admin:

  • W19: a scratch core on a scratch database with website/modules holding uo and rust. rust started. uo was refused with the message above, in the log and in its installed_modules row (startup_failed, manifest).
  • W5: event 88 was dry-run as a draft (kept, so publishing …), then published: Published as v1. The dry run that passed on this draft counts for it. No "not dry run" banner appeared, and version 75 has verified_at and verified_by from the dry run.
  • W2: run 82, phase p1 done and waiting 40 minutes: Why this phase has not advanced / Phase p1: steps done, waiting to advance.
  • W1, core restart (the original race): run 83 opened a one-minute zone on the Oxide rig (Rust 25902425). The walk core was stopped until the zone had expired in the game, then started again. Core's boot reconcile filed it expired at 05:57:24 with the line the game ended it at its deadline. There was no resource.orphaned line and no second resource.expired line. The core log has no "event resource expired" from the module's expired() path, which shows the reconcile did it.
  • W1, rig restart: run 82 opened a one-minute zone, and the rig was restarted at once. The game's own world.expired reached core first, because the module waits for the world to load before it reconciles. The log shows resource.expired only.

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 4 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): core's fixes, built to the org lead's decisions of 2026-10-22. | # | Fix | |---|---| | **W19** | **One module per site at boot, as at install.** The first module directory by name holds the site, whether or not it then loads. Every other is recorded `startup_failed` at the `manifest` stage before any of its code is required, with the reason: *this site already runs the module "rust", and a site runs one module. Remove "uo" or "rust" from the modules directory; the one that sorts first by name is the one that starts.* Before, Module-uo and Module-Rust side by side failed the second with "extension slot … is already filled by "rust"". The org lead chose this over a clearer slot-collision message. Loader, lifecycle, schema and event-contract tests that loaded several fixture modules now load each case alone. The two module-against-module collision tests (prefix and table) are gone, because that case can no longer happen. The checks stay in the code as a second line behind the rule. | | W1 | **A reconcile files a resource gone past its `until` as `expired`, not `orphaned`.** It writes the same `resource.expired` line that `ctx.events.expired()` writes, and a finished run whose last row it was is marked complete. Before its `until`, or with none, gone is still `orphaned`. A row past its `until` that the game still has stays in force. Module-Rust#56 makes zones send `until`. **No MODULE_API bump** (org lead): `until` and reconcile's answer are unchanged. | | W5 | **A dry run that passed on the draft counts for the version published from it.** A passing draft dry run is kept with the sha256 of the validated spec's canonical JSON, in three new nullable columns on `event_definitions`. Publish stamps the new version verified, with that dry run's reviewer and time, when the spec it freezes has the same fingerprint, and writes `version.verified` on the occurrences it re-pins. An edit to the spec after the dry run means nothing carries over. A title edit does not change the spec, so the pass still carries. `POST …/verify` answers `draftRecorded`, and `POST …/publish` answers `verified`. The editor says *kept, so publishing this draft unchanged makes a verified version* and *Published as v1. The dry run that passed on this draft counts for it.* | | W2 | The run console says **"Why this phase has not advanced"** and **"Phase p1: steps done, waiting to advance"**, not "has not started". The editor's hint about phase keys uses the same words. | **OpenAPI** regenerated (`MODULES_DIR` empty). It also picks up the Steam provider description from #218, which the committed spec had missed. **Docs** come in stage 5, as the plan says: MODULE_API (one module at boot, `until` read by reconcile), EVENTS §K and §L, and BACKEND_DESIGN's three columns. ## How it was tested - `npm test` (server): 2167 pass. `routeManifest` fails locally because of this machine's `website/modules` directory, and it fails on plain `edge` too. It passes with `MODULES_DIR` empty, which is what CI has. `publicVersion` failed once at file level in the parallel run and passes alone. - `npm test` (client): 430 pass. `npm run build` passes. - New tests: the one-module rule (refused before require, holds the site even when the first fails, a second never mounts, registers or claims a table, gets a failed row); W1 (past `until` gone → expired, before → orphaned, past but held → in force, last row completes the run, a later `expired()` finds nothing); W5 (pass carries, an edit breaks it, a title edit keeps it, findings keep nothing, re-pinned occurrences get the line); the fingerprint ignores key order but not array order. **Walked** on the walk site (`:3270`, DB `rustwalk`, this branch with Module-Rust `edge` plus its W1 change), signed in in the browser as the walk admin: - **W19:** a scratch core on a scratch database with `website/modules` holding `uo` and `rust`. `rust` started. `uo` was refused with the message above, in the log and in its `installed_modules` row (`startup_failed`, `manifest`). - **W5:** event 88 was dry-run as a draft (*kept, so publishing …*), then published: *Published as v1. The dry run that passed on this draft counts for it.* No "not dry run" banner appeared, and version 75 has `verified_at` and `verified_by` from the dry run. - **W2:** run 82, phase p1 done and waiting 40 minutes: *Why this phase has not advanced* / *Phase p1: steps done, waiting to advance*. - **W1, core restart (the original race):** run 83 opened a one-minute zone on the Oxide rig (Rust 25902425). The walk core was stopped until the zone had expired in the game, then started again. Core's boot reconcile filed it `expired` at 05:57:24 with the line *the game ended it at its deadline*. There was no `resource.orphaned` line and no second `resource.expired` line. The core log has no "event resource expired" from the module's `expired()` path, which shows the reconcile did it. - **W1, rig restart:** run 82 opened a one-minute zone, and the rig was restarted at once. The game's own `world.expired` reached core first, because the module waits for the world to load before it reconciles. The log shows `resource.expired` only. ## 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-22 00:59:25 -05:00
fix(core): the last fixes' core half (W1 W2 W5 W19)
All checks were successful
PR Checks / bot-tests (pull_request) Successful in 49s
PR Checks / client-build (pull_request) Successful in 1m4s
PR Checks / server-tests (pull_request) Successful in 6m6s
f40dd765c3
Stage 4 of docs/modules/rust/PLAN_LAST_FIXES.md, with the org lead's
2026-10-22 decisions.

W19: one module per site at boot, as at install. The first module
directory by name holds the site, whether or not it then loads; every
other is recorded startup_failed at the manifest stage, before a line of
its code is required, with a reason naming the module that holds the
site. Module-uo and Module-Rust side by side used to fail the second
with a slot collision. Loader, lifecycle, schema and event-contract
tests that loaded several fixture modules now load each case alone.

W1: a reconcile files a resource the game no longer has, and that is
past its `until`, as expired rather than orphaned, with the same log
line expired() writes. No MODULE_API bump: `until` and reconcile's
answer are unchanged.

W5: a dry run that passes on the draft is kept with the fingerprint of
the validated spec (three nullable columns on event_definitions).
Publish stamps the new version verified, with that dry run's reviewer
and time, when the spec it freezes has the same fingerprint, and writes
version.verified on the occurrences it re-pins. Verify answers
draftRecorded and publish answers verified; OpenAPI regenerated.

W2: the run console says "Phase p1: steps done, waiting to advance" and
"Why this phase has not advanced", not "has not started".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
whitlocktech merged commit 56c6a279dc into edge 2026-10-22 01:18:26 -05:00
whitlocktech deleted branch fix/last-fixes-core 2026-10-22 01:18:27 -05:00
Sign in to join this conversation.
No description provided.