feat(kb): autonomous capture bridge — SP-A (0.24.18)#31
Merged
Conversation
Foundation of the autonomous-knowledge-loop roadmap (A..E). Deploy the out-of-band drainer (built v0.13.0, never installed/run) with a local-LLM- preferred engine (local proxy → cli-OAuth → --bare), a minimal opt-out systemd relaxation, and a loud capture-health self-check. Verification requires a REAL extraction writing a REAL delta (stub-green is explicitly not 'done'). Grounded by the 2026-06-05 live current-state map. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Incorporate review decisions: verified raw ollama 0.23.4 + qwen2.5:3b + native /v1 endpoint, so the OpenAI-compatible local backend ships IN SP-A (no LiteLLM); hardened local-only systemd unit is the default (zero credential exposure), OAuth-capable is the --oauth opt-in. Real-run verification is now in-session via the local engine (no recursive lock). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ariant (U3/U4) The hardened unit (default) now grants ~/.second-brain AND ~/knowledge so the drainer can actually write the wiki — the prior unit only granted ~/.second-brain and would have silently failed wiki writes. OAuth variant (--oauth opt-in) adds the ~/.claude relaxation; the installer announces that grant before applying. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… guard (U5) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erous local timeout Recent-tail cap so a small local model isn't fed a multi-MB transcript; generous SB_EXTRACTOR_LOCAL_TIMEOUT (default 300s) for slow out-of-band CPU inference. Real-run finding: budgeting content alone is insufficient on a Pi — the 1405-token extract-prompt itself dominates CPU prompt-eval; a slim local prompt is the follow-up. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
'auto' (default) tries local first, falls through to the Claude/API backend when local can't deliver (the working path — Claude is part of Claude Code). 'local' pins (no fallthrough). Shorter local timeout so the fallback isn't slow. Tests cover both. Honors: most important is a WORKING loop; let Claude handle what the Pi-local model can't. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ration row Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ile (deep-review HIGH) Backend 0 wrote the model text to out_file BEFORE the JSON-object check; on a non-object response in auto mode the failed local fell through and a downstream return-0 could ship the stale garbage as a 'successful' extraction, defeating the [degraded] breadcrumb. Now stage→validate→mv (mirrors backends 1/2). + tests for the non-object leak and real-backend preservation; fixed a stale cli-oauth comment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Implements the “autonomous capture bridge” foundation by wiring the out-of-band extraction drainer into a local-LLM-first extractor pipeline, adding systemd deployment variants, and surfacing capture health at SessionStart so archived transcripts don’t silently fail to become knowledge artifacts.
Changes:
- Add a local OpenAI-compatible
/v1/chat/completionsextractor backend (offline-first) with input budgeting and staging validation. - Harden/extend systemd deployment: default unit can write both hot-tier and
~/knowledge, plus an OAuth-capable service variant; installer gains--oauth. - Add SessionStart “capture not running” self-check banner and extend tests/docs/versioning for the new behavior.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
scripts/lib.sh |
Adds local /v1 extractor backend and integrates it into sb_call_extractor. |
scripts/extract-drain.sh |
Fixes drainer health summary to preserve the real backend label instead of hardcoding. |
scripts/install-extract-timer.sh |
Adds variant parsing (--oauth) and keeps default behavior hardened/no-creds write grant. |
scripts/session-load.sh |
Adds SessionStart capture-health self-check banner + suppression flag. |
systemd/sb-extract-drain.service |
Grants write access to both %h/.second-brain and %h/knowledge for wiki/graph output. |
systemd/sb-extract-drain-oauth.service |
New OAuth-capable unit granting RW to %h/.claude for background claude -p fallback. |
tests/test-extractor-local-backend.sh |
New coverage for local backend, budgeting, fallback behavior, and non-object staging guard. |
tests/test-extract-drain.sh |
Extends drainer tests to ensure backend is not hardcoded and is preserved. |
tests/test-install-extract-timer.sh |
Extends installer/systemd template assertions for hardened vs OAuth variant behavior. |
tests/test-session-load-capture-banner.sh |
New test ensuring the capture-health banner appears/suppresses correctly. |
docs/specs/2026-06-05-autonomous-capture-bridge-design.md |
Design spec for SP-A (local backend, systemd variants, banner, verification). |
docs/plans/2026-06-05-autonomous-capture-bridge.md |
Step-by-step implementation plan and verification checklist for SP-A. |
skills/upgrade/SKILL.md |
Adds migration row documenting SP-A and user opt-in install commands. |
.claude-plugin/plugin.json |
Bumps plugin version to 0.24.18. |
.claude-plugin/marketplace.json |
Bumps marketplace version to 0.24.18. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+690
to
+697
| local tmp_out="${out_file}.local.$$" | ||
| printf '%s' "$text" | sb_strip_code_fences > "$tmp_out" | ||
| if jq -e 'type == "object"' "$tmp_out" >/dev/null 2>&1; then | ||
| mv "$tmp_out" "$out_file" | ||
| return 0 | ||
| fi | ||
| rm -f "$tmp_out" | ||
| return 1 |
Comment on lines
+8
to
+11
| fail(){ echo "FAIL: $1"; exit 1; }; pass(){ echo "PASS: $1"; } | ||
| command -v python3 >/dev/null 2>&1 || { echo "SKIP: python3 absent"; exit 0; } | ||
| command -v curl >/dev/null 2>&1 || { echo "SKIP: curl absent"; exit 0; } | ||
|
|
Comment on lines
+24
to
+26
| # Without the knowledge grant an installed drainer silently can't write the wiki. | ||
| # No ~/.claude grant — this hardened default runs the local engine (no creds). | ||
| ReadWritePaths=%h/.second-brain %h/knowledge |
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.
Foundation of the autonomous-knowledge-loop roadmap. Deploys the out-of-band extraction drainer (built v0.13.0 but never installed/run — a prior wiring audit said "wired" while a live-runtime check found 0 transcripts ever drained), so archived transcripts actually become wiki/PROJECT/graph knowledge with no live session.
What's in it
/v1/chat/completions(ollama on localhost) FIRST: offline, no creds, works in-session (no recursive-claude lock). Input-budgeted (SB_EXTRACTOR_LOCAL_MAX_BYTES) +SB_EXTRACTOR_LOCAL_TIMEOUT.SB_EXTRACTOR_ENGINE=auto(default): local → fall through to Claude (OAuth/--bare) when local can't deliver. Live finding: a Pi-5 CPU can't run a 3B over a full real transcript in time → Claude handles it out-of-band.=localpins;=cli/=bareforce.~/knowledge(it could never write the wiki before); hardened local-only default (no creds) + an--oauthopt-in variant that grants~/.claudefor the Claude fallback.capture not runningwhen transcripts are archived but undrained (the "wired ≠ works" guard).Verification
docs/specs,docs/plans); TDD per unit (RED→GREEN).qwen2.5:3b(extracted real decisions/plans from a transcript).out_file) fixed (stage→validate→mv) + 3 test-gaps closed.SB_EXTRACTOR_LOCAL_URLand no timer installed, behaviour unchanged. No MCP server change (2.6.4).Real-world note: the capstone "full real transcript → delta on the Pi" runs via the Claude fallback out-of-band (Pi-local 3B is too slow for big transcripts) — the user verifies that in an idle window (the proven claude-cli backend).
🤖 Generated with Claude Code