sddkit
A Python library that makes Spec-Driven Development practical inside Python applications.
sddkit gives authors a typed, validated, programmable representation of an SDD specification and emitters that produce the agent-ingestion artifacts (AGENTS.md, SKILL.md, and a canonical Markdown spec) an AI coding agent can read at session start.
Installation
pip install specddkit
Requires Python 3.10 or later.
Quick Start
from sddkit import (
Spec, Intent, Constraint, AcceptanceCriterion, NonGoal, Dependency,
EngineerRefinement, Unit,
)
spec = Spec(
name="my-service",
identifier="my-service/v1",
version="1.0.0",
status="draft",
intent=Intent(
summary="Provide a reliable widget API.",
details="Serves widget data to downstream consumers with sub-100ms p99 latency.",
),
constraints=[
Constraint(id="C1", text="Must not depend on any proprietary SDK.", kind="must-not"),
],
acceptance_criteria=[
AcceptanceCriterion(
id="AC1",
text="GET /widgets returns 200 with a JSON array.",
input_pattern="GET /widgets with valid auth",
),
],
non_goals=[NonGoal(id="NG1", text="Not a write API in v1.")],
dependencies=[Dependency(name="pydantic", kind="hard")],
)
# Validate operationality (five PM-section components populated)
report = spec.validate_operational()
print(report.is_operational) # True
print(report.issues) # warnings for any missing optional components
# Serialise and round-trip
yaml_text = spec.to_yaml()
spec2 = Spec.from_yaml(yaml_text)
assert spec2 == spec
# Emit agent-ingestion artifacts to disk
with open("AGENTS.md", "w") as f:
f.write(spec.to_agents_md())
with open("SKILL.md", "w") as f:
f.write(spec.emit_skill_file("spec_ingestion"))
# Derive pytest stubs from acceptance criteria and write to disk
for filename, source in spec.derive_tests(framework="pytest").items():
with open(filename, "w") as f:
f.write(source)
Core Concepts
sddkit implements the operational-spec component model from Tickets Don't Compile:
| Component | Class | Required for operationality |
|---|---|---|
| Intent | Intent |
Yes (required field) |
| Constraints | list[Constraint] |
Warning if empty |
| Acceptance Criteria | list[AcceptanceCriterion] |
Yes (error if empty) |
| Non-Goals | list[NonGoal] |
Warning if empty |
| Dependencies | list[Dependency] |
Info if empty |
Serialisation
All three formats round-trip for canonical fields:
spec.to_yaml() # → YAML string; Spec.from_yaml(text) → Spec
spec.to_json() # → JSON string; Spec.from_json(text) → Spec
spec.to_markdown() # → Markdown with YAML front matter; Spec.from_markdown(text) → Spec
Decomposition
from sddkit import EngineerRefinement, Unit
spec_with_refinement = spec.model_copy(update={
"refinement": EngineerRefinement(
decomposition=[
Unit(id="U1", name="Core models", hard_deps=[]),
Unit(id="U2", name="Serialization", hard_deps=["U1"]),
]
)
})
ordered_units = spec_with_refinement.decompose()
# Returns units in topological (dependency-first) order.
# Raises RefinementIncompleteError if a cycle is detected.
Public API
from sddkit import (
Spec,
Intent,
Constraint,
AcceptanceCriterion,
NonGoal,
Dependency,
EngineerRefinement,
Unit,
ValidationReport,
OperationalityError,
RefinementIncompleteError,
SerializationError,
SddkitError,
)
All exceptions inherit from SddkitError.
Development
pip install -e ".[dev]"
pytest # runs tests with coverage
mypy src/sddkit --strict
ruff check src/sddkit
python -m build
twine check dist/*
License
Apache 2.0. See LICENSE.
Metadata
Release files for specddkit 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| specddkit-1.0.1.tar.gz | 22.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| specddkit-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.7 kB
Release files / specddkit-1.0.1.tar.gz
| Download URL | specddkit-1.0.1.tar.gz |
|---|---|
| Size | 22.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7af45afbbc6cdad53530369571235ecf5b4aa31079eb083eb4560582f4d07538
|
|
BLAKE2b-256 checksum How to use checksums |
a276e60af42e6418b55b2ce724e5c2c2a9da0534f20b7df1859b557071a1dae4
|
| 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 Jun 26, 2026.
Transparency logRelease files / specddkit-1.0.1-py3-none-any.whl
| Download URL | specddkit-1.0.1-py3-none-any.whl |
|---|---|
| Size | 27.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1e0143ad9124531e15d5efabc93ac89f06f349b3f4260784d7edb4c5d6bf0fb1
|
|
BLAKE2b-256 checksum How to use checksums |
5cc4ff8ea863d4ac2cd377a1b6bb4a151ed7da5ea3bc0dc71ef037017911c5ca
|
| 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 Jun 26, 2026.
Transparency log