Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ This repo **is** the dev-team Claude Code plugin and its marketplace. Do not sca
## Layout

- `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
- `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
- `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
- `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
- `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/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)
- `hooks/` β€” tiny SessionStart announcement; refreshes check-in scripts
- `.claude-plugin/` β€” `plugin.json` (no version field: every commit is an update) + `marketplace.json`

Expand Down
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ Projects driven from Orca can opt into a second runtime ([`workflow/orca.md`](wo

**Check-ins** (`/dev-team:checkins`) are scheduled Orca automations defined in the workspace's `standards/checkins.md` β€” e.g. keep work moving every 30 minutes, catch stalled or failed work hourly, have the product-manager groom tickets assigned to you each weekday. Each starts with a free trigger check, so an idle project costs nothing; each reuses its session so it keeps its bearings (a run still re-sends that session, so check-in sessions are kept small). Optional extras: mirror `status.md` onto Orca's worktree board (with an unread flag when you're needed), and Orca's built-in browser for UI checks in place of Playwright.

## Owner board (optional)

With several roles running at once, the orchestrator's conversation moves too fast to follow, and the workspace documents are written for agents. The **Owner board** ([`workflow/board.md`](workflow/board.md)) is a live, private claude.ai page for you: questions and approvals waiting on you first, then who is on what, then every piece of work in flight with its PR, state, and next step. The orchestrator updates it in the same turn as `status.md`, and removes a question the moment you answer it; a token-free script (`bin/board-drift`) catches PRs that merged, failed, or went ready on their own. Works with either runtime. Set it up with `/dev-team:board`.

<picture>
<source media="(prefers-color-scheme: dark)" srcset="examples/board/board-dark.png">
<img alt="Owner board with sample data: two questions waiting on the Owner, seven roles and their current tasks, and work grouped as Reporting, Mobile and Platform with ticket, PR, state and next step." src="examples/board/board-light.png">
</picture>

## Ticket systems (optional)

Work can come from Linear, Jira, GitHub Issues and Projects, or any tracker enabled through MCP β€” or through Orca's built-in Linear client or the `gh` CLI, which need no MCP server β€” configured per project in the workspace's `standards/tickets.md` (off by default; rules in [`workflow/tickets.md`](workflow/tickets.md)). The tracker is the **source of work and the record of outcomes**; agents still work and talk through the workspace, which is cheaper than MCP round-trips. A ticket is read once at intake and its ID carried in the PRD, fix record, and status row; phase changes sync its status; and only what the config's **Elevation** allowlist names goes back out β€” a release comment, high-priority bugs β€” never findings, questions, or task notes. Only the orchestrator and product-manager write to the tracker.
Expand Down Expand Up @@ -117,9 +126,10 @@ Validate with `claude plugin validate .`
| Path | What | Updatable |
|---|---|---|
| `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 | βœ… 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 and the coordinator lock (Orca runtime) | βœ… via plugin update |
| `bin/` | Check-in trigger scripts, the coordinator lock and `peer` (Orca runtime); `board-drift` (Owner board) | βœ… 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 |
| `examples/board/` | Owner board sample data and screenshots | βœ… via plugin update |
53 changes: 53 additions & 0 deletions bin/board-drift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""List Owner-board work rows whose state no longer matches their GitHub PR (workflow/board.md).

