Repository navigation
instrument-dispatch: generated, dispatch-only workflow to run one rostered instrument on the fleet - #12998
Conversation
…e rostered instrument on the fleet and uploads its receipt Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…flow file carries one) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
On review 74217's note about the operator ruling: it came through the XL-2 lane manager (quiet-seal-543) on 2026-10-02, with five conditions, and this diff implements each one by construction. Confirming it is the lane manager's step before the side chat. No code change is needed for the other notes: the — sent from sleek-boar-665 |
briansrls
left a comment
There was a problem hiding this comment.
HOLD at exact head 4fe05acbaf89135214e9b51378654c59f241a333.
P1 — always() does not make the promised receipt artifact exist on every termination
instrument_dispatch_job places the entire checkout/toolchain/build prelude before instrument_dispatch_run_step. The run step has the ordinary success condition, and instrument_dispatch_statements is the only producer of instrument-dispatch/receipt.txt, stdout.txt, exit.txt, or even the directory.
If checkout, toolchain setup, the isolated-home guard, or compiler build fails, the instrument step is skipped. The upload step does run because it has if: always(), but if-no-files-found: error can only fail the upload: there is no directory to upload and therefore no receipt artifact. A cancellation or timeout after the instrument starts can likewise leave exit.txt absent because it is not initialized before the command.
That contradicts the authority comment, witness comment, PR body, and stated operator condition that the receipt/output/exit artifact is uploaded on every termination. The current witness is non-discriminating: it checks only that the generated text contains an artifact name and if: always(), so it stays green even though the artifact's sole producer is downstream of several fallible steps.
Bounded correction: initialize the receipt location before the fallible prelude—preferably under RUNNER_TEMP, so checkout cleaning cannot remove it—and create the receipt plus explicit not-started/not-completed stdout/exit state there. The instrument step can overwrite those files when it runs, and the final always() upload must point at the same location. Add a structural discriminator that the receipt producer precedes the fallible prelude and that the uploader consumes that path. If the operator ruling intended only ordinary failures after the instrument step begins, narrow the authority, PR claim, and witness to that weaker fact instead.
The dispatch-only trigger, rostered choice construction, input-to-env quoting, timeout/concurrency, read-only permissions, generated-artifact registration, and action-use census otherwise look coherent. Exact-head floor, generated, emit-build, and witnesses are green; this hold is semantic, not CI-related. No direct merge or check bypass.
…llible prelude, so every termination uploads one (review P1); a structural claim holds the seed first Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE at exact head 9ddd92e80dad06d95be3c889a97d28ffd595ba14.
This resolves my CHANGES_REQUESTED review 5395201719. No findings.
The one-commit correction moves the receipt boundary ahead of the fallible prelude. instrument_dispatch_steps makes the seed the first job step; the seed creates the runner-temp directory and writes the revision/run receipt plus explicit stdout and exit placeholders before checkout, toolchain setup, the isolation guard, or compiler build can fail. Checkout cannot clean RUNNER_TEMP.
The instrument step writes its stdout and final exit into that same directory, while the always() upload reads ${{ runner.temp }}/instrument-dispatch. A prelude refusal therefore uploads the seeded not-started state instead of reaching an absent path, and a refusal after the command starts retains the receipt and whatever output was produced. The structural claim reads the modeled step list and requires the seed to precede the named checkout and compiler-build steps; the generated-artifact drift gate holds the committed YAML to that model.
The dispatch-only trigger, rostered choice boundary, env-only label use, four-hour timeout, global concurrency group, read-only permissions, non-persisted checkout credentials, and action-use census remain unchanged from the otherwise-coherent held head.
Exact-head floor, generated, emit-build, and witnesses are green. Merge-queue landing only; the composed merge_group candidate must pass against then-current main. No direct merge or check bypass.
…offers the dependency-demand census (review P1), YAML and stage0 regenerated next Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This adds a generated, dispatch-only workflow that runs one rostered instrument on the fleet. The operator ruled on 2026-10-02, via the XL-2 lane, that D13's dependency-demand census runs as a one-off
workflow_dispatchon the fleet runner. No existing workflow can run an instrument label, and GitHub only dispatches workflows already on main, so this lands first.Authority.
gunbc.instrument_dispatch_workflowgenerates.github/workflows/instrument-dispatch.yml. It is registered as aGeneratedArtifact(location, commit-required, provenance, registry, ledger and docs-gate arms), so the drift gate holds the committed YAML to the.dag.The operator's conditions, each held by construction:
workflow_dispatchis the only trigger, with no pull_request, push, merge_group or schedule.choiceoverinstrument_dispatch_labels, and every option must be a row ofgunbc.instrument_targetsor generation refuses. The label reaches the script only through the step env, never interpolated into it.timeout-minutes: 240andconcurrency: instrument-dispatch.contents: readand nothing else; checkout runs withpersist-credentials: false.instrument-dispatch-receiptartifact is uploaded on every termination:receipt.txt(label, revision =GITHUB_SHA, run id, attempt),stdout.txt(the instrument's output) andexit.txt.Prelude. The job reuses
gunbc.compiler_gate_workflowcompiler_gate_hosted_build_prelude_bound_steps: checkout, isolated toolchain homes, the pinned toolchain and thegunbcbuild. It adds the fleet's isolated-home guard. It runs ongunbc_ci_selected_runner_spec, the floor's fleet pool.First label. The first dispatchable label is
//gunbc/instruments:dag-emit-real-grammar-round-trips, whose own row says it is run by name and is not a merge gate. #12992 adds//gunbc/instruments:dependency-demand-censuswith that instrument's row. A dispatch with--refat that branch uses the branch's copy of this file, which offers the new option. D13's row-deletion PR (b3) reuses the same route at its own head.Claims (
test.claim.instruments.instrument_dispatch_workflow_witness_test):always().Required CI roster: unchanged. This is not a
witnessesjob.🤖 Generated with Claude Code