/goal-chain
Run a linear sequence of goalkeeper goals where the judge gates progression between them. Use when the user invokes /goal-chain "<file>" to start a chain. Also auto-invoked by the judge skill on approval to advance the chain cursor.
$ npx -y skills add bonfire-systems/goalkeeper --skill goal-chain --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/goal-chain
Context preview
The summary Claude sees to decide when to auto-load this skill.
Run a linear sequence of goalkeeper goals where the judge gates progression between them. Use when the user invokes /goal-chain "<file>" to start a chain. Also auto-invoked by the judge skill on approval to advance the chain cursor.
SKILL.md
goal-chain.SKILL.mdname: goal-chain
description: Run a linear sequence of goalkeeper goals where the judge gates progression between them. Use when the user invokes /goal-chain "<file>" to start a chain. Also auto-invoked by the judge skill on approval to advance the chain cursor.
You are operating the **goal-chain** skill. A chain is a linear ordered list of goal slugs that execute one after another, gated by judge approval at each step.
Modes
The skill operates in one of three modes determined by args and state:
1. **Start mode** — `args` is a non-empty path to a chain file. Begin a new chain. 2. **Advance mode** — invoked by the judge skill after approve. No args. Move cursor forward. 3. **Status mode** — `args == "status"` or chain exists and user asks plainly. Show progress.
Start mode
Triggered by `/goal-chain "<path/to/chain.md>"`.
1. Parse chain file
The chain file is a markdown document with optional frontmatter and an ordered list of slugs. Accepted formats:
---
name: my-chain-name
---
1. first-goal-slug
2. second-goal-slug
3. third-goal-slug
Or with bullets:
- first-goal-slug
- second-goal-slug
Extract slugs from numbered list items or bullets. Trim whitespace. Strip any trailing comments after `#`.
2. Validate every slug has a contract
For each slug, verify `.claude/goals/<slug>/contract.md` exists. If any are missing, list them and stop. Tell the user to run `/goal-prep` for each missing slug, or remove them from the chain file.
3. Refuse to overlap
If `.claude/goals/active.json` shows an active goal, or `.claude/goals/chain.json` exists with status `active`, refuse and tell the user to `/goal-clear` first.
4. Write chain.json
Per the canonical chain.json shape (see goal.md "Canonical state shapes"):
{
"name": "<from frontmatter or filename>",
"slugs": ["...", "..."],
"cursor": 0,
"status": "active",
"started_at": "<ISO8601>",
"completed_at": null,
"source_file": "<absolute path to chain file>",
"link_approvals": []
}`link_approvals` starts empty and accumulates one entry per judge-approved link as the chain advances.
5. Activate the first slug
Write `.claude/goals/active.json` per the canonical active shape with `chain` populated:
{
"slug": "<slugs[0]>",
"activated_at": "<ISO8601>",
"chain": "<chain name>"
}Initialize that goal's `state.json` per the canonical state.json shape (status=active, rejection_count=0, started_at=now, started_at_commit=`git rev-parse HEAD`, started_at_dirty_paths=`git status --porcelain`, chain_step=1). Append to its `log.md`:
## <ISO8601> — activated (chain step 1/<N>)
Chain: <name>. Starting first goal: <slug>.
6. Spawn the executor subagent
**v0.3+:** chains run their per-goal execution in a **fresh-context subagent** instead of the main conversation. Main context only orchestrates — spawning executor, spawning judge, applying verdict, advancing cursor. This is the load-bearing change that lets a chain run autonomously across many goals without main-context aging out.
Use the Agent tool with `subagent_type: general-purpose`. Pass a self-contained prompt:
1. **The full `contract.md`** — verbatim. 2. **The full `log.md`** — verbatim (so the executor sees the activation entry + any prior checkpoints if this is a re-spawn after judge rejection). 3. **Chain context** — chain name, current cursor position, total slugs, the prior link's approval timestamp. 4. **Repo state** — `git rev-parse HEAD`, `git status --porcelain` (first 20 lines). 5. **The directive** — verbatim, in this exact format:
You are the goalkeeper EXECUTOR SUBAGENT for goal `<slug>` (chain step <N>/<total>).
Your job: read the contract above, execute every Definition-of-Done item, run
the validator at the end, and return a structured summary. You operate in a
fresh context — you have no conversation history beyond this prompt. The
contract is your spec; do not improvise outside it.
Execution loop:
1. Read the contract carefully. Identify the implementation work required.
2. Do the work. Edit/write files as needed. Follow the contract's non-goals
and anti-placeholder rule strictly.
3. Append checkpoint entries to `.claude/goals/<slug>/log.md` as you go
(one per logical sub-task or every ~5 file edits — whichever is more
natural for the work).
4. Run the validator: `<validator.command>`. Capture stdout+stderr.
5. If validator FAILS: diagnose, fix, re-run. Repeat up to a reasonable
attempt budget (~3-5 inner attempts). If still failing, document why
in the log and return with status=blocked.
6. If validator PASSES: append a "validator passed" entry to the log,
update `.claude/goals/<slug>/state.json` with last_validator_result=pass
and last_checkpoint_at, then return.
DO NOT spawn the judge yourself. The chain orchestrator handles that step.
DO NOT advance the chain cursor. DO NOT modify chain.json, active.json, or
the goals_completed list. DO NOT activate the next goal. Just do the work
for THIS goal and return.
Return ONCE with this structured output:
STATUS: validator_pass | validator_fail | blocked | needs_clarification
SUMMARY:
<3-8 sentences describing what you did: files touched, decisions made, any
non-obvious tradeoffs, anything the judge should pay particular attention to>
VALIDATOR_OUTPUT_TAIL:
<last ~40 lines of the validator's stdout+stderr — let the judge see the
actual pass/fail signal directly>
FILES_CHANGED:
<bulleted list of paths modified relative to repo root, plus brief one-line
note per file about what changed>
BLOCKERS: (only if status != validator_pass)
<specific reason: which DoD item, which file, what's missing or wrong>7. Receive executor return, spawn judge
When the executor subagent returns its structured summary:
- **STATUS = blocked or needs_clarification** — append a `## <ISO8601> — executor blocked` entry to the goal's log with the BLOCKERS verbati
Read more
name: goal-chain description: Run a linear sequence of goalkeeper goals where the judge gates progression between them. Use when the user invokes /goal-chain "<file>" to start a chain. Also auto-invoked by the judge skill on approval to advance the chain cursor.
You are operating the **goal-chain** skill. A chain is a linear ordered list of goal slugs that execute one after another, gated by judge approval at each step.
Modes
The skill operates in one of three modes determined by args and state:
1. **Start mode** — `args` is a non-empty path to a chain file. Begin a new chain. 2. **Advance mode** — invoked by the judge skill after approve. No args. Move cursor forward. 3. **Status mode** — `args == "status"` or chain exists and user asks plainly. Show progress.
Start mode
Triggered by `/goal-chain "<path/to/chain.md>"`.
1. Parse chain file
The chain file is a markdown document with optional frontmatter and an ordered list of slugs. Accepted formats:
--- name: my-chain-name --- 1. first-goal-slug 2. second-goal-slug 3. third-goal-slug
Or with bullets:
- first-goal-slug - second-goal-slug
Extract slugs from numbered list items or bullets. Trim whitespace. Strip any trailing comments after `#`.
2. Validate every slug has a contract
For each slug, verify `.claude/goals/<slug>/contract.md` exists. If any are missing, list them and stop. Tell the user to run `/goal-prep` for each missing slug, or remove them from the chain file.
3. Refuse to overlap
If `.claude/goals/active.json` shows an active goal, or `.claude/goals/chain.json` exists with status `active`, refuse and tell the user to `/goal-clear` first.
4. Write chain.json
Per the canonical chain.json shape (see goal.md "Canonical state shapes"):
{
"name": "<from frontmatter or filename>",
"slugs": ["...", "..."],
"cursor": 0,
"status": "active",
"started_at": "<ISO8601>",
"completed_at": null,
"source_file": "<absolute path to chain file>",
"link_approvals": []
}`link_approvals` starts empty and accumulates one entry per judge-approved link as the chain advances.
5. Activate the first slug
Write `.claude/goals/active.json` per the canonical active shape with `chain` populated:
{
"slug": "<slugs[0]>",
"activated_at": "<ISO8601>",
"chain": "<chain name>"
}Initialize that goal's `state.json` per the canonical state.json shape (status=active, rejection_count=0, started_at=now, started_at_commit=`git rev-parse HEAD`, started_at_dirty_paths=`git status --porcelain`, chain_step=1). Append to its `log.md`:
## <ISO8601> — activated (chain step 1/<N>) Chain: <name>. Starting first goal: <slug>.
6. Spawn the executor subagent
**v0.3+:** chains run their per-goal execution in a **fresh-context subagent** instead of the main conversation. Main context only orchestrates — spawning executor, spawning judge, applying verdict, advancing cursor. This is the load-bearing change that lets a chain run autonomously across many goals without main-context aging out.
Use the Agent tool with `subagent_type: general-purpose`. Pass a self-contained prompt:
1. **The full `contract.md`** — verbatim. 2. **The full `log.md`** — verbatim (so the executor sees the activation entry + any prior checkpoints if this is a re-spawn after judge rejection). 3. **Chain context** — chain name, current cursor position, total slugs, the prior link's approval timestamp. 4. **Repo state** — `git rev-parse HEAD`, `git status --porcelain` (first 20 lines). 5. **The directive** — verbatim, in this exact format:
You are the goalkeeper EXECUTOR SUBAGENT for goal `<slug>` (chain step <N>/<total>).
Your job: read the contract above, execute every Definition-of-Done item, run
the validator at the end, and return a structured summary. You operate in a
fresh context — you have no conversation history beyond this prompt. The
contract is your spec; do not improvise outside it.
Execution loop:
1. Read the contract carefully. Identify the implementation work required.
2. Do the work. Edit/write files as needed. Follow the contract's non-goals
and anti-placeholder rule strictly.
3. Append checkpoint entries to `.claude/goals/<slug>/log.md` as you go
(one per logical sub-task or every ~5 file edits — whichever is more
natural for the work).
4. Run the validator: `<validator.command>`. Capture stdout+stderr.
5. If validator FAILS: diagnose, fix, re-run. Repeat up to a reasonable
attempt budget (~3-5 inner attempts). If still failing, document why
in the log and return with status=blocked.
6. If validator PASSES: append a "validator passed" entry to the log,
update `.claude/goals/<slug>/state.json` with last_validator_result=pass
and last_checkpoint_at, then return.
DO NOT spawn the judge yourself. The chain orchestrator handles that step.
DO NOT advance the chain cursor. DO NOT modify chain.json, active.json, or
the goals_completed list. DO NOT activate the next goal. Just do the work
for THIS goal and return.
Return ONCE with this structured output:
STATUS: validator_pass | validator_fail | blocked | needs_clarification
SUMMARY:
<3-8 sentences describing what you did: files touched, decisions made, any
non-obvious tradeoffs, anything the judge should pay particular attention to>
VALIDATOR_OUTPUT_TAIL:
<last ~40 lines of the validator's stdout+stderr — let the judge see the
actual pass/fail signal directly>
FILES_CHANGED:
<bulleted list of paths modified relative to repo root, plus brief one-line
note per file about what changed>
BLOCKERS: (only if status != validator_pass)
<specific reason: which DoD item, which file, what's missing or wrong>7. Receive executor return, spawn judge
When the executor subagent returns its structured summary:
- **STATUS = blocked or needs_clarification** — append a `## <ISO8601> — executor blocked` entry to the goal's log with the BLOCKERS verbati
Showing the first part of this file.
Durable contract-driven goal execution for Claude Code. A subagent judge gates completion against an explicit Definition of Done.
Repo: bonfire-systems/goalkeeper
Other skills on goalkeeper.
- /goal-clear
Stop and archive the currently active goalkeeper goal. Use when the user invokes /goal-clear to abandon or finalize a goal. Files are moved to .claude/goals/_archive/, never deleted.
Open skill - /goal-judge
The gate. Reviews the active goalkeeper goal against its definition-of-done and either approves (advance / mark done) or rejects (with a structured fix-list). Auto-fired by the goal skill when the validator passes (inline mode), or invoked by the goal-chain orchestrator after
Open skill - /goal-pause
Pause the currently active goalkeeper goal without losing state. Use when the user invokes /goal-pause. The goal can later be resumed with /goal-resume.
Open skill - /goal-prep
Interactively draft a goalkeeper contract before executing. Use this skill when the user invokes /goal-prep "<rough idea>", or when /goal is called for a slug that has no contract yet. Produces a well-formed contract.md with explicit objective, definition-of-done, validator
Open skill - /goal-resume
Resume a paused or needs_human goalkeeper goal. Use when the user invokes /goal-resume after they've manually unblocked the goal (e.g. fixed a problem the judge flagged).
Open skill - /goal-supervisor
The mission-level supervisor. One level above goals. Reads the user's mission charter and the most-recently-completed goal's artifacts, then decides whether to PROCEED (draft + activate the next goal), declare the mission DONE, or ESCALATE to the user. Use this skill when the
Open skill