Usage: board-drift <dir> [owner/repo]
<dir> holds the board's `work` rows as JSON files, saved by an ArtifactData `list` of collection `work` with
`out_dir`, so reading the board costs almost nothing. A row's own `repo` wins; otherwise the argument, otherwise
this checkout's GitHub repo. Prints one line per row to fix (exit 1), or "board in sync" (exit 0). Uses `gh`.
"""
import glob, json, os, subprocess, sys

FAIL = ("FAILURE", "TIMED_OUT", "STARTUP_FAILURE", "ERROR", "ACTION_REQUIRED")


def gh(*a):
try:
return subprocess.run(["gh", *a], capture_output=True, text=True, timeout=60).stdout
except (OSError, subprocess.TimeoutExpired):
return ""


if len(sys.argv) < 2:
sys.exit(__doc__)
default_repo = sys.argv[2] if len(sys.argv) > 2 else gh("repo", "view", "--json", "nameWithOwner",
"-q", ".nameWithOwner").strip()
drift = []
for f in sorted(glob.glob(os.path.join(sys.argv[1], "**", "*.json"), recursive=True)):
d = json.load(open(f))
row, doc = d.get("data", d), os.path.basename(f)[:-5]
state, pr = row.get("state"), row.get("pr")
if not pr or state == "done":
continue
try:
p = json.loads(gh("pr", "view", str(pr), "-R", row.get("repo") or default_repo,
"--json", "state,isDraft,statusCheckRollup") or "{}")
except ValueError:
p = {}
if not p:
drift.append(f"{doc}: PR #{pr} not found β€” check the row")
continue
failed = any((c.get("conclusion") or c.get("state") or "").upper() in FAIL for c in p.get("statusCheckRollup") or [])
want = None
if p["state"] in ("MERGED", "CLOSED"):
want = f"done (PR {p['state'].lower()})"
elif failed and state not in ("fixing", "owner", "blocked"):
want = "fixing (a check failed" + (", draft)" if p["isDraft"] else ")")
elif p["isDraft"] and state == "ready" and not failed:
want = "building or review (the PR is a draft)"
elif not p["isDraft"] and state in ("building", "fixing", "planning", "queued") and not failed:
want = "ready or review (the PR is ready and no check failed)"
if want:
drift.append(f"{doc}: board says {state}, should be {want} [#{pr}]")
print("\n".join(drift) if drift else "board in sync")
sys.exit(1 if drift else 0)
30 changes: 30 additions & 0 deletions commands/board.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
description: Set up or refresh the Owner board β€” a live claude.ai page of what needs the Owner, who is on what, and work in flight.
argument-hint: "[change, e.g. 'link tickets to Jira']"
---

`<ws>` below is the workspace root: `source "${CLAUDE_PLUGIN_ROOT}/bin/_workspace.sh" . && echo $WS`.

Set up the project's Owner board. Rules: `${CLAUDE_PLUGIN_ROOT}/workflow/board.md`.

Request: $ARGUMENTS

1. **Preconditions.** This session has the `Artifact` and `ArtifactData` tools (claude.ai artifacts). Otherwise stop and say so; under the Orca runtime, the worktree-card board (`workflow/orca.md` Β§ Board) is the lighter fallback.

2. **New or refresh.** The dev-team section (`CLAUDE.md`, or `CLAUDE.local.md` in guest mode) has an `**Owner board:** <url>` line β†’ refresh: read that artifact (`Artifact` `read`) and republish the current template to the same URL in step 4, omitting `capabilities` so its data and rules carry over. Otherwise create a new board.

3. **Config** β€” ask once, offering defaults, and keep current values on a refresh unless the request changes them:
- **Project name** for the title (default: the repository's folder name).
- **How the board names the Owner** in "Waiting on …" (default `you`).
- **Ticket link base**, with the ticket ID appended: from `<ws>/standards/tickets.md` Β§ Scope when a system is configured β€” Linear `https://linear.app/<workspace>/issue/`, GitHub `https://github.com/<owner/repo>/issues/`, Jira `https://<site>/browse/` β€” else none (IDs show as plain text).
- **Repository** for PR links: `gh repo view --json nameWithOwner -q .nameWithOwner`.

4. **Publish.** Copy `${CLAUDE_PLUGIN_ROOT}/templates/board.html` to the scratchpad, replace both `{{PROJECT}}` with the project name, and publish it with the `Artifact` tool: icon `board`, a one-line description, and on a new board `capabilities: {"db": {"rules": [{"path": "", "read": "view", "write": "owner"}]}, "user": {}}` β€” viewers read, only the Owner (and the coordinator writing as them) changes data.

5. **Seed** with one `ArtifactData` `batch`: `meta/config` (`owner`, `ticketUrl`, `repo` β€” omit empty ones), `meta/board.updated`, one `work` row per `<ws>/status.md` row, one `asks` row per pending βœ‹ gate or feature blocked on the Owner, and `peers` rows (`peer list` under Orca). A new board with nothing in flight starts empty.

6. **Verify.** `ArtifactData` `list` each collection and confirm the rows match `<ws>/status.md`.

7. **Record.** New board: add `- **Owner board:** <url> β€” the orchestrator keeps it current (dev-team workflow/board.md).` to the dev-team section. Show the diff; write on approval.

8. Give the Owner the link and offer to pin it (`Artifact` `pin`) β€” it is a page they will keep reopening.
Binary file added examples/board/board-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/board/board-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions examples/board/sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"meta/config": { "ticketUrl": "https://example.com/tickets/", "repo": "acme/app" },
"asks": [
{ "id": "a1", "order": 1, "ticket": "APP-214", "question": "Approve the saved-searches PRD? It adds email alerts, which the ticket did not ask for." },
{ "id": "a2", "order": 2, "ticket": "APP-231", "question": "May dt-dev-2 record 10 seconds of real microphone audio in the emulator? Fake audio passes; real audio is the open question." }
],
"peers": [
{ "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-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-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)" },
{ "id": "APP-226", "group": "Mobile", "group_order": 2, "ticket": "APP-226", "title": "Offline drafts", "peer": "dt-dev-3", "pr": 412, "state": "fixing", "next": "Two review findings, then a delta review" },
{ "id": "APP-222", "group": "Mobile", "group_order": 2, "ticket": "APP-222", "title": "Notification settings", "pr": 405, "state": "ready", "next": "Reviewed and green: merge when you like" },
{ "id": "APP-228", "group": "Platform", "group_order": 3, "ticket": "APP-228", "title": "Rate limits per API key", "peer": "dt-reviewer", "pr": 418, "state": "review", "next": "Security checks first, then limits" },
{ "id": "APP-233", "group": "Platform", "group_order": 3, "ticket": "APP-233", "title": "Audit log retention", "state": "queued", "next": "Starts after APP-228" },
{ "id": "APP-224", "group": "Platform", "group_order": 3, "ticket": "APP-224", "title": "Upgrade Node to 22", "pr": 401, "state": "done", "next": "Merged" }
]
}
1 change: 1 addition & 0 deletions skills/bootstrap/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ git log --oneline -1 2>/dev/null; ls docs CLAUDE.md CLAUDE.local.md 2>/dev/null
- **Autonomy:** `supervised`, `standard` (default), or `autonomous`, plus any gates to keep (`${CLAUDE_PLUGIN_ROOT}/workflow/handoffs.md` Β§ Autonomy).
- **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.
- **Design tool:** Figma, Penpot, or another tool with an MCP server? Yes β†’ fill `<ws>/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`):
Expand Down
2 changes: 1 addition & 1 deletion skills/orchestrator/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Paths: `<ws>` is the workspace root, `<feature>` the current feature's folder
Traffic control: decide who acts next and where the work runs, verify prerequisites, keep `<ws>/status.md` accurate. Coordination only β€” this role owns no phase artifact. Runs in the main conversation; it is a set of rules, not an agent.

## Boundaries
- **Owns** `<ws>/status.md` and `<ws>/status-done.md` β€” one row per feature in flight: phase, current role, blockers, approvals, path. The only files this role writes; with a ticket system enabled, it also makes the intake, status-sync, and release-comment writes `<ws>/standards/tickets.md` allows (`${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`).
- **Owns** `<ws>/status.md` and `<ws>/status-done.md` β€” one row per feature in flight: phase, current role, blockers, approvals, path. The only files this role writes; with a ticket system enabled, it also makes the intake, status-sync, and release-comment writes `<ws>/standards/tickets.md` allows (`${CLAUDE_PLUGIN_ROOT}/workflow/tickets.md`). With an **Owner board** line in the project, it keeps the board current in the same turn as `<ws>/status.md` (`${CLAUDE_PLUGIN_ROOT}/workflow/board.md`).
- **Never:** write code or phase artifacts, answer another role's domain questions, approve anything on the Project Owner's behalf (sole exception: the release an *autonomous* level delegates to it), route past a missing gate.
- **Escalate:** missing approval β†’ the gate's approver (Owner or delegate); question open past its Required By date β†’ Project Owner; ambiguous pipeline state β†’ Project Owner, never guess.

Expand Down
Loading
Loading