---
name: chorus-proposal
description: Chorus proposal workflow for OpenCode. Use when creating proposals, PRD and tech design drafts, task drafts, acceptance criteria, and dependency DAGs.
license: AGPL-3.0
compatibility: opencode
metadata:
  author: chorus
  version: "0.10.0"
  category: project-management
  mcp_server: lazy-chorus-bridge
  workflow: planning
  role: proposal:write
  audience: opencode-agents
  source: chorus-plugin
  keywords: proposal,prd,tech-design,task-drafts,dependency-dag,acceptance-criteria
  tools: chorus_pm_create_proposal,chorus_pm_add_document_draft,chorus_pm_add_task_draft,chorus_pm_submit_proposal
---


# Proposal Skill

This skill covers the **Planning** stage of the AI-DLC workflow: creating Proposals that contain document drafts (PRD, tech design) and task drafts with dependency DAGs, then submitting them for Admin review.

## OpenCode Tool Access

In OpenCode plugin mode, Chorus uses the lazy bridge tools `chorus_tools`, `chorus_tool_get`, and `chorus_tool_execute`. Start with `chorus_tools`, inspect one tool with `chorus_tool_get({ toolName: "..." })`, then execute it with `chorus_tool_execute({ toolName: "...", arguments: { ... } })`.

---

## Overview

After an Idea's elaboration is resolved (see `chorus-idea`), an agent with `proposal:write` creates a Proposal — a container that holds document drafts and task drafts. On `task:admin` approval, these drafts materialize into real Documents and Tasks.

```
Elaboration resolved --> Create Proposal --> Add drafts --> Validate --> Submit --> Admin chorus-review
```

---

## Tools

**Proposal Management:**

| Tool | Purpose |
|------|---------|
| `chorus_pm_create_proposal` | Create empty proposal container |
| `chorus_pm_validate_proposal` | Validate proposal completeness (returns errors, warnings, info) |
| `chorus_pm_submit_proposal` | Submit proposal for Admin approval (draft -> pending) |

**Document Drafts:**

| Tool | Purpose |
|------|---------|
| `chorus_pm_add_document_draft` | Add document draft to proposal |
| `chorus_pm_update_document_draft` | Update document draft content |
| `chorus_pm_remove_document_draft` | Remove document draft from proposal |

**Task Drafts:**

| Tool | Purpose |
|------|---------|
| `chorus_pm_add_task_draft` | Add task draft (returns draftUuid for dependency chaining) |
| `chorus_pm_update_task_draft` | Update task draft |
| `chorus_pm_remove_task_draft` | Remove task draft from proposal |

**Post-Approval (tasks exist):**

| Tool | Purpose |
|------|---------|
| `chorus_create_tasks` | Batch create tasks (supports intra-batch dependencies via draftUuid) |
| `chorus_pm_assign_task` | Assign a task to an agent with `task:write` |
| `chorus_pm_create_document` | Create standalone document |
| `chorus_pm_update_document` | Update document content (increments version) |
| `chorus_update_task` (with `addDependsOn` / `removeDependsOn`) | Add or remove task dependencies (with cycle detection) |

**Shared tools** (checkin, query, comment, search, notifications): see `/chorus`

---

## Workflow

### Step 1: Create an Empty Proposal

**Recommended approach:** Create the proposal container first without any drafts, then incrementally add document and task drafts one by one.

If the project is known to use OpenSpec, run Step 1.5 first so the proposal description can include `OpenSpec change slug: <slug>`.

```
chorus_tool_execute({ toolName: "chorus_pm_create_proposal", arguments: {
  projectUuid: "<project-uuid>",
  title: "Implement <feature name>",
  description: "Analysis and implementation plan for Idea #xxx",
  inputType: "idea",
  inputUuids: ["<idea-uuid>"]
} })
```

**Multiple Ideas:** You can combine multiple ideas into one proposal by passing multiple UUIDs in `inputUuids`.

### Step 1.5: Detect OpenSpec Mode

Before adding document drafts, check whether this repository should use OpenSpec-backed authoring:

