docs(events): a step's retry delay, MODULE_API 1.15.0 (PLAN_REDESIGNS §14.3.15)

- MODULE_API.md: 1.15.0, the failure envelope's retryAfterMs (clamped to
  one to thirty minutes, one attempt, ignored beside retry: false), the
  rule bullet and the registration line.
- EVENTS.md §F: the envelope rule and the flat delay as a default.
- STEAM_SIGNIN.md: its module contract moves to 1.16.0.
- PLAN_REDESIGNS: §14.3.15, the stage-2 record (six settled points, the
  test-harness gap found on the way), and pointers from §9's summary and
  §14.3.13.

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-15 02:41:12 -05:00
parent 9e501719d0
commit 7d51820bfe
4 changed files with 81 additions and 6 deletions

View File

@@ -929,7 +929,8 @@ pulls) is research, not a walk, so it still comes first:
all of them on both rigs (§14.2, D352); **it ran on 2026-10-14 (§14.2.1)**. Then one integration plan,
answered before code: **written on 2026-10-14 as §14.3**, from D361–D369, and answered as D370–D376. Then the
build, in §14.3.11's nine stages (two of them core), §13 first. **Stage 1, §13, was built on 2026-10-15
(§14.3.14)**, with D378 and D379.
(§14.3.14)**, with D378 and D379. **Stage 2, core's `retryAfterMs` (MODULE_API 1.15.0), was built on
2026-10-15 (§14.3.15).**
**Then one walk, on Oxide and Carbon, of everything still owed (D331):** §2.7; §11's rows; §12.9; §13's and
§14's rows; the in-game rows
@@ -2822,6 +2823,8 @@ ten minutes"*.
**Tests (website).** The delay honoured; clamped at both ends; counted as an attempt; no retry for a run paused
or cancelled in the wait; `MODULE_API.md` and the classify rules updated.
> **Built on 2026-10-15 as MODULE_API 1.15.0** (§14.3.15).
#### 14.3.14 Stage 1, built: Rust's own world events (2026-10-15)
Built on `edge` in Rust-Plugins, Rust-Link and Module-Rust, specified in
@@ -2895,6 +2898,41 @@ Carbon's console; and a configuration save's reload from the website on Carbon (
**Not changed:** the Android app. It reads the API leniently, so it shows neither world events nor the two
columns until it learns them.
#### 14.3.15 Stage 2, built: a step's retry delay (2026-10-15)
Built in `website` as **MODULE_API 1.15.0**, specified in [MODULE_API.md](../../website/MODULE_API.md) §1.1 and
[EVENTS.md](../../website/EVENTS.md) §F, as §14.3.13 planned it. It took 1.15.0 ahead of Steam sign-in, whose plan
now names 1.16.0. No module changes: Module-uo (`^1.10.0`) answers none of it, and Module-Rust stays on
`^1.14.0` until stage 5, when Dangerous Treasures answers it and its pin moves.
**Settled in the code, and overrulable:**
1. **A `retryAfterMs` that is not a number is ignored, not clamped.** `"600000"`, `NaN` and `Infinity` are
dropped and logged, and the flat delay applies; the failure is unchanged. Zero and negatives are numbers and
clamp to the one-minute floor.
2. **Rounded to whole milliseconds.**
3. **Only on the retry shape.** Beside `retry: false` it is not carried, because a terminal failure is never
tried again. A missing `retry` still means retry, so the hint is read there too.
4. **Every retry line now says when**: `step.retry` carries `retryAt` whether or not the module hinted, and
`retryAfterMs` only when it did. The console reads *"failed, attempt 1 of 3, retrying at 20:10: not ready
yet"*. The step table's existing *"due 20:10"* was already there.
5. **`revert()` and `reconcile()` are unchanged.** Cleanup has its own retry counter (`MAX_REVERT_ATTEMPTS`), and
nothing in this plan asks for a delay there.
6. **Paused and cancelled need no new code**: the runner's `findDue` reads only running runs, so a step waiting on
its delay is simply not picked up. The tests prove it rather than adding a guard.
**Tests.** Server: six new in `test/eventRunner.test.js` (the hinted delay honoured and the flat delay not;
an unhinted line's `retryAt`; three attempts at the thirty-minute ceiling fail on schedule; paused in the wait;
cancelled in the wait; `classify()`'s clamps and refusals), 67 in the file. **Found on the way:** the file's
stubs never covered `finishedRunsWithNothingLeft` (MODULE_API 1.11.0), so a tick that reached the cleanup sweep
with a terminal run waited on the dead pool; the cancelled-run test was the first to do it, and it is stubbed
now. Client: the retry line, an older line, an unreadable time. Full suites: server 2102 pass; the only failures
are `routeManifest.test.js`'s two and they fail identically on an untouched `main` here, because they read this
machine's installed `modules/`; client 422/422 and the build.
**No walk rows of its own.** Stage 5's Dangerous Treasures rows exercise it: a step answering *"not ready"*
shows *"retrying at …"* and runs then.
### 14.4 Questions for the org lead
**Answered on 2026-10-14:** Q17 as proposed, out (D358). **Q18 against the proposal: the end walk waits for
@@ -2919,7 +2957,7 @@ it does not hold the end walk (D359).
What this module takes from it:
- **A verified Steam id for a signed-in account**, read through the module contract (MODULE_API 1.15.0 there).
- **A verified Steam id for a signed-in account**, read through the module contract (MODULE_API 1.16.0 there; 1.15.0 went to §14.3.13).
- **A Steam identity as a linked Rust player**, beside the in-game `/link` code (R1). Whether it counts as a link
is that plan's Q1, and what unlinking removes is its Q2.
- When it lands, Module-Rust's account screens and the link flow are updated in their own PR. Rust's grants