diff --git a/README.md b/README.md index 7581d42..4e6c99a 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,15 @@ **A second opinion (and a third) before you ship AI-written code — using the AI subscriptions you already pay for.** -2–3 *different* AI tools review the same change in parallel, only green-lighting when they agree. Runs on your existing Claude Pro / ChatGPT Plus / Gemini Advanced — typical review costs **$0** out of pocket. +2–3 _different_ AI tools review the same change in parallel, only green-lighting when they agree. Runs on your existing Claude Pro / ChatGPT Plus / Gemini Advanced — typical review costs **$0** out of pocket. [![CI](https://github.com/chorus-codes/chorus/actions/workflows/ci.yml/badge.svg)](https://github.com/chorus-codes/chorus/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/chorus-codes?color=22c55e)](https://www.npmjs.com/package/chorus-codes) [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](./LICENSE) -[![Status](https://img.shields.io/badge/status-v0.7-brightgreen)]() -[![Node](https://img.shields.io/badge/node-%E2%89%A520-339933)]() +[![Status](https://img.shields.io/badge/status-v0.8-brightgreen)](./ROADMAP.md) +[![Node](https://img.shields.io/badge/node-%E2%89%A520-339933)](https://nodejs.org/) -[Website](https://chorus.codes) · [Roadmap](./ROADMAP.md) · [Issues](https://github.com/chorus-codes/chorus/issues) +[Repo](https://github.com/crypticpy/chorus) · [Roadmap](./ROADMAP.md) · [Issues](https://github.com/crypticpy/chorus/issues) @@ -43,7 +43,7 @@ Every diff × 3 reviewers × pay-per-token = real money. So nobody does it routi ### Chorus fixes all three ✅ **Different vendors review each other.** -Claude writes, GPT and Gemini check it. Different blind spots cover each other. Disagreement = red flag *before* you merge. +Claude writes, GPT and Gemini check it. Different blind spots cover each other. Disagreement = red flag _before_ you merge. ✅ **Uses your existing AI subscriptions.** You're already paying for Claude Pro / ChatGPT Plus / Gemini Advanced (~$20/mo each). Chorus drives them headlessly through their CLIs — every multi-AI review costs **$0 out of pocket**, just counts against the quota you already have. Per-token API users save 10-100× vs running the same prompts directly. @@ -59,24 +59,24 @@ That's the whole pitch. 🚨 **You asked Claude to write a `divide(a, b)` helper.** It says "looks correct!" You ship. Production crashes at 2am because nobody handled `b = 0`. -*With Chorus: GPT or Gemini would have flagged it in the review pass before you merged.* +_With Chorus: GPT or Gemini would have flagged it in the review pass before you merged._ 🔧 **You're refactoring a critical path.** Your AI rewrote 200 lines and says it's behaviour-equivalent. You're tired and skeptical. -*Run it through Chorus. Three different AIs all saying "yes, equivalent" lets you sleep.* +_Run it through Chorus. Three different AIs all saying "yes, equivalent" lets you sleep._ 🏗️ **Big architectural call** — queue vs polling, sync vs async, this DB vs that one. -Write a paragraph, hit Chorus. *Three different models give you three angles you hadn't thought of.* +Write a paragraph, hit Chorus. _Three different models give you three angles you hadn't thought of._ 📝 **Reviewing a 600-line PR.** -You're short on time. Paste the diff into Chorus. *Three reviewers spot the obvious bugs in 90 seconds. Your job becomes the 5% they couldn't catch.* +You're short on time. Paste the diff into Chorus. _Three reviewers spot the obvious bugs in 90 seconds. Your job becomes the 5% they couldn't catch._ ⚔️ **Test-driven development where neither AI cheats.** -*One AI writes tests blind to the code; another AI writes code to pass them.* Use the `red-green` template. +_One AI writes tests blind to the code; another AI writes code to pass them._ Use the `red-green` template. 🐛 **Hunting a flaky bug.** Reproduces 1-in-20, no obvious pattern. Drop the failing test + suspect code into Chorus. -*Each reviewer attacks the bug from a different angle — race? clock skew? off-by-one? — and you land on the cause faster than walking it alone.* +_Each reviewer attacks the bug from a different angle — race? clock skew? off-by-one? — and you land on the cause faster than walking it alone._ --- @@ -114,15 +114,15 @@ expects regardless of how you installed. Or invoke a specific MCP tool directly — every CLI uses the same name (`chorus`) and exposes nine tools: -| Tool | What it does | -|---|---| -| `create_chat` | Kick off a review (returns a `chatId` + URL) | -| `wait_for_chat` | Block until the run reaches a terminal state | -| `get_chat_status` | Poll a running chat without blocking | -| `cancel_chat` / `resume_chat` | Stop or restart | -| `list_templates` / `list_personas` | Discover what's available | -| `invoke_persona` | Run a single persona (skip multi-reviewer fan-out) | -| `list_blocked` | See chats that need human input | +| Tool | What it does | +| ---------------------------------- | -------------------------------------------------- | +| `create_chat` | Kick off a review (returns a `chatId` + URL) | +| `wait_for_chat` | Block until the run reaches a terminal state | +| `get_chat_status` | Poll a running chat without blocking | +| `cancel_chat` / `resume_chat` | Stop or restart | +| `list_templates` / `list_personas` | Discover what's available | +| `invoke_persona` | Run a single persona (skip multi-reviewer fan-out) | +| `list_blocked` | See chats that need human input | Example raw invocation (from any MCP client): @@ -130,7 +130,7 @@ Example raw invocation (from any MCP client): // tool: chorus.create_chat { "template": "code-review", - "work": "Review the staged diff vs main. Flag race conditions and missing tests." + "work": "Review the staged diff vs main. Flag race conditions and missing tests.", } // → { "chatId": "abc123", "url": "http://localhost:5050/runs/abc123", "status": "reviewing" } ``` @@ -139,10 +139,10 @@ Stream results back into your editor, or open the URL to watch live. --- -**Requires** Node 20+ and at least *one* of these (you probably already have one): +**Requires** Node 20+ and at least _one_ of these (you probably already have one): - Claude Code, Codex CLI, Gemini CLI, OpenCode, or Kimi CLI — uses your existing subscription, no extra cost -- *or* an OpenRouter API key (one key, 200+ models, pay-per-use) +- _or_ an OpenRouter API key (one key, 200+ models, pay-per-use)
Don't have any of those? @@ -202,12 +202,12 @@ function divide(a, b) { Submit to Chorus with the **Code Review** template (1 writer + 2 reviewers, both must agree to ship): -| Step | What happens | -|---|---| -| 1. Claude writes | "Looks correct to me!" | -| 2. GPT reviews in parallel | 🚨 *No type validation — `divide('a','b')` returns `NaN`* | -| 3. Gemini reviews in parallel | 🚨 *Missing zero-check — `divide(1, 0)` returns `Infinity`* | -| 4. Verdict | ❌ **REJECT** — both reviewers flagged real bugs | +| Step | What happens | +| ----------------------------- | ----------------------------------------------------------- | +| 1. Claude writes | "Looks correct to me!" | +| 2. GPT reviews in parallel | 🚨 _No type validation — `divide('a','b')` returns `NaN`_ | +| 3. Gemini reviews in parallel | 🚨 _Missing zero-check — `divide(1, 0)` returns `Infinity`_ | +| 4. Verdict | ❌ **REJECT** — both reviewers flagged real bugs | Now you know what to fix **before** you push. @@ -217,16 +217,33 @@ Now you know what to fix **before** you push. Don't figure out which AIs to use yourself. Pick a pattern that fits the moment: -| Use this when... | Template | -|---|---| -| Pre-merge sanity check | `code-review` — 1 writer + 2 reviewers, both must agree | -| Diagnosing a weird bug | `bug-diagnose` — one hypothesises, one challenges | -| Big architectural call | `architect-review` — 3 different vendors critique your plan | -| TDD where neither AI cheats | `red-green` — tests written blind to code | -| Quick audit of a diff someone else wrote | `review-only` — paste, get 3 opinions, no writer | +| Use this when... | Template | +| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Pre-merge sanity check | `code-review` — 1 writer + 2 reviewers, both must agree | +| Diagnosing a weird bug | `bug-diagnose` — one hypothesises, one challenges | +| Big architectural call | `architect-review` — 3 different vendors critique your plan | +| TDD where neither AI cheats | `red-green` — tests written blind to code | +| Quick audit of a diff someone else wrote | `review-only` — paste, get 3 opinions, no writer | +| Audit a whole repo before changing it | `audit-code-review`, `audit-architecture-review`, `audit-engineering-review`, `audit-de-slopify`, `audit-monolith-breakdown` — produces an approve-by-checkbox plan, then fans approved items out to per-worker branches | +| Babysit a PR through bot review | `pr-babysit` — autonomous loop that judges PR-review-bot comments (CodeRabbit / Sourcery / Greptile / Codex), pushes fixes, replies, and waits for merge | Make your own by dropping a YAML file in `~/.chorus/templates/`. Or duplicate one of the built-ins and tweak. +### Audit + orchestrate (multi-stage review) + +The `audit-*` templates run in two phases: + +1. **Audit phase** — point Chorus at a repo, pick a preset (code review, architecture review, de-slopify, monolith breakdown, engineering review), and one writer produces a checklist of concrete changes. You approve the items you want. +2. **Orchestrate phase** — approved items fan out to worker voices on per-worker git branches. Each worker gets its own slot, model, and persona. Output: an `orchestrate-manifest.json` with diff stats and per-worker status, plus Checkout / Open-PR buttons in the cockpit. + +### Verify phase + TDD loop + +Any template can include a `verify` phase. It runs your project's `package.json#chorus.verify` command (e.g. `pnpm test` or `npx tsc --noEmit`), captures the output, and routes it through the reviewer for a pass/fail verdict. Add `feedbackPhase: implement` + `maxIterations: 3` and a failed verify re-prompts the named doer with the failure output — a tight TDD loop with no human in the middle. + +### PR-babysit + +Once you've got a PR open and the review bots are starting to comment, `chorus babysit register ` puts that PR on an autonomous loop. The daemon polls the PR, judges each new bot comment (apply-trivial / apply-targeted / apply-architectural / reply-disagree / reply-ack / defer-to-human), pushes fixes or posts replies, and runs verify on each fix. After two consecutive quiet ticks the daemon sits in `quiet_check` and waits — it does not call `gh pr merge` itself; you (or the `/babysit-pr` Claude Code skill, which wraps this loop and adds the merge gate) do the squash-merge once CI is green. Inspect with `chorus babysit show `; pause with `chorus babysit pause `. +
Custom template example @@ -239,8 +256,8 @@ slots: lineage: anthropic model: claude-sonnet-4-6 reviewers: - - { lineage: openai, model: codex, persona: sentinel } - - { lineage: google, model: gemini-2.5-pro, persona: sentinel } + - { lineage: openai, model: codex, persona: sentinel } + - { lineage: google, model: gemini-2.5-pro, persona: sentinel } - { lineage: opencode, model: opencode-go/kimi-k2.6, persona: sentinel } quorum: type: unanimous @@ -254,13 +271,13 @@ quorum: Each reviewer can wear a "hat" — a focus area Chorus prepends to their prompt: -| Persona | What they look for | -|---|---| -| 🛡️ **Sentinel** | Security holes, auth bypass, injection | -| 🗺️ **Cartographer** | Cross-platform issues (Windows vs Mac, browser support) | -| 💰 **Accountant** | Cost regressions (extra DB queries, API calls) | -| ⚡ **Profiler** | Performance regressions | -| 🔍 **Inspector**, 📦 **Quartermaster**, 🛎️ **Concierge**, 🏛️ **Conservator**, 📚 **Librarian**, 🌐 **Translator** | …and more — see Personas page in cockpit | +| Persona | What they look for | +| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | +| 🛡️ **Sentinel** | Security holes, auth bypass, injection | +| 🗺️ **Cartographer** | Cross-platform issues (Windows vs Mac, browser support) | +| 💰 **Accountant** | Cost regressions (extra DB queries, API calls) | +| ⚡ **Profiler** | Performance regressions | +| 🔍 **Inspector**, 📦 **Quartermaster**, 🛎️ **Concierge**, 🏛️ **Conservator**, 📚 **Librarian**, 🌐 **Translator** | …and more — see Personas page in cockpit | Different personas reviewing the same change = wider net. @@ -294,13 +311,13 @@ Chorus adds **zero markup**. We don't see your tokens. Reviewers run on your machine. You decide how much trust to give them: -| Mode | Read code | Write code | Network | When to use | -|---|:---:|:---:|:---:|---| -| 🔒 **Strict** | ✅ | ❌ | ❌ | Reviewing a diff you don't trust | -| 📁 **Workspace** *(default)* | ✅ | ✅ inside chat dir | ❌ | Day-to-day | -| 🔓 **Full** | ✅ | ✅ anywhere | ✅ | Personal machine, full trust | +| Mode | Read code | Write code | Network | When to use | +| ---------------------------- | :-------: | :----------------: | :-----: | -------------------------------- | +| 🔒 **Strict** | ✅ | ❌ | ❌ | Reviewing a diff you don't trust | +| 📁 **Workspace** _(default)_ | ✅ | ✅ inside chat dir | ❌ | Day-to-day | +| 🔓 **Full** | ✅ | ✅ anywhere | ✅ | Personal machine, full trust | -Configure on first run, or anytime at *Settings → Permissions*. +Configure on first run, or anytime at _Settings → Permissions_. > **Trust model in plain English.** "Workspace" means the reviewer can write files inside its working directory and run scoped commands, but can't reach the internet or write outside the sandbox. "Full" means anything-goes — only enable on a personal machine you own. Run `chorus doctor` to verify each AI tool got the sandbox you set. @@ -308,13 +325,13 @@ Configure on first run, or anytime at *Settings → Permissions*. ## Compared to other code-review tools -| | **Chorus** | CodeRabbit | Greptile | Cursor Review | GitHub Copilot | -|---|:---:|:---:|:---:|:---:|:---:| -| Multiple AI vendors review the same change | ✅ | ❌ | ❌ | ❌ | ❌ | -| Uses your existing AI subscriptions | ✅ | ❌ | ❌ | ❌ | ❌ | -| Runs locally (your code never leaves your existing AI vendors) | ✅ | ❌ | ❌ | partial | ❌ | -| Open source (modify + self-host) | ✅ Apache-2.0 | ❌ | ❌ | ❌ | ❌ | -| Custom review patterns | ✅ | partial | ❌ | ❌ | ❌ | +| | **Chorus** | CodeRabbit | Greptile | Cursor Review | GitHub Copilot | +| -------------------------------------------------------------- | :-----------: | :--------: | :------: | :-----------: | :------------: | +| Multiple AI vendors review the same change | ✅ | ❌ | ❌ | ❌ | ❌ | +| Uses your existing AI subscriptions | ✅ | ❌ | ❌ | ❌ | ❌ | +| Runs locally (your code never leaves your existing AI vendors) | ✅ | ❌ | ❌ | partial | ❌ | +| Open source (modify + self-host) | ✅ Apache-2.0 | ❌ | ❌ | ❌ | ❌ | +| Custom review patterns | ✅ | partial | ❌ | ❌ | ❌ | **The unique thing:** your code never goes to a new vendor. Chorus just orchestrates the AI tools you already use. @@ -324,6 +341,7 @@ Configure on first run, or anytime at *Settings → Permissions*. ```bash chorus init # one-time: detect + connect AI tools +chorus quickstart # interactive walkthrough: init + start + first chat chorus start --ui # boot + open browser chorus stop # shut it down chorus status # is it running? @@ -331,6 +349,16 @@ chorus doctor # diagnose AI tool detection / sandbox issues chorus diagnose # print a redacted diagnostic bundle for bug reports ``` +### Babysit a PR (autonomous bot-review loop) + +```bash +chorus babysit register # put a PR on the autonomous loop +chorus babysit list [--active] # see what's being watched +chorus babysit show # decisions, comments, current state +chorus babysit pause # stop processing without losing state +chorus babysit resume # restart a paused job +``` + --- ## Reporting bugs @@ -346,7 +374,7 @@ version (and a **VERSION MISMATCH** flag if the CLI was upgraded but the daemon hasn't been restarted), node + OS + arch, daemon health, DB counts, CLI detection, the latest crash dump if any, and the last 50 lines of `daemon.log`. Paste the block into a new issue at -. +. If chorus crashes hard (uncaught exception during boot — common on older Node + Windows combos), a self-contained crash log is written to @@ -363,7 +391,9 @@ Chorus pings home once on startup and once every 24h. The payload is fixed: "schema": 1, "installId": "", "version": "0.7.0", - "os": "linux", "arch": "x64", "node": "22", + "os": "linux", + "arch": "x64", + "node": "22", "daemonUptimeSeconds": 86400, "chatsLast24h": 12 } @@ -388,7 +418,7 @@ The install ID lives at `~/.chorus/install-id` — `rm` it for a fresh one. - [x] **v0.5** — Daemon + cockpit + 4 AI vendors - [x] **v0.6** — MCP server, persona system - [x] **v0.7** — OpenRouter integration, voices table, real-time sidebar -- [ ] **v0.8** — Multi-stage review (write → review → fix → re-review) +- [x] **v0.8** — Multi-stage review: audit + orchestrate (per-worker branches), verify phase + TDD loop, PR-babysit - [ ] **v0.9** — Per-voice persona overrides - [ ] **v1.0** — Hosted GitHub App + cloud fan-out @@ -431,11 +461,12 @@ flowchart TB - **Daemon** — small local server (port 7707) that spawns AI tools as subprocesses, parses their output, and tracks state in a SQLite database at `~/.chorus/chorus.db`. - **Cockpit** — the web UI at port 5050 (Next.js). Templates, chats, voices, settings. -- **MCP server** — lets *other* AI tools (Claude Code, Cursor, etc.) call Chorus programmatically. +- **MCP server** — lets _other_ AI tools (Claude Code, Cursor, etc.) call Chorus programmatically. Each AI runs as an isolated subprocess. Chorus reads their structured output (stream-JSON), compares against the template's quorum rule, and emits a verdict. Nothing leaves your machine except the calls to the AI vendors you already use. Code layout: + - `src/daemon/` — Fastify server + agent shims (one per AI tool) - `src/app/` — Next.js cockpit - `src/mcp/` — JSON-RPC MCP server @@ -450,7 +481,7 @@ Code layout: PRs welcome. ```bash -git clone https://github.com/chorus-codes/chorus.git +git clone https://github.com/crypticpy/chorus.git cd chorus && pnpm install pnpm dev:daemon # daemon on :7707 pnpm dev # cockpit on :5050 @@ -467,11 +498,9 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide. ## Links -- 🌐 Website: - 🗺️ Roadmap: [./ROADMAP.md](./ROADMAP.md) -- 🐛 Issues: -- 💬 Discussions: -- 🐦 Twitter / X: [@chorus_codes](https://twitter.com/chorus_codes) +- 🐛 Issues: +- 💬 Discussions: --- diff --git a/ROADMAP.md b/ROADMAP.md index 5f853a4..f8a700c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -13,7 +13,7 @@ Voices × Personas × Phases ``` - **Voices** — the model behind the keyboard. CLI subscriptions (Claude Code, Codex, Gemini, OpenCode, Kimi) and API-routed models (anything reachable via OpenRouter, Anthropic API, etc.). Each voice has a lineage tag (anthropic / openai / google / moonshot / deepseek / meta / mistral / xai). -- **Personas** — the *role* a reviewer plays. A system prompt + worldview. Same model produces wildly different output as Sentinel (security) vs Cartographer (cross-platform) vs Accountant (cost). +- **Personas** — the _role_ a reviewer plays. A system prompt + worldview. Same model produces wildly different output as Sentinel (security) vs Cartographer (cross-platform) vs Accountant (cost). - **Phases** — the position in the pipeline. Discover, Define, Develop, Deliver, Debate, Decide. User can add, remove, reorder. A **template** is a chosen path through this 3D space — N phases, each with a (voice, persona) pair. Different combinations produce wildly different outcomes. Users will experiment to find what works for their domain (Rails refactor, React perf, Solidity audit, copy review, …) and share what wins. @@ -22,62 +22,67 @@ A **template** is a chosen path through this 3D space — N phases, each with a ## Status tracker -| Item | Version | Status | Notes | -|---|---|---|---| -| Audit fixes 1-7 (dogfood pre-publish) | 0.6 | ✅ DONE | shipped 2026-05-01 | -| Cross-platform CLI detection (`where` + fallback dirs + `--version` verify) | 0.6 | ✅ DONE | | -| Manual CLI path entry UI | 0.6 | ✅ DONE | | -| Persona registry — table + 10 built-ins + seed loader | 0.7 | ✅ DONE | | -| MCP `list_personas` + `invoke_persona` | 0.7 | ✅ DONE | 9 MCP tools total | -| Voices abstraction (table + auto-populate + 6 UI surfaces) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #2 c758e80); 71 voices auto-seed across 5 lineages; vendor_family taxonomy | -| libsql migration (better-sqlite3 → @libsql/client, no node-gyp) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #1 1441532); fixes `npm install -g` on Windows / locked-down boxes | -| Review-only mode (artifact in, no doer; substrate + cockpit + verdict persistence) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #4 b21a4b8); unlocks `/work` & MCP harnesses calling chorus as a pure review service | -| Per-phase `timeoutMs` override (round-2-deferred §2) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #5 9a47f23); 30s..1h schema bound, threaded through doer + reviewer + tmux + review-only synthesis | -| Token-capture rails (round-2-deferred §1) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #8 3910607); `AgentEvent.message_done.usage` + capture in doer return shape — per-lineage parser updates + DB persistence + cost math are follow-ups | -| Opt-out telemetry heartbeat (round-2-deferred §4) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #6 bac7445); daemon-side ping to chorus.codes once on boot + every 24h; three opt-out paths; server endpoint deploy + privacy notice are separate infra tasks | -| Structured JSON-line logger substrate (round-2-deferred §3) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #7 7ce6b46); pino-shaped wire format (level/time/pid/hostname); 5 first-class call sites; mechanical migration of remaining ~50 console sites is a follow-up | -| Codex quota_exhausted detection + `CHORUS_CODEX_HOME` override | 0.7 | ✅ DONE | merged 2026-05-02 (PR #9 ee7b5fb); codex emits `ERROR: hit your usage limit` to stderr and exits 1, parseCodexExit now reads stderr+code and emits `error{kind:'quota_exhausted'}` instead of writing 0-byte answer.md. Round-1 review-only dogfood caught the regex was too loose (codex echoes user prompt to stderr → false-positive risk); fixed by anchoring on literal `ERROR:` prefix. Env override is a stopgap; proper UX is multi-account-per-CLI in v0.8. | -| SSE hijack + backpressure drain race + init log path | 0.7 | ✅ DONE | merged 2026-05-02 (PR #13 a5f6db1); fastify `reply.hijack()` before `reply.raw` writes, drain handler clears `paused` first then flushes, `chorus init` log honours `CHORUS_DB_PATH`. cdx-1 round-2 follow-ups from libsql migration. | -| Cockpit retry button + correct reviewer count | 0.7 | ✅ DONE | merged 2026-05-02 (PR #14 0ab62e4) | -| Templates `liveYaml` precedence test coverage | 0.7 | ✅ DONE | merged 2026-05-02 (PR #15 02e0820) — Fix C from PR #10 | -| Time + token chips on participant cards | 0.7 | ✅ DONE | merged 2026-05-02 (PR #16 b1e2f09); reads from `_stats.json` sidecar | -| Personas wire into doer + reviewer slots (per-slot binding) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #17 969dca5); each phase row carries its own persona — removes the §1 "one-persona-overlay-on-all-voices" limitation | -| CLI orphan reap on `chorus stop` + `start` | 0.7 | ✅ DONE | merged 2026-05-02 (PR #18 3eaf166) | -| `/rerun` server-side guard + retry button surfaces ok:false | 0.7 | ✅ DONE | merged 2026-05-02 (PR #19 a682e14) | -| Persona injection fence + missing-persona warning + stats SSE cleanup | 0.7 | ✅ DONE | merged 2026-05-02 (PR #20 0758791); emits `cli_warning{kind:'persona_missing'}` on lookup failure | -| Auto-fire chat runner on POST /chats (closes deferred #11) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #21 b372bec); MCP-driven flows no longer sit `drafting` until a human opens the URL — runChat fires immediately on POST, SSE becomes a passive subscriber on a per-chat event bus that replays from `phase_events`. | -| MCP `wait_for_chat` progress-notification keepalive | 0.7 | ✅ DONE | merged 2026-05-02 (PR #22 1940964); `notifications/progress` every 30s past Anthropic's 60s default tool timeout | -| Per-slot persona picker in PhaseEditor UI | 0.7 | ✅ DONE | merged 2026-05-02 (PR #23 4ac8cdc); completes the per-phase persona-binding UX from PR #17 | -| Per-card cancel button + per-runner AbortController | 0.7 | ✅ DONE | merged 2026-05-02 (PR #24 58603b6); cancel a single voice mid-run without killing the chat | -| Surface opencode + kimi token usage in message_done | 0.7 | ✅ DONE | merged 2026-05-02 (PR #25 15b219a); per-lineage parser updates aggregating `step_finish` events session-wide | -| `cli_warning` banner + USD cost on participant card | 0.7 | ✅ DONE | merged 2026-05-03 (PR #26 3ff046c); compounds with #25 token aggregation — opencode multi-step cost summed independently of token parsing so a malformed-tokens-but-valid-cost step still bills correctly | -| OpenRouter inline flow (validate → fetch models → multi-add) | 0.7 | ✅ DONE | merged 2026-05-03 (PR #27 9934852); validate / catalog / insert flow + cockpit page. Per-pricing per-Mtok USD math; voice id format `openrouter:`; `classifyOpencodeModel` reused for lineage classification. Self-review caught two follow-ups (defensive pagination + apiKey plumb-through) shipped in same PR. | -| HTTP shim for OpenRouter chat-completion dispatch | 0.7 | ✅ DONE | shipped 2026-05-03; new agent shim at `src/daemon/agents/openrouter.ts` POSTs `/api/v1/chat/completions` with `stream=true` + `stream_options.include_usage`, parses OpenAI-compatible SSE → AgentEvents (text_delta + message_done with native cost/tokens from OpenRouter), honours abort + 10-min timeout. Dispatch hook `pickShimForVoice(lineage, model)` routes any model with `openrouter:` prefix to the HTTP shim regardless of declared lineage; CLI precheck is skipped (auth = secrets table). Voices now insert with `enabled: true` since dispatch works. | -| Phase composition UI (drag/reorder, edit prompts) | 0.7 | 🟡 PARTIAL | per-slot persona binding shipped (PR #17 + #23). Drag-to-reorder, add/remove phases, fork-from-existing still PLANNED. | -| Default chorus-on-chorus template (Sentinel + Cartographer + Accountant + Translator) | 0.7 | 📐 PLANNED | bakes meta-fix | -| Squashed migration push to `chorus-codes/chorus` | 0.7 | ⏳ NEXT | piece-by-piece audit using personas. **Going live ~2026-05-04.** | -| `npm publish chorus-codes` | 0.7 | ⏳ NEXT | unscoped name (verified free). Rotate token after first publish. **Going live ~2026-05-04.** | -| Cleanup `99xAgency/chorus-ship-e2e` sandbox repo | 0.7 | ⏳ TODO | | -| Pre-audit cleanup sweep (12 findings fixed in one go) | 0.7 | ✅ DONE | 2026-05-01 — runner abort/done race, silent-empty doer, attached_files wire-up, builtin seed re-sync, version drift, brief wall, daemon logs, more. See "Pre-flagged" section. | -| **Per-slot fallback voice chain** (HIGH PRIORITY user-pain) | 0.8 | 🔥 NEXT | **Live pain:** when one voice in a multi-voice template errors (quota_exhausted, network, CLI crash), the partial work from other voices is wasted — they have to re-run from scratch alongside whatever voice replaces the failed one. Fix: each phase slot carries a `fallback: voice[]` chain. On retryable errors (`quota_exhausted`, `network`, `timeout`, `cli_failed`), the runner tries the next fallback voice for THAT slot only — other voices' completed work is preserved. Schema: `phases[].voices[].fallback: ['claude-code', 'openrouter:openai/gpt-4', ...]`. Reuses the same persona binding. Surfaces in PhaseEditor as a "+ add fallback" affordance under each voice slot. **Forces lineage-diversity rule into the chain** — fallback voices should default to same lineage as primary (so quorum math doesn't shift). Dovetails with multi-account-per-CLI: a fallback can be the same CLI on a different account when `CHORUS_CODEX_HOME` rotation is wired up. | -| `chorus audit ` CLI shorthand | 0.8 | 💭 IDEA | wraps `invoke_persona` MCP call; ~30 lines in `src/cli/index.ts`; saves typing the JSON in editors/conversations | -| Cockpit edit UI for builtin templates | 0.8 | ⏳ TODO | POST /templates upsert is now safe (preserves source=builtin); editor itself still missing — designed not built | -| Runner decoupling from SSE — background runChat + event bus replay | 0.8 | ⏳ TODO | surgical fix landed for v0.7 (no auto-abort + chat_done latch); proper fix is fire-on-POST so MCP flows don't sit drafting until a human opens the page | -| Home dashboard (CLI status, usage, reset windows, cost) | 0.8 | 📐 PLANNED | | -| Multi-account per CLI (add N codex / claude / gemini accounts of same vendor) | 0.8 | 📐 PLANNED | first-class UX for what `CHORUS_CODEX_HOME` env hack achieves today; auto-rotate to a non-rate-limited account when one hits quota_exhausted; surfaces in home dashboard alongside reset-window per-account | -| Run history + cost aggregates | 0.8 | 📐 PLANNED | | -| Local LLM voices (Ollama, llama.cpp) | 1.0+ | 💭 IDEA | | -| CI integration (`chorus review --pr 1234`) | 1.0+ | 💭 IDEA | | +| Item | Version | Status | Notes | +| ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Audit fixes 1-7 (dogfood pre-publish) | 0.6 | ✅ DONE | shipped 2026-05-01 | +| Cross-platform CLI detection (`where` + fallback dirs + `--version` verify) | 0.6 | ✅ DONE | | +| Manual CLI path entry UI | 0.6 | ✅ DONE | | +| Persona registry — table + 10 built-ins + seed loader | 0.7 | ✅ DONE | | +| MCP `list_personas` + `invoke_persona` | 0.7 | ✅ DONE | 9 MCP tools total | +| Voices abstraction (table + auto-populate + 6 UI surfaces) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #2 c758e80); 71 voices auto-seed across 5 lineages; vendor_family taxonomy | +| libsql migration (better-sqlite3 → @libsql/client, no node-gyp) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #1 1441532); fixes `npm install -g` on Windows / locked-down boxes | +| Review-only mode (artifact in, no doer; substrate + cockpit + verdict persistence) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #4 b21a4b8); unlocks `/work` & MCP harnesses calling chorus as a pure review service | +| Per-phase `timeoutMs` override (round-2-deferred §2) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #5 9a47f23); 30s..1h schema bound, threaded through doer + reviewer + tmux + review-only synthesis | +| Token-capture rails (round-2-deferred §1) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #8 3910607); `AgentEvent.message_done.usage` + capture in doer return shape — per-lineage parser updates + DB persistence + cost math are follow-ups | +| Opt-out telemetry heartbeat (round-2-deferred §4) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #6 bac7445); daemon-side ping to chorus.codes once on boot + every 24h; three opt-out paths; server endpoint deploy + privacy notice are separate infra tasks | +| Structured JSON-line logger substrate (round-2-deferred §3) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #7 7ce6b46); pino-shaped wire format (level/time/pid/hostname); 5 first-class call sites; mechanical migration of remaining ~50 console sites is a follow-up | +| Codex quota_exhausted detection + `CHORUS_CODEX_HOME` override | 0.7 | ✅ DONE | merged 2026-05-02 (PR #9 ee7b5fb); codex emits `ERROR: hit your usage limit` to stderr and exits 1, parseCodexExit now reads stderr+code and emits `error{kind:'quota_exhausted'}` instead of writing 0-byte answer.md. Round-1 review-only dogfood caught the regex was too loose (codex echoes user prompt to stderr → false-positive risk); fixed by anchoring on literal `ERROR:` prefix. Env override is a stopgap; proper UX is multi-account-per-CLI in v0.8. | +| SSE hijack + backpressure drain race + init log path | 0.7 | ✅ DONE | merged 2026-05-02 (PR #13 a5f6db1); fastify `reply.hijack()` before `reply.raw` writes, drain handler clears `paused` first then flushes, `chorus init` log honours `CHORUS_DB_PATH`. cdx-1 round-2 follow-ups from libsql migration. | +| Cockpit retry button + correct reviewer count | 0.7 | ✅ DONE | merged 2026-05-02 (PR #14 0ab62e4) | +| Templates `liveYaml` precedence test coverage | 0.7 | ✅ DONE | merged 2026-05-02 (PR #15 02e0820) — Fix C from PR #10 | +| Time + token chips on participant cards | 0.7 | ✅ DONE | merged 2026-05-02 (PR #16 b1e2f09); reads from `_stats.json` sidecar | +| Personas wire into doer + reviewer slots (per-slot binding) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #17 969dca5); each phase row carries its own persona — removes the §1 "one-persona-overlay-on-all-voices" limitation | +| CLI orphan reap on `chorus stop` + `start` | 0.7 | ✅ DONE | merged 2026-05-02 (PR #18 3eaf166) | +| `/rerun` server-side guard + retry button surfaces ok:false | 0.7 | ✅ DONE | merged 2026-05-02 (PR #19 a682e14) | +| Persona injection fence + missing-persona warning + stats SSE cleanup | 0.7 | ✅ DONE | merged 2026-05-02 (PR #20 0758791); emits `cli_warning{kind:'persona_missing'}` on lookup failure | +| Auto-fire chat runner on POST /chats (closes deferred #11) | 0.7 | ✅ DONE | merged 2026-05-02 (PR #21 b372bec); MCP-driven flows no longer sit `drafting` until a human opens the URL — runChat fires immediately on POST, SSE becomes a passive subscriber on a per-chat event bus that replays from `phase_events`. | +| MCP `wait_for_chat` progress-notification keepalive | 0.7 | ✅ DONE | merged 2026-05-02 (PR #22 1940964); `notifications/progress` every 30s past Anthropic's 60s default tool timeout | +| Per-slot persona picker in PhaseEditor UI | 0.7 | ✅ DONE | merged 2026-05-02 (PR #23 4ac8cdc); completes the per-phase persona-binding UX from PR #17 | +| Per-card cancel button + per-runner AbortController | 0.7 | ✅ DONE | merged 2026-05-02 (PR #24 58603b6); cancel a single voice mid-run without killing the chat | +| Surface opencode + kimi token usage in message_done | 0.7 | ✅ DONE | merged 2026-05-02 (PR #25 15b219a); per-lineage parser updates aggregating `step_finish` events session-wide | +| `cli_warning` banner + USD cost on participant card | 0.7 | ✅ DONE | merged 2026-05-03 (PR #26 3ff046c); compounds with #25 token aggregation — opencode multi-step cost summed independently of token parsing so a malformed-tokens-but-valid-cost step still bills correctly | +| OpenRouter inline flow (validate → fetch models → multi-add) | 0.7 | ✅ DONE | merged 2026-05-03 (PR #27 9934852); validate / catalog / insert flow + cockpit page. Per-pricing per-Mtok USD math; voice id format `openrouter:`; `classifyOpencodeModel` reused for lineage classification. Self-review caught two follow-ups (defensive pagination + apiKey plumb-through) shipped in same PR. | +| HTTP shim for OpenRouter chat-completion dispatch | 0.7 | ✅ DONE | shipped 2026-05-03; new agent shim at `src/daemon/agents/openrouter.ts` POSTs `/api/v1/chat/completions` with `stream=true` + `stream_options.include_usage`, parses OpenAI-compatible SSE → AgentEvents (text_delta + message_done with native cost/tokens from OpenRouter), honours abort + 10-min timeout. Dispatch hook `pickShimForVoice(lineage, model)` routes any model with `openrouter:` prefix to the HTTP shim regardless of declared lineage; CLI precheck is skipped (auth = secrets table). Voices now insert with `enabled: true` since dispatch works. | +| Phase composition UI (drag/reorder, edit prompts) | 0.7 | 🟡 PARTIAL | per-slot persona binding shipped (PR #17 + #23). Drag-to-reorder, add/remove phases, fork-from-existing still PLANNED. | +| Default chorus-on-chorus template (Sentinel + Cartographer + Accountant + Translator) | 0.7 | 📐 PLANNED | bakes meta-fix | +| Squashed migration push to `chorus-codes/chorus` | 0.7 | ❌ MOOT | fork stays its own project at `crypticpy/chorus`; not contributing back upstream | +| `npm publish chorus-codes` | 0.7 | ❌ MOOT | new package name TBD on the rebrand PR; `chorus-codes` was the upstream slot | +| Cleanup `99xAgency/chorus-ship-e2e` sandbox repo | 0.7 | ⏳ TODO | | +| Pre-audit cleanup sweep (12 findings fixed in one go) | 0.7 | ✅ DONE | 2026-05-01 — runner abort/done race, silent-empty doer, attached_files wire-up, builtin seed re-sync, version drift, brief wall, daemon logs, more. See "Pre-flagged" section. | +| Audit phase + 5 presets (`audit-code-review`, `audit-architecture-review`, `audit-engineering-review`, `audit-de-slopify`, `audit-monolith-breakdown`) | 0.8 | ✅ DONE | merged 2026-05-15 (PR #1); writer produces an approve-by-checkbox plan for a whole repo; cockpit checklist UI on the run page | +| Orchestrate phase + per-worker branches | 0.8 | ✅ DONE | merged 2026-05-15 (PR #1); approved audit items fan out to per-worker git branches with per-worker slot + model + persona; `orchestrate-manifest.json` with diff stats; Checkout / Open-PR routes | +| Verify phase + TDD loop (`package.json#chorus.verify`, `feedbackPhase`, `maxIterations`) | 0.8 | ✅ DONE | merged 2026-05-16 (PR #6); failed verify re-prompts the named doer with captured output — tight TDD loop | +| PR-babysit (autonomous bot-review loop) | 0.8 | ✅ DONE | merged 2026-05-16 (PR #6); `chorus babysit register/list/show/pause/resume` CLI + daemon scheduler; judges CodeRabbit / Sourcery / Greptile / Codex comments; pushes fixes or replies; settles in `quiet_check` after two consecutive quiet ticks and waits for an external squash-merge (the `/babysit-pr` Claude Code skill wraps this loop and adds the merge gate) | +| **Per-slot fallback voice chain** (HIGH PRIORITY user-pain) | 0.8 | 🔥 NEXT | **Live pain:** when one voice in a multi-voice template errors (quota_exhausted, network, CLI crash), the partial work from other voices is wasted — they have to re-run from scratch alongside whatever voice replaces the failed one. Fix: each phase slot carries a `fallback: voice[]` chain. On retryable errors (`quota_exhausted`, `network`, `timeout`, `cli_failed`), the runner tries the next fallback voice for THAT slot only — other voices' completed work is preserved. Schema: `phases[].voices[].fallback: ['claude-code', 'openrouter:openai/gpt-4', ...]`. Reuses the same persona binding. Surfaces in PhaseEditor as a "+ add fallback" affordance under each voice slot. **Forces lineage-diversity rule into the chain** — fallback voices should default to same lineage as primary (so quorum math doesn't shift). Dovetails with multi-account-per-CLI: a fallback can be the same CLI on a different account when `CHORUS_CODEX_HOME` rotation is wired up. | +| `chorus audit ` CLI shorthand | 0.8 | 💭 IDEA | wraps `invoke_persona` MCP call; ~30 lines in `src/cli/index.ts`; saves typing the JSON in editors/conversations | +| Cockpit edit UI for builtin templates | 0.8 | ⏳ TODO | POST /templates upsert is now safe (preserves source=builtin); editor itself still missing — designed not built | +| Runner decoupling from SSE — background runChat + event bus replay | 0.7 | ✅ DONE | merged 2026-05-02 (PR #21 b372bec); runChat now fires on POST and SSE is a passive subscriber with event replay (resolves the v0.7 surgical fix's follow-up properly) | +| Home dashboard (CLI status, usage, reset windows, cost) | 0.8 | 📐 PLANNED | | +| Multi-account per CLI (add N codex / claude / gemini accounts of same vendor) | 0.8 | 📐 PLANNED | first-class UX for what `CHORUS_CODEX_HOME` env hack achieves today; auto-rotate to a non-rate-limited account when one hits quota_exhausted; surfaces in home dashboard alongside reset-window per-account | +| Run history + cost aggregates | 0.8 | 📐 PLANNED | | +| Local LLM voices (Ollama, llama.cpp) | 1.0+ | 💭 IDEA | | +| CI integration (`chorus review --pr 1234`) | 1.0+ | 💭 IDEA | | Legend: ✅ done · ⏳ in flight · 🔥 high-priority next · 🟡 partial · 📐 designed · 💭 idea -> **Where we are (2026-05-03):** v0.7 substrate is essentially complete — voices, personas, review-only, token capture, cost surfacing, per-slot persona binding, runner-on-POST, SSE robustness all shipped. Last v0.7 mile: OpenRouter inline (in flight), then squash + publish as `chorus-codes` on npm (unscoped, `chorus.codes` domain match). **Going live ~2026-05-04.** +> **Where we are (2026-05-17):** v0.8 multi-stage review is live — audit + 5 presets, orchestrate phase with per-worker branches, verify phase + TDD feedback loop, and the PR-babysit autonomous bot-review loop all shipped. Fork is now its own project at `crypticpy/chorus`; the `chorus-codes/chorus` migration items are moot. Up next: per-slot fallback voice chain (the highest user-pain item), then home dashboard + multi-account per CLI. --- ## v0.6 — Public launch (DONE 2026-05-01) Shipped: + - Audit-fix sweep — 7 real bugs caught dogfooding pre-publish (build asset copy, fresh-DB migration, MCP id↔chatId, CLI auto-detect, chorus start in dist, web spawn, postinstall hint) - Cross-platform CLI detection — `where` on Windows + `which` on Unix, 8 fallback install dirs per OS, `--version` smoke test - Manual path entry — when auto-detect misses, user pastes the path to the binary and chorus validates @@ -97,20 +102,20 @@ users can compose freely. **Built-in library** (full prompts in [`prompts/personas/`](prompts/personas/)): -| Persona | One-liner | Recommended lineage | -|---|---|---| -| **Sentinel** | Hunts secrets, injection, broken auth, supply-chain risk | anthropic | -| **Conservator** | Spots when a change fights the existing pattern instead of joining it | openai | -| **Cartographer** | Catches Windows/macOS/Linux assumptions, path separators, line endings, encoding | google | -| **Profiler** | N+1 queries, big-O cliffs, cold-path costs, latency budgets | openai | -| **Translator** | Reviews labels, errors, empty states, help text — for layman users, not engineers | anthropic | -| **Accountant** | Asks "who pays for this, when, and is there bill shock?" | anthropic | -| **Concierge** | Time-to-first-success — install path, error legibility, docs alignment | anthropic | -| **Quartermaster** | Scrutinizes every new dep — maintenance, license, transitive footprint, install scripts | openai | -| **Inspector** | Identifies what's not tested but should be — and what's tested but worthless | openai | -| **Librarian** | Reads README, marketing copy, help text alongside the diff and flags every lie | anthropic | - -Each prompt is a *worldview*, not a checklist — single role, list of red flags to actively hunt, and an out-of-scope guard so personas don't bleed into each other's lanes. +| Persona | One-liner | Recommended lineage | +| ----------------- | --------------------------------------------------------------------------------------- | ------------------- | +| **Sentinel** | Hunts secrets, injection, broken auth, supply-chain risk | anthropic | +| **Conservator** | Spots when a change fights the existing pattern instead of joining it | openai | +| **Cartographer** | Catches Windows/macOS/Linux assumptions, path separators, line endings, encoding | google | +| **Profiler** | N+1 queries, big-O cliffs, cold-path costs, latency budgets | openai | +| **Translator** | Reviews labels, errors, empty states, help text — for layman users, not engineers | anthropic | +| **Accountant** | Asks "who pays for this, when, and is there bill shock?" | anthropic | +| **Concierge** | Time-to-first-success — install path, error legibility, docs alignment | anthropic | +| **Quartermaster** | Scrutinizes every new dep — maintenance, license, transitive footprint, install scripts | openai | +| **Inspector** | Identifies what's not tested but should be — and what's tested but worthless | openai | +| **Librarian** | Reads README, marketing copy, help text alongside the diff and flags every lie | anthropic | + +Each prompt is a _worldview_, not a checklist — single role, list of red flags to actively hunt, and an out-of-scope guard so personas don't bleed into each other's lanes. **MCP surface** (live now): @@ -128,6 +133,7 @@ Shipped: `voices` table with `(id, label, source, provider, model_id, lineage, v A new phase kind, `review_only`, that takes the artifact as runtime input and skips doer spawn entirely. The unlock for `/work` and other harnesses to call chorus as a pure review service: `MCP create_chat({template: "review-only", artifact: })`. Shipped: + - **Schema** — `PhaseSchema` is now a discriminated union by `kind`. `review_only` variant requires `reviewer` + `artifact { label, hint, maxBytes (default 1 MiB) }` instead of a doer block. `.refine` rejects hybrid templates (review_only mixed with standard) at parse time. - **Runner** — `runReviewOnlyPhase` writes the artifact synthetically as the doer answer, emits synthetic `phase_start`/`phase_progress` events with `agent: 'artifact'`, then runs reviewers via the existing pool with `iterate.maxRounds = 1`. Single pass — no retry. Ship phase force-skipped (no doer diff to commit). - **DB** — `chats.artifact TEXT` (nullable; capped by template) + `chats.verdict TEXT` (nullable; persisted from `chat_done` so list views can distinguish `verdict='request_changes'` from `verdict='approved'`). Both via idempotent `ADD COLUMN`. @@ -141,6 +147,7 @@ Shipped: Built using its own substrate as the dogfood gate — each commit was reviewed by the new template before the next built on it. Round-2 triage caught 4 real bugs (abort race, ship-skip enforcement, UTF-8 boundary, hybrid validation) all fixed in-branch. 18 new tests; 216/216 passing. Out of scope (deferred): + - Multi-pass review-only with cockpit-driven revision loop. Today: revise yourself, resubmit a fresh chat. - `chorus run` / `chorus review` CLI subcommands. Substrate ready; CLI wiring tracked separately in [`planning/cli-task-surface.md`](planning/cli-task-surface.md). @@ -215,17 +222,11 @@ The four warmup items from [`planning/round-2-deferred.md`](planning/round-2-def ### 6. Default chorus-on-chorus template (PLANNED) -Hard-codes Sentinel + Cartographer + Accountant + Translator as the four reviewer slots in chorus's own audit template. The next person reviewing chorus *can't* skip those four lenses — bakes the meta-lessons into the product. +Hard-codes Sentinel + Cartographer + Accountant + Translator as the four reviewer slots in chorus's own audit template. The next person reviewing chorus _can't_ skip those four lenses — bakes the meta-lessons into the product. -### 7. Migration to chorus-codes (NEXT) +### 7. Migration to chorus-codes (MOOT — fork is its own project) -After v0.7 ships: - -1. Piece-by-piece audit via MCP — fire personas against critical files (`src/cli/index.ts`, `src/daemon/runner.ts`, etc.) using real chorus chats. The audit is the dogfood demo. -2. Findings → cleanup branch → squashed push to `chorus-codes/chorus` (single clean snapshot, no 99xAgency history). -3. Update `package.json` `name` → `chorus-codes` (unscoped, verified free on npm 2026-05-03; `@chorus-codes` org also reserved for future sister packages), repository + bugs URLs. -4. `npm publish` (unscoped, no `--access public` needed). Rotate token after first publish. -5. Cleanup `99xAgency/chorus-ship-e2e` sandbox repo. +The fork at `crypticpy/chorus` has diverged substantially and is now the canonical home, not a downstream of `chorus-codes/chorus`. Remote setup: `origin → crypticpy/chorus` (push + fetch), `chorus-codes → chorus-codes/chorus` (fetch only; push URL disabled). PRs target the fork's `main`. Future upstream catch-up (if any) is a one-way cherry-pick via `git fetch chorus-codes main`, not a sync. The rebrand to a new project name + npm package is tracked separately. --- @@ -238,9 +239,9 @@ Drift bugs / risks spotted in passing — most fixed 2026-05-01 in a single swee The first cartographer audit attempt revealed 5 more findings — most caught while the doer was still running, then the system load spiked because the actual root cause (#17) was hammering the LLM CLIs. All 5 fixed before re-running the audit. - ✅ **#13 Persona-composed brief dominated every chat title** — `mcp__chorus__invoke_persona` writes `# Persona: