SignalSafe TreeSpec wire contract for Python: models, parsing, lint, and patch helpers.
Project description
signalsafe-tree-spec (Python)
Python implementation of the TreeSpec wire contract: Pydantic models, parsing, lint, patch helpers, and constants. Backend counterpart to @signalsafe/tree-spec on npm.
| PyPI distribution name | signalsafe-tree-spec |
| Import path | deliveryplus_tree_spec (stable; historical name) |
| GitHub | SignalSafeSoftware/tree-spec-python |
| Python | 3.12+ (requires-python >=3.12,<4.0) |
| Runtime dependency | Pydantic v2 (pydantic>=2.11.3,<3) |
License: MIT — see LICENSE. See SECURITY.md for vulnerability reporting.
What this package does
- Validate and parse TreeSpec wire JSON into typed Pydantic models (
TreeSpec,Node,Transition, …). - Lint wire payloads (
lint_tree_spec) with structured issues. - Build wire documents programmatically (
TreeSpecBuilder). - Apply JSON patches to wire dicts (
apply_patch_to_spec_dict). - Expose wire constants (
END_NODE_ID,TREESPEC_WIRE_VERSION).
What this package does not do
- HTTP APIs, authentication, persistence, or training UI.
- Scenario simulation (use
@signalsafe/simulator-core/simulator-reactin TypeScript stacks). - Graph editor UI (use
@signalsafe/tree-spec-editor-*packages). - General sandboxing or authorization — contract validation only; host apps decide trust and access control.
Install
pip install signalsafe-tree-spec
Development (this repo uses uv):
uv sync --extra dev
uv run pytest
Distribution name vs import path
pip install signalsafe-tree-spec
import deliveryplus_tree_spec
from deliveryplus_tree_spec import TreeSpec, lint_tree_spec, TreeSpecBuilder
The PyPI name (signalsafe-tree-spec) differs from the import path (deliveryplus_tree_spec) for backward compatibility with existing backends.
Quick start
from deliveryplus_tree_spec import (
END_NODE_ID,
TREESPEC_WIRE_VERSION,
TreeSpec,
TreeSpecBuilder,
lint_tree_spec,
)
wire = {
"wire_version": TREESPEC_WIRE_VERSION,
"start_node": "start",
"nodes": {
"start": {
"type": "prompt",
"prompt": "Verify the sender before clicking?",
"choices": [{"id": "inspect", "label": "Inspect sender"}],
}
},
"transitions": [
{"from": ["start", "inspect"], "to": END_NODE_ID, "outcome": "safe"},
],
}
issues = lint_tree_spec(wire)
assert not issues
spec = TreeSpec.model_validate(wire)
builder = TreeSpecBuilder()
# builder.add_node(...) — see tests/ for full builder flows
Public API
All symbols below are exported from the top-level deliveryplus_tree_spec package:
| Category | Symbols |
|---|---|
| Constants | END_NODE_ID, TREESPEC_WIRE_VERSION |
| Models | TreeSpec, Node, Transition, Choice, Delta, MicroFeedback, ABMeta, ABVariant, … |
| Lint | lint_tree_spec, TreeSpecIssue |
| Builder | TreeSpecBuilder, TreeSpecError |
| Patch | apply_patch_to_spec_dict, PatchApplyError, PatchDict, ReplacePatch, … |
There are no subpath exports — import from deliveryplus_tree_spec only.
Wire contract (high level)
wire_version: optional; omit for implicit v1. ConstantTREESPEC_WIRE_VERSIONdocuments the current version string.start_node: entry node id.nodes: map of node id → node object (type,prompt,choicesor legacyoptions, optionalrender_hints).transitions: list of{ from: [nodeId, choiceId], to, outcome? }. Terminal transitions targetEND_NODE_IDand requireoutcome._meta: optional tree-level metadata (for example graph-editor viewport persisted by editor packages).
Legacy payloads may use options instead of choices and legacy terminal ids; the TypeScript package normalizes these on compile/decompile. Python lint validates the wire shape your backend accepts.
Python / TypeScript parity
| Concern | Python (tree-spec-python) |
TypeScript (@signalsafe/tree-spec) |
|---|---|---|
| Wire models & lint | Pydantic models, lint_tree_spec |
TreeSpecWire, lintTreeSpecWire |
| Authoring graph compile | — | compileTreeSpec / decompileTreeSpec |
| Cross-language fixtures | Share JSON fixtures in your product repo or CI | Same |
Keep fixture JSON in sync when changing wire rules in either language. Full compile/decompile parity lives in TypeScript today; Python focuses on validation, lint, builder, and patch flows used by backends.
Development
uv sync --extra dev
uv run pytest
uv run flake8 .
uv run python -m build # wheel/sdist smoke — full artifact tests in Batch 6
Security
See SECURITY.md. TreeSpec parsing is contract validation, not a sandbox. Validate and authorize TreeSpec JSON in your application layer before treating content as trusted.
Changelog and releases
Related packages
@signalsafe/tree-spec— TypeScript wire contract and compile/lint.tree-spec-editor-*— authoring UI (TypeScript/React).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file signalsafe_tree_spec-0.1.1.tar.gz.
File metadata
- Download URL: signalsafe_tree_spec-0.1.1.tar.gz
- Upload date:
- Size: 18.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
433303dc4a4e4110a0aae65b39df7f1cef80925933839821737eae94076ef329
|
|
| MD5 |
3853dd0d8aba74e278f7aa435a320105
|
|
| BLAKE2b-256 |
6aee4bf7e19cea41de30dd02e59414c5ad021a342a5c97b5eed9411a142e3a80
|
Provenance
The following attestation bundles were made for signalsafe_tree_spec-0.1.1.tar.gz:
Publisher:
ci.yml on SignalSafeSoftware/tree-spec-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
signalsafe_tree_spec-0.1.1.tar.gz -
Subject digest:
433303dc4a4e4110a0aae65b39df7f1cef80925933839821737eae94076ef329 - Sigstore transparency entry: 1977006319
- Sigstore integration time:
-
Permalink:
SignalSafeSoftware/tree-spec-python@24098b825b25701ddf2a0cbf4ff4abdf6b94822e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/SignalSafeSoftware
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@24098b825b25701ddf2a0cbf4ff4abdf6b94822e -
Trigger Event:
push
-
Statement type:
File details
Details for the file signalsafe_tree_spec-0.1.1-py3-none-any.whl.
File metadata
- Download URL: signalsafe_tree_spec-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75c90167700e301d4603e6e5bcb9a965958b1d76a27e1b5671b3bb790b9536b7
|
|
| MD5 |
026ec476a24b365abf8a0bd99dce132c
|
|
| BLAKE2b-256 |
3af71d33451aba2dec8c8c9f59030583f6283bda6b101519dd5b616f1e75f77c
|
Provenance
The following attestation bundles were made for signalsafe_tree_spec-0.1.1-py3-none-any.whl:
Publisher:
ci.yml on SignalSafeSoftware/tree-spec-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
signalsafe_tree_spec-0.1.1-py3-none-any.whl -
Subject digest:
75c90167700e301d4603e6e5bcb9a965958b1d76a27e1b5671b3bb790b9536b7 - Sigstore transparency entry: 1977006448
- Sigstore integration time:
-
Permalink:
SignalSafeSoftware/tree-spec-python@24098b825b25701ddf2a0cbf4ff4abdf6b94822e -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/SignalSafeSoftware
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@24098b825b25701ddf2a0cbf4ff4abdf6b94822e -
Trigger Event:
push
-
Statement type: