{"id":51224863,"url":"https://github.com/saagpatel/bridge-db","last_synced_at":"2026-06-28T10:03:34.765Z","repository":{"id":351493947,"uuid":"1211074929","full_name":"saagpatel/bridge-db","owner":"saagpatel","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-19T13:09:45.000Z","size":703,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-19T14:12:17.600Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saagpatel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-15T03:29:47.000Z","updated_at":"2026-06-19T13:10:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/saagpatel/bridge-db","commit_stats":null,"previous_names":["saagpatel/bridge-db"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/saagpatel/bridge-db","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fbridge-db","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fbridge-db/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fbridge-db/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fbridge-db/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saagpatel","download_url":"https://codeload.github.com/saagpatel/bridge-db/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saagpatel%2Fbridge-db/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34884278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-28T10:03:34.063Z","updated_at":"2026-06-28T10:03:34.760Z","avatar_url":"https://github.com/saagpatel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bridge-db\n\n![CI](https://github.com/saagpatel/bridge-db/actions/workflows/ci.yml/badge.svg)\n![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)\n\nSQLite-backed MCP server for shared state across Claude.ai, Claude Code, Codex, and related local ops tools.\n\nbridge-db replaces ad hoc edits to a shared markdown file with a structured SQLite store and a focused MCP tool surface: cross-system state, FTS5 lexical `recall`, shipped-event sync receipts, shipped-event dispositions, and observability over the audit and recall logs. The markdown bridge file is regenerated from the DB via `export_bridge_markdown` and remains available as a fallback for file-based clients.\n\n## Prerequisites\n\n- **Python 3.12+**\n- **[uv](https://docs.astral.sh/uv/)** — fast Python package manager\n\n```bash\ngit clone https://github.com/saagpatel/bridge-db.git\ncd bridge-db\nuv sync          # install all deps into .venv\nuv run pytest    # verify the install\n```\n\n## Status\n\n- Steady maintenance. Scope is cross-system *state* coordination, lexical `recall`, and observability — not a general knowledge store.\n- Schema v10: context sections carry monotonic `version` tokens; stale writes and raced handoff claims produce durable `write_conflicts` receipts.\n- Schema v11: a migration backfills activity `tags` into `content_index` so lifecycle tags (SHIPPED, DECISION, ...) are recall-able on existing DBs.\n- FTS5 `content_index` mirrors all content tables; `health` and `status` verify source-row / FTS-row alignment.\n- 26 MCP tools across 10 modules (activity, handoffs, context, snapshots, cost, export, health, recall, audit, conflicts).\n\n## Architecture\n\n```\nClaude.ai ──────────────────────────────────────────────┐\n  (direct MCP via Claude Desktop)                       │\n  (fallback: markdown file via Filesystem MCP)          │\n                                                         ▼\nCC skills ──► MCP stdio ──► bridge-db process ──► SQLite (WAL)\nCodex      ──► MCP stdio ──► bridge-db process ──►  ~/.local/share/bridge-db/bridge.db\n                                                         │\n                                              export_bridge_markdown\n                                                         │\n                                                         ▼\n                                           ~/.claude/projects/\u003cencoded-home\u003e/\n                                           memory/claude_ai_context.md\n```\n\nNo shared daemon. Each MCP client spawns its own `bridge-db` process via stdio. WAL mode + `PRAGMA busy_timeout=15000` handles concurrent writer waiting; logical stale-write protection comes from CAS on mutable context sections.\n\n## Tools\n\nVerify the current tool count from source with\n`rg '@mcp\\.tool' src/bridge_db -c`. As of the 2026-06-20 source check, the\nsurface is 26 tools across these 10 modules:\n\n| Module | Tools |\n|---|---|\n| activity | `log_activity`, `get_recent_activity`, `get_activity_signal`, `get_shipped_events`, `confirm_shipped_sync`, `record_shipped_event_disposition`, `mark_shipped_processed` |\n| handoffs | `create_handoff`, `get_pending_handoffs`, `pick_up_handoff`, `clear_handoff` |\n| context | `update_section`, `get_section`, `get_all_sections`, `sync_from_file` |\n| snapshots | `save_snapshot`, `get_latest_snapshot` |\n| cost | `record_cost`, `get_cost_history` |\n| export | `export_bridge_markdown` |\n| health | `health`, `status` |\n| recall | `recall`, `recall_stats` |\n| audit | `audit_tail` |\n| conflicts | `get_write_conflicts` |\n\nWrite tools enforce `caller` ownership, so systems can only write the slices of state they own. Recent hardening also added `notion_os` and `personal_ops` as first-class activity and cost writers.\n\n## Provenance \u0026 the pickup gate\n\nInstruction-bearing rows carry a `source_trust` label — `operator`, `agent`, or `ingested` — recording who authored the content. It lives only in the DB (schema v7+, on `pending_handoffs`, `activity_log`, `context_sections`, `system_snapshots`) and is **never serialized into the markdown export**, which would otherwise launder provenance.\n\n- **Writers** set it via an optional `source_trust` param; the conservative default is `agent` (a Claude-dispatched write is agent-authored unless the operator asserts otherwise). `update_section` preserves an existing section's label on a content-only re-sync.\n- **The gate** lives at the one dangerous transition — `pick_up_handoff` moving a handoff `pending → active`:\n  - `operator`-trust → picks up in one call (`cc` and `codex`).\n  - `cc` + non-`operator` → returns `requires_confirmation` and does **not** transition; re-invoke with `confirm=True` to proceed.\n  - `codex` + non-`operator` → **refused** (Codex runs with `danger-full-access`; `confirm` cannot bypass it). Promote the handoff to `operator` trust first.\n- **Visibility:** `get_pending_handoffs`, `get_section`, `get_all_sections`, `get_recent_activity`, `get_activity_signal`, `get_shipped_events`, `get_latest_snapshot`, and `recall` hits carry `source_trust` plus `instruction_boundary` metadata that tells consumers returned content is stored data, not instructions. Lifecycle aggregates use a trust summary and `source_trust=\"mixed\"` when rows differ. `status` reports `pending_handoffs_by_trust` and `health` a full per-table `source_trust_breakdown`. Each gate decision (`allowed` / `confirmation_required` / `refused`) is written to the audit log.\n\n\u003e Consumers authoring an operator-directed handoff (e.g. the `vibe-code-handoff` skill) should pass `source_trust=\"operator\"` on `create_handoff` so it picks up without confirmation.\n\n## CAS \u0026 Conflict Receipts\n\nContext sections are the mutable bridge surface, so they carry a monotonic\n`version` token. Consumers should read with `get_section`, edit locally, then\ncall `update_section(..., if_match_version=\u003cversion\u003e)`. A stale token returns\n`ok=false`, `conflict=true`, and a `receipt_id` instead of clobbering a newer\nrow. `if_match_updated_at` remains as a compatibility guard, but `version` is\nthe preferred token because timestamps have one-second resolution.\n\nExisting-row blind writes are temporarily allowed in canary mode and returned as\n`legacy_blind_write=true`; set `BRIDGE_DB_CONTEXT_CAS_MODE=enforce` to reject\nthem. New section inserts without CAS remain allowed.\n\n`export_bridge_markdown` records the exported version/hash for each rendered\nClaude.ai-owned context section. Later `sync_from_file` imports a changed\nfallback-file section only if the DB still matches that exported base. If the DB\nhas advanced, the import is rejected and recorded in `write_conflicts`.\n\nUse `get_write_conflicts(status=\"open\")` to inspect stale section writes,\nstale markdown imports, and raced handoff claims.\n\n## Commands\n\n```bash\nuv run pytest              # run all tests\nuv run pyright             # type check (strict mode)\nuv run ruff check          # lint\nuv run python -m bridge_db --doctor  # local environment diagnostics\nuv run python -m bridge_db --status  # compact operator summary\nuv run python -m bridge_db --dogfood # read-only observability dogfood pass\nuv run python -m bridge_db --rebuild-content-index  # repair FTS recall index drift\nuv run python -m bridge_db --log-session-boundary bridge-db  # FTS-safe CC hook logging\nuv run python -m bridge_db          # start MCP server (stdio)\nuv run python -m bridge_db.migration  # migrate from bridge markdown\n```\n\n## Registration\n\nReplace `/path/to/bridge-db` below with the absolute path to your clone of this repo\n(e.g. `$(pwd)` if you are already inside it, or `~/Projects/bridge-db` as a common convention).\n\n**Claude Code (user-scoped):**\n```bash\nclaude mcp add --scope user bridge-db -- uv run --directory /path/to/bridge-db python -m bridge_db\n```\n\n**Codex (`~/.codex/config.toml`):**\n```toml\n[mcp_servers.bridge-db]\ncommand = \"uv\"\nargs = [\"run\", \"--directory\", \"/path/to/bridge-db\", \"python\", \"-m\", \"bridge_db\"]\n```\n\n## Data\n\n- **DB**: `~/.local/share/bridge-db/bridge.db`\n- **Bridge file**: `~/.claude/projects/\u003cencoded-home\u003e/memory/claude_ai_context.md`\n  (Claude Code encodes your home dir path by replacing `/` with `-`; the default is derived\n  automatically at runtime — override via `BRIDGE_FILE_PATH` if needed)\n- Retention: 50 activity entries per source; 10 snapshots per system family\n  (Codex operating and consulted-node snapshots are retained independently)\n- Health check: `health` MCP tool or `uv run python -m bridge_db --doctor`\n- Operator summary: `uv run python -m bridge_db --status`\n- Dogfood pass: `uv run python -m bridge_db --dogfood` bundles the status, FTS index, WAL, recall, and shipped-sync audit checks used after bridge-sync runs\n- FTS repair: `uv run python -m bridge_db --rebuild-content-index` rebuilds the local `content_index` from source tables when health reports recall-index drift\n- Session boundary logging: Claude Code's SessionEnd hook should call `uv run --directory /path/to/bridge-db python -m bridge_db --log-session-boundary \u003cproject\u003e` rather than writing SQLite directly; this path adds the FTS row and does not run activity retention pruning\n- Migration: `uv run python -m bridge_db.migration` (idempotent — safe to re-run)\n\n`activity_log` retention and shipped-sync receipts are separate surfaces:\nactivity rows are recent context, while `shipped_sync_receipts` is the proof\nledger for downstream shipped-event syncs. Treat `processed_shipped_without_receipt=0`\nand `fts_missing=0` as primary clean signals, and use\n`actionable_unprocessed_shipped=0` when policy dispositions explain why raw\n`unprocessed_shipped` remains nonzero.\n\n`get_recent_activity` is the raw compatibility feed: it returns individual\nactivity rows exactly as stored, including high-volume lifecycle telemetry such\nas Claude Code `SessionEnd` rows tagged `session-boundary`. Operator-facing\nconsumers should use `get_activity_signal` instead. It keeps substantive rows\nvisible while compressing repeated lifecycle rows into aggregates keyed by\nsource, project, summary family, and hour/day time bucket. Raw rows and audit\nevents remain available for debugging and forensic review.\n\nActivity rows preserve two time concepts:\n\n- `timestamp` is the caller-supplied logical activity date or timestamp. When\n  omitted by `log_activity`, it defaults to the operator-local calendar date.\n- `created_at` is the UTC insertion timestamp assigned by SQLite.\n\nFor activity discovery APIs with `since` (`get_recent_activity`,\n`get_activity_signal`, and `get_shipped_events`), a row is visible when either\n`timestamp \u003e= since` or `created_at \u003e= since` (with date-only values interpreted\nas UTC midnight for `created_at`). This keeps closeouts created just after UTC\nmidnight discoverable even when their logical activity date is the prior local\nday.\n\nFor Notion reconciliation, treat each shipped event's `notion_sync` object as the\nmachine-readable gate:\n\n- `ready`: fetch the explicit `notion_page_id`, update only that row, fetch it\n  again, then call `confirm_shipped_sync` with the readback proof.\n- `meta_no_target`: do not update Notion. Confirm the event with\n  `downstream_system=policy` and `downstream_ref` pointing to the configured\n  policy file after verifying the policy applies to the event.\n- `unmatched`, `no_notion_target`, or `registry_unavailable`: leave the event\n  unprocessed and repair the project registry or mapping source first.\n\nFor non-receipt handling, use `record_shipped_event_disposition` only when an\noperator policy says the row should remain auditable but should not proceed to a\ndownstream receipt. The disposition appears as `policy_disposition` on\n`get_shipped_events`; it does not write a receipt and does not add `PROCESSED`.\nDo not use `mark_shipped_processed` for `SHIPPED` rows; it is retained only for\nnon-shipped operational events such as `TASK_DONE`, `APPROVAL_SENT`,\n`PLANNING_APPLIED`, or `REVIEW_CLOSED`.\n\n## Startup Sync\n\nClaude.ai may still write its owned sections directly to the bridge markdown file. To keep those edits from being overwritten on the next export, `sync_from_file` imports the four Claude.ai-owned sections (`career`, `speaking`, `research`, `capabilities`) from `BRIDGE_FILE_PATH` into `context_sections` before bridge consumers read from SQLite.\n\nClaude Code's `/start` workflow now runs `mcp__bridge_db__sync_from_file()` before calling bridge read tools, so file edits are pulled into the DB at session start instead of waiting for a later export cycle.\n\nThe current operating model is:\n- MCP is the primary coordination path.\n- `sync_from_file` is the compatibility safety net for Claude.ai-owned file edits.\n- `export_bridge_markdown` keeps the fallback markdown artifact in sync for file-based consumers.\n\n## Docs\n\n- [`integration-spec.md`](integration-spec.md) — Claude.ai direct MCP and fallback-file integration\n- [`ROADMAP.md`](ROADMAP.md) — Execution roadmap for the next integration phases\n- [`docs/EXTERNAL-WRITER-AUDIT.md`](docs/EXTERNAL-WRITER-AUDIT.md) — Direct bridge-db writer audit outside the repo\n- [`docs/BRANCH-RETIREMENT.md`](docs/BRANCH-RETIREMENT.md) — Branch cleanup and stale-ref disposition policy\n\n### Internal / maintainer docs\n\n- [`docs/internal/OPERATOR-CHECKLIST.md`](docs/internal/OPERATOR-CHECKLIST.md) — Local verification checklist\n- [`docs/internal/POST-SYNC-REVIEW.md`](docs/internal/POST-SYNC-REVIEW.md) — Bridge-sync post-run evidence checklist\n- [`docs/internal/PHASE-3-DECISION.md`](docs/internal/PHASE-3-DECISION.md) — Architectural decision: watcher vs startup sync\n- [`docs/internal/codex-migration.md`](docs/internal/codex-migration.md) — Per-consumer migration instructions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fbridge-db","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaagpatel%2Fbridge-db","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaagpatel%2Fbridge-db/lists"}