Skip to content

fix(actions): activate every Lopu PR signal on main - #428

Merged
lopugit merged 3 commits into
mainfrom
codex/lopu-default-listener-parity
Aug 27, 2026
Merged

fix(actions): activate every Lopu PR signal on main#428
lopugit merged 3 commits into
mainfrom
codex/lopu-default-listener-parity

Conversation

@lopugit

@lopugit lopugit commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • activate Lopu on PR synchronize, draft transition, edit, and close events from the real default branch
  • restore the hourly wildcard-union rebuild signal on main
  • expose the protected build-all and backfill-codeql maintenance operations in the default-branch listener
  • wake Lopu for PR-associated first-party GitHub Actions failures through workflow_run, while excluding Lopu PR manager itself
  • retire the standalone Build all branch product listener so union work enters the one protected Lopu maintenance queue
  • add listener, retirement, activation-parity, and Actions-failure regression contracts plus Graphify semantic cache

Why

The protected controller and develop listener were current, but the repository default branch still had the older listener. The half-hour global sweep eventually recovered missed PR lifecycle work, but it did not satisfy the all-repository-change wakeup contract in real time.

GitHub Actions first-party checks also need workflow_run because check_run and check_suite events are suppressed for checks created by GitHub Actions. The bounded workflow list closes that blind spot without allowing Lopu to recurse into its own failures.

The remaining .github/workflows/all-branch.yml listener was also spawning separate, redundant global-fleet jobs. The unified Lopu manager already owns the build-all handoff and its durable lopu-maintenance-build-all namespace. Removing the legacy listener prevents new duplicates while preserving the active build and coalescing only obsolete pending snapshots. The main ruleset does not require the retired workflow context.

The protected routing, diagnosis, and coalescing implementation is in #429, which should merge before this listener PR.

Verification

  • git diff --check
  • node remix/scripts/workflow-caller-contract.mjs
  • Ruby/Psych parse of .github/workflows/resolve-pr-conflicts.yml
  • Graphify semantic extraction through the local Codex proxy: content-addressed cache refreshed for the listener checklist, changelog, and PR note
  • Graphify cluster/report/HTML regeneration with the raised visualization limit
  • Graphify hooks and graphify-out/graph.json merge=graphify driver verified

The worktree-derived graph/report/manifest relabel churn was deliberately not committed; Lopu should rebuild the canonical graph after merge. The content-addressed semantic cache entries are included so the post-merge rebuild is deterministic and cache-backed.

Rollout

  1. Merge fix(actions): let Lopu review first-party CI failures #429 first to activate protected routing and duplicate-review coalescing.
  2. Merge this PR second to activate the default listener and remove the competing Build all branch listener.
  3. The standing main-to-develop sync carries this deletion to develop.

@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thingtime Ready Ready Preview Aug 27, 2026 7:05am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Lopu reviewed f534a367 (the head moved from 005c56b5 mid-review; findings are stated against live state).

No failing check. The lone UNSTABLE signal is Build all branch run 33045953399 holding on the protected lopu-maintenance-build-all queue — the designed hold, not a defect. All four required contexts on main pass, and none of them comes from the Build all branch workflow this PR retires, so nothing is stranded.

The one thing worth blocking on: workflow_run is activated ahead of its router

@github-actions resolves to cb7e6f2a today, and that revision contains exactly one occurrence of the string workflow_run — a comment. The routing is still open in #429. Tracing the current controller if this merges first:

  • route.if and review_detect.if have no workflow_run gate, so both run.
  • A workflow_run payload has no issue.number, pull_request.number or check_run.pull_requests[0].number, so SELECTED_PR and SELECTED_BRANCH are both empty and the review selector falls through to candidates="$open".
  • review_handoff then dispatches one Lopu review of all 79 eligible open PRs — per event.

on: cannot filter a conclusion, so this fires for successful runs too, on any branch. The nine watched workflows produced 348 runs in the preceding 24 hours (Lopu CodeQL all branches 157, Develop S3 PR preview 85, Build all branch 44, Web CI 33, Signed Electron PR Release 15, Workflow control-plane CI 14). Concurrency caps how many run at once, so the outcome is a permanently saturated model fleet rather than unbounded spend — targeted PR reviews would queue behind repo-wide sweeps indefinitely.

Both PR bodies name the ordering, and the ordering is right. It just isn't enforceable: the two PRs target different base branches, so no GitHub mechanism expresses "merge #429 first".

