Skip to content

CI: run the full main lane on demand (workflow_dispatch), writing nothing of main's - #1785

Merged
InauguralPhysicist merged 5 commits into
mainfrom
ci-dispatch
Oct 15, 2026
Merged

InauguralPhysicist merged 5 commits into
mainfrom
ci-dispatch

Conversation

@InauguralPhysicist

@InauguralPhysicist InauguralPhysicist commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1787

What this does

ci.yml triggers on workflow_dispatch, so gh workflow run ci.yml --ref <branch> runs the full main lane on a long-lived branch before it is queued: the ASan shards, both TSan variants, native macOS, valgrind, bench, the extension suites and the db lane. A dispatch is not a pull request, so every job runs as on a push to main. The Phase 2 integration branch (draft PR #1776) had never run those lanes.

Scope, exactly. A dispatch runs the dispatched ref's own ci.yml, and its own tools/ci_tier_check.sh. The properties below hold for main's text. A branch that edits ci.yml can change them, exactly as its pull-request run already could, since a pull request also runs the branch's own workflow file. A dispatch adds no capability that pushing a branch did not already give.

What main's ci.yml writes. The only job that can write is build dev/ci image.

what where it is written
ci-<sha> image tag every non-fork run, a dispatch included
ci-main only a push to refs/heads/main whose SHA is main's tip (git ls-remote); never a dispatch from any ref, the queue, or a re-run of an older push
the buildx GHA cache the run's ref scope: a branch dispatch writes the branch's scope, a dispatch on main writes main's, as a push does
artifacts stay in the run

ci-main is the one name written here that main owns. A dispatch on main also adds runs to main's commit, but the README badge now reads push runs only (badge.svg?branch=main&event=push).

Property checks replace the text pin (finding 13)

[dispatch-write] pinned the writing job's text, so a dangerous edit cleared with the same one-line re-pin as a harmless one. WRITERS and its second hash recipe are deleted. tools/ci_tier_check.sh now checks what the writes do:

  • [ci-main] runs the step that computes the image push's tags, under bash -e, with the workflow, job and step env merged as the runner merges them. It covers:

    • events: push, pull request, merge queue, dispatch;
    • refs: main, a branch, a pull request's merge ref, the queue's ref;
    • tip state: this SHA is main's tip, is not, or the tip cannot be read;
    • fork pull requests.

    That is 52 runs. ci-main must appear exactly on a push to refs/heads/main at main's tip. Further:

    • on.push must be exactly branches: [main].
    • Each image push must take its tags from that one step, read in any case with quotes stripped.
    • The check refuses what the matrix cannot model:
      • a custom shell or directory (defaults:, shell:, working-directory:);
      • env that redirects bash or git (PATH, BASH_ENV, ENV, SHELLOPTS, BASHOPTS, GITHUB_*, GIT_*, BASH_FUNC_*, LD_*);
      • an expression it cannot evaluate;
      • a tags<< output.
  • [writer-actions]: a job that can write uses only actions/checkout, docker/setup-buildx-action, docker/login-action and docker/build-push-action.

    • Each takes only the inputs vetted for it (INPUTS). So there is no outputs:, and cache-to: is type=gha only: an outputs: or a registry cache can push any name, and a registry cache is shared across refs.
    • Identities are compared without the @ref, so Dependabot bumps stay green.
    • No ./ or docker:// action, and no reusable-workflow call.
    • No script except the tag step.
  • [secrets]: ci.yml reads no secret but secrets.GITHUB_TOKEN (dot or bracket syntax), and passes none to a reusable workflow.

  • [event-condition] is now an allowlist of the github fields whose value does not depend on the event (repository*, *_url, workspace, workflow, job, action, token, retention_days). Any other field, or a bare github, is red.

On its first run, the matrix found finding 8 in the tag step: a re-run of an older main push moved ci-main back. The step now adds ci-main only when git ls-remote origin refs/heads/main equals this SHA, does not gate on RUN_ATTEMPT, and fails loudly when the tip is unreadable.

A self-review of that first property version (e0b6e015) then found 10 edits that wrote ci-main, or redirected what the matrix models, while it stayed green: plants O1–O4, J2, J3, W1, H1, Q1 and U4 below. The final checker (f27fe34f) closes them.

PLANTS: each rule proven once (PRINCIPLES §5)

The harness copies the workflows, applies one edit and runs ci_tier_check.sh on the copy (CI_TIER_WF_DIR). "n/a" means the edit's text does not exist in f39bff9c. The pin went red on any edit to the writing job, re-pinnable as row A shows. The table is identical under bash 3.2 and bash 5.

plant before: f39bff9c pin first property version e0b6e015 final
A: finding 13 plant A: ci-main on any non-PR event red dispatch-write, but green once the hash it printed (187c693a40a0ae19) is pasted into WRITERS red ci-main red ci-main
B: finding 13 plant B: timeout 30 -> 31 in dev-image (must stay green) red dispatch-write green green
8: finding 8: the tag step without the main-tip check (the PR's old step) green red ci-main red ci-main
9a: finding 9: workflow defaults.run.shell forging the event green red ci-main red ci-main
9b: finding 9: workflow env BASH_ENV green red ci-main red ci-main
P: on.push widened to release/* green red ci-main red ci-main
U1: finding 1: build-push-action swapped for another action green red ci-main, writer-actions red ci-main, writer-actions
L: finding 1: login-action swapped for a local ./ action green red writer-actions red writer-actions
D: a docker:// action in the writing job red dispatch-write red writer-actions red writer-actions
R: a script step pushing ci-main in the writing job red dispatch-write red writer-actions red writer-actions
U2: finding 5: a PAT pushes ci-main from a read-only job green red secrets red secrets
S: a secret in bracket syntax green red secrets red secrets
E1: finding 6: github.ref_protected green red event-condition red event-condition
E2: finding 6: github['ref_protected'] green red event-condition red event-condition
E3: finding 6: endsWith(github.workflow_ref, ...) green red event-condition red event-condition
E4: control: github.ref == (red in all three) red event-condition red event-condition red event-condition
O1: build-push outputs: pushes ci-main without tags: n/a green red writer-actions
O2: build-push cache-to: a registry cache (shared across refs) n/a green red writer-actions
O3: build-push cache-to: gha plus a registry line n/a green red writer-actions
O4: checkout repository: (origin is no longer this repo) n/a green red writer-actions
J1: job env from the event, read by the tag script n/a red event-condition red ci-main, event-condition
J2: job env PATH (a committed fake git) n/a green red ci-main
J3: step env GIT_CONFIG_* (insteadOf redirects origin) n/a green red ci-main
W1: tag step working-directory: n/a green red ci-main
H1: ci-main on a dispatch via a TAGS<<EOF output n/a green red ci-main
Q1: ci-main on a dispatch as a quoted tag n/a green red ci-main
U4: ci-main on a dispatch via an upper-case TAGS= line n/a green red ci-main
C4: control: a new platforms: value on build-push n/a green green
C5: control: a plain job env value n/a green green
C1: control: a Dependabot SHA bump of build-push-action green green green
U3: control: actions/cache in a read-only job green green green
T: control: the tree green green green
ci-tier: OK — ci.yml jobs=23 (awk=23) required=18 worker=5; 21 required names, each produced once on pull_request+merge_group; 26 jobs on required paths, no push-only condition, no continue-on-error; ci-main only on a push to main at its tip (52 event x ref x tip runs); 1 writing job(s), allowlisted actions and inputs only; no secret but GITHUB_TOKEN
ci-tier: SELFTEST OK — a heavy suite deferred on merge_group/push-only work is rejected

Size of tools/ci_tier_check.sh: 221 lines on main, 241 with the text pin (f39bff9c), 340 now. The property checks cost about 100 lines more than the pin they replace.

Other changes

  • Bench (finding 3). A dispatch is measured against the branch's merge-base with main, which is what the queue measures, not main's tip. The step prints both.
  • Concurrency (findings 4, 11). Dispatch groups (ci-dispatch-<ref>) never cancel in progress: a newer dispatch waits, and a third replaces the waiting one before it starts any job. The text now says:
    • one run per concurrency group;
    • group names compare case-insensitively;
    • a later push does not stop a dispatch (use gh run cancel, which leaves the cancelled run's aggregators failing on that commit, as documented).
  • Where results show (finding 4). In the dispatch run. GitHub's status rollup leaves workflow_dispatch suites out (measured on 82522fc4: 49 dispatch check runs, rollup null), so a dispatch neither appears among a PR's checks nor gates it.
  • Self-test base (finding 12). precheck's comment and SKIP message, and docs/CI.md, cover origin/main on a dispatch.
  • bash 3.2. The checker now runs the tag step, and precheck runs the checker, so ${OWNER,,} failed 51 of the 52 matrix runs under macOS's bash 3.2 ("bad substitution", measured with a bash 3.2 build). The step lowercases with tr instead.

Proof on CI

Runs on this branch, in order:

run head event result
d1 38688003325 68ed2aae dispatch success: 26 jobs, every heavy worker did real work (below)
d2 38688015367 68ed2aae dispatch replaced while waiting: 0 jobs, 0 check runs
d3 38688027625 68ed2aae dispatch replaced while waiting (by d4): 0 jobs, 0 check runs
d4 38688770795 e0b6e015 dispatch success: 26 jobs, 0 failures
d5 38690563225 f27fe34f dispatch success: 26 jobs, 0 failures, the same totals as d1
38688769806 e0b6e015 pull_request success
38690560369 f27fe34f pull_request success: 19 jobs, plus the 5 heavy workers a PR defers to the queue
  • (i) A dispatch does real work. In d1, and with the same totals in d5 on the final head:

    • ASan shards: 1/1 (the long chunk, as on main's push run 38676687632), 3004/3004 and 1490/1490, with shard receipts 3 of 3.
    • linux gcc 4252/4252.
    • The extension lanes: 4494/4494 (server) and 4252/4252 (zlib).
    • db 4495/4495 and macOS 4221/4221.
    • TSan 57/57 and tsan-http 186/186, each catching its seeded race.
    • valgrind smoke 27/27.
    • jit differential 29/29.
    • No job printed deferred to merge queue.
  • Bench baseline lines from d1 (d5 printed the same two lines):

    dispatch: the merge-base of refs/heads/ci-dispatch with origin/main (e48c4a0ea8babd356fa42ee30fd6c1b9efa2aff6) is e48c4a0ea8babd356fa42ee30fd6c1b9efa2aff6
    baseline: e48c4a0ea8babd356fa42ee30fd6c1b9efa2aff6
    ok: alloc_heavy  Ir 4991215983  (0% vs ref)
    

    main has not moved since this branch forked, so on CI the merge-base equals the tip. The distinct case is proven locally. The step text extracted from ci.yml (cut before git worktree add/./build.sh) runs in a checkout made as actions/checkout makes it (git init, remote add, a depth-1 fetch), against a synthetic origin whose main moved two commits past the fork:

    • dispatch: baseline = the fork point, not the tip;
    • pull_request: baseline = origin/main;
    • merge_group: baseline = base_sha.
  • (ii) Dispatches in a row leave no failure under a required name. d2 and d3 were replaced before starting any job. On 68ed2aae, the dispatch suites carry 26 check runs with 0 failures (d1), plus 0 and 0 (d2, d3).

    For contrast, before this fix (cancel-in-progress: true), the dispatch that the next one cancelled in progress (38677615755, on 82522fc4) left FAILURE under 4 required names: asan + ubsan (full suite), db extension (postgres service), extensions (…) and macos / macos-latest.

  • (iii) This PR's run on the final head: 38690560369 on f27fe34f succeeded, and the commit's rollup is SUCCESS.

  • A ref whose ci.yml predates the trigger is refused (measured earlier on stale cloud-1159): HTTP 422 "Workflow does not have 'workflow_dispatch' trigger". So phase2-numbers must take this change (rebase or merge main) before its first dispatch.

After merge

  • The tip guard's first real run. Its git ls-remote runs only on a push to main, so the first push after this merges is its first real run.
    • Expect that run's build dev/ci image job to push :ci-main; the build-push log names the tags.
    • If the tip can't be read, it fails loudly with ::error::cannot read main's tip.
    • The command itself was run against GitHub over SSH and anonymous HTTPS, and returns the exact 40-character tip.
  • phase2-numbers needs main (merge or rebase) before its first dispatch. Then run gh workflow run ci.yml --ref phase2-numbers.
  • Two existing shellcheck findings in ci.yml's ASan receipt steps, untouched here, are filed as ci.yml: two shellcheck findings in the ASan receipt steps (SC2010 ls|grep count, SC2129 redirects) #1791.

The 15 review findings

# resolution
1 action swap past the pin [writer-actions]: actions and their inputs on an allowlist, identities compared without @ref; no ./ or docker:// (plants U1, L, D, O1–O4)
2 a dispatch runs the branch's own ci.yml stated exactly here, in docs/CI.md and in the ci.yml comment
3 bench baseline merge-base on a dispatch (d1's line, plus the local proof of the distinct case)
4 cancelled dispatches; where results show cancel-in-progress is false for dispatch groups (proof ii, with the before measurement); the docs say results show in the run and the rollup leaves dispatch suites out
5 non-token credentials [secrets] (plants U2, S)
6 the event denylist [event-condition] allowlist (plants E1–E3)
7 the real invariant docs, comments and FAIL messages say: ci-main on push + main + tip; ci-<sha> from every non-fork ref
8 a re-run rolls back ci-main ls-remote tip guard, not RUN_ATTEMPT (plant 8)
9 defaults and BASH_ENV refused by [ci-main], with the rest of the env that redirects bash or git (plants 9a, 9b, J2, J3, W1)
10 a dispatch on main and the badge badge.svg?branch=main&event=push; the claim is limited to non-main refs, and what a dispatch on main writes is stated
11 concurrency text one run per group, case-insensitive names, gh run cancel
12 self-test base wording precheck and docs/CI.md
13 altitude property checks replace the text pin (plants A, B)
14 no Done-when Closes #1787, which carries the checklist
15 duplicated hash recipe WRITERS/writer_pin deleted; the one remaining recipe (WAIVE) prints the new hash when a waived script changes

Gates run locally (no compile)

  • ci_tier_check.sh: OK under bash 5 and bash 3.2, including its self-test; shellcheck is clean.
  • workflow_yaml_check: OK.
  • actionlint: only the two findings that are also on main.
  • precheck.sh: 16 passed, 0 failed, 3 skipped; --selftest 10/10.
  • asan_receipts_check --selftest: 3/3.
  • The plant harness: 32/32.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF

InauguralPhysicist and others added 2 commits October 14, 2026 22:41
…hing of main's

A long-lived branch (the Phase 2 integration branch, draft PR #1776) had
never run the heavy workers, which run only in the merge queue and on main
pushes. `gh workflow run ci.yml --ref <branch>` now runs them.

- ci.yml triggers on workflow_dispatch. A dispatch is not a pull request,
  so every job runs as on a push to main.
- Concurrency: a dispatch gets its own group (ci-dispatch-<ref>), so it
  never cancels a push, PR or merge-queue run on any ref, main included,
  and none of those cancels it.
- Outward writes, audited job by job: dev-image is the only ci.yml job with
  a write permission (packages: write). It advanced ci-main on any `push`
  event (safe only because push is filtered to main) and now does so only
  on a push to refs/heads/main. A dispatch pushes only its own ci-<sha>;
  the buildx gha cache is ref-scoped by GitHub, and artifacts stay in the
  run.
- gate-selftests: a dispatch carries no base sha, and `selftests.sh
  --changed ''` selects 0 rows (measured), a silent skip. An empty base now
  falls back to origin/main, so a dispatch selects what the ref changes
  against main, as its PR would. That step's waiver is re-pinned (the
  scope/detect pin is unchanged).
- tools/ci_tier_check.sh gains [dispatch-write]: every ci.yml job holding a
  write permission, its own or the workflow's (missing counts as the
  repository default), must match its reviewed pin in WRITERS. Action
  `uses:` pins are excluded, so Dependabot bumps do not reopen the review.
  Proven once with planted copies, recorded in the PR (PRINCIPLES section
  5, no permanent self-test). Each planted violation went red: a new
  writer, the ci-main gate loosened, the workflow permissions removed, a
  stale pin, and the edited select step's stale waiver. A Dependabot-style
  bump and the tree stayed green.
- docs/CI.md: when to dispatch, what runs, the commands, what it never
  touches, concurrency, where its checks show, and the new rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
…'s ci.yml

Measured: a dispatch of ci.yml on ci-dispatch (whose copy declares the
trigger) was accepted before merge (runs 38677615755, cancelled by the
newer 38677618300 in the same per-ref dispatch group), while one on the
stale branch cloud-1159 (no trigger in its copy) was refused with HTTP
422, "Workflow does not have 'workflow_dispatch' trigger". A long-lived
branch must take this change (rebase or merge main) before its first
dispatch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T03:49:48.048695Z f39bff9 PR opened
🔒 Security Review ✅ Completed 2026-10-15T03:51:37.629171Z f39bff9 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codspeed

codspeed Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 13 untouched benchmarks


Comparing ci-dispatch (f27fe34) with main (e48c4a0)

Open in CodSpeed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f39bff9cf2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yml
# writer in this file is `dev-image`, which advances the rolling ci-main tag
# only on a push to refs/heads/main, and tools/ci_tier_check.sh pins every
# job holding a write permission to its reviewed text.
workflow_dispatch:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Run the writer audit before dispatch writes

When a long-lived branch modifies dev-image so that it accidentally publishes ci-main, dispatching that branch can overwrite the shared image before [dispatch-write] reports the unreviewed hash: dev-image performs the push at lines 161–169, while the audit runs inside gate-selftests, which explicitly waits for dev-image via needs at line 197. This is a real arbitrary-ref path—gh workflow run --help defines --ref as the branch or tag containing the workflow version—so the pin currently detects corruption only after it occurs. Put the audit in a non-writing prerequisite and require every writing job to depend on it before enabling branch dispatches.

Useful? React with 👍 / 👎.

Comment thread docs/CI.md Outdated
Comment on lines +220 to +223
- **Where the results show.** The dispatch reports its checks on the branch's
head commit. If the branch has a pull request, those checks appear on it too,
under the same names as the pull-request run's, and a failure there is a real
failure of that check on that commit.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Correct where dispatch checks are displayed

When the dispatched branch has an open pull request, GitHub explicitly excludes checks from workflow_dispatch runs from the pull request's checks section and from branch-ruleset evaluation, contrary to this claim (GitHub's required-check troubleshooting documentation). An operator following this section may therefore look at the PR, fail to see the heavy-lane failure, and assume the dispatch did not run or passed; direct them to the Actions run or the gh run list result instead.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/ci.yml
# the older one.
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
group: ci-${{ github.event_name == 'workflow_dispatch' && format('dispatch-{0}', github.ref) || github.event.pull_request.number || github.ref }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Isolate the dispatch build cache from main pushes

When a dispatch on main overlaps a normal push to main, these distinct concurrency groups allow both dev-image jobs to run simultaneously, but both export cache-to: type=gha,mode=max under the same branch and the backend's default buildkit scope. Docker documents that builds sharing a scope overwrite the preceding cache (GitHub Actions cache backend), so an older dispatch that finishes last can replace the newer push's cache and make subsequent main-lane image builds cold; concurrent exporters also contend for the same cache object. Give dispatches a separate cache scope or serialize the cache-writing job even if the rest of the workflows remain independent.

Useful? React with 👍 / 👎.

InauguralPhysicist and others added 3 commits October 15, 2026 00:39
…w of #1785)

The altitude correction (finding 13): [dispatch-write] pinned the writing
job's text, so a dangerous edit cleared with the same one-line re-pin as a
harmless one (plant A, re-pinned with the printed 187c693a40a0ae19, was
green), while action swaps, a PAT and workflow-level defaults/BASH_ENV never
reached the pin. WRITERS and its second hash recipe are deleted, and
tools/ci_tier_check.sh checks what the writes do:
- [ci-main]: the step that computes the image push's tags is RUN, under bash
  -e, across event x ref x tip (52 runs, with fork PRs and an unreadable
  tip). ci-main must appear exactly on a push to refs/heads/main at main's
  tip. on.push must be exactly [main]; each push takes its tags from that
  step; a custom shell, BASH_ENV/ENV/GITHUB_* overrides and unevaluable
  expressions are refused.
- [writer-actions]: a job that can write uses only checkout, buildx, login
  and build-push (compared without @ref), no ./ or docker:// action, and no
  script but the tag step.
- [secrets]: ci.yml reads no secret but GITHUB_TOKEN, in dot or bracket
  syntax, and passes none to a reusable workflow.
- [event-condition] is now an ALLOWLIST of event-invariant github fields;
  ref_protected, ['ref_protected'] and workflow_ref were green before.
19 plants, recorded in the PR, before (the f39bff9 checker) and after:
plant B (timeout 30 -> 31) is now green, and everything that slipped past
the pin is red.

The matrix found finding 8 in the tag step on its first run: a re-run of an
older main push moved ci-main back. ci-main now moves only when `git
ls-remote origin refs/heads/main` equals this SHA (not RUN_ATTEMPT), and an
unreadable tip fails loudly.

Also:
- bench measures a dispatch against the branch's merge-base with main (the
  queue's measure), not main's tip;
- dispatch groups never cancel in progress: a newer dispatch waits, a third
  replaces the waiting one before any job starts, so no cancelled dispatch
  leaves aggregators failing under required names;
- the README badge reads push runs only (?branch=main&event=push);
- docs/CI.md: a dispatch runs the branch's own ci.yml (its PR run already
  could); what a dispatch writes, on main too; one run per group,
  case-insensitive group names, a later push not stopping a dispatch; the
  rollup leaving dispatch suites out (measured on 82522fc: 49 check runs,
  no rollup); the rule list; the dispatch self-test base;
- precheck's comment and SKIP message cover the dispatch base.

Closes #1787

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
tools/ci_tier_check.sh now RUNS the dev-image tag step, and precheck runs
the checker, so on macOS's bash 3.2 `${OWNER,,}` failed 51 of the 52 matrix
runs with "bad substitution" (measured with a bash 3.2 build). The step
lowercases with tr instead; the checker and all 19 plants now give the same
result under bash 3.2 and bash 5.

docs/CI.md: the [event-condition] allowlist is the github fields whose
value does not depend on the event (github.token is per run, so "the same
in every run" was not exact).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
Self-review of the first property version (e0b6e01) found 10 edits that
write ci-main, or redirect what the matrix models, while it stayed green.
Each is now red, with the plant recorded in the PR (32 plants, the same
table under bash 3.2 and bash 5):
- [writer-actions]: each allowlisted action takes only the inputs vetted for
  it (INPUTS); build-push-action's `outputs:` or a registry `cache-to:`
  pushes any name, and a registry cache is shared across refs (O1-O3);
  checkout `repository:` moves origin away from this repo (O4).
- [ci-main]: the matrix merges workflow, job and step env as the runner
  does (a job-level env was ignored), and refuses env that redirects bash or
  git: PATH, GIT_*, BASH_FUNC_*, SHELLOPTS, BASHOPTS, LD_* (J2, J3), plus
  `working-directory:` (W1). It reads tags= in any case with quotes
  stripped (Q1, U4) and refuses a tags<< output (H1).
Controls stay green: a new platforms: value (C4), a plain job env (C5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
@InauguralPhysicist

Copy link
Copy Markdown
Collaborator Author

Open on purpose: the fix round for the /code-review findings is in progress. The main change is that the writer text pin becomes property checks (finding 13); it also corrects the dispatch bench baseline and stops a cancelled dispatch from leaving failures under required check names. This merges through the queue after its final CI run and the dispatch proofs are in.

@InauguralPhysicist
InauguralPhysicist added this pull request to the merge queue Oct 15, 2026
Merged via the queue into main with commit 4afbd15 Oct 15, 2026
59 checks passed
@InauguralPhysicist
InauguralPhysicist deleted the ci-dispatch branch October 15, 2026 06:52
InauguralPhysicist added a commit that referenced this pull request Oct 15, 2026
Brings in #1769, #1777 (the observer oracle's floor as a required CI
check), #1770, #1786 and #1785 (the on-demand full main lane).

One conflict, tools/selftests.txt: both sides appended rows at the end of
the registry. Resolved by keeping both: main's observer_oracle/plants.py
row, then this branch's two #1758 Phase 2 rows with their comment.
`tools/selftests.sh --changed origin/main --list` accepts the merged file
(enrolment 46/46). The Makefile merged cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC99CmwatKssQYggkBCgwF
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.

CI: run the full heavy lane on long-lived branches by workflow_dispatch, without moving main's state

1 participant