[rescue] rescue/2026-08-09-bl-599 — restore transcript-window backfill with safety hardening - #690
[rescue] rescue/2026-08-09-bl-599 — restore transcript-window backfill with safety hardening#690EtanHey wants to merge 21 commits into
Conversation
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill # Conflicts: # tests/test_ingest_denylist.py
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
…o feat/indexing-window-backfill
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> # Conflicts: # scripts/run_tests.sh # tests/test_run_tests_script.py
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
| @contextmanager | ||
| def backfill_run_lock(registry_path: str | Path) -> Iterator[None]: | ||
| """Serialize scan, enqueue, and offset persistence for one registry.""" | ||
| registry = Path(registry_path).expanduser() |
There was a problem hiding this comment.
🟠 High brainlayer/backfill.py:55
backfill_run_lock derives the lock filename from registry_path without resolving symlinks, so two processes that pass the same registry through different symlink aliases open different .backfill.lock files and both acquire the lock. This means scan, enqueue, and offset persistence are not serialized for that registry. Consider resolving the registry path (and its parent) before deriving the lock path.
- registry = Path(registry_path).expanduser()
+ registry = Path(registry_path).expanduser().resolve()🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @src/brainlayer/backfill.py around line 55:
`backfill_run_lock` derives the lock filename from `registry_path` without resolving symlinks, so two processes that pass the same registry through different symlink aliases open different `.backfill.lock` files and both acquire the lock. This means scan, enqueue, and offset persistence are not serialized for that registry. Consider resolving the registry path (and its parent) before deriving the lock path.
| changed_files_seen=1 | ||
| mapped=0 | ||
| case "$changed" in | ||
| src/brainlayer/cli/__init__.py) |
There was a problem hiding this comment.
🟡 Medium scripts/run_tests.sh:145
When src/brainlayer/cli/__init__.py changes, only test_cli*.py and test_watch_backfill_cli.py are selected and mapped is set to 1, so the pre-push run skips every other test that exercises the CLI. Tests like test_agent_profiles.py, test_doctor.py, test_git_learning.py, test_reembed_backfill.py, and test_status_truthfulness.py are all silently excluded when the CLI entrypoint changes, letting regressions they cover pass the check. Consider not marking this case as fully mapped — leave changed_source_unmapped=1 (or map to all relevant tests) so the full suite runs as a fallback.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @scripts/run_tests.sh around line 145:
When `src/brainlayer/cli/__init__.py` changes, only `test_cli*.py` and `test_watch_backfill_cli.py` are selected and `mapped` is set to `1`, so the pre-push run skips every other test that exercises the CLI. Tests like `test_agent_profiles.py`, `test_doctor.py`, `test_git_learning.py`, `test_reembed_backfill.py`, and `test_status_truthfulness.py` are all silently excluded when the CLI entrypoint changes, letting regressions they cover pass the check. Consider not marking this case as fully mapped — leave `changed_source_unmapped=1` (or map to all relevant tests) so the full suite runs as a fallback.
|
Lead disposition (Etan delegated): holding open as REFERENCE for Wave 4 backfill lanes rather than merging — the base is stale vs current main, but the transcript-window backfill logic here is directly relevant to Wave 4a-4c. Will close when the Wave 4 implementation supersedes it. — brainlayerClaude lead (Fable 5) 🤖 Generated with Claude Code |
Rescue context
This preserves the full transcript-window backfill implementation and its later safety hardening: idempotent replay, watcher/denylist integration, CLI coverage, progress integrity, quarantine, and fail-loud behavior.
The work came from the retained
bl-599worktree. Raw ahead and verified-unlanded counts are both 21 againstmain; original PR #599 was CLOSED without merge, and the source/test diff is substantive rather than generated noise.It was rescued instead of merged because the original feature PR closed without landing and the branch later accumulated additional safety fixes that need a deliberate shipping decision.
— maintenanceCodex (worker) · codex/gpt-5.6-sol
Note
Restore
watch-backfillCLI with time-windowed, idempotent backfill and safety hardening--since/--untilwindow flags and--legacy-excluded-onlyscope to thewatch-backfillCLI command in cli/init.py, enabling time-bounded, repeatable backfills over previously blanket-denied pathsWindowedFlushin backfill.py to filter watcher entries to a UTC half-open interval, advancing offsets for non-matching lines to ensure idempotencybackfill_run_lock(fcntl file lock) to serialize concurrent backfill runs per registry; exits with code 2 on contention and code 1 when work remains incompleteis_legacy_backfill_denylistedin ingest_denylist.py that applies the current denylist minus retired blanket patterns (cursor agent transcripts, claude subagents, codex/gemini sessions), still blockingbrain-workersubagentsJSONLTailer.read_new_linesin watcher.py with per-call byte caps and_ProgressMarkeremission for blank/malformed lines so offsets advance without enqueuing contentnormalize_provider_entrynow synthesizes a UTC timestamp and sets_timestamp_synthesized=Truewhen the source timestamp is missing or unparseable, changing downstream entry shape📊 Macroscope summarized 90ac44b. 5 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.