Skip to content

feat(backend): coordinate bounded startup reconciliation sweep - #321

Draft
sandersonstabo wants to merge 5 commits into
agent/database-startup-reconciliation-disposition-port-52642bffrom
agent/backend-startup-reconciliation-sweep-port-1a5eff2
Draft

feat(backend): coordinate bounded startup reconciliation sweep#321
sandersonstabo wants to merge 5 commits into
agent/database-startup-reconciliation-disposition-port-52642bffrom
agent/backend-startup-reconciliation-sweep-port-1a5eff2

Conversation

@sandersonstabo

@sandersonstabo sandersonstabo commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

Depends on #320.

Scope

  • add one bounded, expired-only startup-reconciliation sweep coordinator
  • inject deterministic per-candidate patch identities and validate item/patch shape before mutation
  • report interrupted, identical replay, moved, attempted, and discovered counts with honest committed-prefix errors
  • prove discovery ordering/limits, moved concurrency, identical durable replay, prefix failures, validation, and rollback behavior

Exclusions

  • no storage opening, cross-process custody, provider contact, retry/requeue loop, timers, scheduling, or Forge startup wiring
  • no remote merge or master update

Verification

  • focused backend/test build passed
  • 11 focused tests passed
  • fresh production and test Clippy markers passed under workspace all+pedantic deny policy
  • root format, locked/offline Cargo metadata, exact seven-path hashes/status/diff guards passed
  • Bazel shutdown exit 0

Known next work

  • assemble the sweep behind an explicit custody/startup policy after the pending cross-process ownership decision

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Adds a bounded startup-reconciliation sweep coordinator that disposes expired candidates once per pass in deterministic lease order, with caller-supplied patch identities and honest prefix error reporting.

  • Validates limits (1..=64) and patch-shape agreement before mutating any candidate.
  • Reports discovered, attempted, interrupted, already-interrupted, and skipped-moved counts via checked arithmetic.
  • Returns the already-committed prefix report with failing candidate index and run identity; error displays stay content-free and bounded.
  • Keeps storage opening, custody, provider contact, retries, timers, and Forge startup wiring out of scope.
  • Adds 11 focused tests covering ordering, limits, moved/replay races, patch-source failures, shape disagreement, overflow, and prefix honesty.

Written for commit bee13c2. Summary will update on new commits.

Review in cubic

Adds single-pass coordinator over injected Repository with caller-injected
operated_at and validated limit 1..=64. Patch identities are caller-minted
via synchronous StartupReconciliationPatchSource trait, validated for shape
agreement before any mutation. Calls discovery once in deterministic order
then disposes sequentially, returning typed report with discovered/attempted/
interrupted/already_interrupted/skipped_moved counts via checked arithmetic.
Stops on first source or disposition error carrying prefix report, failing
index and run identity without leaking patch material. Empty pass is success;
one pass never loops, sleeps or contacts providers. Keeps error displays
content-free and bounded.

Tests prove empty pass, ordering/limit, launching/no-item vs running/with-item
shapes, moved counting, identical replay as already_interrupted, source
failure prefix reporting, disposition failure prefix honesty, and invalid
limit/overflow/shape disagreement without mutation of failing candidate.

VP owns Cargo/Bazel/module/export registration.
…lay sweep

Removes nested Handle::block_on from StalingSource which could panic
inside tokio::test. Models the true race: discovery obtains a non-terminal
snapshot, then an external OS thread with its own Tokio runtime moves or
identically disposes the target after discovery and before disposition,
synchronized via bounded std::sync::mpsc::sync_channel rendezvous reached
from the synchronous patch-source call. Patch source no longer owns a DB
handle or performs I/O.

For moved, external thread bumps the run row to make the fence stale;
sweep counts skipped_moved, leaves target unmutated, and still commits
later candidates. For identical replay, external thread invokes the
accepted atomic dispose with the same candidate and deterministic patch IDs;
sweep reports already_interrupted, creates no duplicate patch/counter
advance, and continues later candidates. Removes impossible pre-seal and
empty-second-pass narrative.

All 11 tests pass via file-backed temp DB for concurrent cases.
…esses

Removes unused ConversationPatchKind and StartupRunLifecycle imports.
File-backed TempDatabase now drops pool clones, closes DatabaseConnection,
then removes the database file and SQLite sidecars (-wal/-shm/-journal)
with NotFound tolerated and any other error failing the test; best-effort
panic Drop remains but no longer replaces explicit success-path cleanup and
no longer uses remove_dir_all on a broad directory. Both race witnesses
retain zero-capacity channel rendezvous and explicit external thread join.

Verified with Rust 1.98 rustfmt, 11 isolated tests, and strict
isolated clippy -D warnings -D clippy::all -D clippy::pedantic (owned file
clean; narrow allowances only for exhaustive DB proofs).
lib: replace wildcard match on StartupReconciliationError with explicit Repository variant binding; add documented function-scoped too_many_lines allowance for intrinsically sequential bounded coordinator

tests: move local patch sources to module top to fix items_after_statements; add narrow too_many_lines allowances for exhaustive proofs and too_many_arguments for commit helper; rename _temp to temp; fix single-char pattern; remove unused imports

Verified with Rust 1.98 rustfmt, 11 isolated tests, strict cargo clippy -D warnings -D clippy::all -D clippy::pedantic on both lib and test (exit 0), git diff --check clean
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