plugins/dev/skills/ticket-compound/SKILL.md
Compound-engineering capture + curation for a finished ticket — the engineering feedback loop. Harvests the Friction sections that phase agents left in their artifacts plus the git diff, writes a structured entry to the shared learnings store (thoughts/shared/learnings/), prunes/amends stale notes there autonomously, captures new domain vocabulary to thoughts/shared/CONCEPTS.md, and PROPOSES (for human approval) any ADR change. Non-blocking — runs after a ticket ships or fails, never on the critical path. Use when the user says "compound this ticket", "capture learnings", "what did we learn", or run as /catalyst-dev:ticket-compound <TICKET> [mode:headless].
npx skillsauth add coalesce-labs/catalyst ticket-compoundInstall 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.
Capture what a ticket taught us into the shared store (thoughts/ + ADRs), so future agents on
any machine make better decisions. This is research-curate evolved from inventory to action.
Read reference.md (this dir) for the learnings-store schema before writing anything.
Two authority levels (hard rule):
thoughts/shared/learnings/ and
thoughts/shared/CONCEPTS.md, and prune stale notes in thoughts/shared/{research,plans}/.docs/adrs.md. Never edit an ADR directly; queue
it for the morning ritual to approve./catalyst-dev:ticket-compound <TICKET> [mode:headless]
<TICKET> — Linear key (e.g. CTL-619). If omitted, detect from the branch / CATALYST_TICKET.mode:headless — non-interactive: apply all unambiguous autonomous actions silently, mark
ambiguous learnings status: stale, never block on a prompt, end with the sentinel line. This is
what the morning ritual (and, later, the daemon) use. Default is interactive.For <TICKET>, collect:
## Friction / friction: block the phase agents left in their artifacts:
thoughts/shared/{research,plans}/*<TICKET>*.md and the worker signal files
~/catalyst/workers/<TICKET>/*.json.
thoughts/shared/friction/<TICKET>.md — the dedicated per-phase friction log (primary friction source).git log --oneline origin/main..HEAD and git diff --stat origin/main..HEAD
(or the merged SHA from phase-monitor-merge.json).linearis issues read <TICKET> (title, description, final state, estimate).~/catalyst/events/YYYY-MM.jsonl.Capture learnings from failed/abandoned tickets too — the dead-ends are high-signal ("what didn't work" is a first-class section).
Spawn via Task, all at once. Each returns text to you; you do the single write in Step 3 (avoids partial-write races):
problem_type, category (subdir), component, severity, and a filename slug. Returns the
frontmatter skeleton (validate against reference.md).rg -li "<keywords>" thoughts/shared/learnings/**/*.md, read the
frontmatter of hits, and score overlap (problem, root cause, component, files, prevention). Returns
HIGH (4–5) / MODERATE (2–3) / LOW (0–1) plus the matched paths.last_updated:),
rather than creating a near-duplicate. This is the anti-bloat rule.thoughts/shared/learnings/<category>/<slug>.md.Then validate frontmatter (fail loud on the YAML traps in reference.md):
bash "${CLAUDE_PLUGIN_ROOT:-plugins/dev}/scripts/compound/validate-learnings.sh" "<written-path>"
For the related entries the Finder surfaced, classify and act — autonomously (this is the
thoughts/ layer):
| Outcome | When | Action |
|---|---|---|
| Keep | accurate, refs valid | none |
| Update | core correct, refs/paths drifted | targeted in-place edit |
| Consolidate | 2+ heavily overlap, both correct | merge into the canonical, delete the subsumed |
| Replace | core guidance now misleading | write successor, delete old |
| Delete | implementation gone AND domain gone AND no inbound links | remove (git history preserves) |
Same five-outcome pass applies to stale thoughts/shared/{research,plans}/ notes this ticket
contradicted (the "off-track context that got us redirected"). In mode:headless, only act on
unambiguous cases; mark the rest status: stale + stale_reason.
Scan the diff + friction for Catalyst domain terms not yet in thoughts/shared/CONCEPTS.md (e.g. "reclaim",
"revive-budget", "orphan", "signal ownership"). Append concise definitions. Create the file if absent.
If a learning rises to a standing rule (something every agent must always do/avoid), do NOT edit
docs/adrs.md. Append a proposal to the approval queue:
thoughts/shared/compound/pending/<TICKET>.md
Each proposal: the target ADR (new / amend ADR-NNN / supersede ADR-NNN), the exact proposed text,
and a one-line rationale + evidence (ticket + learning path). The morning ritual surfaces these; a
human approves via briefing-followup's action-compound handler, which is the only thing that
writes docs/adrs.md.
Confirm CLAUDE.md teaches agents that the learnings store exists, its shape, and when to grep it. If
not, propose (interactive) / apply (headless) a minimal pointer — never the learnings themselves:
thoughts/shared/learnings/ — past problem→solution entries (grep by component/tags/problem_type).
Search before implementing or debugging in a known area. Curated by /catalyst-dev:ticket-compound.
✓ ticket-compound complete (headless)
ticket: CTL-619
entry: thoughts/shared/learnings/orchestrator-issues/daemon-false-dead-first-commit.md (created)
curated: 1 updated, 0 deleted ; concepts: +2 ; adr-proposals: 1 (pending approval)
ticket-compound complete
monitor-deploy (manual / morning-ritual triggered for now).compound-estimate owns estimation numbers).ticket-retro (the cross-ticket view — separate slice).testing
Phase-agent that fixes a failing verify verdict so the pipeline self-heals instead of stalling to needs-human (CTL-653). Reads `${ORCH_DIR}/workers/<ticket>/verify.json`, fixes the `findings[]` (every severity:"high" plus the regression_risk drivers) directly via Edit/Write, commits the remediation, and emits `phase.remediate.complete.<ticket>`. The scheduler's router then re-dispatches `verify` to re-check (the verify⇄remediate cycle, cap 3). Dispatched as a `claude --bg` job by `phase-agent-dispatch`, which invokes it via slash command — hence `user-invocable: true`.
tools
--- name: phase-triage description: Phase agent that triages a Linear ticket — expands acronyms, classifies (feature/bug/docs/refactor/chore), identifies genuine blockers (a semantic second-pass over the backlog — NOT a prose scrape; CTL-838), estimates scope, writes triage.json, and posts a triage analysis comment to Linear. Triage completion is signaled by that comment plus the local triage.json — there is no `triaged` label. Emits phase.triage.complete.<TICKET> on success and phase.triage.fai
tools
Phase agent for the research step of the 9-phase orchestrator pipeline (CTL-450). Wraps /catalyst-dev:research-codebase and produces thoughts/shared/research/<date>-<ticket>.md, then emits phase.research.complete.<ticket>. Reads triage.json from the worker dir as its prior-phase artifact. Spawned via plugins/dev/scripts/phase-agent-dispatch, which invokes it via slash command — hence `user-invocable: true`.
development
Phase-agent wrapper that opens the pull request after implementation completes (CTL-449 Initiative 1 Phase 3). Delegates to `/catalyst-dev:create-pr` (which already auto-runs `describe-pr` and transitions Linear to `inReview`), then writes the PR number + URL into the phase signal file so the downstream `phase-monitor-merge` agent can read it without re-querying GitHub. Dispatched as a `claude --bg` job by `phase-agent-dispatch`, which invokes it via slash command — hence `user-invocable: true`.