minibeads 0.13.2

A minimal, markdown-based drop-in replacement for the beads issue tracker
Documentation


The upstream beads tool can be found in ./beads and built/run with `go build -o bd ./cmd/bd` and the `./beads/bd` binary it produces.  Run `bd quickstart` to learn about it, and use the CLI to explore it's flags.

This project that you're planning then executing is to create MINIMAL Rust language implementation of the core of `bd`.

* We want to support every `bd subcommand` and flag that the beads MCP server is currently using (beads/integration/beads-mcp), because we will run Claude on containers that have minibeads as their `bd` command.
* We DO NOT want to have any SQL Lite database. Our implementation will be much simpler.
* ./beads contains a version of the upstream project with a recently added MARKDOWN BACKEND

In this session you have the beads MCP loaded. You can try operations on it and see what `bd ...` commands it attempts to invoke. Don't let it install any other version of beads than the Rust one we will develop here.  Let me know if it is trynig to.
## Storage Architecture: Dual Format Support

**ARCHITECTURE UPDATE (2025-10-31)**: Minibeads now supports **dual sources of truth** with bidirectional synchronization.

Unlike upstream beads (which uses SQLite + JSONL), minibeads supports TWO independent storage formats:

1. **Markdown files** (`.beads/issues/*.md`) - Human-friendly, git-mergeable
2. **JSONL file** (`issues.jsonl`) - Machine-friendly, upstream bd compatible

Either format can be modified independently, and `bd sync` merges changes bidirectionally using timestamp-based conflict detection.

### Directory Structure

```
.beads/
├── config.yaml          # Required: contains issue-prefix
├── issues/              # Required: markdown storage (source of truth #1)
│   └── <prefix>-N.md   # Individual issue files
├── issues.jsonl         # Optional: JSONL storage (source of truth #2, when used)
├── .gitignore           # Auto-generated
├── command_history.log  # Optional: command logging (can be disabled with --mb-no-cmd-logging)
└── minibeads.lock       # Temporary: coarse-grained lock file (PID-based)
```

### Synchronization Strategy

Use `bd sync` to synchronize between formats:
- Compares `updated_at` timestamps to detect which format has newer changes
- Merges non-conflicting updates bidirectionally (newer wins)
- Creates issues that exist in only one format
- Flags conflicts (same timestamp, different content) for manual resolution

**Use cases:**
- **Markdown-only workflow**: Don't create JSONL, work exclusively with markdown
- **JSONL interop**: Use `bd export` to create JSONL for upstream bd compatibility
- **Dual format**: Maintain both formats, sync as needed for collaboration
- **Migration**: Import from upstream bd JSONL, then work in markdown

**Implementation**: See minibeads-19 for detailed sync implementation plan.

We will use BEADS_DIR if it is available to find `.beads`, but we will attempt to respect the upstream beads `BEADS_DB` as well. If it points to `/dir/.beads/foo.db` we will just cut off the last part of the path and use that to find .beads.

Our config.yaml will currently ONLY have a field for `issue-prefix`. Beads operations validate the .yaml and require that that key is present. If it's not, they add it to the file without disturbing anything else. The main effect of `bd init` will be to create the .beads/config.yaml that establishes that we have a database.

Actually, the `issue-prefix` is redundant because the markdown issues themselves are the source of truth (SOT). If we find config.yaml but it's missing issue-prefix, then we just check the state of the file system. If all `.beads/issues/<prefix>-<nuum>.md` files share a common prefix, then that's obviously the prefix and we can write it to the config.yaml to make it official, but we should print a WARNING that we are doing so.
### Markdown representation with yaml frontmatter
Follow the same serialization scheme as the markdown backend in the Go ./beads implementation. But for now don't implement comments or events. We will come back to them later.  The ONLY files in our datastore will be `.beads/issues/prefix-XYZ.md`.

Upgrades compared to the Go/markdown version:
- On `bd create` proactively populate an empty `# Description` section in the .md file. Don't do this for the other sections.
- Add extra validation/sanitizing. Our serialization scheme relies on us owning the top-level section headers like "Description" and "Notes. if someone attempts to set one of the string fields in an issue `bd update --description`, but provides markdown that has TOP LEVEL SECTIONS, then increase the section level of everything in their string, moving H1 `# ` to H2 `## ` and so on.  Error if you hit max section level for markdown.
- Likewise if reading an issue from serialization, issue a warning if it has top level section headers that are NOT the built in sections we support.
### Coarse-grained locking
The upstream markdown store has a complicated lock-ordering scheme to lock individual .md issues. Let's do something much simpler. Whenever we operate on our markdown "database" touch a file `.beads/minibeads.lock` and set its contents to our PID. We do exponential backoff with sleeping up to five seconds total while waiting for the coarse-grained lock. In our initial design readers will take the lock as well.

**Implementation verified**: Lock file is `minibeads.lock`, uses PID-based locking with exponential backoff (10ms initial, up to 5000ms total) as specified. See `src/lock.rs`.

---

## Validation Status

**Checked up-to-date as of 2025-10-31_#74(TBD - pending commit)**

**ARCHITECTURE CHANGED (2025-10-31)**: Dual format support added.

All architectural claims verified against implementation:
- ✅ Directory structure matches specification (.beads/config.yaml, .beads/issues/)
- ⚠️ **ARCHITECTURE UPDATE**: Now supports dual formats (markdown + JSONL)
  - Previous: Markdown-only storage (JSONL was export-only)
  - Current: Bidirectional sync support (minibeads-19 in progress)
- ✅ Lock file naming and implementation verified (minibeads.lock with PID)
- ✅ Config.yaml contains only issue-prefix field as specified
- ✅ Description section auto-creation confirmed on `bd create`
- ✅ YAML frontmatter serialization implemented as described