1. Confirm the project root contains `openspec/`.
2. Confirm the `openspec` CLI is available with a harmless command such as `openspec --version`.
3. If both are true, load the `chorus-openspec` skill and use OpenSpec mode.
4. If either is false, continue in free-form mode and add document drafts inline in Step 2.

**OpenSpec mode branch:**

- Pick or confirm a change slug.
- Run `openspec new change <slug>` if the change does not already exist.
- Author local `proposal.md`, `design.md`, `specs/**/spec.md`, and `tasks.md` under `openspec/changes/<slug>/`.
- Include `OpenSpec change slug: <slug>` in the Chorus proposal description, or add it as a proposal comment if the proposal was already created.
- Mirror local OpenSpec documents into Chorus with `chorus_pm_add_document_draft`.
- Convert `tasks.md` into Chorus task drafts with `chorus_pm_add_task_draft`.

**Free-form mode branch:**

- Continue to Step 2: write PRD / tech design / spec content to a file in the Chorus staging directory (injected at session start), then pass its absolute path via `contentPath` in `chorus_pm_add_document_draft` calls. Use OpenCode's native `write` / `edit` tools for these staging files when possible. Do not write document drafts to the project workspace.
- Continue to Step 3 and write task drafts directly in Chorus.

### Step 2: Add Document Drafts

Write each document to a file in the Chorus staging directory first, then add it as a draft by passing the file path via `contentPath`. The Chorus staging directory is injected into your context at session start — use that absolute path. Prefer OpenCode's native `write` / `edit` tools over bash-based file writes when preparing these files. The bridge reads the file and uploads its content; the file is deleted when the session ends.

```
# Write the PRD to the staging directory first (use the injected <chorus-staging-dir> path), then:
chorus_tool_execute({ toolName: "chorus_pm_add_document_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  type: "prd",
  title: "PRD: <Feature Name>",
  contentPath: "<chorus-staging-dir>/prd.md"
} })

# Write the Tech Design first, then:
chorus_tool_execute({ toolName: "chorus_pm_add_document_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  type: "tech_design",
  title: "Tech Design: <Feature Name>",
  contentPath: "<chorus-staging-dir>/design.md"
} })
```

**Document types:** `prd`, `tech_design`, `adr`, `spec`, `guide`

### Step 3: Add Task Drafts

Add task drafts one at a time. The response returns the new draft's `draftUuid` — use it directly for `dependsOnDraftUuids` in subsequent drafts.

```
# First task -> response includes { draftUuid, draftTitle }
chorus_tool_execute({ toolName: "chorus_pm_add_task_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  title: "Implement <component>",
  description: "Detailed description of what to build...",
  priority: "high",
  storyPoints: 3,
  acceptanceCriteriaItems: [
    { description: "Criteria 1", required: true },
    { description: "Criteria 2", required: true }
  ]
} })

# Second task — depends on first
chorus_tool_execute({ toolName: "chorus_pm_add_task_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  title: "Write tests for <component>",
  description: "Unit and integration tests...",
  priority: "medium",
  storyPoints: 2,
  acceptanceCriteriaItems: [
    { description: "Test coverage > 80%", required: true }
  ],
  dependsOnDraftUuids: ["<draftUuid-from-first-task>"]
} })
```

Prefer `acceptanceCriteriaItems` for all new task drafts. Legacy Markdown `acceptanceCriteria` may exist in older proposals, but structured criteria are the current format and support self-checking.

**Task priority:** `low`, `medium`, `high`

### Step 4: Review and Refine Drafts

```
# Review current state
chorus_tool_execute({ toolName: "chorus_get_proposal", arguments: { proposalUuid: "<proposal-uuid>", section: "full" } })

# Update a document draft — write the updated content to a staging file first, then:
chorus_tool_execute({ toolName: "chorus_pm_update_document_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  draftUuid: "<draft-uuid>",
  contentPath: "<chorus-staging-dir>/prd.md"
} })

# Update task draft acceptance criteria in structured form:
chorus_tool_execute({ toolName: "chorus_pm_update_task_draft", arguments: {
  proposalUuid: "<proposal-uuid>",
  draftUuid: "<task-draft-uuid>",
  acceptanceCriteriaItems: [
    { description: "Updated criterion", required: true }
  ]
} })
```

### Step 5: Validate and Submit

Before submitting, validate to preview issues:

```
chorus_tool_execute({ toolName: "chorus_pm_validate_proposal", arguments: { proposalUuid: "<proposal-uuid>" } })
```

Returns `{ valid, issues }` with error, warning, and info levels. Fix errors before submitting.

When validation passes:

```
chorus_tool_execute({ toolName: "chorus_pm_submit_proposal", arguments: { proposalUuid: "<proposal-uuid>" } })
```

This changes the status from `draft` to `pending`. An Admin will review it (see `chorus-review`).

Add a comment explaining your reasoning:

```
chorus_tool_execute({ toolName: "chorus_add_comment", arguments: {
  targetType: "proposal",
  targetUuid: "<proposal-uuid>",
  content: "This proposal covers... Key decisions: ..."
} })
```

### Step 6: Handle Feedback

After submission in OpenCode, the plugin auto-launches `proposal-reviewer` when reviewer gating is enabled and waits for the current VERDICT or timeout. If the VERDICT is **FAIL**, or an Admin rejects the proposal, you need to revise and resubmit.

**IMPORTANT:** A proposal in `pending` status cannot be edited. You **must** reject it first to return it to `draft` status before editing any drafts.

1. **Read feedback:**
   ```
   chorus_tool_execute({ toolName: "chorus_get_proposal", arguments: { proposalUuid: "<proposal-uuid>", section: "full" } })
   chorus_tool_execute({ toolName: "chorus_get_comments", arguments: { targetType: "proposal", targetUuid: "<proposal-uuid>" } })
   ```
   Identify BLOCKERs from the reviewer VERDICT or rejection note.

2. **Reject the proposal** (self-reject your own, or ask admin to reject someone else's):
   ```
   chorus_tool_execute({ toolName: "chorus_pm_reject_proposal", arguments: {
     proposalUuid: "<proposal-uuid>",
     reviewNote: "Reviewer FAIL. Fixing BLOCKERs: <list>"
   } })
   ```
   This returns the proposal to `draft` status. PM agents can only reject their own proposals; admin agents can reject any proposal.

3. **Revise the drafts** (write updated content to staging files first, then upload via `contentPath`):
   ```
   chorus_tool_execute({ toolName: "chorus_pm_update_document_draft", arguments: { proposalUuid: "<proposal-uuid>", draftUuid: "<uuid>", contentPath: "<chorus-staging-dir>/prd.md" } })
   chorus_tool_execute({ toolName: "chorus_pm_update_task_draft", arguments: { proposalUuid: "<proposal-uuid>", draftUuid: "<uuid>", ... } })
   ```

4. **Resubmit:**
   ```
   chorus_tool_execute({ toolName: "chorus_pm_submit_proposal", arguments: { proposalUuid: "<proposal-uuid>" } })
   ```

### Step 7: Post-Approval

When the Admin approves:
- Document drafts become real Documents
- Task drafts become real Tasks (status: `open`, ready for developers)
- The Idea's displayed status is automatically derived from Proposal and Task progress -- no manual update needed

### Step 8: Manage Task Dependencies (Optional)

After tasks are created, you can manage dependencies:

**Batch create tasks with intra-batch dependencies:**

```
chorus_tool_execute({ toolName: "chorus_create_tasks", arguments: {
  projectUuid: "<project-uuid>",
  tasks: [
    { draftUuid: "draft-db", title: "Create database schema", priority: "high", storyPoints: 2 },
    { draftUuid: "draft-api", title: "Implement API endpoints", priority: "high", storyPoints: 4, dependsOnDraftUuids: ["draft-db"] },
    { title: "Write integration tests", priority: "medium", storyPoints: 2, dependsOnDraftUuids: ["draft-api"] }
  ]
} })
```

**Add/remove dependencies on existing tasks:**

```
chorus_tool_execute({ toolName: "chorus_update_task", arguments: { taskUuid: "<task-B-uuid>", addDependsOn: ["<task-A-uuid>"] } })
chorus_tool_execute({ toolName: "chorus_update_task", arguments: { taskUuid: "<task-B-uuid>", removeDependsOn: ["<task-A-uuid>"] } })
```

Dependencies are validated: same project, no self-dependency, no cycles (DFS detection).

### Step 9: Assign Tasks to Agents With `task:write` (Optional)

```
chorus_tool_execute({ toolName: "chorus_pm_assign_task", arguments: { taskUuid: "<task-uuid>", agentUuid: "<developer-agent-uuid>" } })
```

- Task must be `open` or `assigned`
- Target agent must have the `task:write` permission

---

## Document Writing Guidelines

### PRD Structure
```markdown
# PRD: <Feature Name>

## Background
Why this feature is needed.

## Requirements
### Functional Requirements
- FR-1: ...

### Non-Functional Requirements
- NFR-1: ...

## User Stories
- As a user persona, I want an action, so that I get a benefit

## Out of Scope
What is NOT included.
```

### Tech Design Structure
```markdown
# Technical Design: <Feature Name>

## Overview
High-level approach.

## Architecture
System design, component interactions.

## Data Model
Schema changes, new tables.

## API Design
New/modified endpoints.

## Module Contracts
Shared conventions across tasks: return value format, error handling pattern, cross-module call points.

## Implementation Plan
Step-by-step implementation order.

## Risks & Mitigations
Potential issues and how to address them.
```

### Task Writing Guidelines

Good tasks are:
- **Module-scoped** — One cohesive functional module per task, not a single function or file
- **Testable** — Clear, cohesive acceptance criteria (max 6 items per task; group related checks into one criterion but list key coverage, e.g. "All tests pass: service layer unit tests, API integration tests, edge case handling")
- **Sized** — 1-8 story points (hours of agent work)
- **Ordered** — Use `dependsOnDraftUuids` / `dependsOnTaskUuids` to express execution order
- **Descriptive** — Include enough context for a developer agent to start without questions. For tasks with cross-module dependencies, reference the tech design's Module Contracts in the AC
- **Integration checkpoints** — For DAGs with 4+ tasks, include at least one integration checkpoint task at a convergence point whose AC requires end-to-end execution of preceding modules together
- **Hallucination-aware** — When tasks involve external dependencies, note in the task description that developers should verify specifics (API signatures, CLI flags, config keys, model IDs, etc.) against official docs rather than relying on LLM memory

### Task Granularity

Each task should correspond to an **independently runnable and testable functional module** — not a single function, file, or API endpoint. Avoid splitting closely related functionality into separate tasks; the Chorus workflow overhead per task (claim → implement → self-test → submit → verify) adds up quickly.

**Bad → Good examples:**
- Bad: `Book Search` + `Book CRUD` (2 tasks) → Good: `Book Management` (1 task covering CRUD + Search for the same entity)
- Bad: `Chart Rendering` + `Statistics Calculation` (2 tasks) → Good: `Data Analytics` (1 task covering stats + visualization as one module)

---

## Tips

- Keep PRD focused on *what* and *why*; tech design focused on *how*
- Break large features into cohesive module-scoped tasks — but avoid over-splitting related functionality into too many tiny tasks
- Add `storyPoints` to help prioritize and estimate effort
- Keep acceptance criteria cohesive — group related verifications into one item rather than listing each check separately
- Always set up task dependency DAG — tasks without dependencies are assumed parallelizable
- When multiple tasks share data formats or call each other, define contracts in the tech design before writing task AC
- When combining multiple ideas, explain how they relate in the proposal description

---

## Next

- After submission, an Admin will review using `chorus-review`
- After approval, Developers claim tasks using `chorus-develop`
- For Idea elaboration, see `chorus-idea`
- For platform overview, see `/chorus`
