Skip to main content

crucible

A self-contained, deterministic validation engine for OpenSpec v1.1 specifications.

CI PyPI Python versions License: Apache 2.0 mypy strict

pip install crucible-forge  •  import crucible


crucible takes a software specification (with its epics and tickets), scores it against a fixed, configurable rubric, and reports a readiness gate — with no LLM, fully deterministic. Same input, same score, every time.

It is a faithful Python port of the SpecForge @specforge/validator engine, extracted as a standalone library, and is the planning gate of SpecSmither. The output is byte-equivalent to the reference TypeScript engine, verified by differential tests across every phase and output layer.

Why

  • 🎯 Deterministic — pure scoring, no model calls. Reproducible in CI.
  • 📦 Self-contained — pure Python; only pydantic and pyyaml at runtime.
  • 🔬 Faithful — output matches the reference TS validator (differential-tested).
  • 🎚️ Configurable — every threshold, tier weight, and check lives in config.
  • 🏷️ Typed — ships py.typed; passes mypy --strict.

Install

pip install crucible-forge      # → import crucible
# or
uv add crucible-forge

Requires Python ≥ 3.11.

Quick start

from crucible import validate, load_defaults

result = validate(spec, {
    "phase": "planning_spec",
    "config": load_defaults(),                      # optional — loaded by default
    "returns": ["structural", "scoring", "guidance"],
})

if result.scoring and not result.scoring.skipped:
    print(result.scoring.gate_result)   # 'pass' | 'fail'
    print(result.scoring.local_score)   # e.g. 86.11
    print(result.passed)                # overall gate for the phase

# Canonical camelCase JSON (matches the reference engine):
result.to_json_dict()

spec may be a crucible.Specification model or a plain dict (camelCase, the OpenSpec v1.1 shape). The context accepts the original keys (phase, activeEntityId, config, returns) or their snake_case forms.

The model

A spec is a hierarchy:

Specification → Epic → Ticket  (+ acceptance criteria, impl steps, tests, files, dependencies)
                                    ↘ ticket dependency DAG ↙

validate() walks this tree and produces up to four output layers:

layer what it reports
structural schema issues — missing fields, format violations, duplicate orders, entity counts
scoring the readiness score + gate (rubric tiers, weighted blocks, topology penalties, cascade floors)
crossValidation cross-entity consistency — cycles, orphan/island tickets, file conflicts, wave coordination, blueprint coverage
guidance human-readable, prioritized fix suggestions composed from the above

Request the layers you want via returns; a single phase returns whatever it computes, and phase: "all" defaults to ["scoring"].

Phases

validate() is driven by context["phase"]:

phase scope needs activeEntityId
planning_spec spec-level fields
epic_decomposition spec + the epic list
epic_expansion one epic's fields ✓
ticket_decomposition tickets under one epic
ticket_expansion one ticket's fields ✓
cross_validation full-tree consistency checks
all every phase, keyed under by_phase
# Summative gate over the whole tree:
allr = validate(spec, {"phase": "all", "returns": ["scoring", "crossValidation"]})
planning_passed = (
    allr.by_phase["planning_spec"].scoring
    and allr.by_phase["planning_spec"].scoring.gate_result == "pass"
)

Structural-only

When you just need the schema check (no scoring/guidance):

from crucible import validate_structural, load_defaults

res = validate_structural(spec, load_defaults(), "planning_spec")
if not res.missing_fields and not res.invalid_fields:
    ...  # schema-clean

Configuration

Every gate is config-driven. load_defaults() returns the packaged ValidatorConfig (thresholds, tier weights, the 53-entry rubric thresholds, topology penalties, cross-validation rules). Layer overrides with merge_config:

from crucible import load_defaults, merge_config

config = merge_config(load_defaults(), {"thresholds": {"global": 85}})

The scoring rubric (53 entries: 16 spec · 17 epic · 20 ticket) ships as a data asset at crucible/guidance/rubric/data/rubric.json, generated verbatim from the reference source.

Public API

from crucible import (
    validate, validate_structural,            # entry points
    load_defaults, load_from_file,            # config loading
    load_partial_from_file, merge_config,
    CONFIG_DEFAULTS, ValidatorConfigSchema,
    PlanningConfigResolver,                    # project/spec config resolution
    ValidatorInputError,                      # raised on bad context
    Specification, Epic, Ticket, Blueprint,   # OpenSpec models
    models, types,                            # full model + result namespaces
)

Development

uv sync --all-extras --dev
uv run ruff check src tests
uv run mypy
uv run pytest                 # 125 tests, incl. differential vs the TS engine

Fidelity is verified against committed golden output captured from the reference engine, so CI needs no extra tooling.

Status

0.2.0 — a complete port, verified byte-for-byte against the current TS validator across every phase and all four output layers (structural · scoring · crossValidation · guidance). Tracks the reference engine through @specforge/validator 0.1.20: the epic/ticket expansion gate is ALL-PASS (every touched entity must clear its threshold — a strong entity no longer masks a weak one; the mean is still reported), entity-count findings embed the (epicId: …) in their message, and the decomposition guidance advances via complete_planning_session. See CHANGELOG.md.

License

Apache 2.0 © Gabriel Augusto Gonçalves / blacksmithers

Metadata

Release files for crucible-forge 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crucible-forge 0.2.0
File Size Uploaded
crucible_forge-0.2.0.tar.gz 70.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crucible-forge 0.2.0
File Interpreter ABI Platform
crucible_forge-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 179.1 kB

Release files / crucible_forge-0.2.0.tar.gz

Download URL crucible_forge-0.2.0.tar.gz
Size 70.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ed06e9c32b47205d88b0049d6d3e70015e42a0fc586b160fb2bd8d8bc0439449
BLAKE2b-256 checksum
How to use checksums
62eeb14ee591216e93a35dec06cd8062465bcebb5445bfc7c7e53be50601384c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Release files / crucible_forge-0.2.0-py3-none-any.whl

Download URL crucible_forge-0.2.0-py3-none-any.whl
Size 108.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06398d19001f655bcf93e9a2be61ddc890a2318dad3b9d2623994862988fc152
BLAKE2b-256 checksum
How to use checksums
4e7f298c00b8f36db0066fb1a48afc39373d0d01e727182b52e3e22364d8db4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page