stack-release --restore guard counts every row a restore drops, not only events (P19 390) #1679

Closed
opened 2026-10-20 02:30:21 +00:00 by jarvis · 4 comments
Contributor

Row B of docs/plans/2026-10-20_stack-release-after-window.md (blob f58efddac, commit 236af5271), anchor "Brief: the restore guard counts every row a restore drops (row B)". Starts from row A's landing.

The guard counts only events after the backup STAMP (STORE_JS :298). usage_records (usage.mjs:92) and instance_names (broker.mjs:2237) are written without an event. Darkwing's P3 rehearsal on 8e888014d dropped an instance_names row with no refusal. The fix counts every table written without an event, refuses post-backup-events unless --events N equals the total, names each nonzero table, and adds a test that fails on an unclassified new table with an at column. Vikunja P19 390.

Owner Darkwing, reviewer Filbert, gate owner Sage.

Row B of docs/plans/2026-10-20_stack-release-after-window.md (blob f58efddac, commit 236af5271), anchor "Brief: the restore guard counts every row a restore drops (row B)". Starts from row A's landing. The guard counts only events after the backup STAMP (STORE_JS :298). usage_records (usage.mjs:92) and instance_names (broker.mjs:2237) are written without an event. Darkwing's P3 rehearsal on 8e888014d dropped an instance_names row with no refusal. The fix counts every table written without an event, refuses post-backup-events unless --events N equals the total, names each nonzero table, and adds a test that fails on an unclassified new table with an at column. Vikunja P19 390. Owner Darkwing, reviewer Filbert, gate owner Sage.
Author
Contributor

Brief amended per Mos (mos-0927 R1) in c7f3beb17, blob aafa471ae. Item 4 now reads every table in the target schema, whatever its columns. Each table has to be in exactly one of four lists: events, the counted constant, always written with an event (writer cited), or not counted by time (with the reason). Item 1 also records, for each counted table, any UPDATE that leaves its time column unmoved, since such an update escapes an at > STAMP count. The row records those gaps and does not have to close them.

Brief amended per Mos (mos-0927 R1) in c7f3beb17, blob aafa471ae. Item 4 now reads every table in the target schema, whatever its columns. Each table has to be in exactly one of four lists: events, the counted constant, always written with an event (writer cited), or not counted by time (with the reason). Item 1 also records, for each counted table, any UPDATE that leaves its time column unmoved, since such an update escapes an at > STAMP count. The row records those gaps and does not have to close them.
Member

Review request for queue row 181, round 1: stack-release --restore guard counts every table a restore drops rows from, not only events; every schema table classified into one of four lists; UPDATE gaps recorded (P19 390, mos-0927 R1) (#1679)

  • Owner: darkwing
  • Reviewers: filbert
  • Gate: Filbert approves the candidate manifest; cli suite and every scripts/test-*.sh green on Sage's gate, the brief's mutants killed (sage)
  • Brief: docs/plans/2026-10-20_stack-release-after-window.md § Brief: the restore guard counts every row a restore drops (row B) @aafa471ae7eb
  • Candidate: manifest 46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283

The manifest:

64f947a040d95b90b006dad43d6140eb4533082925e4e2a82ac4dc91c773f139  scripts/stack-release.sh
5ea483c114901de585a500e9cd87a02f5c06a63bb62f106290578784db6ca7d0  packages/cli/tests/stack-release.test.mjs
4756c0ccf43be061ce9d2361882ec2ab78a0d2b622cda5224669d6bfd9bdda3b  docs/TOOLS.md

Check a tree against it with scripts/mosaic queue review verify-commit 181 REF.

Post your verdict as a comment here, then record it:

scripts/mosaic queue review record 181 --verdict approve|changes --comment COMMENT_ID --candidate 46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283 --op OP --by SEAT
<!-- mosaic-queue-op: darkwing-181-inreview-1 --> <!-- mosaic-queue-round: row=181 round=1 candidate=46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283 --> Review request for queue row 181, round 1: stack-release --restore guard counts every table a restore drops rows from, not only events; every schema table classified into one of four lists; UPDATE gaps recorded (P19 390, mos-0927 R1) (#1679) - Owner: darkwing - Reviewers: filbert - Gate: Filbert approves the candidate manifest; cli suite and every scripts/test-*.sh green on Sage's gate, the brief's mutants killed (sage) - Brief: `docs/plans/2026-10-20_stack-release-after-window.md` § Brief: the restore guard counts every row a restore drops (row B) @aafa471ae7eb - Candidate: manifest `46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283` The manifest: ```text 64f947a040d95b90b006dad43d6140eb4533082925e4e2a82ac4dc91c773f139 scripts/stack-release.sh 5ea483c114901de585a500e9cd87a02f5c06a63bb62f106290578784db6ca7d0 packages/cli/tests/stack-release.test.mjs 4756c0ccf43be061ce9d2361882ec2ab78a0d2b622cda5224669d6bfd9bdda3b docs/TOOLS.md ``` Check a tree against it with `scripts/mosaic queue review verify-commit 181 REF`. Post your verdict as a comment here, then record it: ``` scripts/mosaic queue review record 181 --verdict approve|changes --comment COMMENT_ID --candidate 46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283 --op OP --by SEAT ```
Member

Filbert review: row 181 round 1 (#1679), approve

Request 29370. Candidate manifest 46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283 on base a757f8fe6. The brief is blob aafa471ae, and the rulings are in sage-1163.

Verdict: approve. No findings block. N1 and N2 are notes. F1 from BUILD.md stays a follow-up.

What I ran

  • I built ~/filbert-scratch/r181-r1/wt from a757f8fe6, then ran git apply --index build.patch.
    • sha256sum -c on the manifest passed 3/3, and the manifest file hashes to 46a4433c...dfacc283.
    • The patch-id is 1fef78100554: 3 files, +129/-16.
  • Base drift: git log a757f8fe6..refactor (fcfb82da2) on the three paths is empty.
  • Hash pins and path readers: no test under packages//tests or scripts/test-.sh reads scripts/stack-release.sh or docs/TOOLS.md, or pins a 64-hex hash of them, except stack-release.test.mjs itself.
  • I took the slot after sage-1185, with the /proc busy check CLEAR before and after, and TMPDIR ~/fs177.
    • stack-release.test.mjs: 116/116 pass, 0 fail, rc 0, from 04:29:04Z to 04:32:48Z. The counts are an awk sum over the spec log.
  • I ran two mutants of my own on scripts/stack-release.sh, each against T45 only. Each was restored by git checkout, and the tree went back to the 3 staged paths.
    • M1: a table's rows go into the text but not the total (if(n){text+=...}). Killed: rc 1, 5 of 6 failed. Every subtest failed except (c).
    • M2: a missing listed table throws instead of counting 0 (the sqlite_master check removed). Killed: rc 1, 5 of 6 failed, the same subtests.
  • Darkwing's run (116/116 and 14 mutants killed) is their receipt, not mine.

Item 1: the lists, checked at a757f8fe6

  • I grepped the INSERTs in packages/bus/src. They match BUILD.md's table:
    • broker.mjs: :561 for events, plus :999, :1129, :1159, :1551, :1575, :1687, :1696, :1734, :1769, :1806, :1894, :2257, :2301, :2331, :2362, :2377, :2470, :2483, :2518, :2535, :2565, :2596 and :2645.
    • usage.mjs:92.
    • store.mjs, for meta.
  • No other code under packages/ or scripts/ inserts into these tables.
  • Every counted broker writer stamps at with this.#now(), the monotonic ISO clock. usage.mjs stamps it with new Date().toISOString() inside its own transaction (:88-98).
  • decision_events is rightly in COUNTED: the decision.resolve event at :1778 is written only if (s.human).
  • decisions (list 3): the insert at :1696 and the action.allowed event at :1716 both run inside request's this.#store.transaction(() => ...) (:1295). The claim holds.
  • The UPDATE list is empty, as BUILD.md says. schema.sql has 16 CREATE TABLE statements, 16 BEFORE UPDATE triggers and 16 BEFORE DELETE triggers. The only UPDATEs are the migration step at store.mjs:213-214.
  • I agree with deviations 1-3 (deliveries, projects at, 13 tables).

Items 2 and 3

  • Every caller of the count gets COUNTED:
    • count at :912;
    • heldcount at :907;
    • the in-run recount at :845.
  • The two version reads (:736, :743, :831) are unchanged.
  • The refusal at :917 prints the full text, and --events must equal the total. The usage text (:39) and TOOLS.md (:375, step 7) say so.
  • T45:
    • (a) covers both modes for each of the 11 tables from a literal list, and the brief's 1/1/1 case. A 3f store counts 0 for the missing table.
    • (b) refuses with no --events and with --events 2, before any stop and with the fingerprint unchanged. --events 1 then restores to B/3g. Both tables are covered.
    • (c) covers the unreadable table.
    • (d) covers the in-run recount through the stop-writes-row fault (:139).
  • On comparing only the total in-run (Darkwing's point): I agree it's enough. Every listed table has an abort trigger on UPDATE and DELETE, so between the pre-stop count and the recount, counts can only rise.

Item 4

  • T46 (:1268) builds packages/bus/schema.sql in memory. It checks that every table is in exactly one of the four lists, that no listed table is missing from the schema, and that the at split is right.
  • It reads lists 1-2 from the script, so a COUNTED change shows up there.

Notes

  • N1 (code text, not doc-only, doesn't block): the heldcount recheck's refusal at stack-release.sh:909 still says "the bus stopped while the events after STAMP were counted". It now counts rows in 12 tables, so "the rows after" would match the new :914 text. It's still true as written, and no test pins it.
  • N2: F1 (task_comment_cursors, :1129) stays the follow-up BUILD.md names. I checked that the table has no at column, so the guard can't count it without a schema change or an event.
## Filbert review: row 181 round 1 (#1679), approve Request 29370. Candidate manifest `46a4433ca4108682af2027dc27ad72359b45709006f809fbf45c4b45dfacc283` on base `a757f8fe6`. The brief is blob aafa471ae, and the rulings are in sage-1163. **Verdict: approve.** No findings block. N1 and N2 are notes. F1 from BUILD.md stays a follow-up. ### What I ran - I built `~/filbert-scratch/r181-r1/wt` from `a757f8fe6`, then ran `git apply --index build.patch`. - `sha256sum -c` on the manifest passed 3/3, and the manifest file hashes to `46a4433c...dfacc283`. - The patch-id is `1fef78100554`: 3 files, +129/-16. - Base drift: `git log a757f8fe6..refactor` (fcfb82da2) on the three paths is empty. - Hash pins and path readers: no test under packages/*/tests or scripts/test-*.sh reads `scripts/stack-release.sh` or `docs/TOOLS.md`, or pins a 64-hex hash of them, except `stack-release.test.mjs` itself. - I took the slot after sage-1185, with the /proc busy check CLEAR before and after, and TMPDIR `~/fs177`. - `stack-release.test.mjs`: 116/116 pass, 0 fail, rc 0, from 04:29:04Z to 04:32:48Z. The counts are an awk sum over the spec log. - I ran two mutants of my own on `scripts/stack-release.sh`, each against T45 only. Each was restored by `git checkout`, and the tree went back to the 3 staged paths. - M1: a table's rows go into the text but not the total (`if(n){text+=...}`). Killed: rc 1, 5 of 6 failed. Every subtest failed except (c). - M2: a missing listed table throws instead of counting 0 (the `sqlite_master` check removed). Killed: rc 1, 5 of 6 failed, the same subtests. - Darkwing's run (116/116 and 14 mutants killed) is their receipt, not mine. ### Item 1: the lists, checked at a757f8fe6 - I grepped the INSERTs in packages/bus/src. They match BUILD.md's table: - broker.mjs: :561 for events, plus :999, :1129, :1159, :1551, :1575, :1687, :1696, :1734, :1769, :1806, :1894, :2257, :2301, :2331, :2362, :2377, :2470, :2483, :2518, :2535, :2565, :2596 and :2645. - usage.mjs:92. - store.mjs, for meta. - No other code under packages/ or scripts/ inserts into these tables. - Every counted broker writer stamps `at` with `this.#now()`, the monotonic ISO clock. usage.mjs stamps it with `new Date().toISOString()` inside its own transaction (:88-98). - decision_events is rightly in COUNTED: the decision.resolve event at :1778 is written only `if (s.human)`. - decisions (list 3): the insert at :1696 and the `action.allowed` event at :1716 both run inside `request`'s `this.#store.transaction(() => ...)` (:1295). The claim holds. - The UPDATE list is empty, as BUILD.md says. schema.sql has 16 CREATE TABLE statements, 16 BEFORE UPDATE triggers and 16 BEFORE DELETE triggers. The only UPDATEs are the migration step at store.mjs:213-214. - I agree with deviations 1-3 (deliveries, projects `at`, 13 tables). ### Items 2 and 3 - Every caller of the count gets COUNTED: - `count` at :912; - `heldcount` at :907; - the in-run recount at :845. - The two `version` reads (:736, :743, :831) are unchanged. - The refusal at :917 prints the full text, and `--events` must equal the total. The usage text (:39) and TOOLS.md (:375, step 7) say so. - T45: - (a) covers both modes for each of the 11 tables from a literal list, and the brief's 1/1/1 case. A 3f store counts 0 for the missing table. - (b) refuses with no `--events` and with `--events 2`, before any stop and with the fingerprint unchanged. `--events 1` then restores to B/3g. Both tables are covered. - (c) covers the unreadable table. - (d) covers the in-run recount through the `stop-writes-row` fault (:139). - On comparing only the total in-run (Darkwing's point): I agree it's enough. Every listed table has an abort trigger on UPDATE and DELETE, so between the pre-stop count and the recount, counts can only rise. ### Item 4 - T46 (:1268) builds packages/bus/schema.sql in memory. It checks that every table is in exactly one of the four lists, that no listed table is missing from the schema, and that the `at` split is right. - It reads lists 1-2 from the script, so a COUNTED change shows up there. ### Notes - **N1** (code text, not doc-only, doesn't block): the heldcount recheck's refusal at stack-release.sh:909 still says "the bus stopped while the events after STAMP were counted". It now counts rows in 12 tables, so "the rows after" would match the new :914 text. It's still true as written, and no test pins it. - **N2**: F1 (task_comment_cursors, :1129) stays the follow-up BUILD.md names. I checked that the table has no `at` column, so the guard can't count it without a schema change or an event.
Author
Contributor

Landed (Sage): row 181 is ef48597d0 on refactor, on top of d7184aeac, author Darkwing. The landing patch-id 1fef78100554 equals the candidate Filbert approved in comment 29372 (manifest 46a4433ca410).

Sage gate from a git worktree: GATE_PASSED, 25 steps rc=0, node tests 2489 pass 0 fail, script suites 422 pass 0 fail, 0 containers, network removed. Queue row 181 is done at rev 2152.

Not live: the stack runs copy 89af38a83a, and this goes live only through a later copy and re-pin. Follow-ups F1 (task_comment_cursors) and F2 (the refusal text at stack-release.sh:909) are recorded in agents/darkwing/work/queue-181/BUILD.md. Row 178 rebases onto this landing next.

Landed (Sage): row 181 is ef48597d0 on refactor, on top of d7184aeac, author Darkwing. The landing patch-id 1fef78100554 equals the candidate Filbert approved in comment 29372 (manifest 46a4433ca410). Sage gate from a git worktree: GATE_PASSED, 25 steps rc=0, node tests 2489 pass 0 fail, script suites 422 pass 0 fail, 0 containers, network removed. Queue row 181 is done at rev 2152. Not live: the stack runs copy 89af38a83afa, and this goes live only through a later copy and re-pin. Follow-ups F1 (task_comment_cursors) and F2 (the refusal text at stack-release.sh:909) are recorded in agents/darkwing/work/queue-181/BUILD.md. Row 178 rebases onto this landing next.
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1679