Helix CLI Session Contract v2
This document defines the black-box contract for the Helix CLI session lifecycle. It is enforced as bytes-on-disk, not as internal implementation behavior.
v2 is a contract bump over v1 with one additional product guarantee: exported/session artifacts self-declare the contract identity that governs them.
Scope
Contracted lifecycle:
simulate— produce a.helixsession from a configrun— alias ofsimulate(must be identical)report— produce deterministic HTML reports from a sessionexport— produce deterministic exported artifacts (JSON + PNG + provenance sidecar)simulate --append— append runs to an existing session in order
Guarantees
Under deterministic mode (PYTHONHASHSEED=0 + HELIX_DETERMINISTIC=1):
- Alias parity:
simulateandrunproduce byte-for-byte identical.helixsessions for the same config. - Deterministic artifact trees:
reportandexportare deterministic across repeated runs. - Filtered report determinism:
report --run-id <id>emits only the requested run’s report with stable output. - Export provenance coupling: exports include a PNG provenance sidecar that correctly hashes the emitted PNG.
- Append semantics:
simulate --appendpreserves run order (session evolution is deterministic). - Contract stamping: session and export provenance include
contract_id+contract_hashso evidence bundles are portable across time/CI logs.
Failure behavior (golden paths)
Contracted failures must be deterministic:
- Non-zero exit codes for invalid inputs.
- Stable error messages (at least at the “reason substring” level).
- Predictable partial outputs (e.g., created directories without a verdict when pack selection fails).
Contract stamp (v2)
Artifacts include:
.helixsession header:contractId(string, e.g.cli_session_contract_v2)contractHash(string, v2 contract hash)
*.export.jsonprovenance block:contract_idcontract_hash
*.png.provenance.json:contract_idcontract_hash
contract_hash is a constant shipped in code and updated only via the vN → vN+1 bump workflow.
Compatibility (downgrade story)
Artifacts are version-stamped. Verification tooling should never claim “OK” for an artifact governed by a newer contract than it understands.
If you try to verify a v2-stamped artifact with a tool that only supports v1, verification fails deterministically:
- Exit code: non-zero
- Error substring:
unsupported cli session contract: cli_session_contract_v2 (tool supports up to v1)
This is intentional: older tools cannot safely validate newer contract semantics (normalization rules, lifecycle behavior, and failure taxonomy). The correct fix is to upgrade the Helix toolchain used for verification.
Downgrade is a tooling/verification compatibility story only; it does not “downgrade” the underlying simulation semantics or re-interpret artifacts to match older assumptions.
Contract hash normalization (v2)
The cross-platform gate compares a single contract hash derived from the full output tree.
Hash inputs:
- All files under the contract test’s output root directory are included.
- Paths are hashed by their relative POSIX path (stable across OS runners).
Per-file normalization rules:
- Non-PNG files: digest is
sha256(file_bytes)except for contract-stamped JSON (below). - PNG files (
*.png): digest issha256(decoded_RGBA_pixels + {size, mode}).- This ignores platform-specific PNG encoding differences (metadata/chunk ordering/compression), while still treating the image as deterministic data.
- Contract-stamped JSON (
*.helix,*.export.json):- Parse JSON.
- Strip
contract_hash/contractHashkeys (to avoid self-referential hashing). - Digest is
sha256(canonical_json_bytes)where canonical JSON usessort_keys=Trueand separators(",", ":").
- PNG provenance sidecars (
*.png.provenance.json):- First, validate the sidecar’s
artifact_sha256exactly matchessha256(png_file_bytes)(byte-level binding). - Then, hash a canonicalized JSON payload where:
artifact_sha256is rewritten to the PNG pixel digest (sha256_pixels:<…>) (pixel-stable across OS),contract_hashis stripped (to avoid self-referential hashing).
- First, validate the sidecar’s
Tree hash:
- Build a JSON object
{relative_path: per_file_digest}with keys sorted. - Compute
sha256(canonical_json_bytes)where canonical JSON usessort_keys=Trueand separators(",", ":").
If any of the above normalization rules change, that is a spec change and requires a new contract version (v3), not an edit-in-place of v2.
Contract bump workflow (v2 → v3)
This contract is designed to be hard to change by accident.
To intentionally change behavior:
- Add new versioned files:
tests/e2e/test_cli_session_contract_v3.pydocs/cli/session_contract_v3.md
- Update documentation pointers:
mkdocs.yml(nav entry for the new version)docs/governance_contract.md(reference the new version)
- Add a changelog entry in
CHANGELOG.md.
Enforcement:
- The CI guard
tools/check_cli_session_contract_bump.pyforbids editing/deleting existingvNcontracts. - The cross-platform workflow always runs the latest
vNviatools/run_cli_session_contract.py.
Enforcement
Source of truth:
tests/e2e/test_cli_session_contract_v2.py
Cross-platform gate (Linux/macOS):
.github/workflows/cli-session-contract.yml
Any intentional behavioral or artifact-shape change to this lifecycle should be treated as a breaking change and versioned as a new contract rather than silently drifting an existing version.