Confirm sync and closeout CI dispatch without holding runners for completion

UN
24m ago
+976-243

The reusable sync and closeout jobs must release their runner while caller CI runs. Historical fleet runs averaged about 85 runner-minutes; one measured sync finished its real work in 44 seconds and then polled for two hours. #229 already removed that completion loop; this completes the bounded dispatch receipt and reporting contract.

Built on #245's head (a69388d2d93ba15fd8f22840f3b9c8780c78f36a) while it was open. Merge #245 first; callers only need the workflow pin bump from the #238 sweep.

  • Keep caller-head dispatch and existing protected, SHA-guarded native squash auto-merge. Add a separate appearance-only receipt step: one shared 60-second budget across selected workflows, at most 12 discovery rounds, ten-second hard-killed API calls. Queued runs count immediately; no conclusion or completion is polled.
  • Match workflow, branch, head SHA, dispatch event and creation time. Registration timeout or lookup failure reports timed_out without failing sync or revoking auto-merge. Genuine dispatch failures still fail before arming.
  • Export the PR URL, registered run URLs, already parked run URLs and registration status through job/reusable outputs and the job summary. The existing hourly approval sweep or a maintainer handles parked native runs; required checks decide auto-merge and the next scheduled rebuild handles blocked landing/base advances.
  • Retain gated import, idempotency, redaction, sync holds, #230 ownership and closeout attribution/revocation. Held closeout PRs now retain reporting without arming. Other reusable workflows have no completion wait. The non-reusable release continuation is separately tracked by pm-github-sgyr.

Expected ordinary duration: under two minutes for the measured 44-second workload plus at most 60 seconds of registration discovery. This is a budget/expectation, not a new live fleet timing measurement.

Validation:

  • node --test --test-concurrency=2 test/ci-handoff-workflow.test.ts test/bot-pr-workflow.test.ts test/self-versioned-workflows.test.ts test/workflow-rule-names.test.ts test/daily-sync-alert.test.ts: 199/199 passed.
  • NPM_CONFIG_USERCONFIG=/dev/null node --test --test-concurrency=2 --test-name-pattern="workflow credentials|earlier armed auto-merge|informational parked-run failure|previous auto-merge is revoked on workflow exit: maintenance" test/import-gate.test.ts test/closeout-workflow.test.ts: 4/4 passed after build.
  • bun test --timeout 120000 test/ci-handoff-workflow.test.ts: 21/21 passed; the full updated Node workflow group also passed through pinned pm test --run --progress.
  • npm run build, npm run typecheck, npm run build:test, npm run lint, npm run privacy, npm run docstring, npm run verify:release-publish-attestation, npm run changelog:full and npm run changelog:check: passed. actionlint is unavailable.
  • Revert proof: in disposable copies, restore each historical dispatch completion-wait shell from the parent of 6ccb293; the new every-reusable-step contract fails independently for sync and closeout (one failure each). Restore the fixed workflows and the contract passes. Missing, denied, timed-out and partial registration all return success and an informational timeout receipt.
  • No authored production TypeScript/JavaScript source changed. Coverage thresholds remain 100/100/100/100; CI certifies the full npm/Bun release gates under the targeted task scope.

Tracker: pm-github-fxhd, reused for #228 and left in progress for orchestrator verification. README and migration notes document the handoff and pin-only adoption.

Additional review evidence at 8090147f1716883c9f35ac0de904517a0c22d6f4: controlled-clock cases exhaust the shared deadline across workflow lookups and forbid a late third lookup while retaining partial URLs. Real GNU timeout cases kill a genuinely stuck lookup after ten seconds and report successful informational timeout receipts. Removing the admission guard or shortening the real timeout independently fails the corresponding behavioral tests (four expected failures across sync/closeout).

Review thread PRRT_kwDOTbN4pM63g99s / comment 4574827470 is addressed by test commit 8090147f1716883c9f35ac0de904517a0c22d6f4; it is left open for orchestrator response, with no thread reply, resolution or reaction.

Final-head CI: CI, CodeQL. Both are queued at handoff preparation. The original bounded CI cutoff is retained; pending checks are not certification.

Summary by Sourcery

Release sync and closeout runners after dispatch by replacing completion polling with bounded CI registration receipts and safer workflow-version resolution.

New Features:

  • Add bounded, appearance-only caller CI registration receipts and reusable outputs for sync and closeout workflows.
  • Default reusable workflows to the release version declared by their immutable workflow commit while retaining explicit version holds with warnings.

Bug Fixes:

  • Prevent sync and closeout jobs from holding runners while waiting for caller CI completion.
  • Ensure registration failures and timeouts remain informational without disrupting successful sync or closeout handling, while genuine dispatch failures still fail.

Enhancements:

  • Preserve protected native auto-merge and closeout attribution safeguards while reporting parked and registered run URLs.
  • Validate the selected extension release before tracker writes and document the workflow-version and CI-handoff migration contracts.

Documentation:

  • Document bounded CI handoff behavior, reusable outputs, caller migration, and fleet version-hold inventory.

Tests:

  • Add workflow-level coverage for registration timing, partial and failed discovery, timeout handling, output wiring, and prevention of completion polling.
  • Update version-resolution tests for manifest-based release selection and registry preflight validation.

Chores:

  • Update the unreleased changelog and project tracking records.

Summary by cubic

Stops the gated sync and closeout workflows from holding a runner while caller CI runs. They now confirm that caller runs appeared within one 60-second budget, then report their URLs and status without polling for completion.

  • Replaces the completion-wait loop with an appearance-only receipt step: one shared 60-second budget, at most 12 discovery rounds, ten-second hard-killed API calls. Queued runs count immediately; no conclusion or completion is polled.
  • Missing, denied, timed-out, or partial registration reports timed_out without failing sync, closeout, or arming auto-merge.
  • Exports the PR URL, registered run URLs, parked run URLs, and registration status through job and reusable outputs and the job summary. Held closeout PRs keep reporting without arming.
  • Defaults reusable workflow installation to the workflow's package release so callers can drop pm-github-version; explicit version holds still install the requested version but warn when it differs.

Migration: Callers must move the workflow pin to a release containing #238 and remove pm-github-version in the same change, since a pin update alone keeps stale inputs as explicit holds. docs/no-ci-polling-migration.md and docs/workflow-version-callers.md cover adoption.