references/ensure-store.md
# Ensure the current project has an orchestra store
This plugin is installed once. Do **not** copy skills, rules, or this
repo into the work project. Store selection comes from the versioned
`.canon/store-binding.json`; `.canon/config.json` contains store mechanics.
Project verification and landing policy comes from the root `orchestra.toml`.
In this repository,
records live in the shared SQLite database outside the worktree. Planning
commands opened from any worktree use that same database.
Requires `canon` and `orchestra` on PATH. Call both by name. Never
resolve a checkout path or a plugin root to run them.
## Which store
Dashboard and `orchestra store` resolve one SQLite database for this
repository under `~/.canon/<repo-name>/`. The tracked
`.canon/store-binding.json` selects `{"store":"global"}`, so every
worktree uses the same records. `.canon/config.json` selects the SQLite
backend, and `.canon/schemas/` keeps the schema snapshots used for
validation.
Run `canon` from any worktree in this repository. Do not pass a checkout
path or a plugin path to select the database. Use `orchestra store path`
to inspect the resolved location.
Run `canon backup` to create a retained backup in the repository's
`~/.canon/<repo-name>/backups/` directory before maintenance. SessionStart checks
the newest backup and creates one when it is older than 24 hours.
## Runtime commands
These are named commands, not files inside a checkout:
- `canon` writes and reads store records. `canon apply <file>` runs
many create, update, supersede, and correct operations from NDJSON
in one call.
- `orchestra handoff`, `orchestra view plan|status|verification`, and
`orchestra brief <work-item>` print derived views. They write no
files.
- `orchestra check` and `orchestra close-batch` run acceptance and
close work.
- `orchestra analyze <phase-slug>` checks a phase's specification,
work-items, and acceptances for consistency. It writes no files.
- `orchestra review-brief` builds the phase-end reviewer brief.
`orchestra suite policy`, `orchestra suite start`,
`orchestra suite poll`, `orchestra suite collect`, and
`orchestra suite record` run the configured phase suite and write
its check-run.
- `orchestra store path` prints the resolved store;
`orchestra store run -- <args>` runs `canon` against it.
- `orchestra verify` judges a claim in `.tuner/manifest.json`.
Do not hardcode a plugin directory or a home checkout in a command.
## Reference fields
A payload field that names another record holds that record's
**subject**, never its `rec-…` id. This covers `effort`, `milestone`,
`phase`, `work_item`, `assignment`, `acceptance`, and each entry of
`depends_on`. For example, an execution-report sets
`"work_item":"<task-slug>"`.
`canon` checks every reference when it writes. A write fails when no
record of the target type has that subject. Write the target record
first. An empty string skips the check.
Pinned fields take a record id instead: `informed_by` and
`contradicted_by` (JSON arrays of ids). The check-run `criterion_id`
is a plain string: an acceptance id, or a phase-level criterion such
as `<phase-slug>-review` or `<phase-slug>-suite`.
List fields are JSON arrays: `requirements`, `decisions`, `test_ids`,
`oracle_hashes`, `failing_node_ids`, `claim_ids`, `old_hashes`,
`new_hashes`, `merged_from`, `depends_on`.
## First run in a work repo
A store is marked by `.canon/config.json`. If it exists, the store
is ready. Do not run `init` again.
If it does not exist, run this from the work repo:
```bash
canon init --schemas score,conductor,tuner
```
`canon init` needs a git repo. If cwd is not git, say so and stop. Do
not write a plan document or extra skill copies.
After you upgrade orchestra or tuner, bring the store schemas up
to date:
```bash
canon schemas sync
```
`canon` validates against the schema snapshots in
`.canon/schemas/`, not against the installed tools.
## Project policy
The root `orchestra.toml` is required for project policy. Its `[suite]`
section controls the phase suite:
```toml
[suite]
mode = "none"
command = ""
gate = "required"
```
Read it with `orchestra suite policy`. Do not waive it. A human changes
`[suite]` in `orchestra.toml`. Keep `.canon/config.json` for store format,
schema versions, backend, and related store mechanics.
## Store records and commits
Records are stored in the SQLite database outside the Git worktree.
Database writes are not Git changes and must not be staged or committed.
The config, binding, and schema snapshots under `.canon/` are versioned
metadata and should be committed with code changes when they change.
A record edited by hand, outside the runtime, fails validation:
```
record revision tamper detected: .canon/records/.../rec-....md
```
Fix that by redoing the edit through `canon update` rather than by
hand-patching the file.
references/intent-qa.md
# Intent Q&A
Use this guide during specification and design work. Read relevant context
before you ask the user for information.
## Read
- Read the active phase, its prerequisites, and current effort context.
- Read the approved specification before design work.
- Read relevant code and system constraints before technical questions.
- Read existing decisions, constraints, and assessments that affect the phase.
Do not ask the user to repeat information already present in the current
records or code.
## Reflect
State the user's goal in plain terms. Separate known facts from assumptions.
Name the decisions that can change behavior, cost, scope, or recovery.
Ask an open question when a necessary fact is unknown. Offer concrete options
only when the user must choose between real alternatives.
## Ask
Ask one focused question at a time. Say why the answer changes the result.
Keep choices distinct and include the practical trade-off for each.
Do not ask about implementation details before you check the code or current
technical facts. Research unstable or unfamiliar facts before asking the user
to choose a preference.
## Test answers
Check each answer against the goal, current records, constraints, and earlier
answers. Name conflicts and ask about the smallest unresolved choice.
Preserve settled choices unless the user changes them.
Do not infer approval from silence, a partial answer, or a request to continue.
Ask for approval of the complete specification or design before recording it.
## Present once
After the open choices are settled, present the complete proposed artifact.
State its scope, assumptions, invariants, risks, and unresolved items. Ask for
approval or explicit delegation to record it.
After the user approves, write only the artifact owned by the current step.
Record the matching workflow review only when the user explicitly approves or
delegates. Do not create work-items from either discussion step.
references/kinds-and-focus.md
# Kinds and focus
Shared rules for every orchestra skill. Do not invent extra skills for
bugs, one-offs, or evals.
## Kinds
`kind` is `deliver` | `repair` | `evaluate` | `incidental`. Put it on
`score:effort` and each `work-item`. Missing `kind` means
`deliver`.
| Kind | Unknown | Done | Records |
|---|---|---|---|
| `deliver` | how | change + binary check | work-item + acceptance + check-run |
| `repair` | what is wrong | cause + repro gone | those, plus observation / finding |
| `evaluate` | whether it holds / which is better | campaign result | check-run if binary; finding if comparative or inconclusive |
| `incidental` | usually nothing | change landed | none, or one work-item (see below) |
`acceptance.method` stays `tdd` | `check` | `manual`; `verify_command`
holds the literal command that backs it (empty string for a `manual`
check with no script). Do not stuff a metric delta into
`check-run.result`. Use `tuner:finding` (`claim`, `basis`,
`invalidated_when`, `needs`).
`executor` on a work-item is `inline` or `subagent`. Every task in a
wave uses the same executor. Missing `executor` means `subagent`.
The phase body includes a `## Landing` section with branch
`phase/<phase-slug>`, worktree
`<repo>/.worktrees/<phase-slug>`, base `main`. When Landing is
present and the phase gate holds, commit the phase branch from the
phase worktree. Then run `orchestra land --phase <phase-slug>`. Land
runs `orchestra gate` first and runs the land adapter only when the
gate holds. The Landing section names branch, worktree, base and repo
only. `orchestra.toml` `[land]` and `[suite]` configure the adapter and
the suite. Merge stays human. On a non-zero exit, stop and ask.
Incidental work has no Landing section. A phase body that omits
Landing is not ready for plan review.
## Focus
A **live** goal is a `score:effort` in lifecycle `active` whose
`payload.status` is not `closed` (missing means open).
### Closing and reopening
`status` (`open` | `closed`) on `score:effort` and `score:position`
says whether an effort is live. It is a payload field, not the
lifecycle. Closing and reopening both `supersede` the effort's goal and
position with the new `status`; `supersede` merges the payload, so the
other fields carry over.
- **Close** only when the user says no more phases follow.
`run` asks when an effort's last phase is done. An effort
whose phases and tasks are all done is "finished" on the dashboard,
but it stays open until the user closes it.
- **Reopen** when work returns to a closed effort: supersede its goal
and position with `status: open`, then add the phase. Never create a
second goal with a closed effort's subject.
Closed goals do not show in views. Find them with:
```bash
canon list --type score:effort --state active --where payload.status=closed
canon supersede --type score:effort --id <goal-id> \
--expected-revision <revision> --payload '{"status":"open"}'
canon supersede --type score:position --id <position-id> \
--expected-revision <revision> --payload '{"status":"open"}'
```
Focus is a **subject string**, not a record. Name it (from `engage`, the
user, or the only live `score:effort` subject). Then:
- Read `orchestra handoff --effort <focus>` and the focus's phases in
`orchestra view plan --effort <focus>`.
- Ignore other live goals. Do not supersede `score:effort` or
`score:position` that belongs to another effort.
- Task-scoped records (`work-item`, `acceptance`, `check-run`,
`decision`, `failed-attempt`, `investigation-observation`, `finding`,
`assignment-amendment`, `execution-report`) use
`subject` = task slug and `payload.effort` = focus. Skills write no
`assignment`; the `in_progress` work-item update carries `assignee`
and `write_root`.
- Goal, the effort position, and continuity-question use `subject` =
focus. A phase has its own position only for a note a person must
read: `subject` = phase slug, `scope` = `phase`, `payload.effort` =
focus. Phase progress is derived from work-item states. Each chat
writes only its own phase's position; the effort position changes
when a phase closes.
An effort is a product area or objective, not one ask. New work in
an area a live goal already covers is a new phase of that effort. A
new effort is a new subject only when no live goal covers the area.
Create its goal/position. Leave the others active.
Hierarchy inside an effort:
- **milestone** (`score:milestone`) — optional time-bounded outcome
that groups phases (e.g. cutover, harden). Payload: `title`,
`ordinal`, `effort`. Not a focus subject; focus stays the effort.
- **phase** (`score:phase`) — one settle → plan → execute → verify
loop. Optional payload `milestone` references a milestone subject.
Phase `ordinal` is effort-scoped (not reset per milestone).
Skills stay phase-scoped. A milestone is a grouping and done-gate for
its phases, not a second chat focus.
## Incidental
- Fits this chat and is not an interrupt of another live effort: **no
records**. Do the work in this session.
- May span chats, or it interrupts a live phase: one `work-item` +
`acceptance`, `kind=incidental`, `phase=""` (no phase record exists
for incidental work; canon checks a non-empty `phase` against
real `score:phase` subjects and skips an empty string), `effort` = a **new** subject (not the interrupted effort).
Work-item `subject` may equal that effort slug when there is only one
task. Do not supersede the main goal.
## Needs-you clears
Human-dismissible Needs-you kinds are `blocking-question`,
`open-question`, `needs-human`, and `unsigned-check` only (not
loop-route, integration, or merge-branch). When the user settles one
in an agent session, the parent session clears that source at the
event — the same CLI outcomes the dashboard dismiss uses. Do not keep
a separate dismiss cache.
| Kind | Source | Clear at the event |
|---|---|---|
| `blocking-question` / `open-question` | `score:continuity-question` still open | `update --transition answered` |
| `needs-human` | active `tuner:finding` with `needs` `human` | `update` with `needs` `none` |
| `unsigned-check` | latest `method=manual` `tuner:check-run` with empty `signed_by` | `correct` setting `signed_by` |
```bash
canon update --type score:continuity-question --id <question-id> \
--transition answered --expected-revision <revision>
canon update --type tuner:finding --id <finding-id> \
--expected-revision <revision> \
--payload '{"needs":"none"}'
canon correct --type tuner:check-run --id <check-run-id> \
--payload '{"signed_by":"<signer>"}'
```
Findings advertise a supersedes relationship but have no superseded
lifecycle state, so clear with `update` (same as dashboard dismiss).
Signer identity comes from config, env, or a short prompt.
## Writing rules
- **Capture at the event.** Write the record when the decision,
observation, or commitment happens. Do not batch writes for session
end or write them from memory.
- **One writer per store.** Only the parent session calls `canon` in
any form that writes. Subagents return evidence in their response
text and never call `canon` or edit `.canon/`. This holds for
every executor mode, including a read-only one: that mode names what
an executor may read, it does not make the store multi-writer.
- **Views are derived.** Records are the authority. Render views with
`orchestra handoff`, `orchestra view plan|status|verification`, and
`orchestra brief <work-item>`. They print to stdout and write no
files. A view may lag a record; read the record before you act on a
claim.
- **Validate before finishing.** Run `canon validate` and fix every
error. The Stop hook runs the same check and blocks on new errors.
- **Follow the lifecycle.** `supersede` a `current` record (new id);
never `update` it to `superseded`. Event records stay `recorded`;
`correct` writes a successor. A stale `--expected-revision` is a
rejected write: re-read, then retry. Never hand-edit a record file.
- **Read by relevance.** Route by focus, then phase. Never bulk-read
the store.
references/verification-policy.md
# Verification method and oracle policy
Choose `method` separately from `oracle_policy`. Record both choices during planning.
| Method | Oracle policy | Evidence needed to close |
|---|---|---|
| `tdd` | `none` | Runner-produced red before runner-produced green |
| `check` | `none` | Passing runner check |
| `tdd` | `frozen` | Assertion-level red, green, and matching frozen hashes |
| `check` | `frozen` | Green and matching frozen hashes; no red required |
| `manual` | `none` | Human sign-off |
`manual` with `frozen` is invalid. An approved oracle amendment can authorize hash changes.
Manifest claims also retain their separate verdict and recheck gates.
## Select and record
Prefer `tdd` for behavior where a failing test helps define the contract.
Prefer `check` for documentation, packaging, and final verification.
Select `frozen` when independent tests against a stable interface justify the authoring cost.
Bug reproductions and compatibility contracts are good candidates.
Do not select frozen oracles for every deliver or repair task automatically.
A phase can set `oracle_policy` to `none` or `frozen`. The default is `none`.
An acceptance can override that default. Stamp the resolved `oracle_policy` on every new acceptance.
A phase default is a planning convenience; explicit acceptance policy fixes the choice for execution.
Existing acceptance freeze metadata still selects `frozen` when explicit policy is absent.
Never remove existing hashes or set `none` to bypass an existing freeze.
Reject partial freeze metadata, `none` with freeze metadata, and `frozen` without complete metadata.
An ordinary acceptance has `oracle_policy: none` and omits `test_ids` and `oracle_hashes`.
Its tests need not exist during planning. An executor writes unfrozen TDD tests during execution,
records red through `orchestra check`, implements the behavior, and records green.
An import or collection failure does not prove that an assertion detects incorrect behavior.
For a new API, create the minimum importable interface and confirm a behavior failure before implementing that behavior.
## Selected frozen acceptances
Skip oracle authoring when no acceptance selects `frozen`.
Otherwise use one independent oracle-author for only the selected frozen acceptances.
The author receives requirement text and the method, not implementation hints.
For frozen `tdd`, require assertion-level red before freezing.
For frozen `check`, tests can pass when authored; red is not required.
Create the acceptance with its policy, test ids, and hashes together.
Do not silently change selected policy when authoring cannot meet its contract.
## Changes during execution
The parent remains the only store writer. Require explicit parent approval before changing an acceptance's method or oracle policy.
The executor reports a proposed change and its reason. It does not weaken the verification contract itself.
Frozen file changes use the existing oracle amendment approval path.
Every frozen hash change requires a parent-approved `tuner:oracle-amendment` record, including changes to manifest claims.
The parent creates or supersedes that record with the acceptance subject, effort, phase, old hashes, new hashes, and approval reason.
Close-batch accepts approved `tuner:oracle-amendment` records whose new hashes match the green tree.
For manifest claims, the parent also uses the signed manifest and verdict path.
Unfrozen tests can change during implementation, but the declared TDD red-first contract still applies.
SKILL.md
---
name: triage-ideas
description: >-
Lists open composer ideas that have no product area, presents each with
assign-area, create-area, dismiss, or leave options, and records the
user's choice. Use when the backlog needs area placement before engage
promotes an idea into work.
---
# Triage ideas
Requires `canon` and `orchestra` on PATH and a live orchestra store. If
missing, follow [ensure-store.md](references/ensure-store.md). Follow
[kinds-and-focus.md](references/kinds-and-focus.md). Parent session writes
records. Subagents return text only.
Promotion into an effort is `engage`. This skill never sets status
`promoted`.
## Steps
1. Run `orchestra handoff` if the handoff was not injected.
2. List open ideas and keep those with no `area` in the payload:
```bash
canon list --type composer:idea --where payload.status=open --state active --full
```
When none remain, say so and stop.
3. List active areas:
```bash
canon list --type composer:area --state active --full
```
4. For each untriaged idea, show its subject, body, and source if any.
Present four options: assign an existing area, create a new area,
dismiss, or leave for later. Mark one option as recommended and say
why. The user decides. Use a question tool with one option per choice
when one is available.
5. When the user assigns an area, supersede the idea with that area slug:
```bash
canon supersede --type composer:idea --id <id> \
--expected-revision <revision> \
--payload '{"area":"<area-slug>"}'
```
6. When no area fits, create one, then assign it. The body must include
`## Scope`:
```bash
canon create --type composer:area \
--subject "<area-slug>" \
--payload '{"title":"<area-title>"}' \
--body-file "<area-body.md>"
canon supersede --type composer:idea --id <id> \
--expected-revision <revision> \
--payload '{"area":"<area-slug>"}'
```
7. When the user dismisses, supersede to `dismissed`:
```bash
canon supersede --type composer:idea --id <id> \
--expected-revision <revision> \
--payload '{"status":"dismissed"}'
```
8. When the user leaves an idea, make no write for it. Continue with the
next untriaged idea.
9. Run `canon validate`. Remind the user that starting work on a triaged
idea is `engage` (promote there, not here).
## Do not
- Set status `promoted` or supersede to `promoted`
- Start `spec`, `tasks`, or `execute` from this skill
- Let subagents write records
- Assign an area the user did not choose