Skip to content

Commit 7bf86d7

Browse files
authored
Merge branch 'main' into fix/embodiment-verify-and-horizon-migration
2 parents 7fd2768 + 8bcfc68 commit 7bf86d7

157 files changed

Lines changed: 21698 additions & 3322 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/PARITY_RECEIPTS.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Parity receipt production controls
2+
3+
The `parity-receipts.yml` workflow runs paid Modal A100 jobs and handles the
4+
credentials used to download the approved model. Its `produce` job is bound to
5+
the `parity-receipts-production` GitHub environment for every trigger:
6+
scheduled runs, `release/**` pushes, and manual dispatches.
7+
8+
Repository administrators must configure that environment before enabling the
9+
workflow:
10+
11+
1. Add at least one independent required reviewer and enable **Prevent
12+
self-review**. The person who initiated or pushed the run must not be able to
13+
approve their own deployment. Deselect **Allow administrators to bypass
14+
configured protection rules**.
15+
2. Limit deployment branches/tags to protected `main` and protected
16+
`release/**` branches. Those protections must require pull requests and
17+
code-owner review for `.github/workflows/parity-receipts.yml`, this document,
18+
and receipt verifier/producer code.
19+
3. Store `MODAL_TOKEN_ID`, `MODAL_TOKEN_SECRET`, and `HF_TOKEN` as environment
20+
secrets, not repository secrets.
21+
4. Store these environment variables:
22+
- `PARITY_RECEIPTS_ENVIRONMENT_PROTECTED=true`
23+
- `PARITY_MODEL_DIGEST=<sha256>` where the digest is SHA-256 of
24+
`huggingface:lerobot/pi05_libero_finetuned_v044@<immutable-hf-commit>`.
25+
5. Audit changes to reviewers, deployment branches, secrets, variables, and
26+
administrator-bypass settings like code changes.
27+
28+
The manual `authorize_paid_run` input records intent only. It cannot supply or
29+
override the approved model digest, credentials, environment, workflow, ref,
30+
or reviewer gate. Scheduled and release runs still wait for the same protected
31+
environment approval before any step can access secrets or start paid work.
32+
33+
Each authorized run derives a canonical receipt namespace from the lowercase
34+
repository identity, checked-out commit SHA, GitHub run ID, and run attempt.
35+
The workflow passes that complete binding to every Modal producer. In receipt
36+
mode, Hugging Face caches, ONNX exports, benchmark inputs, and local result
37+
JSON files live only below `receipt_runs/<namespace>`; partial receipt metadata
38+
and non-canonical or path-like namespaces are rejected. Static legacy paths
39+
remain available only when no receipt metadata is supplied, outside this
40+
workflow. Retrying a run creates a new namespace and cannot reuse an earlier
41+
attempt's measured export directory.
42+
43+
The same namespace is embedded in both GitHub artifact names. Consumers first
44+
select trusted server-returned workflow metadata, recompute that run attempt's
45+
namespace, and then accept exactly one matching manifest and payload artifact.
46+
Artifacts from earlier attempts, similarly named artifacts, and duplicate
47+
matches are rejected rather than selected heuristically.
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
name: Parity receipts
2+
3+
on:
4+
schedule:
5+
- cron: "17 8 * * 1"
6+
workflow_dispatch:
7+
inputs:
8+
authorize_paid_run:
9+
description: Authorize the paid Modal A100 receipt producers
10+
required: true
11+
default: false
12+
type: boolean
13+
push:
14+
branches:
15+
- "release/**"
16+
17+
permissions:
18+
actions: read
19+
contents: read
20+
21+
concurrency:
22+
group: parity-receipts-${{ github.ref }}
23+
cancel-in-progress: false
24+
25+
jobs:
26+
produce:
27+
name: Produce provenance-bound receipts
28+
runs-on: ubuntu-latest
29+
# This environment must require independent reviewers, prevent self-review,
30+
# and allow only protected main/release/* deployment branches. See
31+
# .github/PARITY_RECEIPTS.md. Environment secrets are unavailable until
32+
# its protection rules approve this job.
33+
environment: parity-receipts-production
34+
timeout-minutes: 120
35+
outputs:
36+
authorized: ${{ steps.authorization.outputs.authorized }}
37+
artifact_id: ${{ steps.payload.outputs.artifact-id }}
38+
artifact_name: ${{ steps.namespace.outputs.payload_artifact_name }}
39+
artifact_digest: ${{ steps.payload.outputs.artifact-digest }}
40+
export_id: ${{ steps.manifest.outputs.export_id }}
41+
export_digest: ${{ steps.manifest.outputs.export_digest }}
42+
model_digest: ${{ steps.authorization.outputs.model_digest }}
43+
receipt_namespace: ${{ steps.namespace.outputs.receipt_namespace }}
44+
45+
steps:
46+
- uses: actions/checkout@v4
47+
48+
- uses: actions/setup-python@v5
49+
with:
50+
python-version: "3.12"
51+
cache: pip
52+
cache-dependency-path: pyproject.toml
53+
54+
- name: Check authorization and required identities
55+
id: authorization
56+
env:
57+
AUTHORIZED_INPUT: ${{ inputs.authorize_paid_run || false }}
58+
CONFIGURED_MODEL_DIGEST: ${{ vars.PARITY_MODEL_DIGEST }}
59+
PROTECTED_ENVIRONMENT_CONFIGURED: ${{ vars.PARITY_RECEIPTS_ENVIRONMENT_PROTECTED }}
60+
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
61+
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
62+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
63+
run: |
64+
model_digest="$CONFIGURED_MODEL_DIGEST"
65+
authorized=true
66+
if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ] && [ "$AUTHORIZED_INPUT" != "true" ]; then
67+
authorized=false
68+
fi
69+
if [ -z "$MODAL_TOKEN_ID" ] || [ -z "$MODAL_TOKEN_SECRET" ] || [ -z "$HF_TOKEN" ]; then
70+
authorized=false
71+
fi
72+
if [ "$PROTECTED_ENVIRONMENT_CONFIGURED" != "true" ]; then
73+
authorized=false
74+
fi
75+
if ! printf '%s' "$model_digest" | grep -Eq '^(sha256:)?[0-9a-fA-F]{64}$'; then
76+
authorized=false
77+
fi
78+
echo "authorized=$authorized" >> "$GITHUB_OUTPUT"
79+
echo "model_digest=$model_digest" >> "$GITHUB_OUTPUT"
80+
if [ "$authorized" != "true" ]; then
81+
echo "::notice::Parity receipt production skipped: protected-environment approval/configuration, authorization, secrets, or model digest unavailable."
82+
fi
83+
84+
- name: Install producer client
85+
if: steps.authorization.outputs.authorized == 'true'
86+
run: python -m pip install --upgrade pip modal && python -m pip install -e .
87+
88+
- name: Derive immutable receipt namespace
89+
if: steps.authorization.outputs.authorized == 'true'
90+
id: namespace
91+
run: >-
92+
python -m tether.receipt_provenance namespace
93+
--repository "${{ github.repository }}"
94+
--source-sha "${{ github.sha }}"
95+
--run-id "${{ github.run_id }}"
96+
--run-attempt "${{ github.run_attempt }}"
97+
98+
- name: Run Modal parity producer
99+
if: steps.authorization.outputs.authorized == 'true'
100+
env:
101+
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
102+
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
103+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
104+
run: >-
105+
modal run scripts/modal_per_step_parity.py
106+
--receipt-namespace "${{ steps.namespace.outputs.receipt_namespace }}"
107+
--source-repository "${{ github.repository }}"
108+
--source-sha "${{ github.sha }}"
109+
--workflow-run-id "${{ github.run_id }}"
110+
--workflow-run-attempt "${{ github.run_attempt }}"
111+
112+
- name: Run Modal overhead producer
113+
if: steps.authorization.outputs.authorized == 'true'
114+
env:
115+
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
116+
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
117+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
118+
run: >-
119+
modal run scripts/modal_per_step_overhead.py
120+
--receipt-namespace "${{ steps.namespace.outputs.receipt_namespace }}"
121+
--source-repository "${{ github.repository }}"
122+
--source-sha "${{ github.sha }}"
123+
--workflow-run-id "${{ github.run_id }}"
124+
--workflow-run-attempt "${{ github.run_attempt }}"
125+
126+
- name: Run Modal end-to-end latency producer
127+
if: steps.authorization.outputs.authorized == 'true'
128+
env:
129+
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
130+
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
131+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
132+
run: >-
133+
modal run scripts/modal_per_step_e2e_latency.py
134+
--receipt-namespace "${{ steps.namespace.outputs.receipt_namespace }}"
135+
--source-repository "${{ github.repository }}"
136+
--source-sha "${{ github.sha }}"
137+
--workflow-run-id "${{ github.run_id }}"
138+
--workflow-run-attempt "${{ github.run_attempt }}"
139+
140+
- name: Collect receipt payload
141+
if: steps.authorization.outputs.authorized == 'true'
142+
env:
143+
RECEIPT_SOURCE: ${{ github.workspace }}/../reflex_context
144+
RECEIPT_NAMESPACE: ${{ steps.namespace.outputs.receipt_namespace }}
145+
run: |
146+
mkdir receipt-payload
147+
namespace_source="$RECEIPT_SOURCE/receipt_runs/$RECEIPT_NAMESPACE"
148+
cp "$namespace_source/per_step_parity_last_run.json" receipt-payload/
149+
cp "$namespace_source/per_step_overhead_last_run.json" receipt-payload/
150+
cp "$namespace_source/per_step_e2e_latency_last_run.json" receipt-payload/
151+
152+
- name: Upload hashed receipt payload
153+
if: steps.authorization.outputs.authorized == 'true'
154+
id: payload
155+
uses: actions/upload-artifact@v4
156+
with:
157+
name: ${{ steps.namespace.outputs.payload_artifact_name }}
158+
path: receipt-payload/
159+
if-no-files-found: error
160+
retention-days: 14
161+
162+
- name: Build provenance manifest
163+
if: steps.authorization.outputs.authorized == 'true'
164+
id: manifest
165+
run: >-
166+
python -m tether.receipt_provenance build
167+
--payload-dir receipt-payload
168+
--repository "${{ github.repository }}"
169+
--source-sha "${{ github.sha }}"
170+
--source-ref "${{ github.ref }}"
171+
--run-id "${{ github.run_id }}"
172+
--run-attempt "${{ github.run_attempt }}"
173+
--receipt-namespace "${{ steps.namespace.outputs.receipt_namespace }}"
174+
--event "${{ github.event_name }}"
175+
--artifact-id "${{ steps.payload.outputs.artifact-id }}"
176+
--artifact-name "${{ steps.namespace.outputs.payload_artifact_name }}"
177+
--artifact-digest "${{ steps.payload.outputs.artifact-digest }}"
178+
--model-id "lerobot/pi05_libero_finetuned_v044"
179+
--model-digest "${{ steps.authorization.outputs.model_digest }}"
180+
--expires-in-hours 168
181+
--output receipt-manifest/receipt-manifest.json
182+
183+
- name: Upload provenance manifest
184+
if: steps.authorization.outputs.authorized == 'true'
185+
uses: actions/upload-artifact@v4
186+
with:
187+
name: ${{ steps.namespace.outputs.manifest_artifact_name }}
188+
path: receipt-manifest/receipt-manifest.json
189+
if-no-files-found: error
190+
retention-days: 14
191+
192+
- name: Release branches require receipt authorization
193+
if: >-
194+
always() && startsWith(github.ref, 'refs/heads/release/') &&
195+
steps.authorization.outputs.authorized != 'true'
196+
run: |
197+
echo "::error::Release receipt gate cannot run without the protected receipt environment, Modal/HF secrets, and PARITY_MODEL_DIGEST."
198+
exit 1
199+
200+
consume:
201+
name: Verify and enforce receipt gates
202+
needs: produce
203+
if: needs.produce.outputs.authorized == 'true'
204+
runs-on: ubuntu-latest
205+
timeout-minutes: 15
206+
207+
steps:
208+
- uses: actions/checkout@v4
209+
210+
- uses: actions/setup-python@v5
211+
with:
212+
python-version: "3.12"
213+
cache: pip
214+
cache-dependency-path: pyproject.toml
215+
216+
- name: Install receipt verifier
217+
run: python -m pip install -e ".[dev]"
218+
219+
- name: Download payload by server-assigned artifact id
220+
uses: actions/download-artifact@v4
221+
with:
222+
artifact-ids: ${{ needs.produce.outputs.artifact_id }}
223+
path: receipt-payload
224+
225+
- name: Download named provenance manifest
226+
uses: actions/download-artifact@v4
227+
with:
228+
name: parity-receipt-manifest-${{ github.sha }}
229+
path: receipt-manifest
230+
231+
- name: Verify receipt provenance and internal hashes
232+
run: >-
233+
python -m tether.receipt_provenance verify-local
234+
--manifest receipt-manifest/receipt-manifest.json
235+
--payload-dir receipt-payload
236+
--repository "${{ github.repository }}"
237+
--source-sha "${{ github.sha }}"
238+
--source-ref "${{ github.ref }}"
239+
--run-id "${{ github.run_id }}"
240+
--run-attempt "${{ github.run_attempt }}"
241+
--event "${{ github.event_name }}"
242+
--artifact-id "${{ needs.produce.outputs.artifact_id }}"
243+
--artifact-name "${{ needs.produce.outputs.artifact_name }}"
244+
--artifact-digest "${{ needs.produce.outputs.artifact_digest }}"
245+
--model-id "lerobot/pi05_libero_finetuned_v044"
246+
--model-digest "${{ needs.produce.outputs.model_digest }}"
247+
--export-id "${{ needs.produce.outputs.export_id }}"
248+
--export-digest "${{ needs.produce.outputs.export_digest }}"
249+
250+
- name: Run fail-loud receipt gates
251+
env:
252+
TETHER_RECEIPT_DIR: ${{ github.workspace }}/receipt-payload
253+
TETHER_REQUIRE_RECEIPTS: "1"
254+
run: >-
255+
pytest -v
256+
tests/test_decomposed_per_step_parity.py
257+
tests/test_decomposed_per_step_overhead.py
258+
tests/test_decomposed_per_step_e2e_latency.py

0 commit comments

Comments
 (0)