Skip to content

ci: fully qualify the two remote-tracking refs the promote-baseline ancestry check and the doc-reverts default base read (ORG-ACTIONPINS-CARD) [replaces #494] - #507

Merged
luisleo526 merged 4 commits into
mainfrom
fu/qualified-refs-v2
Oct 25, 2026
Merged

luisleo526 merged 4 commits into
mainfrom
fu/qualified-refs-v2

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Replaces #494 (same commit, replayed onto the v1.7.0 tag base 77b87af403; no content change). #494 will be closed with a pointer here.

Fully qualifies the two remote-tracking refs that the promote-baseline ancestry check and the doc-reverts default base read (ORG-ACTIONPINS-CARD, LB-464 P3): .github/workflows/promote-baseline.yml, scripts/check_doc_reverts.py, scripts/ci_preflight.py and their tests.

Evidence on this head (8a9b8ed18e15c70f1ccd346e30292183f2aaf180):

Base note: main is one release commit (ed9e08ec05) ahead of this branch's base; BEHIND, not conflicting. #495's replacement also edits scripts/ci_preflight.py; if this lands first the later one takes a main merge.

🤖 Generated with Claude Code

…ncestry check and the doc-reverts default base read (ORG-ACTIONPINS-CARD, LB-464 P3)

promote-baseline.yml tested `git merge-base --is-ancestor "$MERGE_SHA" "origin/$BASE_REF"`, and
check_doc_reverts.py default_base() resolved the bare names `origin/main` then `main`. A short name resolves through
git's ref-lookup order, so a tag called `origin/main` (or `main`) would win over the remote-tracking branch or the
local branch. Both now use the fully qualified names (`refs/remotes/origin/$BASE_REF`; `refs/remotes/origin/main`,
then `refs/heads/main`, same order and same fallback to the merged-pull-request walk). The exact-text pin in
scripts/ci_preflight.py is updated to the new command and stays as strict; the old short form is now a finding.

Red-first tests: the pin refuses the short command and accepts the qualified one; a repository where a TAG named
`origin/main` points at an unrelated commit and the real remote-tracking ref points elsewhere, and the same for a tag
named `main` with no remote-tracking ref, each returns the merge base of the real ref and not the tag's. Five controls
keep the order, the environment override, the local fallback, the merged-pull-request fallback and the no-base result.
The first-parent walk is untouched (the lab-host defect is a separate card).

The default_base docstring in scripts/check_doc_reverts.py is re-wrapped around the two renamed refs; the sentences it
carries come from 1e360bd and d093560 and keep their wording, only the ref names change.

Lane: ci-fu-shortrefs (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
luisleo526 and others added 3 commits October 25, 2026 15:44
…it and #509

Brings in the release commit ed9e08e (VERSION and the run-failure catalog diff stamp) and #509
(the run-failure diff tests follow the diff's own start), which cures the red preflight test
test_gen_run_failure_catalog_diff on the tag. No change to this PR's own files.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…y, gate unchanged) [replaces #489] (#505)

* ci(release): the ruleset probe lists every branch ruleset as visible or hidden, even when the gate verdict is a refusal (CR-245 F1 measurement)

The one dispatch of release-ruleset-probe.yml from main (run 40083495967) refused on the first branch ruleset
of the inventory, the organization ruleset `default` (13094758): "returned missing or invalid bypass_actors
(token cannot see this ruleset's bypass_actors)". The verdict reader stops at the first failure, so the run
did not say whether the release App token can see bypass_actors on the repository ruleset that is the real
barrier (21476386), nor on any other. The probe now first prints one line per branch ruleset of the
includes_parents inventory (id, name, source_type, source, enforcement, updated_at, bypass_actors visible
with the actor count or hidden, applies to main, has a pull_request rule), then runs the unchanged verdict:
success prints the existing success lines; a refusal prints the same ::error:: text on stderr and exits 1,
but stdout now carries the listing. A detail read that fails is reported on its own row and the listing
continues. The listing is a measurement: `gate`, `_release_bump` and `_require_release_rulesets` are
untouched, every gate test and the existing source mutants are kept, and the probe's verdict replay over every
existing ruleset fixture still compares verdict and refusal text byte for byte. The workflow
release-ruleset-probe.yml is not changed. The listing reads each branch ruleset detail independently of the
verdict read (two reads per detail in the probe), which docs/ci.md now says.

Red-first rows: the real situation (org ruleset hidden, repository ruleset visible: both listed, the org one
hidden, refusal unchanged), both hidden, one detail read failing, all visible with a valid barrier, the
read-only call list, and a source mutant that drops the listing.

Rewrites named for the doc-reverts check, all introduced by 9c18d41 (#488, "ci(release): read-only ruleset
probe for the release gate (CR-245 F1)"): docs/ci.md "Success prints the barrier id/name and one compact
inventory line with enforcement, source and bypass visibility."; docs/ci.md "Refusal exits 1 with empty stdout
and the reader's `::error::` diagnostic; API/response failures name the endpoint."; docs/ci.md "Two hidden
rulesets need two dispatches: the first refusal names only the first hidden ruleset; make its `bypass_actors`
visible before dispatching again to identify the second." (replaced: all hidden rulesets are listed in one
dispatch); the probe docstring "Read exactly the bump's ruleset evidence, with the same refusal policy."; two
test comments ("The reader report's complete [] inventory fails on main without an endpoint." and "The
runtime assertions already hold there; the prose does not."). The module docstring sentence "Each
endpoint/page is read at most once; failures refuse without retry or sleep." (ad1ebac, #479) is scoped to the
gate's reads.

Lane: ci-fu-cr488m (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the probe listing bounds its inventory=ERROR row to 240 characters like the detail-error rows (CR-245 F1 measurement, sol P2)

The new stdout listing printed the whole exception text on an `inventory=ERROR` row, while the per-ruleset
`detail=ERROR` rows truncate it to 240 characters; a `gh` transport error with 300 characters of stderr was
echoed in full. The row now applies the same bound ([:240], still !r-escaped). Four rows assert the exact bounded
line (an inventory transport error, a repository transport error, a default-branch rejection with a long repository
argument, an invalid summary with a long field) together with the unchanged stderr, exit code 1 and API call list
of the verdict; each has a mutation control that removes only the bound and must fail. The verdict functions are
untouched and the verdict's own stderr is not bounded. No documentation sentence is changed (none described a length
limit).

Lane: ci-fu-cr488n (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…ab doc-reverts walk starts at main's last PR commit

Brings in #505 (the release ruleset probe listing: docs/ci.md, scripts/ci_release_gate.py,
scripts/test_ci_release_gate.py) on top of the v1.7.0 release commit and #509. No change to this PR's
own files; the first parent is main on purpose (CR150's merge shape).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@luisleo526
luisleo526 merged commit db58170 into main Oct 25, 2026
13 checks passed
luisleo526 pushed a commit that referenced this pull request Oct 25, 2026
Brings in #507, #506 and #504 on top of the v1.7.0 line. First parent is this PR's branch head, as the supervisor ordered; no change to the PR's own files beyond what the merge resolves.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
luisleo526 added a commit that referenced this pull request Oct 25, 2026
…#481)

* test(ci): pin equivalence CTest row and prerequisite contract (CR-223-ROW)

* test(ci): require equivalence execution and corpus LFS provisioning

* test(ci): extend verifier partition and native row accounting

* ci(live): run corpus equivalence as a required CTest row (CR-223-ROW)

The corpus equivalence driver becomes a permanent runner CTest row, and the
runner-e2e equivalence exclusion leaves `ci_verify.py`.

Two sentences of `docs/ci.md` that dbd17b3 ("Live runner: normalized feed input
and per-action webhook routing (#320)") introduced are retired here because this
change makes them false, and the message names them so the doc-revert gate can
read the retirement:

- "The standalone corpus equivalence driver is not a runner CTest row; its
  harness unit tests remain in the engine-wide inventory." The driver is now the
  `native_live_equivalence_e2e` row in `runner/CMakeLists.txt`, and the same
  sentence's second clause (the harness unit tests staying in the engine-wide
  inventory) is kept verbatim in the replacement text.
- "It refuses label exclusions, missing runner compile commands, missing
  ASan/UBSan or frame-pointer flags, skipped/disabled tests, and, while
  `runner/transport.cpp` exists, a missing WebSocket row or transport skip even
  without `--require-websocket`." Its "skipped/disabled tests" clause is rewritten
  because a required runner e2e skip now fails outright; every other clause is
  kept in the replacement paragraph.

Restored on purpose: nothing. The rest of the diff only adds text.

* ci: release ruleset probe lists every branch ruleset (measurement only, gate unchanged) [replaces #489] (#505)

* ci(release): the ruleset probe lists every branch ruleset as visible or hidden, even when the gate verdict is a refusal (CR-245 F1 measurement)

The one dispatch of release-ruleset-probe.yml from main (run 40083495967) refused on the first branch ruleset
of the inventory, the organization ruleset `default` (13094758): "returned missing or invalid bypass_actors
(token cannot see this ruleset's bypass_actors)". The verdict reader stops at the first failure, so the run
did not say whether the release App token can see bypass_actors on the repository ruleset that is the real
barrier (21476386), nor on any other. The probe now first prints one line per branch ruleset of the
includes_parents inventory (id, name, source_type, source, enforcement, updated_at, bypass_actors visible
with the actor count or hidden, applies to main, has a pull_request rule), then runs the unchanged verdict:
success prints the existing success lines; a refusal prints the same ::error:: text on stderr and exits 1,
but stdout now carries the listing. A detail read that fails is reported on its own row and the listing
continues. The listing is a measurement: `gate`, `_release_bump` and `_require_release_rulesets` are
untouched, every gate test and the existing source mutants are kept, and the probe's verdict replay over every
existing ruleset fixture still compares verdict and refusal text byte for byte. The workflow
release-ruleset-probe.yml is not changed. The listing reads each branch ruleset detail independently of the
verdict read (two reads per detail in the probe), which docs/ci.md now says.

Red-first rows: the real situation (org ruleset hidden, repository ruleset visible: both listed, the org one
hidden, refusal unchanged), both hidden, one detail read failing, all visible with a valid barrier, the
read-only call list, and a source mutant that drops the listing.

Rewrites named for the doc-reverts check, all introduced by 9c18d41 (#488, "ci(release): read-only ruleset
probe for the release gate (CR-245 F1)"): docs/ci.md "Success prints the barrier id/name and one compact
inventory line with enforcement, source and bypass visibility."; docs/ci.md "Refusal exits 1 with empty stdout
and the reader's `::error::` diagnostic; API/response failures name the endpoint."; docs/ci.md "Two hidden
rulesets need two dispatches: the first refusal names only the first hidden ruleset; make its `bypass_actors`
visible before dispatching again to identify the second." (replaced: all hidden rulesets are listed in one
dispatch); the probe docstring "Read exactly the bump's ruleset evidence, with the same refusal policy."; two
test comments ("The reader report's complete [] inventory fails on main without an endpoint." and "The
runtime assertions already hold there; the prose does not."). The module docstring sentence "Each
endpoint/page is read at most once; failures refuse without retry or sleep." (ad1ebac, #479) is scoped to the
gate's reads.

Lane: ci-fu-cr488m (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the probe listing bounds its inventory=ERROR row to 240 characters like the detail-error rows (CR-245 F1 measurement, sol P2)

The new stdout listing printed the whole exception text on an `inventory=ERROR` row, while the per-ruleset
`detail=ERROR` rows truncate it to 240 characters; a `gh` transport error with 300 characters of stderr was
echoed in full. The row now applies the same bound ([:240], still !r-escaped). Four rows assert the exact bounded
line (an inventory transport error, a repository transport error, a default-branch rejection with a long repository
argument, an invalid summary with a long field) together with the unchanged stderr, exit code 1 and API call list
of the verdict; each has a mutation control that removes only the bound and must fail. The verdict functions are
untouched and the verdict's own stderr is not bounded. No documentation sentence is changed (none described a length
limit).

Lane: ci-fu-cr488n (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: fully qualify the two remote-tracking refs the promote-baseline ancestry check and the doc-reverts default base read (ORG-ACTIONPINS-CARD) [replaces #494] (#507)

* ci: fully qualify the two remote-tracking refs the promote-baseline ancestry check and the doc-reverts default base read (ORG-ACTIONPINS-CARD, LB-464 P3)

promote-baseline.yml tested `git merge-base --is-ancestor "$MERGE_SHA" "origin/$BASE_REF"`, and
check_doc_reverts.py default_base() resolved the bare names `origin/main` then `main`. A short name resolves through
git's ref-lookup order, so a tag called `origin/main` (or `main`) would win over the remote-tracking branch or the
local branch. Both now use the fully qualified names (`refs/remotes/origin/$BASE_REF`; `refs/remotes/origin/main`,
then `refs/heads/main`, same order and same fallback to the merged-pull-request walk). The exact-text pin in
scripts/ci_preflight.py is updated to the new command and stays as strict; the old short form is now a finding.

Red-first tests: the pin refuses the short command and accepts the qualified one; a repository where a TAG named
`origin/main` points at an unrelated commit and the real remote-tracking ref points elsewhere, and the same for a tag
named `main` with no remote-tracking ref, each returns the merge base of the real ref and not the tag's. Five controls
keep the order, the environment override, the local fallback, the merged-pull-request fallback and the no-base result.
The first-parent walk is untouched (the lab-host defect is a separate card).

The default_base docstring in scripts/check_doc_reverts.py is re-wrapped around the two renamed refs; the sentences it
carries come from 1e360bd and d093560 and keep their wording, only the ref names change.

Lane: ci-fu-shortrefs (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: release ruleset probe lists every branch ruleset (measurement only, gate unchanged) [replaces #489] (#505)

* ci(release): the ruleset probe lists every branch ruleset as visible or hidden, even when the gate verdict is a refusal (CR-245 F1 measurement)

The one dispatch of release-ruleset-probe.yml from main (run 40083495967) refused on the first branch ruleset
of the inventory, the organization ruleset `default` (13094758): "returned missing or invalid bypass_actors
(token cannot see this ruleset's bypass_actors)". The verdict reader stops at the first failure, so the run
did not say whether the release App token can see bypass_actors on the repository ruleset that is the real
barrier (21476386), nor on any other. The probe now first prints one line per branch ruleset of the
includes_parents inventory (id, name, source_type, source, enforcement, updated_at, bypass_actors visible
with the actor count or hidden, applies to main, has a pull_request rule), then runs the unchanged verdict:
success prints the existing success lines; a refusal prints the same ::error:: text on stderr and exits 1,
but stdout now carries the listing. A detail read that fails is reported on its own row and the listing
continues. The listing is a measurement: `gate`, `_release_bump` and `_require_release_rulesets` are
untouched, every gate test and the existing source mutants are kept, and the probe's verdict replay over every
existing ruleset fixture still compares verdict and refusal text byte for byte. The workflow
release-ruleset-probe.yml is not changed. The listing reads each branch ruleset detail independently of the
verdict read (two reads per detail in the probe), which docs/ci.md now says.

Red-first rows: the real situation (org ruleset hidden, repository ruleset visible: both listed, the org one
hidden, refusal unchanged), both hidden, one detail read failing, all visible with a valid barrier, the
read-only call list, and a source mutant that drops the listing.

Rewrites named for the doc-reverts check, all introduced by 9c18d41 (#488, "ci(release): read-only ruleset
probe for the release gate (CR-245 F1)"): docs/ci.md "Success prints the barrier id/name and one compact
inventory line with enforcement, source and bypass visibility."; docs/ci.md "Refusal exits 1 with empty stdout
and the reader's `::error::` diagnostic; API/response failures name the endpoint."; docs/ci.md "Two hidden
rulesets need two dispatches: the first refusal names only the first hidden ruleset; make its `bypass_actors`
visible before dispatching again to identify the second." (replaced: all hidden rulesets are listed in one
dispatch); the probe docstring "Read exactly the bump's ruleset evidence, with the same refusal policy."; two
test comments ("The reader report's complete [] inventory fails on main without an endpoint." and "The
runtime assertions already hold there; the prose does not."). The module docstring sentence "Each
endpoint/page is read at most once; failures refuse without retry or sleep." (ad1ebac, #479) is scoped to the
gate's reads.

Lane: ci-fu-cr488m (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the probe listing bounds its inventory=ERROR row to 240 characters like the detail-error rows (CR-245 F1 measurement, sol P2)

The new stdout listing printed the whole exception text on an `inventory=ERROR` row, while the per-ruleset
`detail=ERROR` rows truncate it to 240 characters; a `gh` transport error with 300 characters of stderr was
echoed in full. The row now applies the same bound ([:240], still !r-escaped). Four rows assert the exact bounded
line (an inventory transport error, a repository transport error, a default-branch rejection with a long repository
argument, an invalid summary with a long field) together with the unchanged stderr, exit code 1 and API call list
of the verdict; each has a mutation control that removes only the bound and must fail. The verdict functions are
untouched and the verdict's own stderr is not bounded. No documentation sentence is changed (none described a length
limit).

Lane: ci-fu-cr488n (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: ci-cx <ci-cx@invalid>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the permission-claim text guard also catches backslash-wrapped, bytes-decoded and fullwidth respellings (PROBE-FU) [replaces #493] (#506)

* ci(release): the permission-claim text guard also catches backslash-wrapped, bytes-decoded and fullwidth respellings (PROBE-FU, sol P2 1/2/4)

The guard in WorkflowPinTests.assert_ruleset_visibility_documentation fails when the gate source, docs/ci.md or
release.yml state that the App needs "administration: read". A read of the probe found three respellings it accepted:
a Markdown hard break written as a backslash before the newline, a bytes constant (b"administr\x61tion: re\x61d",
with or without .decode()), and fullwidth compatibility letters. The collapsed view now treats backslash-newline like
whitespace, bytes constants are decoded into the scanned strings, and every view is NFKC-normalised before case
folding. Three new tests (12 rows) each read the real artifacts, assert the unmodified baseline passes, mutate a copy
and require the specific permission-claim AssertionError; removing only the matching handling turns its rows red.

Not closed, by design: YAML double-quoted scalars with escapes in release.yml (sol P2 3) and runtime string
construction (sol P3); a static text guard cannot decide them, and the exact-output pins on the refusal text remain the
decisive protection. No existing assertion, control or forbidden pattern is changed. The rewritten `view` tuple is code,
not a documentation or comment sentence.

Lane: ci-fu-pfuguard (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the permission-claim guard scans the casefold-only views as well as the NFKC views (PROBE-FU round 2, sol R237 P2)

The first PROBE-FU commit normalised every scanned view with NFKC and replaced the casefold-only views. For an input
such as `Needs administration: read` followed by the trade mark sign, the old guard matched (the sign is a non-word
character after `read`), but after NFKC the text is `readtm` and the word boundary no longer matches, so the claim was
accepted: the change made the guard weaker for that input. Each text is now checked in four views (the two original
views casefolded, and both NFKC+casefolded), so normalisation can only add matches. A restoration control appends the
trade mark case to the gate source, docs/ci.md and the workflow text (direct and line-wrapped, six rows), and a removal
mutant drops the casefold-only scan and must break all six rows.

No existing assertion or control changes; no documentation or comment sentence is deleted or rewritten.

Lane: ci-fu-pfuguard2 (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: release ruleset probe lists every branch ruleset (measurement only, gate unchanged) [replaces #489] (#505)

* ci(release): the ruleset probe lists every branch ruleset as visible or hidden, even when the gate verdict is a refusal (CR-245 F1 measurement)

The one dispatch of release-ruleset-probe.yml from main (run 40083495967) refused on the first branch ruleset
of the inventory, the organization ruleset `default` (13094758): "returned missing or invalid bypass_actors
(token cannot see this ruleset's bypass_actors)". The verdict reader stops at the first failure, so the run
did not say whether the release App token can see bypass_actors on the repository ruleset that is the real
barrier (21476386), nor on any other. The probe now first prints one line per branch ruleset of the
includes_parents inventory (id, name, source_type, source, enforcement, updated_at, bypass_actors visible
with the actor count or hidden, applies to main, has a pull_request rule), then runs the unchanged verdict:
success prints the existing success lines; a refusal prints the same ::error:: text on stderr and exits 1,
but stdout now carries the listing. A detail read that fails is reported on its own row and the listing
continues. The listing is a measurement: `gate`, `_release_bump` and `_require_release_rulesets` are
untouched, every gate test and the existing source mutants are kept, and the probe's verdict replay over every
existing ruleset fixture still compares verdict and refusal text byte for byte. The workflow
release-ruleset-probe.yml is not changed. The listing reads each branch ruleset detail independently of the
verdict read (two reads per detail in the probe), which docs/ci.md now says.

Red-first rows: the real situation (org ruleset hidden, repository ruleset visible: both listed, the org one
hidden, refusal unchanged), both hidden, one detail read failing, all visible with a valid barrier, the
read-only call list, and a source mutant that drops the listing.

Rewrites named for the doc-reverts check, all introduced by 9c18d41 (#488, "ci(release): read-only ruleset
probe for the release gate (CR-245 F1)"): docs/ci.md "Success prints the barrier id/name and one compact
inventory line with enforcement, source and bypass visibility."; docs/ci.md "Refusal exits 1 with empty stdout
and the reader's `::error::` diagnostic; API/response failures name the endpoint."; docs/ci.md "Two hidden
rulesets need two dispatches: the first refusal names only the first hidden ruleset; make its `bypass_actors`
visible before dispatching again to identify the second." (replaced: all hidden rulesets are listed in one
dispatch); the probe docstring "Read exactly the bump's ruleset evidence, with the same refusal policy."; two
test comments ("The reader report's complete [] inventory fails on main without an endpoint." and "The
runtime assertions already hold there; the prose does not."). The module docstring sentence "Each
endpoint/page is read at most once; failures refuse without retry or sleep." (ad1ebac, #479) is scoped to the
gate's reads.

Lane: ci-fu-cr488m (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the probe listing bounds its inventory=ERROR row to 240 characters like the detail-error rows (CR-245 F1 measurement, sol P2)

The new stdout listing printed the whole exception text on an `inventory=ERROR` row, while the per-ruleset
`detail=ERROR` rows truncate it to 240 characters; a `gh` transport error with 300 characters of stderr was
echoed in full. The row now applies the same bound ([:240], still !r-escaped). Four rows assert the exact bounded
line (an inventory transport error, a repository transport error, a default-branch rejection with a long repository
argument, an invalid summary with a long field) together with the unchanged stderr, exit code 1 and API call list
of the verdict; each has a mutation control that removes only the bound and must fail. The verdict functions are
untouched and the verdict's own stderr is not bounded. No documentation sentence is changed (none described a length
limit).

Lane: ci-fu-cr488n (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: ci-cx <ci-cx@invalid>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* tests: drop the TIMEOUT 180 ctest property (owner's no-time-limit rule, P2-CM-F4) (#504)

* tests: drop the TIMEOUT 180 property from the six ownership manifest tests (P2-CM-F4)

One set_tests_properties call carried TIMEOUT 180 for test_selected_window_ownership_manifest,
the four test_selected_window_ownership_manifest_controls_shard_{1..4}of4 and
test_selected_window_ownership_d4. The owner's no-time-limit rule forbids a ctest
ceiling: under pool contention shard 1of4 (119 s normally) hit the 180 s ceiling on the
b250ceb merge-commit ci-post (#283). WORKING_DIRECTORY is kept; no test, label or
line count changes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: release ruleset probe lists every branch ruleset (measurement only, gate unchanged) [replaces #489] (#505)

* ci(release): the ruleset probe lists every branch ruleset as visible or hidden, even when the gate verdict is a refusal (CR-245 F1 measurement)

The one dispatch of release-ruleset-probe.yml from main (run 40083495967) refused on the first branch ruleset
of the inventory, the organization ruleset `default` (13094758): "returned missing or invalid bypass_actors
(token cannot see this ruleset's bypass_actors)". The verdict reader stops at the first failure, so the run
did not say whether the release App token can see bypass_actors on the repository ruleset that is the real
barrier (21476386), nor on any other. The probe now first prints one line per branch ruleset of the
includes_parents inventory (id, name, source_type, source, enforcement, updated_at, bypass_actors visible
with the actor count or hidden, applies to main, has a pull_request rule), then runs the unchanged verdict:
success prints the existing success lines; a refusal prints the same ::error:: text on stderr and exits 1,
but stdout now carries the listing. A detail read that fails is reported on its own row and the listing
continues. The listing is a measurement: `gate`, `_release_bump` and `_require_release_rulesets` are
untouched, every gate test and the existing source mutants are kept, and the probe's verdict replay over every
existing ruleset fixture still compares verdict and refusal text byte for byte. The workflow
release-ruleset-probe.yml is not changed. The listing reads each branch ruleset detail independently of the
verdict read (two reads per detail in the probe), which docs/ci.md now says.

Red-first rows: the real situation (org ruleset hidden, repository ruleset visible: both listed, the org one
hidden, refusal unchanged), both hidden, one detail read failing, all visible with a valid barrier, the
read-only call list, and a source mutant that drops the listing.

Rewrites named for the doc-reverts check, all introduced by 9c18d41 (#488, "ci(release): read-only ruleset
probe for the release gate (CR-245 F1)"): docs/ci.md "Success prints the barrier id/name and one compact
inventory line with enforcement, source and bypass visibility."; docs/ci.md "Refusal exits 1 with empty stdout
and the reader's `::error::` diagnostic; API/response failures name the endpoint."; docs/ci.md "Two hidden
rulesets need two dispatches: the first refusal names only the first hidden ruleset; make its `bypass_actors`
visible before dispatching again to identify the second." (replaced: all hidden rulesets are listed in one
dispatch); the probe docstring "Read exactly the bump's ruleset evidence, with the same refusal policy."; two
test comments ("The reader report's complete [] inventory fails on main without an endpoint." and "The
runtime assertions already hold there; the prose does not."). The module docstring sentence "Each
endpoint/page is read at most once; failures refuse without retry or sleep." (ad1ebac, #479) is scoped to the
gate's reads.

Lane: ci-fu-cr488m (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(release): the probe listing bounds its inventory=ERROR row to 240 characters like the detail-error rows (CR-245 F1 measurement, sol P2)

The new stdout listing printed the whole exception text on an `inventory=ERROR` row, while the per-ruleset
`detail=ERROR` rows truncate it to 240 characters; a `gh` transport error with 300 characters of stderr was
echoed in full. The row now applies the same bound ([:240], still !r-escaped). Four rows assert the exact bounded
line (an inventory transport error, a repository transport error, a default-branch rejection with a long repository
argument, an invalid summary with a long field) together with the unchanged stderr, exit code 1 and API call list
of the verdict; each has a mutation control that removes only the bound and must fail. The verdict functions are
untouched and the verdict's own stderr is not bounded. No documentation sentence is changed (none described a length
limit).

Lane: ci-fu-cr488n (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci: pin every third-party action to a full commit SHA with a version comment, and lint it in preflight (ORG-ACTIONPINS) [replaces #495] (#508)

* ci: pin every third-party action in the engine workflows to a full commit SHA with a version comment (ORG-ACTIONPINS)

66 `uses:` lines changed in .github/workflows/*.yml and .github/actions/setup-live-curl/action.yml: 65 mutable tags
rewritten to `@<40-hex sha> # v<version>` and one bare SHA that lacked its comment. Each pin is the same major the file
used before; no step, job, permission, environment, secret or token mint changes (a before/after comparison of the
diff with the refs stripped is identical line for line). Resolved on 2026-10-24 22:48 with `git ls-remote --tags` on a
spot box; every tag is lightweight, so the tag's sha is the commit:

  actions/checkout v4                         11d5960a326750d5838078e36cf38b85af677262  v4.4.0
  actions/upload-artifact v4                  ea165f8d65b6e75b540449e92b4886f43607fa02  v4.6.2
  actions/setup-python v5                     a26af69be951a213d495a4c3e4e4022e16d87065  v5.6.0
  actions/cache, cache/save, cache/restore v4 0057852bfaa89a56745cba8c7296529d2fc39830  v4.3.0
  actions/create-github-app-token v1          d72941d797fd3113feb6b93fd0dec494b13a2547  v1.12.0
  cloudflare/wrangler-action v3               9acf94ace14e7dc412b076f2c5c20b8ce93c79cd  v3.15.0

The byte-pinned copies of the workflow text that scripts/ci_preflight.py, scripts/test_ci_preflight.py and
scripts/test_ci_release_gate.py compare against (the embedded probe workflow, the release and cache expectations,
the Wrangler deployment, test mutations and fixtures) are moved to the same pinned text so each still equals its
workflow. Two tests read the real workflows and composite action and require a 40-hex sha and a version comment on
every third-party reference.

No documentation or comment sentence is deleted or rewritten.

Lane: ci-fu-pins (Codex gpt-6.1-sol).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ci(preflight): refuse any third-party `uses:` that is not a 40-hex commit SHA with a same-line version comment; the lint accepts plain block-style YAML only (ORG-ACTIONPINS)

scripts/ci_preflight.py gains `action_pin_findings`: every `uses:` in .github/workflows/*.yml and every composite
.github/actions/**/action.yml (or .yaml) that is not a local `./` path or a `docker://` image must be
`owner/action[/path]@<40 lowercase hex> # v<version>` on the same line; quoted values, step and job-level `uses:`, remote
reusable workflows and a ref-less `uses:` are judged; the finding names file, line and the offending reference. The lint
is a regression guard for our own reviewed workflow files, so it does not parse arbitrary YAML: it accepts plain block-style
YAML and refuses, with a finding naming file, line, construct and source text, what it cannot follow: anchors, aliases, merge
keys, explicit keys, tags, non-empty flow mappings, quoted keys, backslash escapes in quoted values, quoted values that do not
end on their line, tab indentation, document markers, `uses` without a same-line scalar, unrecognised block lines, non-ASCII
whitespace in structural positions, and any non-LF line break (bare CR, NEL, LS, PS, VT, FF) or C0 control character in the
whole file. Allowed (surveyed on the real tree, twelve YAML files): plain block mappings and sequences, plain and quoted
scalar values, empty `{}` and `[]` as a whole plain value, non-empty flow sequences, block-scalar bodies including `- |`.
Quotes inside flow sequences count only at element start; delimiters of a refused flow collection are counted without quote
masking and the refusal region ends at the first outdent. The `${{ ... }}` scan is linear. The loaders read the bytes and
decode strict UTF-8 (a file that is not UTF-8 is a finding), so a bare CR is no longer erased before the refusal runs. The
documented limit for exotic YAML is in docs/ci.md. The lint was read by sol and argon over five rounds (every finding closed
or classified); the loader and the three promotion-guard tests that now also see the lint's quoted-key finding were fixed
from the lab legs.

Tests: 15 first-round and the later red-first tests (one per refused construct, each break character in a block-scalar body and
in a comment, the C0 controls, flow-quote variants, outdent resumption, loader tests on real files in a temp layout, a real-tree
zero-findings test, mutation controls for the refusal branch and the integration call). docs/ci.md describes the rule.

This commit is the squash of the lint rounds of the series; the pins commit before it rewrites the workflow files. Lanes:
ci-fu-pinlint, ci-fu-pins2/3/4/5 (Codex gpt-6.1-sol), ci-fu-pins6 and pins7 (Claude Sonnet 5.5 via claudock).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: ci-cx <ci-cx@invalid>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: ci-cx <ci-cx@invalid>
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