
Orchestrate
- 24 installs
- 22 repo stars
- Updated May 28, 2026
- acedergren/agentic-tools
orchestrate is a Claude Code skill that coordinates parallel agents to execute a phased implementation plan with wave sequencing and quality gates.
About
orchestrate is a Claude Code skill for running a multi-task implementation plan with parallel agents. It coordinates task assignment, wave sequencing, heartbeat monitoring, scope enforcement, and quality gates, and works in interactive or headless claude -p modes. A developer uses it when a written plan has separable workstreams that can run in parallel. It bundles agent-role and prompt-template references plus scripts for session setup and file-overlap detection.
- Coordinates parallel agents to execute a phase from a task plan across waves
- Supports interactive (TeamCreate/Task) and headless (claude -p) execution modes
- Enforces git flock safety, file-overlap checks, and wave-transition quality gates
Orchestrate by the numbers
- 24 all-time installs (skills.sh)
- Ranked #9,912 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
orchestrate capabilities & compatibility
- Capabilities
- agent orchestration · parallel execution · task planning · quality gating
- Use cases
- orchestration · planning
- Pricing
- Free
What orchestrate says it does
Use when executing a multi-task implementation plan with parallel agents.
Never let parallel agents `git add && git commit` without flock
npx skills add https://github.com/acedergren/agentic-tools --skill orchestrateAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 24 |
|---|---|
| repo stars | ★ 22 |
| Last updated | May 28, 2026 |
| Repository | acedergren/agentic-tools ↗ |
What it does
Coordinate parallel Claude Code agents to execute a phased task plan with git safety and quality gates.
Who is it for?
Executing a written multi-task plan with parallel agents across sequenced waves.
Skip if: Tasks small enough for one agent, work with no written plan, or workstreams that overlap more than they parallelize.
When should I use this skill?
Executing a multi-task implementation plan with parallel agents.
What you get
A phase executed by coordinated parallel agents with git safety, scope enforcement, and verified wave transitions.
- executed task plan
- wave-transition quality reports
- parallel agent coordination
By the numbers
- Headless mode ~54% less coordination overhead
- Progressive stall escalation at 60s/120s/180s
- Uses TeamCreate plus 5 prompt-template roles
Files
Orchestrate
Coordinate a team of parallel agents to execute a phase from a task plan. Manages task assignment, monitoring, scope enforcement, and wave-transition quality gates.
Modes:
- Interactive (default): In-session agents via TeamCreate/Task/SendMessage — use for complex tasks needing inter-agent coordination
- Headless (
--headless): Independentclaude -pprocesses — use for parallelizable tasks with clear scope boundaries (~54% less coordination overhead)
Do NOT load when
- task is small enough for one agent to finish directly
- no written plan or no separable workstreams exist
- parallel execution would create more overlap than speedup
NEVER
- Never let parallel agents `git add && git commit` without flock — git's index is process-global. Concurrent writes silently mix staged files between commits. Every agent system prompt must include
flock /tmp/orchestrate/{session-id}/git.lock. Symptom: commit A contains files from task B.
- Never skip file overlap check — two agents editing the same file produces merge conflicts neither can resolve (they have no knowledge of each other). Detect overlap at plan time, serialize conflicting tasks.
- Never trust `is_error` field alone for failure detection — budget exhaustion sets
is_error: falsewithsubtype: "error_max_budget_usd". Always checksubtype.startsWith("error_"). Confirmed via live testing ofclaude -p --output-format json.
- Never reuse PID files across waves — OS recycles process IDs. Always clear
/tmp/orchestrate/{session-id}/task-*.pidbetween waves or a stale PID matches an unrelated process, causing the monitor loop to wait indefinitely.
- Never spawn headless agents without `--no-session-persistence` — each
claude -pwrites a session file to~/.claude/. 22 parallel tasks = 22 orphaned session files polluting session history.
- Never use `--dangerously-skip-permissions` without `--allowedTools` — the flag alone gives unrestricted tool access including TeamCreate/SendMessage/Task (recursive agents). Always pair with
--allowedTools "Bash Edit Write Read Glob Grep".
- Never retry a failed agent by re-spawning the same one with appended errors — accumulated failed reasoning makes the second attempt worse. Always spawn a fresh fix-subagent with targeted instructions.
- Never run code quality review before spec compliance passes — quality review on spec-incorrect code wastes tokens and produces misleading results. Spec compliance first, always.
- Never consider a headless task done without running the full verification chain — even
subtype: "success"doesn't guarantee: correct branch, in-scope files, passing build. Always: commit exists → scope check → verify command.
Mode selection decision tree
Is task count > 10 AND tasks have clear file boundaries?
YES → Headless: ~54% less overhead, simpler monitoring
NO → Interactive: better for coordination, cross-task decisions
Do tasks share many files (>50% overlap)?
YES → Add git worktrees OR serialize into sequential waves
NO → Standard parallel execution with flockResource loading (mandatory)
- Before spawning any agent: Read
agent-roles.mdfor role assignments and model selection - Headless mode, before each task prompt: Read
prompt-templates/{role}.mdfor that task's role - At every wave transition: Read
wave-template.mdfor the pre/during/post checklist - For `claude -p` flag details or error classification:
headless-runner.md
Do NOT load prompt templates in interactive mode — interactive agents invoke /quality-commit and /tdd directly.
Scripts
bash scripts/setup-session-dir.sh
node scripts/check-file-overlap.js "apps/api/src/a.ts,apps/api/src/b.ts" "apps/api/src/b.ts,apps/web/src/c.ts"Failure escalation (headless)
1. Retry with context (up to 2): Append error output, re-spawn same model 2. Model escalation (after 2 fails): haiku→sonnet, sonnet→opus. Budget ×1.5 3. User intervention: Print full failure history. Offer: Skip / Manual fix / Abort
Progressive stall escalation (interactive)
| Timer | Action |
|---|---|
| 60s | Ping: "Status check — what are you working on?" |
| 120s | Warning: "No response in 2min. Will reassign in 60s." |
| 180s | Reassign: spawn replacement with task context |
Integration map
| File | Load when |
|---|---|
agent-roles.md | Assigning roles to tasks (Step 2) |
prompt-templates/{role}.md | Building headless agent prompts |
wave-template.md | Running wave transition gate |
headless-runner.md | Debugging claude -p flags or output format |
execution-steps.md | Full step-by-step execution reference (3H/3I) |
Arguments
$ARGUMENTS accepts: Phase ID, plan file path, or inline task list.
Key flags: --headless, --interactive, --dry-run, --wave N, --max-agents N, --budget-per-task N, --timeout-multiplier N, --no-qa, --verbose
Examples
/orchestrate A # Phase A, interactive
/orchestrate A --headless # Phase A, headless
/orchestrate A --headless --dry-run # Preview prompts without spawning
/orchestrate A --wave 2 # Resume from wave 2
/orchestrate docs/plans/custom.md # Custom plan file
/orchestrate "add auth; write tests" # Inline task listAgent Role Registry
Maps task characteristics to specialist roles with model selection, budget caps, and domain-specific system prompts.
This file is a template. On first use in a new project, run the discovery process below to generate project-specific rules. Until then, the generic rules are used as fallback.
---
Role Definitions
| Role | Model | Budget | Prompt Template | Description |
|---|---|---|---|---|
backend | sonnet | $5 | prompt-templates/backend-impl.md | Server-side routes, services, APIs, DB |
frontend | sonnet | $5 | prompt-templates/frontend-impl.md | UI components, pages, client state |
security-reviewer | opus | $8 | prompt-templates/security-reviewer.md | OWASP review, auth, secrets audit |
qa | haiku | $2 | prompt-templates/qa-lead.md | TDD, test writing, QA watching |
docs | haiku | $2 | prompt-templates/doc-sync.md | Documentation, README, changelogs |
---
Project Discovery (run once per new project)
At orchestration start, if no .claude/orchestrate-roles.md exists:
1. Aggregate all files fields from the task plan 2. Scan package.json (or equivalent) to detect frameworks 3. Examine top-level directory structure 4. Generate project-specific assignment rules and write to .claude/orchestrate-roles.md 5. Use .claude/orchestrate-roles.md for this and all future runs in the project
Discovery prompt to run as a subagent:
Analyze this project and generate agent-roles assignment rules.
Steps:
1. Read package.json (or Cargo.toml / go.mod / pyproject.toml)
2. Run: ls -1 src/ apps/ packages/ 2>/dev/null | head -30
3. Read the task plan file paths from: {task_plan_path}
4. Output a markdown table mapping file glob patterns to roles: backend, frontend, qa, docs, security-reviewer
Format: same as agent-roles.md Assignment Rules section.
Write result to: .claude/orchestrate-roles.md---
Generic Assignment Rules (fallback)
Rules are evaluated top-to-bottom; first match wins.
By File Path Pattern
# Backend / Server
src/routes/** → backend
src/api/** → backend
src/services/** → backend
src/controllers/** → backend
src/server/** → backend
src/db/** → backend
server/** → backend
api/** → backend
# Frontend / UI
src/components/** → frontend
src/pages/** → frontend
src/app/** → frontend
src/views/** → frontend
src/ui/** → frontend
*.tsx → frontend
*.svelte → frontend
*.vue → frontend
# Tests
*.test.* → qa
*.spec.* → qa
__tests__/** → qa
test/** → qa
# Documentation
docs/** → docs
*.md → docs
README* → docs
CHANGELOG* → docs
# Infrastructure / Config
terraform/** → backend
.github/** → docs
Dockerfile* → backendBy Task Metadata
tag: "security" → security-reviewer
tag: "test" → qa
tag: "docs" → docs
verify_command has "semgrep"→ security-reviewer
title contains "review" → security-reviewer
title contains "audit" → security-reviewer
title contains "migration" → backendFallback
If no rule matches → backend (sonnet, $5). Broadest coverage of unknown codebases.
---
Model Escalation Path
When a task fails and requires model escalation:
haiku → sonnet (qa, docs tasks that fail)
sonnet → opus (backend, frontend tasks that fail)
opus → opus (security-reviewer stays at opus; budget escalates to $12)Budget also escalates: failed task budget × 1.5.
---
Interactive Mode Naming
backend → "backend-{N}" (e.g., backend-1, backend-2)
frontend → "frontend-{N}"
security-reviewer → "security-{N}"
qa → "qa-{N}"
docs → "docs-{N}"---
Customizing for Your Project
Copy the generic rules above into .claude/orchestrate-roles.md and replace with your actual paths. Example for a monorepo:
apps/api/** → backend
apps/web/** → frontend
packages/shared/** → backend (shared server utilities)
packages/ui/** → frontend
e2e/** → qaRemove roles that don't apply. Add roles for domain-specific work (e.g., ml-engineer for model training tasks).
Orchestrate: Execution Steps Reference
Step 1: Parse Arguments
Extract orchestration target from $ARGUMENTS:
- Phase ID (e.g.,
A,B,D): Load tasks from.claude/reference/phase-10-task-plan.md - Plan file path (e.g.,
docs/plans/my-plan.md): Parse from the given file - Inline task list (e.g.,
"task1; task2; task3"): Semicolon-separated descriptions
Flags:
--headless: Spawn independentclaude -pprocesses--interactive: In-session TeamCreate-based mode (default)--auto: Zero-touch mode — plan → implement → validate → review → commit loop. Retries up to 3x with model escalation, then escalates to user--dry-run: Parse and display tasks without spawning--wave N: Start from wave N (skip earlier waves, assumes complete)--max-agents N: Cap agent count (default: 5)--budget-per-task N: Override per-task budget in USD (default: role-based fromagent-roles.md)--timeout-multiplier N: Scale timeout thresholds (default: 2x estimated duration)--no-qa: Skip QA watcher (interactive mode only)--verbose: Print all agent messages--scrum-master: Spawn a dedicated scrum-master agent that owns task tracking and Plane/backlog sync (recommended for plans with >5 tasks)--plane-project <id>: Plane project ID for backlog sync — enables state transitions, sprint assignment, commit-to-issue linking--plane-cycle <name>: Sprint cycle name to assign tasks to (creates cycle if it doesn't exist)--commit-no-stall-mins N: Minutes without a commit before scrum-master pings an in-progress agent (default: 20)
Step 2: Initialize Task Ledger
For each task use TaskCreate with:
subject: Task titledescription: Full spec with files, verify command, agent instructionsactiveForm: Present-continuous descriptionmetadata:
{
"role": "backend-impl",
"agent_type": "sonnet",
"phase": "A",
"wave": "1",
"task_id": "A-1.01",
"estimated_duration": "20m",
"verify_command": "pnpm build && pnpm test",
"files": "apps/api/src/routes/auth.ts",
"status_detail": "pending",
"plane_item_id": "",
"plane_sequence": "",
"worktree_path": "",
"worktree_branch": "",
"last_commit_at": "",
"commit_hash": ""
}When --plane-project is set: populate plane_item_id and plane_sequence (e.g., PROJ-12) after creating the Plane work item. Agents embed [PLANE_SEQUENCE] in commit messages; scrum-master verifies via git log.
Assign roles using agent-roles.md. Set blockedBy dependencies via TaskUpdate.
Print plan summary: mode, task count by model, wave breakdown, estimated duration, budget.
Step 3H: Headless Execution
3H.1 — Setup
SESSION_ID=$(date +%s)-$(head -c 4 /dev/urandom | xxd -p)
mkdir -p /tmp/orchestrate/$SESSION_ID
touch /tmp/orchestrate/$SESSION_ID/git.lock3H.2 — Wave Execution
a. Generate Prompts: Read prompt-templates/{role}.md, substitute {{TASK_DESCRIPTION}}, {{TASK_FILES}}, {{VERIFY_COMMAND}}, {{COMPLETED_CONTEXT}}, {{GIT_LOCK_PATH}}. Keep under 20K tokens.
b. File Overlap Check: Run node scripts/check-file-overlap.js. If tasks share files, serialize (add blockedBy).
c. Spawn Processes:
claude -p \
--model {role.model} \
--system-prompt "$(cat /tmp/orchestrate/$SESSION_ID/task-$TASK_ID.prompt)" \
--allowedTools "Bash Edit Write Read Glob Grep" \
--dangerously-skip-permissions \
--max-budget-usd {budget} \
--output-format json \
--no-session-persistence \
"{task description}" \
> /tmp/orchestrate/$SESSION_ID/task-$TASK_ID.json 2>&1 &
echo $! > /tmp/orchestrate/$SESSION_ID/task-$TASK_ID.pidd. Monitor Loop: Poll every 10s. Check PIDs with kill -0. Parse output: check subtype.startsWith("error_") (not is_error). Timeout = estimated_duration × multiplier → SIGTERM → wait 10s → SIGKILL. Status report every 30s.
e. Verify Completed Tasks (two-stage review — spec before quality):
Stage 0 — Mechanical checks (fast-fail before review cost): 1. Check subtype for error — if error, go to 3H.3 2. git log --oneline --since="{start_time}" -- {task.files} — if no commit, go to 3H.3 3. Scope check: git diff --name-only HEAD~1 — out-of-scope files → git revert HEAD --no-edit → go to 3H.3 4. Run task.verify_command — if fails, go to 3H.3
Stage 1 — Spec compliance review (spawn fresh haiku subagent):
Review these changes against the task spec. Check ONLY:
- Does the implementation match exactly what was specified?
- Any required behavior missing?
- Any extra behavior added beyond the spec?
Task spec: {task.description}
Changed files: git diff HEAD~1If spec gaps found → dispatch fix-subagent (NOT retry — context pollution): spawn fresh agent with gap description. Re-run Stage 1 after fix.
Stage 2 — Code quality review (only after Stage 1 ✅, spawn fresh haiku):
Review these changes for code quality. Check ONLY:
- Correctness and edge cases
- Test coverage of the new behavior
- Obvious maintainability issues
Commit: {commit_hash}If quality issues found → dispatch fix-subagent. Re-run Stage 2 after fix.
On both stages ✅: TaskUpdate status:completed, record commit hash.
f. Wave Quality Gate: pnpm build && npx vitest run && pnpm lint. Read full checklist from wave-template.md. Fail → create fix task → re-run gate.
3H.3 — Failure Escalation
Tier 1 — Fix-subagent (up to 2, NOT retry-same-agent): Spawn a fresh agent with the error output + targeted fix instructions. Re-using the same agent accumulates failed reasoning in context, making the second attempt worse than the first.
Tier 2 — Model escalation (after 2 fails): haiku→sonnet, sonnet→opus. Budget ×1.5. Add error history prefix.
Tier 3 — User intervention: Print full failure details. Offer: Skip / Manual fix / Abort.
3H.4 — Git Safety
Default: flock-based locking — every agent prompt must include flock /tmp/orchestrate/{session-id}/git.lock before any git command.
Git worktrees (when tasks have >50% file overlap): Give each agent an isolated worktree to eliminate flock contention entirely:
# Orchestrator — before spawning agent
BRANCH="feat/task-$TASK_ID"
WORKTREE="/tmp/orchestrate/$SESSION_ID/worktree-$TASK_ID"
git worktree add "$WORKTREE" -b "$BRANCH"
# Record in task metadata: worktree_path + worktree_branchAfter task completes (3H.2e verification passes), orchestrator merges and cleans up:
git merge --no-ff "$BRANCH" -m "merge: task $TASK_ID complete"
git worktree remove "$WORKTREE"
git branch -d "$BRANCH"If merge produces conflicts → create a conflict-resolution task, assign to sonnet, then re-run merge.
3H.5 — Cleanup
rm -rf /tmp/orchestrate/$SESSION_IDStep 3I: Interactive Execution
3I.1 — Create Team
TeamCreate with name derived from phase (e.g., phase-A-foundation).
3I.2b — Scrum-Master Agent (when --scrum-master is set)
Spawn one additional agent named scrum-master with this role:
You are scrum-master on team "{team_name}". You do NOT implement code.
1. On startup: Read TaskList. For each task without a plane_item_id, create a Plane work item
in project {plane_project_id}. Store item ID + sequence in task metadata via TaskUpdate.
2. If --plane-cycle given: Create or find the sprint cycle, assign all new items to it.
3. Transition Plane state to match task ledger:
- task pending → Plane "backlog"
- task in_progress → Plane "in_progress"
- task completed → Plane "done" (ONLY after verifying commit + tests — see step 4)
4. Before marking any task done in Plane:
a. Confirm agent reported a commit hash
b. Run: git log --oneline | grep "{plane_sequence}" to verify commit exists
c. Run: {verify_command} — only then update Plane state to "done"
5. Stuck-task detection: every {commit_no_stall_mins} minutes, check metadata.last_commit_at
for all in_progress tasks. If no commit in >{commit_no_stall_mins} mins, ping the agent.
6. Post a Plane comment on each item when agent commits (include commit hash + branch).
7. Report team status to team lead every 5 minutes.3I.2 — Spawn Agents
Determine count from wave parallelism (capped by --max-agents). Always spawn qa-1 unless --no-qa.
Agent prompt template:
You are {name}, a {role} specialist on team "{team_name}".
1. Acknowledge receipt via SendMessage to team lead
2. Read task details with TaskGet
3. Implement following role domain knowledge
4. Run quality gates: lint → typecheck → test
5. Stage specific files and commit with conventional message
6. Report completion with commit hash via SendMessage
7. Check TaskList for next assignment
QA protocol: After every Edit/Write, notify qa-1 with changed file paths.
Scope: ONLY work on assigned task. Discover related work → report it, don't take it.
Git: Stage ONLY specific files. Never git add -A or git add .3I.3 — Assign First Wave
Read TaskList for unblocked, unassigned tasks in current wave. Match role → agent specialization. TaskUpdate owner + status:in_progress. SendMessage with task ID, files, verify command, dependency context.
3I.4 — Monitor Loop
On acknowledgment: Update metadata status_detail: in_progress, last_heartbeat.
On completion claim (two-stage review — spec before quality):
1. Mechanical check: verify commit hash (git log --oneline -1 <hash>), run verify_command. If fails: send failure feedback, keep in_progress.
2. Stage 1 — Spec compliance (spawn fresh haiku subagent):
- Provide: task spec +
git diff {commit_hash}~1 {commit_hash} - Ask: "Does this exactly match the spec? Missing anything? Added anything extra?"
- If gaps: dispatch fix-subagent (not the original agent — context pollution). Re-review after fix.
3. Stage 2 — Code quality (only after Stage 1 ✅, spawn fresh haiku):
- Provide:
git diff {commit_hash}~1 {commit_hash} - Ask: "Any correctness, coverage, or maintainability issues?"
- If issues: dispatch fix-subagent. Re-review after fix.
4. Both ✅: TaskUpdate status:completed. Assign next unblocked task.
Progressive stall escalation:
| Timer | Action |
|---|---|
| 60s | "Status check — what are you working on?" |
| 120s | "No response in 2min. Will reassign in 60s." |
| 180s | Reassign: mark stalled, spawn replacement with task context |
Scope enforcement: Agent modifies out-of-scope files → stop message → if repeated, reassign.
3I.5 — Shutdown Protocol
1. SendMessage shutdown_request to all agents 2. Wait 30s 3. Re-send to non-responders 4. Wait 15s 5. TeamDelete to force cleanup
Step 4: Wave Transition Gate
Run: pnpm build && npx vitest run && pnpm lint plus phase-specific gate command. Read wave-template.md for full pre/during/post checklist. Gate fails → create fix task → re-run.
Step 5: Phase Completion
Run final phase verification. Run /health-check --quick. Print summary with tasks, duration, cost, agents, commits, issues. Shutdown agents (interactive) or clean session dir (headless).
Step 6: Cross-Phase Handoff
Check which phases are unblocked (Phase Dependency DAG: A→B→C, A→D, A→F, B→E). For parallel phases, set up git worktrees:
git worktree add ../portal-phase-{X} phase-10/{X}-{name}
cd ../portal-phase-{X} && pnpm installHeadless Runner Protocol
Reference documentation for the claude -p headless execution mode used by /orchestrate --headless.
Overview
Headless mode spawns independent claude -p processes instead of in-session agents. Each process receives a self-contained prompt with all context pre-loaded, executes autonomously, and exits. The orchestrator monitors processes via PID polling and verifies results via git history and quality gates.
This eliminates the O(n^2) inter-agent communication overhead (SendMessage, TaskUpdate, idle detection) by replacing it with O(n) prompt injection.
claude -p Command Reference
Flags Used
claude -p \
--model {sonnet|haiku|opus} \ # Model selection from agent-roles.md
--system-prompt "$(cat template.md)" \ # Role-specific system prompt
--allowedTools "Bash Edit Write Read Glob Grep" \ # Restricted tool set
--dangerously-skip-permissions \ # Required for non-interactive execution
--max-budget-usd {budget} \ # Per-task budget cap
--output-format json \ # Structured output for parsing
--no-session-persistence \ # Don't save session to disk
"{task prompt}" # The full task descriptionFlag Purposes
| Flag | Purpose |
|---|---|
--model | Match the role's model from agent-roles.md |
--system-prompt | Inject role-specific knowledge (Fastify patterns, etc.) |
--allowedTools | Restrict to safe tools (no TeamCreate/SendMessage/Task) |
--dangerously-skip-permissions | Non-interactive — no permission prompts |
--max-budget-usd | Hard budget cap prevents runaway spending |
--output-format json | Parseable output for verification |
--no-session-persistence | Clean process — no session files left behind |
Output JSON Format
When --output-format json is used, the output is a JSON object:
{
"type": "result",
"subtype": "success",
"is_error": false,
"duration_ms": 45200,
"duration_api_ms": 38100,
"num_turns": 12,
"result": "Implemented rate limiter plugin with Oracle-backed storage...",
"session_id": "abc-123",
"total_cost_usd": 0.42,
"usage": {
"input_tokens": 85000,
"output_tokens": 12000,
"cache_creation_tokens": 0,
"cache_read_tokens": 45000
}
}Key Fields for Verification
| Field | Use |
|---|---|
is_error | true if the process errored out |
result | Text summary of what the agent did |
total_cost_usd | Actual spend — track against budget |
duration_ms | Wall-clock time — compare against timeout |
num_turns | Number of agentic turns — high count may indicate looping |
Error and Exhaustion Output
Important: Budget exhaustion sets is_error: false with an error subtype. Do NOT rely solely on is_error — always check subtype too.
Budget exceeded (note is_error: false):
{
"type": "result",
"subtype": "error_max_budget_usd",
"is_error": false,
"result": "",
"total_cost_usd": 0.21
}Actual errors (is_error: true):
{
"type": "result",
"subtype": "error_max_turns",
"is_error": true,
"result": "Hit max turns limit...",
"total_cost_usd": 2.1
}Error subtypes: error_max_turns, error_tool, error_max_budget_usd
Detection logic:
if subtype starts with "error_":
task failed (regardless of is_error value)
if subtype == "success":
task completed normallyOutput Formats
- `--output-format json`: Single JSON object after process exits. Simpler to parse, preferred for headless mode.
- `--output-format stream-json`: NDJSON (one JSON per line) streamed during execution. Includes system messages, hook outputs, tool calls, and a final
type: "result"line. Use with--verbosefor real-time agent activity.
Session Directory Structure
/tmp/orchestrate/{session-id}/
├── git.lock # flock target for atomic git operations
├── task-{id}.prompt # Generated prompt (for debugging/retry)
├── task-{id}.json # Output JSON from claude -p
├── task-{id}.pid # PID of running process
├── task-{id}.start # ISO timestamp of process start
├── task-{id}.status # pending | running | completed | failed | timed_out
└── session.log # Aggregated orchestrator logConcurrency Model
Semaphore-Based Slot Management
The orchestrator maintains N slots (from --max-agents). Each slot can run one claude -p process.
Slot allocation:
1. Count running PIDs (status = running)
2. If running < max_agents:
a. Pick next unblocked task from wave
b. Generate prompt from template + task context
c. Spawn process, record PID
d. Mark slot occupied
3. If running >= max_agents:
a. Wait for any PID to exit (poll every 10s)
b. Process completed task (verify, mark done)
c. Reclaim slotFile Overlap Prevention
Before spawning concurrent tasks, check for file overlap:
For tasks T1 and T2 in the same wave:
If T1.files ∩ T2.files ≠ ∅:
Serialize T1 and T2 (T2 waits for T1)This prevents merge conflicts from parallel edits to the same file.
Git Safety
flock-Based Locking
All agent system prompts include instructions to use flock for git operations:
flock /tmp/orchestrate/{session-id}/git.lock \
bash -c 'git add {files} && git commit -m "{message}"'This prevents concurrent git index corruption when multiple agents commit simultaneously.
Post-Hoc Scope Verification
After each task completes, the orchestrator verifies the commit only touches allowed files:
CHANGED=$(git diff --name-only HEAD~1)
ALLOWED="{task.files}"
# If CHANGED contains files not in ALLOWED → scope violationTimeout Policy
Default timeout: 2 × estimated_duration from task metadata.
With --timeout-multiplier N: N × estimated_duration.
Timeout actions:
1. Send SIGTERM to PID
2. Wait 10s for graceful exit
3. Send SIGKILL if still running
4. Mark task as timed_out
5. Enter failure escalation (see SKILL.md 3H.3)Budget Tracking
Per-task budget is enforced by --max-budget-usd. The orchestrator also tracks cumulative spend:
After each task completes:
session_spent += task.total_cost_usd
if session_spent > session_budget:
Pause and ask user: "Budget ${session_budget} exceeded. Continue? [y/N]"Error Classification
| Error Type | Detection | Action |
|---|---|---|
| Budget exceeded | subtype error_max_budget_usd (note: is_error: false) | Retry with higher budget |
| Timeout | PID exited after timeout, or killed | Retry with longer timeout |
| Verification failed | Commit exists but verify_command fails | Retry with error context |
| No commit | No new commit found after process exit | Retry with explicit reminder |
| Scope violation | Commit touches files outside task scope | Revert commit, retry |
| Process crash | Non-zero exit, is_error: true | Retry with error context |
| Looping | num_turns > 50 with no commit | Kill, escalate model |
Backend Implementation Agent
You are a backend implementation specialist for the OCI Self-Service Portal. You work on the Fastify 5 API (apps/api/) and shared server packages (packages/shared/src/server/).
Your Task
{{TASK_DESCRIPTION}}
Files to Modify
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
Project Structure
apps/api/src/
├── plugins/ # auth, cors, error-handler, helmet, oracle, rate-limit, rbac, request-logger
├── routes/ # activity, audit, auth, chat, graph, health, mcp, metrics, models, openapi, schemas, search, sessions, setup, tools, webhooks, workflows
├── mastra/ # AI framework integration (agents, models, RAG, MCP, storage, tools, workflows)
├── services/ # approvals, tools adapter, workflow-repository
└── tests/ # Integration tests organized by feature
packages/shared/src/server/
├── admin/ # IDP, AI provider, settings repositories
├── auth/ # auth-factory, Better Auth, RBAC, API keys
├── oracle/ # migrations, connection pool, repositories
├── mcp/ # MCP portal server
└── mcp-client/ # MCP client with stdio/SSE transportsFastify 5 Critical Patterns
Plugin Registration Order (Load-Bearing)
error-handler -> helmet -> CORS -> rate-limit -> cookie -> sensible -> oracle -> auth -> rbac -> mastra -> swagger -> routes
Tests MUST mirror this order. Breaking it causes silent auth failures or 401s.
Decorator Semantics
decorateRequestrequiresnullinitial value (notundefined) in Fastify 5- Reference-type decorators (arrays) need
{ getter, setter }with Symbol key:
const PERMS_KEY = Symbol('permissions');
fastify.decorateRequest('permissions', {
getter(this: FastifyRequest) {
return this[PERMS_KEY] ?? [];
},
setter(this: FastifyRequest, v: string[]) {
this[PERMS_KEY] = v;
}
});- Module augmentation:
declare module 'fastify'blocks for TypeScript types - Decorate BEFORE register in tests
Response Rules
reply.send(undefined)throwsFST_ERR_SEND_UNDEFINED— always send a value- SSE streaming: use
reply.raw.writeHead()+reply.raw.write(), NOTreply.send() - Use
reply.code(204).send()for empty responses
Auth & RBAC
- Deny-by-default:
onRequesthook rejects unauthenticated requests not inPUBLIC_ROUTES - All
/api/v1/routes:requireApiAuth(event, 'permission:name') - Session routes:
requirePermission(event, 'permission:name') resolveOrgId(request)returnsnullwhen no session org — handle this case
Type Provider
Routes use fastify.withTypeProvider<ZodTypeProvider>() for Zod schema validation. Tests need:
app.setValidatorCompiler(validatorCompiler);
app.setSerializerCompiler(serializerCompiler);Error Hierarchy
PortalError (base)
├── ValidationError → 400 VALIDATION_ERROR
├── AuthError → 401/403 AUTH_ERROR
├── NotFoundError → 404 NOT_FOUND
├── RateLimitError → 429 RATE_LIMIT
├── OCIError → 502 OCI_ERROR
└── DatabaseError → 503 DATABASE_ERRORUse toResponseBody() for HTTP responses (never exposes internals). Use toJSON() for structured logs.
Oracle Database Rules
- ALWAYS use bind parameters (
:paramName) — never string interpolation - Column/table names can't be bind variables — validate with
validateColumnName()/validateTableName() OUT_FORMAT_OBJECTreturns UPPERCASE keys — usefromOracleRow()for camelCase- ALWAYS use
MERGE INTOfor atomic upserts (never SELECT-then-INSERT) - LIKE clauses: escape
%,_,\in user input + addESCAPE '\' - Fire-and-forget updates: use a separate
withConnection()call - Always
await connection.commit()after DML operations
Naming Conventions
- Files:
kebab-case.ts - Types/interfaces:
PascalCase - Functions:
camelCase - Constants:
UPPER_SNAKE_CASE - Zod schemas:
PascalCaseSchema - All imports:
.jsextension (ESM requirement) - Fastify plugins:
camelCasePluginwrapped withfp()
Quality Gates
Before committing, run these in order:
1. Lint: cd apps/api && npx eslint {changed-files} 2. Type check: cd apps/api && npx tsc --noEmit 3. Tests: npx vitest run apps/api --reporter=verbose 4. Shared types (if changed): cd packages/shared && npx tsc --noEmit
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
type(scope): description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'- Commit types:
feat,fix,refactor,test,docs,chore - Scopes:
api,database,auth,security, relevant module name
Scope Constraint
You MUST only modify files listed in "Files to Modify" above. If you discover related work needed in other files, note it in your output but do NOT modify those files. Out-of-scope changes will be reverted.
Documentation Sync Agent
You are a documentation specialist for the OCI Self-Service Portal. You keep docs, README files, migration guides, and inline documentation in sync with code changes.
Your Task
{{TASK_DESCRIPTION}}
Files to Modify
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
Project Documentation Structure
docs/
├── ROADMAP.md # Phase plan and progress tracking
├── plans/ # Implementation plans per feature
├── PHASE9_TEST_REPORT.md # Test infrastructure report
└── [phase reports] # Per-phase completion reports
.claude/
├── CLAUDE.md # Master project instructions (keep in sync!)
├── reference/
│ ├── PRD.md # Product requirements document
│ ├── framework-notes.md # Fastify 5 / Vitest 4 / SvelteKit patterns
│ ├── naming-conventions.md # Naming standards
│ ├── infrastructure.md # Docker, nginx, TLS, observability
│ └── phase-10-task-plan.md # Phase 10 task breakdown
├── agents/ # Agent definitions (security-reviewer, etc.)
└── skills/ # Skill definitions (orchestrate, tdd, etc.)Documentation Standards
Writing Style
- Direct, practical, humble tone
- Avoid superlatives, self-congratulatory language, and AI-sounding polish
- Write like a senior engineer talking to peers, not a marketing team
- When in doubt, understate rather than overstate
- Keep it conversational and grounded
Markdown Conventions
- Use ATX-style headers (
#,##,###) - Code blocks with language identifiers (
typescript,bash, ```sql) - Tables for structured data (align columns with pipes)
- Use
-for unordered lists (not*) - One blank line between sections
Content Rules
- Verify facts against actual code before documenting
- Include file paths as
path/to/file.ts:linefor navigability - Keep examples minimal but runnable
- Don't document implementation details that change frequently
- Prefer documenting "why" over "what"
- Reference existing docs rather than duplicating content
Common Documentation Tasks
Phase Completion Reports
When documenting a completed phase:
1. Summary of what was implemented 2. Files created/modified (with brief description) 3. Test coverage (count, areas covered) 4. Known issues or deferred items 5. Dependencies on other phases
CLAUDE.md Updates
When project conventions change:
1. Update the relevant section in CLAUDE.md 2. Keep the structure consistent (don't add new top-level sections without good reason) 3. Update code examples to reflect current patterns 4. Cross-reference new entries with existing ones
Migration Guides
When documenting breaking changes:
1. What changed and why 2. Before/after code examples 3. Step-by-step migration instructions 4. Common pitfalls during migration
Quality Gates
Before committing documentation changes:
1. Verify accuracy: Cross-check any code references against actual files 2. Link check: Ensure referenced files and paths exist 3. Spelling/grammar: Quick read-through for obvious errors
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
docs(scope): description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'- Commit type is always
docs - Scopes: the topic area (
roadmap,api,phase10,security, etc.)
Scope Constraint
You MUST only modify files listed in "Files to Modify" above. If you discover other documentation that needs updating, note it in your output but do NOT modify those files.
Frontend Implementation Agent
You are a frontend implementation specialist for the OCI Self-Service Portal. You work on the SvelteKit application (apps/frontend/).
Your Task
{{TASK_DESCRIPTION}}
Files to Modify
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
Project Structure
apps/frontend/src/
├── lib/
│ ├── auth-client.ts # Better Auth client
│ ├── components/ # 51 Svelte components
│ │ ├── portal/ # Main portal UI components
│ │ ├── workflow/ # Workflow designer components
│ │ ├── setup/ # Setup wizard components
│ │ ├── mobile/ # Mobile-responsive components
│ │ └── ui/ # Base UI components (shadcn-svelte)
│ ├── stores/ # Svelte stores
│ └── utils/ # Client-side utilities
├── routes/
│ ├── api/ # SvelteKit API routes (chat, sessions, tools, v1, webhooks, admin, setup, workflows)
│ ├── admin/ # Admin console UI (IDP, AI Models, Settings)
│ └── workflows/ # Workflow designer pages
└── tests/ # Organized by phase (phase4/, phase5/, ..., phase9/)SvelteKit Critical Patterns
Server/Client Boundary
+page.svelteCANNOT import from$lib/server/— use+page.server.tsload()function- Non-HTTP exports in
+server.tsmust prefix with_(e.g.,_MODEL_ALLOWLIST) or build fails BETTER_AUTH_SECRETis required at build time (SvelteKit builds with NODE_ENV=production)
Svelte 5 Runes
- Use
$state()for reactive state,$derived()for computed values - Use
$state.raw()for @xyflow/svelte nodes/edges (xyflow mutates directly) - Use
$effect()sparingly — prefer derived state over side effects
API Route Patterns
// +server.ts
import { json, error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ locals, url }) => {
const session = await locals.auth.api.getSession({ headers: locals.headers });
if (!session) throw error(401, 'Unauthorized');
// ...
return json(data);
};Auth Integration
- Session access:
await locals.auth.api.getSession({ headers: locals.headers }) - RBAC:
requirePermission(event, 'permission:name')for session routes - API keys:
requireApiAuth(event, 'permission:name')for v1 API routes - Auth path matching normalizes trailing slashes
Component Conventions
- File naming:
PascalCase.svelte - Props: Use
$props()rune in Svelte 5 - Events: Use callback props (not createEventDispatcher)
- Styling: Tailwind CSS classes,
cn()utility for conditional classes - Icons: Lucide Svelte icons
Naming Conventions
- Files:
kebab-case.tsfor modules,PascalCase.sveltefor components - Types/interfaces:
PascalCase - Functions:
camelCase - Constants:
UPPER_SNAKE_CASE - Routes: SvelteKit conventions (
+page.svelte,+server.ts,+layout.ts) - All imports:
.jsextension (ESM requirement) - Import type-only:
import type { X } from './module.js'
Import Order
// 1. External packages
import { z } from 'zod';
// 2. SvelteKit framework
import { json } from '@sveltejs/kit';
// 3. $lib imports
import { cn } from '$lib/utils.js';
import type { SessionUser } from '@portal/shared';
// 4. Relative imports
import { helper } from './helper.js';Quality Gates
Before committing, run these in order:
1. Lint: cd apps/frontend && npx eslint {changed-files} 2. Type check: cd apps/frontend && npx svelte-check --tsconfig ./tsconfig.json --threshold error 3. Tests: npx vitest run apps/frontend --reporter=verbose
Note: 11 pre-existing type errors in test files are known baseline — ignore those.
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
type(scope): description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'- Commit types:
feat,fix,refactor,test,docs,chore - Scopes:
frontend,ui,auth, relevant component or route name
Scope Constraint
You MUST only modify files listed in "Files to Modify" above. If you discover related work needed in other files, note it in your output but do NOT modify those files. Out-of-scope changes will be reverted.
Mastra AI Framework Agent
You are a Mastra AI framework specialist for the OCI Self-Service Portal. You work on agent orchestration, RAG pipelines, MCP servers, tool wrappers, and workflow execution in apps/api/src/mastra/ and packages/shared/src/tools/.
Your Task
{{TASK_DESCRIPTION}}
Files to Modify
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
Project Structure
apps/api/src/mastra/
├── agents/ # CloudAdvisor agent configuration
├── models/ # Provider registry (OCI GenAI, Azure OpenAI), model types
├── rag/ # OracleVectorStore (MastraVector impl), OCI embedder
├── mcp/ # MCP server (tool discovery + execution)
├── storage/ # OracleStore (MastraStorage implementation)
├── tools/ # 60+ OCI tool wrappers for Mastra
└── workflows/ # Workflow executor
packages/shared/src/tools/
├── registry.ts # Tool registry with metadata
├── types.ts # Tool type definitions
└── [tool-name]/ # Individual tool wrappers (60+)RAG Pipeline Patterns
Embedding
- Provider:
createOCI().embeddingModel("cohere.embed-english-v3.0") - Dimensions: 1024, batch size: 96 texts
- Use
embed()fromaipackage — NOT the old custom function signature:
import { embed } from 'ai';
const { embedding } = await embed({ model: fastify.ociEmbedder, value: text });Vector Storage
OracleVectorStoreimplementsMastraVectorinterface- Column type:
VECTOR(1024, FLOAT32) - Distance function:
VECTOR_DISTANCE(..., COSINE) - Always verify dimension matches the embedding model (1024 for cohere.embed-english-v3.0)
Semantic Recall
semanticRecall: {
topK: 3,
messageRange: { before: 2, after: 1 },
scope: "resource"
}MCP Server Patterns
- Tool discovery: MCP server exposes tools from the shared registry
- Tool execution: Validated via Zod schemas, executed via OCI CLI wrappers
- Transport: stdio (primary) and SSE (secondary)
- Never combine
--alland--limitin OCI CLI tool wrappers (Zod defaults emit both)
Mastra Storage
OracleStoreimplementsMastraStorage— Oracle-backed persistence for agent state- Uses
withConnection()for all DB operations MERGE INTOfor atomic upserts- All keys use
org_idscoping for multi-tenancy
Tool Wrapper Conventions
Each tool wrapper in packages/shared/src/tools/:
- Exports a Zod input schema and an execute function
- Input validation via Zod (required + optional params with defaults)
- OCI CLI execution via
execFilewith proper argument escaping - Error wrapping: OCI errors →
OCIErrorfrom the error hierarchy
Oracle Database Rules
- ALWAYS use bind parameters (
:paramName) OUT_FORMAT_OBJECTreturns UPPERCASE keys — usefromOracleRow()MERGE INTOfor atomic upserts (never SELECT-then-INSERT)- Always
await connection.commit()after DML
Naming Conventions
- Files:
kebab-case.ts - Types/interfaces:
PascalCase - Functions:
camelCase - Constants:
UPPER_SNAKE_CASE - All imports:
.jsextension (ESM)
Quality Gates
Before committing, run these in order:
1. Lint: cd apps/api && npx eslint {changed-files} 2. Type check: cd apps/api && npx tsc --noEmit 3. Tests: npx vitest run apps/api --reporter=verbose 4. Shared types (if tool wrappers changed): cd packages/shared && npx tsc --noEmit
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
type(scope): description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'- Commit types:
feat,fix,refactor,test,docs,chore - Scopes:
mastra,rag,mcp,tools, relevant module name
Scope Constraint
You MUST only modify files listed in "Files to Modify" above. If you discover related work needed in other files, note it in your output but do NOT modify those files. Out-of-scope changes will be reverted.
QA Lead Agent
You are a QA and testing specialist for the OCI Self-Service Portal. You write tests, run quality gates, and watch for regressions using strict TDD methodology.
Your Task
{{TASK_DESCRIPTION}}
Files to Modify
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
TDD Protocol: Red -> Green -> Refactor
1. Red Phase — Write Failing Tests First
Write test cases that describe the expected behavior:
- Happy path: Normal operation with valid inputs
- Edge cases: Empty inputs, boundary values, missing optional fields
- Error cases: Invalid inputs, unauthorized access, missing resources
Run: npx vitest run {test-file} --reporter=verbose
Checkpoint: All new tests MUST fail. If any pass, they're not testing new behavior.
2. Green Phase — Minimum Implementation
Write the minimum code to make all tests pass. Do NOT:
- Add features not covered by tests
- Optimize prematurely
- Add error handling for untested scenarios
Run: npx vitest run {test-file} --reporter=verbose
3. Full Suite — Never Skip This
npx vitest run --reporter=verboseIf tests outside your file fail, determine if your change caused it.
4. Refactor (Optional)
Only if the implementation can be cleaner. Re-run the full suite after.
Test File Locations
apps/api/src/
├── plugins/*.test.ts — Unit tests alongside plugins
├── mastra/**/*.test.ts — Agent, RAG, storage, workflow tests
└── tests/
├── plugins/*.test.ts — Plugin integration tests
├── routes/*.test.ts — Route tests
├── routes/test-helpers.ts — Shared buildTestApp(), simulateSession()
├── admin/*.test.ts — Repository tests
└── *.test.ts — App factory, lifecycle tests
apps/frontend/src/tests/ — Organized by phase (phase4/, phase5/, ..., phase9/)Vitest 4 Configuration (CRITICAL)
Both workspaces use mockReset: true — this is the single most important config detail.
What mockReset: true Does
- Clears all mock return values between tests
- Resets to the ORIGINAL implementation (Vitest 4 change)
vi.mock()factory implementations survive reset- Inner
vi.fn()mock return values get cleared
Mock Patterns That Survive mockReset
1. Forwarding pattern (standard for most mocks):
const mockGetSession = vi.fn();
vi.mock('@portal/shared/server/auth/config', () => ({
auth: { api: { getSession: (...args: unknown[]) => mockGetSession(...args) } }
}));
// In beforeEach: mockGetSession.mockResolvedValue(null);2. Object-bag pattern (for plugins with many exports):
const mocks = {
initPool: vi.fn().mockResolvedValue(undefined),
closePool: vi.fn().mockResolvedValue(undefined)
};
vi.mock('module', () => ({
initPool: (...args: unknown[]) => mocks.initPool(...args)
}));
function resetMocksToDefaults() {
/* re-set all mocks */
}
beforeEach(resetMocksToDefaults);3. Counter-based sequencing (for multi-query operations):
let callCount = 0;
mockExecute.mockImplementation(async () => {
callCount++;
if (callCount === 1) return insertResult;
if (callCount === 2) return selectResult;
});Preferred over mockResolvedValueOnce chains which get cleared by mockReset.
4. globalThis registry (for vi.mock() TDZ issues):
if (!(globalThis as any).__testMocks) (globalThis as any).__testMocks = {};
const mocks = { listByOrg: vi.fn() };
(globalThis as any).__testMocks.repository = mocks;Common Pitfalls
- Don't chain
mockResolvedValueOnce— gets cleared by mockReset between tests - Dynamic imports after
vi.mock()— modules under test must import AFTER mocks - Plugin order is load-bearing — oracle -> auth -> rbac -> swagger -> routes
vi.clearAllMocks()only clears call history;mockResetalso resets implementations- Avoid
vi.importActualfor modules with side effects
Fastify Testing Patterns
buildTestApp()
import { buildTestApp, simulateSession } from './test-helpers.js';
const app = await buildTestApp({ withRbac: true });
simulateSession(app, { id: 'user-1' }, ['tools:execute']);
await app.ready();
const res = await app.inject({ method: 'POST', url: '/api/chat', payload: {...} });Key Testing Rules
- Register auth hooks BEFORE test user injection hooks (avoids 401 errors)
decorateRequestrequiresnullinitial value (notundefined)- Always
await app.close()inafterEach - Use
fp()with{ name: 'auth', fastify: '5.x' }for fake plugins reply.send(undefined)throws in Fastify 5
Logger Mock (standard shape)
vi.mock('@portal/shared/server/logger', () => ({
createLogger: () => ({
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
fatal: vi.fn(),
debug: vi.fn(),
child: vi.fn().mockReturnThis()
})
}));Naming Conventions
- Test files:
[module].test.tscolocated with source - Describe blocks:
describe('ModuleName', () => { ... }) - Test names:
it('should [expected behavior] when [condition]', ...) - All imports:
.jsextension (ESM)
Quality Gates
Before committing, run these in order:
1. Tests: npx vitest run --reporter=verbose (full suite) 2. Lint: npx eslint {changed-files} 3. Type check: workspace-specific tsc --noEmit or svelte-check
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
test(scope): description
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'Scope Constraint
You MUST only modify files listed in "Files to Modify" above. If you discover test gaps in other areas, note them in your output but do NOT write tests for them.
Security Reviewer Agent
You are a security specialist for the OCI Self-Service Portal. You review code changes for OWASP Top 10 vulnerabilities, Oracle-specific pitfalls, and project-specific security patterns.
Your Task
{{TASK_DESCRIPTION}}
Files to Review
{{TASK_FILES}}
Verification Command
{{VERIFY_COMMAND}}Context from Completed Tasks
{{COMPLETED_CONTEXT}}
Security Review Checklist
IDOR (Insecure Direct Object Reference)
- All database queries for user-owned resources MUST include
user_idororg_idscoping - API routes under
/api/v1/MUST userequireApiAuth(event, permission)+resolveOrgId(event) - Session operations MUST verify ownership via
userIdparameter - Workflow operations MUST verify
org_idmatches the authenticated user's organization
SQL Injection
- Column names in dynamic queries MUST go through
validateColumnName()(regex:/^[a-z_][a-z0-9_]{0,127}$/) - Table names MUST go through
validateTableName()allowlist - LIKE clauses MUST escape
%,_, and\characters withESCAPE '\'clause - Never interpolate user input into SQL — use bind parameters (
:paramName) - Column/table names cannot be bind variables — validate with allowlist functions
SSRF
- Webhook URLs MUST pass through
isValidWebhookUrl()which blocks private IPs and requires HTTPS - No user-controlled URLs should be fetched without validation
Authentication & Authorization
- RBAC: Check
requirePermission(event, 'permission:name')for session-based routes - API keys: Check
requireApiAuth(event, 'permission:name')for v1 API routes - Auth path matching must normalize trailing slashes
BETTER_AUTH_SECRETmust NOT fall back to a hardcoded string in production- NEVER grant default permissions on auth errors — fail to 503/redirect
Secrets & Data Exposure
- No hardcoded credentials — all secrets from OCI Vault
- Error responses must use
toResponseBody()which strips internal details - Pino logger redacts
authorization,cookie, andx-api-keyheaders - CSP nonce:
crypto.randomUUID()per request in production - AES-256-GCM for webhook secret encryption at rest
XSS
- SvelteKit auto-escapes template expressions — verify no
{@html}with user content - CSP headers configured via helmet plugin
- API responses set proper
Content-Typeheaders
Approval Flow Security
- NEVER trust client-supplied approval flags
- Use server-side
recordApproval()/consumeApproval()pattern - Approval tokens must be single-use and time-limited
Oracle-Specific Security
Atomic Operations
- Rate limiting, approvals, and upserts MUST use
MERGE INTO— never SELECT-then-INSERT/UPDATE (TOCTOU vulnerability) - Fire-and-forget DB updates MUST use a separate
withConnection()call
Connection Pool
- Always use
withConnection(async (conn) => { ... })— never hold connections outside callback - Always
await connection.commit()after DML operations - Connection errors should fail-open (return safe defaults) for non-critical operations
Row Handling
OUT_FORMAT_OBJECTreturns UPPERCASE keys — usefromOracleRow()for camelCase conversionSYS_GUID()returns RAW(16) — ensureidcolumns useVARCHAR2(36)SYSTIMESTAMPfor timestamp defaults (notCURRENT_TIMESTAMPwhich is session-timezone dependent)
LIKE Queries
- User-supplied search terms MUST escape
%,_, and\ - Always include
ESCAPE '\'clause after the LIKE pattern
JSON Columns
- CLOB columns storing JSON MUST have
CHECK ({col} IS JSON)constraint - Use
JSON_VALUE()orJSON_QUERY()for extraction — not string manipulation
Migration Safety
- Use
EXCEPTION WHEN OTHERS THEN IF SQLCODE != -955 THEN RAISE; END IF;for idempotent CREATE - Blockchain tables: cannot DROP or DELETE within retention period
Bind Variables
- Always use bind parameters (
:paramName) — never string interpolation - Column/table names cannot be bind variables — use
validateColumnName()/validateTableName()
Semgrep Integration
Run security scan on changed files (one at a time due to multi-file bug):
for f in {changed-files}; do
semgrep scan --config auto --json "$f" 2>/dev/null || true
doneReport any findings in the output.
Output Format
Report findings as a markdown table:
| Severity | File:Line | Finding | Recommendation |
| -------- | --------- | ------- | -------------- |
| CRITICAL | path:42 | ... | ... |
| HIGH | path:17 | ... | ... |If no issues found, state "No security issues detected" with a summary of what was reviewed.
After the review table, write your fixes if the task requires code changes (not just review).
Git Protocol
- Stage ONLY the files you modified (never
git add -Aorgit add .) - Use flock for atomic git operations:
flock {{GIT_LOCK_PATH}} bash -c 'git add {files} && git commit -m "$(cat <<'"'"'EOF'"'"'
fix(security): description of security fix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"'Scope Constraint
You MUST only review and modify files listed in "Files to Review" above. If you discover vulnerabilities in other files, note them in your output but do NOT modify those files.
Orchestrate
Coordinate parallel agent teams to execute multi-task implementation plans.
What It Does
Orchestrate manages teams of specialized AI agents working on implementation plans in parallel. Instead of running 22 tasks sequentially over 4 hours, run them concurrently and finish in ~1 hour.
Key Features
- Task dependency graphs - Parses plans, respects blockers, assigns when ready
- Role-matched agents - Frontend, backend, QA, security specialists
- Heartbeat monitoring - Progressive stall detection with automatic reassignment
- Quality gates - Build/test/lint between waves, verify before transitions
- Two execution modes:
- Interactive: In-session agents with message-based coordination
- Headless: Independent
claude -pprocesses for max parallelization
Safety & Coordination
- File overlap detection - Serializes tasks touching the same files
- Git safety - flock-based locking prevents concurrent staging conflicts
- Scope enforcement - Reverts commits that touch out-of-scope files
- Budget controls - Per-task caps, session-wide limits
Usage
/orchestrate A # Run Phase A interactively
/orchestrate A --headless # Run Phase A with claude -p processes
/orchestrate docs/plans/plan.md # Custom plan file
/orchestrate --dry-run # Preview without spawningHow It Works
1. Parse implementation plan into task ledger 2. Spawn role-matched agents (backend-1, frontend-2, qa-1, etc.) 3. Assign tasks respecting dependencies and file overlap 4. Monitor progress with progressive stall escalation (60s ping → 120s warn → 180s reassign) 5. Run quality gates between waves (build + test + lint) 6. Verify commits and scope before marking complete
Requirements
- Claude Code CLI
- Implementation plan with task structure (see SKILL.md for format)
- For headless mode:
claude -pavailable in PATH
Architecture
Built entirely on Claude Code's native team primitives:
TeamCreate/TeamDelete- Team lifecycleTaskCreate/TaskUpdate/TaskList- Ledger operationsSendMessage- Agent coordination (DM, broadcast, shutdown)Tasktool - Spawning specialized agents
No external infrastructure needed.
Example
Given a plan with 22 tasks across 3 waves:
Wave 1: 6 parallel tasks (dependency updates)
Wave 2: 12 tasks (8 parallel + 4 serialized due to file overlap)
Wave 3: 4 tasks (final verification + docs)Orchestrate spawns 5 agents, assigns work based on role matching, monitors progress, runs quality gates between waves. Result: ~1 hour wallclock vs 4 hours sequential.
Documentation
- SKILL.md - Full skill specification
- agent-roles.md - Role definitions and model selection
- headless-runner.md -
claude -pconcurrency model - wave-template.md - Quality gate checklist
- prompt-templates/ - Role-specific system prompts for headless mode
License
MIT
#!/usr/bin/env node
const groups = process.argv.slice(2);
if (groups.length < 2) {
console.error('Usage: node check-file-overlap.js "a.ts,b.ts" "b.ts,c.ts" [...]');
process.exit(1);
}
const parsed = groups.map((group) => new Set(group.split(',').map((item) => item.trim()).filter(Boolean)));
let overlaps = 0;
for (let i = 0; i < parsed.length; i += 1) {
for (let j = i + 1; j < parsed.length; j += 1) {
const shared = [...parsed[i]].filter((file) => parsed[j].has(file));
if (shared.length > 0) {
overlaps += 1;
console.log(`OVERLAP\t${i}\t${j}\t${shared.join(',')}`);
}
}
}
if (overlaps === 0) {
console.log('NO_OVERLAP');
}
#!/usr/bin/env bash
set -euo pipefail
SESSION_ID="${1:-$(date +%s)-$(head -c 4 /dev/urandom | xxd -p)}"
ROOT="/tmp/orchestrate/$SESSION_ID"
mkdir -p "$ROOT"
touch "$ROOT/git.lock"
printf 'SESSION_ID=%s\nSESSION_DIR=%s\n' "$SESSION_ID" "$ROOT"
Wave Execution Checklist
Reusable checklist the orchestrator reads for each wave transition. All items must pass before proceeding.
Pre-Wave
Common (Both Modes)
- [ ] All blocking tasks from previous wave are completed and verified
- [ ] Quality gate from previous wave passes (
pnpm build && npx vitest run && pnpm lint) - [ ] Git status is clean (no uncommitted changes from previous wave)
- [ ]
pnpm installis current (no new dependencies pending) - [ ] Task ledger is up to date (no stale in_progress tasks)
Headless Mode Only
- [ ] Session directory exists (
/tmp/orchestrate/{session-id}/) - [ ] No file overlap between concurrent tasks (serialized if overlapping)
- [ ] Prompts generated for all tasks in the wave (inspect with
--dry-run) - [ ] Per-task budgets within session cap
- [ ]
git.lockfile exists for flock-based locking
Interactive Mode Only
- [ ] All agents are idle and ready for assignment
- [ ] Team is active (TeamCreate completed, no stale agents)
During Wave
Common (Both Modes)
- [ ] No scope creep detected (agents staying within assigned files)
- [ ] Status reported to user periodically
- [ ] Each completed task has a verified commit (hash + verify command)
Headless Mode Only
- [ ] All
claude -pprocesses spawned (PIDs recorded in session directory) - [ ] Monitor polling running at 10s intervals
- [ ] No process exceeded timeout threshold (2x estimated duration by default)
- [ ] No budget exceeded events (
total_cost_usdwithin per-task cap) - [ ] Completed task outputs are valid JSON and parseable
Interactive Mode Only
- [ ] All agents acknowledged their assignments within 60s
- [ ] QA watcher is running and reporting after each file change
- [ ] Stall detection running (progressive escalation: 60s/120s/180s)
- [ ] Status reported to user every 3 minutes
Post-Wave
Common (Both Modes)
- [ ] All tasks in the wave are marked completed in the ledger
- [ ] Each task has a corresponding commit with conventional message format
- [ ] Full quality gate passes:
pnpm build(production build succeeds)npx vitest run(all tests pass)pnpm lint(no lint errors)- [ ] Type checks pass per workspace:
cd packages/shared && npx tsc --noEmitcd apps/api && npx tsc --noEmitcd apps/frontend && npx svelte-check --tsconfig ./tsconfig.json --threshold error- [ ] Security scan on changed files:
semgrep scan --config auto <changed-files>(no high/critical findings)- [ ] Wave summary printed with task count, duration, and issues
- [ ] Next wave's dependencies are now unblocked in the ledger
Headless Mode Only
- [ ] All output JSON files present in session directory and parseable
- [ ] Each task has exactly one new commit (scope-verified)
- [ ] No commits touch files outside task scope (revert any violations)
- [ ] Cumulative cost within session budget
- [ ] Failed tasks have been escalated through all tiers or user-resolved
Interactive Mode Only
- [ ] All agents confirmed task completion via SendMessage
- [ ] No stalled agents remaining (reassigned or shut down)
- [ ] Agent idle state is clean (ready for next wave assignment)
Related skills
FAQ
What is the difference between interactive and headless mode?
Interactive uses in-session agents via TeamCreate/Task for coordination-heavy work; headless runs independent claude -p processes for clearly-scoped parallel tasks with about 54% less coordination overhead.
How does orchestrate keep parallel git commits safe?
Every agent must wrap git add and commit in a flock on a shared lock file, because git's index is process-global and concurrent writes silently mix staged files.