v0.16.0 — UAT gap close: cursor IDE adapter + on-demand history + doctor honesty#22
Merged
Conversation
Two related fixes to make `chorus doctor` a self-consistent diagnostic:
1. Introduce `info` severity for un-setup repos.
integration_*, snippet_*, setup_intents previously emitted `warn` even
when the repo had intentionally not been initialized via `chorus setup`
(e.g. hand-authored CLAUDE.md). They now emit `info` in that state.
Initialization is detected by INTENTS.md or providers/ presence; the
bare .agent-chorus/ directory does not count because the messaging
subsystem creates .agent-chorus/messages/ on first `send`.
2. Reconcile context_pack_hooks_path vs context_pack_pre_push.
The path check used to warn whenever core.hooksPath != ".githooks",
while the pre-push check happily reported the hook installed at the
warned-against path. The two now have one role each:
- context_pack_hooks_path is informational (info severity); reports
the effective hooks path (configured value or default `.git/hooks`).
- context_pack_pre_push is the truth check; warn iff no pre-push hook
is discoverable at the effective path.
Node + Rust mirror each other. Golden fixture updated for the empty
tempdir conformance scenario. UAT findings P2/P4 from
research/uat-cli-features-2026-06-03.md closed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Restructure printHelp() so `chorus <sub> --help` outputs the subcommand's usage, options, and examples first — not the global command blob. The global blob is still emitted for top-level `chorus --help` and `chorus help`, but per-topic help now answers the question the user actually asked. Specific improvements (all from UAT P2/P4): - `chorus report --help` now includes the handoff JSON schema with field-by-field annotations AND a minimal copy-pasteable example. The example loads without INVALID_HANDOFF. - `chorus messages --help` has `--clear` documented above the fold (was buried below the global Commands list). - `chorus doctor --help` documents the four severity levels and the overall-elevation rule introduced in the N3 doctor fix. - Every subcommand's first line is now `Usage: <bin> <sub> ...`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a second cursor surface alongside the v0.15.0 cursor-agent CLI
JSONL adapter. Sessions stored as SQLite databases under
~/.cursor/chats/<dir-hash>/<session-uuid>/store.db
are now first-class citizens of every cursor command (list, read,
search, timeline) at full Node/Rust parity.
Format spec is documented in cli/src/cursor_app.rs:
- meta(key,value) hex-encoded JSON {agentId, latestRootBlobId, ...}
- blobs(id,data) SHA-256 content-addressed
- root blob protobuf-style stream of child SHAs
- message blobs {"role","content"} matching Claude's shape so the
existing claude/cursor-cli tool-call extractor
renders them at parity
- workspace path recovered from "Workspace Path:" header in the
first user-role message, mirroring cursor-cli's
.workspace-trusted/demangle resolution
Changes:
cli:
+ cli/src/cursor_app.rs new module: SQLite reader, root-blob
protobuf parser, workspace recovery
M cli/Cargo.toml add rusqlite 0.31 (bundled feature; no
host SQLite dep)
M cli/src/agents.rs cursor list/read/search merge both
surfaces; expose ConversationTurn +
file_modified_iso + cursor_base_dir_public
+ list_cursor_cli_sessions_count helpers
M cli/src/doctor.rs split sessions_cursor into
sessions_cursor_cli + sessions_cursor_app;
surface checks are presence-only (no cwd
filter) to answer "is the surface
reachable" not "do we have sessions here"
M cli/src/timeline.rs snippet read uses session_id from the
listing (not file_stem) — store.db's stem
is "store", not the session uuid
node:
+ scripts/adapters/cursor_app.cjs SQLite reader using built-in
node:sqlite (Node >= 22.5);
graceful fallback on older Node
leaves the surface invisible
M scripts/adapters/cursor.cjs resolve/read/list/search merge
both surfaces; read() detects
store.db by path suffix and
dispatches to the SQLite reader
M scripts/read_session.cjs doctor mirrors Rust per-surface
split; uses cursor adapter list
directly (no cwd filter for
surface health)
schema + fixtures:
M schemas/list-output.schema.json optional `source` field (cursor
only): "cli" | "app"
M fixtures/golden/doctor.json sessions_cursor_cli +
sessions_cursor_app entries
+ fixtures/golden/read-cursor-app.json parity baseline for the
SQLite read path
M fixtures/golden/timeline.json includes cursor-app fixture row
+ fixtures/session-store/cursor/chats/.../store.db synthetic
SQLite fixture covering user/assistant turns, multi-segment
content, tool_use, and the Workspace Path header
M scripts/conformance.sh adds CHORUS_CURSOR_APP_DATA_DIR
env to the parity matrix and a
new read-cursor-app case
164 cargo tests + conformance green (including the new read-cursor-app
golden + cross-surface timeline assertion). UAT P1 from
research/uat-cli-features-2026-06-03.md closed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The codex search path used `extract_assistant_text_jsonl` (Rust) and an
inline reader in `search()` (Node) that both walked a top-level
`{role:"assistant", content:"..."}` schema. No real codex session has
ever used that shape — codex stores assistant messages in nested
envelopes:
{type:"response_item", payload:{type:"message", role:"assistant",
content:[{text:"..."}, ...]}}
{type:"event_msg", payload:{type:"agent_message", message:"..."}}
Effect: `chorus search --agent codex <query>` returned an empty array
for every query against every real codex session. Read worked because
parse_codex_jsonl handles the real format correctly; search was a dead
extractor.
This is the UAT P3 finding from research/uat-cli-features-2026-06-03.md:
"search 'agent-context' returns empty while session contains it".
Fix mirrors parse_codex_jsonl in both runtimes — handles both envelopes,
delegates to the shared extract_text() helper for content arrays, and
falls back to the string form of event_msg messages when present.
Conformance gains a regression test asserting the invariant
read(text) ⊆ search(text-tokens) for both runtimes against the codex
fixture. The invariant generalizes to every adapter; codex is the only
agent that was failing it pre-fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ILABLE for gemini/hermes
Two pieces of the --tool-calls parity matrix:
1. Cursor IDE (app) sessions render tool_use / tool_result content
identical to claude/codex/cursor-cli. The shared claude content
extractor already handles cursor's content shape (verified in N1);
this commit just adds the conformance case + golden so the path is
regression-protected.
2. Gemini and hermes sessions don't carry tool calls in their on-disk
format. Previously --tool-calls was silently a no-op for these
agents — the output looked indistinguishable from "this session had
no tool calls". Now both runtimes emit a uniform warning when
--tool-calls is requested for an agent that doesn't support it:
"--tool-calls has no effect for <agent> sessions: this agent's
transcript format does not carry tool calls."
`included_tool_calls: true` is still set (the flag was acknowledged);
the warning is the only behavioral change. This eliminates the
silent failure mode where a downstream tool would see
`included_tool_calls: true` and assume tool calls were considered.
Cross-cuts:
- cli/src/main.rs agent_has_no_tool_calls helper + dispatcher push
- scripts/read_session.cjs AGENTS_WITHOUT_TOOL_CALLS set + dispatcher push
- gemini.cjs / hermes.cjs acknowledge --tool-calls in output shape
- conformance parity case for cursor-app + gemini --tool-calls
UAT P3 from research/uat-cli-features-2026-06-03.md closed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the `--history=on-demand|none|eager` flag to `chorus read` that
makes the existing on-demand default behavior explicit and contracted:
on-demand (default): return only the latest session for the cwd.
chorus does NOT auto-pull prior sessions; callers
use `chorus list / timeline / search` explicitly
when they want historical context.
none: metadata only (alias for --metadata-only). For
consumers that want to know a session exists
without paying the content tokens.
eager: reserved for a future multi-session merge.
Today behaves identically to on-demand and emits
a uniform warning so consumers don't silently
rely on a behavior chorus doesn't yet implement.
This is N7 from research/next-scopes-post-v0.15.0-2026-06-03.md. The
field-study finding (`research/context-pack-field-findings-2026-03-20.md`
Finding 3) measured a 2.5x token inflation from agents (Claude)
eagerly reading multiple prior chorus sessions at startup. The chorus
binary itself was already on-demand; this flag makes the contract
explicit so consumers can rely on it, and reserves the future surface
for the multi-session merge.
Mirrored across Rust + Node with conformance for both eager (warning
emitted) and none (content nulled) modes. Invalid values fail closed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three related doctor improvements caught by the independent UAT replay:
F12. Optional adapters report `info` when their data directory is
absent. cursor_cli, cursor_app, and hermes were all `warn` on
repos where the user simply hadn't installed the tool — same
noisy-warn pattern N3 fixed for integration_*. Now `warn` is
reserved for "directory exists but no sessions" (installed but
quiet); bare absence is `info`.
F3. hooks_path + pre_push checks are git-aware. Previously on a
non-git cwd, `git config core.hooksPath` resolved to the user's
global value and doctor reported a pre-push hook as installed
even though the cwd had no `.git/`. Both checks now report
`info: cwd is not a git repository` in that case.
F2. New `env_override_dangling` check. When a CHORUS_*_DIR or
BRIDGE_*_DIR env var points at a non-existent directory, doctor
emits a `warn` naming the env var, the bound adapter, and the
dangling path. Previously this misconfiguration produced silent
partial coverage — sessions just vanished with no signal. The
N1 reviewer caught this case on the test workstation where the
legacy bridge env was still set.
Mirrored Rust + Node. hermes_base_dir_public + is_git_repo helpers
added. Doctor golden updated for the empty-tempdir scenario:
sessions_hermes is now `info: Hermes not configured ...`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tderr When --cwd is passed but no session matches, adapters fall back to the latest session and push a "falling back to latest session" warning to the warnings array. JSON-only consumers that don't scan that array silently get an unrelated session — the failure mode the N1 reviewer caught for cursor and which is symmetrically present in codex/claude/ hermes. Two improvements: 1. New optional `cwd_mismatch: true` field on read output (Rust + Node). Detection: Rust threads a `cwd_mismatch` bool from each adapter that has the fallback path (codex, claude, cursor, hermes). Node detects by phrase-matching the warning string from any adapter. Gemini doesn't scope by absolute cwd so the field never fires for it. 2. The fallback warning is also echoed to stderr (`chorus: ...`) so humans watching the terminal see it even when stdout is piped into another tool. Schema: `cwd_mismatch` added as optional boolean in schemas/read-output.schema.json. Absent when no fallback occurred, so existing goldens are unaffected. Session struct gains a `cwd_mismatch: bool` field; updated at the 6 Session struct constructions in cli/src/agents.rs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The N2 fix added a regression test for codex specifically. The same class of bug — search extractor walking a schema read doesn't — could silently regress any adapter. Per the F4 follow-up identified in research/uat-replay-followups-2026-06-03.md, the invariant read(text) ⊆ search(text-tokens) is now asserted for claude, gemini, cursor (CLI), and cursor (IDE app) in addition to codex. Each agent's fixture has a distinctive assistant message string. The test runs both Node and Rust searches against the full conformance fixture store and asserts the expected session_id appears in results. Pre-fix any agent's search extractor could be broken in isolation and ship; post-fix every adapter is gated by CI on this contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three coverage gaps from the UAT replay (see
research/uat-replay-followups-2026-06-03.md):
F6. Claude + Codex --tool-calls fixtures with real tool_use entries.
The existing `claude-fixture` / `codex-fixture` JSONLs contain no
tool_use / function_call entries, so `read-claude-tool-calls` and
`read-codex-tool-calls` only verified the flag was honored, not
that the renderer emits `[TOOL: <name>]` blocks. New dedicated
fixtures `session-claude-tool-fixture.jsonl` and
`session-codex-tool-fixture.jsonl` exercise the renderer
end-to-end; new goldens assert the `[TOOL: ...]` block content.
F7. Live hermes fixture. Hermes was scaffolded in the
AGENTS_WITHOUT_TOOL_CALLS set alongside gemini, but had no on-disk
test exercising the uniform no-tool-calls warning path. New
fixture `session-hermes-fixture.jsonl` + two conformance cases
(`read-hermes`, `read-hermes-tool-calls`) gate the contract in CI.
Doctor now sees the hermes fixture during conformance and reports
sessions_hermes: pass (golden updated). The Node hermes env-var
expectation was corrected to CHORUS_HERMES_DATA_DIR (matched both
Rust and the adapter); env_override_dangling list extended.
F8. SQLite-redaction fixture. The redaction pipeline applies to both
cursor surfaces logically (same `redactSensitiveText` wrap), but
no fixture exercised it on SQLite-sourced content specifically. A
second cursor IDE store.db fixture (`cursor-app-redaction-uuid`)
embeds an API-token-shaped string and a Bearer-token-shaped
string inside the message blobs. New conformance case
`read-cursor-app-redaction` asserts both runtimes emit
`[REDACTED]` for the offending substrings.
Side-effects:
- timeline + list-codex goldens regenerated to incorporate the new
fixtures (they show up in unscoped listings).
- doctor golden updated for the hermes-fixture-present case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The provider snippet template (`.agent-chorus/providers/<agent>.md`)
and the managed block template (the CLAUDE.md / AGENTS.md / GEMINI.md
block) now document the on-demand history contract introduced in N7,
so consumer agents reading the snippet on first session encounter the
rule explicitly rather than only via `chorus read --help`.
Two changes both mirrored across Rust (cli/src/setup.rs) and Node
(scripts/read_session.cjs):
1. Managed block template extended with the missing support-command
list (diff, audit-redactions, relevance, send, messages) so a
regenerated block doesn't lose richer hand-authored content.
2. Both templates gain a "History contract" section explaining:
- `chorus read` defaults to --history=on-demand (latest only)
- DO NOT eagerly loop prior sessions; the field study measured a
2.5x token inflation when agents did this.
- Use `chorus list / timeline / search` for explicit historical
recall.
- `--history=eager` is reserved; do not depend on it.
This closes the F5 follow-up. The provider snippet files themselves
live under .agent-chorus/providers/ (gitignored, materialized by
`chorus setup`); the dead reference in CLAUDE.md is no longer a
contract gap because every consumer who runs `chorus setup` ends up
with the contract documented locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four hygiene items the independent UAT reviewers flagged:
F9. Rust report --help / doctor --help schema parity. Clap's auto-help
from the doc comment was collapsing the handoff JSON schema into a
single line. Now both subcommands use long_about with explicit
formatting so the Rust binary's --help matches Node's for these
two information-dense surfaces.
F10. Suppress node:sqlite ExperimentalWarning. Every chorus invocation
that touched the cursor adapter emitted
(node:NNNNN) ExperimentalWarning: SQLite is an experimental
feature and might change at any time
to stderr, corrupting any naive stdout/stderr capture. Replace
the default warning listener once at module load with one that
drops only the SQLite Experimental warning and forwards every
other category through. Verified: `node ... 2>/tmp/log` is now
empty for the cursor doctor path.
F11. Node parser rejects unknown flags. Hand-rolled getOptionValue +
hasFlag previously silently ignored typos like `--Json` or
`--limt 3` — the Rust CLI (clap) already fails closed. A new
ALLOWED_FLAGS map per subcommand drives validateFlags() at
dispatch; unknown `--foo` produces "Unknown flag for '<cmd>':
--foo. Run `chorus <cmd> --help` to see allowed flags."
F13. cli/src/cursor_app.rs dead-code warnings cleared. CursorAppSession
fields (`name`, `mode`, `created_at_ms`) and `find_session_db` are
reserved for a future verbose-listing surface; tagged
#[allow(dead_code)] with comments explaining the intent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five real defects + one minor gap surfaced by the fresh-context UAT round-2 reviewers: 1. Rust cwd_matches_project too permissive (cli/src/agents.rs:1369). The hierarchical matcher used `Path::starts_with`, which is component-aware and treats root `/` as a prefix of every absolute path — meaning a session whose recorded cwd was `/` would silently match every --cwd <X> request and short-circuit the cwd_mismatch fallback. Rust+codex never reported cwd_mismatch when such a session existed in history. Align with Node's algorithm: string-based with explicit trailing `/` separator. Now any-path sessions don't act as wildcards. 2. Rust relative_path symlink bug (cli/src/setup.rs:604). When `chorus setup --cwd /tmp/...` ran on macOS, the managed block wrote `Provider snippet: ../../../tmp/.../providers/<agent>.md` instead of `.agent-chorus/providers/<agent>.md`. Root cause: canonicalize() resolved /tmp -> /private/tmp for `base` but left `target` literal because the snippet file didn't exist yet. New canonicalize_via_parent() walks up to the nearest existing ancestor and re-appends the missing tail, so both paths share a canonical prefix. 3. Stale-snippet detection in doctor. A user who ran `chorus setup` before v0.16.0 will not have the on-demand history contract in their provider snippets or managed blocks, and `chorus setup` without --force says "unchanged" and silently leaves them outdated. New doctor checks `snippet_<agent>_stale` and `integration_<agent>_stale` probe for the load-bearing "History contract" phrase; if absent, emit warn with the explicit "Run `chorus setup --force` to refresh." remediation. 4. Rust `setup --help` carries the same enumeration as Node — what files get created, the teardown reversal note, the global plugin caveat. Previously it was flag-list-only. 5. History contract promoted to the top of the managed block so an agent reading CLAUDE.md/AGENTS.md/GEMINI.md at session start encounters the on-demand rule BEFORE the routing bullets and command examples. Violating it is the most expensive failure mode (2.5x token inflation); placement reflects that. 6. ALLOWED_FLAGS now covers `trash-talk` and `agent-context` so a typo on those subcommands fails closed like every other. Files: cli/src/agents.rs (matcher), cli/src/setup.rs (relative_path + template), cli/src/main.rs (setup long_about), cli/src/doctor.rs (stale_snippet_checks), scripts/read_session.cjs (mirror). 164 cargo tests + conformance green. Live doctor on this repo correctly fires `integration_claude_stale` against the hand-authored CLAUDE.md whose managed block predates v0.16.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lockstep version bump 0.15.0 → 0.16.0 across package.json,
cli/Cargo.toml, cli/Cargo.lock.
User-facing docs updated for v0.16.0 capabilities:
README.md
Cut from 466 lines to a focused marketing landing (progressive
disclosure). Keeps hook + demos + 60-second quickstart up top;
consolidates capabilities into one runnable block; adds terse
"What's New in v0.16.0" section linking to RELEASE_NOTES.
Removed: stale comparison tables, duplicate demo callouts, full
flag matrices (CLI_REFERENCE owns those), per-feature deep dives,
inline Mermaid sequence (kept the SVG), Roadmap section.
docs/CLI_REFERENCE.md
Authoritative reference. Adds:
- `--history` (on-demand / none / eager) full semantics table
- `cwd_mismatch` field semantics + stderr mirror rule
- Cursor source field (`"cli" | "app"`) + two-surface adapter doc
- Doctor 4-tier severity model + full check catalogue including
new v0.16.0 IDs (sessions_cursor_{cli,app}, env_override_dangling,
snippet_<agent>_stale, integration_<agent>_stale)
- `report --help` handoff schema cross-link
- Unknown-flag rejection (F11) section
- Search invariant section documenting CI-enforced read ⊆ search
- CHORUS_CURSOR_APP_DATA_DIR env override
- Setup operations table with History contract enrichment +
stale-snippet detection callout
PROTOCOL.md
Bumped to v0.16.0. Adds rules 18-24 covering --history contract,
cwd_mismatch emission, --tool-calls uniform warning, dual-runtime
parity, F11 fail-closed unknown flags, search invariant, Cursor
IDE surface + Node 22.5 graceful fallback. Doctor contract
rewritten with severity model + check-ID catalogue. JSON Output
Contract extended with conditional fields and cursor `source`.
RELEASE_NOTES.md
New top entry for v0.16.0. Structured: headline → highlights →
what's new (by category: Adapter coverage / Read contract /
Doctor honesty / Help & docs / Hygiene) → breaking changes →
upgrade notes → acceptance → known limitations → credits. Maps
every line back to a commit in main..HEAD. Existing v0.15.0
entry preserved verbatim below.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cycle goal: close every gap from the v0.15.0 UAT, then run two fresh-context UAT-review rounds against the changes to make sure they actually hold up.
Result: 6 PRIO-1 scopes (N1-N7) shipped, 9 follow-up fixes (F1-F13) from independent UAT review, 5 R2 defects found by a second review round and fixed. 164 cargo tests + full conformance green. All breaking changes documented.
The headline capabilities for end users:
~/.cursor/chats/<hash>/<uuid>/store.dbSQLite). Previously chorus could only readcursor-agentCLI transcripts; the IDE surface was invisible.chorus read --history=on-demandis the contracted default. Agents reading the provider snippet at session start now see a top-of-block instruction to NOT eagerly loop prior sessions — closes the 2.5x token-inflation finding from the field study.cwd_mismatchfield on read output explicitly flags fallback when--cwddoesn't match any session. No more silent wrong-session returns to JSON-only consumers.infoseverity (doesn't elevate overall), env-var dangling-path detection, git-aware hooks checks, stale-snippet detection that flags pre-v0.16.0 setups.What's in the PR
14 commits, file-disjoint where possible:
Full per-commit detail is in
RELEASE_NOTES.md(v0.16.0 entry at the top of the file).Breaking changes
Called out explicitly in RELEASE_NOTES, summarized here for review:
sessions_cursordoctor check is split intosessions_cursor_cli+sessions_cursor_app. Consumers parsing doctor JSON by check ID need to update.--tool-callson gemini/hermes now emits a uniform warning inwarnings[](previously silent). The flag still setsincluded_tool_calls: true.cwd_matches_projectno longer treats a session withcwd: "/"as a wildcard match. Real bug fix but flips behavior for any consumer that relied on the old broken matcher.cwd_mismatch: truefield added to read output when fallback fires. Schema additive; existing consumers unaffected unless they have strictadditionalProperties: false.Acceptance
cursor_app.rs; was 161 at v0.15.0).read-cursor-app,read-cursor-app-tool-calls,read-cursor-app-redaction,read-{claude,codex}-tool-fixture,read-hermes,read-hermes-tool-calls,read-gemini-tool-calls,read-codex-history-{eager,none}, and 5xsearch-read-parity <agent>.chorus doctorcorrectly firesintegration_claude_staleagainst this repo's hand-authored CLAUDE.md (proves stale-snippet detection works on a real not-yet-refreshed managed block).chorus read --agent cursor --id <uuid>end-to-end, including tool_use rendering with--tool-calls, and redaction applies to SQLite content via the existingredactSensitiveTextwrap.UAT discipline used
Two independent rounds of fresh-context sub-agent UAT review verified the work:
relative_path()symlink bug, missing stale-snippet detection, sparse Rustsetup --help, History contract buried mid-block. All addressed.Acceptance for every scope is in
research/next-scopes-post-v0.15.0-2026-06-03.md(gitignored; cited in RELEASE_NOTES credits).Upgrade notes
Detailed in RELEASE_NOTES; TL;DR:
chorus setup --forceto refresh provider snippets + managed blocks with the on-demand history contract. Doctor will flag stale ones viasnippet_<agent>_stale/integration_<agent>_staleuntil you do.node:sqlite). Older Node gracefully degrades to CLI/JSONL cursor only.BRIDGE_*orCHORUS_*_DIRenv vars pointing at non-existent directories —chorus doctornow flags them viaenv_override_dangling.Test plan
cargo test --manifest-path cli/Cargo.toml→ 164 passbash scripts/conformance.sh→ ends withConformance complete: Node and Rust outputs match …chorus doctor --jsonshows new severity levels and no self-contradictionschorus list --agent cursorreturns bothsource: "cli"andsource: "app"entries when both surfaces have datachorus read --agent codex --cwd /nonexistent/path --jsonreturnscwd_mismatch: trueAND echoes the fallback warning to stderrchorus report --helpincludes the handoff JSON schema and a copy-pasteable examplechorus setup --forceon a clean tmpdir produces provider snippets containing "History contract"chorus list --bogus-flagfails closed with "Unknown flag for 'list': --bogus-flag"🤖 Generated with Claude Code