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

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
This commit is contained in:
2026-10-22 00:38:34 -05:00
parent 9a1654fc54
commit f40dd765c3
18 changed files with 632 additions and 210 deletions

View File

@@ -249,6 +249,16 @@ async function publish(id, userId) {
const versionId = await versionsDb.insert(id, version, checked.spec, userId)
await db.markReady(id, versionId, userId)
// A dry run that passed on this exact draft counts for the version made from
// it (W5), stamped with that pass's reviewer and time rather than the
// publisher's and now: "who last looked at this before it ran unattended" is
// the person who ran the check. Any edit since is a different fingerprint.
const verified = Boolean(
existing.draft_verified_hash &&
existing.draft_verified_hash === spec.fingerprint(checked.spec) &&
(await versionsDb.markVerified(versionId, existing.draft_verified_by || null, existing.draft_verified_at || new Date())),
)
// Occurrences already materialised ahead of their instant move to the new
// version; ones that have begun do not (org lead, 2026-09-02). Logged per run
// rather than only counted, because "which version did this run actually use"
@@ -270,9 +280,18 @@ async function publish(id, userId) {
by: userId,
},
})
// The held occurrence is now going to start, and the line saying why
// belongs on it, as it does when the version is dry-run by hand.
if (verified) {
await logDb.write({
runId: run.id,
kind: 'version.verified',
detail: { versionId, version, by: existing.draft_verified_by || null, fromDraft: true },
})
}
}
return { ok: true, versionId, version, repinned, definition: await db.getById(id) }
return { ok: true, versionId, version, repinned, verified, definition: await db.getById(id) }
}
/**
@@ -373,6 +392,19 @@ async function verify(id, user) {
const report = await verifier.verifySpec(target, { user })
// A pass on the draft is kept with the fingerprint of the spec it passed on,
// for publish to compare (W5). Fingerprinted from `validate`'s output, as
// publish fingerprints the spec it freezes; a draft that no longer validates
// could not be published anyway, so there is nothing to keep.
let draftRecorded = false
if (!version && report.ok) {
const checked = spec.validate(existing.spec, { knownActionIds: spec.actionIdsIn(existing.spec) })
if (checked.ok) {
await db.markDraftVerified(id, { userId: user?.id || null, hash: spec.fingerprint(checked.spec) })
draftRecorded = true
}
}
if (version && report.ok) {
await versionsDb.markVerified(version.id, user?.id || null)
// Written to every run already pinned to this version, because that is where
@@ -397,6 +429,9 @@ async function verify(id, user) {
versionId: version?.id || null,
version: version?.version || null,
recorded: Boolean(version && report.ok),
// A pass on the draft, kept so that publishing this spec unchanged makes a
// verified version (W5).
draftRecorded,
}
}