Skip to content

feat(daemon): close two automagic-invariants convergence gaps - #3286

Merged
Sinity merged 3 commits into
masterfrom
feature/daemon/automagic-convergence-gaps
Jul 26, 2026
Merged

feat(daemon): close two automagic-invariants convergence gaps#3286
Sinity merged 3 commits into
masterfrom
feature/daemon/automagic-convergence-gaps

Conversation

@Sinity

@Sinity Sinity commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

Closes two verified gaps found while auditing the daemon's "automagic invariants" doctrine against actual behavior: blob-GC had no periodic daemon path at all, and embedding-orphan-reconcile's manual apply path was redundant with (and admittedly demoted-not-deleted next to) its own automatic daemon equivalent.

Problem

An audit comparing this repo's stated doctrine ("if Polylogue can maintain a condition fully automatically, it generally should... the redundant manual surface is DELETED, not demoted to escape-hatch status", polylogue-gd6v/4jsk) against actual runtime behavior found:

  1. polylogue ops maintenance blob-gc (reclaiming unreferenced, aged-out content-addressed blobs — a purely mechanical refcount/age decision) had no daemon-periodic equivalent at all, unlike every comparable mechanical maintenance operation (FTS merge, WAL checkpoint, embedding orphan reconcile).
  2. embedding-orphan-reconcile's --yes apply path is redundant: periodic_embedding_orphan_reconcile_check has run the exact same reconciliation automatically every 900s since it shipped, and the CLI docstring already said as much — "this command remains the break-glass inspect/apply path" is the precise anti-pattern the 2026-07-19 ruling names and forbids.

Two other candidate gaps from the same audit turned out not to be real gaps on closer inspection, and are intentionally NOT touched by this PR:

  • missing_bytes_reacquire raw-authority obligations are already re-classified every 30s by _converge_raw_authority_frontier (part of the existing raw-materialization convergence loop) — no gap.
  • judgment_automation_enabled (assertion-candidate auto-judgment, default off) is an unrelated subsystem from raw-authority frontier conflicts, and its default is an explicit write-authority security boundary, not something to flip as a side effect of this audit.

Solution

  • New polylogue/daemon/blob_gc_periodic.py: periodic_blob_gc_check runs one bounded batch (max 200 blobs) every 900s through the daemon write coordinator, structurally mirroring periodic_embedding_orphan_reconcile_check (same transient-lock retry handling, same catch_up_complete gating). No changes to run_blob_gc_report's existing safety invariants (referenced-blob check, generation-age gate, bounded batch, planning outside the destructive lock) — this only adds a caller.
  • embedding-orphan-reconcile is now permanently read-only: removed --yes, the RebuildLease/offline-exclusive apply branch, and the now-dead dry_run=False rendering branch.

Verification

  • devtools test tests/unit/daemon/test_blob_gc_periodic.py — 4 passed, including a DaemonWriteCoordinator production-route proof (bypassing run_sync makes the test fail).
  • devtools test tests/unit/cli/test_archive_maintenance_cli.py -k embedding_orphan — 4 passed, including a new test proving --yes is now rejected as an unknown option.
  • devtools verify --quick — pass.

Summary by CodeRabbit

  • New Features

    • Added periodic background garbage collection for unused blobs, including retry handling for temporary archive locks.
    • Added a single-pass blob cleanup operation that removes eligible, unreferenced files.
  • Bug Fixes

    • Changed embedding-orphan reconciliation to read-only inspection mode.
    • Removed the --yes option and manual deletion capability from the reconciliation command.
  • Documentation

    • Updated topology metadata and status counts to reflect the new maintenance component.

Sinity and others added 2 commits July 27, 2026 00:24
Problem: unlike every other mechanical, non-judgment maintenance
operation (FTS merge, WAL checkpoint, embedding orphan reconcile — all
of which already have a daemon-owned periodic equivalent),
`polylogue ops maintenance blob-gc` had no automatic path at all.
Reclaiming an unreferenced, aged-out content-addressed blob is a pure
mechanical decision (refcount==0 and past the generation-age gate,
storage/blob_gc.py) with no judgment content, so leaving it
manual-invocation-only was a plain, un-tracked gap against this
repo's "if Polylogue can maintain a condition fully automatically, it
generally should" doctrine (polylogue-gd6v/4jsk).

What changed: new polylogue/daemon/blob_gc_periodic.py runs one bounded
batch (max 200, matching embedding-orphan-reconcile's shape) every 900s
through the daemon write coordinator, mirroring
periodic_embedding_orphan_reconcile_check's structure exactly (same
transient-lock retry handling, same catch_up_complete gating). The
existing safety invariants in run_blob_gc_report (referenced-blob check,
generation-age gate, bounded batch, planning outside the destructive
lock) are unchanged -- this only adds a caller.

Verification: devtools test tests/unit/daemon/test_blob_gc_periodic.py
(4 passed, including a DaemonWriteCoordinator production-route proof);
devtools verify --quick (pass).

Co-Authored-By: Claude <noreply@anthropic.com>
Problem: this command's own docstring already admitted the anti-pattern
the automagic-invariants ruling (polylogue-gd6v/4jsk, 2026-07-19) names
and forbids: "daemon convergence reconciles these automatically...
this command remains the break-glass inspect/apply path." The ruling is
explicit that a redundant manual surface must be deleted once its
automatic equivalent exists, not demoted to break-glass status --
periodic_embedding_orphan_reconcile_check (polylogue/daemon/
embedding_backlog.py) has run this exact reconciliation on a 900s
cadence since it shipped, making the CLI's --yes apply path pure
standing debt.

What changed: embedding-orphan-reconcile is now permanently read-only
-- removed --yes, the RebuildLease/offline-exclusive apply branch, and
the dead dry_run-false rendering branch (report.dry_run is always True
by construction now). Removed the apply-path tests
(cli_apply_removes_rows, cli_apply_is_bounded_by_default,
cli_apply_requires_exclusive_offline_lease,
cli_apply_refuses_stale_index_schema) and added one proving --yes is
rejected as an unknown option.

Verification: devtools test tests/unit/cli/test_archive_maintenance_cli.py
-k embedding_orphan (4 passed); devtools verify --quick (pass).

Co-Authored-By: Claude <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Sinity, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2243dff7-5e67-4b0f-b30d-0649431e1816

📥 Commits

Reviewing files that changed from the base of the PR and between 185061c and 43a3c24.

📒 Files selected for processing (1)
  • tests/unit/cli/test_archive_maintenance_cli.py
📝 Walkthrough

Walkthrough

The change makes embedding orphan reconciliation strictly read-only, adds daemon-managed periodic blob garbage collection with coordinator execution and tests, and refreshes generated topology metadata and status counts.

Changes

Embedding orphan diagnostics

Layer / File(s) Summary
Read-only embedding reconciliation
polylogue/cli/commands/maintenance/_embeddings.py
Removes the --yes apply path and mutation guards, always runs in preview mode, and updates help and plain-text output.
CLI contract validation
tests/unit/cli/test_archive_maintenance_cli.py
Verifies that --yes is rejected as an unavailable option.

Periodic blob garbage collection

Layer / File(s) Summary
Blob-GC execution path
polylogue/daemon/blob_gc_periodic.py
Adds bounded one-pass and periodic blob-GC execution with catch-up gating, lock retry handling, and error logging.
Daemon maintenance registration
polylogue/daemon/cli.py
Registers the periodic blob-GC check in the daemon’s background loop set.
Blob-GC behavior tests
tests/unit/daemon/test_blob_gc_periodic.py
Tests missing-path handling, orphan deletion, and coordinator-based execution.

Topology metadata refresh

