--- authority entries ---
{
  "authority_statement": "historical immutable PASS describes past qualification; current authority comes only from this append-only registry and qualification ledger",
  "current_qualified_candidate": "310632f25b112373d97355c5ce3290dc55fb6d036a735e2b53861d983c4fd648",
  "document_sha256": "1df90b8e957a46321424cdc1404c6a7136eacaa7f42759ef0c28a406be0f4fd7",
  "events": [
    {
      "action": "qualify",
      "candidate_digest": "2efe939a9775dccb71c680d6ce8513c919721dc0dba5535f0f64905e34d3bd82",
      "event_sha256": "70a40942745fdc5e05b506751508e4f1d838e07026beb1b3b45758df48b72c44",
      "historical_pass_digest": "d2b51cb4dfa707a86f64ccb56776da6ba1df1f01792cf98e3323f9eee41d1693",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
      "previous_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 1
    },
    {
      "action": "revoke",
      "candidate_digest": "2efe939a9775dccb71c680d6ce8513c919721dc0dba5535f0f64905e34d3bd82",
      "event_sha256": "7a04c1c4443d41a7dcaaba16150b35e4690f23581dbc10a7a798869d25d28322",
      "historical_pass_digest": "d2b51cb4dfa707a86f64ccb56776da6ba1df1f01792cf98e3323f9eee41d1693",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "befd59f68371eb92e6ec74f2307f30167d2c85f1e59172e9f84fed4a6b0f2fd7",
      "previous_sha256": "70a40942745fdc5e05b506751508e4f1d838e07026beb1b3b45758df48b72c44",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 2
    },
    {
      "action": "qualify",
      "candidate_digest": "cbbfc12d1e61c65e5620e4a56b850b0b3d945035a1ab4041c330e50b06fdfe17",
      "event_sha256": "0f2da6c664bc581e391d70bccf1bab173d6cf3112fcba8865a4b1595b607a6b0",
      "historical_pass_digest": "a68176bce2052d31e3d1db565ad9998313f3ef20813edadb18881430baf64f15",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "bf9f3013f77a8ef6379e32f9e13ee808858266149ead79d9857726075979d4d4",
      "previous_sha256": "7a04c1c4443d41a7dcaaba16150b35e4690f23581dbc10a7a798869d25d28322",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 3
    },
    {
      "action": "revoke",
      "candidate_digest": "cbbfc12d1e61c65e5620e4a56b850b0b3d945035a1ab4041c330e50b06fdfe17",
      "event_sha256": "9f20282d17889fa7d2d126ef43efe9d74a6c950670153a308cdbb316b6314b03",
      "historical_pass_digest": "a68176bce2052d31e3d1db565ad9998313f3ef20813edadb18881430baf64f15",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "523a0d39b9ba0961a2c1e5bb31e3d44a9dfbaa0ac30faf92cc04e60be6f8c604",
      "previous_sha256": "0f2da6c664bc581e391d70bccf1bab173d6cf3112fcba8865a4b1595b607a6b0",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 4
    },
    {
      "action": "qualify",
      "candidate_digest": "09a669ddc42875998d34a7d7cb07ae575af06037fcb1438512bbc3930cc990d9",
      "event_sha256": "3f3f4aa0a65140c3fb70871bcbd7b80897aed07860e0919649257806d970e454",
      "historical_pass_digest": "c7a0889b979b2da6f333e5e716ab9664d5dc1847ba85b727eadde30abf06f09d",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "130fa44fc18d119a7c1d11abd50dd7ddeba8ebe9c3a039aa3246c0818626a8c0",
      "previous_sha256": "9f20282d17889fa7d2d126ef43efe9d74a6c950670153a308cdbb316b6314b03",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 5
    },
    {
      "action": "revoke",
      "candidate_digest": "09a669ddc42875998d34a7d7cb07ae575af06037fcb1438512bbc3930cc990d9",
      "event_sha256": "f4a007c6633a567205abfe7d4aec2ddd055d7eb0f2fb1aa79aa227748ca067fb",
      "historical_pass_digest": "c7a0889b979b2da6f333e5e716ab9664d5dc1847ba85b727eadde30abf06f09d",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "f7851dc6efebb498d2681ddf9399d66190dabe3225b4b0a017930edcccbf98c3",
      "previous_sha256": "3f3f4aa0a65140c3fb70871bcbd7b80897aed07860e0919649257806d970e454",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 6
    },
    {
      "action": "qualify",
      "candidate_digest": "c084f8b5e1b8bc1d99edaff856bdf0a36bc8631074769c32695c20c84b2f0c07",
      "event_sha256": "48b795e764cfb16e6fd409f25c6925dcab958cb39b5bc62cc91fe8f37d3cbce6",
      "historical_pass_digest": "5fa0dbc77f99a84bb2109cc9db8a2f5b9cf26a05e48ee8d05eb952b8edd6c3d0",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "14ac3b155bc0f8188c89ced97893b76d355fdaf4a85b55ef28cfdce682aa1cdb",
      "previous_sha256": "f4a007c6633a567205abfe7d4aec2ddd055d7eb0f2fb1aa79aa227748ca067fb",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 7
    },
    {
      "action": "revoke",
      "candidate_digest": "c084f8b5e1b8bc1d99edaff856bdf0a36bc8631074769c32695c20c84b2f0c07",
      "event_sha256": "dcb321cfac52bb58a9c9cd7bdb197c4bde80aa3c3a1081bedd1a08b3c0c1e2dc",
      "historical_pass_digest": "5fa0dbc77f99a84bb2109cc9db8a2f5b9cf26a05e48ee8d05eb952b8edd6c3d0",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "5e274fc5f671a3b4a61f56594feaa9baa05fb9a970996373d7e569281a5f20d8",
      "previous_sha256": "48b795e764cfb16e6fd409f25c6925dcab958cb39b5bc62cc91fe8f37d3cbce6",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 8
    },
    {
      "action": "qualify",
      "candidate_digest": "144d5eeebe06e90aa43b2ca4c555b73afe826e033795bc37443e0c9c37c3094a",
      "event_sha256": "c6a15766327fb10c89ab7e4f407d754354af95847c11efbee2933de871bfd185",
      "historical_pass_digest": "20ab0d05c70fe95fb11c1ef4d1479a188a6caa8015285fcd5507be399d754e8a",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "edb6fdf636e77f0ea7ef1bbf35b307d1e08add024ab22730dbb636038f59e72b",
      "previous_sha256": "dcb321cfac52bb58a9c9cd7bdb197c4bde80aa3c3a1081bedd1a08b3c0c1e2dc",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 9
    },
    {
      "action": "revoke",
      "candidate_digest": "144d5eeebe06e90aa43b2ca4c555b73afe826e033795bc37443e0c9c37c3094a",
      "event_sha256": "3d7851b3360a38b308202b8d068e6152947f6f7f162fc36dd165b569a219b41d",
      "historical_pass_digest": "20ab0d05c70fe95fb11c1ef4d1479a188a6caa8015285fcd5507be399d754e8a",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "892d5e059b9e058f332c1d0251ba61ec3d0139dfb796aaa379dcb2430f2e9912",
      "previous_sha256": "c6a15766327fb10c89ab7e4f407d754354af95847c11efbee2933de871bfd185",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 10
    },
    {
      "action": "qualify",
      "candidate_digest": "0b883e109c995136f88e7350051bfab9dbcca7b8e3512311917c521e090153ea",
      "event_sha256": "a0aa2b67f3d119cea81806f304305eefaca8ed157b5a676875605d7e057166ce",
      "historical_pass_digest": "c5b38cab0798a1f76f624f82085dc9336edfa3bfd9cc2eb897ca2769550af7bd",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "aab792657b8ec796da15b5b89c74c2b41f6e6344c7fca02ac9db8c5a3945f607",
      "previous_sha256": "3d7851b3360a38b308202b8d068e6152947f6f7f162fc36dd165b569a219b41d",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 11
    },
    {
      "action": "revoke",
      "candidate_digest": "0b883e109c995136f88e7350051bfab9dbcca7b8e3512311917c521e090153ea",
      "event_sha256": "15954ce6a8d0866c1695bd0fde46ac81416b4fcb94b79c6f6a3579b6136a7891",
      "historical_pass_digest": "c5b38cab0798a1f76f624f82085dc9336edfa3bfd9cc2eb897ca2769550af7bd",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "7cbaf0e7e1650f978e4caa4ace83e8a607a96db6830b66193c3769880ee05e43",
      "previous_sha256": "a0aa2b67f3d119cea81806f304305eefaca8ed157b5a676875605d7e057166ce",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 12
    },
    {
      "action": "qualify",
      "candidate_digest": "8868327ffff5e85a5522079e40919bd9a6d732a685e42cbd5276aab81bcc2431",
      "event_sha256": "7ec1fd44d17eaada393d0268598c5ad5f2ffce05dfd2a2f455960dcfc72cba3e",
      "historical_pass_digest": "abef260801e13061ddc9b477128eee49362040acea350ece1b900c26148cfcea",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "79c9de2a77abc54fcf9a5871be3081c3de5ae4050e49c010fdc768eb650ad7cb",
      "previous_sha256": "15954ce6a8d0866c1695bd0fde46ac81416b4fcb94b79c6f6a3579b6136a7891",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 13
    },
    {
      "action": "revoke",
      "candidate_digest": "8868327ffff5e85a5522079e40919bd9a6d732a685e42cbd5276aab81bcc2431",
      "event_sha256": "ba5b1cd318e7b6fa9a69d11ce333a744a0df0a105e375e0a0eced76acbff7ceb",
      "historical_pass_digest": "abef260801e13061ddc9b477128eee49362040acea350ece1b900c26148cfcea",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "8fe5e54e16586df8aa9dea86041892f4264ed6bdc8f8a6f7c7e30dbc43bdcfae",
      "previous_sha256": "7ec1fd44d17eaada393d0268598c5ad5f2ffce05dfd2a2f455960dcfc72cba3e",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 14
    },
    {
      "action": "qualify",
      "candidate_digest": "78ecb799bc2e451f6055d892cb1f3af459dca62f4b8dd80c61ff8a3d43789538",
      "event_sha256": "81d6db8a607c3771214d3b1f121fe283e8f8609d15a327a3862c0fd5034564a2",
      "historical_pass_digest": "f3885df7210fea08692a2e52569a8825b3e39919ab5ff08f2f88d3f3f57544fd",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "fb267c318043cac353231e915dfa01adf16d1d6ec9b07da1dd921912f3cfc679",
      "previous_sha256": "ba5b1cd318e7b6fa9a69d11ce333a744a0df0a105e375e0a0eced76acbff7ceb",
      "reason": "historical immutable qualification imported before security revocation",
      "sequence": 15
    },
    {
      "action": "revoke",
      "candidate_digest": "78ecb799bc2e451f6055d892cb1f3af459dca62f4b8dd80c61ff8a3d43789538",
      "event_sha256": "c2efc1dec3b5387eaacacf38e08af805c59f3ad57819ca79f92366467df23190",
      "historical_pass_digest": "f3885df7210fea08692a2e52569a8825b3e39919ab5ff08f2f88d3f3f57544fd",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "bb640bbc2185a23afb72ce62ca40679ef55a979a854c12546af1bad3938cc45a",
      "previous_sha256": "81d6db8a607c3771214d3b1f121fe283e8f8609d15a327a3862c0fd5034564a2",
      "reason": "invalidated by portability, provenance, or security review",
      "sequence": 16
    },
    {
      "action": "qualify",
      "candidate_digest": "310632f25b112373d97355c5ce3290dc55fb6d036a735e2b53861d983c4fd648",
      "event_sha256": "d4e0e2f6d44d15d9ca74c47941d5504a6c1618836b455567f268c7cec8cdffe7",
      "historical_pass_digest": "f712a4004b4e54a8e45f63ec7783265bc6145d77a08ac2adc9a1a4e1ed652157",
      "historical_pass_scope": "past_qualification_only",
      "ledger_predecessor_sha256": "b4145eb685b356f00124540c7625103a929cfa51f780c2f3bdd381c474cb3c07",
      "previous_sha256": "c2efc1dec3b5387eaacacf38e08af805c59f3ad57819ca79f92366467df23190",
      "reason": "isolated dependency-bound zero-inotify v10 qualification",
      "sequence": 17
    }
  ],
  "head_sha256": "d4e0e2f6d44d15d9ca74c47941d5504a6c1618836b455567f268c7cec8cdffe7",
  "invalidated_candidate_digests": [
    "09a669ddc42875998d34a7d7cb07ae575af06037fcb1438512bbc3930cc990d9",
    "0b883e109c995136f88e7350051bfab9dbcca7b8e3512311917c521e090153ea",
    "144d5eeebe06e90aa43b2ca4c555b73afe826e033795bc37443e0c9c37c3094a",
    "2efe939a9775dccb71c680d6ce8513c919721dc0dba5535f0f64905e34d3bd82",
    "78ecb799bc2e451f6055d892cb1f3af459dca62f4b8dd80c61ff8a3d43789538",
    "8868327ffff5e85a5522079e40919bd9a6d732a685e42cbd5276aab81bcc2431",
    "c084f8b5e1b8bc1d99edaff856bdf0a36bc8631074769c32695c20c84b2f0c07",
    "cbbfc12d1e61c65e5620e4a56b850b0b3d945035a1ab4041c330e50b06fdfe17"
  ],
  "ledger_head_sha256": "3dd46f75fa61fe632315c0a8fa5c344671124289a890884ecb8352c741154549",
  "schema": "task26-candidate-revocation-registry-v1"
}
{
  "authority_statement": "historical immutable PASS describes past qualification; current authority comes only from this append-only registry and qualification ledger",
  "document_sha256": "7ab49ac462f254e485bf6dc45abfb778361e204868c2eeed2424af0cceb6f71c",
  "head_sha256": "3dd46f75fa61fe632315c0a8fa5c344671124289a890884ecb8352c741154549",
  "registry_head_sha256": "d4e0e2f6d44d15d9ca74c47941d5504a6c1618836b455567f268c7cec8cdffe7",
  "rows": [
    {
      "action": "qualify",
      "candidate_digest": "2efe939a9775dccb71c680d6ce8513c919721dc0dba5535f0f64905e34d3bd82",
      "historical_pass_digest": "d2b51cb4dfa707a86f64ccb56776da6ba1df1f01792cf98e3323f9eee41d1693",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
      "registry_event_sha256": "70a40942745fdc5e05b506751508e4f1d838e07026beb1b3b45758df48b72c44",
      "row_sha256": "befd59f68371eb92e6ec74f2307f30167d2c85f1e59172e9f84fed4a6b0f2fd7",
      "sequence": 1
    },
    {
      "action": "revoke",
      "candidate_digest": "2efe939a9775dccb71c680d6ce8513c919721dc0dba5535f0f64905e34d3bd82",
      "historical_pass_digest": "d2b51cb4dfa707a86f64ccb56776da6ba1df1f01792cf98e3323f9eee41d1693",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "befd59f68371eb92e6ec74f2307f30167d2c85f1e59172e9f84fed4a6b0f2fd7",
      "registry_event_sha256": "7a04c1c4443d41a7dcaaba16150b35e4690f23581dbc10a7a798869d25d28322",
      "row_sha256": "bf9f3013f77a8ef6379e32f9e13ee808858266149ead79d9857726075979d4d4",
      "sequence": 2
    },
    {
      "action": "qualify",
      "candidate_digest": "cbbfc12d1e61c65e5620e4a56b850b0b3d945035a1ab4041c330e50b06fdfe17",
      "historical_pass_digest": "a68176bce2052d31e3d1db565ad9998313f3ef20813edadb18881430baf64f15",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "bf9f3013f77a8ef6379e32f9e13ee808858266149ead79d9857726075979d4d4",
      "registry_event_sha256": "0f2da6c664bc581e391d70bccf1bab173d6cf3112fcba8865a4b1595b607a6b0",
      "row_sha256": "523a0d39b9ba0961a2c1e5bb31e3d44a9dfbaa0ac30faf92cc04e60be6f8c604",
      "sequence": 3
    },
    {
      "action": "revoke",
      "candidate_digest": "cbbfc12d1e61c65e5620e4a56b850b0b3d945035a1ab4041c330e50b06fdfe17",
      "historical_pass_digest": "a68176bce2052d31e3d1db565ad9998313f3ef20813edadb18881430baf64f15",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "523a0d39b9ba0961a2c1e5bb31e3d44a9dfbaa0ac30faf92cc04e60be6f8c604",
      "registry_event_sha256": "9f20282d17889fa7d2d126ef43efe9d74a6c950670153a308cdbb316b6314b03",
      "row_sha256": "130fa44fc18d119a7c1d11abd50dd7ddeba8ebe9c3a039aa3246c0818626a8c0",
      "sequence": 4
    },
    {
      "action": "qualify",
      "candidate_digest": "09a669ddc42875998d34a7d7cb07ae575af06037fcb1438512bbc3930cc990d9",
      "historical_pass_digest": "c7a0889b979b2da6f333e5e716ab9664d5dc1847ba85b727eadde30abf06f09d",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "130fa44fc18d119a7c1d11abd50dd7ddeba8ebe9c3a039aa3246c0818626a8c0",
      "registry_event_sha256": "3f3f4aa0a65140c3fb70871bcbd7b80897aed07860e0919649257806d970e454",
      "row_sha256": "f7851dc6efebb498d2681ddf9399d66190dabe3225b4b0a017930edcccbf98c3",
      "sequence": 5
    },
    {
      "action": "revoke",
      "candidate_digest": "09a669ddc42875998d34a7d7cb07ae575af06037fcb1438512bbc3930cc990d9",
      "historical_pass_digest": "c7a0889b979b2da6f333e5e716ab9664d5dc1847ba85b727eadde30abf06f09d",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "f7851dc6efebb498d2681ddf9399d66190dabe3225b4b0a017930edcccbf98c3",
      "registry_event_sha256": "f4a007c6633a567205abfe7d4aec2ddd055d7eb0f2fb1aa79aa227748ca067fb",
      "row_sha256": "14ac3b155bc0f8188c89ced97893b76d355fdaf4a85b55ef28cfdce682aa1cdb",
      "sequence": 6
    },
    {
      "action": "qualify",
      "candidate_digest": "c084f8b5e1b8bc1d99edaff856bdf0a36bc8631074769c32695c20c84b2f0c07",
      "historical_pass_digest": "5fa0dbc77f99a84bb2109cc9db8a2f5b9cf26a05e48ee8d05eb952b8edd6c3d0",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "14ac3b155bc0f8188c89ced97893b76d355fdaf4a85b55ef28cfdce682aa1cdb",
      "registry_event_sha256": "48b795e764cfb16e6fd409f25c6925dcab958cb39b5bc62cc91fe8f37d3cbce6",
      "row_sha256": "5e274fc5f671a3b4a61f56594feaa9baa05fb9a970996373d7e569281a5f20d8",
      "sequence": 7
    },
    {
      "action": "revoke",
      "candidate_digest": "c084f8b5e1b8bc1d99edaff856bdf0a36bc8631074769c32695c20c84b2f0c07",
      "historical_pass_digest": "5fa0dbc77f99a84bb2109cc9db8a2f5b9cf26a05e48ee8d05eb952b8edd6c3d0",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "5e274fc5f671a3b4a61f56594feaa9baa05fb9a970996373d7e569281a5f20d8",
      "registry_event_sha256": "dcb321cfac52bb58a9c9cd7bdb197c4bde80aa3c3a1081bedd1a08b3c0c1e2dc",
      "row_sha256": "edb6fdf636e77f0ea7ef1bbf35b307d1e08add024ab22730dbb636038f59e72b",
      "sequence": 8
    },
    {
      "action": "qualify",
      "candidate_digest": "144d5eeebe06e90aa43b2ca4c555b73afe826e033795bc37443e0c9c37c3094a",
      "historical_pass_digest": "20ab0d05c70fe95fb11c1ef4d1479a188a6caa8015285fcd5507be399d754e8a",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "edb6fdf636e77f0ea7ef1bbf35b307d1e08add024ab22730dbb636038f59e72b",
      "registry_event_sha256": "c6a15766327fb10c89ab7e4f407d754354af95847c11efbee2933de871bfd185",
      "row_sha256": "892d5e059b9e058f332c1d0251ba61ec3d0139dfb796aaa379dcb2430f2e9912",
      "sequence": 9
    },
    {
      "action": "revoke",
      "candidate_digest": "144d5eeebe06e90aa43b2ca4c555b73afe826e033795bc37443e0c9c37c3094a",
      "historical_pass_digest": "20ab0d05c70fe95fb11c1ef4d1479a188a6caa8015285fcd5507be399d754e8a",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "892d5e059b9e058f332c1d0251ba61ec3d0139dfb796aaa379dcb2430f2e9912",
      "registry_event_sha256": "3d7851b3360a38b308202b8d068e6152947f6f7f162fc36dd165b569a219b41d",
      "row_sha256": "aab792657b8ec796da15b5b89c74c2b41f6e6344c7fca02ac9db8c5a3945f607",
      "sequence": 10
    },
    {
      "action": "qualify",
      "candidate_digest": "0b883e109c995136f88e7350051bfab9dbcca7b8e3512311917c521e090153ea",
      "historical_pass_digest": "c5b38cab0798a1f76f624f82085dc9336edfa3bfd9cc2eb897ca2769550af7bd",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "aab792657b8ec796da15b5b89c74c2b41f6e6344c7fca02ac9db8c5a3945f607",
      "registry_event_sha256": "a0aa2b67f3d119cea81806f304305eefaca8ed157b5a676875605d7e057166ce",
      "row_sha256": "7cbaf0e7e1650f978e4caa4ace83e8a607a96db6830b66193c3769880ee05e43",
      "sequence": 11
    },
    {
      "action": "revoke",
      "candidate_digest": "0b883e109c995136f88e7350051bfab9dbcca7b8e3512311917c521e090153ea",
      "historical_pass_digest": "c5b38cab0798a1f76f624f82085dc9336edfa3bfd9cc2eb897ca2769550af7bd",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "7cbaf0e7e1650f978e4caa4ace83e8a607a96db6830b66193c3769880ee05e43",
      "registry_event_sha256": "15954ce6a8d0866c1695bd0fde46ac81416b4fcb94b79c6f6a3579b6136a7891",
      "row_sha256": "79c9de2a77abc54fcf9a5871be3081c3de5ae4050e49c010fdc768eb650ad7cb",
      "sequence": 12
    },
    {
      "action": "qualify",
      "candidate_digest": "8868327ffff5e85a5522079e40919bd9a6d732a685e42cbd5276aab81bcc2431",
      "historical_pass_digest": "abef260801e13061ddc9b477128eee49362040acea350ece1b900c26148cfcea",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "79c9de2a77abc54fcf9a5871be3081c3de5ae4050e49c010fdc768eb650ad7cb",
      "registry_event_sha256": "7ec1fd44d17eaada393d0268598c5ad5f2ffce05dfd2a2f455960dcfc72cba3e",
      "row_sha256": "8fe5e54e16586df8aa9dea86041892f4264ed6bdc8f8a6f7c7e30dbc43bdcfae",
      "sequence": 13
    },
    {
      "action": "revoke",
      "candidate_digest": "8868327ffff5e85a5522079e40919bd9a6d732a685e42cbd5276aab81bcc2431",
      "historical_pass_digest": "abef260801e13061ddc9b477128eee49362040acea350ece1b900c26148cfcea",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "8fe5e54e16586df8aa9dea86041892f4264ed6bdc8f8a6f7c7e30dbc43bdcfae",
      "registry_event_sha256": "ba5b1cd318e7b6fa9a69d11ce333a744a0df0a105e375e0a0eced76acbff7ceb",
      "row_sha256": "fb267c318043cac353231e915dfa01adf16d1d6ec9b07da1dd921912f3cfc679",
      "sequence": 14
    },
    {
      "action": "qualify",
      "candidate_digest": "78ecb799bc2e451f6055d892cb1f3af459dca62f4b8dd80c61ff8a3d43789538",
      "historical_pass_digest": "f3885df7210fea08692a2e52569a8825b3e39919ab5ff08f2f88d3f3f57544fd",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "fb267c318043cac353231e915dfa01adf16d1d6ec9b07da1dd921912f3cfc679",
      "registry_event_sha256": "81d6db8a607c3771214d3b1f121fe283e8f8609d15a327a3862c0fd5034564a2",
      "row_sha256": "bb640bbc2185a23afb72ce62ca40679ef55a979a854c12546af1bad3938cc45a",
      "sequence": 15
    },
    {
      "action": "revoke",
      "candidate_digest": "78ecb799bc2e451f6055d892cb1f3af459dca62f4b8dd80c61ff8a3d43789538",
      "historical_pass_digest": "f3885df7210fea08692a2e52569a8825b3e39919ab5ff08f2f88d3f3f57544fd",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "bb640bbc2185a23afb72ce62ca40679ef55a979a854c12546af1bad3938cc45a",
      "registry_event_sha256": "c2efc1dec3b5387eaacacf38e08af805c59f3ad57819ca79f92366467df23190",
      "row_sha256": "b4145eb685b356f00124540c7625103a929cfa51f780c2f3bdd381c474cb3c07",
      "sequence": 16
    },
    {
      "action": "qualify",
      "candidate_digest": "310632f25b112373d97355c5ce3290dc55fb6d036a735e2b53861d983c4fd648",
      "historical_pass_digest": "f712a4004b4e54a8e45f63ec7783265bc6145d77a08ac2adc9a1a4e1ed652157",
      "historical_pass_scope": "past_qualification_only",
      "previous_sha256": "b4145eb685b356f00124540c7625103a929cfa51f780c2f3bdd381c474cb3c07",
      "registry_event_sha256": "d4e0e2f6d44d15d9ca74c47941d5504a6c1618836b455567f268c7cec8cdffe7",
      "row_sha256": "3dd46f75fa61fe632315c0a8fa5c344671124289a890884ecb8352c741154549",
      "sequence": 17
    }
  ],
  "schema": "task26-qualification-ledger-v1"
}
--- candidate structural digest anchors ---
[
  "authority_ledger_head_sha256",
  "authority_registry_head_sha256",
  "candidate_digest",
  "document_sha256",
  "evidence_inventory",
  "expected_state_sha256",
  "golden_runtime_digest",
  "invalidated_candidates",
  "isolated_execution_sha256",
  "ledger_ready_sha256",
  "origin_proof",
  "product_digest",
  "schema",
  "trust_boundary_sha256",
  "wheelhouse_entry_count",
  "wheelhouse_inventory_sha256"
]
{
  "candidate_digest": "310632f25b112373d97355c5ce3290dc55fb6d036a735e2b53861d983c4fd648",
  "candidate_manifest_sha256": null,
  "candidate_manifest": null,
  "manifest_sha256": null,
  "files": 0,
  "entries": 0,
  "inventory": 0
}
--- expected state anchors ---
[
  "authority",
  "candidate_digest",
  "document_sha256",
  "expected_result_sha256",
  "expected_status",
  "hermes_wheel",
  "profile_wheel",
  "provenance_helper",
  "runtime_portable",
  "schema",
  "trust_boundary",
  "verifier",
  "wheelhouse"
]
{
  "candidate_digest": "310632f25b112373d97355c5ce3290dc55fb6d036a735e2b53861d983c4fd648",
  "sealed_file_count": null,
  "files": 0,
  "expected_files": 0,
  "wheelhouse": 5,
  "source": 0
}