So I fixed the root cause in the control plane instead, and it is staged for a dedicated Lopu PR against github-actions. review_detect's scope selector failed open — any event it could not scope escalated to a repository-wide review. That is a defect class, not a workflow_run bug: a metadata-only listener cannot know which controller revision it calls, so every future trigger addition had this failure mode. The selector now keeps $open for the two signals that legitimately mean every open PR (a blank workflow_dispatch, and a push to github-actions) and otherwise logs a notice, sets any=false, and exits 0. Extracting the real step body and driving it against a stub:

BEFORE  workflow_run (unrouted) -> any=true, blank scope  ->  reviews every open PR
AFTER   workflow_run (unrouted) -> any=false              ->  no dispatch
AFTER   workflow_run (routed, #429) -> any=true pr=428

…with pull_request_target, check_run, issue_comment, branch pushes, push to github-actions, and both workflow_dispatch shapes all unchanged. That is the default-deny underneath #429, not a replacement — #429 is still the correct routing and also removes the residual detect churn. Please still merge it first; this just means the order stops being load-bearing.

manage_rebases was checked and already fails closed (*) candidates='[]' ;; in rebase-pr-stacks.yml).

Already fixed by f534a367 — noting it because it was live

At 005c56b5 the thin-listener topology contract failed: workflow-caller-contract.mjs matched the repository_dispatch trigger block literally, and the new explanatory comment between the key and types: broke the contiguous match. It was genuinely red on CI (HAS_WARNINGS: true on both earlier heads, - ⚠️ Thin-listener topology examples (exit 1)), just invisible because that job is non-blocking.

f534a367 fixes it the right way — tolerating comment lines rather than moving the comments — which also clears the identical latent break already sitting on develop. Adding assertions for the pull_request_target type list, cron "53 * * * *", the workflow_run list, and "never watch Lopu PR manager" is a real upgrade. Re-ran on the live head: 6 thin listeners pinned to github-actions, pass.

Smaller notes

  • Build all branch is now a dead entry in workflow_run.workflows on the default branch, since f534a367 retires that product-branch listener. Harmless, and develop still produces those runs until the retirement propagates — worth dropping whenever the list is next touched, not worth a commit.
  • The retirement itself checks out: handoff_all_branch_event covers push to develop/main/github-actions, pull_request_target, and schedule == '53 * * * *', all present here; manual rebuilds move to maintenance_operation: build-all; and the trusted contract's all-branch assertions read only trusted files, so Workflow control-plane CI is unaffected.
  • Develop parity is exact and safe on its own — the current controller already routes cron "53 * * * *", build-all, and backfill-codeql. synchronize really is redundant-but-deduplicated against push: ["**"], so no new self-trigger loop. Correctly omitting both Lopu PR manager and Lopu PR manager (internal rebase handoff) from the watched list is the detail that matters most, and it's right.
  • No CodeQL alerts were open on this head; the disposition file stays [].

Approve on content.

@github-actions

Copy link
Copy Markdown
Contributor

Lopu repository review

Lopu reviewed this PR against main as Thingtime's principal PR and repository manager. Using Claude Opus 5.

The PR head moved during review, so Lopu preserved the newer branch and did not overwrite it.

Lopu also opened a controller/workflow repair PR for the failed check root cause.

Lopu review — PR #428 fix(actions): activate every Lopu PR signal on main

What I compared

  • Reviewed head 005c56b5 against base main@1c5fdfba in the supplied
    worktree (4 files: .github/workflows/resolve-pr-conflicts.yml, TESTING.md,
    two Graphify semantic-cache entries).
  • The head moved mid-review. f534a367 (retire standalone all-branch
    listener
    ) was pushed at 07:02:34Z, after the manifest was cut. I re-read the
    new head from the origin ref and re-ran validation against it, so the findings
    below are stated against live state, and I note where the two differ.
  • Cross-checked against the reviewed develop listener (origin/develop), the
    protected controller (github-actions@cb7e6f2a, checked out at
    $GITHUB_WORKSPACE/trusted), README.md §"GitHub Actions control plane",
    remix/scripts/workflow-caller-contract.mjs, the trusted routing and
    control-plane contracts, PR fix(actions): let Lopu review first-party CI failures #429, live gh pr checks, the Web CI advisory job
    logs, the repository workflow registry, and main's ruleset.

Check state

No failing check. 21 success, 24 skipped, 1 pending; mergeStateStatus is
UNSTABLE only because of that pending run — Build all branch run
33045953399, a pull_request_target union rebuild waiting on the protected
lopu-maintenance-build-all queue. That is the designed hold, not a defect.

The four required contexts on main (Build + typecheck ratchet + unit tests,
API suite (headless /tests runner), Analyze (javascript-typescript),
Analyze (actions)) all pass and none of them originates from the
Build all branch workflow f534a367 retires, so that retirement strands no
required check.

Findings

