.agents/skills/development-orchestrator/SKILL.md
Orchestrate the complete OpenSpec workflow — change creation, artifact authoring, worker dispatch, and review — in a single invocation with minimal user intervention.
npx skillsauth add em-jones/staccato-toolkit development-orchestratorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Drive the complete OpenSpec workflow from change creation to ready-to-archive in one invocation.
Maintainer note: The Rule-Coverage Audit, Quality Tooling Audit, and Radar Prerequisite Check sections in this skill duplicate logic from
openspec-ff-changeandopenspec-continue-change. The canonical descriptions live inopenspec-continue-change. If audit logic changes, update all three skills.
Input: A natural-language description (e.g., "add rate limiting to the API") or a kebab-case change name (e.g., add-rate-limiting). If no input is provided, ask one open-ended question before proceeding.
The development-orchestrator is responsible for ensuring the auditor agent stays alive. This is a passive check — do not block the workflow on it; perform the check opportunistically at the start of each session and at natural pause points (e.g., while waiting for workers).
.opencode/auditor/heartbeat.json
At session start AND after every worker batch completes, read the heartbeat:
cat .opencode/auditor/heartbeat.json 2>/dev/null
Parse last_run_utc. If the heartbeat is missing or stale (older than 15 minutes), the
auditor is considered dead.
HEARTBEAT_FILE=".opencode/auditor/heartbeat.json"
if [ ! -f "$HEARTBEAT_FILE" ]; then
echo "auditor: no heartbeat file — auditor not running"
AUDITOR_DEAD=true
else
LAST_RUN=$(python3 -c "
import json, datetime, sys
with open('$HEARTBEAT_FILE') as f:
hb = json.load(f)
last = datetime.datetime.fromisoformat(hb['last_run_utc'].replace('Z',''))
age = (datetime.datetime.utcnow() - last).total_seconds()
print('stale' if age > 900 else 'alive')
" 2>/dev/null || echo "stale")
AUDITOR_DEAD=$( [ "$LAST_RUN" = "stale" ] && echo true || echo false )
fi
If AUDITOR_DEAD=true, dispatch a new auditor subagent via the Task tool and announce it:
⚠ Auditor heartbeat stale or missing — restarting auditor agent
Dispatch with:
subagent_type: "auditor"description: "Restart auditor background loop"prompt: "Start the auditor cron loop. Load and follow the auditor skill immediately."Do NOT wait for the auditor to complete — it runs indefinitely. Fire and forget.
After dispatching, log the restart:
td log "Auditor restarted — previous heartbeat was stale or missing" 2>/dev/null || true
| Trigger | Action | |---|---| | Session start (before Step 1) | Check heartbeat; restart if dead | | After every worker batch (Step 5c) | Check heartbeat; restart if dead | | Before entering reviewer mode (Step 5d) | Check heartbeat; restart if dead |
td log so the history is visible in task contextIf no input provided, ask:
"What change do you want to work on?"
From the description, derive a kebab-case name (e.g., "add user authentication" → add-user-auth).
If the description is fewer than ~10 words or lacks a clear problem domain (e.g., "fix the thing"), ask one targeted clarifying question before deriving a name.
Announce the derived name before proceeding:
"Using change:
<name>"
Before making any changes, output:
## Autonomous Execution Plan
Change: <name>
Phases:
1. Create change & author all artifacts (proposal → specs → design)
2. Execute all implementation tasks
3. Review all submitted tasks
4. Notify when ready to archive
Proceeding...
Do NOT wait for confirmation — proceed immediately.
Check whether the change already exists:
openspec status --change "<name>" --json 2>/dev/null
If the change does NOT exist (non-zero exit or error): create it:
openspec new change "<name>"
Announce: "Created change: <name>"
If the change already exists: announce:
"Resuming change:
<name>" Show current artifact progress from the status output.
Follow the logic of openspec-ff-change exactly — including the rule-coverage audit. The td hierarchy produced MUST be identical to what openspec-ff-change would produce.
openspec status --change "<name>" --json
Note applyRequires (artifacts needed before implementation) and the full artifact list.
For each artifact with status: "ready":
Get instructions:
openspec instructions <artifact-id> --change "<name>" --json
Read dependency artifact files for context.
Create the artifact at outputPath using template as structure.
context and rules as constraints — do NOT copy them into the file.After creating the artifact, run the rule-coverage audit (see Rule-Coverage Audit below).
After the rule-coverage audit, run the quality tooling audit (see Quality Tooling Audit below).
Announce: ✓ Created <artifact-id>
Re-check status and continue until all applyRequires artifacts are done.
If clarification is needed during proposal authoring (description too vague for capability identification), ask one targeted question then continue without further interruption.
After writing each artifact, create the td hierarchy:
proposal.md:
td is initialized (td init if needed)td create "<change-name>" --type feature → capture <change-root-id>td board create "<change-name>" --query "descendant_of(<change-root-id>)"td-board, td-issue) to proposal.mdspecs/<capability>/spec.md (one per capability in proposal):
td create "<capability>" --type feature --parent <change-root-id> → <spec-id>td board create "<change-name>-<capability>" --query "descendant_of(<spec-id>)"td create "Implement: <req-name>" --type task --parent <spec-id> → link to spectd dep add <downstream-task-id> <upstream-task-id>
Use the requirement ordering implied by the spec narrative — earlier sections generally precede later ones. Only wire explicit dependencies; do not over-constrain.td-board, td-issue) to spec.mddesign.md:
td create "<task>" --type task --parent <change-root-id>td dep add <downstream-task-id> <upstream-task-id>
td-board, td-issue) to design.md pointing to the change rootAfter all applyRequires artifacts are complete, transition immediately into task execution — do NOT pause, summarize, or wait for any response.
Each capability in the proposal has a corresponding board created during artifact authoring, named <change-name>-<capability>. List all capability boards with open tasks:
td board list
Filter to boards matching <change-name>-* that have at least one task in open or in_progress status. Do NOT include boards whose only non-closed tasks are in_review — those streams are awaiting the orchestrator's review pass, not a new worker. These are the worker streams.
Prioritize streams with downstream dependents first: before dispatching, check which streams have tasks that other streams depend on:
# For each stream's spec-id, check if other tasks in the change depend on it
td deps <spec-id>
Order streams so that those with the most downstream dependents are dispatched first. If a stream has no open tasks because all are blocked on dependencies from another stream, skip it — do not dispatch a worker. It will become available on the next loop iteration once its dependencies are closed.
Announce:
## Executing: <change-name>
Streams (priority order):
- <change-name>-<capability-1> (N tasks, M downstream dependents)
- <change-name>-<capability-2> (K tasks)
⏸ <change-name>-<capability-3> (blocked — waiting on <capability-1>)
Dispatching workers...
Use the Task tool to dispatch one worker per stream simultaneously. Issue all Task tool calls in a single message — one per stream. Do NOT wait for one to finish before launching the next.
For each capability stream, call the Task tool with:
subagent_type: "worker"description: "Implement <change-name>-<capability> tasks" (5–10 words)prompt containing only:Your assigned feature: <spec-id>
If only one stream has open tasks, dispatch a single Task tool call (no parallelism needed — dispatch anyway for context isolation).
When a worker returns, perform three checks:
Log the worker's outcome before proceeding:
✓ Worker <change-name>-<capability> returned
Tasks submitted for review: N
Tasks still open: M (blocked or rejected)
Tasks closed: K
Then check whether any previously-blocked streams are now unblocked:
# For each stream that was skipped in 5a due to blocked dependencies:
td ls --ancestor <spec-id> --status open
If a previously-blocked stream now has open (unblocked) tasks, note it — it will be dispatched on the next 5a loop iteration.
Inspect descendant task statuses and advance the parent feature using the correct td state transition commands (the orchestrator owns feature status; workers own child task statuses):
td ls --ancestor <spec-id> --status all
| Child task state | Feature transition |
|---|---|
| ANY child in_progress or in_review | td start <spec-id> (if not already started) |
| ALL children closed | td approve <spec-id> |
| ANY child rejected (returned to open) | td reject <spec-id> (marks for rework) |
Do not attempt to set feature status directly — only use td start, td review, td approve, td reject.
After advancing feature status, check whether any open research tasks exist under the change root that are blocking implementation tasks:
td ls --ancestor <change-root-id> --status open --type task | grep "^Create rule:"
For each open research task found, dispatch a researcher subagent via the Task tool:
subagent_type: "researcher"description: "Create usage rules for <domain>" (5–10 words)prompt: the list of research task ids, e.g.:Your assigned task ids: <research-task-id-1> <research-task-id-2>
Dispatch all researcher tasks in a single message (parallel). Do not proceed to Step 5d until all researcher subagents have returned.
After ALL workers have completed (all tasks submitted for review), rotate to a new session:
td usage --new-session
The output lists all tasks awaiting review across all streams — use that as the review queue.
For each task in in_review:
td context <id>
Review the implementation against the relevant spec requirements and design decisions.
To approve:
td handoff <id> --done "Verified: <summary of what was confirmed>" --remaining "none"
td approve <id>
Announce: ✓ Approved #<id> <title>
To reject:
Query the dependency graph for tasks that depend on the task being rejected, then wire blockers before rejecting:
# Find all tasks that depend on this task (structured query — not grep)
td deps <id>
# For each dependent task returned, ensure the dependency is recorded
# (td dep add is idempotent — safe to re-run if already wired at creation time)
td dep add <dependent-task-id> <id>
# Reject the task
td handoff <id> --done "Review complete, rejected" --remaining "<specific actionable issues>"
td reject <id>
Announce: ✗ Rejected #<id> <title> → <reason> (include count of dependent tasks if any)
After reviewer mode, return to step 5a. Only dispatch workers for streams that have tasks that returned to open via rejection. Do NOT dispatch a worker for a stream where all remaining non-closed tasks are in_review — those are already queued for the next review pass, not for a new worker.
Repeat steps 5a–5d until all tasks on all streams are closed or a genuine blocker is hit.
After each rejection cycle, re-run the feature status evaluation and researcher dispatch check (5c) before rotating the session.
td board show "<td-board>"
Before declaring completion, check for open catalog tasks and open gate tasks:
td ls --board "<td-board>" --status open | grep "^Catalog:"
td ls --board "<td-board>" --status open | grep "^Gate:"
If open Catalog: tasks remain (all other implementation tasks are closed):
⚠ Implementation streams complete but catalog tasks remain: followed by the list of open taskssubagent_type: "worker", description: "Complete catalog tasks for <change-name>", prompt: "Your assigned feature: <change-root-id>") to dispatch a worker for the open catalog tasks, then re-evaluate completion (return to Step 5a)If open Gate: tasks remain (all implementation and catalog tasks are closed):
⚠ Implementation complete but prerequisite gate tasks remain open: followed by the list of open gate tasks with their prereq change namestd close <id>"If no open Catalog: or Gate: tasks (or none exist on the board):
Output:
## Execution Complete
**Change:** <change-name>
**Board:** <td-board>
**Progress:** all issues closed ✓
All tasks implemented and reviewed. Ready to archive — run `/opsx-archive`.
Do NOT autonomously archive. Archiving requires explicit user instruction.
Runs after the specs artifact and after the design artifact. Not optional — if .opencode/rules/patterns/README.md does not exist, warn and skip:
"⚠ Rule-coverage audit skipped:
.opencode/rules/patterns/README.mdnot found."
Identify relevant pattern domains from the capability spec and trigger conditions in .opencode/rules/patterns/README.md
For each domain, check:
ls .opencode/rules/patterns/<layer>/<domain>.md 2>/dev/null
Rule exists: link to each requirement task:
td link <req-task-id> .opencode/rules/patterns/<layer>/<domain>.md --role reference
Rule missing: create research task (once per change):
# Only if not yet created:
td create "research: <change-name>" --type feature --parent <change-root-id>
td create "Create rule: patterns/<layer>/<domain>.md" \
--type task --parent <td-research-id> \
--body "Needed by: <capability-name>
Triggered by: <reason>
Canonical ref: .opencode/rules/patterns/README.md#<domain>
Sources: <from canonical README entry>"
td dep add <req-task-id> <td-research-task-id>
De-duplicate: reuse an existing research task for this domain if one was already created in this run.
Show audit summary per capability.
Review ## Technology Adoption & Usage Rules table and explicit pattern decisions in design.md. For any implied domain not already covered by a specs-phase research task or existing rule, create a research task and wire td dep add to affected cross-cutting tasks.
Show rule-coverage supplement summary.
Then run the quality tooling audit design-phase supplement (see Quality Tooling Audit below). Show quality tooling supplement summary.
Then run the radar prerequisite check (see Radar Prerequisite Check below). Show radar prerequisite check summary.
Then run the skill audit: review the ## Agent Skills table in design.md. For each row with action create or update, ensure a task exists under the change root (create one if missing):
td create "Skill: <action> <skill-name>" --type task --parent <change-root-id>
td link <task-id> design.md --role reference
Show skill audit summary.
Runs after the specs artifact (per capability) and after the design artifact (design-phase supplement). Not optional — if tooling is missing, create parallel OpenSpec changes. Do NOT defer.
See Quality Tooling Pattern Rules for the definition of comprehensive tooling.
Identify the technologies introduced or used by this capability (from the spec).
For each technology, check whether linting, formatting, and testing are configured and running in CI.
All tooling present: link the rule to each requirement task:
td link <req-task-id> .opencode/rules/patterns/delivery/quality-tooling.md --role reference
Any kind missing: create one parallel OpenSpec change per missing kind:
openspec new change "add-<technology>-<kind>"
Create a completion-gate task on the main change (once per technology — de-duplicate):
td create "Gate: quality tooling in place for <technology>" \
--type task \
--parent <change-root-id> \
--body "Blocks completion. Satisfied when these changes are closed and passing:
- add-<technology>-<kind> (openspec change)"
De-duplicate: reuse an existing gate task for this technology if already created in this run.
Show audit summary per capability:
Quality tooling (capability: <cap> / <technology>):
✓ linting (exists in CI)
✓ formatting (exists in CI)
⚠ testing (missing) → openspec change add-<technology>-testing created, gate task td-xxxxx
Review ## Technology Adoption & Usage Rules table in design.md for any technologies not audited in the specs phase. For each new technology, repeat the tooling check. De-duplicate gate tasks.
Show design-phase quality tooling supplement summary.
The radar prerequisite check ensures that every direct dependency declared in the ## Technology Adoption & Usage Rules table either exists in the Tech Radar at ring Adopt, or has a prerequisite change to adopt it. It runs once during design authoring, after the ## Technology Adoption & Usage Rules table is populated and after the quality tooling audit design-phase supplement.
After design.md is created and the ## Technology Adoption & Usage Rules table is populated, after the quality tooling audit design-phase supplement and before the skill audit.
If docs/tech-radar.json does not exist, warn and skip:
"⚠ Radar prerequisite check skipped:
docs/tech-radar.jsonnot found."
Then continue without creating gate tasks.
For each non-n/a row in the ## Technology Adoption & Usage Rules table:
Extract the technology name from the Domain column (first column).
Check current radar — perform case-insensitive lookup of the name in docs/tech-radar.json entries array:
Adopt: report ✓ <name> (Adopt) and continue to next row.Trial, Assess, or Hold: report ⚠ <name> (<ring>) — on radar but not Adopt; proceeding and continue to next row. No gate task or prerequisite change is created (ring progression is human-driven).If NOT in radar, check existing changes — search all design.md files under openspec/changes/ (both active and archive/) for any whose tech-radar frontmatter block contains an entry with a matching name (case-insensitive):
Capture the change directory name as <prereq-name>
Create a gate task (check for duplicates first — if a gate task with this exact title already exists, skip creation):
td create "Gate: <prereq-name> complete" \
--type task \
--parent <change-root-id> \
--body "Blocks completion. Prerequisite change <prereq-name> must be archived before this change can be archived."
Link the gate task to design.md:
td link <gate-task-id> design.md --role reference
Report: ⚠ <name> — not in radar; existing change <prereq-name> adopts it → gate task <gate-task-id>
Continue to next row.
If NOT in radar and no existing change, spawn new change:
Derive change name: adopt-<technology-kebab-case> (e.g., adopt-chi, adopt-otel-go-sdk)
Check whether openspec/changes/adopt-<name> already exists:
⚠ adopt-<name> already existsopenspec new change "adopt-<name>"Create a gate task (check for duplicates first):
td create "Gate: adopt-<name> complete" \
--type task \
--parent <change-root-id> \
--body "Blocks completion. Prerequisite change adopt-<name> must be archived before this change can be archived."
Link the gate task to design.md:
td link <gate-task-id> design.md --role reference
Report: ⚠ <name> — not in radar; spawned openspec/changes/adopt-<name> → gate task <gate-task-id>
Show a summary after processing all rows:
Radar prerequisite check:
✓ chi (Adopt)
⚠ zerolog (Hold) — on radar but not Adopt; proceeding
⚠ some-new-lib — not in radar; existing change adopt-some-new-lib found → gate task td-xxxxx
⚠ another-lib — not in radar; spawned openspec/changes/adopt-another-lib → gate task td-yyyyy
## Technology Adoption & Usage Rules table is populated during design authoring. If docs/tech-radar.json is absent, warn and skip.n/a rows in the Technology Adoption table.Gate: <prereq-name> complete already exists on the board. If it does, reuse it — do not create a duplicate.Gate: <prereq-name> complete — this enables the completion check to find all prerequisite gates.openspec-ff-change logic exactly for artifact authoring — td hierarchy MUST matchcontext and rules from openspec instructions as constraints — do NOT copy them into artifact filessubagent_type: "worker") to dispatch one worker per capability stream simultaneously — never implement tasks directly in the orchestratortd usage --new-session before entering reviewer mode — this is what makes td approve worktd approve and td reject MUST be preceded by td handoff--remaining on rejection MUST be specific and actionabletd start, td approve, or td reject (never td update --status). The orchestrator owns feature status; workers own child task statuses.Create rule: research tasks blocking implementation tasks and dispatch researcher subagents before proceeding to review.td deps <id> to find dependent tasks when rejecting; do NOT grep task titles. Task dependencies are wired at creation time (Step 4c) and are the authoritative source of ordering.## Technology Adoption & Usage Rules table is populated during design authoring. If docs/tech-radar.json is absent, warn and skip.tools
<!--VITE PLUS START--> # Using Vite+, the Unified Toolchain for the Web This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`. ## Vite+ Workflow `vp` is a global binary that handles the full development lifecycle. Run `vp help` to pr
development
Guide for building performant data tables. Uses tanstack-table for table logic (sorting, filtering, pagination) and tanstack-virtual for rendering large datasets efficiently.
development
Expert guidance for building observable, expressive, and fault-tolerant TypeScript applications using the effect-ts/effect ecosystem. Covers Effect<A, E, R> type, error management, dependency injection via Layers, observability (logging, metrics, tracing), concurrency with Fibers, retry/scheduling, Schema validation, Streams, and Sinks.
tools
Complete E2E (end-to-end) and integration testing skill for TypeScript/NestJS projects using Jest, real infrastructure via Docker, and GWT pattern. ALWAYS use this skill when user needs to: **SETUP** - Initialize or configure E2E testing infrastructure: - Set up E2E testing for a new project - Configure docker-compose for testing (Kafka, PostgreSQL, MongoDB, Redis) - Create jest-e2e.config.ts or E2E Jest configuration - Set up test helpers for database, Kafka, or Redis - Configure .env.e2e environment variables - Create test/e2e directory structure **WRITE** - Create or add E2E/integration tests: - Write, create, add, or generate e2e tests or integration tests - Test API endpoints, workflows, or complete features end-to-end - Test with real databases, message brokers, or external services - Test Kafka consumers/producers, event-driven workflows - Working on any file ending in .e2e-spec.ts or in test/e2e/ directory - Use GWT (Given-When-Then) pattern for tests **REVIEW** - Audit or evaluate E2E tests: - Review existing E2E tests for quality - Check test isolation and cleanup patterns - Audit GWT pattern compliance - Evaluate assertion quality and specificity - Check for anti-patterns (multiple WHEN actions, conditional assertions) **RUN** - Execute or analyze E2E test results: - Run E2E tests - Start/stop Docker infrastructure for testing - Analyze E2E test results - Verify Docker services are healthy - Interpret test output and failures **DEBUG** - Fix failing or flaky E2E tests: - Fix failing E2E tests - Debug flaky tests or test isolation issues - Troubleshoot connection errors (database, Kafka, Redis) - Fix timeout issues or async operation failures - Diagnose race conditions or state leakage - Debug Kafka message consumption issues **OPTIMIZE** - Improve E2E test performance: - Speed up slow E2E tests - Optimize Docker infrastructure startup - Replace fixed waits with smart polling - Reduce beforeEach cleanup time - Improve test parallelization where safe Keywords: e2e, end-to-end, integration test, e2e-spec.ts, test/e2e, Jest, supertest, NestJS, Kafka, Redpanda, PostgreSQL, MongoDB, Redis, docker-compose, GWT pattern, Given-When-Then, real infrastructure, test isolation, flaky test, MSW, nock, waitForMessages, fix e2e, debug e2e, run e2e, review e2e, optimize e2e, setup e2e