Layer / File(s) Summary
Generated topology projection
docs/plans/topology-target.yaml
Updates module loc metadata and adds the new periodic blob-GC module.
Topology status counts
docs/topology-status.md
Updates stable, declared, and realized module totals.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Daemon
  participant DaemonWriteCoordinator
  participant BlobGC
  Daemon->>DaemonWriteCoordinator: Schedule maintenance.blob_gc
  DaemonWriteCoordinator->>BlobGC: Run bounded garbage collection
  BlobGC-->>DaemonWriteCoordinator: Return reclaimed blobs and bytes
  DaemonWriteCoordinator-->>Daemon: Return result or transient lock error
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it omits the required Changelog section for the user-visible CLI flag removal and output changes. Add a Changelog entry for the removed --yes flag and output changes, and include Risks/Follow-ups only if needed.
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the daemon-focused change set.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/daemon/automagic-convergence-gaps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unit/cli/test_archive_maintenance_cli.py`:
- Around line 1301-1308: Update the embedding-orphan-reconcile CLI test to avoid
asserting Click’s unstable “no such option” wording. Keep the rejected-option
assertion by requiring exit code 2, verify result.exception is a Click
UsageError (or equivalent expected exception), and retain the check that “--yes”
appears in the output.

In `@tests/unit/daemon/test_blob_gc_periodic.py`:
- Around line 62-69: Update the test helper _backdate to use the repository’s
frozen_clock fixture when setting the blob mtime, deriving an old timestamp from
the frozen instant rather than hard-coding epoch zero. Ensure the age-gate test
remains deterministically older than MIN_AGE_S while using frozen_clock for all
timestamp-sensitive behavior.
- Around line 112-117: Update the test’s run function to call the synchronous
DaemonWriteCoordinator.run_sync method without await, and invoke it directly
instead of wrapping it with asyncio.run. Remove the now-unused asyncio import
while preserving the existing arguments and result assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 927ba287-0c60-405c-bbf9-76174055b57d

📥 Commits

Reviewing files that changed from the base of the PR and between f4cd341 and 185061c.

📒 Files selected for processing (7)
  • docs/plans/topology-target.yaml
  • docs/topology-status.md
  • polylogue/cli/commands/maintenance/_embeddings.py
  • polylogue/daemon/blob_gc_periodic.py
  • polylogue/daemon/cli.py
  • tests/unit/cli/test_archive_maintenance_cli.py
  • tests/unit/daemon/test_blob_gc_periodic.py

Comment thread tests/unit/cli/test_archive_maintenance_cli.py Outdated
Comment on lines +62 to +69
def _backdate(blob_store: BlobStore, blob_hash: str) -> None:
"""Backdate a blob's mtime well past MIN_AGE_S (60s) so it is GC-eligible.

A fixed epoch (not a `time.time()`-relative offset) avoids any host-clock
read in the test itself -- GC eligibility only needs "old enough", not a
real elapsed duration.
"""
os.utime(blob_store.blob_path(blob_hash), (0, 0))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use frozen_clock for the age-gate test.

This test is timestamp-sensitive but hard-codes an epoch instead of using the repository’s required frozen_clock fixture. Derive the old mtime from the frozen instant, or freeze the clock around the GC call.

As per coding guidelines, timestamp-sensitive tests must use frozen_clock.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/daemon/test_blob_gc_periodic.py` around lines 62 - 69, Update the
test helper _backdate to use the repository’s frozen_clock fixture when setting
the blob mtime, deriving an old timestamp from the frozen instant rather than
hard-coding epoch zero. Ensure the age-gate test remains deterministically older
than MIN_AGE_S while using frozen_clock for all timestamp-sensitive behavior.

Source: Coding guidelines

Comment on lines +112 to +117
coordinator = DaemonWriteCoordinator()

async def run() -> object:
return await coordinator.run_sync("maintenance.blob_gc", run_blob_gc_once, db_path, blob_dir)

result = asyncio.run(run())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not await the synchronous coordinator API.

DaemonWriteCoordinator.run_sync is a regular synchronous method (see polylogue/daemon/write_coordinator.py, Lines 403-413). Awaiting its returned BlobGCResult raises TypeError, so this test fails before its assertions.

Suggested fix
-    async def run() -> object:
-        return await coordinator.run_sync("maintenance.blob_gc", run_blob_gc_once, db_path, blob_dir)
-
-    result = asyncio.run(run())
+    result = coordinator.run_sync("maintenance.blob_gc", run_blob_gc_once, db_path, blob_dir)

