@chorus-aidlc/chorus-pi 0.17.2 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ description: Multi-agent orchestration playbook — coordinate OTHER agents and
4
4
  license: AGPL-3.0
5
5
  metadata:
6
6
  author: chorus
7
- version: "0.17.2"
7
+ version: "0.18.0"
8
8
  category: project-management
9
9
  mcp_server: chorus
10
10
  ---
@@ -104,6 +104,14 @@ Guidance: start narrow. If a single owner can hold the whole feature in their he
104
104
 
105
105
  ---
106
106
 
107
+ ## Replying to the agent who woke you (advisory)
108
+
109
+ When an agent wakes a peer on a shared idea or task — an orchestrator dispatching a worker, or any agent `@mention`-ing another — the wake surfaces the **waker's live session anchor**: a note naming the waking agent and telling the woken peer that the waker has an open conversation on this idea. If you are the woken peer, **reply on the same idea/task resource** (comment there rather than opening a brand-new session) and your reply lands back in the waker's existing live session, keeping the collaboration on one thread instead of scattering into a fresh one.
110
+
111
+ This is **advisory, not routing.** There is no automatic server subscription and nothing is force-delivered — replying on the shared resource is simply *where a reply lands* (via the existing return path), not a guaranteed channel. When the waker's origin is **offline** at wake time, no live anchor is surfaced and the exchange degrades to **notify-only**: the reply reaches the waker as an ordinary notification it picks up on its next turn. Only idea/theme-anchored wakes carry this anchor; ad-hoc wakes with no shared idea do not.
112
+
113
+ ---
114
+
107
115
  ## Reversed-Conversation gates (you never auto-ship)
108
116
 
109
117
  Chorus is **AI proposes, humans verify**. As orchestrator you enforce that, you do not bypass it:
@@ -4,7 +4,7 @@ description: Chorus Proposal workflow — create proposals with document and tas
4
4
  license: AGPL-3.0
5
5
  metadata:
6
6
  author: chorus
7
- version: "0.17.2"
7
+ version: "0.18.0"
8
8
  category: project-management
9
9
  mcp_server: chorus
10
10
  ---
@@ -69,7 +69,9 @@ Elaboration resolved --> Create Proposal --> Add drafts --> Validate --> Submit
69
69
 
70
70
  ### Step 1: Create an Empty Proposal
71
71
 
