Skip to content

mtcollins1 runner: extract qualification instruments from the run (leg 3b) - #13225

Open
gunbai-bot[bot] wants to merge 71 commits into
mainfrom
session/gentle-bear-467
Open

gunbai-bot[bot] wants to merge 71 commits into
mainfrom
session/gentle-bear-467

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

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_dispatch qualification_instrument_extraction_frontier_rows as 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:
    • New extdeps.github.actions_artifacts, service github.Artifacts, with ListWorkflowRunArtifacts (actions/list-workflow-run-artifacts) and DownloadArtifact (actions/download-artifact; archive_format is upstream's single member zip, written into the path).
    • github.WorkflowRuns DownloadJobLogsForWorkflowRun (actions/download-job-logs-for-workflow-run).
    • Both downloads are documented upstream as 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).
  • Parsers live with the producers named by qualification_instrument_producer, not with a new authority:
    • gunbc.required_ci_phase_roster gets read_floor_phase_row (timed and untimed rows are separate arms; a missing phase or a non-count wall_ms is garbled). It also holds the one reader for the floor's [tag] k=v line encoding.
    • gunbc.host_budget_source gets read_floor_cgroup_level_row. It decodes high and peak through extdeps.linux.cgroup_v2_memory (max is Unlimited, never a number).
  • Collect, then extract.
    • extract_qualification_instruments takes the sealed CollectedQualificationRun and returns phase rows plus the slot's own cgroup level rows. Levels above the slot are refused as the slot's reading.
    • Otherwise it returns a typed InstrumentReadRefusal: JobLogUnreadable, FloorPhaseRowGarbledInLog, FloorCgroupRowGarbledInLog, FloorPhaseRowsAbsent, or SlotCgroupLevelAbsent (which lists the levels seen).
    • collect_qualification_instruments is the network caller. It reads each served job's log and attempts the claim-cost artifact read.
  • The claim-cost read refuses with a type, and the refusal is carried on the read arm. The ClaimCostArtifactRead arms 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_source is 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)

  1. ClaimCostArtifactEvalSteps and CalibrationSpecimenWitnessLine.
    • Neither reaches the log in complete form. Measured on a recorded floor log: eval_steps appear only on the 25-row [over-cost] preview and on [floor-shared-fill] rows, and the calibration [witness] line is absent.
    • Upload: restored by CI: restore the required-floor-claim-cost upload; RFM row for an instrument artifact that stopped existing while cited #13227 (merged). The required floor job uploads required-floor-claim-cost again. 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 only required-ci-measurement-receipt and compiler-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.
    • The REST body is UTF-8 String only, so a zip answers RestBodyUndecodable.
    • Trigger (what remains): a binary REST response body, and an inflate reader for the exact required_floor_claim_cost.tsv member of the upload-artifact zip, parsed by parse_claim_cost_tsv and bound to this collected run.
  2. GuestIdleMeminfoAndNproc: waits on the boot leg's runner-host-up readback (mtcollins1_boot_leg, still LegAwaitingAuthority).
  3. ConcurrentCohortSeatWindows: seal_cohort needs 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

  • Supplied-input witnesses cover every refusal arm and the positive control. The extraction claims are admitted to conclude_qualification_run by name, so the sealing from mtcollins1 runner: dispatch the floor to the attempt's slot and read the run back (leg 3) #13211 holds.
  • Inhabitance claim the_extraction_reads_a_recorded_required_floor_log:
    • Input: test.fixture.recorded_required_floor_log_excerpt, the verbatim [floor-phase]/[floor-cgroup] lines of run 35048059968 / job 104642384772.
    • It asserts the route: all 79 phase rows are read, and only the 4 slot-level rows out of 12 level rows are taken, with memory.high and peak as printed.
  • Discriminating control (run locally): making level_is_slot accept every level turns the positive control, the slot-level-absent refusal and the inhabitance claim red. Restored.
  • Live real path (scratch entry, interpreter, not committed):
    • read_attempt_job_log on job 104642384772 followed the redirect and read 5,744 lines.
    • read_claim_cost_artifact on run 37174570297 answered ClaimCostArtifactAbsent { names_seen: [required-ci-measurement-receipt] }.
  • All 13 witnesses in runner_qualification_dispatch_witness_test passed 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.pulls github.Pulls.Diff still 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.

  • The floor job comes from mtcollins1 runner: dispatch the floor to the attempt's slot and read the run back (leg 3) #13211's collection, joined by job_ran_on. This PR adds no second join.
  • QualificationJobLogReceipt is sole_constructor, and job_log_standing is admit_callers: [collect_qualification_instruments].
  • The seal is enrolled as executed REDs, using mtcollins1 runner: JIT register/deregister over a managed-host unit binding (leg 2) #13206's forged-probe pattern. test.claim.qualification_job_log_receipt_forged_probe_witness compiles test.probe.qualification_job_log_receipt_forged_probe and requires SoleConstructorViolation at QualificationJobLogReceipt and ConstructorCallAdmissionRefused at job_log_standing, beside a names-only control that refuses at neither.
  • An earlier revision stated this as "checked once, not enrolled". That rested on the stale premise that the floor declines ReadsLiveTree; v2.workflow.required_floor deleted DeclinedLiveTree.

🤖 Generated with Claude Code

Brian Searls and others added 11 commits October 4, 2026 04:03
…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>
…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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_ms should use the existing std.measure millisecond carrier rather than a bare Int whose unit exists only in the field name.
  • The three new REST operations declare exact 500 only. Use the repository's 5xx response 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>
gunbc-ci-auto-heal and others added 6 commits October 4, 2026 06:11
…tter's reading; the interpreter's after #13228)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…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>
@gunbai-bot

gunbai-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Addressed at d2021c086ba. This head also merges #13211's f48396fe6da, which carries #13206's RouteLegStanding split.

1. Collect stage implemented but not wired.

  • CollectInstruments and ObservationOnly now carry collection: RouteLegStanding.
  • stage_legs returns that standing, so route_is_executable cannot become true without the collector edge.
  • mtcollins1_collect_leg is LegAuthorityImplemented { collect_qualification_instruments, wiring_owed }.
  • qualification_instrument_extraction_frontier_rows has a fourth row: FloorPhaseRows/FloorCgroupRows have an implemented authority and no production consumer until the route invokes the collector.
  • The route witness asserts the leg names the collector and is not wired.

2. Cross-wirable target, run and slot.

  • collect_qualification_instruments(dispatched, collection, registration) takes no target, run or unit argument.
  • QualificationExtractionSubject is sole_constructor. It is minted only by qualification_extraction_subject, which checks the inputs through designated_floor_job before any read:
    • dispatched run id vs collected run id → SubjectRunMismatch;
    • attempt on both sides, and the registration's host-unit slot attempt → SubjectAttemptMismatch;
    • a microVM slot → SubjectSlotNotAHostUnit.
  • The cgroup unit is subject.slot.unit.
  • REDs: a_dispatch_of_another_run_refuses_the_subject, a_slot_of_another_attempt_refuses_the_subject.

3. Forgeable success that loses its evidence.

  • QualificationJobLogReceipt is sole_constructor. It carries the subject, log_code_points, the log_digest (content hash of the complete body) and the readings.
  • It is minted only in job_log_standing, which is admit_callers: [collect_qualification_instruments] and runs after the network read.
  • The decoder decode_job_log_instruments stays open and identity-free.
  • designated_job_log refuses a log of any other job (JobLogOfAnotherJob), an unreadable log and an empty log. Witness: a_log_of_another_job_is_not_the_floor_jobs_log.
  • Compile-census probes, run locally with the interpreter:
    • forged receipt literal → SoleConstructorViolation = 1;
    • forged subject literal → 1;
    • outside call to job_log_standing → ConstructorCallAdmissionRefused = 1;
    • positive control calling the decoder → 0.
  • Rung: checked once, not enrolled. Nothing re-runs these probes, so this is not claimed as an enforced wall at this subject. A probe against these declarations is ReadsLiveTree, which the required floor declines rather than executes (gunbc.qualified_pipe_callee_seed_growth). The SubstrateInputsOnly harnesses compile only self-contained modules, so they would test the compiler's generic wall, not this seal. Next-rung trigger: the floor can enrol and execute a ReadsLiveTree compile-refusal probe. The same statement is on QualificationJobLogReceipt's annotation (head 3199c077fdd).
  • Length is recorded in code points, named as such, because the transport hands over a decoded string; a UTF-8 byte count over a 1.5 MB log in .dag was not worth its cost.

4. Rows from different jobs combined.

  • The floor job is the one served job whose runner_name equals the authorized registration's JitRegistration.name, which the mint fixed before GitHub answered. Zero such jobs → NoJobOnRegisteredRunner, which lists the runner names seen. Two or more → SeveralJobsOnRegisteredRunner.
  • Only that job's log is read. Rows can no longer be pooled across jobs.
  • WorkflowJobRun regains runner_name (nullable upstream) with this consumer in the same change, as its annotation required. The 28 existing literals carry none.
  • Witnesses: the_floor_job_is_the_one_the_registered_runner_ran (two served jobs, picks the one on the registered runner), zero_or_two_jobs_on_the_registered_runner_refuse, rows_split_across_two_jobs_are_not_one_measurement.

5. Overclaiming result and field types.

  • QualificationInstrumentsRead is gone. QualificationCollectStage { job_log: JobLogInstrumentStanding, claim_cost: ClaimCostArtifactRead } gives a standing per source; the guest-idle and cohort instruments are not in the payload and remain rows.
  • FloorPhaseTimed.wall is std.measure Millisecond.
  • The three new operations use 5xx.
  • Also took the suggestion: a download 410 now maps to ClaimCostArtifactExpired.

