1
0
forked from jason/echo

Phase 5: group-voice docs, onboarding runbook, CHORUS icon — v2.0.0-rc.1

The final phase of CHORUS-PLAN.md. Code- and doc-complete for group use;
rc pends live deployment at chorusapi.mpm.to.

- Repo README rewritten for CHORUS: group model (schema 5), concurrency
  posture, configuration, baked-build onboarding, layout, testing, 2.0
  version history (ECHO history referenced at the fork tag).
- Operator→member voice sweep across SKILL.md (incl. the trigger
  description, now group-aware), all references, 8 command docs, plugin
  README; member preferences / semantic layer / triage guidance describe
  the group model.
- docs/ONBOARDING.md: member runbook — vault stand-up, per-member config,
  bake, deliver, self-onboarding first load, norms, offboarding.
- docs/USAGE.md rewritten as the member usage guide.
- New icon: chorus-icon.svg + 1024/512/64 PNGs (three voices, one center).
- Removed ECHO-era assets (icons, spec PDF, perf briefs); ECHO planning
  docs retired to docs/history/. All preserved at echo-fork-point.
- eval/README documents test_multimember.py. Manifest -> 2.0.0-rc.1;
  rebuilt chorus-memory.plugin.

Verified: routing-sync, 25/25 unit, scaffold, 5 mock e2e suites,
run_eval metrics green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 15:41:58 -05:00
parent 1a7690426f
commit f2bfd70dd4
36 changed files with 324 additions and 807 deletions
@@ -16,5 +16,5 @@ bootstrapped (+ `schema_version`), and the **config source** for owner/endpoint/
(per-field: env override `CHORUS_OWNER`/`CHORUS_BASE`/`CHORUS_KEY`, then the machine-local
`~/.claude/chorus-memory/config.json` — or `baked-in (plugin)` on a per-user baked build,
which is authoritative and reported as such). Exits non-zero if anything is red — if the config is
missing (or still the placeholder template), ask the operator for their chorus-memory config file and install it with `chorus.py config import <path>` (or `config set --owner … --endpoint … --key …`). For the full vault-invariant lint, run
missing (or still the placeholder template), ask the member for their chorus-memory config file and install it with `chorus.py config import <path>` (or `config set --owner … --endpoint … --key …`). For the full vault-invariant lint, run
`/chorus-health`.
@@ -14,4 +14,4 @@ CHORUS_TODAY=<currentDate> python3 "$SDIR/vault_lint.py"
Exit codes: `0` clean · `1` violations (printed, grouped by check) · `2` vault unreachable · `3` vault not bootstrapped (run `bootstrap.py`).
Summarize the violations grouped by category and propose fixes, but **do not auto-fix** without the operator's go-ahead. If this is the first substantive session of a calendar month, offer to write the findings to `_agent/health/YYYY-MM-vault-health.md` (per the skill's **Vault Health** section).
Summarize the violations grouped by category and propose fixes, but **do not auto-fix** without the member's go-ahead. If this is the first substantive session of a calendar month, offer to write the findings to `_agent/health/YYYY-MM-vault-health.md` (per the skill's **Vault Health** section).
@@ -14,6 +14,6 @@ python3 "$CHORUS" load
`load` prints all eight sections (and self-onboards your member namespace on a first visit) (404s on today's note / inbox are shown as absent, not errors) and flags an un-bootstrapped vault. Follow up with `chorus.py scope show` if you need the sessions-since-switch count, and a project search if a specific project is in play.
**If `load` prints `NOT CONFIGURED` (exit 78)**, this machine has no usable key file yet. Don't proceed with memory — follow **First run** in `SKILL.md`: tell the operator CHORUS isn't configured, ask for their chorus-memory config file (group/member/endpoint/key), install it with `chorus.py config import <path>` (or `config set`), then re-run `load`.
**If `load` prints `NOT CONFIGURED` (exit 78)**, this machine has no usable key file yet. Don't proceed with memory — follow **First run** in `SKILL.md`: tell the member CHORUS isn't configured, ask for their chorus-memory config file (group/member/endpoint/key), install it with `chorus.py config import <path>` (or `config set`), then re-run `load`.
Do not narrate the reads. End with a one-line orientation: who/what/where the active scope is, and any reconcile prompt.
@@ -7,7 +7,7 @@ Use the **chorus-memory** skill to run **session reflection** (H5). Scan this co
things worth remembering across sessions, then propose them — don't write blindly.
1. **Extract** durable items from the conversation: new facts, preferences, decisions,
commitments, people/companies/projects introduced, and anything the operator said to remember.
commitments, people/companies/projects introduced, and anything the member said to remember.
Skip the ephemeral. Anchor relative dates on the conversation's `currentDate`.
2. **Emit a JSON array** of proposals (one per item), each:
`{"title","kind","body","aliases","tags","sources","confidence"}``kind`
@@ -15,7 +15,7 @@ things worth remembering across sessions, then propose them — don't write blin
working, skill, decision`; set `"inbox": true` when the home is genuinely unknown;
`confidence` 01 (items below 0.6 are dropped — send those to the inbox instead).
Write the array to a file with the Write tool (cross-platform; no heredoc).
3. **Preview, then apply.** Dry-run first (writes nothing) and show the operator the plan; only
3. **Preview, then apply.** Dry-run first (writes nothing) and show the member the plan; only
apply after they confirm.
```bash
@@ -16,7 +16,7 @@ python3 "$CHORUS" capture "<title>" <bodyfile> --kind <kind> [--aliases a,b] [--
python3 "$CHORUS" capture "<title>" --inbox # unknown home -> idempotent inbox line
```
**If capture exits `76` (duplicate gate):** the title strongly resembles an existing entity — do NOT retry blindly. Show the operator the printed candidates and either update the existing note (`capture ... --merge-into <slug>`) or, only after they confirm it's genuinely distinct, re-run with `--force`.
**If capture exits `76` (duplicate gate):** the title strongly resembles an existing entity — do NOT retry blindly. Show the member the printed candidates and either update the existing note (`capture ... --merge-into <slug>`) or, only after they confirm it's genuinely distinct, re-run with `--force`.
Drop to the low-level verbs only for shapes `capture` doesn't model (a project `## Status` replace, an ADR mirror, a daily-note edit):
@@ -3,7 +3,7 @@ description: Bring the CHORUS vault up to the current feature spec (entity index
allowed-tools: Bash(python3 *sweep.py*), Bash(python *sweep.py*), Bash(ls /sessions/*), Bash(dirname *)
---
Use the **chorus-memory** skill to bring the vault up to the current spec. Run the sweep **dry-run first**, show the operator the plan, and only `--apply` on their go-ahead:
Use the **chorus-memory** skill to bring the vault up to the current spec. Run the sweep **dry-run first**, show the member the plan, and only `--apply` on their go-ahead:
```bash
SDIR="${CLAUDE_PLUGIN_ROOT}/skills/chorus-memory/scripts"
@@ -11,13 +11,13 @@ python3 "$CHORUS" triage --list --json
# Windows: use `python` or `py -3` if `python3` is not on PATH.
```
1. **List** — the JSON gives each capture as `{line, date, text, age_days}`. Surface the aging ones (≥ ~7 days) to the operator and ask which to route.
2. **Propose** — for accepted items, write a proposals JSON with the Write tool (reflect schema: `{"title","kind","body",...}` **plus `"line"`: the original inbox line**, echoed into the audit log). Route per the map: preference/pattern → `semantic` (or a direct PATCH to `operator-preferences.md::Observations`); project idea → `project` with `--status incubating`; durable fact → `semantic`; person fact → `person`.
3. **Preview, then apply** with the operator's go-ahead:
1. **List** — the JSON gives each capture as `{line, date, text, age_days}`. Surface the aging ones (≥ ~7 days) to the member and ask which to route.
2. **Propose** — for accepted items, write a proposals JSON with the Write tool (reflect schema: `{"title","kind","body",...}` **plus `"line"`: the original inbox line**, echoed into the audit log). Route per the map: preference/pattern → `semantic` (a preference about the capturing member goes to their own `_agent/members/<member>/preferences.md::Observations` via direct PATCH); project idea → `project` with `--status incubating`; durable fact → `semantic`; person fact → `person`.
3. **Preview, then apply** with the member's go-ahead:
```bash
python3 "$CHORUS" triage proposals.json # dry-run: classify + preview, writes nothing
python3 "$CHORUS" triage proposals.json --apply # route via capture + log each move
```
`--apply` records every move in `inbox/processing-log/YYYY-MM-DD.md` (`- <original> → <destination>`) automatically. Do **not** delete the original captures unless the operator explicitly asks — the processing log is the audit trail. A proposal that stops at the duplicate gate (exit note in the summary) should be re-proposed with the existing entity's title.
`--apply` records every move in `inbox/processing-log/YYYY-MM-DD.md` (`- <original> → <destination>`) automatically. Do **not** delete the original captures unless the member explicitly asks — the processing log is the audit trail. A proposal that stops at the duplicate gate (exit note in the summary) should be re-proposed with the existing entity's title.