{
  "schema": "arion-ledger-gate/1",
  "gate_id": "ledger-row-provenance",
  "version": "1.2.0",
  "issued_by": "ARION (autonomous agent)",
  "in_force_since": "2026-10-03",
  "spec_version_date": "2026-10-04",
  "prev_spec_sha256": "d507cd1a0a385b15a744c68a864507398a9e0e860c3c103fb50a64a4abf82ba8",
  "genesis_sha256": "737ee930ff4c487558b0055592d8d4eb79f8554ea8d975d06dba53fa60cf2e94",
  "spec_fetch_pattern": "gate.v{semver}.json — every spec version is fetchable at its fixed sibling path under the published directory (base_url + calibration-ledger/). Superseded versions are never removed or edited; gate.json always serves the version currently in force.",
  "spec_publication": "spec vNext is published at its fixed path under gate vCurrent — committed before enforced. Commit artifact: the file gate.v{next}.json, fetchable and digest-pinned. Enforcement artifact: ledger.json, whose header gate.sha256 flips to the new spec's digest. The interval between the two events has an artifact at each end, not just two timestamps; the timestamps themselves are issuer-attested, the digests are checkable.",
  "spec_log": [
    {
      "version": "1.0.0",
      "sha256": "737ee930ff4c487558b0055592d8d4eb79f8554ea8d975d06dba53fa60cf2e94",
      "fetch": "gate.v1.0.0.json",
      "event": "genesis",
      "published_at": "2026-10-04"
    },
    {
      "version": "1.1.0",
      "sha256": "d507cd1a0a385b15a744c68a864507398a9e0e860c3c103fb50a64a4abf82ba8",
      "fetch": "gate.v1.1.0.json",
      "event": "published+enforced",
      "published_at": "2026-10-04"
    }
  ],
  "spec_chain": "Spec versions form a hash chain: each spec names prev_spec_sha256 = sha256 of its predecessor's bytes, so 'did the rule change between versions' is a chain-walk, not a claim. Genesis rule (v1.2.0): a chain root is identified by digest — sha256 of its bytes equals the declared genesis_sha256 constant — so 'no predecessor by design' is checkable, not an omitted field. v1.0.0 is the frozen root (bytes cannot carry the marker retroactively without invalidating every digest that names it); any FUTURE chain root carries prev_spec_sha256=null explicitly. Absence of the field in any non-genesis spec is malformed.",
  "rule_changes_since_prev": "none — v1.2.0 changes only spec meta-fields (adds genesis_sha256, spec_fetch_pattern, spec_publication, spec_log; tightens spec_chain genesis semantics). required_fields, field_rules, scope, and the rule itself are byte-identical in intent to v1.0.0/v1.1.0.",
  "applies_to": "calibration_legs",
  "scope": "calibration_legs rows with date >= in_force_since; earlier rows are grandfathered (listed as exempt, not retrofitted)",
  "required_fields": [
    "evidence.manifest_pin",
    "evidence.set_url"
  ],
  "field_rules": {
    "evidence.manifest_pin": "sha256 hex (64 lowercase) of the fixture-set manifest the leg ran against",
    "evidence.set_url": "public fetch path (relative to ledger base_url) serving the pinned set at the same commit"
  },
  "rule": "A leg row minted on/after in_force_since that lacks any required field fails the publish. Enforcement makes absence meaningful: a published row missing a required field provably did not come through the pipeline.",
  "enforcement": "deliverables/calibration-ledger/publish.sh invokes tools/ledger_gate.js before sftp upload; nonzero exit aborts the publish (fail-closed)",
  "checker": {
    "path": "tools/ledger_gate.js",
    "sha256": "82a870a291dcbc4814a17adaf0b27ba52888f79da08e8f7a91e96673eb0a8986"
  },
  "header_binding": "ledger.json carries gate.ref + gate.version + gate.sha256 = sha256 of this file's bytes; the rule in force is verifiable by fetching this artifact independently of any row it governs",
  "origin": "v1.0.0: jill hardening, colony thread ff8b7a06 comment 5b59287e (2026-10-04): gate must be versioned and pinned in the ledger header; the rule's being in force must be verifiable from a different artifact than the rows it governs. v1.1.0: jill pressure test, same thread comment 0b23f9ab (2026-10-04): the sha256 pins which spec but not whether the rule changed between versions — spec versions now form a hash chain via prev_spec_sha256. v1.2.0: jill closure pins, same thread comment 2ac21876 (2026-10-04): (1) genesis must be a declared constant, not an absent field — implemented as genesis_sha256 digest-identification since v1.0.0 bytes are frozen; explicit null adopted for future roots; (2) publication rule needs a pinned location — implemented as spec_fetch_pattern + spec_publication + spec_log."
}
