Receber por email
← Voltar para o catálogo

_phase-agent-template

Reference template every phase-agent skill copies (CTL-448). The leading underscore on the directory name prevents the skill loader from picking this up — it is NOT a runnable skill, only a structural template the nine real phase agents (phase-triage, phase-research, phase-plan, phase-implement, phase-verify, phase-review, phase-pr, phase-monitor-merge, phase-monitor-deploy) clone and specialize.

18estrelas
Atualizado há 3 meses

Ver no GitHub ↗

Como adicionar

/plugin marketplace add coalesce-labs/catalyst

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/phase-agent-template/svg)](https://www.skillteca.com.br/skills/phase-agent-template)

Skills relacionadas

Ver todas de DevOps e Infra →

Alerta por categoria

Receba novas skills de DevOps e Infra toda segunda

1 email curto, só com as skills novas de DevOps e Infra. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

_phase-agent-template

This is the structural template for every phase agent in Initiative 1 (plan §"Phase-agent architecture"). It is NOT itself a skill — phase-N SKILL.md files copy this skeleton and fill in the placeholders marked with {{...}}. The leading underscore on this directory keeps the skill loader from registering it. The real phase skills set user-invocable: true because phase-agent-dispatch spawns them via claude --bg "/catalyst-dev:phase-X ..." — the bg session parses that as a user slash command (CTL-490).

Contract

Every phase agent:

  1. Joins the shared orch-${CATALYST_ORCHESTRATOR_ID} comms channel at entry
  2. Reads the prior phase artifact (see lookup table in

plugins/dev/scripts/phase-agent-dispatch) — abort if missing.

  1. Starts a catalyst-session and writes per-phase status updates.
  2. Does the phase-specific work — delegates to a canonical skill via the

Task tool wherever possible. See plan §"Phase agents wrap canonical skills" for the mapping.

  1. On exit, calls plugins/dev/scripts/phase-agent-emit-complete which:
  2. Emits the canonical phase.<name>.{complete,failed}.<ticket> event

(broker phase_lifecycle route — CTL-447).

  • Updates ${ORCH_DIR}/workers/<TICKET>/phase-<name>.json.
  • Calls catalyst-session.sh end.
  1. Linear reads → local replica. For a single-ticket read, prefer

sqlite3 "${CATALYST_REPLICA_DB:-${CATALYST_DIR:-$HOME/catalyst}/catalyst-replica.db}" (bg-safe — resolves in any shell, never 429s; the ${…} is the canonical path resolver, so an install that sets CATALYST_REPLICA_DB/CATALYST_DIR still hits the right DB). linear_read_ticket <ID> is the same read but is a plugin shell function: it only resolves if you first source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/linear-read-replica.sh", else it is "command not found" and you silently fall through to bare linearis. Never a bare linearis/linear issues read <ID> — it 429s the shared quota. Writes and issues list/search stay on linearis. See the linearis skill's "Reading Linear".

Required env vars

The dispatcher (plugins/dev/scripts/phase-agent-dispatch) sets these on the spawned claude --bg process. The phase agent reads them at startup:

| Var | Meaning | |---|---| | CATALYST_ORCHESTRATOR_DIR | Where signal files live (workers/<TICKET>/phase-<name>.json) | | CATALYST_ORCHESTRATOR_ID | Broker session correlation + comms channel suffix | | CATALYST_PHASE | This phase's name (matches the skill suffix) | | CATALYST_TICKET | The ticket this phase agent owns |

Prelude (every phase agent copies this verbatim)

set -euo pipefail

: "${CATALYST_ORCHESTRATOR_DIR:?required (set by phase-agent-dispatch)}"
: "${CATALYST_ORCHESTRATOR_ID:?required}"
: "${CATALYST_PHASE:?required}"
: "${CATALYST_TICKET:?required}"

ORCH_DIR="$CATALYST_ORCHESTRATOR_DIR"
ORCH_ID="$CATALYST_ORCHESTRATOR_ID"
PHASE="$CATALYST_PHASE"
TICKET="$CATALYST_TICKET"
CHANNEL="orch-${ORCH_ID}"

SIGNAL_FILE="${ORCH_DIR}/workers/${TICKET}/phase-${PHASE}.json"
[[ -f "$SIGNAL_FILE" ]] || { echo "phase-${PHASE}: signal file missing" >&2; exit 1; }

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-/Users/ryan/.claude/plugins/cache/catalyst/catalyst-dev/$(jq -r .version "${CLAUDE_PLUGIN_ROOT:-.}/.claude-plugin/plugin.json" 2>/dev/null || echo 0.0.0)}"

