Skip to content

fix(actions): give both stale-run cleanup jobs an identity they can match - #1993

Draft
seonghobae wants to merge 6 commits into
mainfrom
fix/stale-run-cleanup-workflow-identity
Draft

fix(actions): give both stale-run cleanup jobs an identity they can match#1993
seonghobae wants to merge 6 commits into
mainfrom
fix/stale-run-cleanup-workflow-identity

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Causal defect

strix.yml and opencode-review.yml selected cleanup candidates with an exact comparison against the declared workflow name. Both workflows declare run-name:, and the live API reports the rendered run name in .name; the former equality matched 0 of 100 sampled runs for each workflow on 2026-09-07. Closed or converted-to-draft pull requests could therefore leave obsolete scans consuming shared admission capacity.

Bounded repair

  • bind both destructive cleanup selectors to the central workflow .path plus the expected rendered-name prefix;
  • retain foreign-workflow negative controls so pull-request metadata alone cannot authorize cancellation;
  • use the shared rendered-name predicate only for stale_pr_run_ids(workflow=...) and existing current/superseded review-run discovery;
  • preserve native synchronize concurrency and late live-head revalidation;
  • keep the permanent workflow-name non-collision contract non-vacuous across both *.yml and *.yaml.

Scope correction

The earlier head also activated dispatch_strix_evidence().busy_refs for rendered names. That was not required for stale-run retirement: it would serialize unrelated current PRs in one repository while the measured Strix active lifetime was median 177 minutes, p90 637 minutes, and max 742 minutes. Exact head da7636a7a5c01a24de4008195409ed00387bef9c removes that dormant repository-wide guard and its synthetic policy test. Any future repository-wide admission policy needs its own bounded-wait, fairness, rate-limit-benefit, and telemetry evidence.

Exact authority

  • base at last re-fetch: main@c9052e607e5f3cc76e73207e7786b21500721b79
  • current head: da7636a7a5c01a24de4008195409ed00387bef9c
  • lifecycle: Draft / Proposed
  • no force push or rebase; the branch advanced through ordinary child commits only

The predecessor head reported 2984 passed, 1 skipped, 21 subtests, 100% coverage, and 100% interrogate, but that evidence does not transfer. Fresh CI, security, current-head review, and destructive-selector regressions must be terminal-clean on the unchanged exact head before Ready or ordinary merge.

…atch

`strix.yml` and `opencode-review.yml` each run a cleanup job whose only
purpose is retiring superseded runs of their own workflow, and both selected
those runs with `select(.name == "<declared workflow name>")`. Both workflows
declare `run-name:`, and GitHub reports the *rendered* run-name in a run's
`name` field -- so neither equality ever matched and both jobs were silent
no-ops. Measured 2026-09-07 against the live API: of the 100 most recent runs
of each workflow, 0 carried the bare declared name and 100 carried the
rendered `"<declared name> <repo>#<pr>@<sha>"` form.

The workflow-level `concurrency` group hides this on `synchronize`, where it
cancels the previous head's run itself. What was actually lost is every case
no successor run supersedes: a `closed` or `converted_to_draft` pull request
left its in-flight scans running to completion, holding admission slots under
the shared 60-job ceiling for a pull request nobody is waiting on.

Identity now comes from `.path`, the signal `noema-review.yml` already adopted
for this same defect. The same measurement confirmed it stable in both
contexts: `.github/workflows/strix.yml` on native runs in `.github` and on the
nine ruleset-injected runs in `bandscope`, which carries no local copy.
Deleting the filter instead would have been wrong -- the surviving
`$metadata_matches` branch accepts any run whose `pull_requests[]` names the
pull request, so an unfiltered job would cancel other workflows' runs. A
negative control per selector pins that.

The same equality appears twice in the scheduler and is repaired with one
shared predicate, `run_name_identifies_workflow`:

