feat(orchestrator): add backup-plugin-db skill for WAL-safe nightly snapshots - #4
Open
evannadeau wants to merge 3 commits into
Open
Conversation
…napshots Ships a skill that installs daily point-in-time snapshots of the orchestrator plugin's SQLite databases. Mirrors the install-launchers skill pattern (SKILL.md + scripts/) so the canonical content lives inside the plugin and gets installed into the user's environment on demand. What's included - SKILL.md walking through setup. The destination is entirely the user's choice (no defaults inferred); the skill suggests cloud-sync folders or backed-up local paths as examples. - scripts/snapshot-plugin-db.py — WAL-safe online backup via SQLite's Connection.backup() API, atomic temp+rename writes, optional per-source retention (--retain-days), and a refuse-to-write-inside- source guard. - scripts/install-snapshot-timer.sh — bash helper that installs a systemd-user timer when available, or a tagged crontab entry as a fallback. Idempotent on --name. Documents WSL2 linger requirement. - scripts/install-snapshot-task.ps1 — PowerShell helper that registers a Windows Scheduled Task. Idempotent on -TaskName. Prefers pyw.exe for windowless runs. Two-database coverage The plugin uses two SQLite files — global.db (cross-project) and project.db (per-project). The SKILL.md and helpers are explicit about this and walk users through installing one timer per DB they care about (with distinct --name / -TaskName values and optional distinct --retain-days policies). The most common omission this addresses is backing up only the global DB and silently losing the project DB, which typically holds the bulk of a user's knowledge. Python is already a baseline dep for the plugin via sidecar/ (embed_server.py + requirements.txt), so this adds no new runtime requirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…LL.md Calls out Python 3.10+, the Windows Microsoft Store App-Execution-Alias stub trap, a writable destination, and the systemd-user/cron requirement on Linux/macOS. Surfaces the most common upstream-user wall (Store stub on a fresh Windows box) before the install step rather than after a confusing helper failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…SKILL.md Documents where snapshot failures show up by default on each platform (journalctl / cron mail / Task Scheduler LastTaskResult) and the canonical pattern for attaching alerting — systemd drop-in override on Linux/macOS/WSL, RestartCount + event-triggered follow-up task on Windows — without re-registering or modifying the shipped units.
SpawnBox-dev
pushed a commit
that referenced
this pull request
Aug 9, 2026
…nd 3x better (0.47.0) Three-arm A/B on a 300-note subset of the live KB. Identical probes, identical subset selection, identical chunking; only the representation varied. Mean rank of the correct note, lower is better: A whole-note, bge-m3 63.2 B chunked, bge-m3 32.0 C chunked, bge-small 11.4 <- two probes at #1, one at #4 Per-probe (A / B / C): 68/35/42, 52/8/4, 142/98/9, 41/9/1, 13/10/1. Speed, same corpus: 82ms/chunk vs 575ms. A full re-embed drops from ~167 min to ~24 min. Resident memory drops from ~1.8GB to ~130MB, and model load from ~100 CPU-seconds to 2.8s. Smaller, faster, cheaper AND more accurate is a rare combination, and the reason is mundane: bge-m3 is a MULTILINGUAL model. Its capacity encodes cross-lingual structure this English-only corpus never uses, and that structure dominates the space - unrelated notes scored 0.73-0.79 cosine against each other. bge-small-en-v1.5 is an English retrieval specialist, and on short passages that is exactly the job. Honest limits: 5 probes, deliberately adversarial (near-zero lexical overlap with their targets), scored within a 300-note subset rather than the full 7148. The effect is large and consistent (C matched-or-beat B on 4/5) but the sample is small. VECTORS FROM DIFFERENT MODELS ARE NOT COMPARABLE, and this release makes that structural rather than assumed: - Both vector queries now filter `WHERE model = ACTIVE_EMBED_MODEL`. Rows from a previous model are IGNORED, not scored. After this upgrade the vector leg goes quiet and BM25 carries retrieval until the re-embed runs - degraded, not wrong. - cosineSimilarity returns 0 on a dimension mismatch. It iterated a.length, so a 384-dim query against a 1024-dim stored vector silently scored on the first 384 components - a meaningless number that still RANKS - and the reverse direction read past the end and produced NaN. Neither errored. - The model is passed explicitly to the sidecar from mcp/engine/embeddings.ts, making that file the single source of truth. The Python default was a second, independent source for the same decision; a drift between them would write rows tagged with one model but produced by another, poisoning the corpus with mixed vectors that all claim to be comparable. A test asserts the two stay equal. MIGRATION: existing 7148 notes carry bge-m3 vectors and are now inert for search. `backfillChunks()` re-embeds them under the new model - still opt-in, still resumable, still nothing calls it automatically. ~24 min for the corpus. Guards: 4 new model-identity assertions in chunked-retrieval.test.ts. Suite 1086 pass / 0 fail. A pre-existing test that hardcoded "bge-m3" now asserts the constant, so it cannot drift again. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MD4kPkrZLWbUxe4arhdwii
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
Adds a new
backup-plugin-dbskill under the orchestrator plugin that installs nightly point-in-time snapshots of the plugin's SQLite DB(s) using SQLite's online backup API (WAL-safe under a running MCP server), written atomically to a user-chosen destination.Motivated by the realization that the plugin runs against two databases —
~/.claude/orchestrator/global.dband<project>/.orchestrator/project.db— and that the bulk of stored knowledge typically lives in the project DBs. Most users discover this only after losing data.What's in the skill
scripts/snapshot-plugin-db.py— single-source snapshot script.global-YYYY-MM-DD.db/project-YYYY-MM-DD.db) so the same destination can host multiple DBs without collision.--retain-days Nretention, scoped to the source-stem pattern so it cannot accidentally delete adjacent files.--cloud-rootor$CLAUDE_ORCHESTRATOR_BACKUP_ROOT, no implicit defaults, hard-fails with a clear message when neither is set.scripts/install-snapshot-timer.sh— Linux/macOS/WSL helper. Prefers systemd-user; falls back to cron when the user bus is unavailable. Idempotent on--name. Per-install retention. WSL2 linger advisory.scripts/install-snapshot-task.ps1— Windows helper. Registers a Scheduled Task, preferspyw.exeto avoid console flashes, validates-Time/-RetainDays, idempotent on-TaskName.SKILL.md— walkthrough that installs one timer per DB the user cares about, with a Prerequisites section covering the Python 3.10+ requirement and the Windows MS-Store-stub trap.Design choices worth flagging
--name/-TaskNameand optionally a distinct--retain-days. Keeps the script single-purpose and lets users mix retention policies between global and project DBs.Testing
End-to-end validated on two fresh hosts using self-contained agent prompts that synthesize a source DB and exercise install/run/retention/coexistence/idempotency/teardown:
The snapshot script itself was also smoke-tested against real plugin DBs on the authoring host (28-note global, 150-note project, both verified round-trippable via
sqlite3 PRAGMA integrity_check).Out of scope (deliberately)
PRAGMA integrity_checkon the snapshot) but doesn't ship a one-shot restore script. The destructive half of the drill is a user action.Test plan
--retain-daysprunes only files matching the source-stem pattern (verified with adjacent non-matching files).--name, distinct retention).🤖 Generated with Claude Code