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.1.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.1-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: specgate_cli-0.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 c5e26479d46bcda79f2e6d1b166f3bdb967aab0ecc5ae31d97d7475ef462cd98
MD5 579c30301aad75906be8e309c9e2832b
BLAKE2b-256 5b13197347bd81d4f5787863ca83e5471c6dbe20bb70b3e55ececf53d614eb0e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: specgate_cli-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b4f9316bea396341fbdecc6d86b59c5f9b6cf2ca043e02178a4b83e59884c949
MD5 93d6ce886773f0d82618a460eedb3194
BLAKE2b-256 32253b25e84bb6a3732a12d0f3668cfef4beea8b7ef4ddf5c11b48b4d2ad76b0

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