Repository navigation
mtcollins1 runner: extract qualification instruments from the run (leg 3b) - #13225
gunbai-bot[bot] wants to merge 71 commits into
Conversation
…inding (leg 2) One JIT mint over a slot sum (microVM cell | transient systemd unit on a gunbc.managed_host host); ensure-style deregistration with org-listing readback and typed refusal on every exit; teardown inventory generalized to a host-unit arm; census row for deregistration (pre-approved, ruling 2026-10-03); route legs registration/deregistration bound. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ttempt label as input; collect the run back (leg 3) Generalizes extdeps.github.workflows CreateDispatch from the heal-only expected_healed_sha key to the upstream's own inputs object, and dissolves create_dispatch_unconsumed_frontier_rows with a production caller. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ack's subject is the dispatched run Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e the carrier-returning helper (constructor proxy) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ob log; claim-cost read refuses typed (leg 3b) Model the Actions artifacts (List workflow run artifacts, Download an artifact) and job-logs (Download job logs for a workflow run) REST operations in extdeps.github with upstream names; the 302 is followed by the bound REST handler. Parse [floor-phase] rows in gunbc.required_ci_phase_roster and [floor-cgroup] level rows in gunbc.host_budget_source, decoding values through extdeps.linux.cgroup_v2_memory. The collect stage reads each served job's log into typed readings or a typed refusal and attempts the claim-cost artifact read, carrying its typed refusal. The single extraction frontier row becomes three rows, one per missing capability. Supplied-input witnesses are paired with an inhabitance claim over a recorded required-floor log's verbatim rows. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion/gentle-bear-467 # Conflicts: # dag/gunbc/runner/runner_qualification_dispatch.dag # dag/test/claim/runner/runner_qualification_dispatch_witness_test.dag
…pt, token check, workflow compare; split RouteLegStanding
(1) post-delete listing consumes the delete receipts (readback_after_deletes)
(2) JitRegistration sole_constructor, minted only by jit_registration_of
(3) refuse a token or authority for another App/installation
(4) JitDeregistrationReceipt sealed, built only from a GitHub listing
(OrganizationRunnerListRead sealed); pure classifier kept
(5) slots carry their workflow; mint refuses a group restricted to another
RouteLegStanding = LegWired | LegAuthorityImplemented | LegAwaitingAuthority;
route_is_executable requires LegWired; registration/deregistration are
LegAuthorityImplemented with the wiring they owe.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…mplemented with the fleet-converge wiring owed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… derived runner image until the untangle 4a runner medium Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…sion/jolly-bat-898
…ation line's absence from the log, with the recorded run as receipt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Reviewed exact head 3be84a5ee342c43fafae5b87fb3cbcaadfdfea4f.
The provider-facing half is directionally right. The job-log endpoint is modeled as the upstream job-id read through its redirect, the artifact listing/download vocabulary is separated, a short page refuses, garbled tagged rows refuse rather than disappearing, and the missing claim-cost upload remains an explicit typed standing/frontier rather than being fabricated from the log preview. The recorded excerpt also discriminates the slot-level filter from the parent levels.
I cannot approve this head yet. Five structural blockers remain in leg 3b itself, beside the inherited #13211/#13206 findings.
1. The extraction authority is implemented but not wired, while the frontier says the two log instruments are done
collect_qualification_instruments has no production caller in this stack. CollectInstruments in the route carries only the instrument list; it has no authority standing, and route_is_executable checks only effectful legs. Therefore a future route can become executable without any edge to this collector.
The old broad extraction frontier has meanwhile been replaced by rows only for claim cost, boot readback and cohort observation. That reports FloorPhaseRows and FloorCgroupRows as consumed when only witness calls reach the fold.
Represent the same split #13206 is moving toward: extraction authority implemented vs extraction wired into the route. Keep a frontier/awaiting standing until the production route invokes this exact collector, or land the orchestrator edge in this PR. A witness calling the pure fold is not that consumer.
2. Target, run and slot identity are independently cross-wirable
The production entry is:
collect_qualification_instruments(
target: QualificationWorkflowTarget,
collected: CollectedQualificationRun,
slot_unit: NonEmptyStr,
)
None of those three values is joined. A real collected run can be combined with another repository/workflow target for the log/artifact reads and another unit name for the cgroup suffix filter. CollectedQualificationRun does not retain the sealed dispatch or the authorized JIT slot, so this function cannot reject the cross-wire.
The effect must consume one sealed extraction subject derived from the dispatched run plus the authorized JIT registration/host-unit slot. That subject should own the repository/workflow/ref, run and run-attempt identity, designated floor job, runner id and exact systemd unit. No caller-supplied target or unit string should remain at the effect boundary.
Required REDs: a target from run B beside collected run A refuses before a network read; slot B beside run A cannot select any cgroup row.
3. A successful extraction is forgeable and loses the read evidence
QualificationInstrumentsRead is an open variant, extract_qualification_instruments is unrestricted, and AttemptJobLogRead plus ClaimCostArtifactRead are caller-authorable. Any caller can directly author a successful extraction, or obtain one by feeding invented log text to a real CollectedQualificationRun. The construction wall added in #13211 stops fabrication of the collected run, but not fabrication of what that run supposedly measured.
Keep the pure decoder witnessable, but make the production success receipt construction-confined and mint it only downstream of the actual GitHub reads. Retain the source evidence in that receipt: sealed dispatch/collection identity, each job id, a digest and byte count of each complete log body, the read outcome, and the artifact-list/download receipt. A later assessment must not have to trust rows detached from the bytes and job that produced them.
Controls should pin direct-literal refusal, an outside call to the production constructor, and a supplied log whose job id is not the designated collected job.
4. Rows from different jobs can be combined into one apparent floor measurement
conclude_qualification_run still identifies jobs only by attempt label + started_at. Leg 3b downloads every such job and flattens all phase and cgroup rows. Phase rows from job A and a slot cgroup row from job B therefore satisfy one QualificationInstrumentsRead; the success payload drops the source job identities entirely.
This PR cannot retire the job-log instruments before #13211's exact-floor-job/runner-identity blocker is closed. Carry the minted runner id into collection, identify the actual floor/instrument-producing job, and read that job only—or retain readings per job and require both instrument classes from the same designated job. Add the split-across-two-jobs RED.
5. The result and local field types overclaim what is established
QualificationInstrumentsRead is constructed while claim_cost may be ClaimCostArtifactAbsent/unreadable and while GuestIdleMeminfoAndNproc and ConcurrentCohortSeatWindows are not represented in the payload at all. That arm therefore does not mean “qualification instruments read”; it means only that the two job-log instruments were decoded. Model a standing per instrument, or narrow the arm to QualificationJobLogInstrumentsRead, so a downstream route cannot interpret partial extraction as the completed collect stage.
Also:
FloorPhaseTimed.wall_msshould use the existingstd.measuremillisecond carrier rather than a bareIntwhose unit exists only in the field name.- The three new REST operations declare exact
500only. Use the repository's5xxresponse arm so 502/503/504 remain typed unreadable outcomes instead of falling outside the claimed refusal surface.
I accept keeping claim-cost parsing open: the workflow currently does not publish the named artifact, and the present text-only REST realization cannot open the zip. Mapping a download-time 410 to ClaimCostArtifactExpired rather than generic archive-unreadable would be a useful local correction, but it is not an additional blocker.
Exact-head required CI is currently queued. The supplied 13/13 result and the live redirect read support the parser mechanics, but they do not close the construction, subject-binding and route-wiring gaps above.
…verged on the floor) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tter's reading; the interpreter's after #13228) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion/gentle-bear-467
…ambiguous standing, App-token credential, runner-id floor join, attempt-1 binding, ruling+interpretation+interlock - QualificationDispatchSubject (sole_constructor) minted only from the route's JIT registration and its delivered credential, the slot's workflow == the generated fleet-converge workflow, and a floor job whose runs-on is exactly the declared attempt input; REDs for other workflows and labels - dispatch classified through RestMutationExchange: 4xx refused, transport/5xx/undecodable ambiguous - CreateDispatch takes its bearer as an input; dispatch runs under the gunbai-ci installation token, credential checked against DispatchWorkflow; takes the host-generic UnitHoldProof (interlock) - collection: attempt-scoped jobs, run_attempt == 1, revision pinned, workflow path, and the floor job's runner_id == the minted runner id; collected payload keeps the sealed dispatch + WorkflowRun - WorkflowJobRun gains runner_id/runner_name (upstream job resource fields) - census: IrreversibleEffect, discharged by the 2026-10-03 ruling (verbatim) through a separate scope interpretation (eager-gull-22, 2026-10-04); interlock rostered; narrowed-interpretation RED Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…esignated job, sealed receipt with evidence, per-source standing, collect leg not wired 1. The collect stage carries a RouteLegStanding (mtcollins1_collect_leg, LegAuthorityImplemented) that counts toward route_is_executable; the log instruments keep a frontier row until the route invokes collect_qualification_instruments. 2. collect_qualification_instruments takes the sealed DispatchedQualificationRun, the collection and the authorized JitRegistration -- no target or unit argument. QualificationExtractionSubject (sole_constructor) is minted only when the run, attempt and host-unit slot agree. 3. QualificationJobLogReceipt (sole_constructor) is minted only by job_log_standing (admit_callers: collect_qualification_instruments) after the network read, and carries the subject, the log's code-point length and content digest, and the rows. The decoder stays open and identity-free. 4. The floor job is the one served job whose runner_name is the registration's name; zero or two refuse, and only that job's log is read. WorkflowJobRun regains runner_name with this consumer. 5. Per-source standing (QualificationJobLogInstrumentsRead / claim_cost) replaces the instruments-read arm; wall is std.measure Millisecond; new operations use 5xx; a download 410 is ClaimCostArtifactExpired. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n_ref_in_list arity, no panic) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Addressed at 1. Collect stage implemented but not wired.
2. Cross-wirable target, run and slot.
3. Forgeable success that loses its evidence.
4. Rows from different jobs combined.
5. Overclaiming result and field types.
Evidence:
|
…rolled -- with the capability that would enrol it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the minted JitRegistration name); drop runner_id; fix witness braces Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
Re-reviewed exact head 3199c077fdd92fffd39e5f46ad6a9953b79ce3ca.
The five leg-3b findings on 3be84a5 are substantially improved:
- the collect stage now has an explicit
LegAuthorityImplementedstanding and participates inroute_is_executable; - target/run/slot inputs have been replaced with a sealed
QualificationExtractionSubjectand pre-read run/attempt checks; - the job-log success is a sealed receipt minted only downstream of the network read and retains the source subject, complete-body digest and length;
- readings are no longer pooled across every attempt-labelled job;
- the result is split by instrument source,
wall_msis typed asMillisecond, the REST interfaces use5xx, and 410 is an expiry.
Three subject-identity gaps remain in this head, plus two required stack reconciliations.
1. The registration is not joined to the dispatched workflow/repository
QualificationExtractionSubject retains both values, but qualification_extraction_subject compares only:
- dispatch run id to collection run id;
- dispatch attempt to collection/slot attempt;
- runner name to job runner name.
It never compares registration.organization with dispatched.target.owner, and never compares the host-unit slot's workflow with the target's owner/repo/workflow/ref identity. Therefore a valid registration for workflow B can be paired with a dispatch to workflow A when the host and attempt spelling are the same.
The subject mint needs a structural workflow target carried by both registration and dispatch, or a total canonical comparison over owner, repo, workflow id and ref. Required REDs: another organization and another workflow/ref refuse before the log or artifact read.
2. “Floor job” is still inferred only from runner name
designated_floor_job chooses the sole served job whose runner_name equals the registration name. It does not inspect WorkflowJobRun.name or any job identity declared by the target workflow. The witness's helper constructs every candidate with name: "floor", so it does not discriminate this gap.
A helper job can be the sole job on the minted runner while the actual required-floor job runs elsewhere; this code will call the helper the floor job and read its log. The parser will often refuse, but that is not proof that the measured job was the pinned workload — another helper could emit the same tags.
Bind the extraction subject to the declared instrument-producing job identity of the target workflow and require both runner identity and job identity. Required control: helper on the registered runner + floor elsewhere refuses; the declared floor job on the registered runner admits.
3. Reruns and the executed revision are still erased
collect_qualification_run still calls ListJobs, whose default is the latest attempt. It neither uses the available ListAttemptJobs operation nor checks WorkflowRun.run_attempt against every WorkflowJobRun.run_attempt. CollectedQualificationRun then drops run attempt, head_sha, workflow id and event identity beyond the one-time check.
A rerun therefore keeps the dispatch run id but silently replaces the jobs and conclusion used by this extraction. The sealed receipt also cannot later establish that the bytes came from the exact FloorWorkloadPin.revision being assessed.
Use the attempt-specific jobs read or refuse when the run has advanced beyond the admitted attempt; carry the observed run attempt and head_sha (plus target/workflow identity) in the sealed collection/extraction subject. Required RED: attempt 2 under the same run id cannot stand in for the run created by the admitted dispatch.
Stack walls still present at this exact head
This branch still contains the #13206 ccad694 construction hole: jit_registration_of accepts the open JitMintDispatchAuthorized arm, so an outside caller can proxy-mint the sealed JitRegistration on which this extraction subject relies. It also contains the older #13211 dispatch/collection implementation, including mutation outcomes collapsed to QualificationDispatchRefused. Those base change requests must be resolved and this branch rebased before the seal here has the standing claimed for it.
Required prerequisite reconciliation
- #13228 must land first. This exact head correctly uses bare
response_format: Text; under the old interpreter the live read is still decoded as JSON. - After #13227 lands, the claim-cost frontier and PR body become stale: the required workflow does upload
required-floor-claim-cost. Rebase and narrow that row to the remaining binary-body/inflate/member-read capability; do not continue to cite absence of the upload as half of the open trigger.
The one-time seal probes are reported at the right rung — checked once, not enrolled — and I accept that statement. Exact-head CI is still running. The blockers above are subject and stack semantics, not witness-count issues.
…mplate expression (floor NonFoldResidueRosterDiverged) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… joined floor job; one join, not two collect_qualification_run now joins the floor job to the minted runner (job_ran_on), so leg 3b's designated_floor_job and QualificationExtractionSubject are deleted; the receipt carries the sealed CollectedQualificationRun and the registration's host-unit slot. Log and artifact reads are token-bound beside read_run_with in gunbc.github_effect_perform. ActionsArtifact keeps only the fields a consumer reads (review 75456: the unread size_in_bytes Int is removed, not wrapped). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Review 75456 ( Nothing in the change reads The same head merges #13211 Local evidence on this head: 14/14 dispatch witnesses and 29/29 route witnesses pass. Seal probes on the new signatures: forged receipt 1, outside call 1, control 0. That remains "checked once, not enrolled". |
…uery subject (side-chat RC on #13206) (1) JitMintDispatchAuthorized { dispatch: AuthorizedJitMintDispatch } sole_constructor, minted only by dispatch_jit_mint; dispatch_jit_mint, attempt_dispatch and the witness helper `dispatched` are admit_callers-sealed so no admitted caller returns it onward. (2) OrganizationRunnerListRead carries organization, name, App and installation; readback_subject_refusal runs before the answer is read; conclude_from_readback, its inner step and readback_after_deletes admit only ensure_jit_runner_deregistered. REDs: compile probe test.probe.jit_deregistration_forged_probe (victim-runner forgeries of all four sealed records + unadmitted conclusion) enrolled by test.claim.jit_deregistration_forged_probe_witness; pure readback-subject RED. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
The review on
Local results: 20/20 dispatch witnesses and 5/5 forged-probe witnesses pass. |
…ollection over the dispatched subject and the token); collect performs only the planned reads; foreign-token RED inside the real-mint claim Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…9b76) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
REQUEST_CHANGES at exact head 364148293377e5a28a3c3cbd69fd18187d5eb6c4, against DESIGN.md §§3, 4b and 5. The direct leg-3b blocker from review 5408716727 is CLOSED. The remaining blocker is incorporation of the already-requested #13211 base repairs, which are still absent from this exact tree—not another defect in the new leg-3b correction.
Accepted repair:
collect_qualification_instruments_underadmits onlycollect_qualification_instruments, whose token/registration read-plan check precedes the call. The helper now derives bothjob_idandrun_idfrom the sealed collection; neither can be supplied independently.read_claim_cost_artifactadmits only that confined helper.job_log_standingremains confined to the same path, with the slot derived from the collected registration. No new witness wrapper exports the receipt or bypasses these restrictions.- The enrolled probe actually calls both newly restricted helpers. Its claims require ConstructorCallAdmissionRefused at each exact function, while the control source requires zero of those diagnostics. The reported admit-list deletion mutant discriminates the repaired boundary. The existing pure decoder remains available without minting a production receipt.
Two previously reported #13211 bypasses remain in the tree this PR would land:
-
gunbc.runner.runner_qualification_dispatch::collect_qualification_run_underis still unrestricted. Unlike the now-fixed instruments helper, it accepts a dispatched run and an independently supplied controller token, performs the run/job reads, and mintsCollectedQualificationRunwithout the token/registration comparison. The check incollect_qualification_runremains optional to an outside caller. The downstream instruments guard does not repair the provenance of that upstream collection. -
gunbc.runner.runner_jit_perform::receive_jit_mintis still unrestricted. It seals independently supplieddispatchandoutcomeintoBoundJitCredential. A holder of delivery B's genuine credential/runner id and authorized dispatch A can reconstructJitConfigMintedfrom B and call this helper with A, obtaining a delivery labelled with A's complete dispatch. The later dispatch equality therefore does not establish which request produced the credential. This is the same constructor-proxy finding already recorded on #13211, not a new leg-3b obligation.
Incorporate the reviewed base repairs into this child and preserve the collector confinement above; do not implement a competing repair in leg 3b. The resulting exact head needs re-confirmation. No archive-inflation implementation, boot/cohort work, or live dispatch is requested here, and the implemented-not-wired extraction standing remains honest.
Reviewed the complete one-commit, three-file correction from 4872c1ed660053142baaeb0cb8cec594738552fe, exact-head DESIGN, the surrounding receipt/read path, the compiler controls, and the two inherited source paths above. The local 20/20 dispatch, 5/5 forged and TTTFT mutant results are author-reported; I did not execute tests or network/controller actions. Exact-head witnesses run 37248729045 is in progress. The requested head was unchanged immediately before submission.
…ion/gentle-bear-467 # Conflicts: # dag/gunbc/runner/runner_qualification_dispatch.dag # dag/test/claim/runner/runner_qualification_dispatch_witness_test.dag
briansrls
left a comment
There was a problem hiding this comment.
APPROVE at exact head af96af4bdf5ead38423fbcced2fdb51ea9b9fbb1, against DESIGN.md §§3/3c, 4b and 5. The inherited-base-only blocker from the review at 3641482933 is closed, and the accepted leg-3b confinement repair remains intact.
GitHub's comparison establishes that the now-approved #13211 head 7ebc19e01aa6076c4d5acc87089a2c00570589a6 is an ancestor. The merged source keeps its planned collection: collect_qualification_run derives run identity from the sealed dispatch, calls plan_qualification_collection with the actual token identity, and performs reads and constructs the collection only inside the admitted arm. The deleted unchecked collection helper is not restored. The receiver and generate-fold seals are incorporated as well.
The leg-3b entry independently checks its actual token through collect_read_plan using the same token_names_registration. collect_qualification_instruments_under still admits only that checked entry and takes only (collected, token); its job and run ids come from the sealed collection, not independent arguments. read_claim_cost_artifact remains confined to that helper. There is no newly opened route around either token check or the collection's designated job/run.
The combined real-mint claim retains BOTH planner discriminators: foreign App and foreign installation plan no collection reads and no instrument reads; matching identities retain the exact run, attempt and floor-job read plans. The previously accepted outside-helper and free-token artifact-read probes remain outside the changed-file delta. The merge does not replace either check with a constructed success plan in the production entry.
The extraction frontier remains honest: the log path can produce its own instrument receipt, while binary archive/member parsing, boot readback and cohort observation remain separately owed, and production wiring is still required. Approval does not claim a completed throughput qualification or authorize a live dispatch.
Reviewed the correction from 3641482933, base ancestry and merge differences, the exact merged collection/extraction paths and combined witness, and prior discussions. Dispatch 21/21, route 29/29, forged 5/5 and mutation results are author-reported; I did not run local tests, mutants or network/hardware actions. Exact-head witnesses run 37253102577 was still in progress. The head was unchanged immediately before submission. Land after #13211, preserve the accepted #13288 changes when integrating the sibling, and retain required exact-head checks; approval of this tree does not automatically cover a later merge/rebase head.
… conflict resolved keeping both sides' imports and claims Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s; covers is the single source of which rows take its discharge (branch-pin sites dropped: federated on their own parameters); claim pins the iff Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion msg_5756a200) recorded as its own row beside the verbatim 10-03 ruling, replacing the agent interpretation; dispatch and branch pins back in covers and every covered row derives its discharge from it Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # dag/test/claim/authorization_pattern_selection_witness_test.dag
…ion/gentle-bear-467 # Conflicts: # dag/test/claim/authorization_pattern_selection_witness_test.dag
… row takes it only if covers names it); covered sites the selection federates on their own parameters -- registration, deregistration, the reversible branch pins -- do not consume it and owe no interlock Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion/gentle-bear-467
…ts own federated standing, not by the 10-03/10-05 rulings; covers lists ensure_qualification_ref_pin for its branch create only Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ion/gentle-bear-467
…me field, no RestExchangePerformance) Conflicts: github_effect_perform.dag (imports; the generate fold takes main's RestResult and keeps this branch's admit_callers seal) and github_effect_perform_witness_test.dag (main's RestAnswered call, this branch's sealed BoundJitCredential pattern). Beyond the conflicts, the port touches logic: this branch's REST ops drop their outcome fields (CreateDispatch's body is now result: WorkflowDispatchReceipt), the qualification performers carry RestResult<T>, and the dispatch, run collection, ref pin and branch removal decisions match RestAnswered/RestRefused and classify only the refusal (classify_rest_refusal, read or mutation). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The three new operations drop their outcome field; read_job_log_with / list_run_artifacts_with / download_artifact_with carry RestResult beside the sealed read; job-log and claim-cost refusals carry RestExchangeRefusal from classify_rest_refusal (a download 410 stays ClaimCostArtifactExpired). Witnesses build supplied RestResult values through small helpers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… UnimportedBareProvider) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
APPROVE at exact requested head ee6a021a5ce43cbb2512ae270a43988ab49da36d, against DESIGN.md §§3, 4b and 5. The RestResult port preserves the accepted leg-3b decisions and confinement. GitHub's comparison confirms that the separately approved #13211 head 15eb7f6b1a16bf967cca27513522d3ae344cc536 is an ancestor.
The job-log, artifact-list and artifact-download performers now carry RestResult over their actual payloads. They project answer.log, answer.result and answer.archive only inside RestAnswered and preserve RestRefused; no failed exchange is paired with an invented successful body. actions_artifacts continues to bind auth_input to the supplied token, and the explicit Text import resolves the existing serialization name rather than introducing another response-format authority.
The consumer uses main's classify_rest_refusal with RestReadExchange for unreadable logs, lists, run readbacks and archives. A download's explicit 410 still has its existing expiry meaning. An answered archive still yields ClaimCostArchiveNotInflatable, not a parsed TSV or completed instrument reading. The binary-body/member-inflation frontier is not discharged by adopting RestResult.
collect_qualification_instruments still plans against the actual token's App and installation before any read. The only admitted caller of collect_qualification_instruments_under is that checked entry; _under takes only the sealed collection and token, deriving the designated job, run and host-unit slot itself. read_claim_cost_artifact remains confined to _under, and job_log_standing remains confined there too. The compiler probe retains the literal, receipt-mint, unchecked-helper and free-token/run-id controls beside the names-only control. The base's sealed JIT delivery and planned run collection are not replaced by a competing path.
The artifact decision still refuses incomplete lists, zero/multiple matching names, expired artifacts and unreadable reads. The run is read after the listing and must still be at the dispatched attempt before download. The port does not reintroduce first-match duplicate selection or infer attempt identity from the run id alone.
The successful job-log receipt still retains the sealed collection, its slot, complete-log digest and code-point count, and decoded readings. Phase and cgroup rows come from that one designated job, and the slot-level filter is unchanged. A job-log receipt is not a claim that the artifact, boot or cohort instruments were obtained; the per-source standing and implemented-but-unwired collect frontier remain explicit.
Verified the exact-head witnesses workflow 37318668116 completed successfully. The remote Hermetic dispatch 21/21, route 29/29 and forged 5/5 results are author-run receipts; I did not execute claims, mutations, live API reads or hardware operations. The requested head remained unchanged and mergeable before submission.
No source blocker remains in this port. Land after its base and through the normal required landing-head checks. This approval does not cover a later merge/rebase head, archive-reader completion or the eventual live qualification/boot wiring.
|
Heads-up before queueing: this PR adds |
Leg 3b of the mtcollins1 qualification route. Stacked on #13211: this branch contains its commits until it lands, and I will merge main in afterwards.
Dissolves
gunbc.runner.runner_qualification_dispatchqualification_instrument_extraction_frontier_rowsas it was (one row, every instrument unextracted). It is now three rows, one per missing capability. Each row is retired by its own trigger.What reads now
extdeps.github, cited by upstream name:extdeps.github.actions_artifacts, servicegithub.Artifacts, withListWorkflowRunArtifacts(actions/list-workflow-run-artifacts) andDownloadArtifact(actions/download-artifact;archive_formatis upstream's single memberzip, written into the path).github.WorkflowRunsDownloadJobLogsForWorkflowRun(actions/download-job-logs-for-workflow-run).302+Location. The interface names the answer at the end of the redirect; the seed REST handler (ureq) follows it. Transport stays a bound handler (DESIGN §3).qualification_instrument_producer, not with a new authority:gunbc.required_ci_phase_rostergetsread_floor_phase_row(timed and untimed rows are separate arms; a missing phase or a non-countwall_msis garbled). It also holds the one reader for the floor's[tag] k=vline encoding.gunbc.host_budget_sourcegetsread_floor_cgroup_level_row. It decodeshighandpeakthroughextdeps.linux.cgroup_v2_memory(maxis Unlimited, never a number).extract_qualification_instrumentstakes the sealedCollectedQualificationRunand returns phase rows plus the slot's own cgroup level rows. Levels above the slot are refused as the slot's reading.InstrumentReadRefusal:JobLogUnreadable,FloorPhaseRowGarbledInLog,FloorCgroupRowGarbledInLog,FloorPhaseRowsAbsent, orSlotCgroupLevelAbsent(which lists the levels seen).collect_qualification_instrumentsis the network caller. It reads each served job's log and attempts the claim-cost artifact read.ClaimCostArtifactReadarms are: list unreadable, list truncated, absent (with the names that were present), expired, archive unreadable, and archive not inflatable. There is deliberately no parsed arm yet.qualification_instrument_sourceis a total match, so a new instrument cannot compile without saying where its reading comes from.The three remaining rows (parent ruling A: no seed growth here)
[over-cost]preview and on[floor-shared-fill]rows, and the calibration[witness]line is absent.required-floor-claim-costagain. When this PR was first written it did not: the upload had been lost in CI: required witnesses check builds only the compiler, on a hosted runner #11742, and recent runs then published onlyrequired-ci-measurement-receiptandcompiler-pair-candidate. The read now runs under the registration's token, refuses zero or several same-name artifacts, and binds the listing to the collected attempt by re-reading the run afterwards.Stringonly, so a zip answersRestBodyUndecodable.required_floor_claim_cost.tsvmember of the upload-artifact zip, parsed byparse_claim_cost_tsvand bound to this collected run.mtcollins1_boot_leg, still LegAwaitingAuthority).seal_cohortneeds a barrier-released roster of seats, and a one-slot route has none.10 MB cap: a recorded full floor log measured 1.5 MB, so it is not refused for size. Above the cap, the read surfaces as
RestBodyUndecodable→JobLogUnreadable, typed and never truncated.Evidence
conclude_qualification_runby name, so the sealing from mtcollins1 runner: dispatch the floor to the attempt's slot and read the run back (leg 3) #13211 holds.the_extraction_reads_a_recorded_required_floor_log:test.fixture.recorded_required_floor_log_excerpt, the verbatim[floor-phase]/[floor-cgroup]lines of run 35048059968 / job 104642384772.level_is_slotaccept every level turns the positive control, the slot-level-absent refusal and the inhabitance claim red. Restored.read_attempt_job_logon job 104642384772 followed the redirect and read 5,744 lines.read_claim_cost_artifacton run 37174570297 answeredClaimCostArtifactAbsent { names_seen: [required-ci-measurement-receipt] }.runner_qualification_dispatch_witness_testpassed under the interpreter. A full floor and clippy run was not done locally; CI judges.Found along the way, not fixed here
The seed ignores a bare
response_format: Text. It reads only the quoted string"Text", so the bare spelling silently decodes as JSON. The first live run of the log read failed exactly this way with status 200. The new operations use"Text".extdeps.github.pullsgithub.Pulls.Diffstill uses the bare spelling and is presumably broken the same way.Since review on 3be84a5 (sealed receipt, one floor-job join)
The per-blocker replies are on the PR.
job_ran_on. This PR adds no second join.QualificationJobLogReceiptissole_constructor, andjob_log_standingisadmit_callers: [collect_qualification_instruments].test.claim.qualification_job_log_receipt_forged_probe_witnesscompilestest.probe.qualification_job_log_receipt_forged_probeand requiresSoleConstructorViolationatQualificationJobLogReceiptandConstructorCallAdmissionRefusedatjob_log_standing, beside a names-only control that refuses at neither.ReadsLiveTree;v2.workflow.required_floordeletedDeclinedLiveTree.🤖 Generated with Claude Code