1. Thin-listener topology contract failed on the reviewed head — since fixed

remix/scripts/workflow-caller-contract.mjs asserts the resolver listener's
trigger block literally:

/^  repository_dispatch:\n    types: \[resolve-conflicts-cascade, rebase-pr-stack-ai\]$/m

005c56b5 inserted a two-line explanatory comment between the key and types:,
breaking the contiguous match. Reproduced locally (exit 1) and confirmed live:
HAS_WARNINGS: true on both the 171ad004 and 005c56b5 Web CI runs, with
- ⚠️ Thin-listener topology examples (exit 1) in the advisory report. It never
surfaced as a red check because the contract runs only in the non-blocking
Product contract advisories job.

f534a367 already fixes this, and fixes it the right way — the regexes now
tolerate comment lines ((?: .*\n)*?) rather than the comments being moved,
which also clears the identical latent break already sitting on develop. The
same commit adds real coverage for the new triggers (pull_request_target type
list, cron "53 * * * *", the workflow_run list, and an assertion that
Lopu PR manager never appears in its own watched list).

Re-ran on the live head: workflow caller contract: 6 thin listeners pinned to github-actionsPASS. The advisory comment mechanism behaved correctly
throughout: warnings on the two earlier heads, HAS_WARNINGS: false at 07:03:23
on f534a367, which deletes the advisory comment. No action needed.

2. workflow_run is activated ahead of its protected router (the real risk)

This survives the head move and is the substantive finding.

github-actions@cb7e6f2a — the exact revision @github-actions resolves to
today — contains one occurrence of the string workflow_run, and it is a
comment. The routing lives in PR #429, which is still open against
github-actions. If #428 merges first, tracing the current controller:

  • route.if has no workflow_run gate → runs.
  • review_detect.if has no workflow_run gate → runs. Neither
    github.event.issue.number, github.event.pull_request.number nor
    github.event.check_run.pull_requests[0].number exists on a workflow_run
    payload, so SELECTED_PR and SELECTED_BRANCH are both empty and the
    selector falls through to candidates="$open".
  • review_handoff then dispatches one Lopu review of every eligible open PR
    (79 at the time of writing) per event.
  • detect also runs, scoped to PRs based on github.ref_name.

on: cannot filter a conclusion, so this fires for successful runs too, on
any branch. Those nine workflows produced 348 runs in the preceding 24
hours
(Lopu CodeQL all branches 157, Develop S3 PR preview 85,
Build all branch 44, Web CI 33, Signed Electron PR Release 15,
Workflow control-plane CI 14). Concurrency caps how many run at once, so the
outcome is a permanently saturated model fleet rather than unbounded spend — but
targeted PR reviews would queue behind repo-wide sweeps indefinitely.

The PR body flags "Depends on #429", and #429's body says it "should merge
before #428". That ordering is correct and cannot be enforced: the two PRs
target different base branches, so no GitHub mechanism expresses it.

manage_rebases was checked and is already safe — rebase-pr-stacks.yml's
event case ends in *) candidates='[]' ;;.

3. Build all branch is now a dead entry in the watched list (minor)

f534a367 deletes .github/workflows/all-branch.yml from the product branch,
so the default branch will no longer produce Build all branch runs. The name
remains in the listener's workflow_run.workflows list. Harmless — GitHub
ignores names that never fire — and develop still produces those runs from its
own push trigger until the retirement propagates. Worth dropping whenever the
list is next touched, not worth a commit on its own.

I verified the retirement itself is sound: handoff_all_branch_event in the
protected controller fires on push to develop/main/github-actions,
pull_request_target, and schedule == '53 * * * *' — all three present on the
new listener — and maintain_all_branch accepts both build-all and the
internal lopu-internal-all-branch dispatch. The trusted contract's all-branch
assertions read only trusted files, so Workflow control-plane CI is unaffected.
Manual "Build all branch" moves to Lopu PR manager
maintenance_operation: build-all, which the listener already exposes.

