From 8e49462f543b553181cb2c70a3e14b28f5b160ed Mon Sep 17 00:00:00 2001 From: Jay Flowers Date: Mon, 6 Apr 2026 12:14:47 -0400 Subject: [PATCH] docs: complete documentation overhaul with auto-generated tool reference - Add replicator docs command: generates MCP tool reference from live registry (always in sync, 53 tools grouped by category) - Rewrite README: accurate status, badges, all 9 CLI commands, environment variables, MCP client config examples, mermaid architecture diagram, full package layout - Create docs/tools.md: auto-generated schemas + hand-written examples for hive_create, swarmmail_send, swarm_decompose, hivemind_store - Create CONTRIBUTING.md: dev setup, testing conventions, PR workflow - Create CHANGELOG.md: retroactive v0.1.0 and v0.2.0 entries --- AGENTS.md | 1 + CHANGELOG.md | 43 + CONTRIBUTING.md | 69 + README.md | 179 ++- cmd/replicator/docs.go | 134 ++ cmd/replicator/docs_test.go | 80 + cmd/replicator/main.go | 1 + docs/tools.md | 1413 +++++++++++++++++ openspec/changes/docs-overhaul/.openspec.yaml | 2 + openspec/changes/docs-overhaul/design.md | 36 + openspec/changes/docs-overhaul/proposal.md | 43 + .../docs-overhaul/specs/documentation.md | 44 + openspec/changes/docs-overhaul/tasks.md | 26 + 13 files changed, 2037 insertions(+), 34 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 cmd/replicator/docs.go create mode 100644 cmd/replicator/docs_test.go create mode 100644 docs/tools.md create mode 100644 openspec/changes/docs-overhaul/.openspec.yaml create mode 100644 openspec/changes/docs-overhaul/design.md create mode 100644 openspec/changes/docs-overhaul/proposal.md create mode 100644 openspec/changes/docs-overhaul/specs/documentation.md create mode 100644 openspec/changes/docs-overhaul/tasks.md diff --git a/AGENTS.md b/AGENTS.md index 8bbe20c..3133452 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -235,6 +235,7 @@ make install # Install to GOPATH/bin | `replicator doctor` | Check environment health | | `replicator stats` | Display activity summary | | `replicator query` | Run preset SQL analytics queries | +| `replicator docs` | Generate MCP tool reference (markdown) | | `replicator version` | Print version, commit, build date | ## Project Structure diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fa8997f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,43 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format follows [Keep a Changelog](https://keepachangelog.com/) and +this project adheres to [Semantic Versioning](https://semver.org/). + +## [0.2.0] - 2026-04-06 + +### Added +- 53 MCP tools across 4 categories: Hive (11), Swarm Mail (10), + Swarm (24), Memory (8) +- Swarm orchestration with git worktree isolation +- Agent messaging with file reservations +- Dewey memory proxy with graceful degradation +- CLI commands: init, doctor, stats, query, setup +- Parity testing engine (100% shape match vs TypeScript) +- macOS code signing and notarization +- Homebrew distribution via `brew install unbound-force/tap/replicator` +- GoReleaser v2 release pipeline (darwin-arm64, linux-amd64, linux-arm64) +- Dewey MCP tool name update (dewey#28 prefix drop) +- `replicator init` command for per-repo setup +- Constitution and expanded AGENTS.md + +### Changed +- Version command now displays commit hash and build date +- Makefile: added release, install targets + +## [0.1.0] - 2026-04-04 + +### Added +- Initial release: Phase 0 scaffold +- MCP JSON-RPC server (stdio transport) +- SQLite database via `modernc.org/sqlite` (pure Go, no CGo) +- Tool registry framework +- 4 hive tools: `hive_cells`, `hive_create`, `hive_close`, `hive_update` +- CLI: `replicator serve`, `replicator cells`, `replicator version` +- 16 tests across 3 packages +- CI workflow (go vet + go test + go build) +- MIT LICENSE with Joel Hooks attribution + +[0.2.0]: https://github.com/unbound-force/replicator/releases/tag/v0.2.0 +[0.1.0]: https://github.com/unbound-force/replicator/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f99a903 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# Contributing to Replicator + +## Prerequisites + +- Go 1.25+ +- Git +- Make + +## Development Setup + +```bash +git clone git@github.com:unbound-force/replicator.git +cd replicator +make check # builds, vets, and runs all tests +``` + +## Building and Testing + +```bash +make build # Build binary to bin/replicator +make test # Run all tests +make vet # Run go vet +make check # Vet + test (use this before submitting PRs) +``` + +## Testing Conventions + +- **Standard library only**: Use `testing` package. No testify, gomega, or + external assertion libraries. +- **Assertions**: Use `t.Errorf` / `t.Fatalf` directly. +- **Naming**: `TestXxx_Description` (e.g., `TestCreateCell_Defaults`). +- **Database tests**: Use `db.OpenMemory()` for in-memory SQLite. +- **Filesystem tests**: Use `t.TempDir()` for temporary directories. +- **HTTP tests**: Use `httptest.NewServer` for mock servers. +- **No shared state**: Each test creates its own fixtures. +- **Git tests**: Guard with `if testing.Short() { t.Skip("requires git") }`. + +Always run tests with `-count=1` to disable caching. + +## Pull Request Workflow + +1. **Create a branch**: Speckit features use `NNN-feature-name`, OpenSpec + changes use `opsx/change-name`. +2. **Spec first**: Non-trivial changes require a spec (either Speckit under + `specs/` or OpenSpec under `openspec/changes/`). When in doubt, use a spec. +3. **Conventional commits**: Use `type: description` format + (feat, fix, docs, chore, refactor, test). +4. **CI must pass**: Run `make check` locally before pushing. +5. **One concern per PR**: Keep changes focused and minimal. + +## Coding Conventions + +- `gofmt` and `goimports` for formatting +- GoDoc comments on all exported functions and types +- Error wrapping: `fmt.Errorf("context: %w", err)` +- Use `errors.Is` for sentinel errors (not string comparison) +- Import grouping: stdlib, then third-party, then internal +- JSON tags required on serialized struct fields +- No global mutable state + +## Project Structure + +See [AGENTS.md](AGENTS.md) for the full project structure, constitution, +behavioral constraints, and specification framework. + +## License + +By contributing, you agree that your contributions will be licensed under +the [MIT License](LICENSE). diff --git a/README.md b/README.md index aabf0fe..b4cae4c 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,185 @@ # Replicator +[![CI](https://github.com/unbound-force/replicator/actions/workflows/ci.yml/badge.svg)](https://github.com/unbound-force/replicator/actions/workflows/ci.yml) +![Go 1.25+](https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go&logoColor=white) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) + Multi-agent coordination for AI coding agents. Single Go binary, zero runtime dependencies. > Go rewrite of [cyborg-swarm](https://github.com/unbound-force/cyborg-swarm) (TypeScript). Same tools, same protocol, faster startup, simpler distribution. -## Status: Phase 0 (Scaffold) +## Status + +**53 MCP tools** | **190+ tests** | **15MB binary** | **<50ms startup** -Working: -- [x] SQLite database with hive schema (cells, events, agents) -- [x] MCP JSON-RPC server (stdio transport) -- [x] 4 tools: `hive_cells`, `hive_create`, `hive_close`, `hive_update` -- [x] CLI: `replicator serve`, `replicator cells`, `replicator version` +All 5 implementation phases are complete: -Planned: -- [ ] Phase 1: Remaining hive tools + swarm mail messaging -- [ ] Phase 2: Swarm orchestration (decompose, spawn, worktrees) -- [ ] Phase 3: Memory (Dewey proxy, Zen LLM client) -- [ ] Phase 4: Full CLI (setup, doctor, stats, query, dashboard) -- [ ] Phase 5: Parity testing against cyborg-swarm +- [x] Phase 0: MCP server, SQLite, tool registry +- [x] Phase 1: Hive (11 tools) + Swarm Mail (10 tools) +- [x] Phase 2: Swarm Orchestration (24 tools) +- [x] Phase 3: Memory / Dewey proxy (8 tools) +- [x] Phase 4: CLI (9 commands) +- [x] Phase 5: Parity testing (100% shape match) ## Install +### Homebrew (macOS) + ```bash -# From source -go install github.com/unbound-force/replicator/cmd/replicator@latest +brew install unbound-force/tap/replicator +``` + +### Go Install -# Or download binary from releases -# https://github.com/unbound-force/replicator/releases +```bash +go install github.com/unbound-force/replicator/cmd/replicator@latest ``` +### Binary Download + +Download from [GitHub Releases](https://github.com/unbound-force/replicator/releases). Available for macOS (arm64), Linux (amd64, arm64). + ## Usage ```bash -# Initialize a project for swarm operations +# Per-repo setup (creates .hive/ directory) replicator init -# Start MCP server (for AI agent connections) +# Per-machine setup (creates ~/.config/swarm-tools/ + SQLite DB) +replicator setup + +# Start MCP server (AI agents connect via stdio) replicator serve -# List hive cells +# List work items replicator cells -# Version +# Check environment health +replicator doctor + +# Activity summary +replicator stats + +# Run preset analytics queries +replicator query cells_by_status + +# Generate tool reference docs +replicator docs + +# Version info replicator version ``` -## Development +## MCP Tools (53) -```bash -make build # Build binary to bin/replicator -make test # Run all tests -make vet # Go vet -make check # vet + test -make serve # Build and run MCP server +Replicator exposes 53 tools via the [MCP protocol](https://modelcontextprotocol.io/) over stdio JSON-RPC: + +| Category | Tools | Purpose | +|----------|-------|---------| +| **Hive** | 11 | Work item tracking: create, query, update, close, epics, sessions, sync | +| **Swarm Mail** | 10 | Agent messaging: send, inbox, ack, file reservations | +| **Swarm** | 24 | Orchestration: decompose, spawn, worktrees, progress, review, insights | +| **Memory** | 8 | Dewey proxy: store/find learnings, deprecated tool stubs | + +See the full [Tool Reference](docs/tools.md) for schemas and examples. + +## Connecting an AI Agent + +Add replicator to your `opencode.json`: + +```json +{ + "mcp": { + "replicator": { + "type": "stdio", + "command": "replicator", + "args": ["serve"] + } + } +} +``` + +For Claude Code, add to `mcp_servers` in your config: + +```json +{ + "mcp_servers": { + "replicator": { + "command": "replicator", + "args": ["serve"] + } + } +} ``` +## Environment Variables + +| Variable | Default | Purpose | +|----------|---------|---------| +| `REPLICATOR_DB` | `~/.config/swarm-tools/swarm.db` | SQLite database path | +| `DEWEY_MCP_URL` | `http://localhost:3333/mcp/` | Dewey semantic memory endpoint | +| `ZEN_API_KEY` | *(none)* | OpenCode Zen gateway for LLM calls | + ## Architecture +```mermaid +flowchart LR + Agent["AI Agent\n(OpenCode, Claude)"] + MCP["MCP Server\n(stdio JSON-RPC)"] + Reg["Tool Registry\n(53 tools)"] + Domain["Domain Logic\n(hive, swarm, mail)"] + DB["SQLite\n(WAL mode)"] + Dewey["Dewey\n(semantic memory)"] + Git["Git\n(worktrees)"] + + Agent -->|stdin/stdout| MCP + MCP --> Reg + Reg --> Domain + Domain --> DB + Domain -->|HTTP proxy| Dewey + Domain -->|os/exec| Git +``` + +### Package Layout + ``` -cmd/replicator/ CLI entrypoint (cobra) +cmd/replicator/ CLI entrypoint (cobra) internal/ - config/ Configuration (env vars, defaults) - db/ SQLite connection + migrations - hive/ Cell (work item) domain logic - mcp/ MCP JSON-RPC server + config/ Configuration (env vars, defaults) + db/ SQLite + migrations (7 tables) + hive/ Cell CRUD, epics, sessions, sync + swarmmail/ Agent messaging, file reservations + swarm/ Decomposition, spawning, worktrees, review, insights + memory/ Dewey proxy, deprecated tool stubs + gitutil/ Git worktree operations (os/exec) + doctor/ Health check engine + stats/ Database activity summary + query/ Preset SQL analytics + mcp/ MCP JSON-RPC server tools/ - registry/ Tool registration framework - hive/ Hive MCP tool handlers + registry/ Tool registration framework + hive/ Hive tool handlers (11) + swarmmail/ Swarm mail tool handlers (10) + swarm/ Swarm tool handlers (24) + memory/ Memory tool handlers (8) +test/parity/ Shape comparison engine + fixtures +docs/ Generated tool reference ``` +## Development + +```bash +make build # Build binary to bin/replicator +make test # Run all tests +make vet # Go vet +make check # Vet + test +make serve # Build and run MCP server +make release # GoReleaser dry-run (local) +make install # Install to GOPATH/bin +``` + +See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and PR workflow. + ## Credits Go rewrite of [cyborg-swarm](https://github.com/unbound-force/cyborg-swarm), originally forked from [swarm-tools](https://github.com/joelhooks/swarm-tools) by [Joel Hooks](https://github.com/joelhooks). See [LICENSE](LICENSE). diff --git a/cmd/replicator/docs.go b/cmd/replicator/docs.go new file mode 100644 index 0000000..67947b4 --- /dev/null +++ b/cmd/replicator/docs.go @@ -0,0 +1,134 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "os" + "sort" + "strings" + + "github.com/spf13/cobra" + "github.com/unbound-force/replicator/internal/db" + "github.com/unbound-force/replicator/internal/memory" + "github.com/unbound-force/replicator/internal/tools/hive" + memorytools "github.com/unbound-force/replicator/internal/tools/memory" + "github.com/unbound-force/replicator/internal/tools/registry" + swarmtools "github.com/unbound-force/replicator/internal/tools/swarm" + swarmmailtools "github.com/unbound-force/replicator/internal/tools/swarmmail" +) + +func docsCmd() *cobra.Command { + var outputFlag string + cmd := &cobra.Command{ + Use: "docs", + Short: "Generate MCP tool reference documentation", + Long: `Generates a markdown document listing all registered MCP tools +with their names, descriptions, and argument schemas. + +Output is grouped by category: Hive, Swarm Mail, Swarm, Memory.`, + RunE: func(cmd *cobra.Command, args []string) error { + return runDocs(outputFlag) + }, + } + cmd.Flags().StringVar(&outputFlag, "output", "", "Write to file instead of stdout") + return cmd +} + +// runDocs generates the tool reference markdown. +func runDocs(outputPath string) error { + // Build the full registry (same wiring as serve.go). + store, err := db.OpenMemory() + if err != nil { + return fmt.Errorf("open memory db: %w", err) + } + defer store.Close() + + reg := registry.New() + hive.Register(reg, store) + swarmmailtools.Register(reg, store) + swarmtools.Register(reg, store) + memClient := memory.NewClient("http://localhost:3333/mcp/") + memorytools.Register(reg, memClient) + + var w io.Writer = os.Stdout + if outputPath != "" { + f, err := os.Create(outputPath) + if err != nil { + return fmt.Errorf("create output file: %w", err) + } + defer f.Close() + w = f + } + + return writeDocs(w, reg) +} + +// category maps tool name prefixes to display categories. +var categories = []struct { + prefix string + name string +}{ + {"hive_", "Hive"}, + {"swarmmail_", "Swarm Mail"}, + {"swarm_", "Swarm"}, + {"hivemind_", "Memory"}, +} + +func toolCategory(name string) string { + for _, c := range categories { + if strings.HasPrefix(name, c.prefix) { + return c.name + } + } + return "Other" +} + +func writeDocs(w io.Writer, reg *registry.Registry) error { + fmt.Fprintf(w, "# MCP Tool Reference\n\n") + fmt.Fprintf(w, "Auto-generated by `replicator docs`. %d tools registered.\n\n", reg.Count()) + + // Group tools by category. + grouped := make(map[string][]*registry.Tool) + for _, t := range reg.List() { + cat := toolCategory(t.Name) + grouped[cat] = append(grouped[cat], t) + } + + // Write in category order. + for _, c := range categories { + tools := grouped[c.name] + if len(tools) == 0 { + continue + } + + // Sort tools within category alphabetically. + sort.Slice(tools, func(i, j int) bool { + return tools[i].Name < tools[j].Name + }) + + fmt.Fprintf(w, "## %s (%d tools)\n\n", c.name, len(tools)) + + for _, t := range tools { + fmt.Fprintf(w, "### `%s`\n\n", t.Name) + fmt.Fprintf(w, "%s\n\n", t.Description) + + // Pretty-print the input schema. + var schema any + if err := json.Unmarshal(t.InputSchema, &schema); err == nil { + pretty, _ := json.MarshalIndent(schema, "", " ") + fmt.Fprintf(w, "```json\n%s\n```\n\n", pretty) + } + } + } + + // Write any uncategorized tools. + if other, ok := grouped["Other"]; ok && len(other) > 0 { + fmt.Fprintf(w, "## Other (%d tools)\n\n", len(other)) + for _, t := range other { + fmt.Fprintf(w, "### `%s`\n\n%s\n\n", t.Name, t.Description) + } + } + + return nil +} diff --git a/cmd/replicator/docs_test.go b/cmd/replicator/docs_test.go new file mode 100644 index 0000000..cd2f2bd --- /dev/null +++ b/cmd/replicator/docs_test.go @@ -0,0 +1,80 @@ +package main + +import ( + "bytes" + "strings" + "testing" + + "github.com/unbound-force/replicator/internal/db" + "github.com/unbound-force/replicator/internal/memory" + "github.com/unbound-force/replicator/internal/tools/hive" + memorytools "github.com/unbound-force/replicator/internal/tools/memory" + "github.com/unbound-force/replicator/internal/tools/registry" + swarmtools "github.com/unbound-force/replicator/internal/tools/swarm" + swarmmailtools "github.com/unbound-force/replicator/internal/tools/swarmmail" +) + +func buildFullRegistry(t *testing.T) *registry.Registry { + t.Helper() + store, err := db.OpenMemory() + if err != nil { + t.Fatalf("OpenMemory: %v", err) + } + t.Cleanup(func() { store.Close() }) + + reg := registry.New() + hive.Register(reg, store) + swarmmailtools.Register(reg, store) + swarmtools.Register(reg, store) + memClient := memory.NewClient("http://localhost:3333/mcp/") + memorytools.Register(reg, memClient) + return reg +} + +func TestWriteDocs_ContainsAllTools(t *testing.T) { + reg := buildFullRegistry(t) + + var buf bytes.Buffer + if err := writeDocs(&buf, reg); err != nil { + t.Fatalf("writeDocs: %v", err) + } + + output := buf.String() + + // Verify all registered tools appear in the output. + for _, tool := range reg.List() { + if !strings.Contains(output, tool.Name) { + t.Errorf("tool %q not found in docs output", tool.Name) + } + } +} + +func TestWriteDocs_HasCategoryHeaders(t *testing.T) { + reg := buildFullRegistry(t) + + var buf bytes.Buffer + writeDocs(&buf, reg) + output := buf.String() + + for _, header := range []string{"## Hive", "## Swarm Mail", "## Swarm", "## Memory"} { + if !strings.Contains(output, header) { + t.Errorf("missing category header: %q", header) + } + } +} + +func TestWriteDocs_ToolCount(t *testing.T) { + reg := buildFullRegistry(t) + + if reg.Count() < 50 { + t.Errorf("expected at least 50 tools, got %d", reg.Count()) + } + + var buf bytes.Buffer + writeDocs(&buf, reg) + output := buf.String() + + if !strings.Contains(output, "tools registered") { + t.Error("output missing tool count line") + } +} diff --git a/cmd/replicator/main.go b/cmd/replicator/main.go index ca0a148..f84d855 100644 --- a/cmd/replicator/main.go +++ b/cmd/replicator/main.go @@ -43,6 +43,7 @@ via Dewey).`, root.AddCommand(queryCmd()) root.AddCommand(setupCmd()) root.AddCommand(initCmd()) + root.AddCommand(docsCmd()) if err := root.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/docs/tools.md b/docs/tools.md new file mode 100644 index 0000000..b42ab17 --- /dev/null +++ b/docs/tools.md @@ -0,0 +1,1413 @@ +# MCP Tool Reference + +Auto-generated by `replicator docs`. 53 tools registered. + +> Regenerate this file: `replicator docs --output docs/tools.md` + +## Quick Examples + +### Create a work item + +```json +{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ + "name": "hive_create", + "arguments": {"title": "Fix login bug", "type": "bug", "priority": 2} +}} +``` + +### Send a message between agents + +```json +{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ + "name": "swarmmail_send", + "arguments": { + "to": ["worker-1"], + "subject": "Task assigned", + "body": "Please implement the login fix", + "importance": "high" + } +}} +``` + +### Decompose a task + +```json +{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ + "name": "swarm_decompose", + "arguments": { + "task": "Add user authentication with OAuth2", + "max_subtasks": 5 + } +}} +``` + +### Store a learning + +```json +{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ + "name": "hivemind_store", + "arguments": { + "information": "SQLite WAL mode requires single-writer concurrency", + "tags": "sqlite,gotcha,concurrency" + } +}} +``` + +--- + +## Hive (11 tools) + +### `hive_cells` + +Query cells from the hive database with flexible filtering. Use to list work items, find by status/type, or look up a cell by partial ID. + +```json +{ + "properties": { + "id": { + "description": "Partial cell ID to match", + "type": "string" + }, + "limit": { + "description": "Max results (default 50)", + "type": "number" + }, + "ready": { + "description": "If true, return only unblocked cells", + "type": "boolean" + }, + "status": { + "enum": [ + "open", + "in_progress", + "blocked", + "closed" + ], + "type": "string" + }, + "type": { + "enum": [ + "task", + "bug", + "feature", + "epic", + "chore" + ], + "type": "string" + } + }, + "type": "object" +} +``` + +### `hive_close` + +Close a cell with a reason. + +```json +{ + "properties": { + "id": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "id", + "reason" + ], + "type": "object" +} +``` + +### `hive_create` + +Create a new cell (work item) in the hive. + +```json +{ + "properties": { + "description": { + "type": "string" + }, + "parent_id": { + "type": "string" + }, + "priority": { + "maximum": 3, + "minimum": 0, + "type": "number" + }, + "title": { + "type": "string" + }, + "type": { + "enum": [ + "task", + "bug", + "feature", + "epic", + "chore" + ], + "type": "string" + } + }, + "required": [ + "title" + ], + "type": "object" +} +``` + +### `hive_create_epic` + +Create an epic with subtasks in one atomic operation. + +```json +{ + "properties": { + "epic_description": { + "type": "string" + }, + "epic_title": { + "type": "string" + }, + "subtasks": { + "items": { + "properties": { + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "priority": { + "maximum": 3, + "minimum": 0, + "type": "number" + }, + "title": { + "type": "string" + } + }, + "required": [ + "title" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "epic_title", + "subtasks" + ], + "type": "object" +} +``` + +### `hive_query` + +Query cells with filters (alias for hive_cells). + +```json +{ + "properties": { + "id": { + "type": "string" + }, + "limit": { + "type": "number" + }, + "ready": { + "type": "boolean" + }, + "status": { + "enum": [ + "open", + "in_progress", + "blocked", + "closed" + ], + "type": "string" + }, + "type": { + "enum": [ + "task", + "bug", + "feature", + "epic", + "chore" + ], + "type": "string" + } + }, + "type": "object" +} +``` + +### `hive_ready` + +Get the next ready cell (unblocked, highest priority). + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hive_session_end` + +End current session with handoff notes for next session. + +```json +{ + "properties": { + "handoff_notes": { + "type": "string" + } + }, + "type": "object" +} +``` + +### `hive_session_start` + +Start a new work session. Returns previous session's handoff notes if available. + +```json +{ + "properties": { + "active_cell_id": { + "type": "string" + } + }, + "type": "object" +} +``` + +### `hive_start` + +Mark a cell as in-progress. + +```json +{ + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" +} +``` + +### `hive_sync` + +Sync cells to git and push. + +```json +{ + "properties": { + "auto_pull": { + "type": "boolean" + }, + "project_path": { + "description": "Project directory to sync (default: \".\")", + "type": "string" + } + }, + "type": "object" +} +``` + +### `hive_update` + +Update a cell's status, description, or priority. + +```json +{ + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "priority": { + "maximum": 3, + "minimum": 0, + "type": "number" + }, + "status": { + "enum": [ + "open", + "in_progress", + "blocked", + "closed" + ], + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" +} +``` + +## Swarm Mail (10 tools) + +### `swarmmail_ack` + +Acknowledge a message. + +```json +{ + "properties": { + "message_id": { + "type": "number" + } + }, + "required": [ + "message_id" + ], + "type": "object" +} +``` + +### `swarmmail_health` + +Check swarm mail database health. + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `swarmmail_inbox` + +Fetch inbox (max 5 messages, bodies excluded). + +```json +{ + "properties": { + "limit": { + "maximum": 5, + "type": "number" + }, + "urgent_only": { + "type": "boolean" + } + }, + "type": "object" +} +``` + +### `swarmmail_init` + +Initialize swarm mail session. Registers the agent. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + }, + "project_path": { + "type": "string" + }, + "task_description": { + "type": "string" + } + }, + "required": [ + "project_path" + ], + "type": "object" +} +``` + +### `swarmmail_read_message` + +Fetch one message body by ID. + +```json +{ + "properties": { + "message_id": { + "type": "number" + } + }, + "required": [ + "message_id" + ], + "type": "object" +} +``` + +### `swarmmail_release` + +Release file reservations. + +```json +{ + "properties": { + "paths": { + "items": { + "type": "string" + }, + "type": "array" + }, + "reservation_ids": { + "items": { + "type": "number" + }, + "type": "array" + } + }, + "type": "object" +} +``` + +### `swarmmail_release_agent` + +Release all file reservations for a specific agent. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + } + }, + "required": [ + "agent_name" + ], + "type": "object" +} +``` + +### `swarmmail_release_all` + +Release all file reservations in the project. + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `swarmmail_reserve` + +Reserve file paths for exclusive editing. + +```json +{ + "properties": { + "exclusive": { + "type": "boolean" + }, + "paths": { + "items": { + "type": "string" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "ttl_seconds": { + "type": "number" + } + }, + "required": [ + "paths" + ], + "type": "object" +} +``` + +### `swarmmail_send` + +Send a message to other agents via swarm mail. + +```json +{ + "properties": { + "ack_required": { + "type": "boolean" + }, + "body": { + "type": "string" + }, + "importance": { + "enum": [ + "low", + "normal", + "high", + "urgent" + ], + "type": "string" + }, + "subject": { + "type": "string" + }, + "thread_id": { + "type": "string" + }, + "to": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "to", + "subject", + "body" + ], + "type": "object" +} +``` + +## Swarm (24 tools) + +### `swarm_adversarial_review` + +VDD-style adversarial code review using hostile, fresh-context agent. + +```json +{ + "properties": { + "diff": { + "type": "string" + }, + "test_output": { + "type": "string" + } + }, + "required": [ + "diff" + ], + "type": "object" +} +``` + +### `swarm_broadcast` + +Broadcast context update to all agents working on the same epic. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + }, + "epic_id": { + "type": "string" + }, + "files_affected": { + "items": { + "type": "string" + }, + "type": "array" + }, + "importance": { + "enum": [ + "info", + "warning", + "blocker" + ], + "type": "string" + }, + "message": { + "type": "string" + }, + "project_path": { + "type": "string" + } + }, + "required": [ + "project_path", + "agent_name", + "epic_id", + "message" + ], + "type": "object" +} +``` + +### `swarm_complete` + +Mark subtask complete with Verification Gate. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + }, + "bead_id": { + "type": "string" + }, + "evaluation": { + "type": "string" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "project_key": { + "type": "string" + }, + "skip_review": { + "type": "boolean" + }, + "skip_verification": { + "type": "boolean" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "project_key", + "agent_name", + "bead_id", + "summary" + ], + "type": "object" +} +``` + +### `swarm_complete_subtask` + +Handle subtask completion after Task agent returns. + +```json +{ + "properties": { + "bead_id": { + "type": "string" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "task_result": { + "type": "string" + } + }, + "required": [ + "bead_id", + "task_result" + ], + "type": "object" +} +``` + +### `swarm_decompose` + +Generate decomposition prompt for breaking task into subtasks. + +```json +{ + "properties": { + "context": { + "type": "string" + }, + "max_subtasks": { + "maximum": 10, + "minimum": 2, + "type": "integer" + }, + "task": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "task" + ], + "type": "object" +} +``` + +### `swarm_evaluation_prompt` + +Generate self-evaluation prompt for a completed subtask. + +```json +{ + "properties": { + "bead_id": { + "type": "string" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "subtask_title": { + "type": "string" + } + }, + "required": [ + "bead_id", + "subtask_title", + "files_touched" + ], + "type": "object" +} +``` + +### `swarm_get_file_insights` + +Get file-specific gotchas for worker context. + +```json +{ + "properties": { + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "files" + ], + "type": "object" +} +``` + +### `swarm_get_pattern_insights` + +Get common failure patterns across swarms. + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `swarm_get_strategy_insights` + +Get strategy success rates for decomposition planning. + +```json +{ + "properties": { + "task": { + "type": "string" + } + }, + "required": [ + "task" + ], + "type": "object" +} +``` + +### `swarm_init` + +Initialize swarm session and check tool availability. + +```json +{ + "properties": { + "isolation": { + "enum": [ + "worktree", + "reservation" + ], + "type": "string" + }, + "project_path": { + "type": "string" + } + }, + "type": "object" +} +``` + +### `swarm_plan_prompt` + +Generate strategy-specific decomposition prompt. + +```json +{ + "properties": { + "context": { + "type": "string" + }, + "max_subtasks": { + "maximum": 10, + "minimum": 2, + "type": "integer" + }, + "strategy": { + "enum": [ + "file-based", + "feature-based", + "risk-based", + "auto" + ], + "type": "string" + }, + "task": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "task" + ], + "type": "object" +} +``` + +### `swarm_progress` + +Report progress on a subtask to coordinator. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + }, + "bead_id": { + "type": "string" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "message": { + "type": "string" + }, + "progress_percent": { + "maximum": 100, + "minimum": 0, + "type": "number" + }, + "project_key": { + "type": "string" + }, + "status": { + "enum": [ + "in_progress", + "blocked", + "completed", + "failed" + ], + "type": "string" + } + }, + "required": [ + "project_key", + "agent_name", + "bead_id", + "status" + ], + "type": "object" +} +``` + +### `swarm_record_outcome` + +Record subtask outcome for implicit feedback scoring. + +```json +{ + "properties": { + "bead_id": { + "type": "string" + }, + "criteria": { + "items": { + "type": "string" + }, + "type": "array" + }, + "duration_ms": { + "minimum": 0, + "type": "integer" + }, + "error_count": { + "minimum": 0, + "type": "integer" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "retry_count": { + "minimum": 0, + "type": "integer" + }, + "strategy": { + "enum": [ + "file-based", + "feature-based", + "risk-based" + ], + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "bead_id", + "duration_ms", + "success" + ], + "type": "object" +} +``` + +### `swarm_review` + +Generate a review prompt for a completed subtask. + +```json +{ + "properties": { + "epic_id": { + "type": "string" + }, + "files_touched": { + "items": { + "type": "string" + }, + "type": "array" + }, + "project_key": { + "type": "string" + }, + "task_id": { + "type": "string" + } + }, + "required": [ + "project_key", + "epic_id", + "task_id" + ], + "type": "object" +} +``` + +### `swarm_review_feedback` + +Send review feedback to a worker. Tracks attempts (max 3). + +```json +{ + "properties": { + "issues": { + "type": "string" + }, + "project_key": { + "type": "string" + }, + "status": { + "enum": [ + "approved", + "needs_changes" + ], + "type": "string" + }, + "summary": { + "type": "string" + }, + "task_id": { + "type": "string" + }, + "worker_id": { + "type": "string" + } + }, + "required": [ + "project_key", + "task_id", + "worker_id", + "status" + ], + "type": "object" +} +``` + +### `swarm_select_strategy` + +Analyze task and recommend decomposition strategy. + +```json +{ + "properties": { + "codebase_context": { + "type": "string" + }, + "task": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "task" + ], + "type": "object" +} +``` + +### `swarm_spawn_subtask` + +Prepare a subtask for spawning with Task tool. + +```json +{ + "properties": { + "bead_id": { + "type": "string" + }, + "epic_id": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "shared_context": { + "type": "string" + }, + "subtask_description": { + "type": "string" + }, + "subtask_title": { + "type": "string" + } + }, + "required": [ + "bead_id", + "epic_id", + "subtask_title", + "files" + ], + "type": "object" +} +``` + +### `swarm_status` + +Get status of a swarm by epic ID. + +```json +{ + "properties": { + "epic_id": { + "type": "string" + }, + "project_key": { + "type": "string" + } + }, + "required": [ + "epic_id", + "project_key" + ], + "type": "object" +} +``` + +### `swarm_subtask_prompt` + +Generate the prompt for a spawned subtask agent. + +```json +{ + "properties": { + "agent_name": { + "type": "string" + }, + "bead_id": { + "type": "string" + }, + "epic_id": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "shared_context": { + "type": "string" + }, + "subtask_description": { + "type": "string" + }, + "subtask_title": { + "type": "string" + } + }, + "required": [ + "agent_name", + "bead_id", + "epic_id", + "subtask_title", + "files" + ], + "type": "object" +} +``` + +### `swarm_validate_decomposition` + +Validate a decomposition response against CellTreeSchema. + +```json +{ + "properties": { + "response": { + "type": "string" + } + }, + "required": [ + "response" + ], + "type": "object" +} +``` + +### `swarm_worktree_cleanup` + +Remove a worktree after completion or abort. Idempotent. + +```json +{ + "properties": { + "cleanup_all": { + "type": "boolean" + }, + "project_path": { + "type": "string" + }, + "task_id": { + "type": "string" + } + }, + "required": [ + "project_path" + ], + "type": "object" +} +``` + +### `swarm_worktree_create` + +Create a git worktree for isolated task execution. + +```json +{ + "properties": { + "project_path": { + "type": "string" + }, + "start_commit": { + "type": "string" + }, + "task_id": { + "type": "string" + } + }, + "required": [ + "project_path", + "task_id", + "start_commit" + ], + "type": "object" +} +``` + +### `swarm_worktree_list` + +List all active worktrees for a project. + +```json +{ + "properties": { + "project_path": { + "type": "string" + } + }, + "required": [ + "project_path" + ], + "type": "object" +} +``` + +### `swarm_worktree_merge` + +Cherry-pick commits from worktree back to main branch. + +```json +{ + "properties": { + "project_path": { + "type": "string" + }, + "start_commit": { + "type": "string" + }, + "task_id": { + "type": "string" + } + }, + "required": [ + "project_path", + "task_id" + ], + "type": "object" +} +``` + +## Memory (8 tools) + +### `hivemind_find` + +Search all memories by semantic similarity. Proxies to Dewey semantic search. + +```json +{ + "properties": { + "collection": { + "type": "string" + }, + "limit": { + "type": "number" + }, + "query": { + "type": "string" + } + }, + "required": [ + "query" + ], + "type": "object" +} +``` + +### `hivemind_get` + +Get specific memory by ID (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hivemind_index` + +Index AI session directories (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hivemind_remove` + +Delete outdated/incorrect memory (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hivemind_stats` + +Memory statistics and health check (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hivemind_store` + +Store a memory (learnings, decisions, patterns) with metadata and tags. Proxies to Dewey semantic search. + +```json +{ + "properties": { + "information": { + "type": "string" + }, + "tags": { + "type": "string" + } + }, + "required": [ + "information" + ], + "type": "object" +} +``` + +### `hivemind_sync` + +Sync learnings to git-backed team sharing (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + +### `hivemind_validate` + +Confirm memory is still accurate (DEPRECATED) + +```json +{ + "properties": {}, + "type": "object" +} +``` + diff --git a/openspec/changes/docs-overhaul/.openspec.yaml b/openspec/changes/docs-overhaul/.openspec.yaml new file mode 100644 index 0000000..796d2d7 --- /dev/null +++ b/openspec/changes/docs-overhaul/.openspec.yaml @@ -0,0 +1,2 @@ +schema: unbound-force +created: 2026-04-06 diff --git a/openspec/changes/docs-overhaul/design.md b/openspec/changes/docs-overhaul/design.md new file mode 100644 index 0000000..143d1db --- /dev/null +++ b/openspec/changes/docs-overhaul/design.md @@ -0,0 +1,36 @@ +## Context + +The README is stuck at Phase 0. The codebase has 53 tools, 8 CLI commands, 190+ tests, and a working Homebrew distribution. GoDoc coverage is 100% and AGENTS.md is comprehensive, but user-facing docs are stale or missing. + +## Goals / Non-Goals + +### Goals +- Rewrite README to accurately reflect the current codebase +- Create a `replicator docs` command that auto-generates tool reference markdown +- Create `docs/tools.md` combining auto-generated schemas with hand-written examples +- Add CONTRIBUTING.md and CHANGELOG.md +- Add mermaid architecture diagram to README + +### Non-Goals +- Generating a docs website (static site, Hugo, etc.) +- Adding `Example_xxx` test functions for godoc (low priority polish) +- Creating a SECURITY.md (no public vulnerability reporting process yet) +- Updating spec artifacts (they're historical records) + +## Decisions + +**D1: `replicator docs` iterates the registry.** The command creates an in-memory store, registers all tools (same wiring as `serve.go`), then iterates `registry.List()` to emit markdown. This guarantees the output matches what `tools/list` returns at runtime. + +**D2: Category grouping via naming convention.** Tools are grouped by prefix: `hive_*` → Hive, `swarmmail_*` → Swarm Mail, `swarm_*` → Swarm, `hivemind_*` → Memory. The `docs` command derives the category from the tool name prefix. + +**D3: Output format is GitHub-flavored markdown.** Each tool gets: `### tool_name`, description paragraph, and `inputSchema` as a fenced JSON code block. The `--output` flag writes to a file; default is stdout. + +**D4: `docs/tools.md` is partially generated, partially hand-written.** The auto-generated section (schema tables) is wrapped in `` / `` markers. Hand-written examples live outside the markers and are preserved across regeneration. + +**D5: README mermaid diagram shows the MCP request flow.** A `flowchart LR` diagram: `Agent --> |stdin JSON-RPC| MCP Server --> Registry --> Tool Handler --> Domain Logic --> SQLite`. This renders natively on GitHub. + +## Risks / Trade-offs + +**Risk: None.** This is documentation. No production behavior changes. The only new code is the `docs` command which reads the registry (read-only) and writes markdown (stdout or file). + +**Trade-off: Hand-written examples require maintenance.** When a tool's schema changes, the auto-generated schema section updates automatically but the hand-written examples may drift. Mitigation: keep examples minimal (3-4 key tools, not all 53). diff --git a/openspec/changes/docs-overhaul/proposal.md b/openspec/changes/docs-overhaul/proposal.md new file mode 100644 index 0000000..445ee57 --- /dev/null +++ b/openspec/changes/docs-overhaul/proposal.md @@ -0,0 +1,43 @@ +## Why + +The README describes Phase 0 with 4 tools. The actual codebase has completed all 5 phases with 53 MCP tools, 8 CLI commands, full swarm orchestration, Dewey memory proxy, and parity testing. A developer or AI agent looking at the README gets a fundamentally wrong picture of what replicator can do. + +Beyond the README, there is no MCP tool reference document -- the 53 tools and their argument schemas are only discoverable by reading source code or calling `tools/list` at runtime. There is no CONTRIBUTING.md, no CHANGELOG.md, and no architecture diagram. + +GoDoc coverage is already excellent (100% of exported functions/types have doc comments), and AGENTS.md is comprehensive for AI agents. The gap is in user-facing documentation. + +## What Changes + +### New Capabilities +- `replicator docs` CLI command: auto-generates a markdown tool reference from the live tool registry (always in sync with code) +- `docs/tools.md`: complete MCP tool reference with schemas and hand-written usage examples for key tools +- Mermaid architecture diagram in README showing the MCP request flow + +### Modified Capabilities +- `README.md`: rewritten from scratch with accurate status, full tool inventory, all CLI commands, environment variables, MCP client config examples, badges, and architecture tree +- `CONTRIBUTING.md`: new file covering dev setup, testing conventions, PR workflow, and spec-first requirements +- `CHANGELOG.md`: retroactive entries for v0.1.0 and v0.2.0 + +## Impact + +- `cmd/replicator/docs.go` (new, ~80 lines) +- `cmd/replicator/docs_test.go` (new, ~40 lines) +- `cmd/replicator/main.go` (add `docsCmd()` registration) +- `docs/tools.md` (new, auto-generated + hand-curated examples) +- `README.md` (full rewrite) +- `CONTRIBUTING.md` (new) +- `CHANGELOG.md` (new) + +## Constitution Alignment + +### I. Autonomous Collaboration +**PASS**: The `replicator docs` command produces a self-describing artifact (markdown) that any consumer can read without consulting the producing tool. + +### II. Composability First +**PASS**: Documentation does not introduce dependencies. The `docs` command uses only the existing tool registry -- no new imports. + +### III. Observable Quality +**PASS**: The tool reference is auto-generated from the same registry that serves MCP requests, guaranteeing accuracy. The `docs` command's output can be diffed against `docs/tools.md` to detect drift. + +### IV. Testability +**PASS**: The `docs` command is testable by verifying its output contains all registered tools. No external services needed. diff --git a/openspec/changes/docs-overhaul/specs/documentation.md b/openspec/changes/docs-overhaul/specs/documentation.md new file mode 100644 index 0000000..c085e7e --- /dev/null +++ b/openspec/changes/docs-overhaul/specs/documentation.md @@ -0,0 +1,44 @@ +## ADDED Requirements + +### Requirement: Auto-generated tool reference + +`replicator docs` MUST output a markdown document listing all registered MCP tools with their names, descriptions, and argument schemas. + +#### Scenario: Generate tool reference to stdout +- **GIVEN** the tool registry has 53 tools registered +- **WHEN** `replicator docs` is run +- **THEN** stdout contains a markdown document with all 53 tools grouped by category + +#### Scenario: Generate tool reference to file +- **GIVEN** a valid output path +- **WHEN** `replicator docs --output docs/tools.md` is run +- **THEN** the file is created with the tool reference content + +#### Scenario: Tool count matches registry +- **GIVEN** a new tool is added to the registry +- **WHEN** `replicator docs` is run after rebuild +- **THEN** the new tool appears in the output without any manual doc updates + +### Requirement: Accurate README + +The README MUST accurately reflect the current state of the codebase: tool count, CLI commands, architecture, install methods, and status. + +#### Scenario: Developer reads README +- **GIVEN** a developer visits the GitHub repo +- **WHEN** they read the README +- **THEN** the status section reflects all 5 completed phases, the tool count is 53, and all 8 CLI commands are documented + +### Requirement: Contributing guide + +A CONTRIBUTING.md MUST exist explaining development setup, testing conventions, and PR workflow for human contributors. + +#### Scenario: New contributor setup +- **GIVEN** a developer clones the repo +- **WHEN** they read CONTRIBUTING.md +- **THEN** they can build, test, and submit a PR by following the documented steps + +## MODIFIED Requirements + +### Requirement: CLI command list + +The CLI MUST include a `docs` command alongside the existing `init`, `setup`, `serve`, `cells`, `doctor`, `stats`, `query`, and `version` commands. diff --git a/openspec/changes/docs-overhaul/tasks.md b/openspec/changes/docs-overhaul/tasks.md new file mode 100644 index 0000000..b2df472 --- /dev/null +++ b/openspec/changes/docs-overhaul/tasks.md @@ -0,0 +1,26 @@ +## 1. `replicator docs` command + +- [x] 1.1 Create `cmd/replicator/docs.go` with `docsCmd() *cobra.Command` and `runDocs(outputPath string) error`. Wire in-memory store + full tool registration (hive, swarmmail, swarm, memory). Iterate `registry.List()`, group by name prefix (`hive_` / `swarmmail_` / `swarm_` / `hivemind_`), emit markdown with `### tool_name`, description, and fenced JSON `inputSchema` per tool. +- [x] 1.2 Add `--output` flag (default stdout). When set, write to file instead of stdout. +- [x] 1.3 Register `docsCmd()` in `cmd/replicator/main.go` +- [x] 1.4 Create `cmd/replicator/docs_test.go`: verify output contains all 53 tool names, verify category headers exist (Hive, Swarm Mail, Swarm, Memory), verify output is valid markdown + +## 2. Tool reference document + +- [x] 2.1 Run `replicator docs` and write output to `docs/tools.md` +- [x] 2.2 Add hand-written usage examples (request/response JSON) for 4 key tools: `hive_create`, `swarmmail_send`, `swarm_decompose`, `hivemind_store` + +## 3. README rewrite + +- [x] 3.1 Rewrite `README.md` with: project description, badges (CI workflow, Go version, license), accurate status (all phases complete, 53 tools, 190+ tests, 15MB binary), install section (Homebrew + `go install` + binary download), full usage section (all 9 CLI commands including `docs`), environment variables table, MCP client config example (`opencode.json` snippet), mermaid architecture diagram (flowchart: Agent → MCP Server → Registry → Tool → Domain → SQLite), complete package tree (all 15+ packages), credits + +## 4. Supporting docs + +- [x] 4.1 Create `CONTRIBUTING.md`: prerequisites (Go 1.25+, git), dev setup (`git clone` + `make check`), testing conventions (stdlib only, `db.OpenMemory()`, `t.TempDir()`, `httptest.NewServer`), PR workflow (branch naming, conventional commits, review council), spec-first development requirement (link to AGENTS.md) +- [x] 4.2 Create `CHANGELOG.md` with retroactive entries: v0.1.0 (Phase 0 scaffold, 4 tools, MCP server, SQLite, CI), v0.2.0 (Phases 1-5 complete, 53 tools, macOS signing, Homebrew distribution, Dewey proxy, parity testing, init command) + +## 5. Final updates + +- [x] 5.1 Update AGENTS.md CLI commands table to include `replicator docs` +- [x] 5.2 Run `make check` -- all tests pass +- [x] 5.3 Run `./bin/replicator docs | head -20` -- verify tool reference output