- `dispatch_strix_evidence`'s `busy_refs` was always empty, so the
  `repository_busy` guard that serializes Strix dispatch per target repository
  never fired. Since 2026-09-04 that let 20 dispatch runs reach 5 simultaneous
  for one target repository, against the 1 the guard specifies.
- `stale_pr_run_ids`'s `workflow=` filter had the same defect. Its only
  production caller passes no workflow, so it never ran; it stayed a trap that
  silently returned nothing for any caller that did supply one.

Two fixtures asserted the dead behaviour and are corrected rather than
deleted. `test_dispatch_strix_waits_for_active_target_repository_run` paired a
bare `name` with a rendered `display_title` inside one run record -- a
combination GitHub cannot produce -- which is how a passing test coexisted
with a predicate matching 0 of 100 live runs.

`run_name_identifies_workflow` accepts a candidate followed by a space, so a
future workflow named as an extension of an existing one would start answering
for it. Nothing else in the repository would notice, so the premise that makes
the prefix accept safe -- no central workflow name prefixes another, 0 of 35 --
is pinned as its own test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae added bug Something isn't working priority: medium Normal-priority or P2 work status: needs-review Open pull request requiring current-head review or checks type: bug Defect or incorrect behavior labels Sep 6, 2026 — with ChatGPT Codex Connector
`run_name_identifies_workflow` accepts a candidate followed by a space, which
is safe only while no central workflow name prefixes another. The test pinning
that premise globbed `*.yml` alone, so a future `.yaml` workflow would drop out
of the check silently -- and the `>= 30` vacuity guard would not catch it
either, since 35 files minus one still clears the floor. A test whose only
purpose is announcing a change nobody would otherwise see must not be
bypassable by a file extension. Reported by a peer session's read review of
#1993.

Both extensions are globbed now, and a second assertion requires every
workflow file to contribute a name, so a file dropping out by losing its
top-level `name:` fails as loudly as one dropping out by extension.

Neither change alters today's result: 35 `.yml`, 0 `.yaml`, 35 distinct names.
This closes a future hole rather than fixing a present miss, and is stated that
way because nothing in the tree can demonstrate it yet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head review for 18a04550dd0325b10ecfafa41b06d3f9c16ff3fa.

Blocking scope finding — split the Strix repository-wide serialization policy from the stale-run identity repair.

The .path repairs in strix.yml and opencode-review.yml, plus the rendered-name predicate used by stale_pr_run_ids, are direct repairs for selectors that matched 0/100 live runs. Their production selectors have positive and foreign-workflow negative controls, and current-head Agent Review Runtime Quality run 34066418775 verifies the exact checkout with 2,984 passed / 1 skipped / 21 subtests and 100% measured coverage.

However, changing dispatch_strix_evidence().busy_refs from exact equality to run_name_identifies_workflow is a separate throughput-policy activation. It is not required to retire predecessor-head runs. It changes distinct current PRs in one repository from observed concurrency up to five to repository-wide serialization. The PR's own live measurement says an active Strix lifetime is median 177 minutes, p90 637 minutes, max 742 minutes; therefore the second unrelated PR can lose current-head evidence for hours. That is a buyer-visible admission/fairness decision, not a fixture correction.

Please keep the three stale/superseded-run identity repairs here and move the busy_refs activation into its own owner lane with RED→GREEN evidence for: (1) bounded wait/SLO for a second current PR, (2) starvation-free retry/fairness across PRs, (3) provider/rate-limit benefit versus the measured latency cost, and (4) exact telemetry for repository_busy duration and target run identity. If the policy remains here, equivalent acceptance evidence is required before merge.

This branch also overlaps scripts/ci/pr_review_merge_scheduler_core.py with #1986 and #1999. Preserve every valid delta by ordinary merge order plus non-force restack onto the first integrated sibling; do not treat a sibling's checks or review as evidence for this head.

Current required security runs are queued, not passing, so this review does not confer merge authority.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Revalidation on current exact head 5c3e6b272838dca0a1496123976d5f6fcc26349d.