4. Develop parity (the PR's primary purpose) is correct

origin/develop's listener already carries the extended pull_request_target
type list, cron "53 * * * *", and the build-all/backfill-codeql options,
and the current protected controller already routes all three
(handoff_all_branch_event, maintain_all_branch, maintain_codeql_backfill).
Commit 171ad004 is exact parity and is safe on its own. synchronize is
correctly described as redundant-but-deduplicated against the existing
push: branches: ["**"] listener, so it introduces no new self-trigger loop
beyond what pushes already cause. closed/converted_to_draft cost nothing —
review_detect filters on --state open and isDraft. workflow_run
correctly omits both Lopu PR manager and Lopu PR manager (internal rebase handoff), so review failures cannot recurse.

No CodeQL alerts were open on this head; 428.json was an empty snapshot and
the disposition file is left as [].

Changes I made

None in the PR worktree, deliberately:

  • The one reproducible defect at the reviewed head (finding 1) was already
    fixed at the live head, better than I would have fixed it.
  • Finding 2 cannot be fixed by editing this PR. Deleting the workflow_run
    block would revert deliberate, freshly-pushed work — including the contract
    assertions f534a367 added to guarantee that block exists — and my worktree
    is pinned to a superseded head, so any commit would fail the publisher's lease
    check anyway. Adding a conclusion guard to the listener would violate the
    documented contract that a listener carries "triggers, caller permissions, and
    typed inputs only".
  • Findings 3 and 4 do not justify a commit.

One change in $GITHUB_WORKSPACE/trusted — the root cause of finding 2 is
in the protected control plane, so it is staged there for a dedicated Lopu fix
PR against github-actions, with the diagnosis in
$RUNNER_TEMP/lopu-workflow-fix.md.

review_detect's scope selector failed open: any event it could not scope
fell through to candidates="$open" and escalated to a repository-wide review.
That is a defect class, not a workflow_run bug — a metadata-only listener
cannot know which controller revision it calls, so every future trigger
addition had this failure mode. The selector now keeps $open for the two
signals that legitimately mean "every open PR" (a blank workflow_dispatch, and
a push to github-actions) and otherwise logs a notice, sets any=false and
exits 0.

This is the default-deny underneath #429, not a replacement for it: #429 remains
the correct routing implementation and also removes the residual detect churn.
The change is confined to the step's shell body, ~20 lines below the
SELECTED_PR: env line #429 edits, so the two should merge cleanly.

Validation run

In $GITHUB_WORKSPACE/trusted: Ruby/Psych YAML load with aliases: true (OK,
18 jobs), python3 yaml.safe_load (OK), git diff --check (OK), node --check
over every .github/scripts/*.mjs (OK), bash -n over every
.github/scripts/*.sh (OK), and the full control-plane suite —
resolve-pr-conflicts-routing-contract.mjs --self-test,
workflow-control-plane-contract.mjs --self-test,
promotion-worker-routing-contract.mjs --self-test,
build-all-branch.mjs --self-test,
classify-claude-credential-failure.mjs --self-test,
electron-pr-release-contract.mjs, promotion-worker-contract.sh,
rebase-ownership-routing-contract.sh — all pass.

Behavioural test: the Select one Lopu review scope step body was extracted
from the YAML via yaml.safe_load (the real step, not a paraphrase) and driven
against a stubbed gh returning three eligible open PRs.

Before, an unrouted workflow_run printed Lopu will review 3 PR(s) and set
any=true with a blank scope — a repository-wide review. After:

workflow_run (UNROUTED, pre-#429)   -> any=false  (no dispatch)
workflow_run (routed, #429)         -> any=true  pr=428
pull_request_target                 -> any=true  pr=428
check_run                           -> any=true  pr=431
issue_comment                       -> any=true  pr=430
push feature branch                 -> any=true  branch=feat/a
push github-actions (all-scan)      -> any=true  all 3 PRs
workflow_dispatch blank (all-scan)  -> any=true  all 3 PRs
workflow_dispatch branch selector   -> any=true  branch=develop
unrouted comment event              -> any=false  (no dispatch)

Every previously working scope is preserved; only the unrouted fallthrough
changes.

In the PR worktree at the live head f534a367:
node remix/scripts/workflow-caller-contract.mjs
workflow caller contract: 6 thin listeners pinned to github-actions (PASS).
At the reviewed head 005c56b5 the same command exits 1, which is finding 1.

Recommendation

Approve on content. Merge #429 first; if that ordering cannot be guaranteed,
land the controller default-deny above and the order stops mattering.

View Lopu workflow run

github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	.github/workflows/all-branch.yml
github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	.github/workflows/all-branch.yml
github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	.github/workflows/all-branch.yml
github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	.github/workflows/all-branch.yml
github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	graphify-out/cache/semantic/af1da8fa2a236285fac4bb25d0f5c9d4485157e1cd5bfb4d94c14744735bfb2a.json
@lopugit
lopugit merged commit ae012e2 into main Aug 27, 2026
51 checks passed
github-actions Bot added a commit that referenced this pull request Aug 27, 2026
# Conflicts:
#	graphify-out/cache/semantic/af1da8fa2a236285fac4bb25d0f5c9d4485157e1cd5bfb4d94c14744735bfb2a.json
@lopugit
lopugit deleted the codex/lopu-default-listener-parity branch September 1, 2026 10:46
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