Repository navigation
ci: light PR set, heavy suites after merge (CR-233) - #477
Closed
luisleo526 wants to merge 8 commits into
Closed
luisleo526 wants to merge 8 commits into
luisleo526 wants to merge 8 commits into
Conversation
A. Pull requests: authz, changes, fast preflight, one Ubuntu Release smoke, docs build, and the existing corpus-parity subset. Preflight is split by tier: preflight keeps the source, documentation and policy checks and no longer installs Python or pytest; the build-driving stages (verifier-tests, kernel-residuals-tests, unittest-shards-tests, run-json-harness-tests) move to preflight-slow. B. Off the pull_request trigger, nothing is dropped: preflight-slow, build Debug, both macOS legs, sanitizers, kernel-only, all three native-live profiles (exclude_slow: false) and a new corpus-parity full caller run on push to main, the new 01:30 UTC nightly schedule and workflow_dispatch. Job ids and check names are unchanged; no timeout-minutes is added; the build matrix keeps its literal ["self-hosted","pf-gcp-pr"] runner and the hosted macOS exception. The PR Release smoke builds a new pineforge_pr_smoke target (twelve existing test executables, refused if missing, disabled, skippable or labelled slow/private_fixtures) and runs ctest -L '^fast$' --no-tests=error. The compiler cache is ccache-main-<os>-<arch>-<type>-: PRs restore the newest main save by prefix and never write, only a successful main run saves. Pins and refusal tests: ci_preflight.py pins the trigger set, the build strategy, the tier split, the smoke command, the cache steps and the twelve fast rows by sha256; each new refusal asserts its mutation changed the input first, and the build aggregate gets a truth-table test over every lane and event. docs/ci.md carries the new trigger map and marks the D1/D3 PR split historical. Known gap, left unchanged on purpose: corpus-parity.yml keeps its own path-filtered pull_request trigger, and its full job is gated only on `inputs.mode != 'subset'`, so on that standalone event it still runs full parity. Closing it needs a decision on that workflow's triggers. Co-Authored-By: Claude Code <[email protected]>
…233 B gap)
corpus-parity.yml kept a path-filtered pull_request trigger, and its full job
was gated only on `inputs.mode != 'subset'`, which is true on a standalone PR
event, so a PR touching the corpus pin or the parity tooling still ran the
whole 312-probe population. Remove that standalone trigger: full parity now
runs on the nightly schedule, on workflow_dispatch, and on the full-event
pipeline; the PR early signal is the subset ci.yml calls. The full job also
gains `github.event_name != 'pull_request'` so a reusable-workflow caller
cannot reintroduce it. Nothing is dropped: schedule, workflow_dispatch,
workflow_call and the subset job are unchanged.
Pin it in ci_preflight with corpus_parity_trigger_findings: the on: block must
be exactly {schedule, workflow_dispatch, workflow_call} (no commented-out
trigger keys) and the corpus-parity job must carry exactly one if: value
excluding pull_request callers, compared canonically (whitespace removed) so a
`|| true` short-circuit is refused too. Nine refusal tests in PreflightFailures
load the real workflow, mutate only their in-memory copy, assert the copy
changed, and assert the finding; one acceptance test asserts the unmodified
file and the whole workflow contract stay clean.
The docs/ci.md sentence rewrite here replaces text introduced by 21ba62b,
03b2406 and b816635 describing the old pull-request routing of full parity;
the deleted sentence is deliberate, not a doc revert.
Tests not executed on the supervisor's Mac (LB-446 repo-script refusal): the
engine PR's own preflight run is their first execution, and no pass is claimed.
Co-Authored-By: Claude Code <[email protected]>
Comment on lines
+600
to
+602
| self.assertTrue({'doc-lint', 'doc-anchors', 'doc-reverts', | ||
| 'ci-workflow-contract', 'preflight-tests'} <= | ||
| {entry[0] for entry in fast}) |
Comment on lines
+603
to
+604
| self.assertTrue({name for name, _ in ci_verify.source_guard_commands(ROOT)} <= | ||
| {entry[0] for entry in fast}) |
The owner's rule: a PR whose diff is only .github/** runs authz, actionlint, ci-policy-check and preflight's workflow-contract stages, not the build, test, sanitizer or parity legs, which stay post-merge on main. The path class is decided twice from the API. The changes job publishes a scheduling hint; the required build aggregate repeats the read itself, bound to the event's PR number, repository, head and base, every /files page and both rename sides, and never trusts needs.changes.outputs.github_only. Empty, truncated, malformed or unreadable diffs and a diff that moves mid-read fail closed before the verdict step. scripts/ci_*.py stays out of the class: mixed diffs follow the ordinary PR plan. docs.yml no longer builds Doxygen for .github-only PRs. Red-first mutations in scripts/test_ci_preflight.py: a src/ diff with the heavy legs skipped fails; a .github-only diff with them skipped passes; a workflow + scripts/ci_preflight.py diff fails; empty/unreadable input fails before the aggregate runs. Each asserts its own fixture changed, runs the workflow's inline reader in a real Python child (transport bytes mocked only) and uses its actual exit status. Nothing was executed on the Mac: py_compile and git diff --check only. Co-Authored-By: Claude Code <[email protected]>
The first CI run on 0d63b1b died in configure, before any test ran: CMake Error at tests/CMakeLists.txt:7121 (message): PR fast row or executable is missing: test_integration test_integration is in L3A_LEGACY_OWNER_TEST_SOURCES, which line 723 removes from TEST_SOURCES unconditionally, so a source-layer configure registers no such test or target and the guard fired. The other eleven names in PINEFORGE_PR_FAST_TESTS each survive that removal and are appended to TEST_SOURCES or registered directly, so the list keeps them. The guard itself did its job: it refused a fast set that names a row the build never registers.
Comment on lines
+617
to
+618
| self.assertTrue({plan_name for plan_name, _ in plan} <= | ||
| {name for name, _ in check_commands(ROOT, tier='fast')}) |
FLEET-POST=A (owner, laneboss bulletin #1083): a post-merge fleet of four
runners labelled ["self-hosted","pf-gcp-post"] admits only push, schedule and
workflow_dispatch on engine main and refuses every pull_request. This splits
CI by event at file level so no job picks a label from github.event_name.
- ci.yml is now pull_request only: authz, changes, preflight, build (Ubuntu
Release), corpus-parity-subset, build-gate.
- ci-post.yml is new and carries every full-event job: authz, changes,
preflight, preflight-slow, build (Ubuntu Release/Debug), build-macos,
sanitizers, kernel-only, native-live, corpus-parity(-subset), build-gate.
- corpus-parity.yml, native-live.yml, docs.yml lose their post-merge events;
corpus-parity-subset.yml and docs-post.yml are their post counterparts.
- macOS is the sole hosted exception (laneboss ci-labels.md, LB-535): the two
macOS post cells run as their own build-macos job on hosted macos-26 with no
PF_CI_LABELS, and build-gate requires both build results. All four check
names stay byte-identical.
- scripts/ci_preflight.py: POST_RUNNER, per-workflow event routes followed
through local reusable calls to a fixed point, HOSTED_JOB_RUNNERS pinning
exactly {ci-post.yml: {build-macos: macos-26}}, a split-aware
POST_BUILD_STRATEGY, and a job inventory that pins build-macos.
- scripts/test_ci_preflight.py: four red-first tests (macOS on the Linux post
fleet, all four rendered check names preserved, hosted exception refuses any
unallowlisted job or widened label, the exception never applies to a
pull_request-reachable workflow or reusable caller).
- docs/ci.md and .github/actionlint.yaml record the routing and the label.
The live policy checker's R6 still flags pf-gcp-post until laneboss posts
LB-535; that finding is ACCEPTED for now and named in the PR body, not
suppressed in code.
cfda278 dropped test_integration from PINEFORGE_PR_FAST_TESTS because L3A_LEGACY_OWNER_TEST_SOURCES removes it unconditionally and the source-layer configure registers no such test or target. The guard itself was correct; the pin that measures that list was not moved with it, so every preflight run on 6605c80 reported one extra finding against the real tree: PR fast rows must keep one pinned CMake label list and executable build target (scripts/ci_preflight.py:1371-1375) The pin is the lockstep partner of cfda278, not a checker change. Recomputed over the eleven rows exactly as fast_rows() builds them, '\n'.join(rows) + '\n', reading tests/CMakeLists.txt: old c6ec80674daf15ea1cc5d390acdf5f1098620a7fad65a86dfbe5e12fbe29b568 = the twelve-row list with test_integration between test_native_run_spec and test_native_bare_host_contracts new 0509b2219786efb6878b193639344c299ff8075ba4532dbe09e80e6e97b60a9a = the eleven rows that remain The checker was not touched. docs/ci.md:57 already says eleven, and the tests already name exactly those eleven rows (scripts/test_ci_preflight.py:944-950); no count of twelve for this list remained anywhere in the tree. Co-Authored-By: Claude Code <[email protected]>
The proof on 6605c80 failed four rows in every compiled profile (test_ci_preflight, test_two_world_registration, test_two_world_registration_controls, test_private_fixture_reads_controls). test_ci_preflight is the separate fast-row pin (64137d8); the other three share ONE cause: check_two_world_registration: tests/CMakeLists.txt: unmodelled condition 'NOT TEST ${_pf_fast_test} OR NOT TARGET ${_pf_fast_test}' f82ef8a added the fast-row guard if(PINEFORGE_BUILD_SOURCE_LAYER AND (NOT TEST ${_pf_fast_test} OR NOT TARGET ${_pf_fast_test})) The walk already evaluates NOT/AND/OR with CMake precedence, but _atom() only stripped the enclosing parentheses and then handed the whole group to split_values(), which saw seven tokens and refused it. So a legitimate, already-supported shape was reported as unreadable and every two-world control inherited the exit 2. Fix: after the parentheses are stripped, re-dispatch through _or() when the remaining text still splits on top-level AND/OR. Nothing else changes; a token sequence that is not a modelled predicate still raises Unreadable. The refused class is fail-closed, so this widens the model, it does not silence a finding. Not executed on the Mac: LB-446 refuses repo Python here, so the first check is the next CI/proof run on this head. The rows that exercise it are the real-tree cleanliness test and the private-fixture control pair above. Co-Authored-By: Claude Code <[email protected]>
Collaborator
Author
luisleo526
added a commit
that referenced
this pull request
Oct 22, 2026
…, squash of #477) (#480) One tree-identical squash of the CR-233 branch (PR #477), on engine main 20267dd, so that the doc-reverts gate judges the change once, against main, with this message. It replaces the branch's eleven commits (f82ef8a, 0d63b1b, b4a98a4, cfda278, 9f33e1b, a merge of main, 64137d8, ab12867, 60bcfe2c, 8c2386ed and the control test 077d3ebb); the branch is kept as ci/cr233-pr-split-r2. What changes: - ci.yml keeps only the PR wall (authz, changes, preflight, Release/Debug build, corpus-parity-subset, build-gate); the full-event jobs (preflight-slow, macOS build, sanitizers, kernel-only, native-live, full corpus parity) move to ci-post.yml on pf-gcp-post; docs build/deploy split into docs.yml and docs-post.yml; corpus-parity-subset becomes its own workflow. - scripts/ci_preflight.py, its tests and docs/ci.md follow the split (runner contract, PR vs post aggregates, PR_PROOF_JOBS, PR fast rows). - scripts/check_two_world_registration.py models a parenthesised boolean group and get_test_property (property reads bind NOTFOUND); tests/CMakeLists.txt carries the PR-fast-rows guard; control tests 21 and 22 cover both. doc-reverts: docs/ci.md rewords or drops sentences introduced by earlier commits on main. They are named here: a8089b2 (the GCP fleet routing, #474), 21ba62b (native-live and the Ubuntu Debug leg as pool-only checks, #464), 03b2406 (release jobs on pf-ci-release, #461), 3c19a69 (Linux x64 jobs on the pf-ci-spot pool, #420), 133f571 (1.0 prep, docs-only CI skip, #303), d3cca9e (docs: migration semantics, publication guards), eed6598 (defer macOS Debug from pull requests, CR-195, #454). Each deleted sentence is superseded by the PR/post split described above; none is a silent revert. Proof: the previous head of this tree failed CLOUD proof rj-20261021t210656-9f91b8 on the causes fixed here (get_test_property unmodelled in the two-world walk, a stale macOS anchor, a stale aggregate lane list); this commit has not been run by its author, the next CLOUD proof is its first run. Co-authored-by: Claude Sonnet 5.5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 25, 2026
Two textual conflicts, one semantic follow-up: - .github/workflows/native-live.yml: main added strace to the native build dependencies, this PR added git-lfs; the install line keeps both. - scripts/ci_verify.py EXCLUDED_REGISTERED_MIN: main's native floor is 963, this PR adds one native runner row, so the floor stays 964; main's reworded D1 comment is kept. - scripts/test_ci_verify.py: main's test_the_native_profile_is_not_under_this_rule (not in the PR's base) ran the native profile at 963 registered and 963 rows; with this PR's row the tree registers 964, so the test runs at 964/964. Doc deletions that arrive from main with this merge, named for check_doc_reverts (they are main's own edits to docs/ci.md, not changes made here): six sentences deleted or reworded by 717c75d (promote-baseline refuses untrusted heads and actors, #482) and by 3a0d150 (the CR-233 split of the PR wall from full-event verification, #477): "Only after those checks can an unmerged close pass without a merger lookup and skip `promote`", "The trigger has no `branches:` filter and the guard does not require a `main` base ref", "Release and promotion are unchanged:", "The same stage pins the complete shared `promote-guard` block byte for byte", "Decision tests execute the guard script extracted from the real workflow with bash and an executable `gh` stub first on PATH", "Mutation tests alter the real promotion workflow to replace the script with `exit 0`". Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526
pushed a commit
that referenced
this pull request
Oct 25, 2026
…e runner split rewrites (3a0d150) test_release_ruleset_probe_workflow_is_installed_and_pinned still expected the probe's authz job on the PR fleet; it now expects the pinned hosted image, matching RELEASE_JOB_RUNNERS. docs/ci.md rewrites routing sentences that 3a0d150 (ci(cr233): split the PR wall from full-event verification, squash of #477) introduced, because the routing they describe changes with this PR: "No job chooses its label by event."; "`corpus-parity-subset.yml` is reusable only from the PR pipeline;"; "`corpus-parity.yml` keeps full parity and the full-event subset on the post fleet."; "The checker follows local reusable calls, so a PR caller cannot borrow a post workflow even behind a job condition."; "FLEET-POST=A (laneboss bulletin #1083, CR-233 ADD 2) supersedes the earlier non-release fleet policy."; "Each non-release workflow has one event class and one literal scheduler array, including authz, classification and aggregates:"; "The fleet is inferred from events and caller reachability, independently of workflow file names and job conditions."; "The command table pins job inventory and core-count usage, without assigning fleets by file name." The big and credentialed jobs keep the fleet routing those sentences described; only the named light jobs move to the hosted image. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 25, 2026
… (CI-RUNNER-SPLIT, R309 + R312) (#514) authz, changes and the aggregate `build` gate of ci.yml and ci-post.yml, the authz job of corpus-parity, corpus-parity-subset, docs, docs-post, native-live and release-ruleset-probe, and the docs build now run on `ubuntu-24.04`. The big jobs (preflight, build/sanitizer/kernel matrices, corpus parity, native-live) stay on the pf-gcp fleet, and the credentialed jobs (docs-post build, promote, release, notify-hub, probe) stay internal. Nothing else in the workflows changes. scripts/ci_preflight.py pins exactly these jobs to the hosted image and still refuses a big or credentialed job on a hosted label and any unlisted label; its tests (including the probe workflow pin), docs/ci.md and the release-gate test's routing prose follow. Fork pull requests on hosted runners run without our secrets, so the VM-only fork-refusal hook is not needed for the moved jobs. Rollback is relabelling a job back to its pf-gcp label. AGENTS.md follows in its own docs PR. docs/ci.md rewrites routing sentences that 3a0d150 (ci(cr233): split the PR wall from full-event verification, squash of #477) introduced, because the routing they describe changes with this PR: "No job chooses its label by event."; "`corpus-parity-subset.yml` is reusable only from the PR pipeline;"; "`corpus-parity.yml` keeps full parity and the full-event subset on the post fleet."; "The checker follows local reusable calls, so a PR caller cannot borrow a post workflow even behind a job condition."; "FLEET-POST=A (laneboss bulletin #1083, CR-233 ADD 2) supersedes the earlier non-release fleet policy."; "Each non-release workflow has one event class and one literal scheduler array, including authz, classification and aggregates:"; "The fleet is inferred from events and caller reachability, independently of workflow file names and job conditions."; "The command table pins job inventory and core-count usage, without assigning fleets by file name." The big and credentialed jobs keep the fleet routing those sentences described; only the named light jobs move to the hosted image. Supersedes PR #512 (same change; its first commit lacked the 3a0d150 naming, which the doc-reverts check requires per commit and a later fix commit cannot supply; no force-push, so this is a new branch with the whole change in one commit). Co-authored-by: Claude Sonnet 5.5 <[email protected]>
luisleo526
added a commit
that referenced
this pull request
Oct 25, 2026
…513) * docs(agents): the CI routing paragraph names the hosted light jobs (companion to the runner split) AGENTS.md lines 16-18 now say that the big jobs stay on the pf-gcp fleets, the secret-free light jobs (authz, changes, build gates, the docs build) run on the pinned hosted image ubuntu-24.04, and rollback is relabelling. Three lines replaced by three lines: the file keeps its 160 lines, so the content-hashed doc anchors do not move. Lands right after the runner split PR; until then the file describes the old routing. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> * ci: run the light secret-free CI jobs on a pinned GitHub-hosted image (CI-RUNNER-SPLIT, R309 + R312) (#514) authz, changes and the aggregate `build` gate of ci.yml and ci-post.yml, the authz job of corpus-parity, corpus-parity-subset, docs, docs-post, native-live and release-ruleset-probe, and the docs build now run on `ubuntu-24.04`. The big jobs (preflight, build/sanitizer/kernel matrices, corpus parity, native-live) stay on the pf-gcp fleet, and the credentialed jobs (docs-post build, promote, release, notify-hub, probe) stay internal. Nothing else in the workflows changes. scripts/ci_preflight.py pins exactly these jobs to the hosted image and still refuses a big or credentialed job on a hosted label and any unlisted label; its tests (including the probe workflow pin), docs/ci.md and the release-gate test's routing prose follow. Fork pull requests on hosted runners run without our secrets, so the VM-only fork-refusal hook is not needed for the moved jobs. Rollback is relabelling a job back to its pf-gcp label. AGENTS.md follows in its own docs PR. docs/ci.md rewrites routing sentences that 3a0d150 (ci(cr233): split the PR wall from full-event verification, squash of #477) introduced, because the routing they describe changes with this PR: "No job chooses its label by event."; "`corpus-parity-subset.yml` is reusable only from the PR pipeline;"; "`corpus-parity.yml` keeps full parity and the full-event subset on the post fleet."; "The checker follows local reusable calls, so a PR caller cannot borrow a post workflow even behind a job condition."; "FLEET-POST=A (laneboss bulletin #1083, CR-233 ADD 2) supersedes the earlier non-release fleet policy."; "Each non-release workflow has one event class and one literal scheduler array, including authz, classification and aggregates:"; "The fleet is inferred from events and caller reachability, independently of workflow file names and job conditions."; "The command table pins job inventory and core-count usage, without assigning fleets by file name." The big and credentialed jobs keep the fleet routing those sentences described; only the named light jobs move to the hosted image. Supersedes PR #512 (same change; its first commit lacked the 3a0d150 naming, which the doc-reverts check requires per commit and a later fix commit cannot supply; no force-push, so this is a new branch with the whole change in one commit). Co-authored-by: Claude Sonnet 5.5 <[email protected]> --------- Co-authored-by: ci-cx <ci-cx@invalid> Co-authored-by: Claude Sonnet 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CR-233 (owner CI-2 = A+B, #1050): a light pull-request set for the engine. Heavy suites move to push:main, nightly and workflow_dispatch; nothing is dropped.
scripts/test_ci_preflight.py.corpus-parity.ymlloses its standalonepull_requesttrigger. The subset measured 598 s on 2 vCPU with a cold cache, over the 6-minute line, so it moves to the lab-status path. Corpus parity on PRs stays gated by the requiredpineforge/paritystatus. Test:test_corpus_parity_rejects_readded_pull_request_trigger.Still to come on this PR (owner, 10-22 02:20): a PR whose diff is only
.github/**runs only authz, actionlint, ci-policy-check and preflight's fast workflow-contract stages. The required aggregate computes the changed paths itself and fails on any skipped heavy leg unless the diff is.github-only.scripts/ci_*.pyis not.github-only. This comes with mutation tests.This branch is the rebase of ci/cr233-pr-split onto a8089b2 (#474) as a new branch (tree unchanged by the rebase). The refusal tests run for the first time in this PR's preflight.
🤖 Generated with Claude Code