The only delta from reviewed head 18a04550… is in tests/test_stale_run_cleanup_workflow_identity.py: it adds *.yaml discovery and non-vacuity/name-count assertions. That strengthens the workflow-name collision premise, but it does not alter the production dispatch_strix_evidence().busy_refs activation.

Therefore the blocking scope finding in review 5127083392 remains current: split repository-wide cross-PR Strix serialization into its own policy lane (with bounded-wait/fairness/rate-limit/telemetry evidence), while preserving the three stale-run identity repairs here. The new head's required workflow runs are queued; the cancelled predecessor-head runs are obsolete evidence and are not promoted.

@seonghobae
seonghobae marked this pull request as draft September 7, 2026 00:05
@seonghobae seonghobae removed the status: needs-review Open pull request requiring current-head review or checks label Sep 7, 2026
@seonghobae seonghobae added the status: draft Draft pull request label Sep 7, 2026 — with ChatGPT Codex Connector

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Current-head verification for da7636a7a5c01a24de4008195409ed00387bef9c.

The scope finding from reviews 5127083392 / 5127085606 is resolved on this head:

  • the child delta removes the repository-wide busy_refs / repository_busy policy path and its synthetic policy test;
  • dispatch_strix_evidence now performs only same-PR current/stale run handling before exact-head dispatch;
  • the direct .path repairs for Strix/OpenCode cleanup and the rendered-name repair for stale_pr_run_ids(workflow=...) remain;
  • PR lifecycle is correctly Draft while current-head evidence is incomplete.

Fresh hosted run 34068657349 checked out this exact SHA and completed Agent Review Runtime Quality successfully: Strix quick gate PASS; 2,983 passed, 1 skipped, 21 subtests; 100% measured coverage; interrogate PASS. I found no new substantive defect in the scope-correction delta.

This does not grant merge authority: CodeQL, Security Scan, Python Security, and SAST are still queued, and there is no qualifying independent current-head approval. Preserve #1986/#1999 overlap through ordinary merge order and non-force restack after the first sibling integrates.

…t inverted

Splitting the `repository_busy` policy out of this branch also rewrapped the
sentence explaining why a prefix accept is safe, and four words fell out at the
line boundary. It read:

    ... so this predicate narrows a candidate identity alone.

instead of:

    ... so this predicate narrows a candidate set rather than deciding
    identity alone.

The shortened form asserts exactly what the sentence exists to deny, and it is
the sentence a future reader relies on to decide whether the prefix accept can
stand. No test reads prose, so the full suite stayed green over it; the split's
own addition -- pull-request metadata as a third identity pin -- is correct and
is kept.

`cancelled_refs` also became assigned-but-never-read once `busy_refs` was
removed, since that comprehension was its only consumer. Renamed to
`_cancelled_refs`, matching the sibling call thirty lines above which already
discards the same value as `_cancelled_run_refs`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Exact-head revalidation for c35acda41249b2492fa31d51d4398b15ecdb6617: the single commit since da7636a7a5c01a24de4008195409ed00387bef9c is non-behavioral.

  • It restores the intended sentence that run_name_identifies_workflow() only narrows a candidate set; the call sites still require an independent identity pin.
  • It renames the now-unused cancelled_refs binding after the repository-wide busy_refs/repository_busy policy was removed.
  • It does not reintroduce cross-PR Strix serialization, and the prior merge-admission finding remains resolved.

This is not an approval or a transfer of predecessor-head CI evidence. The PR remains Draft and the exact-head CodeQL, Security Scan, Python Security, SAST, and Runtime Quality runs must reach terminal success on this unchanged SHA before ordinary merge admission.

@seonghobae
seonghobae marked this pull request as ready for review September 7, 2026 02:00
@seonghobae
seonghobae enabled auto-merge (squash) September 7, 2026 02:06
@seonghobae
seonghobae marked this pull request as draft September 7, 2026 03:16
auto-merge was automatically disabled September 7, 2026 03:16

Pull request was converted to draft

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

Labels

bug Something isn't working priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant