fix: never strand changes when triage is unavailable; de-noise digest - #7
Merged
Merged
Conversation
Triage and delivery had a gap that silently dropped real changes, plus two sources of digest noise. Fixes, each with tests: - Triage worklist is now ledger-sourced. `run_once` triaged only this-run detections, so a change recorded during a run that could not triage kept a NULL verdict and was never re-detected (its content hash / feed seen-set already matched) — stranding it out of the digest forever. `store.changes_needing_triage()` returns every `verdict IS NULL AND superseded = 0` row, so a later run drains the backlog. - Send-all when triage cannot run. When the triager returns `unavailable`, the run now marks every untriaged row substantive (no description) so the digest still goes out with the AI-unavailable banner instead of withholding the changes — same effect as the noop triager. - Scheduler units carry user env. `[schedule.env]` is baked into the launchd plist / systemd unit / crontab alongside PATH, so an account-aware `claude` wrapper can resolve a profile (e.g. CLAUDE_ACCOUNT) from the bare scheduled environment that otherwise fails triage. - Exclude the GKI per-version build-list pages (`/docs/core/architecture/ kernel/gki-android...-builds`) from source-android: they auto-regenerate with new build rows on nearly every crawl, churning the digest without telling a developer anything. The curated GKI docs are still watched. - Synthesize a feed title from the summary when the entry title is only a date (the AndroidX aggregate feed titles every entry by date). Display-only: the dedupe identity and title+summary hash still use the original feed values. Co-Authored-By: Penny-One (Batcave) <noreply@anthropic.com>
A single drain of hundreds of changes runs many sequential `claude -p` calls; a batch of 25 items (up to 100KB of page content) could exceed the 120s subprocess timeout, tripping the run's AI-unavailable banner and the send-all fallback even though most batches succeeded. Shrink the batch (25 -> 12) and raise the per-call timeout (120s -> 300s) so a one-shot drain finishes cleanly; steady-state runs are unaffected. Co-Authored-By: Penny-One (Batcave) <noreply@anthropic.com>
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.
Summary
Triage and delivery had a gap that silently dropped real changes (a change detected during an AI-unavailable run was stranded out of the digest forever), plus two sources of digest noise and a scheduled-run triage failure. Each fix is TDD'd.
Fixes
run_oncetriaged only this-run detections, so a change recorded during a run that could not triage kept aNULLverdict and was never re-detected (its content hash / feed seen-set already matched) — stranding it out of the digest forever.store.changes_needing_triage()now returns everyverdict IS NULL AND superseded = 0row, so a later run drains the backlog.unavailable, the run marks every untriaged rowsubstantive(no description) so the digest still goes out with the AI-unavailable banner instead of withholding the changes — same effect as thenooptriager.[schedule.env]is baked into the launchd plist / systemd unit / crontab alongsidePATH, so an account-awareclaudewrapper can resolve a profile (e.g.CLAUDE_ACCOUNT) from the bare scheduled environment that otherwise fails triage./docs/core/architecture/kernel/gki-android...-builds) fromsource-android: they auto-regenerate with new build rows on nearly every crawl, churning the digest without telling a developer anything. The curated GKI docs (gki-faq,gki-releases,gki-versioning, …) are still watched.Testing
uv run pytest— 486 passed.ruff check/ruff format --checkclean. New tests cover: ledger-sourced triage drain, send-all on unavailable,[schedule.env]load + plist/systemd/crontab embedding + TUI round-trip, GKI exclusion against the shipped catalog, and date-title synthesis (single, multi, fallback, non-date untouched).🦇 Generated by Penny-One at Batcave