Steve Yegge f56632adcf perf(storage): stop burning two wasted MySQL sessions per bd invocation (wy-s8ytnw) (#6122)
* perf(storage): stop burning two wasted MySQL sessions per bd invocation (wy-s8ytnw)

Every bd store-open against a shared dolt sql-server cost two sessions that
did no work:

1. readAndDial's data-port probe (internal/storage/dbproxy/proxy/endpoint.go)
   dialed the proxy data port and closed it to "prove" it accepts. The proxy's
   handleConn dials the BACKEND for every accepted client connection before a
   byte flows, so the zero-byte probe was a full backend MySQL session on every
   invocation from a proxied clone — and it proved nothing the authenticated
   control-port identity reply had not: ListenAndServe binds the data listener
   before the control listener exists. Drop the probe; the identity reply is
   the liveness proof. (Deferring the backend dial until the first client byte
   was considered and rejected: MySQL is server-speaks-first, so a real client
   waits for the greeting and would deadlock.)

2. The no-database init connection. On the proxied/server uow path
   (openAndInitSchema) and the dolt.New server path (openServerConnection) bd
   opened a second, database-less pool per store-open purely to probe
   existence (SHOW DATABASES / the schema-init preparation) before opening
   the real pool. Both sites now try the database-scoped connection FIRST —
   keyed the way the Gateway case already is, not by deleting the probe: a
   successful connect is the existence proof, so the steady-state open (every
   open but the very first) costs one session. Any connect failure (1049
   Unknown database, server down, bad credentials) falls through to the
   historical no-database path, which still owns creation, the #5042
   ownership signal that arms FreshBootstrapHeal, databaseNotFoundError, and
   every existing error message. `created` is honestly false on the fast
   path; the uow provider reuses the init pool (nothing in the migration path
   mutates session state).

New test TestReadAndDialAdoptsWithoutDialingDataPort pins the probe removal;
it fails (1 accept) against the previous endpoint.go and passes now.

Why the live server still saw a bare CREATE DATABASE per open despite
openServerConnection's SHOW DATABASES guard (the question on wy-s8ytnw): that
guard is not on the proxied path at all — the CREATE came from the uow
schema-init preparation, already fixed upstream by #6022 (alreadyConverged);
the deployed binary (71e5ad700) predates it (wy-7sx6cj).

* fix(storage): cap the fast-path probe budget; correct the pool-reuse premise

Maintainer review fixes for PR #6122. All four are non-gating minors (plus
one nit) from the review synthesis; the quality scorecard's decision was
approve with no required changes.

- uow fast path no longer costs a second retry budget (finding 1). openDB's
  30s transient-ping budget was spent twice against an unreachable server:
  once on the fast-path probe, whose error was discarded, and again on the
  fall-through open. Measured 0s + 19.8s where it was 19.8s twice; the
  returned "uow: ping db: ..." text is unchanged. The probe is now a single
  bounded ping, mirroring the sibling fast path in internal/storage/dolt,
  and the historical open keeps the retry budget it owned at base. Nothing
  is lost by not retrying here: the endpoint is already live when
  openAndInitSchema runs (GetCreateDatabaseProxyServerEndpoint), so the
  probe was never the thing waiting out a starting server.
- Replace the pool-reuse comment's false premise (finding 2). "Nothing in
  the migration path mutates session state" is wrong: six shipped
  migrations clear FOREIGN_KEY_CHECKS and restore it, and the guarded ones
  leave user variables set. State the real invariant instead — one pinned
  session per attempt, paired restores inside each script, pool closed on
  every initSchema failure — and record the forward requirement in
  migrations/README.md, where migration authors will meet it.
- Log why either fast path fell through (finding 3), matching lock.go's
  alreadyConverged idiom, so a fast path that has quietly stopped firing is
  visible under BD_DEBUG instead of silently costing the second session.
- Amend both stale empty-DSN premise comments (finding 5, nit):
  selectProbeDatabase and alreadyConverged now describe both entry shapes.

Finding 4 (a server-gated assertion on open-path selection) is left as the
follow-up that the synthesis and the scorecard both marked optional.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: plato <plato@ghosttrack.com>
Co-authored-by: Eddie the Engineer <julianknutsen@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 09:38:01 -07:00
2026-07-08 12:21:24 -07:00
2026-05-01 17:46:37 -07:00

bd - Beads

Distributed graph issue tracker for AI agents, powered by Dolt.

Platforms: macOS, Linux, Windows, FreeBSD

License Go Report Card Release npm version PyPI

Docs: https://beads.gascity.com/

Beads provides a persistent, structured memory for coding agents. It replaces messy markdown plans with a dependency-aware graph, allowing agents to handle long-horizon tasks without losing context.

flowchart LR
    create["bd create<br/>new bead"] --> depgraph["dependency<br/>graph"]
    depgraph --> ready["bd ready<br/>claimable work"]
    ready --> claim["bd update --claim<br/>agent takes it"]
    claim --> close["bd close<br/>work done"]
    close -->|blockers released| ready
    depgraph <-->|"bd dolt push / pull"| remote[("other machines<br/>and agents")]

Quick Start

# Install beads CLI (system-wide - don't clone this repo into your project)
curl -fsSL https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh | bash

# Initialize in YOUR project
cd your-project
bd init

# Optional: refresh or install richer instructions for your agent
bd setup codex    # Codex CLI - installs skill, AGENTS.md guidance, and hooks
bd setup claude   # Claude Code - installs hooks/settings
bd setup factory  # Factory.ai Droid - creates/updates AGENTS.md

Note: Beads is a CLI tool you install once and use everywhere. You don't need to clone this repository into your project.

bd init creates or updates AGENTS.md by default so agents can discover the beads workflow, and also installs project Claude/Codex integrations unless you pass --skip-agents or --stealth. Use bd setup --list to see supported integrations, including bd setup codex, bd setup factory, bd setup claude, bd setup mux, bd setup cursor, and more. See Agent and IDE setup.

Manual copy-paste is only for unsupported agents, existing projects where you cannot rerun bd init/bd setup, or custom instruction files. In those cases, run bd onboard and paste the printed snippet into the file your agent reads.

If your agent is not covered by bd setup, add this minimal AGENTS.md section:

This project uses bd (beads) for issue tracking.

- Run `bd prime` for workflow context and command guidance.
- Use `bd ready`, `bd show <id>`, `bd update <id> --claim`, and `bd close <id>`.
- Use `bd remember "insight"` for persistent project memory; do not create MEMORY.md files.
- Do not use markdown TODO lists for task tracking.

🛠 Features

  • Dolt-Powered: Version-controlled SQL database with cell-level merge, native branching, and built-in sync via Dolt remotes.
  • Agent-Optimized: JSON output, dependency tracking, and auto-ready task detection.
  • Zero Conflict: Hash-based IDs (bd-a1b2) prevent merge collisions in multi-agent/multi-branch workflows.
  • Compaction: Semantic "memory decay" summarizes old closed tasks to save context window.
  • Messaging: Message issue type with threading (--thread), ephemeral lifecycle, and mail delegation.
  • Graph Links: relates-to, duplicates, supersedes, and replies-to for knowledge graphs.

📖 Essential Commands

Command Action
bd ready List tasks with no open blockers.
bd create "Title" -p 0 Create a P0 task.
bd update <id> --claim Atomically claim a task (sets assignee + in_progress).
bd dep add <child> <parent> Link tasks (blocks, related, parent-child).
bd show <id> View task details and audit trail.
bd prime Print agent workflow context and persistent memories.
bd remember "insight" Store project memory that bd prime injects later.

🔗 Hierarchy & Workflow

Beads supports hierarchical IDs for epics:

  • bd-a3f8 (Epic)
  • bd-a3f8.1 (Task)
  • bd-a3f8.1.1 (Sub-task)

Stealth Mode: Run bd init --stealth to use Beads locally without committing files to the main repo. Perfect for personal use on shared projects. See Git-Free Usage below.

Contributor vs Maintainer: When working on open-source projects:

  • Contributors (forked repos): Run bd init --contributor to route planning issues to a separate repo (e.g., ~/.beads-planning). Keeps experimental work out of PRs.
  • Maintainers (write access): Beads auto-detects maintainer role via SSH URLs or HTTPS with credentials. Only need git config beads.role maintainer if using GitHub HTTPS without credentials but you have write access.

📦 Installation

brew install beads           # macOS / Linux (recommended)
npm install -g @beads/bd     # Node.js users

Other methods: install script | go install | from source | Windows | Arch AUR

Requirements: macOS, Linux, Windows, or FreeBSD. See docs/getting-started/installation.md for complete installation guide.

Upgrading? Replacing the binary is not always the whole story. Short version: sync remote-backed databases with your current bd, back up with bd export --all, upgrade the binary, then run bd info --whats-new, bd hooks install, and bd version. If the upgrade crosses a schema migration on a remote-backed database, exactly one designated clone runs bd migrate and bd dolt push; other clones install the new binary and run bd bootstrap. See the full upgrade guide or docs/getting-started/installation.md.

Security And Verification

Before trusting any downloaded binary, verify its checksum against the release checksums.txt.

The install scripts verify release checksums before install. For manual installs, do this verification yourself before first run.

On macOS, scripts/install.sh preserves the downloaded signature by default. Local ad-hoc re-signing is explicit opt-in via BEADS_INSTALL_RESIGN_MACOS=1.

See docs/reference/antivirus.md for Windows AV false-positive guidance and verification workflow.

💾 Storage Modes

Beads uses Dolt as its database. Two modes:

  • Embedded (default)bd init. Dolt runs in-process, data lives in .beads/embeddeddolt/, single writer. Recommended for most users.
  • Serverbd init --server. Connects to an external dolt sql-server for multiple concurrent writers; data lives in .beads/dolt/.

Cross-machine sync uses bd dolt push / bd dolt pull against refs/dolt/data on your git remote; .beads/issues.jsonl is an export for viewers and interchange, not the source of truth or a backup. Back up and migrate between modes with bd backup; reclaim space with bd prune / bd purge.

Full detail — connection flags, sockets, maintenance, backup, and migration — in the Dolt backend guide.

Schema Version Guard

bd checks the database schema version at open time. If the database has been migrated by a newer binary and an older binary tries to open it, bd exits with an actionable error rather than issuing queries that fail with cryptic SQL errors:

schema version mismatch: database is at v45, binary knows up to v42 (3 migrations ahead)

  Your bd binary is stale. Queries for dropped or renamed columns will fail
  with cryptic SQL errors (e.g. "column X could not be found in any table in scope").

  Rebuild from main:
    CGO_ENABLED=0 go build -tags gms_pure_go ./cmd/bd

  Or install the latest release:
    CGO_ENABLED=0 go install -tags gms_pure_go github.com/steveyegge/beads/cmd/bd@latest

  To proceed despite the risk (some read commands may still work):
    BD_IGNORE_SCHEMA_SKEW=1 bd <command>
    bd --ignore-schema-skew <command>

When this fires: only when the database schema is ahead of the binary (a newer binary migrated the database; this binary doesn't know those migrations). Normal upgrades, where the binary migrates the database forward, are unaffected.

Escape hatch: BD_IGNORE_SCHEMA_SKEW=1 (or --ignore-schema-skew) bypasses the guard with a warning on stderr. Use this only if you know the forward migrations are additive and safe for your specific workload.

🌐 Community Tools

See docs/community-tools.md for a curated list of community-built UIs, extensions, and integrations—including terminal interfaces, web UIs, editor extensions, and native apps.

See docs/related-projects.md for adjacent or complementary projects that solve different problems in the same neighborhood.

🚀 Git-Free Usage

Beads works without git. The Dolt database is the storage backend — git integration (hooks, repo discovery, identity) is optional.

# Initialize without git
export BEADS_DIR=/path/to/your/project/.beads
bd init --quiet --stealth

# All core commands work with zero git calls
bd create "Fix auth bug" -p 1 -t bug
bd ready --json
bd update bd-a1b2 --claim
bd prime
bd close bd-a1b2 "Fixed"

BEADS_DIR tells bd where to put the .beads/ database directory, bypassing git repo discovery. --stealth sets no-git-ops: true in config, disabling all git hook installation and git operations.

This is useful for:

  • Non-git VCS (Sapling, Jujutsu, Piper) — no .git/ directory needed
  • Monorepos — point BEADS_DIR at a specific subdirectory
  • CI/CD — isolated task tracking without repo-level side effects
  • Evaluation/testing — ephemeral databases in /tmp

📝 Documentation

S
Description
Dolt-powered issue tracker for multi-session work with dependencies and persistent memory across conversation compaction. Use when work spans sessions, has…
Readme MIT 276 MiB
Languages
Go 96.8%
Shell 1.6%
Python 1.2%
Rust 0.2%