# Goal Contract

> Spec a rough task into a locked work contract BEFORE starting — Goal, Acceptance, Non-goals, plus the Budget and Tripwire that cap effort. Use before beginning a coding phase, or when the operator says "spec this goal", "pre-goal", "lock a contract", "new phase", "write goals/acceptance/non-goals", or wants to prevent objective-drift and overcorrection (a 1-hour task ballooning into a day). Produces a paste-ready LOCKED CONTRACT block.

- Skill: `webdevtodayjason/goal-contract` (Agent Skill)
- Install (CLI): `npx skillmds@latest add webdevtodayjason/goal-contract`
- Raw SKILL.md: https://api.skillmd.com/api/skills/webdevtodayjason/goal-contract/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Finance & Business
- Author: webdevtodayjason (https://skillmd.com/u/webdevtodayjason)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/webdevtodayjason/goal-contract

---


# Goal Contract

Turn a rough task into a **locked contract** before any code is written. Adds the
missing third leg — **cost** — to the usual goal/acceptance/non-goals, so work
can neither drift off-objective nor balloon past its worth.

## Why — the three legs

Every unit of work needs all three. Most setups have the first two and miss the third:

- **Context** — the situation (claude-mem, vault, ops already provide this).
- **Direction** — Goal + Acceptance + Non-goals.
- **Cost** — Budget + Tripwire. *This is the leg usually missing.* An agent has no
  intrinsic price on its own effort, so without a cost leg it both **wanders**
  (drift) and **over-builds** (a 1-hour job becomes a day). Same hole, two symptoms.

## Workflow

1. **Take the rough statement** of the next task/phase. Ask at most ONE clarifying
   question, and only if the goal is genuinely ambiguous. Do not interrogate.
2. **Draft the contract** using the template below. Acceptance must be observable;
   non-goals concrete; budget real (not "as needed").
3. **Offer a distilled version** — same contract, tighter. Let the user pick full or distilled.
4. **Emit the paste-ready LOCKED CONTRACT block.** The user pastes it back to start work.

## Contract template

- **GOAL** — one sentence, an *outcome* (not a method).
- **ACCEPTANCE** — 2–4 bullets, each observable/testable ("endpoint returns 200", "test passes", "phase < 200ms").
- **NON-GOALS** — concrete things NOT to touch this round (named files, refactors, features, "nice-to-haves").
- **BUDGET** — an effort ceiling. Pick what fits: ~time (e.g. ~1h), ≤N files, or "smallest change that meets acceptance".
- **TRIPWIRE** — if budget is hit, OR scope wants to expand, OR a refactor outside the goal tempts → STOP and report; don't grind.

## Paste-ready output

```
=== LOCKED CONTRACT ===
GOAL: ...
ACCEPTANCE:
  - ...
NON-GOALS:
  - ...
BUDGET: ...
TRIPWIRE: At the budget — or any scope/non-goal temptation — STOP and report before
continuing. No grinding, no gold-plating.
RULES: Restate this contract before the first action. Check every step against GOAL +
NON-GOALS. Report against ACCEPTANCE at the budget and before declaring done.
=== Work only to this contract. ===
```

## Dart ledger (ratified 2026-07-11)

Every locked contract lives in **both places**: locally (this machinery — the local
gates remain the only enforcement) and as a **Dart task — the ledger and source of
truth for history** (https://app.dartai.com).

- **On a machine with the proctor hooks installed, this is automatic** — `dart-ledger.py`
  creates the task at contract-lock (title `⛓ <GOAL>`, tag `goal-contract`, status
  `Doing`, full contract in the description) and closes it at gate-pass (`Done` +
  outcome comment); yields and `/disarm` are commented, not closed. You add no manual step.
- **Board resolution**, first hit wins: `DART_BOARD` env → `Dart board: <Space>/<Board>`
  line in the project's `CLAUDE.md` → `~/.claude/goal-contract/dart-boards.json` →
  fallback `Space/Richard-Jason-Projects` with a `[project]` title prefix.
- **No hooks here (other machine, headless)?** Do it via Dart MCP: `create_task` at lock
  with the same conventions, `update_task` to `Done` + `add_task_comment` with the final
  disposition at close. The ledger entry is part of the contract — not optional.
- Verify plumbing anytime: `python3 ~/.claude/hooks/goal-contract/dart-ledger.py --status`
  (token + board for cwd) or `--selftest`.

## For the agent executing a locked contract

- Restate GOAL + NON-GOALS in one line before the first action.
- **The smallest change that meets ACCEPTANCE wins.** Extra tests, abstractions, or
  cleanup not named in ACCEPTANCE are non-goals — adding them is overcorrection.
- **Pre-existing brokenness is the one carve-out from "smallest change."** If you walk
  into a failing test, type debt, dead code, or a stale doc — in a file you're touching,
  or otherwise cheap — **fix it; don't note-and-leave.** If the honest fix would blow the
  budget/scope, that's a tripwire: STOP, surface it *with the measured cost*, and let the
  user choose (expand now vs. explicitly defer). This is distinct from gold-plating
  above: adding things nobody asked for is still overcorrection; leaving existing
  brokenness noted-but-unowned is not allowed. "The linter will catch it" is banned.
  **Owned means you are taking the problem into this contract to fix it before done** —
  not that you appended a Follow-Up and walked away. If something truly cannot be fixed
  inside this contract, call it deferred/operator-blocked, with owner + next action + proof,
  and state whether the goal is blocked.
- Hit the budget, or tempted past scope? **Stop and report** — never unilaterally decide to go bigger.

## Example

Rough input: *"make the app faster, the startup is slow"*

```
=== LOCKED CONTRACT ===
GOAL: Cut cold-start latency so the service is ready to serve in under a second.
ACCEPTANCE:
  - startup < 1s (startup benchmark)
  - endpoints unchanged (no behavior change)
NON-GOALS:
  - the request cache, the installer, the dashboard, the migration runner
BUDGET: ~half-day, ≤4 files, behind the existing loader.
TRIPWIRE: if it needs a new subsystem or touches >4 files, STOP and report. No grinding.
RULES: Restate before starting. Check each step against GOAL + NON-GOALS. Report at budget and before done.
=== Work only to this contract. ===
```