--- evidence scenario results ---
01-onboarding_22_clear.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
02-deterministic_ambiguity_revision.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
03-preview_isolation.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
04-approved_card_projection_gate.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
05-unknown_delivery_no_retry.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
06-successful_lifecycle.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
07-cleanup_resume_terminal.json: {"status":null,"scenario":null,"assertions":null,"checks":null,"events":null,"failures":null,"details":null}
--- task specific security receipt snippets ---
===.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/receipts/security-attacks-installed.log===
.........                                                                [100%]
9 passed, 7 deselected in 1.46s
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001/onboarding
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001/onboarding'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001/outbox
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001/outbox'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers/client_001'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data/customers'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files/data'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6/files'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives/cfa1412d228c4359b98ca14a23a446d6'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup/archives'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data/customer-cleanup'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile/data'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0/profile'
  warnings.warn(
/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/_pytest/pathlib.py:96: PytestWarning: (rm_rf) error removing /tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0
<class 'OSError'>: [Errno 39] Directory not empty: '/tmp/pytest-of-cube/garbage-a0c0fb0d-3ac5-4f97-8002-ac7f027151f0/test_duplicate_and_concurrent_0'
  warnings.warn(

===.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/receipts/security-attacks-source.log===
.........                                                                [100%]
9 passed, 7 deselected in 1.42s

===.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/receipts/direct-url-attack-installed.json===
{"attack":"direct-URL dependency","reason":"direct URL dependencies are forbidden","status":"PASS"}

===.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/receipts/direct-url-attack-source.json===
{"attack":"direct-URL dependency","reason":"direct URL dependencies are forbidden","status":"PASS"}

===.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/receipts/installed-runtime-probe.json===
{"origin_probe":{"cwd":"/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/controlled-cwd","isolated":1,"modules":{"checkin_cli":"/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/checkin_cli/__init__.py","gateway":"/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/gateway/__init__.py"},"pythonpath_present":false,"schema":"task26-rehydrated-origin-probe-v1"},"runtime":{"distributions":{"hermes":{"dist_info":"/home/cube/.cache/task26-isolated-bound-runtime-st_01a01574-v10/venv/lib/python3.12/site-packages/hermes_agent-0.17.0.dist-info","distribution_name":"hermes-agent","distribution_version":"0.17.0","installed_inventory":[{"path":"../../../bin/dualcoach_admin","sha256":"ef703ae33b9d7b317ed2f2d7f0b0caab3861845f11849a7e1c093c940c50998c","size":295},{"path":"../../../bin/dualcoach_tasks21_25_controller","sha256":"349077091fcc320e4d6cb68413dace940a8962bfac73f3ebf93dbfad74e33a49","size":311},{"path":"../../../bin/hermes","sha256":"8bcbae42cea582a01b942feeca6d159c2b2b404e73eabc31a6a74aed471c4f08","size":277},{"path":"../../../bin/hermes-acp","sha256":"307a15156b4ecf52d6ae2665480be5f3c5f9ddbae13409e3cbe38d76036c2456","size":279},{"path":"../../../bin/hermes-agent","sha256":"9796ebf75d9b6adeacddcc2d0c93d8cb1ae0ea750fed24072a45684aca8d2e67","size":271},{"path":"../../../locales/af.yaml","sha256":"d950512308a5c124535e1da357b39c3e4d6ceab6b966d729bdddcdd469dc66ff","size":27098},{"path":"../../../locales/de.yaml","sha256":"01c244a51f3d80775ddbd9eae4b38dc9fedf8301bbd1b99504f975bee8746e0b","size":28352},{"path":"../../../locales/en.yaml","sha256":"bc6ac5f81f2547a43fcb6366841a56c9d21b55f5cafb8281e1937c15751cbece","size":26591},{"path":"../../../locales/es.yaml","sha256":"db54c48ce19adaa421ea8dc1ff2ab409aea5448414e80098254ad7d826ca0fd2","size":28119},{"path":"../../../locales/fr.yaml","sha256":"831b383ca71cf5d90ff515553aff6d83e28daa3c191b34e4cadf891eb780ddaa","size":28565},{"path":"../../../locales/ga.yaml","sha256":"6be039b0b6b41f68fb32332b30121b9d4a9f291992d3a9d233b661bb1247fca6","size":28957},{"path":"../../../locales/hu.yaml","sha256":"5709ec0df26064641ae5e3d35f03fc2051cb1f1cf3fbb4727568ddbef0f30862","size":29273},{"path":"../../../locales/it.yaml","sha256":"52b8fc801848f49b2f32c148f6cbb373ee765d02cdd396fd5551eb277a45c246","size":27920},{"path":"../../../locales/ja.yaml","sha256":"86a1cff1c2741e543940425fff5f164476e61a7a55debff8a368c36db77e3bb2","size":32706},{"path":"../../../locales/ko.yaml","sha256":"85bffd4f9598a6178975942b189f9168d5ea8a07690531002d6ccba128a9d3bc","size":29813},{"path":"../../../locales/pt.yaml","sha256":"e8064421258a4a66708d63f67a5c33c9b011a3b4b91b52ce7b13d51d85f24280","size":28140},{"path":"../../../locales/ru.yaml","sha256":"c2fea6e231eb1403c646f1ecf8ffab3b9c0d7d32b0d6c44177001fc844486262","size":37475},{"path":"../../../locales/tr.yaml","sha256":"117533fffade5cf515569b36e36eb872fba1b299f23e2956362e8a62a0074773","size":27843},{"path":"../../../locales/uk.yaml","sha256":"79ad25d24facbac0f0db7e63471340baf88d0e940f042ebd61dd88934b5ed19c","size":37624},{"path":"../../../locales/zh-hant.yaml","sha256":"2a941cc42289d9d6f17c088d6fd2ad7fbebfeb6a71018f2e72d1cf7de60491d5","size":26378},{"path":"../../../locales/zh.yaml","sha256":"ac99c83a88387dc3789eb567de7531b796ed8cafc9112e508a7623b22fd7b592","size":25839},{"path":"../../../optional-mcps/linear/manifest.yaml","sha256":"f3065abe734885e7adef9af7a2ee96c224cc79b88158c29fab88e5ab1098d478","size":1477},{"path":"../../../optional-mcps/n8n/manifest.yaml","sha256":"448ed9cd21b6e14afca6c70902e98475c725ced26d0e7645224aa877e31da71b","size":2703},{"path":"acp_adapter/__init__.py","sha256":"c841e4cd574c5ae19003aebaee22396db3cc515dd600934059bbe78958324e98","size":67},{"path":"acp_adapter/__main__.py","sha256":"65164332e6d17cb9325248ea8bbdf346e5ced681e6474c6d28f1729bd5c26225","size":99},{"path":"acp_adapter/auth.py","sha256":"fa19bb0ec30e202e860c742c95e7035417d03cf0933750f0c83d4a4329891f5d","size":2854},{"path":"acp_adapter/edit_approval.py","sha256":"d7378886d66635621104f0a7b21d6768807fe71340e79501464b4b900a63ec90","size":9531},{"path":"acp_adapter/entry.py","sha256":"7cb4be5532a03450136368a9d9ee0eb1ef578fbf920ec219a0427b8cda3c505e","size":8956},{"path":"acp_adapter/events.py","sha256":"a961f50b288feca5664871d929cbf2f2532cdaaa50f206ad6fbdcb77a9f2ca38","size":9824},{"path":"acp_adapter/permissions.py","sha256":"57001c99a5c04d6c5c795d2e0b18d1f4b021e3731d9d011eb9142301e8e95bc4","size":5526},{"path":"acp_adapter/provenance.py","sha256":"138ffc113f473a9d3b423ca55526d8c2b68ba8ca1f29a23255c8891e5ac3954c","size":4669},{"path":"acp_adapter/server.py","sha256":"4b2f1e2b1a5df583955e1c97acdf527d95eca6bb641bfa2f0d5d4dd03240a8f0","size":86110},{"path":"acp_adapter/session.py","sha256":"46fc1e36f66648892841e047a66e518aa6ab1855625af4fb4b9ab39a872f8a94","size":23398},{"path":"acp_adapter/tools.py","sha256":"45a36272bb881bfcec4378c3b5d74272d53ea0e4db75e4dd56b0db666da3efd7","size":53868},{"path":"agent/__init__.py","sha256":"99f85bec3844de2bfbd984d64768b22a3a4c5dba01375c6832b292d24e1617e4","size":337},{"path":"agent/account_usage.py","sha256":"9d641878a4999af6c820d5b31918c643a187803fbd6440b381f186bc171c99c1","size":24592},{"path":"agent/agent_init.py","sha256":"7e90d8202794bec74c05285018a211e596abdf66b75b662d1b6b1618da2a7f7b","size":89649},{"path":"agent/agent_runtime_helpers.py","sha256":"deb4b766d047a8129026798b1d8f1dc43f9564c174adc6b7d694980213f1d685","size":115100},{"path":"agent/anthropic_adapter.py","sha256":"65b1ae7d939b4c59d7eafb11609d2ffd07bd6ae6b3c7a52110b8cb79ab61ed57","size":110703},{"path":"agent/async_utils.py","sha256":"fce5e59bd1079207e4c4ef280a99f8543f0c50af6b3eba1dc2d73bef0b47f670","size":2551},{"path":"agent/auxiliary_client.py","sha256":"0ef47cd358c2c5b9d54038602b822015f2abe70f4423cbda1f3e71f2878d8f57","size":289147},{"path":"agent/azure_identity_adapter.py","sha256":"3a3ec5fc5ae0e9d149863d4165ae0026352e277aaadb8544e5e94eaf89624be0","size":23066},{"path":"agent/background_review.py","sha256":"68556e01b5c9caf5a5c0147f58b40d31932e57c491525252d7426024b938449c","size":36876},{"path":"agent/bedrock_adapter.py","sha256":"0b5e87d7fd2ff5974cc928b66348ba17eac323ff6b4542a3d17d9cc880db7b1d","size":53255},{"path":"agent/billing_view.py","sha256":"24ca4126e6be0c21f1658be34225dd8770f60310885e2d55accecaec52c5a878","size":10816},{"path":"agent/browser_provider.py","sha256":"d91962a5e22c728ac745a60326b07f02b13c8e715a29bdc956ecfd11b2987119","size":7127},{"path":"agent/browser_registry.py","sha256":"189256e28316d68c60c2bfba4575e08c32ae520ced458f8c233115f0a14fe11a","size":7662},{"path":"agent/chat_completion_helpers.py","sha256":"002e78d009a0e758dd724b732b2402b7e4740de40d1da642f214e85327201de3","size":133529},{"path":"agent/codex_responses_adapter.py","sha256":"bc32d3fbc0cef1a7e7b93d82eb0ec2cac1fcb4342eb22a17d0fed36f2f5d3b7b","size":61435},{"path":"agent/codex_runtime.py","sha256":"1463415d4ea81b1d67154183424671c29b65db7ac14d1152ae012b1f7858dd47","size":28973},{"path":"agent/coding_context.py","sha256":"e37ee484d37da7a4f8d8046ddbbfeb6a75df7081734c590e1e82d172b8f9c72e","size":31656},{"path":"agent/context_compressor.py","sha256":"7b8e2891de5f3f4c39e069ecb3e20605784b2dc930454f87309f5503e5869308","size":116076},{"path":"agent/context_engine.py","sha256":"a0eca9190b2f5060ad3a8574ad80a0aa377b5e847064018e30895befa50a78da","size":8873},{"path":"agent/context_references.py","sha256":"919d76ee81a508c91c0e073de00ecb76669e9e3e760a78287492012a145b2988","size":18383},{"path":"agent/conversation_compression.py","sha256":"08dcace7c25f37d4985015e6c7c9c6a9b70ed93baed387598b2cda293e145a56","size":43954},{"path":"agent/conversation_loop.py","sha256":"ecc7d7b35361b0a4067e346e04fd2955563e40ce7e6fd9d15be9ac8e20feb34d","size":253135},{"path":"agent/copilot_acp_client.py","sha256":"8f7da2714097848d95474f91d4d9f9fb2b1088a104ff95be2e4c36f0cc26ef59","size":24328},{"path":"agent/credential_persistence.py","sha256":"90837202cdb5670601f399d7cb2a69470f846c4f4a3839cd8793f9c2ccdf7780","size":5020},{"path":"agent/credential_pool.py","sha256":"3756c1f91a1e8b3b8e1d7508e90f3399538aca3c0220acd149a0808e6484d4f6","size":99766},{"path":"agent/credential_sources.py","sha256":"8c928627fc91c96998ddd57a45d7604598c2b80c0a2c41b96910ff2aa906d197","size":18766},{"path":"agent/credits_tracker.py","sha256":"caa05e8169c2cad03b80f693087af07a66c894ddc50b1808a25ef39e5e41647d","size":37810},{"path":"agent/curator.py","sha256":"18945e999df5e6bf31649b7a41d8157c818053a0dbb722fb67a15dd476622441","size":81902},{"path":"agent/curator_backup.py","sha256":"bc4af49b9bd8e4007fbd4abc82c4f15ffe3422aa129bc84fb4b8f56d7e33ad69","size":27640},{"path":"agent/display.py","sha256":"0002c962cc7e995f6b55f999b62a853cb8bfc148bc940ce762ebd9886562342c","size":41108},{"path":"agent/error_classifier.py","sha256":"026c0b1fdeac58342df9dcf636dac2d718a1ce18da4983cfa9027cbc95b57c79","size":55668},{"path":"agent/errors.py","sha256":"5d783749f00fa40101db03b4d1ca64e6c6968b7ae3e92c4e8ff07d1315304c08","size":119},{"path":"agent/file_safety.py","sha256":"8e042a26f6d967d7f1c8924077752fcdc08aae3681ffb4e12ce6dcf9485a7d1c","size":25310},{"path":"agent/gemini_cloudcode_adapter.py","sha256":"766b88aeb68d194df7e24dd24f013743a9f0e34067a35ae855f7179ffa5f03c9","size":34078},{"path":"agent/gemini_native_adapter.py","sha256":"85819852a919704c2eec815a48711cac2c1335b02ad5138aed2c4a5061dbbee4","size":36572},{"path":"agent/gemini_schema.py","sha256":"a34dcdea0e3e017402ba6424fadd62505cb6e10960aef52e8ec8be1ea0163a82","size":3338},{"path":"agent/google_code_assist.py","sha256":"895e43189b460ed0f13d6690f5ca7db494343c1558ff3c3c55482fd9604e8e6d","size":16854},{"path":"agent/google_oauth.py","sha256":"bd2a34c19a0d331d04a5f92a0d19d175bb04be18a0136b9e3681824a4da2a365","size":38620},{"path":"agent/i18n.py","sha256":"da00908c795175144294cb29be6e216889a20c598fa26442aac7ea8acdc68beb","size":11563},{"path":"agent/image_gen_provider.py","sha256":"ec4908a2d6484d5bda09d771f7d49881c388bcd3cc2db67d632ee44c46a73cf0","size":13673},{"path":"agent/image_gen_registry.py","sha256":"8de740e6c193a0ea338cd5eb47b2752c728df3865e07a487fc5833f03f183ee5","size":5158},{"path":"agent/image_routing.py","sha256":"757864fd9857c2542daa0fa5968a293ace787eef668b4a98a0e5c102d6a92689","size":21104},{"path":"agent/insights.py","sha256":"1377136ad7011acb6faf171bc6412ee0efd077bc69e15e97432d8d8f0492e745","size":38613},{"path":"agent/iteration_budget.py","sha256":"84d59d56993715920fc53f9d670a8f66523235d7a2b94e94b14847d61f381082","size":1992},{"path":"agent/jiter_preload.py","sha256":"1df1336c3c6bc67904dcc13572c159d169afa71ad94494dc7ddebe8843337536","size":1175},{"path":"agent/lmstudio_reasoning.py","sha256":"fdf64cb2e02a7a25796b2f28a720518d273c135831e23bdf7e36de9cfe1fbf48","size":2026},{"path":"agent/lsp/__init__.py","sha256":"5fce00264dd2e4d02750fd092063fb54de3308993003e234ee228f4b7f02981f","size":3943},{"path":"agent/lsp/cli.py","sha256":"1930c3a0f27c38f90ebcb1b27428ec46fd5d126f00588b39fc339c6cabe0c77b","size":10584},{"path":"agent/lsp/client.py","sha256":"29656ba299297ff6c7d32b2e845edace60dfacfd3dbe9768a843e2d84446c087","size":37878},{"path":"agent/lsp/eventlog.py","sha256":"dbc1f63dd0815129cc54745a614370457931321b12d82df361f98bc184d4733a","size":7782},{"path":"agent/lsp/install.py","sha256":"3d1d4ff99a016ac29699210b14fff902f9159c55f6d61f799201892365682760","size":14431},{"path":"agent/lsp/manager.py","sha256":"5ba99bebfe204d2299b2ca97d0b7c3302916896948d46046df35d14262a3da09","size":25828},{"path":"agent/lsp/protocol.py","sha256":"04747ff4fbc6113da44c3eee8bcda691809df6cf0afac993265bd82b94c5de18","size":6759},{"path":"agent/lsp/range_shift.py","sha256":"775cab0472fc25c1b71a296e9a87c2ac1aba433cbc73ed54f0731fdcf01e2295","size":6073},{"path":"agent/lsp/reporter.py","sha256":"20b812dd8142abc5b30568b9c0a71f776302e80ea2ec9370d58ed3d8c3e701ba","size":2558},{"path":"agent/lsp/servers.py","sha256":"d2e2f48349ab88962e039c8a0713369b42cb214c8ff9575c8c087534dde0bd39","size":34301},{"path":"agent/lsp/workspace.py","sha256":"3cf2155fd06655ab57bdf7b768274f2d64207924283e87909dbfd5241cd609e9","size":7763},{"path":"agent/manual_compression_feedback.py","sha256":"970206dad272f05492c36d9eb022d51ad500badb3be3a5be57450dd6deafd36f","size":1565},{"path":"agent/markdown_tables.py","sha256":"3aa4aed00eb23e52bbc7cc39b3080ef1a15296239add74147eb6179b6ca9bc05","size":10258},{"path":"agent/memory_manager.py","sha256":"7454b39671eba5f89901d2b96d81754c3e5d21ed693553115b89f9f39d15f154","size":37420},{"path":"agent/memory_provider.py","sha256":"597210754e83a0eab2c522c233d87cb2dbad6d2b423c6bccd07cf6162072c5bd","size":12297},{"path":"agent/message_content.py","sha256":"83ca96c3300ece2fc5f3e3a3bee2b7201cb9b664bf17bcb51373593f33fc0aa3","size":1347},{"path":"agent/message_sanitization.py","sha256":"bea1a9fd2a24f5e56d10fe5cf93b0186c3d578e40c04a91afbf0bea56c7665d2","size":17594},{"path":"agent/model_metadata.py","sha256":"44e28ae9a1ca9cbc147827f509203de1e5351e089994a04e1a63d3c82b676431","size":89465},{"path":"agent/models_dev.py","sha256":"bc68a199e808893f57e3fefbd3548927622dfc211e6fa7f9c08ed8988dbc4b89","size":25639},{"path":"agent/moonshot_schema.py","sha256":"095c1b66b4a3c531ab46ba8d5b23dcf60431915c49f027de203c12b3be0c3c56","size":9805},{"path":"agent/nous_rate_guard.py","sha256":"edbb54b3100c4b870631023fabfbb8df22c8cd5a664dd42e0e6180d1e89ea039","size":11090},{"path":"agent/onboarding.py","sha256":"a902454b073e8173439031c3fc42d464a6f10832744ae17d3a184f4d2ab74ad9","size":10290},{"path":"agent/plugin_llm.py","sha256":"4158b0ed2be2140eb99f09e1a488daed04da496052fe415cb84e412e4b71fb30","size":38661},{"path":"agent/portal_tags.py","sha256":"7012801387f3a97f028721ba2aa08f29bb228b127cc0cfc27bb57a5be51469db","size":2367},{"path":"agent/process_bootstrap.py","sha256":"da32d8c11a2a97e171cfee39c6891274cc60af8a8ad69020545a291c2b891a12","size":5200},{"path":"agent/prompt_builder.py","sha256":"9667e06eabca287adcfa4b034a6d3b0b7337a24673777266f1f0962ad37ae5e6","size":87021},{"path":"agent/prompt_caching.py","sha256":"4f1261a4cc2917b38c87f09bfde3c4d1b9afe2a11774013a792d8dafff8ddb7f","size":2437},{"path":"agent/rate_limit_tracker.py","sha256":"38d7dab81a470f00bc45f3d0d58ecb5105035babeab80d8f5b45b812630e8756","size":8458},{"path":"agent/redact.py","sha256":"0aed6e85ad6a1418d9637439372b703821204e0f854832d9d655ff020a3544a7","size":19624},{"path":"agent/retry_utils.py","sha256":"448db34fefabca195102e31b42fce79e25c8228ce943ce0203af2c59d833e5a2","size":1812},{"path":"agent/runtime_cwd.py","sha256":"6ac5f599dd11da46905d6fe7c244380e08ea3626a4e07246a5875e20b4313f49","size":2037},{"path":"agent/secret_scope.py","sha256":"e4fc76b51e360b96a773927b19e2e1ce592e9295d8ecd747dcf383e7668b48f2","size":8649},{"path":"agent/secret_sources/__init__.py","sha256":"179f86d13921bebb39700bec4f22ade473eea2836b91a2aead113a6a85d1d920","size":546},{"path":"agent/secret_sources/bitwarden.py","sha256":"7349d5544f8551b1db06c5cb29f871909271b3f44916c8d26cc17b66d83a1901","size":25512},{"path":"agent/shell_hooks.py","sha256":"0d25aaa64cf38d7942267934932b404903182f1c7e9eef67bc351de384c245f2","size":30018},{"path":"agent/skill_bundles.py","sha256":"c32510ad6ef23a3237dc76048972a003f3a8cac03e3b385380bc86757c846b7d","size":13572},{"path":"agent/skill_commands.py","sha256":"35307fed554fb2633166d89746fc53a14dfe71eb81fa1b65411a9332a400193e","size":24021},{"path":"agent/skill_preprocessing.py","sha256":"54927510bd11439e3623497c99cd65394fe4920105ec186ff0ec68b5e84c7a14","size":4806},{"path":"agent/skill_utils.py","sha256":"12c814701b8e2c1ad21c5e8ca2019a36dda2baa8a218b663bfcfe99237d040f9","size":27117},{"path":"agent/ssl_guard.py","sha256":"9aea6d0d4d5c88aec9a55357b2b6b6183dab282e5ffd4b02b59992d2fc45ff63","size":3104},{"path":"agent/stream_diag.py","sha256":"80405602a3c459ee2ebfd6a70c22537e533314600847475fd1c81bd08dfe05a2","size":9877},{"path":"agent/subdirectory_hints.py","sha256":"7521e6b44fd00f95998529b10b1e852a47c93b27d1c6ef21e88253b2a80503e5","size":10028},{"path":"agent/system_prompt.py","sha256":"3a03e0cb661691e0f4187eef75be0fe182d04333ba34f5f9ef177035cf1eb1e5","size":24256},{"path":"agent/think_scrubber.py","sha256":"080552759edc99ab5c21261f0ff2186e74528d7b783dfe31d3de89110b6c7b7c","size":15430},{"path":"agent/title_generator.py","sha256":"1a8686f3fa93abd9b5f5b4295d76b2f8ea1945aa589655dbb42d6a256bad5ac2","size":7052},{"path":"agent/tool_dispatch_helpers.py","sha256":"274aab40544dc8173a9c0852417c41b699595fd4167c72c58a1ff98a1de67e66","size":14802},{"path":"agent/tool_executor.py","sha256":"0d00f80220e21e55d29f94bf764d6f185f4d0ca6a3968c5c025e756c3a4af843","size":70514},{"path":"agent/tool_guardrails.py","sha256":"7adfaea16ba984d9ea43af15ab526652f7be4f9995518dadc06d01fdfc5c6a85","size":17934},{"path":"agent/tool_result_classification.py","sha256":"d8312576d03a3087b0d1dfccdc394efecb7ce96d1e3dd88b9207131ac313376a","size":777},{"path":"agent/trajectory.py","sha256":"f1163056e1b5ba0588fc6b85a58dc8c4bb48eca9d27a256e358308222e5b3934","size":2028},{"path":"agent/transcription_provider.py","sha256":"fc43c1abb1ce3496f70c8a5e8b40dd017cfb6812632b6684ab2c1ebaac27a4a1","size":6894},{"path":"agent/transcription_registry.py","sha256":"e2d4c59b08a2e8a5042dc2f68015e07c8d1909b163efeffb862ebfb97c609eea","size":4124},{"path":"agent/transports/__init__.py","sha256":"fe832003b28c5470608eb51a055e5cc759f1fb81d93174b54dbbd217f97bbffe","size":2017},{"path":"agent/transports/anthropic.py","sha256":"7bac289e5d9022a15ec9f4cbab9fad9a1c22a135f39f02e1a7530b2b8d504573","size":11261},{"path":"agent/transports/base.py","sha256":"e9b0d020f9cf1aae5d0a470363c7694cb3f3f0257fbeff00fc80435e9b80befe","size":3024},{"path":"agent/transports/bedrock.py","sha256":"527d2af5acccf582f4247c3357c2d08869a0be5cf8f4ef888200e17f5884ad07","size":5459},{"path":"agent/transports/chat_completions.py","sha256":"2215e620a4bae80d1cdeac53b72b9df8b680694af970ad85eabf88e1660d8c19","size":34059},{"path":"agent/transports/codex.py","sha256":"5792aa97238da2471d374478cc76342a4c3812dc8a3510300002ea2c30441266","size":20781},{"path":"agent/transports/codex_app_server.py","sha256":"8ed97de64f51622f937f62063037263cbb23fa7211e7eb289a577cfa8c255b79","size":14846},{"path":"agent/transports/codex_app_server_session.py","sha256":"1b33e9461d41398bf2a5762617340d1745266b86667d26d8ba50baa21574bf59","size":38386},{"path":"agent/transports/codex_event_projector.py","sha256":"deaa15be5e727c1d7e06a31f8cc73ef0af312884664c87ede3a6513aad3bc7c8","size":12736},{"path":"agent/transports/hermes_tools_mcp_server.py","sha256":"d69a6f7d6d331e08d1104f06fe29e33144f7d28f0673dcfd64689d0d42839d0f","size":9140},{"path":"agent/transports/types.py","sha256":"148b1f6389d10952a70da2a79c7a6baf056f7a41178b9b5e0b673626dad2fa2b","size":6332},{"path":"agent/tts_provider.py","sha256":"0878120da094b250bf8d30a3fb32ae1d8481c0331a9099ceef7608ccb1c888cf","size":10331},{"path":"agent/tts_registry.py","sha256":"54c546a1a077b77660bc87f3421ec84c3fce18ed3a1d4e38fb68e1f9439df835","size":4411},{"path":"agent/turn_context.py","sha256":"fb75869bec92072e337302e61734a092da1b506dd0535bccc55dbb4d039ae93d","size":17518},{"path":"agent/turn_finalizer.py","sha256":"9eeaf590357cdc08274770677b874fd3eb3c8609bc1f14ca2bae8d00717b643b","size":19689},{"path":"agent/turn_retry_state.py","sha256":"e06d7ecda3c0de57ece520aeef531c6347ff7dde0faa904a725c1e778e5cc0a0","size":3338},{"path":"agent/usage_pricing.py","sha256":"6e4c50192324cb2d384b0b6174478865d08b843cf69f166c0604c3ec306cdefd","size":34476},{"path":"agent/video_gen_provider.py","sha256":"d76806ca313e957e93b16034454028f1deab8fc11894230cf56af7b3768df478","size":10095},{"path":"agent/video_gen_registry.py","sha256":"10a4b7696dfdfae90e666a820e56107616ee2129528df7fdaf7449cb77fa776f","size":3659},{"path":"agent/web_search_provider.py","sha256":"340287269dcc7868c1d05299bd1cce7f233de3ae4d701e5660fabfee9b525967","size":6527},{"path":"agent/web_search_registry.py","sha256":"a7906429cfc7cd8d5a45baa8aa4da3e4fefdf10a336799792e2d2883c0f9fe11","size":9103},{"path":"batch_runner.py","sha256":"2acba9a0d1245871c2c1e29898f546c74912b3d42f469a559d7


**Planning targeted test cleanup inspection**

**Planning source extraction from wheel archives**

**Refining JSON extraction with targeted keys**

bash

ROOT=.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10; printf '%s\n' '--- candidate evidence inventory names and result anchors ---'; jq -r '.evidence_inventory[] | [.path,.sha256,.size] | @tsv' "$ROOT/candidate.json"; printf '%s\n' '--- expected verifier and wheel anchors ---'; jq '{schema,candidate_digest,expected_status,expected_result_sha256,verifier,provenance_helper,hermes_wheel,profile_wheel,wheelhouse,authority,trust_boundary}' "$ROOT/sealed-expected-state.json"; printf '%s\n' '--- summary check inventory ---'; jq '{status, candidate_digest, checks, qualification, security, scenarios, sealed_files, evidence_inventory}' "$ROOT/qualification-summary.json"

W=.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10/artifacts; printf '%s\n' '--- hermes task26 code/tests ---'; unzip -l "$W/hermes_agent-0.17.0-py3-none-any.whl" | grep -Ei '(task26|onboarding|candidate.authority|final.state|commit.receipt|commit.observer)' | head -300; printf '%s\n' '--- profile task26 code/tests ---'; unzip -l "$W/physique_checkin_cli-0.1.0-py3-none-any.whl" | grep -Ei '(task26|onboarding|candidate|delivery|projection|cleanup|observer|test)' | head -400

ROOT=.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10; printf '%s\n' '--- artifact & inventory consistency, symlinks, duplicates ---'; sha256sum "$ROOT"/artifacts/*.whl; jq -r '.entries[] | [.relative_path,.sha256,.size,.mode,.project,.version] | @tsv' "$ROOT/seals/wheelhouse-inventory.json" > /tmp/task26-wheel-inventory.tsv; printf 'inventory_entries='; wc -l < /tmp/task26-wheel-inventory.tsv; printf 'actual_wheels='; find "$ROOT/wheelhouse" -maxdepth 1 -type f -name '*.whl' | wc -l; printf 'all_dir_entries='; find "$ROOT/wheelhouse" -mindepth 1 -maxdepth 1 -printf '%y %f\n' | sort | uniq -c; printf 'symlinks='; find "$ROOT/wheelhouse" -type l -printf '%p -> %l\n'; printf 'duplicate normalized projects:'; cut -f5 /tmp/task26-wheel-inventory.tsv | sort | uniq -d; printf '\nmissing/extra/name-mismatch:'; comm -3 <(cut -f1 /tmp/task26-wheel-inventory.tsv | sort) <(find "$ROOT/wheelhouse" -maxdepth 1 -type f -name '*.whl' -printf '%f\n' | sort); printf '\nmode anomalies:'; awk -F '\t' '$4 != 256 {print}' /tmp/task26-wheel-inventory.tsv

ROOT=.omo/evidence/task26/task26-isolated-bound-wheelhouse-installed-st_01a01574-v10; printf '%s\n' '--- expected task26 scenario files: metadata ---'; for f in "$ROOT/installed-golden-bundle/task26-evidence"/*.json; do echo "==$(basename "$f")=="; jq 'keys' "$f"; jq -r 'to_entries[] | select(.key|test("status|result|scenario|assertion|check|pass|fail|step|event|delivery|projection|cleanup";"i")) | [.key, (.value|tostring|.[0:500])] | @tsv' "$f"; done; printf '%s\n' '--- scenario receipt stream types ---'; jq -r '[.type,.event,.action,.status,.result,.name,.operation] | map(select(. != null)) | @json' "$ROOT/installed-golden-bundle/task26-evidence/receipts.jsonl"


#!/usr/bin/env python3
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
import os
import stat
import sys
from pathlib import Path
from typing import Any, cast

def canonical(value: object) -> bytes:
    return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False).encode()

def sha256_file(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()

def document(path: Path, label: str) -> dict[str, Any]:
    value = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(value, dict) or any(not isinstance(key, str) for key in value):
        raise ValueError(f"{label} is invalid")
    return cast(dict[str, Any], value)

def load_module(path: Path, name: str) -> Any:
    spec = importlib.util.spec_from_file_location(name, path)
    if spec is None or spec.loader is None:
        raise ValueError(f"module unavailable: {path}")
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

def verify_modes(bundle: Path, *, allow_mutable: bool) -> None:
    for path in (bundle, *sorted(bundle.rglob("*"))):
        info = path.lstat()
        if stat.S_ISLNK(info.st_mode) or info.st_uid != os.geteuid():
            raise ValueError(f"unsafe bundle path: {path}")
        if path.is_dir():
            allowed = {0o500, 0o700} if allow_mutable else {0o500}
        elif path.is_file() and info.st_nlink == 1:
            allowed = {0o400, 0o600} if allow_mutable else {0o400}
        else:
            raise ValueError(f"bundle path type is invalid: {path}")
        if stat.S_IMODE(info.st_mode) not in allowed:
            raise ValueError(f"bundle mode is not frozen: {path}")

def verify(bundle: Path, runtime_path: Path | None, *, allow_mutable: bool) -> dict[str, object]:
    bundle = bundle.absolute()
    verify_modes(bundle, allow_mutable=allow_mutable)
    candidate = document(bundle / "candidate.json", "candidate manifest")
    unsigned_candidate = {key: value for key, value in candidate.items() if key != "document_sha256"}
    if candidate.get("document_sha256") != hashlib.sha256(canonical(unsigned_candidate)).hexdigest():
        raise ValueError("candidate manifest digest is invalid")
    candidate_digest = str(candidate.get("candidate_digest", ""))
    authority_module = load_module(bundle / "gateway/platforms/task26_candidate_authority.py", "sealed_task26_authority")
    authority = authority_module.verify_candidate_authority(bundle, candidate_digest)
    expected_heads = {
        "registry_head_sha256": candidate.get("authority_registry_head_sha256"),
        "ledger_head_sha256": candidate.get("authority_ledger_head_sha256"),
    }
    if any(authority.get(key) != value for key, value in expected_heads.items()):
        raise ValueError("candidate authority heads differ from manifest")
    expected = document(bundle / "sealed-expected-state.json", "sealed expected state")
    final_state_module = load_module(
        bundle / "gateway/platforms/task26_final_state.py", "sealed_task26_final_state"
    )
    hermes_wheel = next((bundle / "artifacts").glob("hermes_agent-*.whl"))
    profile_wheel = next((bundle / "artifacts").glob("physique_checkin_cli-*.whl"))
    final_state_module.verify_expected_state(
        bundle,
        bundle / "sealed-expected-state.json",
        hermes_wheel=hermes_wheel,
        profile_wheel=profile_wheel,
    )
    wheelhouse = final_state_module.verify_wheelhouse_inventory(
        bundle / "wheelhouse",
        expected.get("wheelhouse"),
        required_wheels=(profile_wheel, hermes_wheel),
    )
    ledger_ready = document(bundle / "ledger-ready-receipt.json", "ledger-ready receipt")
    if ledger_ready.get("document_sha256") != hashlib.sha256(canonical({key: value for key, value in ledger_ready.items() if key != "document_sha256"})).hexdigest():
        raise ValueError("ledger-ready receipt digest is invalid")
    if ledger_ready != {
        "schema": "task26-ledger-ready-receipt-v1",
        "candidate_digest": candidate_digest,
        "registry_head_sha256": authority["registry_head_sha256"],
        "ledger_head_sha256": authority["ledger_head_sha256"],
        "expected_state_sha256": sha256_file(bundle / "sealed-expected-state.json"),
        "document_sha256": ledger_ready["document_sha256"],
    }:
        raise ValueError("ledger-ready receipt binding is invalid")
    if candidate.get("expected_state_sha256") != sha256_file(bundle / "sealed-expected-state.json") or candidate.get("ledger_ready_sha256") != sha256_file(bundle / "ledger-ready-receipt.json"):
        raise ValueError("candidate final-state binding is invalid")
    excluded = {"candidate.json", "SEAL.json"}
    actual = [
        {"path": path.relative_to(bundle).as_posix(), "sha256": sha256_file(path), "size": path.stat().st_size}
        for path in sorted(bundle.rglob("*"))
        if path.is_file() and path.relative_to(bundle).as_posix() not in excluded
    ]
    if actual != candidate.get("evidence_inventory"):
        raise ValueError("candidate evidence inventory differs")
    seal = document(bundle / "SEAL.json", "bundle seal")
    unsigned_seal = {key: value for key, value in seal.items() if key != "document_sha256"}
    if seal.get("document_sha256") != hashlib.sha256(canonical(unsigned_seal)).hexdigest() or seal.get("candidate_manifest_sha256") != sha256_file(bundle / "candidate.json") or seal.get("candidate_digest") != candidate_digest or seal.get("registry_head_sha256") != authority["registry_head_sha256"] or seal.get("ledger_head_sha256") != authority["ledger_head_sha256"]:
        raise ValueError("bundle seal binding is invalid")
    verifier_module = load_module(bundle / "verification-tools/verify_source_golden_path.py", "sealed_golden_verifier")
    contract = verifier_module.verify_task26_contract(bundle / "installed-golden-bundle")
    installed_receipt = document(bundle / "receipts/installed-golden-verifier-1.json", "installed Golden receipt")
    if contract != installed_receipt.get("task26_contract") or installed_receipt.get("candidate_digest") != candidate_digest:
        raise ValueError("installed seven-clause receipt differs")
    observer = {
        "backend": installed_receipt.get("observer_backend"),
        "directory_resource_count": installed_receipt.get("observer_directory_resource_count"),
        "inotify_watch_count": installed_receipt.get("observer_inotify_watch_count"),
        "receipt_count": installed_receipt.get("observer_receipt_count"),
    }
    if observer != {
        "backend": "dnotify_signalfd_v1",
        "directory_resource_count": 1,
        "inotify_watch_count": 0,
        "receipt_count": 5,
    }:
        raise ValueError("zero-inotify observer receipt differs")
    rehydrated = False
    if runtime_path is not None:
        runtime = verifier_module.read_private_json(runtime_path)
        verified = verifier_module.verify(bundle / "installed-golden-bundle", runtime_override=runtime)
        if verified.get("status") != "ACTUAL_INSTALLED_GOLDEN_PATH_PASS" or verified.get("candidate_digest") != candidate_digest or verified.get("task26_contract") != contract:
            raise ValueError("rehydrated installed Golden verification differs")
        rehydrated = True
    result = {
        "status": "TASK26_FROZEN_CANDIDATE_PASS",
        "candidate_digest": candidate_digest,
        "product_digest": candidate.get("product_digest"),
        "golden_runtime_digest": candidate.get("golden_runtime_digest"),
        "candidate_authority": authority,
        "installed_task26_contract": contract,
        "observer": observer,
        "isolated_execution": expected["runtime_portable"]["origin_proof"]["execution"],
        "installed_origin_proof": expected["runtime_portable"]["origin_proof"],
        "trust_boundary": expected["trust_boundary"],
        "wheelhouse_inventory_sha256": wheelhouse["inventory_sha256"],
        "wheelhouse_entry_count": len(wheelhouse["entries"]),
        "frozen_modes_verified": not allow_mutable,
        "rehydrated_runtime_verified": rehydrated,
    }
    if runtime_path is not None and expected.get("candidate_digest") != candidate_digest:
        raise ValueError("sealed expected state candidate differs")
    return result

def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("bundle", type=Path)
    parser.add_argument("--rehydrated-runtime", type=Path)
    parser.add_argument("--allow-mutable", action="store_true")
    args = parser.parse_args()
    try:
        result = verify(args.bundle, args.rehydrated_runtime, allow_mutable=args.allow_mutable)
    except (OSError, ValueError, json.JSONDecodeError) as exc:
        print(json.dumps({"status": "TASK26_FROZEN_CANDIDATE_FAIL", "reason": str(exc)}, sort_keys=True), file=sys.stderr)
        return 1
    print(json.dumps(result, ensure_ascii=False, sort_keys=True, separators=(",", ":")))
    return 0

if __name__ == "__main__":
    raise SystemExit(main())


#!/usr/bin/env python3
"""Strict, offline provenance primitives for installed Golden Path runtimes."""
from __future__ import annotations

import base64
import csv
import hashlib
import io
import json
import os
import stat
import sys
import zipfile
from email.parser import BytesParser
from email.policy import compat32
from pathlib import Path
from typing import Any, Iterable, Mapping, Sequence, cast

def canonical(value: object) -> bytes:
    return json.dumps(
        value,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
        allow_nan=False,
    ).encode()

def sha256_file(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as stream:
        for chunk in iter(lambda: stream.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()

def _normal(name: str) -> str:
    return "-".join(name.lower().replace("_", "-").split("-"))

def _within(path: Path, roots: Iterable[Path]) -> bool:
    resolved = path.resolve(strict=True)
    return any(resolved == root.resolve(strict=True) or resolved.is_relative_to(root.resolve(strict=True)) for root in roots)

def _regular(path: Path, label: str, *, private: bool = False) -> None:
    info = path.lstat()
    if stat.S_ISLNK(info.st_mode):
        raise ValueError(f"{label} is a symlink")
    if not stat.S_ISREG(info.st_mode) or info.st_nlink != 1 or info.st_uid != os.geteuid():
        raise ValueError(f"{label} is not an owned regular file")
    if private and stat.S_IMODE(info.st_mode) not in {0o600, 0o400}:
        raise ValueError(f"{label} permissions are not private")

def _private_directory(path: Path, label: str) -> None:
    info = path.lstat()
    if stat.S_ISLNK(info.st_mode):
        raise ValueError(f"{label} is a symlink")
    if not stat.S_ISDIR(info.st_mode) or info.st_uid != os.geteuid():
        raise ValueError(f"{label} is not an owned directory")
    if stat.S_IMODE(info.st_mode) not in {0o700, 0o500}:
        raise ValueError(f"{label} permissions are not private")

def read_private_json(path: Path) -> dict[str, Any]:
    _regular(path, "provenance", private=True)
    value = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(value, dict) or any(not isinstance(key, str) for key in value):
        raise ValueError("provenance is not an object")
    return cast(dict[str, Any], value)

def _decode_record_hash(value: str, label: str) -> str:
    algorithm, separator, encoded = value.partition("=")
    if algorithm != "sha256" or not separator or not encoded:
        raise ValueError(f"{label} RECORD hash is invalid")
    try:
        raw = base64.urlsafe_b64decode(encoded + "=" * (-len(encoded) % 4))
    except Exception as exc:
        raise ValueError(f"{label} RECORD hash is invalid") from exc
    if len(raw) != hashlib.sha256().digest_size:
        raise ValueError(f"{label} RECORD hash is invalid")
    return raw.hex()

def _record_rows(data: bytes, record_relative: str, label: str) -> list[tuple[str, str, int | None]]:
    try:
        decoded = data.decode("utf-8")
        parsed = list(csv.reader(io.StringIO(decoded, newline="")))
    except (UnicodeDecodeError, csv.Error) as exc:
        raise ValueError(f"{label} RECORD is invalid") from exc
    rows: list[tuple[str, str, int | None]] = []
    seen: set[str] = set()
    for row in parsed:
        if len(row) != 3:
            raise ValueError(f"{label} RECORD row is invalid")
        relative, encoded_hash, raw_size = row
        candidate = Path(relative)
        if not relative or candidate.is_absolute() or relative in seen:
            raise ValueError(f"{label} RECORD path is invalid")
        seen.add(relative)
        if relative == record_relative:
            if encoded_hash or raw_size:
                raise ValueError(f"{label} RECORD self-row is invalid")
            rows.append((relative, "", None))
            continue
        if not encoded_hash or not raw_size.isdecimal():
            raise ValueError(f"{label} RECORD hash or size is missing")
        rows.append((relative, _decode_record_hash(encoded_hash, label), int(raw_size)))
    if record_relative not in seen:
        raise ValueError(f"{label} RECORD self-row is missing")
    return rows

def _wheel_inventory(
    wheel: Path,
    dist_info_name: str,
    installed_rows: Sequence[tuple[str, str, int | None]],
    label: str,
    *,
    site_packages: Path,
    venv: Path,
) -> str:
    _regular(wheel, f"{label} wheel", private=True)
    try:
        with zipfile.ZipFile(wheel) as archive:
            names = archive.namelist()
            if len(names) != len(set(names)) or any(name.startswith("/") or ".." in Path(name).parts for name in names):
                raise ValueError(f"{label} wheel members are invalid")
            record_relative = f"{dist_info_name}/RECORD"
            wheel_record = archive.read(record_relative)
            rows = _record_rows(wheel_record, record_relative, label)
            installed_by_path = {row[0]: row for row in installed_rows}
            if set(names) != {row[0] for row in rows}:
                raise ValueError(f"{label} wheel inventory differs from wheel RECORD")
            data_prefix = f"{dist_info_name.removesuffix('.dist-info')}.data/"
            for relative, expected_hash, expected_size in rows:
                if relative == record_relative:
                    continue
                try:
                    payload = archive.read(relative)
                except KeyError as exc:
                    raise ValueError(f"{label} wheel RECORD member is missing: {relative}") from exc
                if len(payload) != expected_size:
                    raise ValueError(f"{label} wheel RECORD size mismatch: {relative}")
                if hashlib.sha256(payload).hexdigest() != expected_hash:
                    raise ValueError(f"{label} wheel RECORD hash mismatch: {relative}")
                installed_relative = relative
                if relative.startswith(data_prefix):
                    scheme, separator, suffix = relative[len(data_prefix):].partition("/")
                    if not separator or not suffix:
                        raise ValueError(f"{label} wheel data member is invalid: {relative}")
                    if scheme in {"purelib", "platlib"}:
                        installed_relative = suffix
                    elif scheme == "data":
                        installed_relative = Path(os.path.relpath(venv / suffix, site_packages)).as_posix()
                    else:
                        raise ValueError(f"{label} unsupported wheel data scheme: {scheme}")
                installed = installed_by_path.get(installed_relative)
                if installed != (installed_relative, expected_hash, expected_size):
                    raise ValueError(f"{label} installed RECORD differs for wheel member: {relative}")
            return hashlib.sha256(wheel_record).hexdigest()
    except zipfile.BadZipFile as exc:
        raise ValueError(f"{label} wheel is invalid") from exc

def verify_packaged_module_parity(
    *,
    source: Path,
    wheel: Path,
    wheel_member: str,
    installed: Path,
) -> dict[str, object]:
    """Prove one packaged helper is byte-identical in source, wheel, and install."""
    _regular(source, "module source")
    _regular(wheel, "module wheel", private=True)
    _regular(installed, "installed module")
    member = Path(wheel_member)
    if not wheel_member or member.is_absolute() or ".." in member.parts:
        raise ValueError("wheel module path is invalid")
    try:
        with zipfile.ZipFile(wheel) as archive:
            names = archive.namelist()
            if wheel_member not in names:
                raise ValueError("packaged module is absent from wheel")
            payload = archive.read(wheel_member)
            record_names = [name for name in names if name.endswith(".dist-info/RECORD")]
            if len(record_names) != 1:
                raise ValueError("wheel RECORD cardinality is invalid")
            rows = _record_rows(archive.read(record_names[0]), record_names[0], "module wheel")
            row = next((item for item in rows if item[0] == wheel_member), None)
            if row is None or row[1] != hashlib.sha256(payload).hexdigest() or row[2] != len(payload):
                raise ValueError("packaged module wheel RECORD binding is invalid")
    except zipfile.BadZipFile as exc:
        raise ValueError("module wheel is invalid") from exc
    source_bytes = source.read_bytes()
    installed_bytes = installed.read_bytes()
    if source_bytes != payload or installed_bytes != payload:
        raise ValueError("source, wheel, and installed module bytes differ")
    digest = hashlib.sha256(payload).hexdigest()
    return {
        "module": wheel_member.removesuffix(".py").replace("/", "."),
        "sha256": digest,
        "size": len(payload),
        "source_path": str(source.resolve(strict=True)),
        "wheel_path": str(wheel.resolve(strict=True)),
        "installed_path": str(installed.resolve(strict=True)),
    }

def inspect_installed_distribution(
    *,
    venv: Path,
    site_packages: Path,
    wheel: Path,
    distribution_name: str,
    import_packages: Sequence[str],
) -> dict[str, object]:
    """Recompute one wheel's installed inventory from METADATA and RECORD."""
    venv = venv.absolute()
    site_packages = site_packages.absolute()
    wheel = wheel.absolute()
    _private_directory(venv, "installed venv")
    if not site_packages.is_dir() or not _within(site_packages, (venv,)):
        raise ValueError("site-packages is outside the installed venv")
    matches: list[tuple[Path, bytes, str, str]] = []
    for dist_info in sorted(site_packages.glob("*.dist-info")):
        if dist_info.is_symlink() or not dist_info.is_dir():
            continue
        metadata_path = dist_info / "METADATA"
        if not metadata_path.is_file() or metadata_path.is_symlink():
            continue
        metadata = metadata_path.read_bytes()
        message = BytesParser(policy=compat32).parsebytes(metadata)
        name = str(message.get("Name", ""))
        version = str(message.get("Version", ""))
        if _normal(name) == _normal(distribution_name):
            matches.append((dist_info, metadata, name, version))
    if len(matches) != 1:
        raise ValueError(f"installed distribution cardinality is invalid: {distribution_name}")
    dist_info, metadata, declared_name, version = matches[0]
    if not version:
        raise ValueError(f"installed distribution version is unavailable: {distribution_name}")
    record = dist_info / "RECORD"
    _regular(record, f"{distribution_name} RECORD")
    record_data = record.read_bytes()
    record_relative = record.relative_to(site_packages).as_posix()
    rows = _record_rows(record_data, record_relative, distribution_name)
    inventory: list[dict[str, object]] = []
    for relative, expected_hash, expected_size in rows:
        target = site_packages / relative
        try:
            target.resolve(strict=True)
        except OSError as exc:
            raise ValueError(f"{distribution_name} RECORD file is unavailable: {relative}") from exc
        if not _within(target, (venv,)):
            raise ValueError(f"{distribution_name} RECORD path escapes the installed venv")
        _regular(target, f"{distribution_name} RECORD file")
        if relative == record_relative:
            actual_hash = hashlib.sha256(record_data).hexdigest()
            actual_size = len(record_data)
        else:
            actual_size = target.stat().st_size
            if actual_size != expected_size:
                raise ValueError(f"{distribution_name} RECORD size mismatch: {relative}")
            actual_hash = sha256_file(target)
            if actual_hash != expected_hash:
                raise ValueError(f"{distribution_name} RECORD hash mismatch: {relative}")
        inventory.append({"path": relative, "sha256": actual_hash, "size": actual_size})
    wheel_record_sha256 = _wheel_inventory(
        wheel,
        dist_info.name,
        rows,
        distribution_name,
        site_packages=site_packages,
        venv=venv,
    )
    package_roots: list[str] = []
    for package in import_packages:
        if not package or "." in package or "/" in package:
            raise ValueError("import package name is invalid")
        root = site_packages / package
        if root.is_symlink() or not root.is_dir():
            raise ValueError(f"installed package root is unavailable: {package}")
        package_roots.append(str(root.resolve(strict=True)))
    return {
        "distribution_name": declared_name,
        "distribution_version": version,
        "dist_info": str(dist_info.resolve(strict=True)),
        "metadata_sha256": hashlib.sha256(metadata).hexdigest(),
        "package_roots": package_roots,
        "record_path": str(record.resolve(strict=True)),
        "record_sha256": hashlib.sha256(record_data).hexdigest(),
        "wheel_filename": wheel.name,
        "wheel_path": str(wheel),
        "wheel_sha256": sha256_file(wheel),
        "wheel_record_sha256": wheel_record_sha256,
        "installed_inventory": inventory,
        "installed_inventory_sha256": hashlib.sha256(canonical(inventory)).hexdigest(),
    }

def validate_import_environment(
    *,
    venv: Path,
    site_packages: Path,
    import_packages: Sequence[str],
    search_path: Sequence[str] | None = None,
    executable: Path | None = None,
) -> dict[str, object]:
    """Reject another import authority ahead of the declared site-packages."""
    venv = venv.absolute()
    site_packages = site_packages.resolve(strict=True)
    declared_python = venv / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
    if not declared_python.exists():
        raise ValueError("installed interpreter is unavailable")
    actual = (executable or Path(sys.executable)).absolute()
    try:
        same = os.path.samefile(actual, declared_python)
    except OSError:
        same = False
    if not same:
        raise ValueError("running interpreter differs from declared installed interpreter")
    entries = tuple(sys.path if search_path is None else search_path)
    resolved_entries: list[Path] = []
    for entry in entries:
        candidate = Path(entry or os.getcwd()).absolute()
        if candidate.exists():
            resolved_entries.append(candidate.resolve(strict=True))
    try:
        site_index = resolved_entries.index(site_packages)
    except ValueError as exc:
        raise ValueError("declared site-packages is absent from interpreter search path") from exc
    for entry in resolved_entries[:site_index]:
        if entry == site_packages:
            continue
        if any((entry / package).exists() for package in import_packages):
            raise ValueError(f"import authority precedes declared site-packages: {entry}")
    interpreter = declared_python.resolve(strict=True)
    _regular(interpreter, "installed interpreter")
    return {
        "declared_path": str(declared_python.absolute()),
        "resolved_path": str(interpreter),
        "sha256": sha256_file(interpreter),
        "version": list(sys.version_info[:3]),
        "site_packages": str(site_packages),
    }

def loaded_module_receipts(
    modules: Mapping[str, Path], *, allowed_roots: Sequence[Path]
) -> list[dict[str, object]]:
    roots = tuple(root.resolve(strict=True) for root in allowed_roots)
    receipts: list[dict[str, object]] = []
    for name, raw_path in sorted(modules.items()):
        path = raw_path.absolute()
        if not _within(path, roots):
            raise ValueError(f"loaded module is outside declared installed roots: {name}")
        _regular(path, f"loaded module {name}")
        receipts.append(
            {
                "module": name,
                "path": str(path.resolve(strict=True)),
                "sha256": sha256_file(path),
                "size": path.stat().st_size,
            }
        )
    return receipts

def portable_installed_runtime(runtime: Mapping[str, object]) -> dict[str, object]:
    """Remove ephemeral paths while retaining every byte and RECORD identity."""
    distributions = cast(Mapping[str, object], runtime.get("distributions"))
    portable_distributions: dict[str, object] = {}
    for role in ("profile", "hermes"):
        distribution = cast(Mapping[str, object], distributions.get(role))
        inventory = [
            row
            for row in cast(Sequence[Mapping[str, object]], distribution.get("installed_inventory"))
            if ".." not in Path(str(row.get("path", ""))).parts
            and not str(row.get("path", "")).endswith(".dist-info/RECORD")
        ]
        portable_distribution: dict[str, object] = {
            key: distribution.get(key)
            for key in (
                "distribution_name", "distribution_version", "metadata_sha256",
                "wheel_filename", "wheel_sha256", "wheel_record_sha256",
            )
        }
        portable_distribution["installed_inventory"] = inventory
        portable_distribution["installed_inventory_sha256"] = hashlib.sha256(
            canonical(inventory)
        ).hexdigest()
        portable_distributions[role] = portable_distribution
    interpreter = cast(Mapping[str, object], runtime.get("interpreter"))
    return {
        "schema": "installed-golden-runtime-portable-v1",
        "interpreter": {
            "sha256": interpreter.get("sha256"),
            "version": interpreter.get("version"),
        },
        "distributions": portable_distributions,
    }

def collect_installed_runtime(
    *,
    venv: Path,
    site_packages: Path,
    profile_wheel: Path,
    hermes_wheel: Path,
) -> dict[str, object]:
    interpreter = validate_import_environment(
        venv=venv,
        site_packages=site_packages,
        import_packages=("checkin_cli", "gateway"),
    )
    profile = inspect_installed_distribution(
        venv=venv,
        site_packages=site_packages,
        wheel=profile_wheel,
        distribution_name="physique-checkin-cli",
        import_packages=("checkin_cli",),
    )
    hermes = inspect_installed_distribution(
        venv=venv,
        site_packages=site_packages,
        wheel=hermes_wheel,
        distribution_name="hermes-agent",
        import_packages=("gateway",),
    )
    return {
        "schema": "installed-golden-runtime-v1",
        "venv": str(venv.absolute()),
        "site_packages": str(site_packages.resolve(strict=True)),
        "interpreter": interpreter,
        "distributions": {"profile": profile, "hermes": hermes},
    }


"""Append-only qualification and revocation authority for Task26 candidates.

Historical bundle PASS artifacts remain immutable statements about past
qualification.  Current authority is derived only from these paired registry and
ledger chains.
"""
from __future__ import annotations

import hashlib
import json
import os
import re
from pathlib import Path
from typing import Any, Literal, cast

AuthorityAction = Literal["qualify", "revoke"]
ZERO = "0" * 64
AUTHORITY_STATEMENT = (
    "historical immutable PASS describes past qualification; current authority "
    "comes only from this append-only registry and qualification ledger"
)
_DIGEST = re.compile(r"^[0-9a-f]{64}$")

def _canonical(value: object) -> bytes:
    return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False).encode()

def _digest(value: object) -> str:
    return hashlib.sha256(_canonical(value)).hexdigest()

def _object(value: object, label: str) -> dict[str, Any]:
    if not isinstance(value, dict) or any(not isinstance(key, str) for key in value):
        raise ValueError(f"{label} is invalid")
    return cast(dict[str, Any], value)

def _read(path: Path, label: str) -> dict[str, Any]:
    if path.is_symlink() or not path.is_file():
        raise ValueError(f"{label} is unavailable")
    return _object(json.loads(path.read_text(encoding="utf-8")), label)

def _write(path: Path, value: object) -> None:
    path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
    path.parent.chmod(0o700)
    temporary = path.with_name(f".{path.name}.{os.getpid()}.tmp")
    fd = os.open(temporary, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600)
    try:
        os.write(fd, _canonical(value) + b"\n")
        os.fsync(fd)
    finally:
        os.close(fd)
    os.replace(temporary, path)
    path.chmod(0o600)

def _paths(root: Path) -> tuple[Path, Path]:
    authority = root / "candidate-authority"
    return authority / "registry.json", authority / "qualification-ledger.json"

def _empty() -> tuple[dict[str, object], dict[str, object]]:
    registry: dict[str, object] = {
        "schema": "task26-candidate-revocation-registry-v1",
        "authority_statement": AUTHORITY_STATEMENT,
        "events": [],
        "head_sha256": ZERO,
        "ledger_head_sha256": ZERO,
        "current_qualified_candidate": None,
        "invalidated_candidate_digests": [],
    }
    registry["document_sha256"] = _digest(registry)
    ledger: dict[str, object] = {
        "schema": "task26-qualification-ledger-v1",
        "authority_statement": AUTHORITY_STATEMENT,
        "rows": [],
        "head_sha256": ZERO,
        "registry_head_sha256": ZERO,
    }
    ledger["document_sha256"] = _digest(ledger)
    return registry, ledger

def append_candidate_authority(
    root: Path,
    *,
    candidate_digest: str,
    action: AuthorityAction,
    historical_pass_digest: str,
    reason: str,
) -> dict[str, object]:
    """Append one paired registry event and ledger row."""
    if _DIGEST.fullmatch(candidate_digest) is None or _DIGEST.fullmatch(historical_pass_digest) is None:
        raise ValueError("candidate authority digest is invalid")
    if action not in {"qualify", "revoke"} or not reason.strip() or len(reason) > 240:
        raise ValueError("candidate authority action is invalid")
    registry_path, ledger_path = _paths(root)
    if registry_path.exists() or ledger_path.exists():
        verify_candidate_authority(root, None)
        registry = _read(registry_path, "candidate revocation registry")
        ledger = _read(ledger_path, "qualification ledger")
    else:
        registry, ledger = _empty()
    events = list(cast(list[object], registry["events"]))
    rows = list(cast(list[object], ledger["rows"]))
    invalidated = list(cast(list[str], registry["invalidated_candidate_digests"]))
    qualified = {
        str(cast(dict[str, object], event)["candidate_digest"])
        for event in events
        if cast(dict[str, object], event).get("action") == "qualify"
    }
    if action == "revoke" and (candidate_digest not in qualified or candidate_digest in invalidated):
        raise ValueError("revocation has no bound predecessor qualification")
    if action == "qualify" and candidate_digest in invalidated:
        raise ValueError("a revoked digest cannot be requalified")
    sequence = len(events) + 1
    event: dict[str, object] = {
        "sequence": sequence,
        "previous_sha256": registry["head_sha256"],
        "ledger_predecessor_sha256": ledger["head_sha256"],
        "action": action,
        "candidate_digest": candidate_digest,
        "historical_pass_digest": historical_pass_digest,
        "historical_pass_scope": "past_qualification_only",
        "reason": reason.strip(),
    }
    event["event_sha256"] = _digest(event)
    row: dict[str, object] = {
        "sequence": sequence,
        "previous_sha256": ledger["head_sha256"],
        "registry_event_sha256": event["event_sha256"],
        "action": action,
        "candidate_digest": candidate_digest,
        "historical_pass_digest": historical_pass_digest,
        "historical_pass_scope": "past_qualification_only",
    }
    row["row_sha256"] = _digest(row)
    events.append(event)
    rows.append(row)
    if action == "revoke":
        invalidated.append(candidate_digest)
    current = candidate_digest if action == "qualify" else registry["current_qualified_candidate"]
    if action == "revoke" and current == candidate_digest:
        current = None
    next_registry: dict[str, object] = {
        "schema": "task26-candidate-revocation-registry-v1",
        "authority_statement": AUTHORITY_STATEMENT,
        "events": events,
        "head_sha256": event["event_sha256"],
        "ledger_head_sha256": row["row_sha256"],
        "current_qualified_candidate": current,
        "invalidated_candidate_digests": sorted(invalidated),
    }
    next_registry["document_sha256"] = _digest(next_registry)
    next_ledger: dict[str, object] = {
        "schema": "task26-qualification-ledger-v1",
        "authority_statement": AUTHORITY_STATEMENT,
        "rows": rows,
        "head_sha256": row["row_sha256"],
        "registry_head_sha256": event["event_sha256"],
    }
    next_ledger["document_sha256"] = _digest(next_ledger)
    _write(registry_path, next_registry)
    _write(ledger_path, next_ledger)
    return {"registry_head_sha256": event["event_sha256"], "ledger_head_sha256": row["row_sha256"], "current_qualified_candidate": current}

def verify_candidate_authority(root: Path, candidate_digest: str | None) -> dict[str, object]:
    """Verify both chains and, when supplied, require current non-revoked authority."""
    registry_path, ledger_path = _paths(root)
    registry = _read(registry_path, "candidate revocation registry")
    ledger = _read(ledger_path, "qualification ledger")
    if registry.get("schema") != "task26-candidate-revocation-registry-v1" or ledger.get("schema") != "task26-qualification-ledger-v1":
        raise ValueError("candidate authority schema is invalid")
    if registry.get("authority_statement") != AUTHORITY_STATEMENT or ledger.get("authority_statement") != AUTHORITY_STATEMENT:
        raise ValueError("candidate authority scope is invalid")
    if registry.get("document_sha256") != _digest({key: value for key, value in registry.items() if key != "document_sha256"}):
        raise ValueError("candidate registry document digest is invalid")
    if ledger.get("document_sha256") != _digest({key: value for key, value in ledger.items() if key != "document_sha256"}):
        raise ValueError("qualification ledger document digest is invalid")
    events = registry.get("events")
    rows = ledger.get("rows")
    if not isinstance(events, list) or not isinstance(rows, list) or len(events) != len(rows) or not events:
        raise ValueError("candidate authority chain cardinality is invalid")
    registry_previous = ZERO
    ledger_previous = ZERO
    current: str | None = None
    invalidated: set[str] = set()
    qualified: set[str] = set()
    for sequence, (raw_event, raw_row) in enumerate(zip(events, rows, strict=True), 1):
        event = _object(raw_event, "candidate registry event")
        row = _object(raw_row, "qualification ledger row")
        event_hash = event.get("event_sha256")
        row_hash = row.get("row_sha256")
        if (
            event.get("sequence") != sequence
            or row.get("sequence") != sequence
            or event.get("previous_sha256") != registry_previous
            or event.get("ledger_predecessor_sha256") != ledger_previous
            or row.get("previous_sha256") != ledger_previous
            or row.get("registry_event_sha256") != event_hash
            or event_hash != _digest({key: value for key, value in event.items() if key != "event_sha256"})
            or row_hash != _digest({key: value for key, value in row.items() if key != "row_sha256"})
            or any(event.get(key) != row.get(key) for key in ("action", "candidate_digest", "historical_pass_digest", "historical_pass_scope"))
            or event.get("historical_pass_scope") != "past_qualification_only"
        ):
            raise ValueError("candidate authority predecessor or digest binding is invalid")
        digest = str(event.get("candidate_digest"))
        if event.get("action") == "qualify":
            if digest in invalidated:
                raise ValueError("revoked candidate was requalified")
            qualified.add(digest)
            current = digest
        elif event.get("action") == "revoke":
            if digest not in qualified or digest in invalidated:
                raise ValueError("revocation has no bound predecessor qualification")
            invalidated.add(digest)
            if current == digest:
                current = None
        else:
            raise ValueError("candidate authority action is invalid")
        registry_previous = str(event_hash)
        ledger_previous = str(row_hash)
    if (
        registry.get("head_sha256") != registry_previous
        or registry.get("ledger_head_sha256") != ledger_previous
        or ledger.get("head_sha256") != ledger_previous
        or ledger.get("registry_head_sha256") != registry_previous
        or registry.get("current_qualified_candidate") != current
        or registry.get("invalidated_candidate_digests") != sorted(invalidated)
    ):
        raise ValueError("latest registry and ledger binding is stale")
    if candidate_digest is not None:
        if candidate_digest in invalidated:
            raise ValueError("candidate digest is revoked")
        if current != candidate_digest:
            raise ValueError("candidate is not the latest qualified candidate")
    return {"registry_head_sha256": registry_previous, "ledger_head_sha256": ledger_previous, "current_qualified_candidate": current, "invalidated_candidate_digests": sorted(invalidated)}


"""Hash-linked same-invocation evidence writer for the Task26 Golden Path.

This module records raw inputs and native API outcomes.  It deliberately emits no
PASS counters or verdicts; the independent verifier owns every acceptance rule.
"""
from __future__ import annotations

import hashlib
import json
import os
import secrets
from pathlib import Path
from typing import Mapping

ZERO = "0" * 64
CLAUSES = (
    "onboarding_22_clear",
    "deterministic_ambiguity_revision",
    "preview_isolation",
    "approved_card_projection_gate",
    "unknown_delivery_no_retry",
    "successful_lifecycle",
    "cleanup_resume_terminal",
)

def canonical(value: object) -> bytes:
    return json.dumps(
        value,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
        allow_nan=False,
    ).encode("utf-8")

def sha256_bytes(value: bytes) -> str:
    return hashlib.sha256(value).hexdigest()

class Task26EvidenceWriter:
    """Append one immutable artifact and one chained receipt per required clause."""

    def __init__(self, profile: Path, *, candidate_digest: str) -> None:
        self.root = profile / "task26-evidence"
        self.root.mkdir(mode=0o700)
        self.root.chmod(0o700)
        self.receipts = self.root / "receipts.jsonl"
        self.receipts.touch(mode=0o600)
        self.receipts.chmod(0o600)
        self.invocation_id = secrets.token_hex(16)
        self.candidate_digest = candidate_digest
        self._previous = ZERO
        self._sequence = 0

    def record(self, clause: str, payload: Mapping[str, object]) -> None:
        if clause not in CLAUSES or self._sequence >= len(CLAUSES):
            raise ValueError("Task26 clause is invalid or duplicated")
        if clause != CLAUSES[self._sequence]:
            raise ValueError("Task26 clauses must be emitted in contract order")
        self._sequence += 1
        artifact_name = f"{self._sequence:02d}-{clause}.json"
        artifact = {
            "schema": "task26-native-artifact-v1",
            "invocation_id": self.invocation_id,
            "candidate_digest": self.candidate_digest,
            "clause": clause,
            "payload": dict(payload),
        }
        artifact_bytes = canonical(artifact) + b"\n"
        artifact_path = self.root / artifact_name
        fd = os.open(
            artifact_path,
            os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW,
            0o600,
        )
        try:
            os.write(fd, artifact_bytes)
            os.fsync(fd)
        finally:
            os.close(fd)
        receipt = {
            "schema": "task26-native-receipt-v1",
            "sequence": self._sequence,
            "clause": clause,
            "invocation_id": self.invocation_id,
            "candidate_digest": self.candidate_digest,
            "previous_sha256": self._previous,
            "artifact": artifact_name,
            "artifact_sha256": sha256_bytes(artifact_bytes),
        }
        receipt["receipt_sha256"] = sha256_bytes(canonical(receipt))
        with self.receipts.open("ab") as stream:
            stream.write(canonical(receipt) + b"\n")
            stream.flush()
            os.fsync(stream.fileno())
        self._previous = str(receipt["receipt_sha256"])

    def finish(self) -> str:
        if self._sequence != len(CLAUSES):
            raise RuntimeError("Task26 evidence contract is incomplete")
        return self._previous