tallylock 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. tallylock-0.1.0a1/.github/workflows/ci.yml +88 -0
  2. tallylock-0.1.0a1/.github/workflows/release.yml +54 -0
  3. tallylock-0.1.0a1/LICENSE +202 -0
  4. tallylock-0.1.0a1/MANIFEST.in +21 -0
  5. tallylock-0.1.0a1/NOTICE +7 -0
  6. tallylock-0.1.0a1/PKG-INFO +89 -0
  7. tallylock-0.1.0a1/PLAN.md +131 -0
  8. tallylock-0.1.0a1/README.md +69 -0
  9. tallylock-0.1.0a1/RUNBOOK.md +23 -0
  10. tallylock-0.1.0a1/conformance/README.md +25 -0
  11. tallylock-0.1.0a1/docs/ACCEPTANCE.md +45 -0
  12. tallylock-0.1.0a1/docs/DEPENDENCIES.md +20 -0
  13. tallylock-0.1.0a1/docs/IMPLEMENTATION_PLAN.md +283 -0
  14. tallylock-0.1.0a1/docs/INTEGRATION.md +72 -0
  15. tallylock-0.1.0a1/docs/METHODS.md +40 -0
  16. tallylock-0.1.0a1/docs/PROTOCOL.md +131 -0
  17. tallylock-0.1.0a1/docs/QUICKSTART.md +111 -0
  18. tallylock-0.1.0a1/docs/READINESS.md +48 -0
  19. tallylock-0.1.0a1/docs/SOURCES.md +23 -0
  20. tallylock-0.1.0a1/docs/TESTING_HANDOFF.md +39 -0
  21. tallylock-0.1.0a1/docs/THREAT_MODEL.md +30 -0
  22. tallylock-0.1.0a1/docs/reviews/COLONY_ZERO_FEEDBACK.md +18 -0
  23. tallylock-0.1.0a1/docs/reviews/FINAL_REVIEW.md +39 -0
  24. tallylock-0.1.0a1/docs/reviews/IMPLEMENTATION_REVIEW.md +147 -0
  25. tallylock-0.1.0a1/docs/reviews/OUROBOROS_FEEDBACK.md +18 -0
  26. tallylock-0.1.0a1/docs/reviews/REVIEW_LOG.md +61 -0
  27. tallylock-0.1.0a1/docs/roadmap/AGENT_GUIDE.md +77 -0
  28. tallylock-0.1.0a1/docs/roadmap/DESIGN.md +214 -0
  29. tallylock-0.1.0a1/docs/roadmap/FEATURES.json +230 -0
  30. tallylock-0.1.0a1/docs/roadmap/NOVICE_OVERVIEW.md +42 -0
  31. tallylock-0.1.0a1/docs/roadmap/PHASE1_RECUT.md +89 -0
  32. tallylock-0.1.0a1/docs/roadmap/README.md +51 -0
  33. tallylock-0.1.0a1/docs/roadmap/ROADMAP.md +98 -0
  34. tallylock-0.1.0a1/docs/roadmap/WEBSITE_PLAN.md +51 -0
  35. tallylock-0.1.0a1/docs/testing-feedback.schema.json +95 -0
  36. tallylock-0.1.0a1/docs/testing-feedback.template.json +19 -0
  37. tallylock-0.1.0a1/examples/basic/README.md +19 -0
  38. tallylock-0.1.0a1/examples/basic/manifest.json +17 -0
  39. tallylock-0.1.0a1/examples/basic/outputs/metrics.json +1 -0
  40. tallylock-0.1.0a1/examples/basic/outputs/run-log.txt +2 -0
  41. tallylock-0.1.0a1/pyproject.toml +35 -0
  42. tallylock-0.1.0a1/setup.cfg +4 -0
  43. tallylock-0.1.0a1/src/tallylock/__init__.py +3 -0
  44. tallylock-0.1.0a1/src/tallylock/__main__.py +4 -0
  45. tallylock-0.1.0a1/src/tallylock/_http.py +223 -0
  46. tallylock-0.1.0a1/src/tallylock/anchors.py +193 -0
  47. tallylock-0.1.0a1/src/tallylock/canonical.py +122 -0
  48. tallylock-0.1.0a1/src/tallylock/chain.py +71 -0
  49. tallylock-0.1.0a1/src/tallylock/cli.py +624 -0
  50. tallylock-0.1.0a1/src/tallylock/data/conformance/README.md +66 -0
  51. tallylock-0.1.0a1/src/tallylock/data/conformance/canonical.json +1 -0
  52. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-artifact-bytes.json +1 -0
  53. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-attempt.json +1 -0
  54. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-base64.json +1 -0
  55. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-bool-counter.json +1 -0
  56. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-budget.json +1 -0
  57. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-call-after-end.json +1 -0
  58. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-call-before-start.json +1 -0
  59. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-completed-null-score.json +1 -0
  60. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-completed-reason.json +1 -0
  61. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-duplicate.json +1 -0
  62. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-float.json +1 -0
  63. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-noncanonical.json +1 -0
  64. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-unsafe.json +1 -0
  65. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-cross-sample-retry.json +1 -0
  66. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-dangling-call.json +1 -0
  67. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-duplicate-call.json +1 -0
  68. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-duplicate-start.json +1 -0
  69. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-early-terminal.json +1 -0
  70. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-envelope-field.json +1 -0
  71. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-event-binding.json +1 -0
  72. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-event-future.json +1 -0
  73. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-extra-artifact.json +1 -0
  74. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-false-math-all-hashes.json +1 -0
  75. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-false-math.json +1 -0
  76. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-dataset-pin.json +1 -0
  77. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-denominator.json +1 -0
  78. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-duplicate.json +1 -0
  79. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-observed-type.json +1 -0
  80. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-unknown-field.json +1 -0
  81. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-event-kind.json +1 -0
  82. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-fixture-dataset.json +1 -0
  83. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-fixture-scores.json +1 -0
  84. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-manifest-missing-result-format.json +1 -0
  85. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-result-score-profile.json +1 -0
  86. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-result-valid-manifest.json +1 -0
  87. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-artifact-rank.json +1 -0
  88. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-call-count.json +1 -0
  89. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-completed-size.json +1 -0
  90. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-event-over-limit.json +1 -0
  91. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-final-call.json +1 -0
  92. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-first-call.json +1 -0
  93. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-and-missing-event-format.json +1 -0
  94. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-missing-manifest-format.json +1 -0
  95. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-nonstring-event-format.json +1 -0
  96. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-nonstring-result-format.json +1 -0
  97. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-id.json +1 -0
  98. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-no-end-room.json +1 -0
  99. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-no-pinned-dataset.json +1 -0
  100. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-nonfinal-terminal.json +1 -0
  101. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-retry-position.json +1 -0
  102. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-sibling.json +1 -0
  103. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-size.json +1 -0
  104. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-unused-sibling.json +1 -0
  105. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-depth.json +1 -0
  106. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-duplicate.json +1 -0
  107. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-float.json +1 -0
  108. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-nonfinite.json +1 -0
  109. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-surrogate.json +1 -0
  110. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-unsafe.json +1 -0
  111. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-utf8.json +1 -0
  112. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-known-subtotal-overflow.json +1 -0
  113. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-field-future-result.json +1 -0
  114. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-future.json +1 -0
  115. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-malformed.json +1 -0
  116. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-missing-format.json +1 -0
  117. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-semantics-future-result.json +1 -0
  118. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-unknown-string.json +1 -0
  119. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-artifact.json +1 -0
  120. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-coverage.json +1 -0
  121. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-manifest-format-future-profile.json +1 -0
  122. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-result-format-future-profile.json +1 -0
  123. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-path-traversal.json +1 -0
  124. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-prefix-collision.json +1 -0
  125. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-profile.json +1 -0
  126. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-blank.json +1 -0
  127. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-crlf.json +1 -0
  128. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-digest.json +1 -0
  129. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-no-lf.json +1 -0
  130. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-root.json +1 -0
  131. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-whitespace.json +1 -0
  132. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-registration.json +1 -0
  133. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-resources.json +1 -0
  134. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-result-unknown-field.json +1 -0
  135. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-retry-forward.json +1 -0
  136. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-retry-self.json +1 -0
  137. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-score-binding.json +1 -0
  138. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-second-score-role.json +1 -0
  139. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-terminal-reason.json +1 -0
  140. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-artifact-unavailable.json +1 -0
  141. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-call.json +1 -0
  142. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-event-exact-limit.json +1 -0
  143. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-multiple-pinned-dataset-copies.json +1 -0
  144. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-open-failed.json +1 -0
  145. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-terminal.json +1 -0
  146. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-artifacts-unicode.json +1 -0
  147. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-budget-unknown-total.json +1 -0
  148. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-empty-failure.json +1 -0
  149. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-fixture-exact.json +1 -0
  150. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-fixture-null-failure.json +1 -0
  151. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-multiple-pinned-dataset-copies.json +1 -0
  152. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-null-total-safe-subtotal.json +1 -0
  153. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-opaque-score.json +1 -0
  154. tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-retry.json +1 -0
  155. tallylock-0.1.0a1/src/tallylock/data/conformance/index.json +1 -0
  156. tallylock-0.1.0a1/src/tallylock/data/conformance/trees.json +1 -0
  157. tallylock-0.1.0a1/src/tallylock/data/examples/basic/README.md +19 -0
  158. tallylock-0.1.0a1/src/tallylock/data/examples/basic/manifest.json +17 -0
  159. tallylock-0.1.0a1/src/tallylock/data/examples/basic/outputs/metrics.json +1 -0
  160. tallylock-0.1.0a1/src/tallylock/data/examples/basic/outputs/run-log.txt +2 -0
  161. tallylock-0.1.0a1/src/tallylock/data/schemas/protocol-v1.json +166 -0
  162. tallylock-0.1.0a1/src/tallylock/doctor.py +91 -0
  163. tallylock-0.1.0a1/src/tallylock/errors.py +12 -0
  164. tallylock-0.1.0a1/src/tallylock/evidence.py +305 -0
  165. tallylock-0.1.0a1/src/tallylock/filesystem.py +720 -0
  166. tallylock-0.1.0a1/src/tallylock/fixture.py +54 -0
  167. tallylock-0.1.0a1/src/tallylock/ledger.py +494 -0
  168. tallylock-0.1.0a1/src/tallylock/merkle.py +106 -0
  169. tallylock-0.1.0a1/src/tallylock/paths.py +51 -0
  170. tallylock-0.1.0a1/src/tallylock/records.py +228 -0
  171. tallylock-0.1.0a1/src/tallylock/render.py +176 -0
  172. tallylock-0.1.0a1/src/tallylock/schema.py +331 -0
  173. tallylock-0.1.0a1/src/tallylock/scoring.py +72 -0
  174. tallylock-0.1.0a1/src/tallylock/store.py +493 -0
  175. tallylock-0.1.0a1/src/tallylock/tally.py +192 -0
  176. tallylock-0.1.0a1/src/tallylock/timestamping.py +370 -0
  177. tallylock-0.1.0a1/src/tallylock/transport.py +114 -0
  178. tallylock-0.1.0a1/src/tallylock/verify.py +470 -0
  179. tallylock-0.1.0a1/src/tallylock.egg-info/PKG-INFO +89 -0
  180. tallylock-0.1.0a1/src/tallylock.egg-info/SOURCES.txt +225 -0
  181. tallylock-0.1.0a1/src/tallylock.egg-info/dependency_links.txt +1 -0
  182. tallylock-0.1.0a1/src/tallylock.egg-info/entry_points.txt +2 -0
  183. tallylock-0.1.0a1/src/tallylock.egg-info/requires.txt +8 -0
  184. tallylock-0.1.0a1/src/tallylock.egg-info/top_level.txt +1 -0
  185. tallylock-0.1.0a1/tests/fixtures/contracts/artifact-paths.json +6 -0
  186. tallylock-0.1.0a1/tests/fixtures/contracts/chain.json +20 -0
  187. tallylock-0.1.0a1/tests/fixtures/contracts/trace-manifest.json +17 -0
  188. tallylock-0.1.0a1/tests/fixtures/ots/README.md +13 -0
  189. tallylock-0.1.0a1/tests/fixtures/ots/calendar-depth69.json +56 -0
  190. tallylock-0.1.0a1/tests/fixtures/ots/historical-header.hex +1 -0
  191. tallylock-0.1.0a1/tests/reference_corpus_author.py +502 -0
  192. tallylock-0.1.0a1/tests/test_anchors.py +286 -0
  193. tallylock-0.1.0a1/tests/test_canonical.py +70 -0
  194. tallylock-0.1.0a1/tests/test_chain.py +135 -0
  195. tallylock-0.1.0a1/tests/test_cli.py +588 -0
  196. tallylock-0.1.0a1/tests/test_cli_adversarial.py +159 -0
  197. tallylock-0.1.0a1/tests/test_cli_modes.py +353 -0
  198. tallylock-0.1.0a1/tests/test_cli_tally.py +58 -0
  199. tallylock-0.1.0a1/tests/test_conformance.py +169 -0
  200. tallylock-0.1.0a1/tests/test_crash_recovery.py +113 -0
  201. tallylock-0.1.0a1/tests/test_evidence.py +398 -0
  202. tallylock-0.1.0a1/tests/test_filesystem.py +800 -0
  203. tallylock-0.1.0a1/tests/test_filesystem_adversarial.py +232 -0
  204. tallylock-0.1.0a1/tests/test_fixture.py +55 -0
  205. tallylock-0.1.0a1/tests/test_http.py +284 -0
  206. tallylock-0.1.0a1/tests/test_http_adversarial.py +42 -0
  207. tallylock-0.1.0a1/tests/test_ledger.py +473 -0
  208. tallylock-0.1.0a1/tests/test_live_ots_interop.py +79 -0
  209. tallylock-0.1.0a1/tests/test_merkle.py +81 -0
  210. tallylock-0.1.0a1/tests/test_records.py +295 -0
  211. tallylock-0.1.0a1/tests/test_records_adversarial.py +105 -0
  212. tallylock-0.1.0a1/tests/test_recovery_adversarial.py +131 -0
  213. tallylock-0.1.0a1/tests/test_reference_adversarial.py +147 -0
  214. tallylock-0.1.0a1/tests/test_reference_verify.py +110 -0
  215. tallylock-0.1.0a1/tests/test_resources.py +34 -0
  216. tallylock-0.1.0a1/tests/test_schema.py +703 -0
  217. tallylock-0.1.0a1/tests/test_scoring.py +177 -0
  218. tallylock-0.1.0a1/tests/test_store.py +582 -0
  219. tallylock-0.1.0a1/tests/test_store_adversarial.py +84 -0
  220. tallylock-0.1.0a1/tests/test_tally.py +225 -0
  221. tallylock-0.1.0a1/tests/test_timestamping.py +505 -0
  222. tallylock-0.1.0a1/tests/test_transport.py +148 -0
  223. tallylock-0.1.0a1/tests/test_verify.py +522 -0
  224. tallylock-0.1.0a1/tests/test_verify_adversarial.py +149 -0
  225. tallylock-0.1.0a1/tools/check_distribution.py +102 -0
  226. tallylock-0.1.0a1/tools/check_install.py +213 -0
  227. tallylock-0.1.0a1/tools/reference_verify.py +583 -0
