Repository navigation
feat(#536): Gate A preflight before the first CUDA call (CC-536-01-02 N-T2) - #565
Merged
Merged
Conversation
… N-T2)
saccade_track and saccade_track_measurement now run Gate A right after the
run takes <out> and before any runtime is built: the strict config and every
CUDA-free plan built from it (ingest, sequence output, post-detector,
pipeline, schedule), the detector plan from the lineage and the attestation
(N-R4), every sequence's seqinfo.ini and img1 listing (read_sequence_input,
the same max_frames), the output directories (RunCompletion::check_writable:
<out>, the --report directory, each --trace/<seq>/), and the operator
library, head artifact and backbone engine present under the model root with
the plan's sha256. A refusal exits 2 with the journal failed and a message
starting "preflight: "; passing prints "<entrypoint>: preflight passed".
Gate A lives in saccade_shipping_preflight, which links no CUDA library. The
runtimes gain a constructor taking the detector plan, so Gate B loads exactly
the bindings Gate A hashed without reading the lineage again; the detector
load still checks the hashes. identity stays {"level": null}: no
checksum_matched or expected_source_verified claim in this slice.
Tests: test_shipping_preflight.cpp (CI, CUDA-free) runs each check on a
self-consistent stand-in bundle and refuses each failure with the journal
failed. test_saccade_track_preflight_cli.py observes cuInit at the built
entrypoint through CUDA_INJECTION64_PATH + LD_DEBUG=files: the positive
control passes Gate A and initializes CUDA, then fails in Gate B; replaced
head, self-consistent lineage with the attestation, missing attestation,
unreadable sequence and missing --report directory refuse with no cuInit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he refusal beyond the listing The mutation check found max_frames_ignored surviving: write_sequence kept the earlier img1 entries, so pass_max_frames listed every frame and passed without --max-frames. write_sequence now starts from an empty directory, and max_frames_beyond_listing pins the refusal past the listing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Archive the outgoing canonical (implementation 6848dfaa31137ba2, the #562/#563 Completion publication) and promote a fresh capture from the controlled host (build/runtime_identity, Release, --run-probe --require-complete) at the implementation head 7c24b9e. Axes: * implementation MOVED 6848dfaa31137ba2 -> 9ef960e0fd1683ee; files 292 -> 294. - Added (2): shipping/include/saccade_shipping/preflight.hpp, shipping/src/preflight.cpp (Gate A, CC-536-01-02 N-T2). - Changed (13): shipping/CMakeLists.txt (saccade_shipping_preflight and its CUDA-free test; the entrypoints link it), detector_plan.hpp/.cpp (resolve_model_path), detector_host.cpp (uses it), serial_runtime.hpp/.cpp and double_buffer_runtime.hpp/.cpp (constructor taking the detector plan), run_completion.hpp/.cpp (check_writable), tools/track_driver.hpp, tools/saccade_track.cpp and tools/saccade_track_measurement.cpp (Gate A before the runtime). - Removed: none. * environment, decision_surface, identity_semantics, runtime_inputs: unchanged. * probe: re-run fresh, not reused. Behavior 2dabed0b, equal to the previous publication. The build witness moved because build/runtime_identity was reconfigured (cmake -S . -B) and rebuilt. Probe equality is not an equivalence claim; equivalence stays unproven. check_runtime_identity_staleness.py --mode attested: exit 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chore(provenance): republish the runtime coordinate for #536 Gate A
raylei50653
added a commit
that referenced
this pull request
Oct 10, 2026
…alf-publish boundary #567 review P2 ×2: - Gate A known limits: only the three model artifacts are re-hashed at load; sequence re-read checks seqinfo.ini and the img1 listing but never hashes frame content, so a same-name, valid, correctly sized JPEG swapped in after Gate A is processed normally. Listed as an uncovered TOCTOU boundary. - CC-536-08-02 unverified: keep the #559-era evidence boundary, add that since #565 a replaced head with a still-consistent lineage+attestation is refused in Gate A before CUDA (covered by the replace-head negative control), while the full interrupted half-publish flow remains unverified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 10, 2026
architecture(B): design a supported architecture with traceable diagrams and behavior contracts
#536
Open
raylei50653
added a commit
that referenced
this pull request
Oct 11, 2026
Review P2 on #574: the §4 introduction still said CC-536-01-02 had only Gate A and no identity level. State that legacy checksum_matched is implemented at source level while expected_source_verified, the recognised expected source and the enforcing policy remain open, and scope the §6 item 3 'identity.level stays null' note to the #565 slice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements #536 / CC-536-01-02 Gate A (N-T2) as the authorized next slice: every CUDA-free check runs after
saccade_trackhas taken<out>and before the first CUDA API call. A refusal exits 2 with the journal set tofailedand makes no CUDA call.Gate A checks, in order (cheapest first):
seqinfo.iniandimg1listing, read the same way the runtime reads them (same--max-frames).<out>, in the--reportdirectory (which must already exist) and in each--trace/<seq>/.Implementation:
saccade_shipping_preflight(shipping/{include,src}/…/preflight.*). This library links no CUDA library.RunCompletion::check_writable()handles the output check.SerialRuntimeandDoubleBufferRuntimegain a constructor that takes theDetectorPlan, so Gate B loads exactly the bindings Gate A hashed and doesn't re-read the lineage. The detector load still checks the hashes.resolve_model_pathis shared between Gate A and the detector load.<entrypoint>: preflight passedafter the run-id line.Not in scope:
identity.levelstaysnull. This PR makes nochecksum_matchedorexpected_source_verifiedclaim and does not mark CC-536-01-02 complete overall. Identity binding, the expected source (#549 S1), package re-pin and the report-parse P3 are separate slices.Evidence
CI (CUDA-free)
tests/native/test_shipping_preflight.cppbuilds a self-consistent stand-in bundle. It shows the bundle passes, and that each check refuses its own failure: config ×2, lineage ×2, attestation bound to another lineage, sequence ×2, max-frames beyond the listing, report dir, trace dir, and 3 missing plus 3 replaced model files. Each refusal leaves the journalfailedwithpreflight:,identity.levelnull, and no probe file. 237 checks.Local, at the built entrypoint (
tests/unit/test_saccade_track_preflight_cli.py)CUDA_INJECTION64_PATHinsidecuInit, andLD_DEBUG=fileslogs that dlopen. Loadinglibcuda.so.1is not used as the signal, becauselibcublasLt's constructor dlopens it beforemainin every run.cuInitis observed, and Gate B refuses it (dlopenof the stand-in operator library fails).--reportdirectory. Each is refused in Gate A with nocuInit.Mutation check (local): all 9 mutants were caught: no artifact check, no sequence check, no output check, attestation ignored, max-frames ignored, unprefixed errors, probe file left behind, report dir not checked, and runtime built before preflight (caught by the CLI test through
cuInit). One mutant,max_frames_ignored, survived at first because the test kept the oldimg1entries. I fixed the test in7c24b9e3and the rerun caught it. Raw logs: gitignoredresults/536_preflight/mutation_35bdcd80/.GPU (local, gpu0 lease, clean tree at
7c24b9e3,build-release): raw output in gitignoredresults/536_preflight/runtime_7c24b9e3/(run.shmirrors #562's).--againstthe feat(#536): run completion for saccade_track (CC-536-01-01) #562 formal run and the PR-C2 formal run): MOT txt, trace hash and graph counts are identical, so the MOT bytes are unchanged.noneand--schedule serial: EXACT.aa84cccd…), and the tree is clean after the run.serial_runtime,double_buffer_runtime,detector_s2,post_detector_host,ingest_host,native_build): 6/6.Known limits
.saccade_track.preflight.<run_id>.tmpfile behind (same as the other temp files).entrypoint_pin.json) is still the PR-C2 build. Re-pin is a later slice; local-only.Runtime coordinate republication follows as a stacked PR (runbook §3.2).
🤖 Generated with Claude Code