diff --git a/CLAUDE.md b/CLAUDE.md index f90c93c..6033701 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This repo **is** the dev-team Claude Code plugin and its marketplace. Do not sca - `agents/` + `skills/` — the six roles (orchestrator is skill-only, no agent); each agent is a thin launcher — preloads its skill via `skills:`, sets effort and memory, pins no tools or model (skills are the single source of truth for role definitions) - `commands/` — `/dev-team:sync` seed-sync command; `/dev-team:tickets` ticket-system setup/tuning; `/dev-team:checkins` Orca check-in setup; `/dev-team:board` Owner board setup -- `bin/` — check-in trigger scripts and the coordinator lock, run by Orca automations (copied into each project's git dir by the hook); `peer`, the Orca coordinator's dispatch / tell / watch helper; `board-drift`, the Owner board's PR check +- `bin/` — check-in trigger scripts and the coordinator lock, run by Orca automations (copied into each project's git dir by the hook); `peer`, the Orca coordinator's dispatch / tell / watch helper; `board-drift`, the Owner board's PR check; `seed-drift`, sync's drift check - `templates/`, `workflow/` — framework reference shipped with the plugin, referenced via `${CLAUDE_PLUGIN_ROOT}`; `workflow/handoffs.md` is the canonical home of gate-validity rules, `workflow/adoption.md` of existing-project adoption rules, `workflow/orca.md` of the optional Orca runtime, `workflow/tickets.md` of ticket-system rules, `workflow/board.md` of the Owner board - `seeds/` — files the `bootstrap` skill copies into consuming projects (standards, stack, status, backlog index, project CLAUDE.md); project-owned after copy - `examples/workspace/` — worked example (one feature folder plus its ADR) referenced by the skills; `examples/board/` — Owner board sample data and README screenshots (made-up data only) diff --git a/README.md b/README.md index 5b73bd3..655fbec 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Plugin updates never touch project-owned files, so a project bootstrapped before - **Moves** an older type-first workspace to feature folders (dry run first, then `git mv` with links rewritten) - **Copies** any seed file the project is missing (standards, `stack/stack.md`, `status.md`, `status-done.md`, the backlog index and archive) and creates any missing folders -- **Reports drift** in existing standards: lists seed sections (`##` headings) absent from your project's copy, ignoring your customizations +- **Reports drift** (`bin/seed-drift`): seed sections (`##` headings) absent from your standards, seed rules absent from the project's dev-team section, and Orca Runtime-line settings renamed or added since — names only, so your customizations never show up as drift - **Appends only what you approve** — never overwrites, rewrites, or deletes project content After a sync, fill placeholders in newly copied files and commit them to your project repo. @@ -128,7 +128,7 @@ Validate with `claude plugin validate .` | `agents/`, `skills/` | The six roles (orchestrator is skill-only) + bootstrap skill | ✅ via plugin update | | `commands/` | `/dev-team:sync` — pull missing/updated seeds into a project; `/dev-team:tickets` — ticket-system setup/tuning; `/dev-team:checkins` — Orca check-ins; `/dev-team:board` — Owner board | ✅ via plugin update | | `templates/`, `workflow/` | Document templates, pipeline/handoff/communication rules | ✅ via plugin update | -| `bin/` | Check-in trigger scripts, the coordinator lock and `peer` (Orca runtime); `board-drift` (Owner board) | ✅ via plugin update | +| `bin/` | Check-in trigger scripts, the coordinator lock and `peer` (Orca runtime); `board-drift` (Owner board); `seed-drift` (sync) | ✅ via plugin update | | `hooks/` | Session-start announcement + agent-memory size sentinel | ✅ via plugin update | | `seeds/` | Copied into projects by bootstrap/sync | ❌ project-owned after copy | | `examples/workspace/` | Worked example of the full pipeline, in the workspace layout | ✅ via plugin update | diff --git a/bin/seed-drift b/bin/seed-drift new file mode 100755 index 0000000..84bfa3c --- /dev/null +++ b/bin/seed-drift @@ -0,0 +1,47 @@ +#!/bin/bash +# seed-drift [project-dir] — what the plugin's seeds have that this project's copies lack (commands/sync.md step 4). +# Reports seed sections missing from /standards/*.md, seed rules missing from the dev-team section, and +# outdated Orca Runtime-line settings. Prints one line per finding (exit 1), or "up to date" (exit 0). +P=${1:-.} +PLUGIN=$(cd "$(dirname "$0")/.." && pwd) +source "$PLUGIN/bin/_workspace.sh" "$P" +found=0 +say() { echo "$1"; found=1; } +norm() { sed -e 's/^## *//' -e 's/ *(.*) *$//' | tr '[:upper:]' '[:lower:]'; } + +# 1. Standards: seed "## " sections the project's copy lacks. "(active)" and case don't count. +for seed in "$PLUGIN"/seeds/standards/*.md; do + f="$P/$WS/standards/$(basename "$seed")" + [ -f "$f" ] || continue + have=$(grep '^## ' "$f" | norm) + while IFS= read -r h; do + printf '%s\n' "$have" | grep -qxF "$(printf '%s\n' "$h" | norm)" || + say "standards/$(basename "$seed"): missing section \"${h#\#\# }\"" + done < <(grep '^## ' "$seed") +done + +# 2. The dev-team section: seed rules (bold labels under "## Rules") it lacks. Guest mode keeps it in CLAUDE.local.md. +section="$P/CLAUDE.md" +grep -qs '\*\*Workspace:\*\*' "$P/CLAUDE.local.md" && section="$P/CLAUDE.local.md" +if grep -qs -e '^# Development Organization' -e '\*\*Workspace:\*\*' "$section"; then + orca=$(grep -s 'Runtime: Orca' "$section") + label() { sed -n 's/^- \*\*\([^*:.]*\)[:.].*/\1/p'; } + have=$(label < "$section") + while IFS= read -r l; do + # Under the Orca runtime the Runtime line replaces the in-conversation rule. + [ -n "$orca" ] && [ "$l" = "Run roles in this conversation" ] && continue + printf '%s\n' "$have" | grep -qxF "$l" || say "$(basename "$section"): missing rule \"$l\"" + done < <(sed -n '/^## Rules/,/^## /p' "$PLUGIN/seeds/CLAUDE.project.md" | label) + + # 3. The Orca Runtime line: settings renamed or added since the project wrote it (workflow/orca.md § Opt in). + if [ -n "$orca" ]; then + case "$orca" in *"Peer clear threshold"*) + say "Runtime line: \"Peer clear threshold\" is now \"Peer size limit: 400k\" (a fresh session per task; the limit is the mid-task safety net)" ;; + *"Peer size limit"*) ;; + *) say "Runtime line: no \"Peer size limit\" (400k applies)" ;; + esac + case "$orca" in *"Board:"*) ;; *) say "Runtime line: no \"Board:\" setting (off applies)" ;; esac + fi +fi +[ $found = 0 ] && echo "up to date" +exit $found diff --git a/commands/sync.md b/commands/sync.md index e1b2865..ad07b15 100644 --- a/commands/sync.md +++ b/commands/sync.md @@ -1,5 +1,5 @@ --- -description: Sync plugin seeds into the project workspace — moves an old type-first layout to feature folders, copies missing files, reports seed sections missing from existing standards. Never overwrites. +description: Sync plugin seeds into the project workspace — moves an old type-first layout to feature folders, copies missing files, reports seed sections, rules, and settings an existing project lacks. Never overwrites. --- Sync this project's workspace with the plugin's seeds. Seeds are **project-owned after copy** — never overwrite or modify an existing project file without explicit approval. Layout and settings: `${CLAUDE_PLUGIN_ROOT}/workflow/workspace.md`. @@ -29,8 +29,8 @@ cp -n "${CLAUDE_PLUGIN_ROOT}/seeds/standards/"*.md "$WS/standards/" **Guest mode** (the dev-team section is in `CLAUDE.local.md`): copy only the process standards — `planning.md`, `documentation.md`, `review.md`. Code conventions (`coding.md`, `testing.md`, `architecture.md`, `design.md`) come from the repo itself; copy one only if the repo documents nothing on that subject and the Owner wants it. `tickets.md` and `checkins.md` are never copied here — `/dev-team:tickets` and `/dev-team:checkins` add them when enabled. -4. **Drift check** on files that already existed: for each `$WS/standards/*.md` with a same-named seed, compare `##` headings. List seed headings absent from the project file — sections added to the plugin since the project's copy. Ignore all other differences (project customizations always win). +4. **Drift check** on what already existed: `"${CLAUDE_PLUGIN_ROOT}/bin/seed-drift" .` lists what the plugin added since the project's copies were made — seed sections missing from `$WS/standards/*.md`, seed rules missing from the dev-team section (`CLAUDE.md`, or `CLAUDE.local.md` in guest mode), and Orca Runtime-line settings renamed or added (`${CLAUDE_PLUGIN_ROOT}/workflow/orca.md` § Opt in). It compares names only; every other difference is a project customization and always wins. -5. **Report** four lists: **moved** (step 2), **copied** (was missing), **up to date**, **behind** (seed headings missing — name them). For each "behind" file, offer to append the missing sections verbatim; append only what the user approves. Never delete or rewrite existing content. +5. **Report** four lists: **moved** (step 2), **copied** (was missing), **up to date**, **behind** (each `seed-drift` line). For each behind item, offer the fix: append a missing section verbatim from its seed, append a missing rule bullet verbatim from `${CLAUDE_PLUGIN_ROOT}/seeds/CLAUDE.project.md`, or update the Runtime line to the setting it names. Apply only what the user approves. Never delete or rewrite existing content beyond that. 6. Remind the user to fill placeholders in newly copied files and to commit — to the project repo, or, for an uncommitted workspace, nothing to do: the Stop hook commits the workspace's own repository. diff --git a/examples/board/board-dark.png b/examples/board/board-dark.png index 456e17d..77319a6 100644 Binary files a/examples/board/board-dark.png and b/examples/board/board-dark.png differ diff --git a/examples/board/board-light.png b/examples/board/board-light.png index 051bcb8..9e1f0b1 100644 Binary files a/examples/board/board-light.png and b/examples/board/board-light.png differ diff --git a/examples/board/sample.json b/examples/board/sample.json index b738ee0..296d641 100644 --- a/examples/board/sample.json +++ b/examples/board/sample.json @@ -8,13 +8,14 @@ { "id": "dt-product", "order": 1, "name": "dt-product", "role": "product-manager", "doing": "APP-214 saved searches: PRD waiting on you" }, { "id": "dt-designer", "order": 2, "name": "dt-designer", "role": "designer", "doing": "APP-219 onboarding checklist: mockups" }, { "id": "dt-architect", "order": 3, "name": "dt-architect", "role": "principal-engineer", "doing": "Idle" }, - { "id": "dt-dev-1", "order": 4, "name": "dt-dev-1", "role": "senior-developer", "doing": "APP-207 CSV export: T03 of 4" }, + { "id": "dt-dev-1", "order": 4, "name": "dt-dev-1", "role": "senior-developer", "doing": "APP-207 CSV export: #420 writer, stacked on #409" }, { "id": "dt-dev-2", "order": 5, "name": "dt-dev-2", "role": "senior-developer", "doing": "APP-231 voice notes: waiting on the mic go" }, { "id": "dt-dev-3", "order": 6, "name": "dt-dev-3", "role": "senior-developer", "doing": "APP-226 fixing review findings on #412" }, { "id": "dt-reviewer", "order": 7, "name": "dt-reviewer", "role": "reviewer", "doing": "Reviewing #418, APP-228 rate limits" } ], "work": [ - { "id": "APP-207", "group": "Reporting", "group_order": 1, "ticket": "APP-207", "title": "CSV export for invoices", "peer": "dt-dev-1", "pr": 409, "state": "building", "next": "T03 streaming writer, then T04" }, + { "id": "APP-207-query", "group": "Reporting", "group_order": 1, "ticket": "APP-207", "title": "CSV export: invoice query", "peer": "dt-dev-1", "pr": 409, "state": "ready", "next": "Reviewed and green: merges with #420, not alone" }, + { "id": "APP-207-writer", "group": "Reporting", "group_order": 1, "ticket": "APP-207", "title": "CSV export: streaming writer (stacked on #409)", "peer": "dt-dev-1", "pr": 420, "state": "building", "next": "T04, then review; merges with #409" }, { "id": "APP-214", "group": "Reporting", "group_order": 1, "ticket": "APP-214", "title": "Saved searches", "peer": "dt-product", "state": "owner", "next": "PRD approval (Needs you)" }, { "id": "APP-219", "group": "Reporting", "group_order": 1, "ticket": "APP-219", "title": "Onboarding checklist", "peer": "dt-designer", "state": "planning", "next": "Mockups to the PM for approval" }, { "id": "APP-231", "group": "Mobile", "group_order": 2, "ticket": "APP-231", "title": "Voice notes on Android", "peer": "dt-dev-2", "pr": 415, "state": "owner", "next": "Recording go (Needs you)" }, diff --git a/seeds/standards/coding.md b/seeds/standards/coding.md index 99cf703..01d6823 100644 --- a/seeds/standards/coding.md +++ b/seeds/standards/coding.md @@ -23,6 +23,14 @@ Footer, when needed: `Refs: /tasks/index.md`, `Closes: #`. One commit per coherent unit of work: a task, a batch of tasks completed together, or one fast-path fix. Never mix pipeline work with unrelated fixes. +## Stacked PRs (active when `gh stack` is installed) +Applies when `gh extension list` shows `github/gh-stack`. Who syncs what is decided by what is in flight, not fixed: adapt as stacks form and change. + +- **Build on unmerged work; don't wait for the merge.** A task that depends on work whose PR has not merged builds on that PR's branch as a stacked PR: `gh stack checkout ` (or `gh stack init `), `gh stack add `, commit, then `gh stack submit --auto` (new PRs open as drafts) and set the real title. +- **Each PR is reviewed on its own diff.** Its base is the branch below it; that branch's head is the Review manifest's base commit. +- **A stack merges together, bottom up,** once every PR in it is reviewed and green. A green lower PR never merges alone: `main` stays shippable for anyone releasing. +- **Keeping branches current — the owner syncs by default.** Your own stack (every branch yours): `gh stack sync`, which rebases and force-pushes the whole stack with lease. A stack shared with others: bring only your branch up to date — merge the branch below into it and push — and never run `gh stack sync`, which would rewrite their branches. When many hands share stacks, the orchestrator (the coordinator under Orca) may name one **stack keeper** for a while: it brings lower changes up with merge commits only, never force-pushes, and tells each owner to pull. Say who syncs when a stack forms, and change it when the stack changes. + ## Naming _TBD — casing, file naming, module naming._ diff --git a/seeds/standards/review.md b/seeds/standards/review.md index 4c8aa84..eb10478 100644 --- a/seeds/standards/review.md +++ b/seeds/standards/review.md @@ -18,5 +18,11 @@ - **standard** — diff review with targeted caller checks. - **deep** — the work contains a major decision: trace every changed public interface's callers; line-by-line on security-sensitive paths. Set by the Principal Engineer in the task index. +## Review order (active) +For changes that touch access, money, or existing data, check in this order and record each step in the review: +1. **Security** — who can read or change what, before and after. Probe base and head with a real request where possible, not only by reading. +2. **Breakage** — callers, existing data, existing connections and integrations. +3. **Cost** — performance and spend. + ## Checklists _TBD — per-project checklist (security, performance, accessibility…)._ diff --git a/seeds/standards/testing.md b/seeds/standards/testing.md index fdd329b..cbe27c2 100644 --- a/seeds/standards/testing.md +++ b/seeds/standards/testing.md @@ -7,6 +7,9 @@ - The Senior Developer runs the full suite before marking any task complete. - The Reviewer independently runs the suite during review. +## Behaviour changes (active) +Changes whose effect is statistical — prompts, model or tool choice, ranking, search relevance, performance — are accepted on a before/after run, never on reading the code: a fixed set of real cases, run several times on the base and on the branch; success checked against the system's real outcome (the database, not the reply); the cost (calls, failures, tokens, time); and an explicit list of what got worse. + ## Test types and coverage _TBD — unit/integration/e2e expectations, coverage thresholds._ diff --git a/skills/bootstrap/SKILL.md b/skills/bootstrap/SKILL.md index 5949231..ecd6219 100644 --- a/skills/bootstrap/SKILL.md +++ b/skills/bootstrap/SKILL.md @@ -51,6 +51,7 @@ git log --oneline -1 2>/dev/null; ls docs CLAUDE.md CLAUDE.local.md 2>/dev/null - **Ticket system:** Linear, Jira, GitHub, or another tracker? Yes → run `${CLAUDE_PLUGIN_ROOT}/commands/tickets.md`. No → `/dev-team:tickets` enables it later. - **Orca:** does the Owner run Claude from Orca? Yes → add the Runtime line (`${CLAUDE_PLUGIN_ROOT}/workflow/orca.md` § Opt in) and offer `/dev-team:checkins`. - **Owner board:** a live page of what needs the Owner, who is on what, and work in flight — recommended when several roles run at once. Yes → run `${CLAUDE_PLUGIN_ROOT}/commands/board.md`. No → `/dev-team:board` sets it up later. + - **Stacked PRs:** `gh extension list` shows `github/gh-stack` → tell the Owner `/standards/coding.md` § Stacked PRs applies. Not installed → the section stays dormant; `gh extension install github/gh-stack` turns it on. - **Design tool:** Figma, Penpot, or another tool with an MCP server? Yes → fill `/standards/design.md` § Design tool. No → mockups are HTML in each feature's `mockups/`. 6. **Existing projects — harvest, then draw the line** (`workflow/adoption.md`): diff --git a/skills/orchestrator/SKILL.md b/skills/orchestrator/SKILL.md index 946e9e2..8dbb18e 100644 --- a/skills/orchestrator/SKILL.md +++ b/skills/orchestrator/SKILL.md @@ -19,6 +19,7 @@ Traffic control: decide who acts next and where the work runs, verify prerequisi `/status.md`; `/backlog/index.md` rows when asked what is waiting; artifact **headers only** — existence via Glob, approval via Grep (`Status:`, `Approved by`), Designer requirement via Grep for `## UX Direction` in the brief or PRD. Never read artifact bodies. ## Workflow +0. **Reports first.** A role's report that asks for a go — install, run, merge, record — is answered before anything else, in the same turn, and the answer recorded; the Owner should never be the one to find a role waiting on you. Pass the Owner's words on verbatim (`${CLAUDE_PLUGIN_ROOT}/workflow/communication.md` § Relaying the Owner). 1. Asked to pull work and a ticket system is enabled → run the config's work query and classify each ticket by its Routing, passing the ticket ID to the receiving role. Classify: bug/chore → Senior Developer fast path; small change or doc correction → the role owning the affected artifact (no gates, no status row); feature, ticket, or decision-changing work → Product Manager triage, which sets the path (`workflow/overview.md` § Paths); real but not now → a backlog item for the Product Manager (no status row until promoted). 2. Recommend where it runs: inline in this conversation by default; an agent only for concurrency, independent review, context relief, or a full phase of a role whose model the project pins differently from this session's — started with that role's model (`workflow/overview.md` § Models per role). Project `CLAUDE.md` declares **Runtime: Orca** → dispatch to top-level peers per `${CLAUDE_PLUGIN_ROOT}/workflow/orca.md` instead; never spawn subagents. 3. A feature whose `Approvals` column reads `pre-adoption` predates this organization: its upstream gates are waived, its downstream gates apply in full (`workflow/adoption.md`). Never route it back to fill in missing history. diff --git a/skills/principal-engineer/SKILL.md b/skills/principal-engineer/SKILL.md index 40043c3..fbb20f3 100644 --- a/skills/principal-engineer/SKILL.md +++ b/skills/principal-engineer/SKILL.md @@ -21,9 +21,9 @@ Approved brief or PRD — only: Ask or Goals, User Stories, Acceptance Criteria, ## Workflow 1. Verify the handoff is valid (`workflow/handoffs.md`). -2. **Decide your phase** and record it on the Path: a plan when there are real design choices (data model, interfaces, more than one moving part); otherwise tasks straight from the brief, or one task. Unknowns block the choice → technical **discovery** first (`templates/discovery.md`). With a plan: tie each section to the acceptance criteria. Prefer existing patterns and stack capabilities over new construction — the smallest design that satisfies the criteria wins. Raise question docs for gaps; affected sections stay draft until answered. +2. **Decide your phase** and record it on the Path: a plan when there are real design choices (data model, interfaces, more than one moving part); otherwise tasks straight from the brief, or one task. Unknowns block the choice → technical **discovery** first (`templates/discovery.md`). **Risk-gated work** — access control or permissions, migrating existing data, renaming or removing a public interface — always starts with a risk discovery (its § Risk), written by you or a developer you call, verified by you against the code, and decided by the Owner as a major decision before any task is built. With a plan: tie each section to the acceptance criteria. Prefer existing patterns and stack capabilities over new construction — the smallest design that satisfies the criteria wins. Raise question docs for gaps; affected sections stay draft until answered. 3. Write ADRs for significant, hard-to-reverse decisions. -4. Break the plan into `/tasks/`: an `index.md` status table plus one `T-.md` file per task. Tasks are small — one sitting, one concern, independently verifiable — each listing dependencies, files, acceptance criteria, and testing. Every task traces to a plan element (or, without a plan, to acceptance criteria), every plan element maps to at least one task, and no task depends on a later one. A task that cannot be made small and verifiable signals a plan problem — fix the plan, not the task. Set the index's Review tier: **deep** when the work contains a major decision, **light** for a small change with no plan, **standard** otherwise. +4. Break the plan into `/tasks/`: an `index.md` status table plus one `T-.md` file per task. Tasks are small — one sitting, one concern, independently verifiable — each listing dependencies, files, acceptance criteria, and testing. Every task traces to a plan element (or, without a plan, to acceptance criteria), every plan element maps to at least one task, and no task depends on a later one. A task that cannot be made small and verifiable signals a plan problem — fix the plan, not the task. Dependent tasks that ship as separate PRs are built as a stack (`/standards/coding.md` § Stacked PRs). Changes whose effect is statistical (prompts, model or tool choice, ranking, performance) get a measurement task per `/standards/testing.md` § Behaviour changes. Set the index's Review tier: **deep** when the work contains a major decision, **light** for a small change with no plan, **standard** otherwise. 5. Debt the plan knowingly accepts — a simplification with a named upgrade path, a deferred refactor — is filed as a `debt` backlog item, never left in the plan as an intention. 6. Certify (`Approved by: Principal Engineer`; Outstanding Questions empty) — **unless** the plan contains a major decision (new dependency or stack change, data-model change affecting existing data, security-sensitive surface, anything irreversible, any ADR): take **that decision** to the Project Owner (✋) and certify the rest once decided. The project's autonomy level shifts who signs both (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Autonomy). Hand off to the Senior Developer. 7. **Assume mistakes** — yours and upstream's: self-review against the source before any handoff; question smells on receipt (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Assume mistakes). diff --git a/skills/product-manager/SKILL.md b/skills/product-manager/SKILL.md index d495f27..61b6d03 100644 --- a/skills/product-manager/SKILL.md +++ b/skills/product-manager/SKILL.md @@ -21,7 +21,7 @@ The feature request; existing PRDs, answered questions, `/status.md`, `/ ## Workflow 1. **Feasibility.** Can agents do this, given `/standards/planning.md` § Agent limits? **Human** → one row in `/triage.md` (ticket, decision, reason), tell the Owner, stop. **Split** → continue, listing the human steps as **Owner tasks**. Unsure → ask the Owner rather than guess. -2. **Triage.** Read the request (from a ticket: read it once and record `Ticket:` per `${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`) and related docs. Request already says what is wanted → **brief**. New product surface, several stakeholders, or unclear scope → **PRD** (split large features into several). Can't tell yet → product **discovery** first (`templates/discovery.md`). +2. **Triage.** Read the request (from a ticket: read it once and record `Ticket:` per `${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`) and related docs. Request already says what is wanted → **brief**. New product surface, several stakeholders, or unclear scope → **PRD** (split large features into several). Can't tell yet → product **discovery** first (`templates/discovery.md`). Work from an audit or a list (findings, a sweep, a checklist): an item is in scope only with evidence it is a real problem today — a reproduction, a failing case, a user report — and every item left out gets a one-line reason under Out of Scope. 3. Write it from its template, with testable acceptance criteria — never optional — and the **Path**: the phases you expect, each downstream role confirming or changing its own. A brief that outgrows itself becomes a PRD. 4. UI features: write **UX Direction** — the key experience decisions only; detail belongs to the Designer. Its presence makes the Designer phase mandatory, its absence routes to the Principal Engineer (`workflow/handoffs.md`). Record the route in the Handoff's Next Agent. 5. Record every unknown as an Open Question (question docs where another party must answer). diff --git a/skills/reviewer/SKILL.md b/skills/reviewer/SKILL.md index 030fd9e..0ca1572 100644 --- a/skills/reviewer/SKILL.md +++ b/skills/reviewer/SKILL.md @@ -24,8 +24,8 @@ The task index — statuses, completion notes (claims to verify), and its **Revi 2. Read the diff for the manifest's range (`git diff ...`) — this is the review scope. Expand only to the callers of a changed symbol when verifying an interface or behavior change (prefer symbol tools: find references). 3. Run the tests with the manifest's command (summary/quiet reporter); read failures only. Never trust claimed results. 4. Walk the criteria as a checklist — every task acceptance criterion, every brief or PRD acceptance criterion, UI behavior against the design spec (in a real browser — Orca's built-in browser under the Orca runtime, else a Playwright MCP server when available — never inferred from code) — verifying each with the smallest read; spot-check completion-note claims against the diff. PRD has a UX Direction section but no approved design spec → **Blocker**: the Designer phase was skipped. -5. Check standards compliance on the changed code, including comment noise (comments that narrate or restate code are a Minor finding). **Light tier** (small change, no plan) stops at criteria and tests plus a standards check of the changed lines only. **Deep tier** (the work contains a major decision) additionally traces every changed public interface's callers and reviews security-sensitive paths line by line. -6. Write the review: severity-classified findings citing location + violated criterion, the recommendation, and the **Reviewed range**. Blockers/Majors → Senior Developer, then a **delta re-review**: verify only the prior findings and the diff since the last reviewed head. Otherwise → the release decision, signed per the project's autonomy level (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Autonomy). +5. Check standards compliance on the changed code, including comment noise (comments that narrate or restate code are a Minor finding). **Light tier** (small change, no plan) stops at criteria and tests plus a standards check of the changed lines only. **Deep tier** (the work contains a major decision) additionally traces every changed public interface's callers and reviews security-sensitive paths line by line, in the order `/standards/review.md` § Review order sets — probing base and head with real requests where it can, not only by reading. +6. Write the review: severity-classified findings citing location + violated criterion, the recommendation, and the **Reviewed range**. Blockers/Majors → Senior Developer, then a **delta re-review**: verify only the prior findings and the diff since the last reviewed head. A commit pushed after your approval gets the same delta review (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Rules). Otherwise → the release decision, signed per the project's autonomy level (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Autonomy). 7. **Assume mistakes** — yours and upstream's: self-review against the source before any handoff; question smells on receipt (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Assume mistakes). A finding you cannot point to in the diff is your mistake, not the developer's. ## Example diff --git a/skills/senior-developer/SKILL.md b/skills/senior-developer/SKILL.md index 01a3ef0..3e026f1 100644 --- a/skills/senior-developer/SKILL.md +++ b/skills/senior-developer/SKILL.md @@ -21,6 +21,10 @@ Implement certified tasks exactly as specified — working code with tests, one - No abstractions beyond what the task names. The smallest diff that satisfies the criteria wins — in the right place; a small change in the wrong place is a second bug. - Comments only where the *why* is not obvious from the code — never narration, history, or commented-out code (`/standards/coding.md`). - Fix root causes, not symptoms: check every caller of anything you change — one guard in the shared function beats one per caller. +- External call fails locally → check the environment first with its cheapest call (credential identity, service health), using the project's documented credential source, before changing code. +- Work that depends on an unmerged PR stacks on it when `gh stack` is installed (`/standards/coding.md` § Stacked PRs). +- **Never poll CI.** Wait on checks with one blocking command run in the background (`gh pr checks --watch`) — never `/loop`, wake-ups, or repeated checks, which spend tokens all day. +- Microphone, camera, and screen are faked by default; a real recording needs the Owner's go (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` § Autonomy). Checks only the Owner can run get exact steps (`${CLAUDE_PLUGIN_ROOT}/workflow/communication.md` § Relaying the Owner). - Record deliberate simplifications (and the upgrade path) in the completion notes or fix record; file the follow-up as a `debt` backlog item, and a bug you find but must not fix here as a `bug` item (`/standards/planning.md`). ## Consumes @@ -34,7 +38,7 @@ Implement certified tasks exactly as specified — working code with tests, one 5. All tasks done → complete the Review manifest (head commit, test command with a summary/quiet reporter) and hand off to the Reviewer. ## Fast path (bugs and chores) -Delegated directly by the Project Owner — no PRD, plan, or tasks. From a ticket: read it once and record `Ticket:` (`${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`) — never write to it. Fix, test, and record in `/fixes/-.md` from `${CLAUDE_PLUGIN_ROOT}/templates/fix.md`. Guardrail: if the fix would change requirements, public interfaces, data models, or an ADR'd decision — stop and escalate; that is pipeline work. +Delegated directly by the Project Owner — no PRD, plan, or tasks. From a ticket: read it once and record `Ticket:` (`${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`) — never write to it. Fix, test, and record in `/fixes/-.md` from `${CLAUDE_PLUGIN_ROOT}/templates/fix.md`. Guardrail: if the fix would change requirements, public interfaces, data models, who can access what, or an ADR'd decision — stop and escalate; that is pipeline work. ## Example Implementing T02 from `${CLAUDE_PLUGIN_ROOT}/examples/workspace/features/user-authentication/tasks/`: touch only its listed files, match the plan's `PasswordHasher` interface, test hash/verify round-trip and short-password rejection — nothing more. diff --git a/templates/board.html b/templates/board.html index 6debec6..4edad6b 100644 --- a/templates/board.html +++ b/templates/board.html @@ -154,7 +154,12 @@

Work

for (const w of data.work) { const g = w.group || "Other"; if (!byGroup.has(g)) byGroup.set(g, []); byGroup.get(g).push(w); } const gOrder = [...byGroup.keys()].sort((a, b) => (byGroup.get(a)[0].group_order ?? 99) - (byGroup.get(b)[0].group_order ?? 99)); for (const g of gOrder) { - const rows = byGroup.get(g).sort((a, b) => ORDER.indexOf(a.state) - ORDER.indexOf(b.state) || (a.ticket || "").localeCompare(b.ticket || "")); + // Rows sharing a ticket (a stack, or one ticket in several PRs) stay together, placed by their most urgent row. + const rank = r => ORDER.indexOf(r.state); + const first = new Map(); + for (const r of byGroup.get(g)) { const k = r.ticket || r.id; first.set(k, Math.min(first.get(k) ?? 99, rank(r))); } + const key = r => first.get(r.ticket || r.id); + const rows = byGroup.get(g).sort((a, b) => key(a) - key(b) || (a.ticket || "").localeCompare(b.ticket || "") || (a.pr || 0) - (b.pr || 0)); const open = rows.filter(r => r.state !== "done").length; const tbody = el("tbody"); for (const r of rows) { diff --git a/templates/discovery.md b/templates/discovery.md index 9eb2f60..3180892 100644 --- a/templates/discovery.md +++ b/templates/discovery.md @@ -10,5 +10,8 @@ ## Findings +## Risk *(risk-gated work only — delete otherwise)* + + ## Recommendation diff --git a/tests/board.sh b/tests/board.sh index 7908537..47c64d1 100755 --- a/tests/board.sh +++ b/tests/board.sh @@ -81,6 +81,8 @@ else ok "render: owner state defaults to you" '[ "$(count ">Waiting on you<")" = 2 ]' ok "render: ticket links from config" '[[ $DOM == *"href=\"https://example.com/tickets/APP-207\""* ]]' ok "render: PR links from config repo" '[[ $DOM == *"href=\"https://github.com/acme/app/pull/409\""* ]]' + ok "render: stacked PRs, lower waits" '[[ $DOM == *"merges with #420, not alone"* ]] && [[ $DOM == *"https://github.com/acme/app/pull/420"* ]] && [[ $DOM == *"stacked on #409"* ]]' + ok "render: a stack stays together, bottom up" 'printf "%s" "$DOM" | python3 -c "import re,sys;d=sys.stdin.read();i,j=d.find(\"invoice query\"),d.find(\"streaming writer\");sys.exit(0 if 0<=i [workspace root]: a project whose dev-team section and standards match the seeds + rm -rf "$T/p"; mkdir -p "$T/p/${2:-docs}/standards" + cp "$REPO"/seeds/standards/*.md "$T/p/${2:-docs}/standards/" + sed "s|\`docs\` · features \`docs/features\`|\`${2:-docs}\` · features \`${2:-docs}/features\`|" \ + "$REPO/seeds/CLAUDE.project.md" > "$T/p/$1" +} +run() { OUT=$("$REPO/bin/seed-drift" "$T/p"); RC=$?; } +drop() { python3 -c 'import sys;p=sys.argv[1];s=open(p).read();assert sys.argv[2] in s;open(p,"w").write(s.replace(sys.argv[2],sys.argv[3]))' "$@"; } + +fresh CLAUDE.md; run +ok "seed copy is up to date" '[ $RC = 0 ] && [ "$OUT" = "up to date" ]' + +fresh CLAUDE.md +drop "$T/p/docs/standards/review.md" "## Review order (active)" "## Notes" +drop "$T/p/docs/standards/testing.md" "## Test types and coverage" "## TEST TYPES AND COVERAGE (customized)" +run +ok "missing section reported" '[ $RC = 1 ] && [[ $OUT == *"standards/review.md: missing section \"Review order (active)\""* ]]' +ok "renamed suffix or case is not drift" '[[ $OUT != *"Test types"* ]]' + +fresh CLAUDE.md +drop "$T/p/CLAUDE.md" "- **Build small.**" "- Keep it small:" +drop "$T/p/CLAUDE.md" "**Autonomy: standard.**" "**Autonomy: autonomous; Owner keeps: release.**" +run +ok "missing rule reported" '[[ $OUT == *"CLAUDE.md: missing rule \"Build small\""* ]]' +ok "changed rule value is not drift" '[[ $OUT != *Autonomy* ]]' + +fresh CLAUDE.md +drop "$T/p/CLAUDE.md" "- **Run roles in this conversation.**" "- **Runtime: Orca.** Roles run as Orca peers. Peer clear threshold: 25% of the peer's context window. Board: off. +- Old:" +run +ok "Orca: in-conversation rule not required" '[[ $OUT != *"Run roles in this conversation"* ]]' +ok "Orca: clear threshold rename reported" '[[ $OUT == *"\"Peer clear threshold\" is now \"Peer size limit: 400k\""* ]]' +drop "$T/p/CLAUDE.md" "Peer clear threshold: 25% of the peer's context window. Board: off." "Peer size limit: 300k." +run +ok "Orca: missing Board setting reported" '[[ $OUT == *"no \"Board:\" setting"* ]] && [[ $OUT != *"Peer size limit"* ]]' +drop "$T/p/CLAUDE.md" "Peer size limit: 300k." "Peer size limit: 300k. Board: on." +run +ok "Orca: current Runtime line is quiet" '[ $RC = 0 ]' + +fresh CLAUDE.md +drop "$T/p/CLAUDE.md" "- **Run roles in this conversation.**" "- Run roles here:" +run +ok "no Orca: in-conversation rule required" '[[ $OUT == *"missing rule \"Run roles in this conversation\""* ]]' + +fresh CLAUDE.local.md .dev-team +printf '# Their project\n\n- **Their own rule.** Something.\n' > "$T/p/CLAUDE.md" +drop "$T/p/.dev-team/standards/planning.md" "## Agent limits (active)" "## Limits" +run +ok "guest: workspace root from local file" '[[ $OUT == *"standards/planning.md: missing section \"Agent limits (active)\""* ]]' +ok "guest: their CLAUDE.md is not checked" '[[ $OUT != *"CLAUDE.md: missing"* ]]' + +rm -rf "$T/p"; mkdir -p "$T/p"; printf '# Some project\n\n- **Unrelated.** Rule.\n' > "$T/p/CLAUDE.md"; run +ok "no dev-team section, nothing to report" '[ $RC = 0 ] && [ "$OUT" = "up to date" ]' +exit $fail diff --git a/workflow/board.md b/workflow/board.md index 57be69e..9a8dcb2 100644 --- a/workflow/board.md +++ b/workflow/board.md @@ -22,6 +22,7 @@ A private claude.ai artifact with its own database. The page (`${CLAUDE_PLUGIN_R - **Same turn as `/status.md`.** Every status change, dispatch, settlement, and question routed to the Owner updates the board in the same turn — one `ArtifactData` `batch`, including `meta/board.updated`. The Owner trusts the board; a lagging one is worse than none. - **Asks come and go at once.** A question or approval for the Owner becomes an `asks` row the moment it is routed to them, and its work row goes to `owner`. The row is deleted in the turn the answer arrives. +- **Stacked PRs:** a row's `next` names its stack (`merges with #415 and #418`); a lower PR stays `ready` until the whole stack merges together (`/standards/coding.md` § Stacked PRs). - **Done rows** stay `done` until the Owner has seen them, then are deleted — at the latest the next day. - **Read cheaply, fix drift.** Read rows with an `ArtifactData` `list` using `out_dir` (files, not context). `${CLAUDE_PLUGIN_ROOT}/bin/board-drift ` prints the work rows whose PR moved on its own — merged, a failed check, marked ready — fix only those. Run it whenever the coordinator wakes (under Orca, after every `peer watch`) and before answering the Owner on status. - **Only the orchestrator writes.** Roles report through their normal channels; peers never touch the board. diff --git a/workflow/communication.md b/workflow/communication.md index db9951d..e0ce104 100644 --- a/workflow/communication.md +++ b/workflow/communication.md @@ -39,6 +39,11 @@ Never bypass the chain. Example: the Senior Developer must not ask the Project O - Be concise; link to documents instead of restating them. - One question per question document. +## Relaying the Owner + +- **The Owner's words travel verbatim.** When passing an Owner observation, decision, or answer to a role, quote it exactly, then add any interpretation separately and mark it as yours. A paraphrase sends the role after the wrong cause. +- **The Owner as the hands.** When a check needs the Owner — a device, an account, a physical step — the role writes exact steps: device and build, what to do or say, for how long, what to look for, and what to send back. The coordinator relays them unchanged. One thing per round. The role collects logs itself wherever it can (for example, a local-only diagnostic build that writes to a file) rather than asking the Owner to read them. + ## Plain language Everything a role writes — artifacts, notes, questions, summaries, commit messages — is read by people and re-read by agents. Neither needs padding. diff --git a/workflow/handoffs.md b/workflow/handoffs.md index 1aa77cd..f140f9e 100644 --- a/workflow/handoffs.md +++ b/workflow/handoffs.md @@ -31,6 +31,7 @@ Every artifact ends with a **Handoff** section containing exactly: - A PRD or brief containing a **UX Direction** section must flow through the Designer: any downstream handoff (plan, tasks, implementation) for it without a PM-approved design spec is invalid. This rule is canonical here — other documents reference it. - Outstanding Questions must be empty — or explicitly waived by the gate's approver — before downstream work starts. - The receiving agent verifies the Handoff section before starting; anything missing goes back to the producing agent as a question document, not a guess. +- **Approval covers a commit, not a branch.** A review approves the head of its Reviewed range. Any commit pushed after it gets a delta review of that diff — the tests for what changed, not the whole suite — before release or merge. The release approver checks that the reviewed head is the head being released. ## Autonomy @@ -46,7 +47,7 @@ How involved the Project Owner is, set per project by one line in the project `C | Requirement question | ✋ Owner (PM drafts the answer) | ✅ PM as proxy | ✅ PM as proxy | | Release (feature → Done) | ✋ Owner | ✋ Owner | ✅ Orchestrator, on *Approve* or *Approve with follow-ups* (follow-ups filed as backlog items) | -- **The floor stays with the Owner at every level**: anything irreversible or destructive (including data-model changes affecting existing data), security-sensitive surfaces (auth, permissions, secrets, PII), anything that spends money, and any action leaving the repository (deploy, publish, external messages). Release means *Done in `/status.md`*, never a deploy. Ticket-system writes that `/standards/tickets.md` allows are pre-authorized by that config (`workflow/tickets.md`), and Owner-board writes by turning the board on (`workflow/board.md`). +- **The floor stays with the Owner at every level**: anything irreversible or destructive (including data-model changes affecting existing data), security-sensitive surfaces (auth, permissions, secrets, PII), anything that spends money, any action leaving the repository (deploy, publish, external messages), and recording the Owner or their surroundings (microphone, camera, screen). Roles use fake devices by default; a command that switches a browser or emulator to the host's microphone counts as recording. A real recording needs the Owner's go for that one recording — what, where, how long — asked through the coordinator. Release means *Done in `/status.md`*, never a deploy. Ticket-system writes that `/standards/tickets.md` allows are pre-authorized by that config (`workflow/tickets.md`), and Owner-board writes by turning the board on (`workflow/board.md`). - **Overrides** follow the level: `Autonomy: autonomous; Owner keeps: PRD, release` holds named gates at ✋; `Owner waives: floor` delegates the floor too and must be written out explicitly. - **Record who decided**: an approval made because of the level reads `Approved by: (autonomy: )` in the artifact and `/status.md`, so the Owner can audit everything decided without them. - **Surface what was decided without the Owner.** When a feature reaches Done at any level below *supervised*, the Orchestrator's report lists, in a few lines, every decision the Owner did not sign for that feature: brief or PRD Assumptions, major decisions made by a role, and gates the level delegated. The audit trail is useless if nobody reads it. @@ -60,5 +61,6 @@ Every agent — you included — makes mistakes, and long sessions drift from th - **On receipt, question what smells.** An assignment can be wrong too — a request, a dispatch, a task, an upstream artifact. Smells: criteria that are untestable or contradict each other; a task that conflicts with the code, the plan, the standards, or the PRD's scope; a missing approval; a step that seems unnecessary or unexplained; an instruction that contradicts the documents (documents win). Blocking smell → question document to the owner (`workflow/communication.md`) and pause that item only; non-blocking → proceed and record it. Questioning is expected; deciding stays with the owner. - **Watch for drift.** Cannot state the acceptance criteria without looking, editing files the task does not name, or reversing an earlier decision → stop, re-read the sources, and if the session is long, end at a clean boundary so a fresh context continues. - **Hand over when you end mid-work.** Commit or push what is done, then write a **hand-over note** — done / state / left, a few lines each — in the task file's completion notes (fast path: the fix record), marked `partial`. The next session starts from that note, not from your context. +- **Clean up what you start** — containers, volumes, worktrees, test data, tokens — before reporting done, and list in the report what was removed or who still uses it. - **Stop at what you can't do.** Missing access, a step that needs a person, anything on the Agent limits list: mark the feature **blocked on Owner** with the exact ask (`/status.md` Blockers) — never guess, work around it, or fake the step. - **Approving is verifying.** A delegated or self-approval gets the same scrutiny as an Owner approval — never a rubber stamp. diff --git a/workflow/orca.md b/workflow/orca.md index c9e86d0..c2e3f2c 100644 --- a/workflow/orca.md +++ b/workflow/orca.md @@ -57,7 +57,7 @@ When the task index has independent chains, record the base commit in the Review - **Serialized** — the coordinator dispatches the next stream's merge only after the previous one settles. The peer brings its stream up to date with the feature branch, verifies, then advances the feature branch; it never overwrites another stream's merge. - **Tests only where code combined** — docs-only changes, or a feature branch that has not moved since the stream last tested: none. Other streams' code came in: the targeted tests covering the code both touched (`/standards/testing.md`). The full suite runs once, on the last merge. - **Trivial conflicts only** — its own lines and index/backlog rows. A real conflict with another stream's code means the plan's disjointness was wrong: question doc to the Principal Engineer, never a guessed resolution. -- **Last merge completes the Review manifest** (head commit, test command); the coordinator's spec says which merge is last. Then the Reviewer is dispatched and the stream homes are free. +- **Last merge completes the Review manifest** (head commit, test command); the coordinator's spec says which merge is last. Then the Reviewer is dispatched, the stream homes are free, and each stream's child worktree is removed once its merge is in. When an answered question lands in the feature worktree, the coordinator `peer tell`s the waiting stream to pull the feature branch.