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.
- tallylock-0.1.0a1/.github/workflows/ci.yml +88 -0
- tallylock-0.1.0a1/.github/workflows/release.yml +54 -0
- tallylock-0.1.0a1/LICENSE +202 -0
- tallylock-0.1.0a1/MANIFEST.in +21 -0
- tallylock-0.1.0a1/NOTICE +7 -0
- tallylock-0.1.0a1/PKG-INFO +89 -0
- tallylock-0.1.0a1/PLAN.md +131 -0
- tallylock-0.1.0a1/README.md +69 -0
- tallylock-0.1.0a1/RUNBOOK.md +23 -0
- tallylock-0.1.0a1/conformance/README.md +25 -0
- tallylock-0.1.0a1/docs/ACCEPTANCE.md +45 -0
- tallylock-0.1.0a1/docs/DEPENDENCIES.md +20 -0
- tallylock-0.1.0a1/docs/IMPLEMENTATION_PLAN.md +283 -0
- tallylock-0.1.0a1/docs/INTEGRATION.md +72 -0
- tallylock-0.1.0a1/docs/METHODS.md +40 -0
- tallylock-0.1.0a1/docs/PROTOCOL.md +131 -0
- tallylock-0.1.0a1/docs/QUICKSTART.md +111 -0
- tallylock-0.1.0a1/docs/READINESS.md +48 -0
- tallylock-0.1.0a1/docs/SOURCES.md +23 -0
- tallylock-0.1.0a1/docs/TESTING_HANDOFF.md +39 -0
- tallylock-0.1.0a1/docs/THREAT_MODEL.md +30 -0
- tallylock-0.1.0a1/docs/reviews/COLONY_ZERO_FEEDBACK.md +18 -0
- tallylock-0.1.0a1/docs/reviews/FINAL_REVIEW.md +39 -0
- tallylock-0.1.0a1/docs/reviews/IMPLEMENTATION_REVIEW.md +147 -0
- tallylock-0.1.0a1/docs/reviews/OUROBOROS_FEEDBACK.md +18 -0
- tallylock-0.1.0a1/docs/reviews/REVIEW_LOG.md +61 -0
- tallylock-0.1.0a1/docs/roadmap/AGENT_GUIDE.md +77 -0
- tallylock-0.1.0a1/docs/roadmap/DESIGN.md +214 -0
- tallylock-0.1.0a1/docs/roadmap/FEATURES.json +230 -0
- tallylock-0.1.0a1/docs/roadmap/NOVICE_OVERVIEW.md +42 -0
- tallylock-0.1.0a1/docs/roadmap/PHASE1_RECUT.md +89 -0
- tallylock-0.1.0a1/docs/roadmap/README.md +51 -0
- tallylock-0.1.0a1/docs/roadmap/ROADMAP.md +98 -0
- tallylock-0.1.0a1/docs/roadmap/WEBSITE_PLAN.md +51 -0
- tallylock-0.1.0a1/docs/testing-feedback.schema.json +95 -0
- tallylock-0.1.0a1/docs/testing-feedback.template.json +19 -0
- tallylock-0.1.0a1/examples/basic/README.md +19 -0
- tallylock-0.1.0a1/examples/basic/manifest.json +17 -0
- tallylock-0.1.0a1/examples/basic/outputs/metrics.json +1 -0
- tallylock-0.1.0a1/examples/basic/outputs/run-log.txt +2 -0
- tallylock-0.1.0a1/pyproject.toml +35 -0
- tallylock-0.1.0a1/setup.cfg +4 -0
- tallylock-0.1.0a1/src/tallylock/__init__.py +3 -0
- tallylock-0.1.0a1/src/tallylock/__main__.py +4 -0
- tallylock-0.1.0a1/src/tallylock/_http.py +223 -0
- tallylock-0.1.0a1/src/tallylock/anchors.py +193 -0
- tallylock-0.1.0a1/src/tallylock/canonical.py +122 -0
- tallylock-0.1.0a1/src/tallylock/chain.py +71 -0
- tallylock-0.1.0a1/src/tallylock/cli.py +624 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/README.md +66 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/canonical.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-artifact-bytes.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-attempt.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-base64.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-bool-counter.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-budget.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-call-after-end.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-call-before-start.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-completed-null-score.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-completed-reason.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-duplicate.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-float.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-noncanonical.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-core-unsafe.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-cross-sample-retry.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-dangling-call.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-duplicate-call.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-duplicate-start.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-early-terminal.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-envelope-field.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-event-binding.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-event-future.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-extra-artifact.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-false-math-all-hashes.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-false-math.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-dataset-pin.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-denominator.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-duplicate.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-observed-type.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-fixture-unknown-field.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-event-kind.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-fixture-dataset.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-fixture-scores.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-manifest-missing-result-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-result-score-profile.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-future-result-valid-manifest.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-artifact-rank.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-call-count.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-completed-size.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-event-over-limit.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-final-call.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-first-call.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-and-missing-event-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-missing-manifest-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-nonstring-event-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-future-nonstring-result-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-id.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-no-end-room.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-no-pinned-dataset.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-nonfinal-terminal.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-retry-position.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-sibling.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-size.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-inclusion-unused-sibling.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-depth.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-duplicate.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-float.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-nonfinite.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-surrogate.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-unsafe.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-json-utf8.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-known-subtotal-overflow.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-field-future-result.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-future.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-malformed.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-missing-format.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-semantics-future-result.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-manifest-unknown-string.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-artifact.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-coverage.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-manifest-format-future-profile.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-missing-result-format-future-profile.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-path-traversal.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-prefix-collision.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-profile.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-blank.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-crlf.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-digest.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-no-lf.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-root.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-record-whitespace.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-registration.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-resources.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-result-unknown-field.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-retry-forward.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-retry-self.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-score-binding.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-second-score-role.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/bad-terminal-reason.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-artifact-unavailable.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-call.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-event-exact-limit.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-multiple-pinned-dataset-copies.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-open-failed.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/inclusion-terminal.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-artifacts-unicode.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-budget-unknown-total.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-empty-failure.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-fixture-exact.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-fixture-null-failure.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-multiple-pinned-dataset-copies.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-null-total-safe-subtotal.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-opaque-score.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/cases/run-retry.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/index.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/conformance/trees.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/examples/basic/README.md +19 -0
- tallylock-0.1.0a1/src/tallylock/data/examples/basic/manifest.json +17 -0
- tallylock-0.1.0a1/src/tallylock/data/examples/basic/outputs/metrics.json +1 -0
- tallylock-0.1.0a1/src/tallylock/data/examples/basic/outputs/run-log.txt +2 -0
- tallylock-0.1.0a1/src/tallylock/data/schemas/protocol-v1.json +166 -0
- tallylock-0.1.0a1/src/tallylock/doctor.py +91 -0
- tallylock-0.1.0a1/src/tallylock/errors.py +12 -0
- tallylock-0.1.0a1/src/tallylock/evidence.py +305 -0
- tallylock-0.1.0a1/src/tallylock/filesystem.py +720 -0
- tallylock-0.1.0a1/src/tallylock/fixture.py +54 -0
- tallylock-0.1.0a1/src/tallylock/ledger.py +494 -0
- tallylock-0.1.0a1/src/tallylock/merkle.py +106 -0
- tallylock-0.1.0a1/src/tallylock/paths.py +51 -0
- tallylock-0.1.0a1/src/tallylock/records.py +228 -0
- tallylock-0.1.0a1/src/tallylock/render.py +176 -0
- tallylock-0.1.0a1/src/tallylock/schema.py +331 -0
- tallylock-0.1.0a1/src/tallylock/scoring.py +72 -0
- tallylock-0.1.0a1/src/tallylock/store.py +493 -0
- tallylock-0.1.0a1/src/tallylock/tally.py +192 -0
- tallylock-0.1.0a1/src/tallylock/timestamping.py +370 -0
- tallylock-0.1.0a1/src/tallylock/transport.py +114 -0
- tallylock-0.1.0a1/src/tallylock/verify.py +470 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/PKG-INFO +89 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/SOURCES.txt +225 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/dependency_links.txt +1 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/entry_points.txt +2 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/requires.txt +8 -0
- tallylock-0.1.0a1/src/tallylock.egg-info/top_level.txt +1 -0
- tallylock-0.1.0a1/tests/fixtures/contracts/artifact-paths.json +6 -0
- tallylock-0.1.0a1/tests/fixtures/contracts/chain.json +20 -0
- tallylock-0.1.0a1/tests/fixtures/contracts/trace-manifest.json +17 -0
- tallylock-0.1.0a1/tests/fixtures/ots/README.md +13 -0
- tallylock-0.1.0a1/tests/fixtures/ots/calendar-depth69.json +56 -0
- tallylock-0.1.0a1/tests/fixtures/ots/historical-header.hex +1 -0
- tallylock-0.1.0a1/tests/reference_corpus_author.py +502 -0
- tallylock-0.1.0a1/tests/test_anchors.py +286 -0
- tallylock-0.1.0a1/tests/test_canonical.py +70 -0
- tallylock-0.1.0a1/tests/test_chain.py +135 -0
- tallylock-0.1.0a1/tests/test_cli.py +588 -0
- tallylock-0.1.0a1/tests/test_cli_adversarial.py +159 -0
- tallylock-0.1.0a1/tests/test_cli_modes.py +353 -0
- tallylock-0.1.0a1/tests/test_cli_tally.py +58 -0
- tallylock-0.1.0a1/tests/test_conformance.py +169 -0
- tallylock-0.1.0a1/tests/test_crash_recovery.py +113 -0
- tallylock-0.1.0a1/tests/test_evidence.py +398 -0
- tallylock-0.1.0a1/tests/test_filesystem.py +800 -0
- tallylock-0.1.0a1/tests/test_filesystem_adversarial.py +232 -0
- tallylock-0.1.0a1/tests/test_fixture.py +55 -0
- tallylock-0.1.0a1/tests/test_http.py +284 -0
- tallylock-0.1.0a1/tests/test_http_adversarial.py +42 -0
- tallylock-0.1.0a1/tests/test_ledger.py +473 -0
- tallylock-0.1.0a1/tests/test_live_ots_interop.py +79 -0
- tallylock-0.1.0a1/tests/test_merkle.py +81 -0
- tallylock-0.1.0a1/tests/test_records.py +295 -0
- tallylock-0.1.0a1/tests/test_records_adversarial.py +105 -0
- tallylock-0.1.0a1/tests/test_recovery_adversarial.py +131 -0
- tallylock-0.1.0a1/tests/test_reference_adversarial.py +147 -0
- tallylock-0.1.0a1/tests/test_reference_verify.py +110 -0
- tallylock-0.1.0a1/tests/test_resources.py +34 -0
- tallylock-0.1.0a1/tests/test_schema.py +703 -0
- tallylock-0.1.0a1/tests/test_scoring.py +177 -0
- tallylock-0.1.0a1/tests/test_store.py +582 -0
- tallylock-0.1.0a1/tests/test_store_adversarial.py +84 -0
- tallylock-0.1.0a1/tests/test_tally.py +225 -0
- tallylock-0.1.0a1/tests/test_timestamping.py +505 -0
- tallylock-0.1.0a1/tests/test_transport.py +148 -0
- tallylock-0.1.0a1/tests/test_verify.py +522 -0
- tallylock-0.1.0a1/tests/test_verify_adversarial.py +149 -0
- tallylock-0.1.0a1/tools/check_distribution.py +102 -0
- tallylock-0.1.0a1/tools/check_install.py +213 -0
- 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
|
tallylock-0.1.0a1/NOTICE
ADDED
|
@@ -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.
|