feat(symphony): tracker-agnostic orchestrator plugin
Sketch of a Claude Code port of openai/symphony — a daemon-style
orchestrator that polls an issue tracker, dispatches isolated worker
agents per issue, and reconciles state across ticks. Tracker-agnostic
by design: the project's CLAUDE.md documents how to talk to whatever
tracker is in use (GitHub Issues, Gitea, tracker CLI, Linear, etc.);
the plugin reads those instructions rather than shipping per-tracker
adapters.
Includes:
- /symphony-init for first-time setup (detects gh/gitea/tracker, writes
the tracker section into project CLAUDE.md, drops WORKFLOW.md, offers
to schedule the tick)
- /symphony-tick fired by /schedule cron entries (idempotent, silent,
never prompts)
- per-issue worker agent in isolated worktrees
- on-disk state in .symphony/state.json (survives cron cold starts)
Known divergences from the spec are documented in the plugin CLAUDE.md
(no streaming agent telemetry; no codex.* knobs; hooks run inside the
worker rather than the orchestrator).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:03:21 -05:00
|
|
|
---
|
|
|
|
|
# Pick the tracker your project uses. Symphony does not care which —
|
|
|
|
|
# it asks the project's CLAUDE.md how to talk to it.
|
|
|
|
|
#
|
|
|
|
|
# github — `gh` CLI
|
|
|
|
|
# gitea — gitea MCP server
|
|
|
|
|
# tracker — local `.tracker/` CLI (see tracker-usage skill)
|
|
|
|
|
# linear — Linear MCP / GraphQL
|
|
|
|
|
# <yours> — anything, as long as your CLAUDE.md documents it
|
|
|
|
|
tracker:
|
|
|
|
|
kind: github
|
|
|
|
|
active_states: [open]
|
|
|
|
|
terminal_states: [closed]
|
|
|
|
|
|
|
|
|
|
polling:
|
|
|
|
|
interval_ms: 60000
|
|
|
|
|
|
|
|
|
|
workspace:
|
|
|
|
|
root: ~/.symphony/workspaces
|
|
|
|
|
|
|
|
|
|
hooks:
|
|
|
|
|
after_create: |
|
|
|
|
|
git fetch origin
|
|
|
|
|
git checkout -b "{{ issue.branch_name | default: issue.identifier }}"
|
|
|
|
|
before_run: |
|
|
|
|
|
# project-specific install/setup
|
|
|
|
|
test -f package.json && npm install --silent || true
|
|
|
|
|
test -f pyproject.toml && uv sync || true
|
|
|
|
|
after_run: |
|
|
|
|
|
# advisory — never blocks the tick
|
|
|
|
|
true
|
|
|
|
|
timeout_ms: 120000
|
|
|
|
|
|
|
|
|
|
agent:
|
|
|
|
|
max_concurrent_agents: 3
|
|
|
|
|
max_turns: 30
|
|
|
|
|
max_retry_backoff_ms: 600000
|
|
|
|
|
max_concurrent_agents_by_state:
|
|
|
|
|
"in progress": 2
|
2026-04-29 21:51:23 -05:00
|
|
|
# Worker heartbeat cadence — affects how quickly other Symphony sessions
|
|
|
|
|
# (Discord triggers, webhooks, separate user sessions) detect abandoned
|
|
|
|
|
# workers. Defaults are safe; tighten if you have many concurrent sessions.
|
|
|
|
|
heartbeat_interval_ms: 60000 # workers refresh the heartbeat at most this often
|
|
|
|
|
heartbeat_stale_ms: 300000 # reconciler treats heartbeats older than this as abandoned
|
feat(symphony): tracker-agnostic orchestrator plugin
Sketch of a Claude Code port of openai/symphony — a daemon-style
orchestrator that polls an issue tracker, dispatches isolated worker
agents per issue, and reconciles state across ticks. Tracker-agnostic
by design: the project's CLAUDE.md documents how to talk to whatever
tracker is in use (GitHub Issues, Gitea, tracker CLI, Linear, etc.);
the plugin reads those instructions rather than shipping per-tracker
adapters.
Includes:
- /symphony-init for first-time setup (detects gh/gitea/tracker, writes
the tracker section into project CLAUDE.md, drops WORKFLOW.md, offers
to schedule the tick)
- /symphony-tick fired by /schedule cron entries (idempotent, silent,
never prompts)
- per-issue worker agent in isolated worktrees
- on-disk state in .symphony/state.json (survives cron cold starts)
Known divergences from the spec are documented in the plugin CLAUDE.md
(no streaming agent telemetry; no codex.* knobs; hooks run inside the
worker rather than the orchestrator).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:03:21 -05:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
You are working on issue **{{ issue.identifier }}** — {{ issue.title }}.
|
|
|
|
|
|
|
|
|
|
{% if attempt %}This is retry attempt {{ attempt }}. Review prior worktree commits and
|
|
|
|
|
pick up where the last attempt stopped.{% endif %}
|
|
|
|
|
|
|
|
|
|
## Issue body
|
|
|
|
|
|
|
|
|
|
{{ issue.description }}
|
|
|
|
|
|
|
|
|
|
## Labels
|
|
|
|
|
|
|
|
|
|
{{ issue.labels | join: ", " }}
|
|
|
|
|
|
|
|
|
|
## Your job
|
|
|
|
|
|
|
|
|
|
1. Implement the change on branch `{{ issue.branch_name | default: issue.identifier }}`.
|
|
|
|
|
2. Add or update tests covering the new behavior. Run them.
|
|
|
|
|
3. Commit referencing `{{ issue.identifier }}`.
|
|
|
|
|
4. Push the branch and open a PR.
|
|
|
|
|
5. Comment on the issue with the PR link, then transition the issue to a "review" state.
|
|
|
|
|
Use the commands documented in this project's CLAUDE.md under the issue tracker
|
|
|
|
|
section — the plugin does not know your tracker's quirks.
|
|
|
|
|
|
|
|
|
|
If you cannot finish in your turn budget, leave a status comment on the issue summarizing
|
|
|
|
|
progress and stop. Do not transition state.
|