Skip to content

fix(retention): verify SQL page progress and expose GC frontiers (#4787) - #4798

Open
ScriptedAlchemy wants to merge 31 commits into
fix/daemon-mount-rollback-fixturefrom
fix/4787-retention-sql-progress
Open

ScriptedAlchemy wants to merge 31 commits into
fix/daemon-mount-rollback-fixturefrom
fix/4787-retention-sql-progress

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Scope — Refs #4787, partial; keep issue open

Six retention-only files above explicit CI prerequisites. The former eight-file diff included two independent test-fixture repairs. Those repairs remain byte-for-byte in the tree and in the original history; they have not been reverted or overwritten.

Review/landing order:

  1. test(automation): bind scheduler fixtures to backend identities #4821 — scheduler backend-identity fixture repair, merged into master.
  2. test(daemon): isolate failed-mount cleanup from graph readiness #4827 — one-file failed-mount cleanup fixture repair, now targeting master.
  3. This PR — canonical GC, replay compaction, retention regressions and daemon measurements, stacked on test(daemon): isolate failed-mount cleanup from graph readiness #4827.

Do not merge this PR into the prerequisite branch. Land the prerequisites in master through their own reviews, retarget this PR to master, verify its diff and exact-head CI again, then consider the ordinary merge gate. No auto-merge is enabled. Do not undo the fixture repairs or transplant held #4776/decision-model work to reduce this stack.

Retention implementation retained

  • Canonical-body GC reports candidates discharged, verifies selected candidate identities are actually absent inside the writer transaction, and rejects a checkpoint that did not persist. A refused or rewritten checkpoint/candidate deletion rolls back rather than claiming false progress.
  • Replay compaction admits a contiguous prefix under both metadata-parsing and body-verification budgets before SQL JSON eligibility checks. Direct-column octet_length avoids materializing oversized text merely to discover its size.
  • Replay verifies its persisted store-ID frontier inside the transaction; oversized/ineligible work can advance without destructive cleanup or repeated parsing of deferred documents.
  • Reports and daemon logs include committed-frontier/candidate progress, metadata bytes examined, and elapsed wall time through commit. Wall time is not CPU time, and the separate cold-store JSON cursor is not either SQL frontier.
  • Database-backed regressions retain 52-row/owner backlogs with 48+4 pagination, zero-reclamation progress, checkpoint/candidate rollback and recovery, exact live-data preservation and quiescence. The Linux process-read-cost regression uses fresh test connections rather than unauthorized cache PRAGMAs.

Scope reconciliation and concurrent work

Commit af1045000305250ac1cefd94e87ea1ddeefc201c joins only the already-present fixture prerequisites. Its first parent is the exact prior #4798 head 4984a54fc4cf6cd71d2191d60a80639b1f0b183f; its second parent is #4827 ee44f8c16b736c36075eaadfe4bee6551194951a. At reconciliation, the full source tree was 3f493dd3a148e21f7bbfe8f9f59a14392d00dd8e, identical to the prior head. GitHub comparison confirms zero changed files versus that parent, and exactly six retention files versus the prerequisite. Publication uses a nonforce expected-old-head fast-forward, not a rebase or reset.

The previous overlap warning was too broad: #4813 changes maintenance writer admission, while this PR adds fields to the two outcome log functions at separate hunks. A shared filename is not by itself a merge conflict. #4813 remains independently owned; none of its writer-admission implementation is imported or changed here. The scheduler fixture has one existing review owner, #4821, whose blob matches this tree exactly. Combined runtime behavior still needs normal integration testing when both source PRs land.

Validation and acceptance boundaries

  • The reconciliation changes ancestry/review scope, not source bytes or test assertions. The daemon fixture extraction was independently diff-reviewed; source identity and both comparison boundaries were verified before publication.
  • The source-equivalent prior-head run 42536602973 passed Repository gates (including Bazel formatting), Change scope, benchmark harness and Feature gates; Clippy, Linux fleet and Dashboard were still queued at inspection. This is not a full green run or a fresh exact-head Rust pass.
  • Native macOS Bazel on 1f0446809f passed 11 canonical-body GC cases, 11 replay-metadata cases, and 4 registered-store retention cases. The daemon composition library built successfully. These runs exercised writer-transaction rollback after ignored/rewritten checkpoints, candidate-removal refusal, recovery across bounded pages, oversized metadata and idle quiescence.
  • The daemon now emits the committed bootstrap frontier even if an owner disappears between the initial scan bound and the tick, yielding a page with zero rows. A real SQLite regression observes that frontier once and confirms the following idle tick produces no work to log. Review follow-up
  • Metadata-byte evidence counts only metadata admitted for eligibility after both byte budgets are applied. The preceding SQL size-discovery query may inspect additional row headers. Rows deferred by the body budget are excluded from the eligibility byte count, and admitted ineligible rows are included. The byte count measures logical input. Elapsed time includes the writer commit. Physical I/O and sustained process CPU still require the affected-host measurements below. Measurement review Hosted checks and independent review remain required.
  • On 9a1c8a27d0, all 11 replay-metadata cases passed on native macOS, including the peer correction that counts admitted ineligible rows as skipped. On dfd0c6a106, all 34 native macOS LCM retention tests passed, including all 11 replay-metadata cases. Both ignored and rewritten checkpoint writes roll back earlier changes and recover. The budget regression verifies that only the admitted prefix contributes bytes. The application consumes the budget once, before eligibility parsing. Checkpoint review
  • The original affected-host 90–110% CPU incident remains unproven resolved. Full acceptance needs consecutive committed SQL frontiers/candidate identities, per-tick work/timing and CPU observations, restart/quiescence evidence, and proof on master. No Fixes #4787 claim or automatic issue closure.

Protected mixed #4776 and all Kev/decision-model PRs, including #4797, remain draft and excluded from merging. Release #4763 remains read-only. No production, infrastructure, tags, credentials or task schedules are changed.

Review order remains #4834 → #4827 → this PR. The #4834 Linux fleet passed all 183 targets on 7264f0d6c2, including both affected binaries uncached. Targeted native Windows passed both selected suites. Its Clippy job encountered an upstream HTTP 504 downloading the pinned build tool. The prior Linux run covered 9a1c8a27d0 before the prerequisite updated. Merge still requires independent review, completed CI and revalidation against master.

The CLI fixtures from #4834 are now in the #4827 prerequisite. At b3f839a836, GitHub still shows exactly the six retention files and the feature patch ID matches the prior head.

The previous verification run checks 189b07186e against #4827 at 4ecf593ba3. This head includes the Linux launcher download prerequisite. The 6-file feature diff has the same paths and stable patch ID after updating the prerequisite. At ddabf4a972, the initial and continuation passes both attach the owning session database path to canonical-body and replay-metadata progress. The native macOS daemon regression captured four actual operator log lines for two different stores sharing the same frontier values and verified exactly one event of each type per store. The Bazel formatter and four additional frontier cases passed. Current hosted workflow

Report candidate discharge and replay SQL frontiers for each scanned page.
Reject incomplete candidate discharge or nonadvancing replay pages.
Add >48-row behavioral regressions for zero-reclamation backlogs.

Refs #4787
@changeset-bot

changeset-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6edf069

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Admit a size-bounded metadata prefix before running SQL JSON eligibility
checks, including rows that cannot be compacted. Resolve admitted IDs in
one query under the existing writer transaction. Preserve oversized
metadata while advancing past it without parsing or blocking later rows.

Expose examined metadata bytes through the page report and tracing span.
Add database-backed regressions for large ineligible backlogs and an
oversized stored document followed by valid compactable work.

Refs #4787

Copy link
Copy Markdown
Owner Author

Published replay CPU-amplification fix — Refs #4787

Follow-up commit 001b1ab is now on this issue-specific PR. It changes only replay_metadata.rs and its database-backed tests; the previous canonical-GC/frontier work remains intact.

Confirmed defect and correction

candidates() evaluated json_valid/json_type on up to 48 complete metadata documents before step() applied the 4 MiB verification budget. Large ineligible structured replay documents did not consume that later budget at all. The row cap therefore did not bound JSON eligibility work.

The fix first reads identities/sizes, admits a contiguous prefix under a 4 MiB metadata-parsing budget, then evaluates eligibility in one batched primary-key query under the same writer transaction. No per-row query loop is added. Individually oversized metadata is left byte-for-byte intact and advanced past without parsing; later valid work remains reachable. Existing body-verification budget, sanitizer receipts, guarded writes, rollback behavior, and 48-row cap remain in place.

metadata_bytes_examined reports admitted eligibility bytes, including ineligible or prefetched-but-deferred rows. The lcm.retention.replay_metadata.page tracing span exposes that field through the existing span-timing surface. This bounds JSON parsing, not every physical disk read; size discovery still has an I/O cost.

Behavioral evidence

A disposable SQLite 3.46.1 probe executed the original and replacement SQL, instrumenting actual json_valid input bytes. For 48 structured documents:

  • Original single page: 25,924,272 bytes submitted for eligibility validation.
  • Fixed pages: 3,780,623 bytes each for six 7-row pages, then 3,240,534 bytes for the final 6 rows.
  • Persisted frontier: 0 → 7 → 14 → 21 → 28 → 35 → 42 → 48, followed by an idle page. No document revisited or changed.
  • Oversized, external, NULL, and malformed metadata cases passed; later eligible work remained discoverable. The eligibility query plan uses INTEGER PRIMARY KEY probes rather than a full-table scan.

Added two real Rust database-backed regressions: (1) large ineligible documents require multiple bounded ticks, strictly advance the durable frontier, quiesce, and preserve complete messages/receipts; (2) oversized stored metadata stays unchanged while a subsequent valid row is actually compacted. Existing corruption rollback, stale-write, representation-preservation, and 48+4 progress regressions are unchanged.

Validation and ownership

Reviewed the exact two-file diff in a separate pass and verified one commit ahead of 8db58ec7. Published with expected_sha=8db58ec7ddbfbe29d295404cb37c84c4b2b458d0, force=false; verified PR head at 001b1abe.

The SQLite probe is not a repository Rust/Bazel pass. No local Bazel toolchain was available; no Cargo was invoked. New-head CI run https://github.com/ScriptedAlchemy/tracedecay/actions/runs/42434994670 is pending. The relevant Rust suite is bazel test //crates/tracedecay-lcm:unit_test --test_output=errors; new-head formatting, compilation and behavioral tests must pass before landing.

The original affected-host 90–110% CPU incident is not yet proven resolved. Its consecutive canonical candidate/frontier and actual tick/commit measurements remain required, and the cold-store JSON cursor is a separate authority. Keep #4787 open; no Fixes claim or master closure. Protected mixed #4776 remains draft and untouched; no Kev/decision-model work moved, no release #4763/production/infrastructure/credential changes, and no other task schedules changed.

Apply only the two exact Rustfmt changes identified by the blocked
repository formatting gate on the last PR head.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — repaired the first exact-head CI failure on this isolated PR.

The Bazel //:rustfmt_check gate in CI run 42434994670 failed in //crates/tracedecay-lcm:rustfmt_check_2024 on two formatting differences in the new replay-metadata regression tests (tests.rs:428 and :520). No product logic failed in that gate. Published 2a42006eef255c577137620543f9fa25cdbe96c0 with only those exact two rustfmt transformations, via nonforce expected_sha=001b1abe47f636b05ed95c964e3cbd6f6ab5cdee; verified remote ref and PR head.

New exact-head CI run 42437993937 is queued; no passing Bazel/Rust test is claimed yet, and the previous run's Linux/Clippy work is not an accepted pass. Keep #4787 open pending exact-head tests and affected-host SQL-frontier/CPU/cadence evidence. No changes to draft #4776, release #4763, other owner work, or scheduled tasks.

Read back the replay frontier in the page's writer transaction before
reporting progress. Refuse ignored or rewritten checkpoint writes so the
existing transaction owner rolls back metadata changes rather than
committing a page that will be visited again. Idle pages do not write.

Add real database regressions for an ignored initial checkpoint, a
rewritten existing checkpoint, rollback and successful recovery, and
write-free idle pages. Preserve existing parsing and body budgets.

Refs #4787

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retention implementation review — Refs #4787

Reviewed the published checkpoint repair at 91ffd680d7ec128dbf5cd14d9bcc721b4e457a21, including its two-file diff against 2a42006. This is a code update on this PR, not merely a proposed change.

The previous guard checked an advancing local after value but did not establish that set_gc_meta actually stored it. The new read-back occurs inside the same writer transaction, before returning a successful report; an ignored or rewritten checkpoint now returns an error through the existing rollback owner. Empty pages no longer initialize or rewrite the checkpoint. Existing metadata/body budgets and sanitizer checks remain intact.

The added database-backed Rust regressions cover an ignored initial checkpoint, an existing checkpoint rewritten after INSERT, and an idle page whose checkpoint writes are explicitly forbidden. The refusal tests prove that compaction happened before the failure, then verify restoration of the complete message/receipts, the prior checkpoint and summary revision, followed by successful compaction and quiescence once the injected fault is removed.

Validation remains open: the disposable SQLite reproduction passed 20 assertions, reproducing repeated identical 48-row pages under both injected checkpoint faults and recovery through 48+4 pages after removing the faults. That is not a Rust/Bazel test pass, and these injected faults are not established as the affected host's cause. No local Bazel was available; no Cargo was run. Exact-head CI run 42442366451 was queued when checked. Require the relevant Bazel unit tests and applicable CI on this head, rather than inheriting an earlier head's green checks.

Not an approval or incident-resolution claim. Keep Refs #4787: closure still requires the original CPU/frontier acceptance evidence in master. Consecutive committed frontiers/candidate discharge and measured tick timing are needed to distinguish a stalled page from an advancing backlog. No auto-merge; the separate mixed #4776 remains draft and excluded from merging.

pub rows_skipped_oversized: u64,
/// Metadata bytes admitted to SQL eligibility parsing, including ineligible
/// rows and any prefetched rows deferred by the separate body byte budget.
pub metadata_bytes_examined: u64,

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Measurement/acceptance note: this is the admitted metadata size for eligibility parsing, including prefetched rows the body budget may defer. It is not total physical I/O, unique committed bytes, or a CPU measurement; the initial size-discovery query runs before this admission. Keep the scope explicit when evaluating #4787, and correlate it with committed frontiers and actual page/tick timings before claiming the sustained CPU incident is resolved.

Refuse an unchanged bootstrap page or a checkpoint that did not persist,
even when its SQL UPDATE reports one affected row. Roll back enrolled refs
and seed writes through the existing writer transaction on refusal.

Add a database-backed 52-owner regression proving repeated 48-row pages
fail closed when a trigger rewrites their frontier, then resume through
48+4 pages and quiesce without collecting the live shared body.

Refs #4787

Copy link
Copy Markdown
Owner Author

Published canonical-body bootstrap checkpoint guard — Refs #4787

Commit ad3729b860 is now on this existing issue-specific PR. It changes only canonical_body_gc.rs and its Rust database-backed tests, preserving every concurrent commit.

Bug class: the former save_progress accepted UPDATE ... affected-row count = 1 as proof that the raw/observation/body bootstrap frontier persisted. A database trigger can rewrite the row after that UPDATE and still return one affected row. If the writer commits the 48 newly enrolled refs while the frontier stays behind, subsequent maintenance ticks rescan the same 48 owners and repeatedly pay the bootstrap cost.

Fix: after each nonempty bootstrap stage, require a changed frontier, then read back all bootstrap progress fields within the same registered writer transaction and reject mismatches. The existing rollback owner aborts enrolled owner references and body-candidate seeds together. No SQL state is reset or discarded; the durable owner/candidate invariants remain unchanged.

Regression added: 52 raw owners sharing one still-live canonical body, with an AFTER UPDATE trigger that deliberately rewrites raw_through to zero. A 48-row page must fail closed after staging 48 refs; rollback must restore zero refs and the original frontier. Removing the injected fault must produce actual, distinct committed 48+4 raw pages, finish bootstrap and candidate discharge, retain the live body and quiesce. A separate disposable SQLite reproduction with recursive triggers enabled observed refused 48 / durable refs 0, then committed 0→48→52, then idle. This is a mechanistic reproduction, not an affected-host diagnosis or repository Bazel test pass.

Validation: compared the exact two-file commit diff against parent 91ffd680; no changes to metadata parsing, Kev/decision model, held draft #4776, release #4763, infrastructure, credentials or other owner work. Published with expected_sha=91ffd680d7ec128dbf5cd14d9bcc721b4e457a21, force=false and verified the PR head. Local runtime has no Bazel/toolchain or repository checkout; no Cargo. Exact-head hosted CI #42443962770 is queued. Require actual nonzero Bazel unit tests, Rust format/Clippy and reviews on this head.

Still open: this is a verified failure class and rollback guard, not proof this trigger or checkpoint rewrite caused the reported 90–110% production CPU. Correlate consecutive committed GC/replay frontiers and candidate discharge with per-tick duration, rollback diagnostics, and affected-host CPU before a Fixes #4787 claim. The cold-store JSON cursor is a distinct authority. Do not auto-merge; keep #4787 open and #4776 draft/unmerged.

Apply the exact formatting required by the failing Bazel rustfmt gate
in the new canonical-body frontier rollback regression.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — fixed the next exact-head CI blocker on isolated PR #4798.

Bazel CI run 42443962770 failed only the repository Rust formatting gate at crates/tracedecay-global-db/src/observation/canonical_body_gc/tests.rs:598: the new 52-owner checkpoint regression's assert_eq! required a multiline rustfmt layout. Published 21032e3de2e90d2860d8d73b8e10e3c8faf6ffd7 with only the exact formatting change. Verified it is one fast-forward commit after ad3729b, and updated the PR using expected_sha=ad3729b..., force=false. No production behavior or other owner files changed.

Exact-head CI run 42446728946 is queued, not passing yet. Repository Rust/Bazel regressions, affected-host 90–110% CPU and consecutive SQL frontiers/tick timings still require validation. Keep this PR unmerged until the relevant gates pass, keep issue #4787 open until master-proven acceptance, and leave mixed draft #4776 and release #4763 untouched.

Bound replay eligibility admission by the conservative body verification
budget before parsing metadata. Deferred rows no longer incur repeated
JSON validation on successive ticks. Assert exactly-once metadata admission
across database-backed multi-page body-budget regressions.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — published focused replay-CPU work to this issue-specific PR at 8e044d4, a single-parent, nonforce expected-old-head fast-forward from 21032e3. Only crates/tracedecay-lcm/src/retention/replay_metadata.rs and its existing database-backed tests changed.

Defect found in the previous bounded-parsing fix: candidates() enforced its 4 MiB metadata-admission budget before evaluating JSON eligibility, but could still parse eligibility for future eligible rows that step() could not visit because the independent 4 MiB body-verification budget was exhausted. Those deferred rows were JSON-parsed again on later ticks, amplifying CPU despite strictly advancing SQL frontiers. The repair conservatively admits inline candidates under both metadata and body byte estimates before the batched eligibility query. Individually oversized rows still advance without loading or rewriting their bodies; non-inline rows remain ineligible; no per-row database round trips or weakened checks were added.

Falsifiable behavioral regression: extended the real Rust row_and_byte_budgets_advance_a_durable_frontier_and_finished_pages_are_noops fixture to retain each row's actual stored metadata byte length and assert that each body-budgeted page's metadata_bytes_examined equals only its scanned rows, including the final and idle pages. The previous implementation fails the middle-page assertion: it prefetched metadata for more rows than it could scan. Existing receipt, body-preservation, rollback and frontier tests are unchanged.

An independent disposable SQLite size-admission analog with four ~700 KiB canonical/replay rows reproduced the discrepancy: the old 48-row admission submitted 2,800,244 bytes for eligibility despite processing only two rows (1,400,122 bytes of those rows); the corrected admission submits 1,400,122 bytes and resumes the remaining two on the next page. This is not a repository Rust/Bazel or affected-host CPU pass. No Bazel toolchain/checkout is available locally; no Cargo was run. Exact-head CI run 42451037206 is queued; exact-head Rust tests/formatting/Clippy must still pass.

Keep issue #4787 open and retain Refs #4787: the 90–110% affected-host CPU incident is not proven resolved without consecutive committed SQL frontiers, candidate discharge, real per-tick span timings and the CPU trend, followed by master acceptance. Protected mixed #4776 remains draft / never merge, and release #4763, production/infra, tags, credentials and other owner branches/schedules are untouched.

Measure each canonical-body GC and replay-metadata pass from admission
through successful writer commit. Include elapsed milliseconds and
admitted metadata bytes in the existing daemon progress events so an
affected host can distinguish stalled page retries from costly but
advancing backlogs. Preserve the transactional progress guards.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — published focused instrumentation on this issue-specific PR, commit a1b2bcf. The new daemon retention page events report wall-clock elapsed_ms through successful writer commit for both canonical-body GC and replay compaction. Replay events now also report metadata_bytes_examined alongside the already-published durable frontier_before/after, while canonical events retain actual candidates_discharged. This gives affected-host logs real per-page time/cost and transactional progress for deciding whether 48-row ticks are stalled or merely advancing through a backlog. The durations are elapsed wall time, not process CPU samples; metadata_bytes_examined measures admitted SQL eligibility input, not total physical bytes read. No budgets or scheduling were weakened.

I independently checked the exact three-file, single-parent diff against 8e044d4, then published the update with expected_sha=8e044d4..., force=false, and verified the PR head is a1b2bcf. Existing database-backed 48+4, checkpoint-refusal, rollback, and quiescence regressions remain present. No local Bazel executable or repository checkout is available in this runtime; no Rust/Bazel test pass is claimed and no Cargo was used. Exact-head hosted CI is queued.

This is a diagnostic improvement, not an affected-host incident resolution. Affected-host CPU samples and consecutive committed SQL frontier/candidate/tick measurements are still needed. Keep issue #4787 open and PR #4798 under validation, without auto-merge. Protected mixed #4776 remains draft and excluded from merging; release #4763, production, and other issue-owner branches are unchanged.

Apply the exact three rustfmt transformations in the latest failed
repository gate without changing retention behavior.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — published CI remediation 3924b363 to this isolated retention PR. Previous exact-head CI run 42453542610 failed Repository gates only because Bazel rustfmt found three layout diffs: the if let chain in replay_metadata.rs:167 and two elapsed_ms.map_or_else calls in daemon/maintenance.rs:388,441. The new commit applies exactly those three formatting transformations; no behavior or tests were changed. Verified an exact-old-head (a1b2bcf...), nonforce fast-forward and confirmed both remote branch and PR head at 3924b363. New CI run 42458529667 is queued; repository Bazel Rust tests and Clippy are not yet confirmed on this commit. No Cargo used.

Reviewed concurrency: #4813 also edits daemon/maintenance.rs (separate writer admission path); its branch was not touched or rebased. #4776 remains draft and excluded from merging; release #4763 and master untouched. This is not evidence that the original 90–110% affected-host CPU incident is resolved. Keep #4787 open, do not use Fixes, and do not merge or auto-merge without acceptance evidence.

Copy link
Copy Markdown
Owner Author

Refs #4787 — exact-head Bazel Rust validation is now available on CI run 42458529667, head 3924b36324044b9770ebb81fc201b40ae0e55a10 (2026-11-08). The prior “tests queued” status is superseded.

Relevant results: //crates/tracedecay-global-db:unit_test PASSED (121.5s) and //crates/tracedecay-lcm:unit_test PASSED (30.9s), including the published database-backed canonical/replay pagination and checkpoint regressions. Repository formatting/policy gates, Clippy, Dashboard, and Feature gates also passed.

New CI blocker, not a proven #4787 regression: Test Linux (fleet) FAILED four suites:

  • //crates/tracedecay:automation_runner_test: 3 scheduler tests return backend_unconfigured instead of the expected due/lock outcomes. The same three failures at the same lines also occur on unchanged master SHA 91c72aba, master CI 42328697300; not introduced by this retention-only patch.
  • //crates/tracedecay:daemon_suite: unrelated mounted fan-out journey reports workflow.reset_required.
  • //crates/tracedecay:dashboard_api_test: fact detail test times out on fact_store_add.
  • //crates/tracedecay-session-memory:unit_test: canonical temporal-digest test times out. These last three may be environmental/load-sensitive but are not yet baseline-qualified, so their failure cannot be waived.

The separate Linux and Windows legs were still queued/in progress on last check. No CI was weakened and no unrelated owner branches were edited. Keep this PR unmerged until required gates are resolved and independently reviewed. The underlying affected-host 90–110% CPU incident still lacks post-fix repeated-tick SQL-frontier, candidate-count, wall-time and CPU observations; this exact-head Bazel pass establishes code regressions, not production incident resolution. Issue #4787 remains open. #4776 must remain draft/unmerged; #4763 read-only.

Use SQLite record byte lengths without materializing raw text. Defer
storage-kind reads and unnecessary canonical lookups until admission,
and do not read canonical size scalars beyond an oversized BLOB.
Skip eligibility parsing when the stored representations already exceed
the page budget, while preserving the rows and advancing the frontier.

Add an isolated Linux database regression measuring actual read syscall
bytes for oversized inline, metadata, and canonical payloads. Verify
subsequent valid compaction, complete byte preservation, and quiescence.

Refs #4787

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — independent review of the new replay read-cost patch at a945a8b85b4a1f3f146872ff226d3319014b9b21 (one nonforce fast-forward after 3924b363). This changes only the replay size/admission path and a Linux process-I/O behavioral regression; it does not move or duplicate the protected #4776 work.

I exercised the exact new size-discovery SQL in a disposable SQLite 3.46.1 database with 52 inline rows, multibyte/NUL text and a deliberately lowered SQLITE_LIMIT_LENGTH=1024: pages returned 48, then 4, then 0, with exact byte lengths. An ordinary full-content read failed at that limit. A separate file-backed overflow fixture (8 MiB inline body, 8 MiB metadata, 8 MiB canonical BLOB, mmap off) observed only ~8–16 KiB /proc/self/io rchar per isolated size-probe query; that corroborates the avoided full-text materialization, not a daemon CPU benchmark. The older LENGTH(CAST(... AS BLOB)) implementation fails the tight-limit probe.

Review scope: the new conditional canonical join, query budget admission, durable frontier guard and the child-process read-cost regression; no independent correctness issue found in those paths. The new read_cost test is Linux-only and exact-head Bazel CI is still queued, so this is not Rust/Bazel/macOS/Windows execution evidence or proof the affected-host 90–110% CPU incident is resolved. Require exact-head CI and real successive committed frontiers/candidates, per-tick timing, rollback evidence and CPU samples before closing #4787. No approval to merge is implied.

Apply the exact Bazel rustfmt_check_2024 correction at read_cost.rs:62.
No runtime or test behavior changes.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — published CI-format repair ee4dc4cb18947177d78862ed4e1c9f400a7a02d2 to this existing issue-specific PR, preserving all concurrent work with expected_sha=a945a8b85b4a1f3f146872ff226d3319014b9b21, force=false.

Exact-head blocker: run 42470152899 failed Repository gates at //crates/tracedecay-lcm:rustfmt_check_2024, solely on a one-line layout change in crates/tracedecay-lcm/src/retention/replay_metadata/read_cost.rs:62. This commit applies exactly the formatter's displayed transformation. No production SQL or regression semantics changed. The remote PR head has been verified at ee4dc4c.

The superseding exact-head CI run 42477719995 is queued, not a pass. No local Bazel executable available; no Cargo used. The earlier 3924b36 relevant Bazel Rust tests passed, but this new Linux read-cost test still needs an exact-head pass. Keep #4787 open pending full CI and affected-host consecutive committed frontier, candidate discharge, elapsed page/tick and CPU evidence. No Fixes claim. Keep #4776 draft/unmerged; #4813, release #4763 and operator systems untouched.

Refs #4787

Use a fresh exact-SQL test connection for each measured replay page,
so SQLite cannot reuse a warmed per-connection page cache. Remove the
cache/mmap/shrink PRAGMAs rejected by the registered SQL authority.
Keep the byte-read thresholds, 48-row semantics, frontier assertions,
post-repair replay equivalence, and idle checks unchanged.

Copy link
Copy Markdown
Owner Author

Refs #4787 — repaired the exact-head Linux Bazel regression in the isolated issue PR.

CI run 42477719995, head ee4dc4cb, failed //crates/tracedecay-lcm:unit_test because the new oversized_rows_skip_payload_io fixture attempted PRAGMA cache_size / PRAGMA mmap_size through the registered exact-SQL test authority. SQLite refused execute_batch with SQLITE_AUTH (23), not authorized at read_cost.rs:55, before any read-cost assertions ran. PRAGMA shrink_memory used later in the fixture was subject to the same restriction.

Published 33988f731c8d as a single-file test-only correction. It removes the unauthorized PRAGMAs and opens a fresh TestConnection for each measured page, retaining cold per-connection SQLite caches instead of relaxing the process-read assertion. The three oversized cases, retained-byte checks, exact SQL frontier, replay-equivalence assertion and idle termination are unchanged. The commit is a one-parent, expected-old-head ee4dc4cb, force=false fast-forward; remote PR head verified.

New exact-head Bazel CI 42491853590 is pending. I did not run Cargo or claim local Bazel/native macOS tests. The older fleet run also had three scheduler tests known red on master and other broad-suite timeouts; those are not solved by this retention-only correction. Keep #4798 unmerged until exact-head tests and review pass. Original 90–110% affected-host CPU condition still lacks consecutive post-fix candidate discharge, durable SQL frontiers, tick durations and CPU measurements. Issue #4787 remains open; #4776 remains draft/unmerged, #4763 read-only, #4813 separately owned.

Copy link
Copy Markdown
Owner Author

Refs #4787 — exact-head Bazel CI update for 33988f731c8d8de09b2fbeca18fe4572e5599a8c (run 42491853590, 2026-11-08).

The issue-owned regression now passes: //crates/tracedecay-lcm:unit_test (7.2s), including the Linux isolated oversized-replay read-cost test corrected in 33988f7; //crates/tracedecay-global-db:unit_test also passes (280.7s). Repository gates, Clippy, Dashboard and Feature gates are green. This is hosted Bazel execution, not a local Cargo run or a macOS affected-host measurement.

Remaining new CI blockers: Linux fleet still fails automation_runner_test in the same three backend_unconfigured scheduler cases already reproduced on unmodified master 91c72aba (master run 42328697300); do not copy/rework that active ownership into this retention PR. It also fails runtime_acceptance_suite::runtime_surface_acceptance::stdio_bridge_exits_successfully_after_client_shutdown_and_exit with LSP gateway request deadline elapsed; explicit detach failed: ... authority is unavailable. Unlike the scheduler failures, this test passed on that master fleet run, so it is an unqualified new CI failure, not a proven #4787 regression or a known baseline red. The Linux summary job therefore fails. Windows was still in progress at this check. CI remains unweakened.

No new retention-source defect was established from these failures and no unrelated owner code was altered. Keep #4798 unmerged and #4787 open. The original ~90–110% affected-host CPU still requires successive committed GC candidate discharges and replay SQL frontiers, per-page/tick wall-time/CPU observations, and stable host CPU after the fix before incident closure. Protected mixed #4776 remains DRAFT/unmerged; #4813 is separately owned; #4763 and production/infra/tags/credentials remain untouched.

ScriptedAlchemy added a commit that referenced this pull request Nov 9, 2026
Preserve the failed-mount fixture repair from 4984a54 byte-for-byte
in its own reviewable change above the shared scheduler repair #4821.
The rollback journey uses the existing session-retrieval opener,
checks the authoritative session path, and verifies both reopened
projects bind their own session stores. No deadline or assertion is
removed, and the malformed graph must still refuse admission.

This separates CI fixture work from the retention-specific #4798
review without reverting fixes, rewriting history, or editing #4813.
It is not evidence that the affected-host retention CPU incident is
resolved. Refs #4787.
Join the reviewed #4821 and #4827 prerequisite ancestry without
changing the existing #4798 tree. Both prerequisite file blobs
already match this head exactly. Preserve all retention source,
behavioral tests, and concurrent history while allowing a focused
six-file retention review above the prerequisites.

Do not merge into the prerequisite branch. Land prerequisites in
master, retarget, revalidate, and retain the issue acceptance hold.
No changes from #4813, held #4776, or decision-model work are moved.

Refs #4787
@ScriptedAlchemy
ScriptedAlchemy changed the base branch from master to fix/daemon-mount-rollback-fixture November 9, 2026 00:29

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — reconciled and verified the issue-specific review scope.

af1045000305250ac1cefd94e87ea1ddeefc201c was published with force=false, expected prior head 4984a54fc4cf6cd71d2191d60a80639b1f0b183f. The first-parent source tree is IDENTICAL (3f493dd3a148e21f7bbfe8f9f59a14392d00dd8e): GitHub compare reports no changed files. The second parent is the explicit fixture prerequisite #4827, itself based on existing #4821. Compare against that prerequisite now reports exactly six retention files, and the live PR confirms six changed files.

The scheduler fixture is the exact existing #4821 blob 7342786381bcaf3c08454d2dc2711a6c731e7151; the failed-mount fixture is the exact existing #4798 blob 51efc83f65cffb7e27cb3a13eb5297684850f79d, now reviewed separately in #4827. No peer commit was reverted, no assertion or deadline relaxed, and no retention implementation/test removed. This is a scope/ancestry correction, NOT a new CPU-performance claim.

Correction to the earlier blocker: #4813's admission changes and this PR's outcome-log additions occupy separate maintenance.rs hunks. Filename overlap alone did not establish a merge conflict. #4813's current branch and implementation are untouched; combined behavior remains subject to integration tests.

Landing order: #4821 into master; retarget #4827 to master and validate/land through its own review; then retarget #4798 to master and revalidate. DO NOT merge #4798 into its temporary prerequisite branch. Do not auto-merge. The normal PR workflow has no base-branch filter, so this stack does not intentionally skip Bazel CI.

No local Bazel executable is available; no Cargo used. Prior source-equivalent run 42536602973 had passed Repository gates but had not completed Linux at inspection. New exact-head CI is still required. Affected-host consecutive committed SQL-frontier/candidate progress, actual tick timing/CPU and final master acceptance remain missing. Keep #4787 open and retain all protected #4776/Kev and release holds.

Expose the phase-qualified raw, observation and canonical-body SQL
frontiers before and after each successful bootstrap page. Populate
these only after the same-transaction checkpoint readback succeeds;
collection and idle pages cannot masquerade as bootstrap progress.

Log the frontiers with the already measured page cost and discharge
counts. A real SQLite-backed regression checks three distinct phases,
the durable cursor after each tick, retained live content, collection
and quiescence. The existing 52-owner rollback/48+4 regression now
asserts its committed 0->48->52 frontier values.

Refs #4787; not incident acceptance. No CI, dependency, release,
or concurrent writer-admission change.

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — published focused bootstrap SQL frontier diagnostics at ce112eff, then independently re-read the complete three-file commit diff and compared it with the current master implementation.

Previously unobservable: canonical-body GC emitted roots_scanned=48 / bodies_scanned=48 while bootstrapping but no before/after raw/observation/body SQL checkpoint. A repeated page could not be distinguished from consecutive committed progress in the daemon log without separate database access. This change logs phase-qualified bootstrap_frontier_before and bootstrap_frontier_after only after save_progress has read back the persisted checkpoint inside the writer transaction. Collection/idle pages use not_scanned (and retain the existing candidates_discharged and elapsed_ms fields). It does not change GC eligibility, page limit, or scheduling.

Behavioral regression: a real SQL test fixture seeds a referenced raw owner, observation and canonical body; three consecutive ticks must show raw:0→1, observations:0→1, and bodies:→<actual hash>, matching each independently re-read SQL checkpoint. The next tick must discharge the candidate without deleting the referenced body, then quiesce with no fabricated frontier. The existing trigger-rewrite rollback + 52-owner 48+4 recovery regression now also requires committed raw:0→48→52 readings. The patch touches only canonical GC source/tests and the existing daemon outcome log, leaving #4813 writer-admission hunks and the prerequisite fixture PRs unchanged.

Validation hold: local checkout/Bazel is unavailable, so the new Rust regression has not executed here; no Cargo was used. Exact-head hosted Bazel run was queued at inspection. Require nonzero //crates/tracedecay-global-db:unit_test and applicable daemon/Clippy/format checks before merge. This improves diagnosis, not proof that the originally reported affected-host 90–110% CPU is resolved. Consecutive host CPU/tick/frontier evidence and complete acceptance on master are still absent; keep #4787 open. #4776 and Kev drafts remain protected, #4763 read-only.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Owner Author

Refs #4787 — new merge/verification dependency blocker (2026-11-09 UTC). Current #4798 head dfd0c6a10600ecdcd93f7e0fa5ed94611e36de44 still has the six-file retention-specific review diff, but it now depends on #4827, which itself is based on draft #4834 (7264f0d6). #4834's exact-head hosted CI 42554938852 skips Linux Bazel, Clippy and Windows while draft; repository-gate/frontend checks do not establish native Rust qualification. The native macOS fixture results described on #4834 are useful but do not replace the required hosted integration evidence. #4798's own exact-head run 42559320042 was queued/in progress at inspection, not a passing Rust result. Do not merge #4798 into the temporary prerequisite, bypass #4834's review/CI, or conflate pending checks with green. Keep the dependency order #4834 → #4827 → #4798 and revalidate against master after prerequisites land. Current issue-owned source review found no confirmed new retention defect requiring a speculative patch. Affected-host consecutive committed SQL frontiers, tick duration/cadence and CPU samples remain unavailable; do not claim 90–110% CPU resolution or close #4787. #4776 and Kev/decision PRs stay draft/unmerged; #4763, production, CI protections, owner branches and schedules untouched.

Rows skipped by replay eligibility were not counted as skipped,
so the reported 48 scanned / 0 compacted / 0 skipped contradicted
what the page actually examined. Include those intact rows in the
skip count; keep oversized skips as a subset and leave the durable
frontier, eligibility, body reads and scheduling unchanged.

Assert the real SQLite-backed 48+4 ineligible pages, five preserved
representation kinds and multi-tick metadata-budget pages report
true skipped counts while preserving content and quiescence.

Refs #4787

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — published and independently diff-reviewed 9a1c8a27d0 as a two-file retention diagnostics correction, exact expected-old-head dfd0c6a106, nonforce fast-forward.

Confirmed issue-symptom defect: replay compaction increments rows_scanned and commits a strictly advancing store-ID frontier when an eligibility check rejects a structured, external or otherwise noncompactable representation, but did not count that preserved row in rows_skipped. Thus a legitimate page could log 48 scanned / 0 compacted / 0 skipped—exactly the ambiguous pattern reported in #4787—even while it committed progress. The new final else counts these ineligible, preserved rows; rows_skipped_oversized remains a subset. No SQL eligibility, body reads, cursor, byte budget, scheduling, or retention/deletion behavior changes.

The existing real database-backed Rust regressions now require (a) five distinct preserved representation rows -> five skips, (b) 52 ineligible rows -> 48 + 4 scanned and skipped with durable frontiers 0→48→52 and a subsequent idle tick, and (c) each admitted bounded large-ineligible-metadata page -> rows_skipped == rows_scanned, with bytes/frontiers, original messages and receipts preserved. The previous implementation fails these new count assertions. I checked the published commit diff: exactly those two files, one added count branch, documentation and assertions; no test or policy weakening.

Verification hold: local Bazel/checkout is unavailable; no Cargo. New exact-head CI #42566057533 is pending. Require nonzero bazel test //crates/tracedecay-lcm:unit_test --test_output=errors and the other issue-specific/Bazel gates. No affected-host 90–110% CPU or consecutive process/tick evidence is available: this fixes truthful diagnostics, not a proven CPU root cause or issue closure.

Separate integration blocker: #4827 CI #42555076056 completed the Linux fleet with 182/183 targets passing; the unrelated runtime_acceptance_suite::production_lsp_negotiates_and_projects_canonical_context test failed at acknowledge daemon LSP frame: DeadlineExceeded (140/141 tests in that target). //crates/tracedecay:unit_test passed, so the failed-mount fixture is not the observed red target. The prerequisite #4834's explicit Linux/Windows run #42560828022 is in progress. Do not weaken the LSP assertion or infer baseline causality before comparing runs.

#4798 is still stacked behind #4827 → draft #4834 and must not merge into that prerequisite or bypass its review. #4813 is separately owned; protected #4776 and Kev/decision-model #4797 remain DRAFT/unmerged, release #4763 read-only. No master merge, production changes or schedule changes.

Mounted session stores can commit identical 48-row pages in the same
maintenance cycle. Previously their canonical and replay operator lines
had no store identity, so interleaved advancing SQL frontiers appeared
to be the same stalled page. Include the exact mounted database path in
success and refusal events without changing retention or scheduling.

A subprocess regression exercises the actual operator stderr with two
stores both reporting 0->48, requires four uniquely attributable log
lines, and rejects vacuous zero-test success. Refs #4787.

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — source review of exact new head bfba4837.

Confirmed diagnostic defect: MaintenanceCoordinator::run_tick iterates up to eight sorted mounted stores and can emit canonical-GC and replay-metadata page results for different session databases in one cycle. Both operator events lacked a store identifier. Two independent databases each advancing 0→48 therefore produced indistinguishable reported frontiers, making an apparently repeated 48-row page insufficient evidence of a same-store livelock.

Published one-file fix: pass the exact mounted RegisteredGlobalDb::db_path() through both full and continuation reporting paths. Add store to successful canonical/replay page events and to their degraded/refusal events. This changes only logging and source-level test coverage; neither database/frontier, deletion eligibility, 48-row budget, writer admission nor tick scheduling changes. The independently inspected diff is exactly one file (84 additions / 4 deletions), with no changes to #4813 or the prerequisite branches.

Behavioral regression: an isolated child test calls the actual operator logger for two distinct mounted paths that both report 48 rows and exactly the same SQL frontier 0→48. It requires four emitted stderr events, exactly one uniquely attributable event of each type per store, and nonzero libtest execution; previously the store-disambiguation assertions would fail. No output-string/source-shape inventory or synthetic DB CPU benchmark is substituted for affected-host evidence.

Validation hold: the Rust test has not executed on this head: local Bazel/checkout is unavailable; no Cargo. Exact-head hosted CI is queued. Require nonzero //crates/tracedecay:unit_test, other two retention unit targets, Clippy, rustfmt and peer review before merge. This solves log attribution, not the original 90–110% CPU incident; consecutive same-store committed SQL frontiers, per-tick elapsed/work counts and affected-host CPU/restart/quiescence remain necessary. Keep #4787 open, Refs only.

Held #4776 / Kev and #4797 remain draft/nonmergeable; #4763, production, other owner branches and schedules unchanged.

Keep selected unreferenced body candidates queued if the underlying DELETE
was ignored. Verify the body is absent before discharging its candidate;
otherwise rollback the page instead of silently leaking unreclaimed bodies.

Exercise 52 real candidates with a vetoed DELETE, rollback, recovery,
48+4 committed reclamation, and an idle final tick.

Refs #4787

Copy link
Copy Markdown
Owner Author

Refs #4787 — published and independently diff-reviewed source fix at c3f2d94d2bcc on this issue-specific PR, exact old head f3b937a0, force=false. Only canonical-body GC and its database-backed Rust tests changed; the prerequisite and admission-owner branches were not modified.

Confirmed failure mode: collect_candidates used the count of explicit candidate-row deletions plus body DELETE RETURNING as proof of complete discharge. SQLite's BEFORE DELETE ... RAISE(IGNORE) can suppress deletion of a still-unreferenced body. The old code nevertheless removed that body's candidate, reported success, and lost the only guaranteed future GC re-enqueue. A disposable SQLite reproduction demonstrated a surviving orphan body with zero candidates after the old sequence.

Fix: Before deleting candidate rows, verify every selected body that still exists is actually owned by a canonical reference. A surviving unreferenced body makes the transaction return a typed integrity error, so the caller rolls back rather than claiming progress. The new Rust regression uses 52 real inserted candidates and a vetoing SQLite trigger: it requires refusal and preservation of all 52 candidate/body rows, then removes the trigger and asserts successful 48+4 deletion/discharge, zero remaining candidates, and an idle final tick. The same SQL logic passed an independent SQLite rollback/recovery probe, not the repository Rust/Bazel suite.

Exact-head CI run 42763155068 is queued. Bazel is not installed in this runtime, and Cargo was not used. This closes a real silent-GC-leak hole, not the original observed 90–110% CPU root cause: affected-host consecutive same-store SQL frontiers, real tick cadence and CPU, restart/quiescence, and final master acceptance remain unproven. Keep #4787 open and Refs-only. Do not merge or auto-merge held #4776/Kev drafts.

Replace per-owner and per-body bootstrap INSERT submissions with one
indexed INSERT SELECT per bounded page. Keep the selected last identity,
sparse-key semantics, eligibility predicate and transactional checkpoint.

Add real SQLite executor regressions for bounded write submissions,
52-row sparse frontiers, live-body preservation, eligibility at the page
tail, and late statement failure with full rollback and successful retry.
Preserve the concurrent vetoed-delete repair without rewriting history.

Refs #4787

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Published bootstrap batching repair — Refs #4787

Pushed eb9bd17 on top of the concurrent c3f2d94. This changes the canonical-body bootstrap implementation and adds one test module; the PR now has seven retention-specific paths rather than six. No prerequisite branch was changed.

Source defect and correction

A full eligible raw-owner bootstrap page, or a canonical-body candidate-seeding page, submitted 48 separate awaited INSERTs through the SQLite executor before its checkpoint write. Replace those per-row INSERTs with one indexed INSERT OR IGNORE ... SELECT bounded by the last identity selected for the page. Selection and insertion stay inside the same writer transaction. Sparse IDs, the inline/canonical ownership predicate, the 48-row cap, frozen upper bounds, checkpoint verification and rollback remain intact. The observation-reference bootstrap is unchanged.

The independent SQLite mechanism reproduction compared identical 52-row inputs: full eligible pages used 49 → 2 execute submissions, including the checkpoint; four-row tails used 5 → 2. Sparse raw frontiers advanced 0 → 96 → 104 with identical enrolled owners. Late insertion failure rolled back the page and checkpoint, and retry recovered. Mixed ineligible tail rows preserved the page boundary. These are SQL-call counts, not measured Rust worker timings or an affected-host CPU reduction; read queries and commit calls are not included in that count. A nonempty all-ineligible raw page may now issue an empty batched INSERT.

Committed behavioral regressions

bootstrap_write_tests.rs forwards the real executor to a real SQLite transaction and counts write submissions; it does not replace the database with a mock or assert source strings.

  • bootstrap_pages_batch_writes_and_preserve_sparse_frontiers: 52 real canonical bodies and sparse raw owners, distinct 48+4 raw/body pages, bounded write submissions, exact durable frontiers/owners, 48+4 candidate discharge, zero deletion of live bodies, original BLOB preservation and idle completion.
  • bootstrap_batch_refusal_rolls_back_and_recovers: inject a late SQLite RAISE(FAIL) separately during raw-owner and body-candidate seeding; require refusal, exact checkpoint rollback, no committed partial entries, body preservation and successful 48+4 retry.
  • bootstrap_batch_eligibility_does_not_change_the_page_boundary: external and directly stored-text owners at the end of a full page do not expand the admitted range or consume the following four owners.

Review, publication and validation limits

I inspected the detached commit diff in a separate review pass before attaching it. It contains only the module declaration and two bootstrap changes plus the new regressions. The concurrent vetoed-body-delete guard and its existing tests remain unchanged. Publication used force=false and exact expected old head c3f2d94d2bcc4b7c70e074e06e3b7b294c2452aa; the remote ref was then verified at eb9bd17.

The new Rust tests have not executed locally. No Bazel executable/complete checkout is available here; no Cargo, direct rustc or rustfmt was used. Exact-head CI 42764859366 is queued. Require nonzero execution of the new cases under bazel test //crates/tracedecay-global-db:unit_test --test_output=errors, the existing retention suites, pinned formatting/Clippy and required hosted checks. This COMMENT is not independent reviewer approval or a merge authorization.

The separate queued-writer head-of-line blocker reviewed on #4834 is not repaired by this patch. The original sustained 90–110% CPU incident still needs same-store committed frontiers, real tick/CPU and restart/quiescence measurements and acceptance on master. Keep #4787 open, Refs only. No merge, protected #4776/Kev draft change, release #4763, production/infra, credential, tag or schedule action was performed.

Group validated observation reference inserts into bounded storage-worker
submissions instead of one asynchronous request per referenced hash.
Preserve Rust reference parsing, identity order and transactional rollback.

Prove 48+4 pages across the 128-statement boundary, durable SQL frontiers,
partial-batch refusal/rollback, reference deduplication and quiescence.

Refs #4787

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — independent follow-up review of exact head 9b50818107afea5486193022122c3a45f9a5b40d.

The previous observation bootstrap performed one awaited INSERT OR IGNORE per distinct canonical hash in the selected 48-owner page. This commit retains the existing collect_body_refs validation/deduplication and selected-ID frontier, but uses the engine's owned WriteStatement / Transaction::execute_statements path in at most 128 pending writes per submission. The existing writer transaction owns all groups and the checkpoint; a late refusal rolls everything back. No SQL page-size, retention cadence, policy, or test assertion was relaxed.

Reviewed the two-file commit against eb9bd17c and its real production caller. The new database-backed Rust cases require 48+4 observation pages with 141 then 153 distinct indexed references, 128+13 writes on the first page across two batch submissions plus the checkpoint, exact 0→96→104 persisted observation frontiers, body preservation, idle quiescence, and rollback after a deliberately refused insert following a completed first batch, then recovery.

Independent disposable on-disk SQLite reproduction passed the injected refusal/rollback and recovery: first 48-owner page = 141 refs / 3 submissions including checkpoint, next 4-owner page = 12 additional refs / 2 submissions, no repeated page after frontier 104, all 52 canonical bodies retained across reopening. This reproduction measures submission count rather than production daemon CPU or storage-worker duration, and is not Rust/Bazel CI.

Hold merge/issue closure: exact-head Bazel CI is queued at https://github.com/ScriptedAlchemy/tracedecay/actions/runs/42768531776; no Bazel executable is available in this runtime, no Cargo was used. The original affected-host 90–110% CPU incident still requires consecutive same-store committed SQL frontiers/candidate counts, actual per-tick CPU and cadence, restart/quiescence, and verified acceptance on master. This is partial work only; no Fixes #4787 claim. Protected #4776/Kev drafts and release #4763 unchanged.

After batched bootstrap writes, verify the selected raw owner references,
Rust-validated observation references, and canonical-body candidates exist
inside the writer transaction. A suppressed INSERT must not commit a frontier
that can drop a live body or permanently abandon an orphan.

Exercise RAISE(IGNORE) for all three phases, rollback, 48+4 recovery,
and live-data preservation.

Refs #4787

@ScriptedAlchemy ScriptedAlchemy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refs #4787 — source-integrity review of exact published commit 6edf06957b7bff930d19e6956f6573ac90d22da7 against 9b50818107afea5486193022122c3a45f9a5b40d.

Confirmed failure class: The three canonical-body bootstrap phases previously treated successful INSERT OR IGNORE submissions as proof of derived ownership/candidate enrollment. A SQLite BEFORE INSERT ... RAISE(IGNORE) trigger can suppress one selected entry without returning an error; the old path would still commit the raw/observation/body bootstrap frontier. Missing raw/observation references could then make live bodies appear orphaned; missing candidates could strand unreferenced bodies behind the committed cursor.

Published correction: After raw-owner batching, observation WriteStatement batches, and body-candidate seeding, verify the actual selected identities in the same guarded SQLite writer transaction before save_progress. Observation verification uses the exact Rust-validated/deduplicated owner/hash pairs rather than reparsing original observation documents; legitimate already-existing derived entries remain valid. Any missing item produces a typed error and rolls back the entire page. The 48-row page cap, eligibility, and checkpoint authority remain unchanged.

New database-backed Rust regressions: Deliberately suppress one raw reference, one observation reference after a full 128-statement group, and one 48th candidate; require refused checkpoint, full rollback, recovery of distinct 48+4 pages and preservation of all 52 live body blobs. Existing duplicate, sparse-key, candidate discharge and idle tests remain intact.

Independent SQLite (not Bazel) validation: Three in-memory trigger-refusal scenarios each found the omitted entry; rollback retained no partial derived state; subsequent recovery indexed 52 entries in bounded pages. The exact SQL verification against 141 distinct observation pairs also detected one suppressed owner and passed after restoring the three references. There is no local repository checkout or Bazel executable, so no claim of Rust/Bazel execution or affected-host CPU reduction. New exact-head hosted CI is pending.

This is a partial safety/progress repair, not resolution of the original sustained 90–110% CPU incident. #4787 must stay open pending actual same-store committed frontier/tick/CPU/restart evidence and master-proven acceptance. Protected #4776/Kev drafts and release #4763 remain untouched; publication used exact-old-head 9b50818107af and force=false.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant