fix(repair): cut over durable cluster intake publication (rework of #873) - #901
Conversation
Rework of the #873 cutover layer on top of the #900 dispatch rework: - Result publication resolves the validated target repositories from the downloaded worker artifacts (result.repo, fail-closed against the allowed owner) and mints its target-read token for those repositories instead of hard-coding openclaw/openclaw. - Intake hydrates state with a read-only, non-persisted credential and drops its contents-write grants; it never publishes from its checkout. - Result publication narrows the ClawSweeper app token and workflow permissions to read (state writes use the state credential). - A failed publisher rerun in self-heal is reported per run and never aborts subsequent publisher retries or cluster self-heal work. - Docs state the accurate guarantee: at-least-once workflow creation with exactly-once worker execution intent, receipt-gated worker-side dedupe, and job-path-only worker concurrency.
|
Codex review: needs real behavior proof before merge. Reviewed July 27, 2026, 6:19 PM ET / 22:19 UTC. ClawSweeper reviewWhat this changesThis PR routes cluster-repair intake and result publication through the durable state-materializer path, narrows workflow credentials, validates artifact-derived target repositories, and adds recovery-focused tests and operator documentation. Merge readiness⛔ Blocked until real behavior proof is added - 4 items remain Keep open: this is a substantial production repair-workflow cutover, and its own checklist says the live durable-intake, non-default-target publication, recovery, and replay proof has not yet run. The remaining code finding is low-risk, but real behavior proof is required before merge. Likely related people: RomneyDa appears to own the original cutover design; steipete is the recent contributor for the merged dispatch substrate and this rework. Priority: P2 Review scores
Verification
How this fits togetherCluster repair turns grouped GitHub reports into repair-worker jobs. This PR changes the handoff from intake through durable state materialization and then result publication, affecting production workflow dispatch, recovery, and the generated state ledger. flowchart LR
A[GitCrawl cluster snapshot] --> B[Cluster intake workflow]
B --> C[Authenticated durable intake]
C --> D[State materializer]
D --> E[Receipt-verified repair worker]
E --> F[Worker result artifacts]
F --> G[Validated target result publication]
G --> H[State ledger and self-heal]
Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Remove the release-owned changelog entry, then attach redacted live evidence for one allowed non-default target covering intake acceptance, receipt-verified dispatch, result publication, crash recovery, and idempotent replay before merging. Do we have a high-confidence way to reproduce the issue? No high-confidence current-main reproduction was established in this review. The supplied history identifies prior live failures that motivated the branch, but the branch's full production-like validation checklist remains unexecuted. Is this the best way to solve the issue? Unclear until the live proof runs: the durable materializer integration is consistent with the merged dispatch substrate, but this production workflow cutover needs observed end-to-end behavior before it is the confirmed best solution. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against be805237adc2. LabelsLabel justifications:
EvidenceAcceptance criteria:
What 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 (3 earlier review cycles)
|
…across the cluster cutover lanes The production CLAWSWEEPER_ALLOWED_OWNER variable is a comma-separated owner list (openclaw,steipete; issue #604 / allowedRepairOwners), but three cutover gates treated it as a single owner and failed closed on every dispatch: - repair-cluster-intake.yml 'Resolve target repository' rejected the list outright (live proof run 30302458881 failed here). - resolve-result-targets rejected the list before minting the reader token; it now validates every result owner against the parsed list and fails closed when results span multiple owners, since one publication mints one reader token. - restore-cluster-intake-job compared the job-path owner against the raw list string, which could never match. Proof enablement, no-op on main: the intake wake and worker dispatch now run on the invoking revision (GITHUB_REF_NAME / CLAWSWEEPER_DISPATCH_REF), and repair-publish-results gains a validated workflow_dispatch lane for a completed worker run while workflow_run events stay pinned to trusted default-branch code.
…r-intake The hosted runner's pnpm forwards the literal -- from 'pnpm run repair:publish-cluster-intake -- <intent>', so the CLI read '--' as the intent path and durable acceptance failed with ENOENT '.../--' (live proof run 30303202343). Use the first real positional and cover the separator in a CLI regression test.
…contract The cluster-intake acceptance policy (#900) requires at least two candidate references, but the importer offered single-open-member clusters and the selector could choose one, failing the whole intake run at durable acceptance with 'cluster intake job reference policy mismatch' (live proof run 30304188033). Filter selection to clusters with >= 2 open members and skip single-candidate clusters defensively in the job loop.
…a hard main pin The mid-job 'git checkout -B main origin/main' pin mixed main's package.json with a branch-built dist/ on the manual publication lane, so repair:state-delta-paths was missing at 'Commit result ledger' (live proof run 30308450188). workflow_run events keep publishing default-branch code; a workflow_dispatch publishes its own write-gated ref.
Summary
Rework of #873 by @RomneyDa — the 5/5 cutover layer of the cluster-fixer reliability stack, re-applied on top of #900 (the reworked #884 dispatch layer) and reconciled with what #879/#899/#900 changed on
main. RomneyDa's original commit is cherry-picked with authorship preserved; a maintainer fix commit addresses the review findings. #873 stays open for its audit and review history; this PR supersedes it.What the cutover does (unchanged from #873 in intent):
repair:publish-mainpublication to the durable cluster-intake append/materializer contract.allow_merge: false, and all existing production gate settings.Changes vs original #873 (review findings)
openclaw/openclaw). Newrepair:resolve-result-targetsresolves the target repositories from the downloaded worker artifacts (result.repo), fails closed on any repository outside the allowed owner or a malformed identity, falls back to the configured default when no result is present, and the reader token is minted for exactly those repositories after artifact download. Regression tests cover the non-default-target path.create-state-tokennow takes permission inputs; intake requestscontents: read/actions: readand hydrates withpersist-credentials: "false". Intake's central token and workflow permissions drop to contents-read — intake never publishes from its checkout. Result publication narrows its ClawSweeper app token and workflow permissions to read; state writes go through the state credential and the durable append only.gh run rerunin self-heal logs a warning per run and continues, so one transient API failure cannot suppress the remaining publisher retries or the cluster self-heal step.jobs/**/results/**), and the intake wake (state-materializer.yml -f intake_priority=true) drives the feat(repair): dispatch durable cluster jobs (rework of #884) #900 receipt-verified dispatch with claim-before-side-effect ordering.Validation
pnpm run build:all,pnpm run lint,pnpm run check:static(includes format check) — clean.resolve-result-targets,state-delta-paths,cluster-workflow-security,gitcrawl-store,cluster-intake-state,state-materializer,dispatch-receipt-owner,state-writer-workflow,actions-checkout-v7,clawsweeper— all pass.test:repaircategory: only the two known environment-sensitive macOS failures (process-tree-containmentLinux symbols,state-publication-batching-proof/private/varaliasing), both untouched by this diff and pre-existing on the base.Pre-merge live proof checklist (design only — not yet executed)
One real durable cluster intake → receipt-verified dispatch → worker execution → result publication on a low-traffic allowed-owner target (not
openclaw/openclaw), with all production gates preserved and no automerge.durable cluster intake accepted: N job(s), delivery cluster-intake:<slug>:<store-sha>; no state push from the intake run; the state token grant is read-only; astate-materializer.ymlrun starts withintake_priority=true.workflow_dispatch; exactly onerepair-cluster-workerrun per stable dispatch key; the state ledger entry carriesaccepted_intent_receipt; only the accepted job andresults/cluster-repair-intake/<slug>.jsonpaths are projected — record unrelated job/ledger blob hashes before and after and verify they are unchanged.Resolve result target repositoriesstep resolves the actual target from the artifact, the reader token is minted for that repository, and the publish/finalize steps succeed — this is the live proof for finding 1.repair-publish-resultsrun (< 3 attempts) present, triggerrepair-self-heal.ymlwithexecute=false; if a rerun fails, expect the per-run warning and theSelf-heal failed cluster runsstep still executing.force_store=true); expectalready accepteddedupe and no additional worker run.Credits
Original implementation and stack design by @RomneyDa (#873, on top of #881–#884). Maintainer rework applies the review findings from the #873 review thread.