Skip to main content

Turn a spec into a frozen acceptance harness enforced via Claude Code Stop hook.

Project description

specgate

Turn a spec into a frozen acceptance harness, then enforce it as a Claude Code Stop hook — so the agent literally cannot end its turn until every criterion passes.

Core invariant

The agent that writes the code must never be able to alter the harness that grades it.

The harness is generated and human-approved before implementation begins, then frozen by a SHA-256 hash. The Stop-hook gate re-verifies that hash on every run. A hash mismatch is a hard block — the agent cannot weaken its own test.

Install

pipx install specgate

Requires Python 3.11+. No runtime dependencies.

The generate → freeze → enforce flow

1. Init (once per repo)

cd my-repo
specgate init

Creates .specgate/ and merges a Stop-hook entry into .claude/settings.json. Existing hooks are preserved.

2. Write a spec

Write a spec file with concrete, measurable requirements:

# Feature: Password Reset

1. POST /password-reset with a valid email returns HTTP 202 and enqueues one email.
2. A reset token is single-use; a second attempt returns HTTP 400.
3. Tokens expire after exactly 24 hours.

Vague specs are rejected by specgate generate. Clarify first.

3. Generate the harness

specgate generate issues/password-reset.md

Calls claude -p to extract acceptance criteria and emit pytest check files into .specgate/harness/. Prints a summary of every criterion for review. manifest.json is written with approved: false.

4. Review and freeze (human sign-off)

Read the summary. Inspect the generated checks in .specgate/harness/. Edit them if needed. When satisfied:

specgate freeze

This computes a SHA-256 hash over the harness directory, stores it in manifest.json, and sets approved: true. From this point, the harness is the definition of done.

5. Implement

Tell the agent to implement the feature. The Stop hook fires at the end of every reply:

  • If the harness passes → the turn ends normally.
  • If any criterion fails → the agent receives a specific, actionable block reason naming the failing criteria and is forced to continue.
  • If the hash has changed → hard block: the agent is told to restore the harness. It cannot bypass this.
  • After 5 consecutive blocks → the agent is instructed to summarize its attempts and ask the human for guidance (before the 8-block Claude Code cap).

Debug manually

specgate check     # same code path as the hook — prints pass/fail per criterion
specgate status    # show approval state, hash match, block count

Gate protocol (Stop hook)

The hook receives JSON on stdin and writes to stdout:

  • Block: {"decision": "block", "reason": "<specific failing criteria + hint>"}, exit 0.
  • Pass: no output, exit 0.
  • Loop guard: if stop_hook_active is true, exit 0 immediately — prevents infinite loops.

.specgate/ layout

.specgate/
  harness/          ← generated pytest checks (frozen by hash)
  manifest.json     ← criteria, check map, hash, approval flag
  state.json        ← block counter, last run (written by gate, never committed)

Commit .specgate/harness/ and .specgate/manifest.json. Do not commit state.json.

Configuration

Env var Default Purpose
SPECGATE_ESCALATION 5 Block count before "ask the human" escalation
SPECGATE_TIMEOUT 120 Wall-clock budget (seconds) for the harness run
SPECGATE_BACKEND_TIMEOUT 120 Timeout for claude -p generation calls

Constraints

  • Standard library only — no runtime dependencies.
  • Generation backend: claude -p (Claude Code CLI) — reuses your existing auth.
  • Generated harness may use the target repo's test framework (default: pytest).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

specgate_cli-0.2.0.tar.gz (19.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

specgate_cli-0.2.0-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file specgate_cli-0.2.0.tar.gz.

File metadata

  • Download URL: specgate_cli-0.2.0.tar.gz
  • Upload date:
  • Size: 19.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for specgate_cli-0.2.0.tar.gz
Algorithm Hash digest
SHA256 a872d310e4d8eeca1ae7da0810a1169d7e21e6b6a9ef7857ac6b4b4bf20a2cec
MD5 d684a30a398e9cf71e8537d8f87770c6
BLAKE2b-256 8d4fbe942268f1e39d08a6125139c067d89e64bf162e091c73d7d94cf80fc988

See more details on using hashes here.

File details

Details for the file specgate_cli-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: specgate_cli-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for specgate_cli-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 844a69300c1b144e5513cc468f24c27b8e96e060cab24e8bf8dc326ed1a803a8
MD5 609f125494431a00e862f8c0d1005982
BLAKE2b-256 844ff64f67a201abe87277a3620ac7b62d90830e27e4b07b2c3fae5efbc39ca9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page