fix(ci): build the main bundle in the jobs that publish the action ledger - #948
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 30, 2026, 8:26 PM ET / July 31, 2026, 00:26 UTC. ClawSweeper reviewWhat this changesThe PR makes the repair comment-router and repair cluster-worker jobs build both required Node bundles before publishing action-ledger paths, adds Merge readinessThis is a focused fix for the action-ledger publication failure tracked by #946. The patch and supplied terminal proof credibly show that the jobs now emit the CLI bundle they invoke, with a guard against regression; it should remain open for normal maintainer landing rather than cleanup closure. Priority: P1 Review scores
Verification
How this fits togetherThe repair comment router and cluster worker are GitHub Actions jobs that process repair work and then publish immutable action-ledger paths. Their setup step builds runtime bundles consumed by later CLI commands, which in turn update the durable action-ledger publication path. flowchart LR
A[Repair work arrives] --> B[Router or cluster-worker job]
B --> C[Setup installs and builds Node bundles]
C --> D[Main CLI bundle]
C --> E[Repair CLI bundle]
D --> F[Publish action-ledger paths]
E --> F
F --> G[Durable action ledger]
Before merge
Agent review detailsSecurityNone. Review metrics
Root-cause clusterRelationship: Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Land the narrow sequential Do we have a high-confidence way to reproduce the issue? Yes—the workflow source directly pairs Is this the best way to solve the issue? Yes—the sequential shared build script is the narrowest maintainable repair because it produces exactly the two Node bundles these jobs use, preserves the unused dashboard exclusion, and the regression guard follows script aliases instead of hard-coding one script name. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c8f44886fde4. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (8 earlier review cycles)
|
…dger The comment router and the cluster worker's execute job run `node dist/clawsweeper.js publish-action-event-paths`, but both asked setup-pnpm for `build:repair`, which compiles tsconfig.repair.json only. dist/clawsweeper.js comes from the main build, so the step failed with MODULE_NOT_FOUND on every run that reached it. Both jobs now request `build:node`, a new script that chains the two Node bundles they use and leaves out the dashboard leg neither runs. It has to chain rather than select both by regex: pnpm runs regex-selected scripts concurrently, and tsconfig.repair.json also compiles five non-repair sources that tsconfig.json emits to the same paths, so the two compilers would race on the same output. The router's curated sparse checkout gains tsconfig.json so the main build can find its config; the execute job checks out the whole tree already. The guard resolves a build-script through package.json rather than listing which script names cover which bundle, so `build`, `build:node` and `build:all` are all recognised without restating the mapping. It walks every workflow, finds each job that runs the bundle, and requires that job to build it or to restore the named `clawsweeper-runtime-dist` artifact the way sweep's review shard does. Keying the exemption on that artifact name matters: the execute job downloads unrelated worker artifacts, and a looser check would have let it revert silently.
144236b to
c5ab997
Compare
…ew cache
itemContentDigest fed context.pullChecks into the digest verbatim, and
pullChecksContext fills that from commits/{headSha}/check-runs with no author or
app filter. A completed review writes its labels and durable comment, which
retriggers clawsweeper-dispatch and github-activity; those add check runs to the
head, the digest changes, reviewContentCacheHit misses, and the unchanged head is
reviewed again -- which writes labels again. On openclaw#948's head 144236b, 26 of 38
check runs were those two jobs, and 13 of them were byte-identical after
compactCheckRun.
Across every review comment on this repo the durable comments record 154
consecutive re-reviews of an unchanged head, median gap 33 minutes, below the
HOURLY_REVIEW_MS floor that reviewCadenceMs can return.
De-duplicate the compacted runs inside the digest. Once a run is reduced to
{name,status,conclusion,app} a repeat reports nothing the first one did not,
while a run that newly fails differs in conclusion and keeps its own entry. This
touches the cache key only: pullChecksContext is unchanged, so the check list the
reviewer sees through reviewContextLedger is unchanged.
The same bot was already excluded from timeline, labels, and PR review comments;
checks were the remaining input.
Fixes #946.
What this fixes
repair comment routerandrepair cluster worker'sexecutejob runnode dist/clawsweeper.js publish-action-event-paths, but both askedsetup-pnpmfor
build-script: build:repair. That script istsc -p tsconfig.repair.jsonanddoes not emit
dist/clawsweeper.js, which comes from the main build. ThePublish immutable command action ledgerstep therefore failed withMODULE_NOT_FOUNDon every run that reached it.Both jobs now request
build:node, a new script that chains the two Node bundlesthey use and leaves out the dashboard leg neither runs. The router's curated sparse
checkout also gains
tsconfig.jsonso the main build can find its config; theexecute job already checks out the whole tree.
build:nodechains rather than selecting both scripts by regex, because pnpm runsregex-selected scripts concurrently and
tsconfig.repair.jsonalso compiles fivenon-repair sources (
src/repository-profiles.ts,src/codex-output-capture.ts,src/codex-spawn.ts,src/codex-app-server-worker.ts,src/codex-process-worker.ts) thattsconfig.jsonemits to the same paths. Twoconcurrent compilers would race on those outputs.
Rebased onto current main
Head
c5ab9976, baseorigin/main9e464d65. The review on this PR asked for theproof to be re-taken against current main, so every capture below was re-run at
this head. The diff is unchanged at +128 −4.
The two workflow files this PR edits are byte-identical between the earlier base
8365a79aand current main, and both direct main-bundle call sites are stillpresent:
The router's sparse checkout at current main still carries the broad
srcentryand still omits
tsconfig.json, which is exactly what the added entry supplies:Evidence
Driving the exact build-script value each job passes at head
c5ab9976, theninvoking the bundle the failing step invokes:
After the change the module resolves and execution reaches
publishActionEventPathsCommandinsidedist/clawsweeper.js, failing only on theplaceholder argument. That is the discriminator: the subcommand is reachable.
The router's sparse entry is load-bearing on its own. Its checkout is
cone-mode: falsewith a curated list, so a file it does not name is absent:The guard
test/repair/workflow-sparse-checkout.test.tsgains a check that walks everyworkflow, finds each job with a step that runs
dist/clawsweeper.jsdirectly, andrequires that job to obtain the bundle — by a build-script that builds it, or by
restoring the
clawsweeper-runtime-distartifact, which is howsweep.yml'sreviewshard gets it. Jobs that build from a sparse checkout must also carrytsconfig.json. It audits every job that invokes the bundle directly — nine jobscarrying fifteen invocation lines today: two jobs in
assist.yml(five lines),five in
sweep.yml(eight lines), and the two changed here (one line each).Two details are deliberate. The helper resolves a build-script through
package.json, following
pnpm runchains, sobuild,build:nodeandbuild:allare all recognised without restating which name covers which bundle.And the artifact exemption requires that exact artifact name rather than accepting
actions/download-artifactin general — the execute job downloads unrelated workerartifacts, and a looser check would let it revert silently.
The audit is deliberately limited to direct invocations. A job that reaches the
bundle through a package script is not covered, because some
build-scriptvaluesare GitHub expressions that only a live run resolves —
sweep.yml'sevent-review-applypicks betweenbuild:allandbuild:repairthat way. Wideningthe audit would mean evaluating those expressions, so it is left out rather than
guessed at.
Reverting any one of the three parts fails the guard, and nothing else:
The pre-existing
build-script: build:repairstring assertion became the same kindof resolved check, since the router no longer passes that literal.
Proof summary
Behavior addressed: the
Publish immutable command action ledgerstep inrepair comment routerand inrepair cluster worker'sexecutejob abortswith
MODULE_NOT_FOUNDbecause the job never buildsdist/clawsweeper.js.Real environment tested: production GitHub Actions runs for the router
failure (see The immutable command action ledger never publishes: its job never builds dist/clawsweeper.js #946); local Node
v24.18.0running the exact build-script valuesthe workflows pass, plus the built CLI itself.
Exact steps or command run after this patch:
rm -rf dist && pnpm run build:node node dist/clawsweeper.js publish-action-event-paths --paths-file /dev/null node --test test/repair/workflow-sparse-checkout.test.tsEvidence after fix: the capture above — the bundle exists, the dashboard leg
is still skipped, and the CLI reaches
publishActionEventPathsCommand.Observed result after fix:
pass 8 / fail 0on the guard file, andfail 1naming the exact missing piece when any one part is reverted.What was not tested: this patch is not deployed, so there is no production
run of the fixed jobs. The immutable command action ledger never publishes: its job never builds dist/clawsweeper.js #946 documents the router failing repeatedly in
production; for the
executejob the same defect is established by reading theworkflow — it passes
build:repairand runs the bundle — rather than by anobserved run, because that job is conditional and I did not catch it in the act.
pnpm run checkat this head on Nodev24.18.0ran 2,812 tests with 6 failures,all host-caused and all inside
test/repair/target-validation.test.ts, which thispatch does not touch: three need
git worktree list -z(this host has Git2.34.1,
-zarrived in 2.36) and three cannot resolve the bun/npm/pnpmcontainment fixtures.
pnpm run build:allexits 0, and every static check andlint lane passes.
Not in scope
sweep.ymlandassist.ymlalready pass a build that emits the bundle(
build:allandbuild), so they are unchanged.different defect and are tracked in Track exact-review publication, lifecycle telemetry, and OpenClaw Bay correctness #898.