Remove the now-unused asyncio import as part of the fix.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
coordinator = DaemonWriteCoordinator()
async def run() -> object:
return await coordinator.run_sync("maintenance.blob_gc", run_blob_gc_once, db_path, blob_dir)
result = asyncio.run(run())
coordinator = DaemonWriteCoordinator()
result = coordinator.run_sync("maintenance.blob_gc", run_blob_gc_once, db_path, blob_dir)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/daemon/test_blob_gc_periodic.py` around lines 112 - 117, Update
the test’s run function to call the synchronous DaemonWriteCoordinator.run_sync
method without await, and invoke it directly instead of wrapping it with
asyncio.run. Remove the now-unused asyncio import while preserving the existing
arguments and result assertions.

CodeRabbit review on #3286: "no such option" matches Click's current
NoSuchOption text but isn't a stable public contract. Assert
exit_code == 2 (Click's CliRunner converts a rejected option into
SystemExit(2) before invoke() returns, so the original UsageError
itself is not what result.exception carries) plus the option name in
the output instead.

Co-Authored-By: Claude <noreply@anthropic.com>
@Sinity

Sinity commented Jul 26, 2026

Copy link
Copy Markdown
Owner Author

Addressed the Click-wording finding (now asserts exit_code == 2 + option name in output, not Click's internal error text).

The other two don't hold up:

"Do not await the synchronous coordinator API" — this is incorrect for the class actually used here. DaemonWriteCoordinator.run_sync (polylogue/daemon/write_coordinator.py:227) is async def; the suggested non-async call would itself be the bug (returns a coroutine, never actually runs the GC pass). The suggestion appears to be confusing it with a different, similarly-named sync wrapper elsewhere in the same file (used by the HTTP thread bridge, not by tests). Confirmed empirically, not just by reading: the test as written passes (4 passed), and it's the exact same coordinator = DaemonWriteCoordinator(); async def run(): return await coordinator.run_sync(...); asyncio.run(run()) pattern already used in tests/unit/daemon/test_embedding_orphan_reconcile_daemon.py::test_daemon_coordinator_owns_real_orphan_reconcile_mutation, which also passes today.

"Use frozen_clock for the age-gate test" — not applicable: _backdate sets a blob's mtime to a fixed epoch (0), it doesn't read the host clock at all. frozen_clock pins what time.time()/datetime.now() return to code under test; there's no such call here to pin. devtools verify --quick's verify-test-clock-hygiene step (which does flag real host-clock reads via AST) already passes on this file.

@Sinity
Sinity merged commit e9c3d88 into master Jul 26, 2026
3 checks passed
@Sinity
Sinity deleted the feature/daemon/automagic-convergence-gaps branch July 26, 2026 23:30
Sinity added a commit that referenced this pull request Aug 2, 2026
Problem

Auditing ops maintenance/doctor manual repair surfaces against the
automagic-invariants doctrine (polylogue-cfvvt) against PR #3286's own
precedent found an inconsistency: that PR added
daemon/blob_gc_periodic.py's periodic_blob_gc_check (reclaiming eligible
blobs automatically every 900s in bounded batches through the write
coordinator) and, in the same change, removed
embedding-orphan-reconcile's --yes apply path because its own periodic
reconciler made it redundant. blob-gc's --yes survived that PR by
omission even though the identical reasoning applies: the manual
mutate path is now doing nothing periodic_blob_gc_check doesn't already
do.

Solution

- polylogue/cli/commands/maintenance/_blob_gc.py: removed --yes and the
  apply branch from blob_gc_command; the command is now always a
  dry-run preview (mutates always False), matching
  embedding-orphan-reconcile's read-only shape. gc-history (audit trail
  read) is untouched. storage/blob_gc.py (run_blob_gc_report, dry_run
  param) is untouched -- the daemon's periodic caller still uses it
  with dry_run=False.
- Updated the command's help text in maintenance/__init__.py and
  replaced test_blob_gc_cli_yes_deletes_and_records_generation with
  test_blob_gc_cli_has_no_mutate_flag, mirroring
  test_embedding_orphan_reconcile_cli_has_no_mutate_flag's
  exit-code-2/--yes-rejected assertion pattern.
- polylogue/storage/message_type_backfill.py: added a docstring
  paragraph documenting why this doctor-repair target is KEEP (finite
  one-time legacy-row remediation, no recurring daemon condition since
  new-ingest rows are classified correctly since PR #836/#944) as part
  of the same audit.

The audit's other findings (blob-reference-prune-orphans/
replace-from-source and embeddings-rescue: KEEP, no daemon path exists
and both require genuine judgment or are one-time migrations; doctor's
5 destructive cleanup targets: KEEP, destructive=True by design with no
daemon caller; doctor's session_insights repair target: proven
redundant by the same shape but scoped out to a dedicated follow-up,
polylogue-ygfwa, given its wider surface coupling) required no code
changes and are recorded in polylogue-cfvvt's notes.

Verification

- devtools test tests/unit/cli/test_archive_maintenance_cli.py -k
  blob_gc -- 3 passed
- devtools test tests/unit/daemon/test_blob_gc_periodic.py -- 4 passed
- devtools render all --check -- clean, no "out of sync" surfaces
- devtools verify --quick -- exit 0, all 19 steps green
- tests/unit/storage/test_blob_gc.py's 7 failures are pre-existing
  (clock_guard time.time() violations in code this change never
  touches) and unrelated to this diff

Ref polylogue-cfvvt

Co-Authored-By: Claude <noreply@anthropic.com>
Sinity added a commit that referenced this pull request Aug 2, 2026
## Summary

Audits four candidate manual `ops maintenance`/`ops doctor` repair surfaces (polylogue-cfvvt) against the automagic-invariants doctrine and deletes the one confirmed-redundant mutate path found: `ops maintenance blob-gc --yes`.

## Problem

PR #3286 added `daemon/blob_gc_periodic.py`'s `periodic_blob_gc_check` (reclaims eligible, aged-out, unreferenced blobs automatically every 900s in bounded batches of 200 through the write coordinator) and, in the same change, removed `embedding-orphan-reconcile`'s `--yes` apply path because its own periodic reconciler made manual apply redundant. `blob-gc`'s `--yes` survived that PR by omission even though the identical reasoning applies: the manual mutate path does nothing `periodic_blob_gc_check` doesn't already do on its own.

## Solution

- `polylogue/cli/commands/maintenance/_blob_gc.py`: removed `--yes` and the apply branch from `blob_gc_command`; the command is now always a dry-run preview (`mutates` always `False`), matching `embedding-orphan-reconcile`'s read-only shape. `gc-history` (audit-trail read) is untouched. `storage/blob_gc.py` (`run_blob_gc_report`, `dry_run` param) is untouched — the daemon's periodic caller still uses it with `dry_run=False`.
- Updated the command's catalog help text in `maintenance/__init__.py`.
- Replaced `test_blob_gc_cli_yes_deletes_and_records_generation` with `test_blob_gc_cli_has_no_mutate_flag`, mirroring `test_embedding_orphan_reconcile_cli_has_no_mutate_flag`'s exit-code-2/`--yes`-rejected assertion pattern.
- `polylogue/storage/message_type_backfill.py`: added a docstring paragraph documenting why this doctor-repair target is a legitimate KEEP (finite one-time legacy-row remediation; no recurring daemon condition since new-ingest rows are classified correctly since PR #836/#944), recorded as part of the same audit.

The audit's other findings required no code changes and are recorded in `polylogue-cfvvt`'s notes:

- `blob-reference-prune-orphans`/`blob-reference-replace-from-source`: KEEP — no daemon path exists for `blob_refs` debt at all, and both commands require genuine judgment per missing blob.
- `embeddings-rescue`: KEEP — already documented as an explicit one-time break-glass migration, structurally undetectable by daemon convergence.
- Doctor's 5 destructive cleanup targets (`orphaned_messages`, `empty_sessions`, `orphaned_attachments`, `orphaned_blobs`, `superseded_raw_snapshots`): KEEP — `destructive=True` by catalog design, zero daemon caller, genuinely consent-gated.
- Doctor's `session_insights` repair target: proven to have the same redundancy shape (covered by both a per-ingest `ConvergenceStage` and a dedicated periodic `convergence_debt` retry loop), but scoped out to a dedicated follow-up (`polylogue-ygfwa`) given its wider surface coupling (`REPAIR_HANDLERS`, maintenance planner/replay, archive-debt status reporting) versus `blob-gc`'s single CLI file.

## Verification

- `devtools test tests/unit/cli/test_archive_maintenance_cli.py -k blob_gc` — 3 passed
- `devtools test tests/unit/daemon/test_blob_gc_periodic.py` — 4 passed
- `devtools render all --check` — clean, no "out of sync" surfaces
- `devtools verify --quick` — exit 0, all 19 steps green
- `tests/unit/storage/test_blob_gc.py`'s 7 failures are pre-existing (`clock_guard` `time.time()` violations in code this change never touches) and unrelated to this diff

Ref polylogue-cfvvt
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