knowledge-curator: recover inbox notes missing from vault clone via DB fallback#594
Merged
Conversation
An agent PR reworded the comment in an already-applied Flyway migration
(assistant-api V12). Flyway checksums the whole file, so the edit flipped the
checksum and crashlooped assistant-api on the next boot. Nothing in CI caught
it before merge.
check-migrations.sh enforces two invariants on every PR:
- immutability: a migration present on the base branch may not be modified,
renamed, or deleted (label allow-migration-change downgrades this to a
warning for a reviewed correction);
- versioning: per service, versions are unique and each newly added
migration's version exceeds the highest already on the base branch.
knowledge-api splits versions across migration/ and migration-pg/; both trees
share one per-service version namespace, which the script accounts for. The
workflow runs unconditionally so it is safe to require as a status check.
…B fallback InboxPass.has_work() was a pure filesystem scan. A note captured to kb_notes whose file was absent from the local vault PVC clone (DB/git desync) could sit in _inbox scope indefinitely — has_work() returned False every tick and run() was never called to vault.sync() + pull the file from the remote. has_work() now falls back to a cheap DB query (SELECT 1 FROM kb_notes WHERE scope = '_inbox' AND vault_path NOT LIKE '_inbox/_needs-review/%' LIMIT 1) when the filesystem scan finds nothing. If the DB says there is work, run() proceeds, vault.sync() pulls the file from the remote, and the pass processes it normally. Notes that are genuinely missing from the remote too will produce a no_work outcome from run() — safe, no infinite loop. Adds has_inbox_notes() to CuratorStore protocol, PostgresCuratorStore, and InMemoryCuratorStore; two new unit tests cover the fallback and the _needs-review exclusion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
InboxPass.has_work()performed a pure filesystem scan of the vault PVC clone.A note captured to
kb_noteswhose file was absent from the local clone — dueto a DB/git desync, a failed push that was retried on a re-cloned PVC, or any
other divergence — would sit with
scope = '_inbox'in the databaseindefinitely. Every curator tick returned
has_work() = False,run()wasnever called, and the note was never promoted.
A May 2026 capture (
home_direct A records owned by in-cluster cloudflare-ddns)has been stuck in this state for 19 days.
Fix
has_work()now falls back to a cheap DB existence check when the filesystemscan finds nothing:
If the DB reports work,
run()proceeds —vault.sync()pulls from the remotebefore the inbox scan, so a file that exists on the remote will be pulled and
processed. If the file is genuinely absent from the remote too,
run()returnsno_worksafely.has_inbox_notes()is added to theCuratorStoreprotocol,PostgresCuratorStore,and
InMemoryCuratorStore. Two new unit tests cover the DB-fallback path and the_needs-reviewexclusion.The stuck May note will drain automatically on the next curator tick without
any manual intervention.