---
name: goal-craft
description: >
  Turn a rough task — or a Jira/Linear ticket — into one strong, verifiable, ready-to-run
  /goal command for Claude Code's built-in /goal feature. Use this whenever the user wants
  to set a goal, write or sharpen a /goal condition, turn a ticket into a goal, kick off
  autonomous multi-turn work, or decide when an agent should stop on its own. Invoke as
  "/goal-craft TICKET-ID" (e.g. /goal-craft DEC-8527) to read that ticket — Jira or Linear
  depending on the project's config — and craft it into a goal; "/goal-craft <task>" for a
  freeform task; or "/goal-craft" alone to use the current conversation. Produces a single,
  concrete /goal command — no placeholders, nothing to paste first — that the user can copy
  straight into any session. Trigger on mentions of "/goal", "completion condition",
  "stopping condition", "let it run until...", "autonomous goal", "work until done", "turn
  this ticket into a goal", or a bare ticket ID handed to goal-craft — even if the user
  never names a framework. Prefer this skill over free-handing a /goal condition: a vague or
  unbounded condition is the main reason autonomous runs loop, stop early, or game their own
  success check.
---

# goal-craft

Turn a task into **one ready-to-run `/goal` command** — verifiable, bounded, and hard to
game. The command is the entire deliverable: the user copies it and pastes it into a
session (maybe a fresh one), so it must be concrete and self-contained.

## Why this shape

`/goal <condition>` makes Claude work autonomously across turns until the condition is met.
After **every turn**, a small fast model (Claude Haiku) re-reads the condition and the
environment and answers yes/no: done yet? If yes, the run stops. If no, the reason guides
the next turn. That drives two rules:

1. **Judged from observable state.** The condition must resolve to something checkable — a
   command exit code, a test count, a file's contents, an observable fact — not a subjective
   "looks good." If a cheap model can't confidently say yes/no, the run stops early or never
   stops.
2. **One concrete, self-contained command.** Everything that decides "done" rides *inside*
   the command: the check, the guardrails that keep it honest, and the give-up bound. There
   is no separate "context to paste first," and **no placeholders** like `<path>` — every
   value is filled in (resolved during the interview, see step 3). What stays out:
   process/how-to instructions and rationale, which aren't part of "done."

## The three-part frame (how to think — it all lands in one command)

Map the task onto three parts. They are a thinking tool; they converge into a single
`/goal` line, not three artifacts:

| Part | What it is | Where it lands |
|---|---|---|
| **1. Outcome state** | the done-state of the system — a *state*, not a task list | shapes the condition (usually implicit) |
| **2. Success check** | the verifiable predicate + give-up bound that decides "done" | the core of the command |
| **3. Guardrails** | the shortcuts that would satisfy the words while betraying the intent | folded into the command as part of "done" (e.g. "…without deleting any test") |

The move that stops reward-hacking: write the success check, then fold in a guard against
the *cheapest way to fake it*.

## Workflow

### 1. Identify the input
goal-craft has three entry points:

- **`/goal-craft TICKET-ID`** — an argument shaped like `DEC-8527` or `ENG-42`
  (`^[A-Z][A-Z0-9]+-\d+$`). Read that ticket from the project's tracker and craft the goal
  from it. Follow **`references/from-ticket.md`** for tracker detection, fetching, and
  mapping the ticket onto the three parts.
- **`/goal-craft <task description>`** — craft from the free-form task the user gave.
- **`/goal-craft` with no argument** — craft from the current conversation.

### 2. Map the source onto the three parts
Pull out the outcome state, any implied success check, and any constraints. **Reuse
whatever is already written** — a ticket's acceptance criteria or Definition of Done, a
spec, prior conversation. Keep the intent; tighten only what isn't objectively verifiable.

### 3. Fill every gap — including the concrete specifics
Two kinds of gap, both closed *before* emitting, because the command ships with no
placeholders:

- **Measurability gaps** — verification (how "done" is checked), the bound (when it gives
  up), and the guardrails (what would game it).
- **Concrete specifics** — the exact values the command needs to run as-is: output
  path/filename, source repo or table, the command to invoke, the threshold or lookback
  window. These are resolved now, never emitted as `<path>`.

How you close them depends on whether the user's around:

- **Present** (the normal case, incl. `/goal-craft TICKET-ID`): ask the *few* targeted
  questions that materially change measurability, scope, or a required concrete value (aim
  for one to three). If the command needs a path or a source you don't know, that's a
  question — don't emit a placeholder for it.
- **Unavailable / wants speed**: ground the value by investigating, or pick a concrete,
  sensible default and state it in one line ("writing to `analysis/unused-columns.csv` —
  move it if you'd rather"). Still no placeholders.

Either way, **investigate first** — a grounded value (the suite uses Django's runner; the
repo convention is `analysis/*.csv`) beats guessing or asking. Never ship a goal you can't
verify; if no objective check exists, standing one up is the real first task.

### 4. Emit — one command, nothing else
Output a single `/goal` command in one code block: the observable condition, the folded-in
guardrails, and the give-up bound — every value concrete. **That is the whole output.** The
user copies it and runs it. At most one short line beneath, and only if you made an
assumption worth flagging. No "set context first" block, no rationale, no caveats.

```
/goal <one concrete, self-contained condition: names the observable check, folds in the guard against gaming it, and ends with a give-up bound>
```

Keep process/how-to steps and explanation *out* of the command — the per-turn evaluator
only needs what decides "done," and extra text gives it more to misjudge. Fold in a
guardrail only when it's genuinely a completion gate (no test deleted; nothing modified
outside `src/auth/`); skip generic advice. Keep guard clauses terse so the line stays
readable.

## The quality bar

Before handing it over, check the command against these. If it fails one, fix it or say why
it can't be met.

- **Verifiable** — resolves to an observable yes/no (exit code, test count, file
  exists/matches, queue empty), not "looks correct." A Haiku-class model must be able to
  judge it from what it can see. If "done" means several things at once, name them all —
  the evaluator only checks what you state.
- **Bounded** — has an explicit give-up / escalate condition so a stuck run doesn't loop
  forever. A success predicate with no stop is incomplete.
- **Honest** — can't be satisfied by gaming the check. Fold a guard against the cheapest
  cheat *into the command* (e.g. "…without deleting, skipping, or weakening any test"). The
  agent optimizes the *letter* of the goal; close the obvious loopholes.
- **Concrete** — runs as-is: real paths, commands, thresholds. No `<placeholders>`; if you
  were tempted to write one, that was a question for step 3.
- **Single, coherent target** — one outcome. If the request bundles unrelated goals, split
  them; an evaluator can't cleanly judge "A and also unrelated B."

## Examples

**Example 1 — "fix the failing auth tests"**

Weak: `/goal the tests pass` — unverifiable scope, no bound, trivially gamed by deleting
tests.

Strong:
```
/goal `pytest tests/auth` exits 0 with zero skipped or xfail-ed tests and a collected-test count >= the count before changes, with fixes made in src/auth/ source rather than by editing, deleting, or weakening any test; give up and summarize the blocking failures after 3 unsuccessful fix attempts
```

**Example 2 — "keep improving the page load speed"**

Unbounded and unverifiable as written. Concrete and bounded:
```
/goal a production Lighthouse CI run reports the dashboard's cold-load LCP < 2.5s with the full test suite green, achieved without removing or lazy-deferring content to fake the metric and without editing the Lighthouse config or thresholds; give up and report the remaining bottlenecks after 5 attempts or if the budget proves infeasible
```

Both are one line, fully concrete, copy-and-run. The outcome state is implicit in the
condition; the guardrails are folded in as part of "done"; the bound ends the loop.

## Failure modes you're defending against

- **No stopping condition** → the agent over-works past done or loops. Fixed by the bound.
- **Vague "looks good" success** → the evaluator can't judge it; runs stop early or never.
  Fixed by a machine-checkable predicate.
- **Reward hacking / specification gaming** → the agent satisfies the literal words by
  cheating (deletes tests, edits the grader). Fixed by folding a guard into the command.
- **Placeholders / "fill this in later"** → a command that won't run as pasted. Fixed by
  resolving every concrete value in the interview.
- **Goal drift** → bundled or fuzzy objectives. Fixed by one coherent outcome.