@@ -0,0 +1,88 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request, workflow_dispatch]
4
+
5
+ permissions:
6
+ contents: read
7
+
8
+ concurrency:
9
+ group: ci-${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ test-and-distribute:
14
+ runs-on: ubuntu-24.04
15
+ timeout-minutes: 20
16
+ strategy:
17
+ fail-fast: false
18
+ max-parallel: 2
19
+ matrix:
20
+ python-version: ['3.11', '3.12', '3.13']
21
+ env:
22
+ PIP_NO_INPUT: '1'
23
+ PIP_DISABLE_PIP_VERSION_CHECK: '1'
24
+ PIP_DEFAULT_TIMEOUT: '30'
25
+ PIP_RETRIES: '2'
26
+ steps:
27
+ - name: Check out source
28
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
29
+ with:
30
+ persist-credentials: false
31
+
32
+ - name: Set up Python
33
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
34
+ with:
35
+ python-version: ${{ matrix.python-version }}
36
+
37
+ - name: Install contributor dependencies
38
+ shell: bash
39
+ run: |
40
+ for attempt in 1 2 3; do
41
+ if python -m pip install 'setuptools>=77' wheel '.[dev]'; then
42
+ break
43
+ fi
44
+ if (( attempt == 3 )); then
45
+ exit 1
46
+ fi
47
+ sleep "$(( attempt * 5 ))"
48
+ done
49
+ python -m pip check
50
+
51
+ - name: Run full test suite
52
+ run: python -m pytest
53
+
54
+ - name: Audit and check clean installs
55
+ shell: bash
56
+ run: |
57
+ set -euo pipefail
58
+ dist_dir="$(mktemp -d "$RUNNER_TEMP/tallylock-dist.XXXXXX")"
59
+ wheel_env="$(mktemp -d "$RUNNER_TEMP/tallylock-wheel.XXXXXX")"
60
+ source_env="$(mktemp -d "$RUNNER_TEMP/tallylock-source.XXXXXX")"
61
+ expected_version="$(python -c 'import tomllib; from pathlib import Path; print(tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"])')"
62
+
63
+ pip_install() {
64
+ local python_bin="$1"
65
+ shift
66
+ for attempt in 1 2 3; do
67
+ if "$python_bin" -m pip install "$@"; then
68
+ return 0
69
+ fi
70
+ if (( attempt == 3 )); then
71
+ return 1
72
+ fi
73
+ sleep "$(( attempt * 5 ))"
74
+ done
75
+ }
76
+
77
+ python -m build --no-isolation --outdir "$dist_dir" .
78
+ python tools/check_distribution.py --dist "$dist_dir" --source-root .
79
+
80
+ python -m venv "$wheel_env"
81
+ pip_install "$wheel_env/bin/python" "$dist_dir"/*.whl
82
+ "$wheel_env/bin/python" -m pip check
83
+ python tools/check_install.py --python "$wheel_env/bin/python" --expected-version "$expected_version"
84
+
85
+ python -m venv "$source_env"
86
+ pip_install "$source_env/bin/python" "$dist_dir"/*.tar.gz
87
+ "$source_env/bin/python" -m pip check
88
+ python tools/check_install.py --python "$source_env/bin/python" --expected-version "$expected_version"
@@ -0,0 +1,54 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions: {}
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-24.04
13
+ timeout-minutes: 15
14
+ permissions:
15
+ contents: read
16
+ steps:
17
+ - name: Check out source
18
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19
+ with:
20
+ persist-credentials: false
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
24
+ with:
25
+ python-version: '3.12'
26
+
27
+ - name: Build distributions
28
+ run: |
29
+ python -m pip install "setuptools>=77" wheel "build>=1,<2"
30
+ python -m build --no-isolation
31
+
32
+ - name: Upload distributions
33
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+ if-no-files-found: error
38
+
39
+ publish:
40
+ needs: build
41
+ runs-on: ubuntu-24.04
42
+ timeout-minutes: 10
43
+ environment: pypi
44
+ permissions:
45
+ id-token: write
46
+ steps:
47
+ - name: Download distributions
48
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
49
+ with:
50
+ name: dist
51
+ path: dist/
52
+
53
+ - name: Publish to PyPI with trusted publishing
54
+ uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,21 @@
1
+ include LICENSE NOTICE README.md RUNBOOK.md PLAN.md pyproject.toml
2
+
3
+ # Public source inputs needed to rebuild, test, and audit an sdist.
4
+ graft src/tallylock
5
+ graft tests
6
+ graft docs
7
+ graft .github
8
+ graft examples/basic
9
+ graft conformance
10
+ graft tools
11
+
12
+ # Local planning, worker state, and generated files are never source inputs.
13
+ prune .git
14
+ prune .planning
15
+ prune .superpowers
16
+ prune .worker
17
+ prune .venv
18
+ prune build
19
+ prune dist
20
+ prune .pytest_cache
21
+ global-exclude *.pyc *.pyo .DS_Store
@@ -0,0 +1,7 @@
1
+ TallyLock
2
+ Copyright 2026 Christopher Ayers
3
+ Developed by TriplePass Labs.
4
+
5
+ TallyLock is licensed under Apache-2.0. Runtime dependencies are separate
6
+ projects and retain their own licenses. Their observed versions, metadata,
7
+ license files, and project links are listed in docs/DEPENDENCIES.md.
@@ -0,0 +1,89 @@
1
+ Metadata-Version: 2.4
2
+ Name: tallylock
3
+ Version: 0.1.0a1
4
+ Summary: Standalone evaluation receipts with independently checkable artifact and timestamp evidence
5
+ Author: Christopher Ayers
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Repository, https://github.com/TriplePassLabs/tallylock
8
+ Requires-Python: <3.14,>=3.11
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Requires-Dist: rfc8785==0.1.4
13
+ Requires-Dist: opentimestamps==0.5.0
14
+ Requires-Dist: python-bitcoinlib==0.12.2
15
+ Requires-Dist: jsonschema==4.26.0
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest<10,>=8; extra == "dev"
18
+ Requires-Dist: build<2,>=1; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # TallyLock
22
+
23
+ TallyLock was named Prove until 2026-11-07. The command is `tallylock` and the package is `tallylock`. Protocol v1 wire identifiers keep their original `prove.` prefix (for example `prove.manifest.v1`), and receipts keep their `.prove/` state directory, so existing receipt IDs and anchored timestamps stay valid.
24
+
25
+ TallyLock freezes evaluation plans and ordinary output files into standalone receipts. Its Python CLI verifies byte integrity offline and separates that evidence from reported scores, model identity and execution claims. Developed by [TriplePass Labs](https://github.com/TriplePassLabs). Created and maintained by [Christopher Ayers](https://github.com/BrianBoitano).
26
+
27
+ [Lab website](https://triplepasslabs.com) · [GitHub organization](https://github.com/TriplePassLabs) · [Founder profile](https://github.com/BrianBoitano)
28
+
29
+ It binds an evaluation plan, recorded artifacts and reported results to commitments with optional OpenTimestamps evidence. Verification distinguishes artifact integrity from claims about execution, model identity, timing and scientific validity.
30
+
31
+ Version `0.1.0a1` is an unreleased implementation candidate for Linux with Python 3.11 through 3.13. Use a supported interpreter and install the reviewed wheel in its own environment. The example below selects Python 3.12; substitute your supported interpreter when needed.
32
+
33
+ On Ubuntu or Debian, that interpreter needs its matching venv package before environment creation. Ubuntu 24.04 users selecting Python 3.12 need `python3.12-venv`. The [offline quickstart](docs/QUICKSTART.md) gives the prerequisite and an optional fallback when `uv` is already installed. See the [Ubuntu Python setup guide](https://ubuntu.com/developers/docs/howto/python-setup/) and [package record](https://packages.ubuntu.com/noble/python3.12-venv).
34
+
35
+ ```sh
36
+ python3.12 -m venv .venv-tallylock
37
+ . .venv-tallylock/bin/activate
38
+ python -m pip install /absolute/path/to/tallylock-0.1.0a1-py3-none-any.whl
39
+ tallylock --version
40
+ ```
41
+
42
+ From a reviewed source checkout, `python -m pip install .` works in the same environment. Installation may fetch dependencies. No unpublished PyPI release is assumed.
43
+
44
+ Future install path (after the first PyPI release): `pipx install tallylock`. It does not work yet, so use the reviewed wheel above for now. Distribution acceptance and release status are recorded in [the readiness audit](docs/READINESS.md).
45
+
46
+ The [offline quickstart](docs/QUICKSTART.md) uses only the installed CLI, a fresh manifest and an ordinary output directory. It needs no model, provider account, research checkout or hosted service. `python -m tallylock` can replace `tallylock` in every command.
47
+
48
+ ```sh
49
+ tallylock init --out manifest.json --name "My evaluation"
50
+ tallylock pre-register manifest.json --receipt receipt
51
+ mkdir outputs
52
+ printf 'ordinary external output\n' > outputs/result.txt
53
+ tallylock seal receipt --artifacts outputs
54
+ tallylock verify receipt
55
+ ```
56
+
57
+ Edit the manifest before preregistration. Run your external evaluation program yourself and pass its output directory to `seal`. TallyLock never launches a model or executes a scorer named in metadata. See [generic integration](docs/INTEGRATION.md) for explicit score/trace options, bounded reports and recovery.
58
+
59
+ Anchoring is explicit: `tallylock anchor receipt`, then `tallylock upgrade receipt` as calendars gain attestations. Submission and pending proofs are not completed anchoring. Plain `tallylock verify receipt` checks integrity and reports the timestamp as not checked, exiting 0 when integrity passes. With `--chain-cache FILE` it also runs the anchored check. `--policy anchored` is the strict form: it requires qualifying Bitcoin attestations and an explicitly selected local chain cache, and exits 3 without them. Verification never contacts a node or calendar. Independently assess the cache's provenance and freshness.
60
+
61
+ Output is one JSON object per stdout line when piped and a short plain-language summary on a terminal. Force either with `--json` or `--human` (not both). `tallylock doctor [RECEIPT]` checks the installation and a receipt's timestamp state without writing or using the network. Statuses are 0 for the requested action/check, 2 invalid input, 3 insufficient evidence, 4 unsupported evidence, 5 operational failure and 130 interruption. A returned timestamp action can still be pending or retry-wait. After optional anchoring fails, completed local state and IDs remain in the report. Resume with `anchor`/`upgrade` without the original outputs.
62
+
63
+ Static examples and canonical conformance assets ship under `tallylock/data/examples/basic` and `tallylock/data/conformance`, accessible through `importlib.resources`. Basic use requires no optional harness importer.
64
+
65
+ - [Project plan](PLAN.md): scope, protocol decisions, milestones and release gates.
66
+ - [Threat model](docs/THREAT_MODEL.md): attacks, defenses and remaining trust.
67
+ - [Acceptance tests](docs/ACCEPTANCE.md): tests required before implementation claims.
68
+ - [Sources and alternatives](docs/SOURCES.md): primary references and reuse decisions.
69
+ - [Review log](docs/reviews/REVIEW_LOG.md): critiques and their disposition.
70
+ - [Proposed flagship roadmap](docs/roadmap/README.md): setup choices, AI instructions and twenty staged features. Design for review; proposed commands are not implemented.
71
+
72
+ ## License
73
+
74
+ Licensed under [Apache-2.0](LICENSE). Copyright 2026 Christopher Ayers.
75
+
76
+ ## Record every run
77
+
78
+ ```sh
79
+ tallylock run --repeat 5 -- python eval.py --seed {seed}
80
+ tallylock score
81
+ ```
82
+
83
+ Every attempt is recorded, including failures. `score` reports the best result, the real score with its range, and a claim line others can check with `tallylock check`. See [the quickstart](docs/QUICKSTART.md#record-every-run-and-get-the-real-score) and [the method](docs/METHODS.md).
84
+
85
+ ## What a receipt means
86
+
87
+ A valid completed timestamp establishes that a commitment existed by a Bitcoin block. Artifact hashes reveal changes to committed bytes. Neither establishes that an evaluator ran honestly, used the claimed model, disclosed all attempts, or produced a scientifically sound result.
88
+
89
+ TallyLock works alongside evaluation harnesses. A preregistration ID alone establishes no independently witnessed chronology. External research experiments remain separate from the protocol's cryptographic checks.
@@ -0,0 +1,131 @@
1
+ # TallyLock project plan
2
+
3
+ Revision 5, 2026-11-06. Chris authorized implementation through a standalone CLI candidate ready for external research-session testing, with adversarial critique and documented feedback. Implementation begins from the reviewed plan. This revision replaces earlier approval holds for that scope.
4
+
5
+ ## Standalone product requirement
6
+
7
+ Chris clarified on 2026-11-06: TallyLock is an independent, general-purpose, easily installable CLI. Colony Zero and Ouroboros are external consumers used for acceptance testing. The shipped package, core manifest and receipt formats, generic workflow, verifier and quickstart must have no dependency on those repositories, their naming, internal paths, schemas, services or hardware. A clean user must be able to install a built wheel with pip or pipx and complete the documented generic example without a research-project checkout, private credentials or a TriplePass Labs service. Public PyPI publication remains a later release step; the candidate must be installable from its versioned wheel and source distribution now.
8
+
9
+ Generic manifests, artifact ingestion and data-only verification are the primary interfaces. Harness-specific import adapters are optional conveniences; they cannot be required by the core package or the primary installation path. Colony/Ouroboros integration belongs in external instructions and examples, never in project-specific core behavior. Keep the first public-facing quickstart domain-neutral. The testing handoff asks a separate research session to use the installed CLI as an ordinary external user and document friction, defects and missing general capabilities.
10
+
11
+ ## Goal and product decision
12
+
13
+ Make one real evaluation auditable without requiring its author to remain online or requiring trust in TriplePass Labs. Publish a portable receipt connecting a frozen plan, preserved execution artifacts and declared results to independent timestamp evidence. A verifier must explain exactly what it checked and what remains an assertion.
14
+
15
+ The narrow product is an evidence layer for existing harnesses. The first milestone does not include a production inference runner, generic agent framework, dashboard, transparency service, signatures, trusted execution, custom Bitcoin consensus implementation, or paid evaluation sweep.
16
+
17
+ The useful distinction from hashing a log is the explicit binding of plan, artifacts, ordered records, final outcome and verification policy, with interoperable timestamp proofs and honest evidence reporting. Novelty and market demand are hypotheses, not established facts. See [alternatives](docs/SOURCES.md).
18
+
19
+ ## Problems in the original plan and decisions
20
+
21
+ | Original weakness | Revised decision |
22
+ |---|---|
23
+ | “Proof that an evaluation ran” exceeds timestamp guarantees | Evidence dimensions replace an unqualified verified badge |
24
+ | Timestamping a plan can happen after private rehearsal | Never infer no prior runs or honest chronology from a receipt |
25
+ | A new runner makes the first build larger and less adoptable | Ingest a documented fixture format first; adapt an existing harness later |
26
+ | “Offline” hides the source of Bitcoin trust | Verifier controls a previously validated chain snapshot; current freshness is reported separately |
27
+ | A sealed score may be mathematically wrong | Integrity and score recomputation are separate checks; one deterministic fixture scorer is independently reproducible |
28
+ | “Preregistered” conflates anchors with an observed start | Report plan anchoring and operator-declared launch policy separately |
29
+ | Generic parity claims mix tokens, money and compute | Separate token, measured-resource and API-cost comparisons |
30
+ | 100 runs can become a volume vanity metric | Count unique scheduled, completed executions; expose missing attempts and uncertainty |
31
+ | Three downloads are not adoption | Require independently published, independently verified real receipts and usability evidence |
32
+
33
+ ## Evidence contract
34
+
35
+ An offline report contains separate fields for schema support, artifact integrity, Merkle membership or full-tree verification, plan and result timestamp status, chain evidence source and cached tip, confirmation policy, declared execution outcome, model evidence, score recomputation, issuer identity and launch-policy assertions. The report never equates an operator declaration with an independent observation. Issuer identity is `unverified` in v0.1, even when an author name appears in metadata. Model evidence is one of `self_declared`, `provider_metadata_recorded`, or `weight_digest_recorded`; none means executed-model attestation.
36
+
37
+ Verification has two scopes. `full` checks every committed artifact and recomputes the complete ordered tree. `inclusion` checks one explicitly identified record against a committed root and tree size; it cannot claim complete artifacts or complete execution history. Neither scope establishes that omitted, unrecorded calls never happened.
38
+
39
+ A valid record may describe failed, aborted or budget-exceeded work. Those are evaluation outcomes, not necessarily invalid receipts. Missing required artifacts or broken commitments are invalid evidence. Unsupported versions, absent chain evidence and pending anchors must not look like successful anchored verification.
40
+
41
+ Proposed exit codes: 0 means all checks required by the selected scope and policy passed; 2 malformed or invalid evidence; 3 pending or insufficient evidence; 4 unsupported version or algorithm; 5 operational failure. Human and JSON output both name scope and remaining assertions. The default verification policy requires both completed anchors and all artifacts; an explicit `--integrity-only` policy can pass hashes while plainly reporting timestamps unchecked.
42
+
43
+ ## Minimal receipt format
44
+
45
+ Use a plain directory in the first version. No archive extraction, remote artifact resolution or plugin execution during verification.
46
+
47
+ | File | Role |
48
+ |---|---|
49
+ | `manifest.json` | Frozen plan core, canonical UTF-8 bytes |
50
+ | `result.json` | Final result core binding the manifest digest and artifact inventory |
51
+ | `artifacts/` | Exact recorded bytes, including original harness output and normalized fixture records |
52
+ | `proofs/manifest.ots` and `proofs/result.ots` | Detached timestamp proofs for the exact canonical core files |
53
+
54
+ The core excludes mutable proof files, chain caches and verifier reports to avoid circular digests. Proof upgrades preserve core bytes and receipt identity. A registration ID is SHA-256 of canonical manifest bytes; the manifest includes a 128-bit random nonce to distinguish intentional repeated registrations. Fixed published test fixtures use an explicitly fixed nonce. A receipt ID is SHA-256 of canonical result bytes. Multiple result receipts may reference a registration. Each manifest predeclares its permitted attempt IDs, using unique lowercase ASCII identifiers matching `[a-z0-9][a-z0-9_-]{0,63}`, and expected sample coverage for each. Results must reference one such ID. The protocol cannot prove no other receipts or undeclared executions exist.
55
+
56
+ The manifest binds a protocol version, registration nonce, experiment description, task/split content digests, evaluation harness revision and effective configuration, prompts and generation settings, model evidence, scorer and analysis revisions, attempt and retry policies, resource ceilings, stopping rules, expected sample IDs, and declared execution policy. Fields unsupported by a provider are explicit unknowns. References alone are not substitutes for content digests. Expected sample IDs are explicit in v0.1. Private-inventory commitment and reveal verification is deferred to G5 and requires a separately versioned schema, exact domain-separated commitment preimage and reveal format, and mutation vectors before it can be claimed supported. A v0.1 receipt cannot claim verified secret-inventory membership.
57
+
58
+ The result binds the registration digest, attempt ID, final outcome, artifact inventory with SHA-256 and byte counts, tree algorithm and event count, ordered event root, resource ledger and reported score artifact. The inventory is a canonical JSON mapping sorted by relative path with digest, byte length, media type and role per entry. For v0.1 artifact paths are lowercase ASCII POSIX paths, with only letters, digits, dot, underscore, hyphen and slash; reject empty, dot and parent components, repeated slashes, duplicate paths and unlisted files beneath `artifacts/`. Completeness applies to that directory, not detached proofs. Fixed core/proof paths are protocol files; other root content must be rejected or explicitly designated non-normative local state by the schema. An inclusion proof does not imply the inventory is available. Any operator-reported start and end times are labeled as such. A finalization timestamp is never labeled as execution time.
59
+
60
+ Canonical JSON uses RFC 8785 with a deliberately narrower first-version profile: no duplicate keys, no non-finite numbers, no floats, no lone surrogate code points, and integers in the inclusive range -9007199254740991 through 9007199254740991. Counters and lengths must also be nonnegative. Represent decimal quantities as schema-constrained decimal strings with named units. Reject unknown normative fields or versions rather than silently ignoring semantics. Preserve raw artifacts byte-for-byte; canonicalization applies to protocol JSON, not arbitrary source logs. Pin a conforming implementation after its conformance vectors pass.
61
+
62
+ Use the RFC 9162 Merkle tree hash construction with SHA-256, leaf/internal-node domain separation and its defined split rule; do not duplicate odd leaves. Leaves are canonical normalized event objects. Each binds the registration digest, attempt ID, contiguous zero-based event index, event kind and relevant sample ID. The result commits tree size. For zero events use the specified empty-tree hash; only a failed, aborted or budget-exceeded attempt with an explicit reason can finalize empty. Validate inclusion index, tree size and exact proof consumption. [Construction reference](https://www.rfc-editor.org/rfc/rfc9162.html#section-2.1)
63
+
64
+ G1 begins by freezing a closed versioned schema table before implementation: `sample_start`, `call`, `sample_end`, and `attempt_end`; each records its event index and identifiers. That table must define required/optional fields, absent/null rules, identifier syntax and exact canonical leaf bytes, and cover every event type in fixed vectors. Unknown event fields fail. A call records status, visible input/output artifact references, token usage or unknown, and retry linkage to an earlier call in the same attempt. Artifact references use the inventory path grammar and resolve to a listed entry. A sample end records its terminal status. Every expected sample has one terminal status or the attempt declares incomplete coverage. The core checks that call/sample/attempt IDs, event ordering, artifact references and final counts agree. It cannot validate that an untrusted producer told the truth.
65
+
66
+ The score binding is an object naming exactly one inventory path with role `score`, its SHA-256 and byte length, a scoring-profile identifier and a declared aggregate as a rational numerator/denominator pair or an explicit unavailable state. Resolve the path and require all copied digest/size fields to match the inventory. Freeze score, resource and event schemas together at the start of G1; no independent implementation can rely on prose guesses about these fields. G1 also freezes outcome/coverage and policy/exit-code tables: completed evaluations require full declared coverage; failed, aborted and budget-exceeded attempts may declare incomplete coverage with explicit reasons. Valid receipts may describe unsuccessful evaluations. Test pending anchors under integrity-only policy, wrong fixture scores under recomputation policy, and unavailable artifacts under inclusion policy.
67
+
68
+ ## Timestamp and trust workflow
69
+
70
+ 1. `tallylock pre-register manifest.json`: validate, canonicalize to a new receipt directory and freeze core bytes atomically. With `--anchor ots`, request a timestamp after writing durable local state. A submitted proof is pending until completed and checked.
71
+ 2. An external evaluator runs. The first version includes a deterministic fixture producer for tests, not a general inference runner. A later harness integration may enforce waiting for a confirmed plan anchor locally. Its attestation remains an operator assertion unless independently witnessed.
72
+ 3. `tallylock seal RECEIPT --artifacts DIR --anchor ots`: snapshot immutable artifact copies, validate internal consistency and finalize a result core before network work. A failed anchor request cannot erase or change the local result. No overwrite of finalized core files; corrections create a new receipt referencing the superseded ID.
73
+ 4. `tallylock upgrade RECEIPT`: complete proofs using the pinned OpenTimestamps implementation, with bounded timeouts, backoff and concurrency. Recover interrupted work from local state; preserve prior proof bytes before atomic replacement. Never rewrite cores. Identical repeated commands must be safe.
74
+ 5. `tallylock verify RECEIPT --offline --chain-cache PATH`: perform only local reads. Default full verification requires completed proofs for both cores and independently obtained chain data. A separate `tallylock inspect` reports available evidence without asserting verification.
75
+
76
+ OpenTimestamps stamping and upgrading may contact public calendars; proof submission is not finality. Use upstream formats and verification operations, not invented timestamp cryptography. A proof request has a durable idempotency key based on its core digest. A retry may receive different valid proof bytes while the commitment stays identical. [Upstream workflow](https://github.com/opentimestamps/opentimestamps-client)
77
+
78
+ The first offline cache is explicitly local trust material, not part of the receipt. A separate `tallylock evidence export --bitcoin-rpc ...` command reads the verifier's own fully validated Bitcoin Core node and exports the required block headers, heights, block hashes, confirmation observations and observed tip into a versioned cache. RPC credentials come from a configuration file or cookie, never a CLI URL. Do not deploy a node as part of this project phase; first assess access to an existing independently validated source. If none exists, the real offline-anchor milestone remains blocked on evidence acquisition, not silently downgraded to explorer trust.
79
+
80
+ The exporter confirms the required blocks belong to the node's active chain and records its synchronization state. Its cache schema binds format version, creation time, tip hash/height, node validation/synchronization observations and required anchor headers with their hashes, heights and cached confirmations. Export captures the tip before and after reading all anchor data and retries the bounded snapshot operation if the chain view changes. Verification recomputes header hashes, matches anchor Merkle roots and checks the cache's height/hash mapping and confirmation arithmetic. Authenticity of the cache comes from the verifier's independent acquisition, not a self-asserted JSON field. An attacker who can replace that trust store can subvert the check. A receipt-provided cache is rejected as an implicit trust source. Only an explicitly supplied verifier-owned `--chain-cache` is used; no bundle-relative discovery is allowed. The software cannot determine who originally created an explicitly trusted cache. This validated-node-export design intentionally does not claim to validate cumulative work offline.
81
+
82
+ Default Bitcoin confirmation policy is six blocks including the anchor, recorded as a project policy rather than a guarantee of irreversibility. Cached confirmations are relative to the exported chain view. No timestamp or confirmation count establishes the current chain after disconnection. Live refresh can detect reorganizations later; offline output must retain the cached tip and provenance.
83
+
84
+ There is no cryptographic “ran after registration” verdict in v0.1. Future unpredictable task selection may constrain which task set could be finalized in advance, but seed grinding, leaked generators, rehearsals and operator control remain relevant. Witnesses, trusted execution and randomness beacons require separate threat models and are deferred.
85
+
86
+ ## Safe processing and persistence
87
+
88
+ Treat manifests, logs and proofs as hostile data. Never run harness/scorer code during ordinary verification. Score evidence is `recorded_only`, `recomputed_fixture`, or `not_available`; v0.1 recomputation uses only a built-in deterministic fixture scoring profile with exact per-sample rules, denominators, exclusion policy and rational aggregate arithmetic. The verifier never imports arbitrary scorer code from a receipt. Accept only regular files beneath the receipt root: reject symlinks, absolute paths, traversal, duplicate or case-colliding artifact paths and changed files during snapshot. No artifacts are fetched from embedded URLs. Limit metadata to 8 MiB per core, 1 MiB per event, 10 million events and 16 MiB per detached proof in the first parser policy; hash artifact data by streaming and make bounded policy overrides explicit. Limits are operational bounds, not wire-format promises. End-to-end score recomputation for other scorers is a separate explicitly sandboxed action and is outside v0.1.
89
+
90
+ Verification also treats concurrent filesystem mutation as hostile. Resolve files beneath an opened receipt-root descriptor without following symlinks; use no-follow descriptor-relative opens, require regular-file descriptor metadata, and compare device/inode/type/size and change metadata before and after streaming. Reject changes and any digest/byte-count mismatch. Apply equivalent handling to core and proof reads, not only artifact hashing. Fail closed on platforms without tested primitives. This is read-time race resistance, not a guarantee against an attacker controlling the operating system.
91
+
92
+ One writer per receipt directory, using exclusive lock creation with an explicit recovery procedure. Write temporary files, flush and atomically replace local state; refuse conflicting repeated inputs. Tests interrupt each persistence boundary. Proof pending, network failure and invalid data produce distinct machine-readable states. Online calendar work has one active request per receipt and capped retries; offline verification has no network fallback.
93
+
94
+ Do not mutate private logs to sanitize them after sealing. Before public export, choose a deliberate disclosure profile: public-reproducible includes all necessary permitted artifacts; commitment-only discloses hashes and optional later reveals while reporting unavailable evidence. Low-entropy private task material needs a random nonce in its commitment preimage; hold that nonce until reveal. No parallel unsalted digest of the same withheld plaintext may appear in an exported inventory or metadata, or the intended guessing protection is lost. The private-inventory/reveal profile is deferred and must test this boundary before G5. Never include credentials or personal data in fixture content. Changes in disclosure create distinct artifacts and receipts, not silent replacements.
95
+
96
+ ## Work packages and acceptance gates
97
+
98
+ | Gate | Deliverable | Verification |
99
+ |---|---|---|
100
+ | G0, this phase | Reviewed plan, threat model, test matrix and dedicated repo | Every blocking critique has a disposition; unresolved external prerequisites are explicit; Chris approves the first implementation scope |
101
+ | G1, receipt core | Freeze versioned manifest/result/event/score/resource schemas and vectors first; then deterministic fixture and local hash/tree verifier | Independent fixed vectors, mutation tests, score recomputation, hostile path/parser tests and interrupted-finalization recovery pass; no inference required |
102
+ | G2, timestamp round trip | Upstream OTS adapter, local evidence export and offline verification | Fresh plan anchors, fixture execution follows the local gate, separate result anchors; a clean disconnected verifier validates both against independently acquired cache; pending/invalid/untrusted cases fail honestly |
103
+ | G3, external-harness pilot | One pinned Inspect import adapter plus Colony Zero example | Original log bytes retained; mapping report accounts for every source record as mapped, preserved-unmapped or unsupported; unsupported semantics prevent strict normalized-execution claims; two unfamiliar people verify a pilot and explain the remaining trust |
104
+ | G4, release | Stable v1 protocol, clean PyPI install and compatibility corpus | External pilot has no blocking correctness/usability issues; install and quickstart succeed without development checkout; distribution name cleared; supported Python/OS matrix documented |
105
+ | G5, research deployments | Observatory and swarm report | Scientific and adoption gates below, approved model roster and budget, public downloadable evidence |
106
+
107
+ G1 does not claim Bitcoin anchoring. G2 must use a real anchor and a real independently prepared chain view; mocks establish only unit behavior. Historical fixtures cannot substitute for the fresh G2 experiment. No paid inference, new node deployment or production service changes occur in G0-G1. Timing depends on evidence access, review and Bitcoin confirmation, not a promised number of days.
108
+
109
+ Implementation modules should separate core data/hash/tree logic, read-only verification, local store/finalization, timestamp transport, chain-evidence export and CLI presentation. Verification must not import model-provider SDKs or call writer operations. Publish vectors before optimizing performance. The first supported runtime is Python 3.11-3.13 on Linux; qualify other platforms only after their atomic-write, path and locking behavior is tested. Third-party adapters and a pure-node-free chain verifier are outside the first implementation. G3 accepts only a pinned exported Inspect JSON representation, parsed as data without loading task code, resolving external paths, fetching attachments or activating plugins. Binary `.eval` ingestion is deferred until its parser boundary is separately reviewed.
110
+
111
+ ## Scientific gates
112
+
113
+ The observatory tracks evaluated service behavior, not unobservable weight changes. Freeze a core task panel and scorer; changing either starts a new comparable series. Keep a fixed public sentinel panel and separately version private holdouts with salted commitments and delayed reveals. Record disclosure times and stop using revealed holdouts as secret tests. A frozen open-weight reference runs through the evaluator/control path on each sweep, so changes in that control trigger an evaluator-drift investigation. Daily sentinel measurements are descriptive; weekly preregistered comparisons are confirmatory. Specify one primary endpoint per series, a smallest meaningful change, paired sampling units, replicate structure, power calculation, missing-data handling and multiple-comparison/continual-testing policy before calling a change “drift.” Repeated API calls to one prompt are not independent task samples. Track outages and missingness separately from accuracy, and account for repeated peeking. Choose and simulate the actual error-control procedure before G5, rather than treating repeated ordinary confidence intervals as sequential evidence. Run simulation/calibration against a fixed local fixture before funding live collection.
114
+
115
+ The 100-run target counts unique scheduled executions with complete result receipts and confirmed anchors, not proof upgrades, retries or duplicated views. An anchored published schedule enumerates intended run IDs and deadlines; publish terminal dispositions for each. This detects missing outcomes relative to that schedule, not secret off-schedule evaluations or a dishonest schedule author. Archive schedule revisions and periodically anchor their inventory. A signed/witnessed global transparency service is not implied.
116
+
117
+ Swarm studies have distinct token-budget, API-cost and controlled-resource tracks. Count routing, coordination, all members, retries, failures, judging and tool use consistently. Report unavailable hidden reasoning usage, tokenizer differences and training/amortization assumptions. A closed API track cannot claim strict compute parity. Controlled open-weight comparisons name hardware, precision, measured resource units and accounting boundaries. Include best single member, best-of-N and simple voting controls; pair tasks and repeat seeds where supported. Preregister superiority or noninferiority margins, multiplicity rules and stopping criteria. Negative and inconclusive results satisfy the research objective.
118
+
119
+ No arbitrary sample-size promise replaces a powered design. A report's headline scores must be independently recomputable from disclosed records or clearly labeled non-recomputable. Model-graded outcomes need pinned judge settings and calibration; changing judges creates a new analysis version. Hugging Face publication requires permission to redistribute the actual data, not only permission to run a benchmark.
120
+
121
+ ## Adoption and stop rules
122
+
123
+ Before expanding the platform, test whether an unfamiliar maintainer can wrap existing logs without rerunning a model. Pilot target: integration within one working day, active verification within 15 minutes after chain evidence is prepared, and correct interpretation of what the receipt does not prove. Record setup time, failed steps, provider/harness version and a short comprehension check. Bitcoin synchronization and anchoring wait are measured separately rather than hidden in a speed claim.
124
+
125
+ Three independent external adopters means three unaffiliated maintainers or researchers publishing their own real receipts; team-produced fixtures, forks and downloads do not count. This remains a project success metric after release, not a prerequisite that prevents shipping the tool needed for adoption. Outreach remains owner-authorized work, not automatic messaging. If pilots prefer signed logs or existing attestations and cannot identify useful incremental assurance, simplify or reposition before building the observatory. If independent chain preparation dominates usability, report it as a blocker and evaluate an explicitly different trust mode rather than marketing it as solved.
126
+
127
+ ## Costs and open decisions
128
+
129
+ This design phase uses existing tools at no new spend. Public calendars currently offer free submissions. Future API evaluations, hosting and any Bitcoin node storage/network costs require a separately costed roster and hard budget. The repository is TriplePassLabs/tallylock; Chris selected public visibility and Apache-2.0 on 2026-11-05, then moved TallyLock under the business organization. The PyPI distribution and CLI command names still need availability/conflict checks before release; TallyLock is a working product name. Do not reuse private project implementation merely because public receipts are available.
130
+
131
+ G0 can finish with an explicit chain-evidence acquisition prerequisite; G2 cannot pass without satisfying it. G1 still requires Chris's approval after the adversarial review, as requested. No implementation is authorized by the presence of this plan.