72
- **Recommended approach:** Create the proposal container first without any drafts, then incrementally add document and task drafts one by one.
72
+ **Resolve the spec mode (Step 1.5) BEFORE this create.** In OpenSpec and spec-lite modes the container's `description` MUST carry a locator line (`OpenSpec change slug: <slug>` or `Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/`), and `description` can only be set at creation — decide the mode + slug/dated-path first and include that line in this single call. Free-form mode omits any locator line.
73
+
74
+ **Recommended approach:** Create the proposal container first (with the mode's locator line in `description` when applicable), then incrementally add document and task drafts one by one.
73
75
 
74
76
  ```
75
77
  chorus_pm_create_proposal({
@@ -85,15 +87,20 @@ chorus_pm_create_proposal({
85
87
 
86
88
  > **A theme cannot be a proposal input** — `chorus_pm_create_proposal` rejects any input idea with `isContainer = true`. Derive a child idea from the theme and write the proposal on the child instead. (See the theme-ideas section of the `/idea` skill.)
87
89
 
88
- ### Step 1.5: Detect OpenSpec mode
90
+ ### Step 1.5: Select spec mode
91
+
92
+ The spec mode is **already computed** by the chorus-pi extension's `session_start` handler (`resolveSpecMode`) — do NOT re-derive it. Read the `## Spec Mode` section of your injected context: it states `CHORUS_SPEC_MODE=<lite|openspec|off>` + a routing note. (No `## Spec Mode` in context? See `openspec-aware` §1 manual fallback — never hand-roll the rule.) Act on that value:
93
+
94
+ - If the section says the mode **cannot be honored** (explicit `CHORUS_SPEC_MODE=openspec` but OpenSpec unusable — config-conflict or install-hint reason), **halt** and surface it; do not fall back.
95
+ - Otherwise branch on the resolved mode:
89
96
 
90
- Before authoring document drafts, **load the `openspec-aware` skill at `skills/openspec-aware/SKILL.md`** and run its §1 detection contract. Branch on the result:
97
+ - **resolved = spec-lite** → load the `spec-lite` skill (`/skill:spec-lite`) and follow it: pick `$SLUG` (a **capability**, not one change). Ensure the durable `.chorus/specs/<slug>/spec.md` exists (local-only, **no Chorus ids**; use the `spec-lite` skill's inline durable-spec template) and update it in place. Create this change's **dated folder** `.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` with its **synced** Chorus-typed docs (`prd.md` primary, optional `tech_design.md`…; use the `spec-lite` skill's inline dated-folder document template). Put the literal locator line `Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` in the **Step 1 create** `description`, then mirror **each** dated-folder `<type>.md` to its persistent Document (`chorus_pm_add_document_draft --arg-file` first time, `chorus_pm_update_document --arg-file` after) via `chorus mcp call … --arg-file content=.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/<type>.md`. **`spec.md` is never mirrored.** Skip Step 2 below. (Tasks via `chorus_pm_add_task_draft`; no `tasks.md`.)
91
98
 
92
- - **`CHORUS_OPENSPEC_ACTIVE=1`** → follow `openspec-aware` §3. Pick `$SLUG`, scaffold `openspec/changes/<slug>/`, author `proposal.md` / `design.md` / `specs/<capability>/spec.md` locally, then create the proposal container (Step 1 above) with the literal line `OpenSpec change slug: <slug>` in `description`, and mirror each local file into a document draft.
99
+ - **resolved = OpenSpec** (the `## Spec Mode` section shows `CHORUS_OPENSPEC_ACTIVE=1` — i.e. `CHORUS_SPEC_MODE=openspec` *or* unset, with OpenSpec usable) → follow the `openspec-aware` skill §3. Pick `$SLUG`, scaffold `openspec/changes/<slug>/`, author `proposal.md` / `design.md` / `specs/<capability>/spec.md` locally, then put the literal line `OpenSpec change slug: <slug>` in the **Step 1 create** `description`, and mirror each local file into a document draft.
93
100
 
94
- > **⛔ Mandatory in OpenSpec mode:** mirror calls fill `content` from the local file — prefer `chorus mcp call … --arg-file content=<file>`, falling back to the `chorus-mcp-call.sh` wrapper with `json_encode_file` when `chorus` is not on `PATH` — see `openspec-aware` §3.6. Do **not** call `chorus_pm_add_document_draft` directly from the MCP harness with a hand-typed `content` field. Re-typing thousands of lines through the LLM burns 20k+ content tokens per proposal and breaks byte-equality with the local source of truth (`openspec-aware` §2 Rule 1 explains the full reasoning). Skip Step 2 below when in OpenSpec mode — the file-fill flow in `openspec-aware` §3.6 replaces it for documents.
101
+ > **⛔ Mandatory in OpenSpec mode:** mirror calls fill `content` from the local file — prefer `chorus mcp call … --arg-file content=<file>`, falling back to the `chorus-mcp-call.sh` wrapper with `json_encode_file` when `chorus` is not on `PATH` — see `openspec-aware` §3.6. Do **not** call `chorus_pm_add_document_draft` directly with a hand-typed `content` field. Re-typing thousands of lines burns 20k+ content tokens per proposal and breaks byte-equality (`openspec-aware` §2 Rule 1). Skip Step 2 when in OpenSpec mode — the file-fill flow replaces it for documents.
95
102
 
96
- - **`CHORUS_OPENSPEC_ACTIVE=0`** (CLI absent or `CHORUS_OPENSPEC_MODE=off`) → proceed with Step 2 unchanged. Author drafts inline as free-form Markdown via direct MCP `chorus_pm_add_document_draft`.
103
+ - **resolved = free-form** (explicit `CHORUS_SPEC_MODE=off`) → proceed with Step 2 unchanged. Author drafts inline as free-form Markdown via direct MCP `chorus_pm_add_document_draft`.
97
104
 
98
105
  ### Step 2: Add Document Drafts
99
106
 
@@ -4,7 +4,7 @@ description: Quick Task workflow — skip Idea→Proposal, create tasks directly
4
4
  license: AGPL-3.0
5
5
  metadata:
6
6
  author: chorus
7
- version: "0.17.2"
7
+ version: "0.18.0"
8
8
  category: project-management
9
9
  mcp_server: chorus
10
10
  ---
@@ -152,7 +152,7 @@ chorus_submit_for_verify({
152
152
  })
153
153
  ```
154
154
 
155
- Submitting is not final verification. Spawn the required task-reviewer agent with `subagent_spawn` as described in `/skill:develop`, wait for it, and read the newest `VERDICT:` Task comment. `PASS` and `PASS WITH NOTES` continue. On `FAIL`, do not verify or hand off: fix every unresolved BLOCKER, repeat AC self-check and submission, then run a fresh independent task review.
155
+ Submitting is not final verification. Spawn the required task-reviewer agent with `subagent_spawn` as described in `/skill:develop`, wait for it, and read THIS round's `VERDICT:` Task comment — the one posted after your dispatch, not an older round's. `PASS` and `PASS WITH NOTES` continue. On `FAIL`, do not verify or hand off: fix every unresolved BLOCKER, repeat AC self-check and submission, then run a fresh independent task review.
156
156
 
157
157
  ### Step 8: Permission-Aware Verification
158
158
 
@@ -4,7 +4,7 @@ description: Chorus Review workflow — approve/reject proposals, verify tasks,
4
4
  license: AGPL-3.0
5
5
  metadata:
6
6
  author: chorus
7
- version: "0.17.2"
7
+ version: "0.18.0"
8
8
  category: project-management
9
9
  mcp_server: chorus
10
10
  ---
@@ -65,12 +65,12 @@ Key responsibilities:
65
65
  When reviewing proposals, tasks, or an Idea's final aggregate code change, prefer spawning an independent reviewer sub-agent over reviewing manually:
66
66
 
67
67
  1. **Try the reviewer first.** Spawn `chorus-proposal-reviewer` (for proposals), `chorus-task-reviewer` (for tasks), or `chorus-code-reviewer` (the final ship-time gateway over an Idea's aggregate code change, after its last task is verified — pass the `ideaUuid`; it posts its VERDICT on the **idea**) as a read-only sub-agent. **Use the blocking `subagent` tool** (it waits for the VERDICT and returns it) — you must wait for the VERDICT before proceeding. It posts a VERDICT comment with detailed findings.
68
- 2. **Read the VERDICT.** After the reviewer completes, call `chorus_get_comments` and find the most recent comment containing `VERDICT:`. There are exactly three possible outcomes:
68
+ 2. **Read the VERDICT.** After the reviewer completes, call `chorus_get_comments` and find THIS round's `VERDICT:` comment — the one posted after your dispatch, not an older round's. There are exactly three possible outcomes:
69
69
  - **VERDICT: PASS** — No issues found. Approve (proposals) or mark AC passed and verify (tasks).
70
70
  - **VERDICT: PASS WITH NOTES** — Minor non-blocking notes. Still approve/verify. Notes are informational.
71
71
  - **VERDICT: FAIL** — BLOCKERs found. Reject (proposals) or reopen (tasks). Fix the specific BLOCKERs listed in the comment before resubmitting.
72
- 3. **No new VERDICT comment?** The reviewer exhausted its turn budget before posting. Respawn it ONCE with an explicit prompt like: *"Stay within your turn budget. Skip deep source verification — batch all MCP fetches up front, skim for obvious BLOCKERs only, and reserve your last few turns to post the VERDICT comment."* If the second attempt also fails to post, review manually using the checklists below.
73
- 4. **Track rounds.** Count existing VERDICT comments before spawning. After 3 rounds of FAIL on the same item, stop the loop and escalate to human review.
72
+ 3. **No new VERDICT comment?** Check what the reviewer *did* post. A comment reporting that the round limit was reached, or any other explicit refusal to review, is a deliberate escalation to a human: STOP — do not respawn, do not self-review, do not post a VERDICT of your own. If it posted nothing at all, respawn it ONCE, telling it to stay within its turn budget and reserve its last turns for the VERDICT, then apply this same check again to what the retry posts. An explicit refusal from the retry still means STOP; only a second true silence lets you review the item yourself as a read-only pass using the checklists below and POST the VERDICT — **absence is never a PASS**.
73
+ 4. **Track rounds.** Count existing VERDICT comments before spawning. After 3 rounds of FAIL on the same item, stop the loop and escalate to human review: post a comment saying the round limit was reached and a human decision is needed, and post no VERDICT. Nobody — including you on a later turn — may replace that escalation with a self-reviewed VERDICT.
74
74
  5. **Fallback.** If the reviewer is unavailable (e.g., agent type not registered, sub-agent spawn fails), review the item yourself using the quality checklists in the workflows below.
75
75
 
76
76
  ---
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: spec-lite
3
+ description: Lightweight, Chorus-native local specs for Chorus PM workflows in Pi — a durable local spec `.chorus/specs/<slug>/spec.md` (one per capability/feature) edited in place and NEVER synced (git history is its record), plus one dated folder per change effort `.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` holding Chorus-typed docs (prd.md, tech_design.md, …) that ARE mirrored 1:1 into persistent Chorus Documents via `--arg-file`. The fallback when OpenSpec isn't in use; a low-token alternative to the heavier openspec-aware path. Read from proposal / develop / yolo when the spec mode resolves to `lite`.
4
+ license: AGPL-3.0
5
+ metadata:
6
+ author: chorus
7
+ version: "0.18.0"
8
+ category: project-management
9
+ mcp_server: chorus
10
+ ---
11
+
12
+ # spec-lite — durable local spec + per-change synced docs
13
+
14
+ A **shared sub-procedure** for the Chorus stage skills (proposal, develop, yolo) — the lightweight
15
+ spec mode, modelled on **superpowers** (a durable spec that lives on, plus per-effort artifacts):
16
+ one **durable local spec** per capability (`<slug>/spec.md`, edited in place, **never synced** — git
17
+ history is its 留痕), plus one **dated folder per change effort** (`<slug>/<YYYY-MM-DD>-<change-slug>/`
18
+ of Chorus-typed docs — `prd.md`, … — that **are** mirrored 1:1 into persistent Chorus Documents).
19
+ No new CLI, MCP tool, backend, or schema — mirroring reuses the existing document tools.
20
+
21
+ ## Mode (how you got here)
22
+
23
+ The spec mode is computed by the chorus-pi extension's `session_start` handler (`resolveSpecMode`),
24
+ **not by you** — the `## Spec Mode` section of your injected context states the resolved
25
+ `CHORUS_SPEC_MODE`. You are here because it resolved to `lite`; if it is anything else, this skill is a
26
+ no-op — return to the caller. (For the record, the rule: an explicit `CHORUS_SPEC_MODE` wins, else
27
+ OpenSpec when usable, else lite.)
28
+
29
+ ## The durable local spec — `<slug>/spec.md`
30
+
31
+ `.chorus/specs/<slug>/spec.md` — `<slug>` (kebab-case) names a **capability/feature, not one change**.
32
+ This is the single, cumulative, human-readable "current truth" of the capability: **edited in place**
33
+ by every change, **never mirrored to Chorus, carries no Chorus ids**. Minimal frontmatter only
34
+ (`slug`, `title`, `status: draft|active|done`, `created`), then plain prose — `## Intent`,
35
+ `## Requirements` (prose + `- [ ]` acceptance points, no `SHALL`/scenario grammar), `## Non-goals`.
36
+ Start from the inline **durable `spec.md` template** below. Its git history is the whole record — no changelog
37
+ section, no Chorus round-trip. **This file NEVER enters the mirror loop.**
38
+
39
+ `status` describes the **capability**, not a single change: `active` while any change is in flight,
40
+ `done` when the current change delivers and none is open. A **new** change against a `done` capability
41
+ reopens it to `active`, back to `done` on delivery.
42
+
43
+ ### Template — the durable `spec.md`
44
+
45
+ ```markdown
46
+ ---
47
+ slug: <kebab-case-capability>
48
+ title: <Capability title>
49
+ status: draft # draft | active | done
50
+ created: <YYYY-MM-DD>
51
+ ---
52
+
53
+ ## Intent
54
+ <what this capability is for, in prose>
55
+
56
+ ## Requirements
57
+ <prose, no SHALL/scenario grammar>
58
+ - [ ] <acceptance point>
59
+
60
+ ## Non-goals
61
+ - <explicitly out of scope>
62
+ ```
63
+
64
+ ## Per-change dated folders — `<slug>/<YYYY-MM-DD>-<change-slug>/`
65
+
66
+ Each change effort is **one dated folder directly under `<slug>/`** (no `changes/` wrapper), e.g.
67
+ `.chorus/specs/<slug>/2026-09-08-add-export/`. Date + slug so same-day changes don't collide and
68
+ folders sort by date. It holds the **Chorus-typed** docs for THAT change — one file per Document type:
69
+
70
+ | File | `Document.type` | Required? |
71
+ |---|---|---|
72
+ | `prd.md` | `prd` | **yes** — the primary per-change doc |
73
+ | `tech_design.md` | `tech_design` | optional — the "how" |
74
+ | `adr.md` / `guide.md` / `spec.md` | `adr` / `guide` / `spec` | optional |
75
+
76
+ These files **ARE synced** — each maps to **one persistent Chorus Document** of its type. Their
77
+ frontmatter carries the sync ids `proposalUuid` and `documentUuid` (the type is implied by the
78
+ filename). Start from the inline **dated-folder document template** below. A different change to the same
79
+ capability is a different dated folder. The **current change's** folder is edited and re-mirrored
80
+ throughout its effort (until delivery); only **previously-delivered** dated folders are left frozen —
81
+ you don't reach back and rewrite a past change.
82
+
83
+ > **Two files named `spec.md`, different roles.** The durable `<slug>/spec.md` (local only, no ids) is
84
+ > NOT the same as a per-change `spec`-type doc, which would live at `<slug>/<date>-<slug>/spec.md`
85
+ > (synced, carries ids). Prefer `prd.md` as the per-change primary doc to avoid the confusion.
86
+
87
+ ### Template — a dated-folder document
88
+
89
+ The document **type is implied by the filename** (`prd.md` → `prd`, `tech_design.md` → `tech_design`, …),
90
+ **NOT** a frontmatter key.
91
+
92
+ ```markdown
93
+ ---
94
+ title: <Document title as it appears in Chorus>
95
+ proposalUuid: <uuid> # written on first mirror
96
+ documentUuid: # empty until the draft materializes on approval
97
+ ---
98
+
99
+ # <Document title>
100
+ <body — this file's bytes are the source of truth for the Chorus Document>
101
+ ```
102
+
103
+ ## Flow (one change)
104
+
105
+ 1. Confirm mode = `lite` (else no-op).
106
+ 2. Create the dated folder `<slug>/<YYYY-MM-DD>-<change-slug>/` and write its **synced** change docs —
107
+ `prd.md` (required), `tech_design.md` etc. only if warranted (use the **dated-folder document template** above).
108
+ 3. **Update `<slug>/spec.md` in place** to the new cumulative truth (Requirements, acceptance points,
109
+ `status`) — local only, no sync.
110
+ 4. Create the proposal container with one literal locator line in `description` (own line, no trailing
111
+ punctuation) so develop finds the change:
112
+ `Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/`
113
+ 5. **Mirror the dated folder's docs** to Chorus (below). Add tasks via `chorus_pm_add_task_draft` —
114
+ **no `tasks.md`**, no CLI / validate / archive, no delta grammar. **Tasks live in Chorus.**
115
+ 6. Develop → keep editing `spec.md` + the change docs, re-mirroring the change docs as work lands and
116
+ ticking acceptance points. On delivery set the durable `spec.md` `status: done`.
117
+
118
+ ## Mirror — only the dated-folder docs (never `spec.md`)
119
+
120
+ Every dated-folder `<type>.md` maps to **one persistent Chorus Document** of that `type`, tracked by
121
+ `documentUuid` in the file's frontmatter. Fill `content` from the file's bytes with `--arg-file` —
122
+ never re-type the body (drifts, burns ~20k tokens). One call per file; resolve identity by
123
+ `documentUuid` / `(proposalUuid, type)`, **never by `title` alone** (a lookup finding zero or >1 MUST
124
+ **halt**). Guard every call with the `chorus_check_response` halt-on-error helper (`openspec-aware`
125
+ §6). No `chorus` on `PATH`? Fall back to `chorus-mcp-call.sh` + `json_encode_file` (`openspec-aware` §3.6);
126
+ the extension resolves the bundled wrapper and surfaces its path in the session_start context.
127
+ **`<slug>/spec.md` is NEVER in this loop.**
128
+
129
+ - **First time a doc is authored** (its dated folder is new): write `proposalUuid` into frontmatter,
130
+ mirror into a proposal **draft** —
131
+ `chorus mcp call chorus_pm_add_document_draft "{\"proposalUuid\":\"$P\",\"type\":\"prd\",\"title\":\"PRD: $TITLE\"}" --arg-file content=".chorus/specs/$SLUG/$DATED/prd.md"`.
132
+ Edit the draft via `chorus_pm_update_document_draft` (returned `draftUuid`) before approval. On
133
+ approval it materializes into a persistent Document — resolve by `(proposalUuid, type)` via
134
+ `chorus_get_documents`, record `documentUuid` in frontmatter, re-mirror once so local == Chorus.
135
+ - **Later edits** (a doc that already has a `documentUuid`): edit the file, then
136
+ `chorus mcp call chorus_pm_update_document "{\"documentUuid\":\"$D\"}" --arg-file content=".chorus/specs/$SLUG/$DATED/<type>.md"`.
137
+ Each update **auto-increments the Document version** — that version history is the change doc's
138
+ record in Chorus, alongside git.
139
+
140
+ ## 留痕: git history + Document versions
141
+
142
+ `git log -- .chorus/specs/$SLUG/` is the audit trail — the durable `spec.md`'s in-place diffs plus each
143
+ dated folder's change docs; the mirrored Documents' auto-incremented versions are the parallel record
144
+ in Chorus. No changelog section to maintain. Only `.chorus/specs/` is version-controlled (`.chorus/*` +
145
+ `!.chorus/specs/`).
146
+
147
+ **Single-writer:** the folder is shared — in a multi-task wave only the **orchestrator / main agent**
148
+ edits + re-mirrors; parallel workers report via `chorus_report_work` only, re-reading before any write.
149
+ **Task state lives in Chorus**, not the docs — the `- [ ]` points are acceptance intent, not a tracker.
@@ -4,7 +4,7 @@ description: Full-auto AI-DLC pipeline — from prompt to done. Automates the en
4
4
  license: AGPL-3.0
5
5
  metadata:
6
6
  author: chorus
7
- version: "0.17.2"
7
+ version: "0.18.0"
8
8
  category: project-management
9
9
  mcp_server: chorus
10
10
  ---
@@ -188,21 +188,17 @@ In /yolo mode, the agent generates elaboration questions and answers them itself
188
188
 
189
189
  #### Step 1.4: Create Proposal
190
190
 
191
- 1. **Detect OpenSpec mode.** Load the `openspec-aware` skill at `skills/openspec-aware/SKILL.md` and run its §1 detection contract. The result determines how the rest of this step authors documents:
191
+ 1. **Read the spec mode (already computed).** The chorus-pi extension's `session_start` handler (`resolveSpecMode`) has already resolved it — do NOT re-derive. Read the `## Spec Mode` section: `CHORUS_SPEC_MODE=<lite|openspec|off>` + a routing note. Act on it: `openspec` (usable, shows `CHORUS_OPENSPEC_ACTIVE=1`) → **2a**; `off` → **2b**; `lite` → **2c**. If it says the mode **cannot be honored** (explicit `openspec` but unusable), **halt** and surface it — do NOT fall back or enter 2a with no OpenSpec. (No `## Spec Mode`? See `openspec-aware` §1 manual fallback.) This matters because yolo runs unattended.
192
192
 
193
- - `CHORUS_OPENSPEC_ACTIVE=1` → spec-driven branch (sub-step 2a below).
194
- - `CHORUS_OPENSPEC_ACTIVE=0` → free-form branch (sub-step 2b below).
195
-
196
- This is mandatory — yolo runs unattended, so silently picking the wrong mode is exactly the failure scenario the detection contract exists to prevent.
197
-
198
- 2. **Create the empty proposal container.** In OpenSpec mode, the `description` MUST contain the literal line `OpenSpec change slug: <slug>` (use the `$SLUG` you'll pick in 2a); in free-form mode, omit that line.
193
+ 2. **Create the empty proposal container.** The `description` MUST carry the mode's locator line — OpenSpec: `OpenSpec change slug: <slug>`; spec-lite: `Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/`; free-form: none. `description` is only settable at creation, so decide the slug/dated-path first.
199
194
 
200
195
  ```
201
196
  chorus_pm_create_proposal({
202
197
  projectUuid: "<project-uuid>",
203
198
  title: "<feature name>",
204
- description: "<summary>\n\nOpenSpec change slug: <slug>", // OpenSpec mode
205
- // description: "<summary>", // free-form mode
199
+ description: "<summary>\n\nOpenSpec change slug: <slug>", // OpenSpec (2a)
200
+ // description: "<summary>\n\nSpec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/", // spec-lite (2c)
201
+ // description: "<summary>", // free-form (2b)
206
202
  inputType: "idea",
207
203
  inputUuids: ["<idea-uuid>"]
208
204
  })
@@ -220,7 +216,7 @@ In /yolo mode, the agent generates elaboration questions and answers them itself
220
216
 
221
217
  Then continue to step 3 (task drafts).
222
218
 
223
- **2b. Free-form mode (`CHORUS_OPENSPEC_ACTIVE=0`).** Add a tech design document draft directly via MCP, content authored inline:
219
+ **2b. Free-form mode (resolved mode = free-form).** Only when step 1 resolved to free-form — i.e. explicit `CHORUS_SPEC_MODE=off` (unset never comes here: it resolves to OpenSpec when usable, else spec-lite/2c). Add a tech design document draft directly via MCP, content authored inline:
224
220
 
225
221
  ```
226
222
  chorus_pm_add_document_draft({
@@ -231,6 +227,8 @@ In /yolo mode, the agent generates elaboration questions and answers them itself
231
227
  })
232
228
  ```
233
229
 
230
+ **2c. spec-lite mode (resolved mode = lite).** Load the `spec-lite` skill (`/skill:spec-lite`). Pick `$SLUG` (a **capability**). Ensure the durable `.chorus/specs/<slug>/spec.md` exists (local-only, no ids; use the `spec-lite` skill's inline durable-spec template) and update it in place. Create this change's **dated folder** `.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` with its **synced** Chorus-typed docs (shape = the `spec-lite` skill's inline dated-folder document template) — `prd.md` (primary), optional `tech_design.md`… The `description` carries the `Spec-lite: .chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/` locator (step 2). Mirror **each** dated-folder `<type>.md` to its persistent Document byte-exact — first time `chorus mcp call chorus_pm_add_document_draft "{\"proposalUuid\":\"<uuid>\",\"type\":\"prd\",\"title\":\"PRD: <feature>\"}" --arg-file content=.chorus/specs/<slug>/<YYYY-MM-DD>-<change-slug>/prd.md`, later edits via `chorus_pm_update_document` against the recorded `documentUuid` (`chorus-mcp-call.sh` fallback when `chorus` not on `PATH`). **`spec.md` is never mirrored.** No `openspec/changes/` scaffold; no `tasks.md`. Then continue to step 3.
231
+
234
232
  3. **Add task drafts incrementally** (use returned `draftUuid` for dependency chaining). `acceptanceCriteriaItems` is **required** on every draft — at least one non-blank criterion, or the call is rejected:
235
233
  ```
236
234
  # First task
@@ -272,6 +270,20 @@ In /yolo mode, the agent generates elaboration questions and answers them itself
272
270
 
273
271
  ---
274
272
 
273
+ ### Reviewer contract (applies to every review gate below)
274
+
275
+ Every gate in Phases 2, 4 and 4.5 follows the same three steps. They are written once here; the phases below only name their entity and their stage-specific actions.
276
+
277
+ 1. **Spawn and wait.** Spawn the reviewer as a read-only sub-agent, then wait for it: spawn it via the blocking `subagent` tool, which waits for the reviewer to finish. Read the verdict from the reviewer's `VERDICT:` comment on the entity.
278
+ 2. **Read THIS round's VERDICT.** Call `chorus_get_comments` on the entity and find the `VERDICT:` comment posted **after your dispatch**, not an older round's. Do not advance the gate before you have read it.
279
+ 3. **No VERDICT for this round?** Check what the reviewer *did* post:
280
+ - **A reported round limit, or any other explicit refusal to review** — a deliberate escalation to a human. STOP: do not respawn, do not self-review, do not post a VERDICT of your own.
281
+ - **Nothing at all** — respawn ONCE, telling it to stay within its turn budget and reserve its last turns for the VERDICT, then apply this same check again to what the retry posts. An explicit refusal from the retry still means STOP; only a second true silence lets you review the entity yourself as a read-only pass and POST the VERDICT, then proceed on what you posted rather than looping forever.
282
+
283
+ **Absence is never a PASS**, and a round limit reached by someone else is never yours to clear.
284
+
285
+ ---
286
+
275
287
  ### Phase 2: Proposal Review Loop
276
288
 
277
289
  After `chorus_pm_submit_proposal`, the extension nudges you to spawn `chorus-proposal-reviewer`. You MUST manually spawn it as a read-only sub-agent via the blocking `subagent` tool (it waits for the VERDICT). Wait for it to complete, then:
@@ -280,7 +292,7 @@ After `chorus_pm_submit_proposal`, the extension nudges you to spawn `chorus-pro
280
292
  ```
281
293
  chorus_get_comments({ targetType: "proposal", targetUuid: "<proposal-uuid>" })
282
294
  ```
283
- Look for the most recent comment containing `VERDICT:`.
295
+ Look for THIS round's `VERDICT:` comment — the one posted after your dispatch, not an older round's.
284
296
 
285
297
  2. **Act on the VERDICT:**
286
298
 
@@ -314,7 +326,7 @@ After `chorus_pm_submit_proposal`, the extension nudges you to spawn `chorus-pro
314
326
  Proposal UUID: <uuid>"
315
327
  ```
316
328
 
317
- 4. **No new VERDICT comment after reviewer returns?** The reviewer exhausted its turn budget. Respawn it ONCE with a concise-budget hint: *"Stay within turn budget. Skip deep source verification. Fetch proposal + comments + idea only, skim for obvious BLOCKERs, and post your VERDICT within the first 10 turns."* If the second attempt still produces no VERDICT, treat the proposal as PASS WITH NOTES and proceed — the pipeline cannot loop forever on a silent reviewer.
329
+ 4. **No new VERDICT for this round?** Apply step 3 of the **Reviewer contract**, reviewing the proposal yourself if the reviewer stays silent.
318
330
 
319
331
  ---
320
332
 
@@ -411,7 +423,7 @@ for each task in wave_tasks:
411
423
 
412
424
  # 3. Read task-reviewer VERDICT
413
425
  comments = chorus_get_comments({ targetType: "task", targetUuid: "<task-uuid>" })
414
- # Find the most recent comment containing "VERDICT:"
426
+ # Find THIS round's "VERDICT:" comment — the one posted after your dispatch, not an older round's
415
427
 
416
428
  # 4. Act on VERDICT — three possible outcomes:
417
429
  if VERDICT is "PASS":
@@ -449,7 +461,7 @@ ESCALATE: "Task '{title}' failed review after {maxRounds} rounds.
449
461
 
450
462
  Continue with remaining tasks -- do not halt the entire pipeline for one stuck task.
451
463
 
452
- **No new VERDICT comment after the task-reviewer returns?** It exhausted its turn budget. Respawn it ONCE with a concise-budget hint: *"Stay within turn budget. Skip deep verification. Fetch task/proposal/comments, run only the core tests, and post your VERDICT within the first 12 turns."* If the second attempt also produces no VERDICT, treat as PASS WITH NOTES and proceed — do not loop indefinitely.
464
+ **No new VERDICT for this round?** Apply step 3 of the **Reviewer contract**, reviewing the task yourself if the reviewer stays silent.
453
465
 
454
466
  ---
455
467
 
@@ -465,7 +477,7 @@ subagent({ agent: "chorus-code-reviewer",
465
477
 
466
478
  # Read its VERDICT on the idea
467
479
  comments = chorus_get_comments({ targetType: "idea", targetUuid: "<idea-uuid>" })
468
- # Find the most recent comment containing "VERDICT:"
480
+ # Find THIS round's "VERDICT:" comment — the one posted after your dispatch, not an older round's
469
481
  ```
470
482
 
471
483
  Act on the VERDICT:
@@ -479,7 +491,7 @@ ESCALATE: "Idea '<title>' failed code review after {CHORUS_MAX_CODE_REVIEW_ROUND
479
491
  Last BLOCKERs: <list>. Manual intervention needed. Idea UUID: <uuid>"
480
492
  ```
481
493
 
482
- **No new VERDICT comment after the code-reviewer returns?** It exhausted its turn budget (the code-reviewer runs with a larger budget than the task-reviewer because it reviews the whole feature). Respawn it ONCE with a concise-budget hint, then if still silent treat as PASS WITH NOTES and proceed — do not loop forever on a silent reviewer.
494
+ **No new VERDICT for this round?** Apply step 3 of the **Reviewer contract**, reviewing the idea's aggregate change yourself if the reviewer stays silent.
483
495
 
484
496
  > The code-review gateway is **behavioral**, consistent with the proposal/task reviewers: its verdict is advisory and does not change the Idea's stored status. The /yolo orchestrator honors it — PASS to ship, FAIL to loop. It runs **before** the completion report so the report is never written for a feature with an outstanding FAIL.
485
497