carlos / platform Public

provision: census for Task 9 fix round 2: estimateRules and moveTimings re-pinned in place, the console envelope and the seal

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev a1ac66fc200f2e936d23a6009158658a55d8baf3 parent 2196d91
3 files changed, +12 −6
  • docs/superpowers/notes/census-proposal-self-serve-moves-2.md +2 −0
  • internal/provision/plan14_root_reads_test.go +4 −1
  • internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv +6 −5

CI failed — run details

CI log
=== gate ===
.amadan/test-gate.sh

amadan: step gate failed: signal: terminated

amadan: job failed at step gate — its output is above, not at the tail of this log
diff --git a/docs/superpowers/notes/census-proposal-self-serve-moves-2.md b/docs/superpowers/notes/census-proposal-self-serve-moves-2.md
index a9f77e2ab..c7ef4a2c1 100644
--- a/docs/superpowers/notes/census-proposal-self-serve-moves-2.md
+++ b/docs/superpowers/notes/census-proposal-self-serve-moves-2.md
@@ -43,3 +43,5 @@ Task 8 fix round 1 adds no root read, class or task and no record write. The ope
Task 9 (the estimate, the timings and the events) adds no root read, class or task, and no record write. In the root-read overlay twelve accepted-legacy units are added under `rev3=PROPOSED-self-serve-moves-2`, each frozen with a one-line basis, and none reads a file: the timing marks and `move_timings` (`ssMarkTx`, `Store.MarkSelfServeTiming`, `Store.SelfServeTimings`, `Store.InsertMoveTiming`, `Store.MoveTimings`), the estimate's medians (`Server.estimateRules`, whose sites are the `Open` term, a struct field), the events (`ssRowEventTx`, `Store.SelfServeEvents` and the dead-letter `Store.selfServeEventDeliveryFailed`), `Store.RecordSelfServeHealth` and `Store.SetSelfServeReason` (now transactions with their events, where they used `setSelfServe` before) and the operator status door `Server.handleAPIInstanceOfflineStatus` (its site is the request URL's `Query`, the `?log=1` switch). `Server.estimate`, `Store.AbortSelfServe`, `Store.AdvanceSelfServeToStep`, `Store.ConsumeSelfServeRequest` and `Store.migrateSelfServe` are re-pinned in place with their bases extended (the medians; the events and marks in the change's own transaction; the events' `attempts` column, added idempotently). The internal/console envelope is re-pinned in place, and the seal moves to `16987f09…`. In the record-write inventory nothing changes: the marks, `move_timings`, the events and their delivery are console SQLite only, and the one new bucket access is a read (the advance into landed reads the move's reports through `readOfflineEvidence`, a key-site, for the seal's sizes). `claimWriterReasons` already names `self_serve_events` and `self_serve_timings` as the claims-off pass's writers; `move_timings` is `NonApp` in the store gate and its one writer, the finaliser's timings effect, runs only in that pass, so `TestClaimConsoleMutationInvariant` reaches no new writer.
Task 9 fix round 1 adds no root read, class or task and no record write. `Store.MoveTimings`'s query moved to `Store.moveTimings`, which it shares with the estimate's window (`moveTimingWindow`: the rated rows of at least 1 MiB, or the rows under that floor, which measure a term's fixed part), so `MoveTimings`'s Task 9 rows, never ruled on, are withdrawn and `moveTimings` is frozen accepted-legacy in their place. `Server.estimateRules` (a rate measured past the term's fixed part) and `Store.SetSelfServeReason` (its event stamped with the tick's clock) are re-pinned in place; the internal/console envelope is re-pinned in place and the seal moves to `532a916e…`.
+
+Task 9 fix round 2 adds no root read, class or task and no record write. `Server.estimateRules` (a rated timing that finished inside its fixed part, or within one tick of it, is left out of the rate's median; the 100 ms clamp is gone) and `Store.moveTimings` (the rate floor is now a bound parameter) are re-pinned in place with their bases extended; `selfServeMoveTimings` (no land or promote row from a landed mark without bytes) reads nothing and is no unit. The internal/console envelope is re-pinned in place and the seal moves to `603f7552…`.
diff --git a/internal/provision/plan14_root_reads_test.go b/internal/provision/plan14_root_reads_test.go
index 10139b85e..1a18331db 100644
--- a/internal/provision/plan14_root_reads_test.go
+++ b/internal/provision/plan14_root_reads_test.go
@@ -1359,7 +1359,10 @@ func TestPlan14RootReadCensus(t *testing.T) {
// once more. Its fix round 1 withdraws MoveTimings's unruled rows (its
// query moved to moveTimings, frozen in their place) and re-pins
// estimateRules and SetSelfServeReason in place, which moves it again.
- seal = "532a916ebc21d41287812993943bed488b7dfcc2250570000aedb82cc48919f6"
+ // Its fix round 2 re-pins estimateRules (rated rows inside the fixed
+ // part left out) and moveTimings (the floor bound) in place, which
+ // moves it once more.
+ seal = "603f7552a0b96baaccc745d86c97b6ded5dfbe9f291b7fc98234cc0cb505f582"
errs := append(compareRootReads(got, inv), checkRootReadLegacy(inv, seal)...)
errs = append(errs, checkRootReadDeclarations(got, inv)...)
if len(errs) > 0 {
diff --git a/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv b/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv
index 6ac8d781d..1e2e4b4bf 100644
--- a/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv
+++ b/internal/provision/testdata/plan14-root-reads-self-serve-moves-2.tsv
@@ -23,7 +23,7 @@ internal/console/templates/settings.html external legacy accepted-legacy accepte
internal/provision/offline_move.go offlineBegin legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=root-input (J4, as OfflineStart); the console (cmd/console serve under console.service, user carlos-console): self-serve moves 1 Task 7's body (OfflineStart's, the state a parameter; a direct start advances move_seq and stamps move.seq, refusing ErrLifetimeExhausted at MaxInt64 before any write), and it now also creates the self-serve move in offline-queued for OfflineQueue (queued_at, staged_at and precheck_at at the caller's stamp, move.seq set to the record's move_seq, no advance) and records return_of; a stage and a queue hold nothing; its one site is still rec.ActiveRun.Open(), a method on the record's run state (RunState.Open), not a file read; self-serve moves 2 Task 2 file:Open@208 0a9b432ddf2f39a977c0651e377258b35c1d05635e9979583eeac6253d6c0ec8
@coverage internal/provision d018e5699137db933be2142f7526d0d1d10b08170525886bd9c424cde5578b55
# Task 3 (per-box reservations with a legacy projection and a sentinel, the fenced reclaim and the operator doors' bound admission), rev3=PROPOSED-self-serve-moves-2: no root read, class or task is added and no accepted-legacy unit is re-pinned, so the seal does not move. The new units (moves.ParseOfflineActive, moves.OfflineActiveBody, the console's offlinereserve.go, the doors' offlineApplyBound and offlineAdvanceBound) read no file: their reads are the bucket's control/offline-moves/active.json and the instance record through the judged readers and fenceRecord. Envelopes re-pinned in place (Task 2's rows replaced): internal/console (offlinereserve.go, the start and stage doors, the Server's two evidence fields) and internal/moves (the reservation table in offline.go).
-@coverage internal/console 31e3cb7931b2d2797538080f3d20d18262cefa9a58e804c3d235e429b1d8c9f0
+@coverage internal/console 19756da0ccdd51a48ee785c7949011ac6ab6e18e6517314cfbcd4595ddbbac86
@coverage internal/moves 6a61fc2680d29b8998a383c7c65756f78a06ac312279148bdde752546686cd8d
# Task 4 (the journal, the events table, the console lease and the pass skeleton), rev3=PROPOSED-self-serve-moves-2: no root read, class or task is added. The console SQLite journal (selfserve_store.go) adds twenty-two units, each frozen accepted-legacy with a reviewed basis (console SQL as carlos-console, no bucket or root action), and the lease's console name adds one crypto/rand read (Server.selfServeConsoleID); serve (in place: the paging arm takes the store, the pass is started), NewServer (the row evidence and the recovery-mode scan) and Store.migrate (migrateSelfServe) are re-pinned. The seal moves. The lease and the pass read control/offline-moves/console.json and active.json from the bucket, not a file. Envelopes re-pinned in place: cmd/console, internal/console and internal/provision (WithWriteGuard in WriteRecord).
@legacy a8dd51a494ab3cd2ad371ded2850b6d78492569729527ea82cd8dd0f2b418a78 internal/console/selfserve_lease.go Server.selfServeConsoleID legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads crypto/rand once per process for the random console name the self-serve moves lease carries; randomness grants no root authority file:Read@110 3303b18ec5c77ccaf662064801f94276bfe947c31378cc1ecb8c4fe509d5d4d1
@@ -209,8 +209,8 @@ internal/console/selfserve_store.go Store.finishSelfServeMove legacy accepted-le
# Task 9 (the estimate, the timings and the events), rev3=PROPOSED-self-serve-moves-2: no root read, class or task is added and no record write. Twelve accepted-legacy units are added, each console SQLite or a URL query, none a file: the timing marks and move_timings (ssMarkTx, MarkSelfServeTiming, SelfServeTimings, InsertMoveTiming, MoveTimings), the estimate's medians (estimateRules, whose sites are the Open term), the events (ssRowEventTx, SelfServeEvents, the dead-letter selfServeEventDeliveryFailed), RecordSelfServeHealth and SetSelfServeReason (now transactions with their events) and the operator status door (its ?log=1 query). Server.estimate, Store.AbortSelfServe, Store.AdvanceSelfServeToStep, Store.ConsumeSelfServeRequest and Store.migrateSelfServe are re-pinned in place. The seal moves. The internal/console envelope is re-pinned in place.
@legacy 990c2a58e7657184add84d7aa4ba65124f5e45b13e68d06918e9a07de08c4b67 internal/console/apiinstancemove_offline.go Server.handleAPIInstanceOfflineStatus legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the operator offline status door; its site is the request URL's Query (the ?log=1 switch for the move's events, self-serve moves 2 Task 9), not a file; it reads the record through offlineGate and the console SQLite journal; no root action file:Query@213 2341180d34b7c3be07f910ab719c9ec40254de662d414c7ba4a4a7feb59b0b40
internal/console/apiinstancemove_offline.go Server.handleAPIInstanceOfflineStatus legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the operator offline status door; its site is the request URL's Query (the ?log=1 switch for the move's events, self-serve moves 2 Task 9), not a file; it reads the record through offlineGate and the console SQLite journal; no root action file:Query@213 2341180d34b7c3be07f910ab719c9ec40254de662d414c7ba4a4a7feb59b0b40
-@legacy 8d6e27c7315d7d62d2ce12c20a69d6fbfb8c01d4b318210194bdf39e21d6a836 internal/console/selfserve_estimate.go Server.estimateRules legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the estimate's terms refined from the region pair's move_timings medians in the console SQLite; its sites are the Open term (a struct field named Open), not a file; no root action; fix round 1: every term's fixed part from the rows under 1 MiB, a rate term's rate from the rows of at least 1 MiB measured past that fixed part (moveTimingWindow) file:Open@1257,file:Open@74 e32e6fdff0fef5b31e40266b7d6ed451f41e8bcf73efb778c848bbe3f152673e
-internal/console/selfserve_estimate.go Server.estimateRules legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the estimate's terms refined from the region pair's move_timings medians in the console SQLite; its sites are the Open term (a struct field named Open), not a file; no root action; fix round 1: every term's fixed part from the rows under 1 MiB, a rate term's rate from the rows of at least 1 MiB measured past that fixed part (moveTimingWindow) file:Open@1257,file:Open@74 e32e6fdff0fef5b31e40266b7d6ed451f41e8bcf73efb778c848bbe3f152673e
+@legacy ebf0d8e703cc53d7068ba1a24efafb5a2e7b3422744325ebf49812cb117971e7 internal/console/selfserve_estimate.go Server.estimateRules legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the estimate's terms refined from the region pair's move_timings medians in the console SQLite; its sites are the Open term (a struct field named Open), not a file; no root action; fix round 1: every term's fixed part from the rows under 1 MiB, a rate term's rate from the rows of at least 1 MiB measured past that fixed part (moveTimingWindow); fix round 2: a rated row less than one tick (5 s) past the fixed part is left out of the rate's median, and the default rate stands until five informative rows exist (the 100 ms clamp removed) file:Open@1199,file:Open@74 3a5c46d11d91db5404bdeb477832d2fbac4ab01812f65f7ec09aa3101cc7d4f9
+internal/console/selfserve_estimate.go Server.estimateRules legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: the estimate's terms refined from the region pair's move_timings medians in the console SQLite; its sites are the Open term (a struct field named Open), not a file; no root action; fix round 1: every term's fixed part from the rows under 1 MiB, a rate term's rate from the rows of at least 1 MiB measured past that fixed part (moveTimingWindow); fix round 2: a rated row less than one tick (5 s) past the fixed part is left out of the rate's median, and the default rate stands until five informative rows exist (the 100 ms clamp removed) file:Open@1199,file:Open@74 3a5c46d11d91db5404bdeb477832d2fbac4ab01812f65f7ec09aa3101cc7d4f9
@legacy 66f14cd5f12b609aa5a53aa4e9c9ca2a6f8de2deb410b7f4841e4145192b6c4e internal/console/selfserve_estimate.go Store.InsertMoveTiming legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: one INSERT ... ON CONFLICT DO NOTHING of a finished move's phase timing into the console SQLite move_timings; no bucket or root action file:Exec@208 cab08b1af56d4130e2c83e77d7324558c1e336edf3aefdc0455fad80d242f886
internal/console/selfserve_estimate.go Store.InsertMoveTiming legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: one INSERT ... ON CONFLICT DO NOTHING of a finished move's phase timing into the console SQLite move_timings; no bucket or root action file:Exec@208 cab08b1af56d4130e2c83e77d7324558c1e336edf3aefdc0455fad80d242f886
@legacy 0a99bf6b173528019e217c62566e3e9b7e0f9a0f695c962fa8425ff89977d87d internal/console/selfserve_estimate.go Store.MarkSelfServeTiming legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: one console SQLite transaction that checks the self-serve row exists and inserts its timing mark insert-only (ssMarkTx); no bucket or root action file:QueryRow@210 d67ab8a6b3d3144a9ea18be9d37c7053635cb8f01c2c52368193445ad0ab92db
@@ -230,5 +230,6 @@ internal/console/selfserve_store.go Store.RecordSelfServeHealth legacy accepted-
@legacy 51232553f83142a5924adb4595ef9640aafbdbd45b2d19bf676f7b5173a3e9b8 internal/console/selfserve_store.go Store.SetSelfServeReason legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads a self-serve row's reason and sets the new one, inserting a waiting event only when it changed, in one console SQLite transaction (it used setSelfServe before self-serve moves 2 Task 9); no bucket or root action; fix round 1: the waiting event is stamped with the caller's tick clock file:Exec@413,file:QueryRow@183 075dc66bb1564ba52f06f858728e7c66eeba015ff0a4fe9f06df1accf67fbe5b
internal/console/selfserve_store.go Store.SetSelfServeReason legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads a self-serve row's reason and sets the new one, inserting a waiting event only when it changed, in one console SQLite transaction (it used setSelfServe before self-serve moves 2 Task 9); no bucket or root action; fix round 1: the waiting event is stamped with the caller's tick clock file:Exec@413,file:QueryRow@183 075dc66bb1564ba52f06f858728e7c66eeba015ff0a4fe9f06df1accf67fbe5b
# Task 9 fix round 1, rev3=PROPOSED-self-serve-moves-2: Store.MoveTimings's query moved to moveTimings (shared with the estimate's moveTimingWindow), so MoveTimings's Task 9 rows, never ruled on, are withdrawn and moveTimings is frozen accepted-legacy; Server.estimateRules (the rate measured past the fixed part) and Store.SetSelfServeReason (the event at the tick's clock) are re-pinned in place; the internal/console envelope is re-pinned in place.
-@legacy a1db4c994658cab78fcca3beaf136fb95c0947c9917243d5aab839b83b1205a4 internal/console/selfserve_estimate.go Store.moveTimings legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads the region pair's newest move_timings rows of one phase under a fixed condition (all rows, the rated rows or the rows under the rate floor) from the console SQLite, for MoveTimings and the estimate's window; no bucket or root action file:Query@107 a3d3e331cce891a1d9ef679ad09651bf50e5f6a303dfae40c5964654829f24c3
-internal/console/selfserve_estimate.go Store.moveTimings legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads the region pair's newest move_timings rows of one phase under a fixed condition (all rows, the rated rows or the rows under the rate floor) from the console SQLite, for MoveTimings and the estimate's window; no bucket or root action file:Query@107 a3d3e331cce891a1d9ef679ad09651bf50e5f6a303dfae40c5964654829f24c3
+@legacy 109c25b1df111f2086bc4027c6505ea6bfa8c150b5bfd09af1d7355901eefa94 internal/console/selfserve_estimate.go Store.moveTimings legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads the region pair's newest move_timings rows of one phase under a fixed condition (all rows, the rated rows or the rows under the rate floor) from the console SQLite, for MoveTimings and the estimate's window; no bucket or root action; fix round 2: the rate floor is a bound parameter file:Query@181 7c6d87943159d50771a66237824dc8be7c25e2334d688010450aa7357bc88b16
+internal/console/selfserve_estimate.go Store.moveTimings legacy accepted-legacy accepted-legacy;rev3=PROPOSED-self-serve-moves-2;basis=console.service user carlos-console, J4 root-input: reads the region pair's newest move_timings rows of one phase under a fixed condition (all rows, the rated rows or the rows under the rate floor) from the console SQLite, for MoveTimings and the estimate's window; no bucket or root action; fix round 2: the rate floor is a bound parameter file:Query@181 7c6d87943159d50771a66237824dc8be7c25e2334d688010450aa7357bc88b16
+# Task 9 fix round 2, rev3=PROPOSED-self-serve-moves-2: Server.estimateRules (a rated row inside its fixed part, or within a tick of it, carries no rate and is left out) and Store.moveTimings (the floor bound) are re-pinned in place; the internal/console envelope is re-pinned in place.