← Docs
Helix CLI docs
Browse Helix CLI docs

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:

  1. simulate — produce a .helix session from a config
  2. run — alias of simulate (must be identical)
  3. report — produce deterministic HTML reports from a session
  4. export — produce deterministic exported artifacts (JSON + PNG + provenance sidecar)
  5. simulate --append — append runs to an existing session in order

Guarantees

Under deterministic mode (PYTHONHASHSEED=0 + HELIX_DETERMINISTIC=1):

  • Alias parity: simulate and run produce byte-for-byte identical .helix sessions for the same config.
  • Deterministic artifact trees: report and export are 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 --append preserves run order (session evolution is deterministic).
  • Contract stamping: session and export provenance include contract_id + contract_hash so 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:

  • .helix session header:
    • contractId (string, e.g. cli_session_contract_v2)
    • contractHash (string, v2 contract hash)
  • *.export.json provenance block:
    • contract_id
    • contract_hash
  • *.png.provenance.json:
    • contract_id
    • contract_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 is sha256(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 / contractHash keys (to avoid self-referential hashing).
    • Digest is sha256(canonical_json_bytes) where canonical JSON uses sort_keys=True and separators (",", ":").
  • PNG provenance sidecars (*.png.provenance.json):
    • First, validate the sidecar’s artifact_sha256 exactly matches sha256(png_file_bytes) (byte-level binding).
    • Then, hash a canonicalized JSON payload where:
      • artifact_sha256 is rewritten to the PNG pixel digest (sha256_pixels:<…>) (pixel-stable across OS),
      • contract_hash is stripped (to avoid self-referential hashing).

Tree hash:

  • Build a JSON object {relative_path: per_file_digest} with keys sorted.
  • Compute sha256(canonical_json_bytes) where canonical JSON uses sort_keys=True and 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:

  1. Add new versioned files:
    • tests/e2e/test_cli_session_contract_v3.py
    • docs/cli/session_contract_v3.md
  2. Update documentation pointers:
    • mkdocs.yml (nav entry for the new version)
    • docs/governance_contract.md (reference the new version)
  3. Add a changelog entry in CHANGELOG.md.

Enforcement:

  • The CI guard tools/check_cli_session_contract_bump.py forbids editing/deleting existing vN contracts.
  • The cross-platform workflow always runs the latest vN via tools/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.