# 0. Codified bg_job_id yield (CTL-615). If the signal file's bg_job_id
#    names a DIFFERENT live bg job, we are a redispatch duplicate of a
#    still-running canonical worker. Bow out without touching the signal,
#    without emitting any phase event. The helper writes a yield sidecar
#    `${ORCH_DIR}/workers/${TICKET}/.phase-${PHASE}-yield` so the
#    operator/daemon can attribute the no-op. Exit 0 by design — this is
#    NOT a failure; the canonical worker keeps running.
YIELD_CHECK="${PLUGIN_ROOT}/scripts/phase-agent-yield-check.sh"
if [[ -x "$YIELD_CHECK" ]] && bash "$YIELD_CHECK" \
     --signal "$SIGNAL_FILE" \
     --phase "$PHASE" \
     --worker-dir "$(dirname "$SIGNAL_FILE")"; then
  echo "phase-${PHASE}: yielding to canonical worker (CTL-615)" >&2
  exit 0
fi

# 1. Join the shared comms channel (best-effort — phase agents must not crash
#    if catalyst-comms is unavailable).
COMMS="${PLUGIN_ROOT}/scripts/catalyst-comms"
[[ -x "$COMMS" ]] || COMMS="$(command -v catalyst-comms 2>/dev/null || true)"
if [[ -n "$COMMS" ]]; then
  "$COMMS" join "$CHANNEL" --as "$TICKET" \
    --capabilities "phase-${PHASE}: ${TICKET}" \
    --orch "$ORCH_ID" --parent orchestrator --ttl 3600 >/dev/null 2>&1 || true
  "$COMMS" send "$CHANNEL" "phase-${PHASE} started" --as "$TICKET" --type info \
    --orch "$ORCH_ID" >/dev/null 2>&1 || true
fi

# 2. Start a catalyst-session (cost / token instrumentation).
SESSION_SCRIPT="${PLUGIN_ROOT}/scripts/catalyst-session.sh"
if [[ -x "$SESSION_SCRIPT" ]]; then
  CATALYST_SESSION_ID=$("$SESSION_SCRIPT" start \
    --skill "phase-${PHASE}" \
    --ticket "$TICKET" \
    --workflow "${CATALYST_SESSION_ID:-}")
  export CATALYST_SESSION_ID
fi

# 3. Mark the signal file as "running" + record the start timestamp +
#    persist catalystSessionId (CTL-496: orchestrate-roll-usage --phase
#    reads this to attribute cost to the right session_metrics row without
#    relying on the ticket+skill_name DB-lookup heuristic).
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
TMP="${SIGNAL_FILE}.tmp.$$"
jq --arg ts "$TS" --arg sid "${CATALYST_SESSION_ID:-}" '
  .status = "running"
  | .updatedAt = $ts
  | if $sid != "" then .catalystSessionId = $sid else . end
' "$SIGNAL_FILE" > "$TMP" \
  && mv "$TMP" "$SIGNAL_FILE"

/goal condition

Every phase agent declares a /goal line at the top of its phase-specific work block. The condition MUST be transcript-evaluable and reference the artifact this phase produces (per the lookup table in phase-agent-dispatch). Example for phase-research:

/goal "I have written thoughts/shared/research/<date>-${TICKET,,}.md
       with valid frontmatter and at least 10 file:line references AND I
       have printed the path + a confirmation line; OR I have stopped
       after 35 turns and printed what's done."

Turn caps come from .catalyst/config.json:catalyst.orchestration.phaseAgents.turnCaps.<phase> with per-phase defaults baked into phase-agent-dispatch.

Comms discipline (CTL-448)

Outbound message types — phase agent → orchestrator:

| Type | When | Cadence per session | |-------------|-----------------------------------------------|---------------------| | info | Phase started / phase work milestones | 3–5 | | attention | Scope conflict, missing access, repeated failures, stalled | 0–2 | | question | Specific clarification needed (msg_id is correlation key) | 0–1 | | done | Terminal success (emitted by phase-agent-emit-complete) | 1 |

Inbound message types — orchestrator → phase agent (reads on every loop tick):

| Type | Effect | |-------------|-------------------------------------------------------------| | directive | Answer to a previously-posted question (correlated via .re field). Phase agent uses the answer and proceeds. | | pause | Halt and poll. Resumes on directive or info resume signal. | | abort | Phase agent cleans up, calls phase-agent-emit-complete with --status failed --reason aborted_by_orchestrator, exits. |

Use the helper functions in plugins/dev/scripts/catalyst-comms directly — do NOT reimplement send/poll logic per phase. The contract tests live in plugins/dev/scripts/__tests__/phase-agent-comms.test.sh.

Phase-specific work block (TEMPLATE)

/goal "{{ transcript-evaluable goal condition for this phase }}"

{{ Phase-specific instructions. The actual work delegates to the canonical
   skill (e.g., /catalyst-dev:research-codebase) via the Task tool wherever
Compartilhar X LinkedIn