Evidence:

  • 18/18 runner_qualification_dispatch_witness_test and 29/29 runner_throughput_qualification_witness_test pass under the interpreter.
  • The inhabitance claim now runs the decoder over the recorded run's bytes.
  • Exact-head required CI is pending.

gunbc-ci-auto-heal and others added 2 commits October 4, 2026 06:45
…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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact head 3199c077fdd92fffd39e5f46ad6a9953b79ce3ca.

The five leg-3b findings on 3be84a5 are substantially improved:

  • the collect stage now has an explicit LegAuthorityImplemented standing and participates in route_is_executable;
  • target/run/slot inputs have been replaced with a sealed QualificationExtractionSubject and 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_ms is typed as Millisecond, the REST interfaces use 5xx, 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.

gunbc-ci-auto-heal and others added 2 commits October 4, 2026 07:42
…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>
@gunbai-bot

gunbai-bot Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

Review 75456 (ActionsArtifact.size_in_bytes: Int) is fixed at ffc3edb4397, by removal rather than by ByteSize.

Nothing in the change reads size_in_bytes, and the same is true of archive_download_url, created_at and expires_at. The claim-cost read only finds the artifact by name, refuses on upstream's expired flag, and downloads it by id. Under DESIGN §3c, a field with no consumer is dangling, and this module's neighbours already decline unread upstream fields (extdeps.github.workflow_runs). So ActionsArtifact is now { id, name, expired }, and its annotation says a size that is one day read arrives as std.measure ByteSize.

The same head merges #13211 a20fb39695e. Its collection now joins the floor job to the minted runner, so this PR's second join (designated_floor_job and QualificationExtractionSubject) is deleted. The receipt now carries the sealed CollectedQualificationRun plus the registration's host-unit slot, and the log and artifact reads are token-bound beside read_run_with. The join refusals are witnessed once, by #13211's claims against decide_floor_job / decide_qualification_run.

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>
@gunbai-bot

gunbai-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

The review on 4872c1e (the _under bypass) is addressed at 3641482933.

  • collect_qualification_instruments_under now takes only the sealed collection and the token. It derives the job id and run id from collected.floor_job and collected.dispatched.receipt, and admits only collect_qualification_instruments, which runs collect_read_plan first. A caller can no longer read a genuine collection under an unadmitted token, or pair it with another run's id.
  • read_claim_cost_artifact, the other exported read entry with a free token and run id, now admits only _under.
  • Compiler REDs: the enrolled forged probe adds two forgeries. (c) is an outside call to _under; (d) is a free-token, other-run claim-cost read. the_reads_refuse_a_caller_other_than_the_checked_entry and the_claim_cost_read_refuses_a_free_token_and_run_id require ConstructorCallAdmissionRefused at each name, and the names-only control is extended to stay at zero for both.
  • Discriminating control (run locally): removing _under's admit list turns exactly that claim red (TTTFT). The source is restored.
  • Exported read entries that remain: collect_qualification_run and collect_qualification_instruments, both gated by the token join. The *_with reads in gunbc.github_effect_perform are generic primitives, like read_run_with, and mint nothing sealed.

Local results: 20/20 dispatch witnesses and 5/5 forged-probe witnesses pass.

gunbc-ci-auto-heal and others added 2 commits October 5, 2026 00:46
…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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_under admits only collect_qualification_instruments, whose token/registration read-plan check precedes the call. The helper now derives both job_id and run_id from the sealed collection; neither can be supplied independently.
  • read_claim_cost_artifact admits only that confined helper. job_log_standing remains 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:

  1. gunbc.runner.runner_qualification_dispatch::collect_qualification_run_under is 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 mints CollectedQualificationRun without the token/registration comparison. The check in collect_qualification_run remains optional to an outside caller. The downstream instruments guard does not repair the provenance of that upstream collection.

  2. gunbc.runner.runner_jit_perform::receive_jit_mint is still unrestricted. It seals independently supplied dispatch and outcome into BoundJitCredential. A holder of delivery B's genuine credential/runner id and authorized dispatch A can reconstruct JitConfigMinted from 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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 5, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 5, 2026
gunbc-ci-auto-heal and others added 9 commits October 5, 2026 05:30
… 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>
…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>
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 5, 2026
…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>
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 5, 2026
gunbc-ci-auto-heal and others added 2 commits October 5, 2026 12:51
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 briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 5, 2026
@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 6, 2026
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 6, 2026
@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 6, 2026
@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Oct 6, 2026
@gunbai-bot
gunbai-bot Bot removed this pull request from the merge queue due to a manual request Oct 6, 2026
@gunbai-bot

gunbai-bot Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up before queueing: this PR adds import v2.std.optional, but #13388 re-homed that module to std.optional, so it no longer resolves on main. The PR's own run may pass because it predates main's change. In the merge queue it will fail the floor (unresolved import: module 'v2.std.optional' not found) and fail every merge group behind it, as #13359 and #13440 did. Please merge main in and repoint those imports to std.optional before enqueueing. — sent from swift-bat-828

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant