Repository navigation
ci: report tests after PR retargeting - #1161
Conversation
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Replaces the e2e-retarget dispatcher with an edited trigger in e2e-tests and integration-tests. A base change now runs as a normal pull_request run against the new merge commit. Title or body edits skip in their own concurrency group, under a job name that cannot satisfy a required check. Reviewed 53fa8ef, full tier (CI workflow files). Static review: no build, the diff touches only workflow routing.
What I checked, and 6 candidates I ruled out
Read in full: e2e-tests.yml, integration-tests.yml at the head, plus the other workflows, to check that nothing else still referenced e2e-retarget.yml (none do).
Ruleset: master requires Run Integration Tests, Run Tests, SwiftFormat and e2e-status. The two renamed jobs are the two required names this PR touches.
Live runs: the retarget run 40734881494 is event: pull_request. Its detect-changes checked out Merge 53fa8ef… into 25f8225…, and 25f8225 is the current master tip, so the base change does validate the new merge candidate. The metadata-edit run 40735606784 skipped every job, and the skipped status job is reported under the unevaluated expression name, not e2e-status.
actionlint 1.7 on both changed workflows: clean apart from the custom namespace-profile-mac runner label.
Ruled out
- Metadata edit cancels a running validation: the group suffix is
metadata-<run_id>for those edits andvalidationfor everything else, so the two never share a group. A retarget does sharevalidationwith an in-flightsynchronizerun and cancels it, which is the point, since that run tested the old base. - Skipped metadata job satisfies a required check: a skipped check run counts as passing. These carry a different name, though, and run 40735606784 shows they never report as
e2e-statusorRun Integration Tests. - Retarget leaves E2E gated off by the path filter:
codeis forced true on a base change, so the paths-filter result against the new base cannot skip it. workflow_dispatchwithprchanges behaviour:github.event.actionis empty there, so it keeps thevalidationgroup (e2e-tests-<pr>-validation, as before) and the merge-ref checkout is unchanged.- Draft PR retargeted: the
draft == falsegate still skips it, andready_for_reviewstarts validation later, as before. - Fork PR retargeted: the removed dispatcher excluded forks because it dispatched with the repo token. A plain
pull_requestrun from a fork gets the same restricted context as itsopenedrun.
Merge confidence: 4/5, a CI change to two required checks whose hosted E2E and integration runs on this PR are still in progress.
|
Placed in the 3.1.0 milestone: it fixes the missing e2e and integration checks on stacked PRs retargeted to master, which 3.1.0 PRs hit today. This PR closes no issue, so it carries the milestone itself. |
pwltr
left a comment
There was a problem hiding this comment.
One P2 finding: rerunning the retarget helper fails before dispatching E2E and integration. Reproduced at f7bc57c: all 25 module tests pass with the normal first-attempt environment; with GITHUB_RUN_ATTEMPT=2, eight fail and 17 pass.
Reviewer model: gpt-6.1-sol
Reasoning effort: xhigh
coreyphillips
left a comment
There was a problem hiding this comment.
Two independent reviews.
needs changing before merge
- Merge verification rejects every PR whose base.sha is behind its merge commit (.github/scripts/retarget-tests.cjs:37).
dispatchRetargetTestsonly accepts a merge commit ifcommit.parents[0].sha === pr.base.sha. GitHub does not refreshpull_request.base.shawhen master advances; it changes only on a push or a base change. The test merge commit, by contrast, is rebuilt on a newer master. So manual recovery fails whenever master has moved since the PR's last push or retarget. The loop runs 10 times, then fails both required checks with "No verified PR merge commit is available". Live data for the two PRs the QA notes say to backfill:1039 base.sha=cc5f81fb merge abb24b20 parents=68bede62,88f75ea4 (master tip 25f8225b) 1119 base.sha=91f82baf merge e7ae10f8 parents=681f5aaa,828cb0a8How I confirmed it: I ran this branch'sretarget-tests.cjsin workflow_dispatch mode forpr=1039andpr=1119from a scratch script in /tmp.pulls.getandgit.getCommitwere real read-onlygh apicalls; check and dispatch writes were mocked. Both runs created two checks, failed both with "No verified PR merge commit is available", and dispatched nothing. Rechecking 20s later showed the samebase.shaand merge SHAs, so the real 2s sleeps would not help. The author's helper probe (run 40742226481) passed only because #1162'sbase.shaequalled the master tip at that moment. The rerun path (manual case 3) goes through the same helper viareportRetargetResult. After a long E2E run master has usually moved, so a rerun replaces both checks with failures, including an integration check that had passed. Suggested fix: requireparents[1] === head, and requireparents[0]to be master's tip or an ancestor of it (for example compare${parents[0]}...masterand acceptidenticalorahead). Do not compare againstpr.base.sha. Exact equality with the master tip is not enough either: #1039's merge parent 68bede6 is behind the tip. The test fixture setsbase.shaequal toparents[0], which is why the suite misses this.
worth doing, does not block
- Rerunning one suite resets and reruns both required checks (.github/scripts/retarget-tests.cjs:84-92). When a completed check's suite is rerun, the
phase: 'start'branch ofreportRetargetResultdispatchese2e-retarget.ymlfor the whole PR.dispatchRetargetTeststhen creates newe2e-statusandRun Integration Testschecks and dispatches both workflows. So rerunning a flaky E2E shard also puts an already passed integration check back to queued, and repeats roughly an hour of macOS integration testing. The reverse happens when integration is rerun. Consider passing the suite to the helper so it recreates and dispatches only that check. - Retarget dispatches put PR results on master's tip commit (.github/scripts/retarget-tests.cjs:48). The helper now dispatches both suites with
ref: 'master', where the old helper used the PR head branch. A workflow_dispatch run's check suite uses the tip of the dispatched ref ashead_sha, so every job check from these runs lands on master's current tip. That includese2e-status,Run Integration Testsand the reporter jobs. When a retargeted PR fails, master's latest commit shows a rede2e-statusandRun Integration Testsnext to its own push-triggered integration run. This misleads anyone reading master's commit status. The validation runs cited in the PR were dispatched on a probe branch whose tip was the PR head (run 40742705214: head 74580e9). They therefore could not show this. - Retarget validation forces full E2E even when no app code changed (.github/workflows/e2e-tests.yml:48). In retarget mode,
detect-changessetscodeto true throughinputs.retarget_run != ''and skipsdorny/paths-filter. On the pull_request path the same PR would skip E2E and reporte2e-statussuccess. As a result, a docs-only or journeys-only stacked PR runs the full E2E suite after retarget and can be blocked by a flaky run. The merge commit is already checked out, so the existing filter againstmastershould still work in this mode. - PR-controlled code now writes to master's Actions cache scope (.github/workflows/e2e-tests.yml:83). The dispatched runs are on
refs/heads/master. They check out the PR merge commit and run its composite./.github/actions/swift-packages, which savesSourcePackageson a cache miss. The E2E job also saves~/.npm, which has arestore-keysprefix. Caches saved there go into master's scope, which every branch and PR can restore. Before this PR, the dispatch ran on the PR branch and its caches stayed in that branch's scope. Only a same-repo author with write access could abuse this, and the effect is limited to CI runs. Still, it moves unreviewed branch code into the default-branch cache. Consider skipping cache saves in retarget mode.
nits
- Manual recovery succeeds silently when it validates nothing (.github/scripts/retarget-tests.cjs:16-19). If the dispatched PR is a draft, from a fork, closed, not based on master, or its head changed between reads,
dispatchRetargetTestsreturns early. The run is green, no checks are created and no message explains why. A maintainer backfilling a PR has to inspect the PR checks to notice. Acore.warningorsetFailedfor the manual path would make this visible. - Unused mocks left in the test fixture (.github/scripts/retarget-tests.test.cjs:26).
checks.listForRef(a Symbol) andgithub.paginateare defined infixture()but the module never calls them. They look left over from an earlier design.
coreyphillips
left a comment
There was a problem hiding this comment.
Rechecked after 1 new commit (4491e32). Nothing blocking remains.
addressed
- Merge verification rejects every PR whose base.sha is behind its merge commit (.github/scripts/retarget-tests.cjs:37). Fixed: retarget-tests.cjs:53-61 now requires parents[1] to be the head and compares parents[0] with master, accepting only identical or ahead. It no longer reads pr.base.sha. I ran the helper in manual mode against live #1039 and #1119, with real read-only pulls/getCommit/compare calls and mocked writes. Both compares returned ahead, both checks stayed queued, and both suites were dispatched with merges abb24b2 and e7ae10f.
- Rerunning one suite resets and reruns both required checks (.github/scripts/retarget-tests.cjs:84-92). Fixed: retarget-tests.cjs:113 now passes the finished check's suite to the helper, and lines 17-19, 38 and 67 limit check creation and dispatch to that suite. The tests at retarget-tests.test.cjs:196-212 pass. My live harness run for #1039 with suite=integration created one check and one integration dispatch.
- Retarget validation forces full E2E even when no app code changed (.github/workflows/e2e-tests.yml:48). Fixed: e2e-tests.yml:50 no longer forces code=true. Lines 52-66 run the path filter with base set to HEAD^1 and ref set to the pinned merge SHA. In paths-filter v4, a SHA base takes the two-commit git diff path, and fetch-depth 2 makes both commits local. e2eRetargetResult maps code=false to a successful 'No E2E code changes' check. This is confirmed from source and tests only, not from a hosted retarget run.
- PR-controlled code now writes to master's Actions cache scope (.github/workflows/e2e-tests.yml:83). Fixed: cache-mode: read is now set at e2e-tests.yml:79 and 197 and at integration-tests.yml:40. GitHub's dependency-caching reference documents this as enforced through scoped cache tokens, so saves are skipped. Hosted runs 40765129594 and 40765129059 at 4491e32 started with the key, so it parses.
- Manual recovery succeeds silently when it validates nothing (.github/scripts/retarget-tests.cjs:16-19). Fixed: retarget-tests.cjs:25-34 now calls core.setFailed on the manual path for draft, fork, other-base, closed and changed-head PRs. The five cases at retarget-tests.test.cjs:214-229 pass.
- Unused mocks left in the test fixture (.github/scripts/retarget-tests.test.cjs:26). Fixed: The fixture at retarget-tests.test.cjs:18-39 no longer defines checks.listForRef or github.paginate. A grep finds neither name in the test file or the module.
still open
- Retarget dispatches put PR results on master's tip commit (.github/scripts/retarget-tests.cjs:48). The helper now dispatches both suites with
ref: 'master', where the old helper used the PR head branch. A workflow_dispatch run's check suite uses the tip of the dispatched ref ashead_sha, so every job check from these runs lands on master's current tip. That includese2e-status,Run Integration Testsand the reporter jobs. When a retargeted PR fails, master's latest commit shows a rede2e-statusandRun Integration Testsnext to its own push-triggered integration run. This misleads anyone reading master's commit status. The validation runs cited in the PR were dispatched on a probe branch whose tip was the PR head (run 40742705214: head 74580e9). They therefore could not show this. The helper still dispatches with ref master (retarget-tests.cjs:70), so the native e2e-status and Run Integration Tests job checks still land on master's tip. The run-name labels help identify the runs but do not remove those checks. Deferring this to #1165 (open, 3.2.0) is reasonable for a non-blocking point, but the response confirms the point rather than rebutting it.
new since the last review
worth doing, does not block
- Manual e2e-tests dispatch with only a PR number now fails at detect-changes (.github/workflows/e2e-tests.yml:56-66). Since 4491e32, a manual
e2e-tests.ymldispatch that setsprbut notretarget_runfails indetect-changes, so it never tests the PR. The cause is at e2e-tests.yml:66, which now passesref: refs/pull/N/mergetodorny/paths-filter. Themerge-basestep runs only in retarget mode, sobasestaysmaster, and paths-filter takesgetChangesSinceMergeBase('master', 'refs/pull/N/merge'). ItsgetLocalRefrunsgit show-ref refs/pull/N/mergeand only accepts matches underrefs/heads,refs/tagsorrefs/remotes/origin. But actions/checkout stores the pull ref asrefs/remotes/pull/N/merge, so the lookup never matches. The action then throwsCould not determine what is refs/pull/N/merge. I confirmed this by reading the paths-filter v4 source (main.tsandgit.ts). In a scratch repo,git show-ref refs/pull/7/mergereturned nothing with onlyrefs/remotes/pull/7/mergepresent. The job failure leavescodefalse, soe2e-statusreports "E2E skipped" while the run as a whole is red. On master,gh workflow run e2e-tests.yml --ref <pr-branch> -f pr=N, the old retarget command, still filters correctly. A fix: run the merge-base step wheneverinputs.pris set, and output bothHEAD^1andHEADSHAs forbaseandref. Two SHAs take the two-commit diff path that already works for retarget. - Read-only cache on PR E2E builds drops per-PR SwiftPM cache reuse (.github/workflows/e2e-tests.yml:78-79).
cache-mode: readonbuild-local(e2e-tests.yml:79) applies to normalpull_requestruns as well as retarget dispatches. Before this change, a PR run that missed the cache savedSourcePackagesinto its ownrefs/pull/N/mergescope, so later pushes on the same PR could restore it. GitHub's docs saypull_requestsaves are already confined to that scope, so they never reached master's. Now every push re-resolves from scratch when master has no cache for the PR's Xcode 26.2 key. Per.github/actions/swift-packages, that means re-cloning bitkit-core's history of over 13 GB. The 26.2 key is only seeded on master by the nightlye2e-staging. So this affects every push of a PR that changesPackage.resolved, and every PR between a master dependency bump and the next nightly. Integration loses little, becauseunit-testson the same PR still saves the Xcode 16.4 key into the PR scope. I confirmed the behavior from the cache-mode reference, not from a hosted miss. If cache-mode accepts an expression,readonly wheninputs.retarget_runis set would keep the protection where it matters. Otherwise this is a cost to accept knowingly.
talosmachina
left a comment
There was a problem hiding this comment.
Re-review of 679d9b5 after 53fa8ef. No findings. My earlier review had 0 findings, so there is nothing to walk. The approach changed since then: the edited trigger moved back out of the test workflows, and e2e-retarget.yml now creates e2e-status and Run Integration Tests on the PR head, pins a verified merge commit, and dispatches both suites against master definitions. Each child reports to its own check id. Full tier (CI workflows). Static review plus the module tests: no app build, since the diff touches only workflow routing.
What I checked, and 6 candidates I ruled out
Read in full: retarget-tests.cjs, e2e-retarget.yml, e2e-tests.yml, and the integration-tests.yml diff at 679d9b5, plus .github/actions/swift-packages.
Module tests: node --test .github/scripts/retarget-tests.test.cjs gives 40/40 at the head, and 40/40 again with GITHUB_RUN_ATTEMPT=3.
Live runs: validation PR #1162 shows both PR-head checks created on 74580e9 and moved to in_progress by the children. The pinned merge 17f3d81 is Merge 74580e9 into 25f8225, and 25f8225 was the master tip. The manual pr=1039 probe 40768094210 passed checkout, SHA resolution and paths-filter. The 4491e32 -> 679d9b5 diff is the detection fix plus the fail-closed e2e-status step.
Earlier threads: all review threads have answers in their threads. The dispatch-ref check placement is deferred to #1165, and the read-only cache cost is accepted in Gaps. I am not reopening either.
Ruled out
- Stale reporter overwrites a newer validation:
reportRetargetResultre-reads the PR head and requiresexternal_id=retarget:<run>-<attempt>:<name>on a check bound to that head. An old child cannot touch a new generation's check. - Old app merge without the reporter script: the reporter loads from a sparse checkout of
github.workflow_sha, not from the app merge, so backfilling #1039/#1119 does not depend on their merges containing this file. - Merge candidate built on a base that is not master:
parents[1] == headpluscompareCommits(parents[0], master)in {identical, ahead} rejects behind or diverged bases. The tests cover both. - Rerun of a completed check loops: phase
starton a completed check dispatches the helper with only that suite, then fails the child. The helper creates a new generation, so the guard does not fire again on the new run. - Docs-only retarget reports success while detection failed:
e2eRetargetResultrequiresdetect-changesande2e-statusto succeed before it mapscode == falseto not_required. The newe2e-statusstep fails when detection did not succeed. - Integration concurrency across PRs: the group is now keyed on
pull_request.number || inputs.pr || ref, so two PRs' dispatches no longer cancel each other on the sharedmasterref.
Merge confidence: 4/5. Two required checks are rerouted, and the hosted E2E and integration runs at 679d9b5 are still pending, so the end-to-end retarget path has no green run at this head yet.
Reviewer model: claude-opus-5-5
Reasoning effort: Not exposed (the run metadata does not report it; only a configured default is available)
pwltr
left a comment
There was a problem hiding this comment.
Reviewed 679d9b5729; no additional actionable findings. The 40 helper tests pass normally and with GITHUB_RUN_ATTEMPT=2, and current-head CI is green. Live retarget/rerun reporting was not exercised here. The documented cache tradeoff is accepted; native check isolation remains tracked in #1165.
Reviewer model: gpt-6.1-sol
Reasoning effort: xhigh
|
@piotr-iohk Merging this PR on @pwltr's approval of head 679d9b5, with checks green and no open threads. It changes CI only, so no device run applies. |
|
@piotr-iohk Merged, as it was approved and green. |
coreyphillips
left a comment
There was a problem hiding this comment.
Rechecked after 1 new commit (679d9b5). Nothing blocking remains.
addressed
- Manual e2e-tests dispatch with only a PR number now fails at detect-changes (.github/workflows/e2e-tests.yml:56-66). Fixed: At
e2e-tests.yml:56-68, any dispatch that setsprnow writesHEAD^1andHEADSHAs. paths-filter receives both SHAs asbase/ref. I checked paths-filter v4main.ts: a SHA base on a non-PR event takesgetChanges(baseSha, head), skipping the ref lookup that failed. In a scratch repo, a depth-2 fetch of a pull merge ref kept the first parent present, and the parent..head diff listed only the PR's file. The new step ate2e-tests.yml:383-387also failse2e-statuswhen detection does not succeed, which closes the 'E2E skipped' half.
still open
- Retarget dispatches put PR results on master's tip commit (.github/scripts/retarget-tests.cjs:48). The helper now dispatches both suites with
ref: 'master', where the old helper used the PR head branch. A workflow_dispatch run's check suite uses the tip of the dispatched ref ashead_sha, so every job check from these runs lands on master's current tip. That includese2e-status,Run Integration Testsand the reporter jobs. When a retargeted PR fails, master's latest commit shows a rede2e-statusandRun Integration Testsnext to its own push-triggered integration run. This misleads anyone reading master's commit status. The validation runs cited in the PR were dispatched on a probe branch whose tip was the PR head (run 40742705214: head 74580e9). They therefore could not show this. The code is unchanged:retarget-tests.cjsstill dispatches withref: manual && event.inputs.workflow_ref || 'master', so the job checks still land on master's tip. The new run-name labels help, and deferring the point to open issue #1165 (milestone 3.2.0) is reasonable for a non-blocking point. That deferral does not show the point wrong, so I am leaving it open rather than holding the merge on it. - Read-only cache on PR E2E builds drops per-PR SwiftPM cache reuse (.github/workflows/e2e-tests.yml:78-79).
cache-mode: readonbuild-local(e2e-tests.yml:79) applies to normalpull_requestruns as well as retarget dispatches. Before this change, a PR run that missed the cache savedSourcePackagesinto its ownrefs/pull/N/mergescope, so later pushes on the same PR could restore it. GitHub's docs saypull_requestsaves are already confined to that scope, so they never reached master's. Now every push re-resolves from scratch when master has no cache for the PR's Xcode 26.2 key. Per.github/actions/swift-packages, that means re-cloning bitkit-core's history of over 13 GB. The 26.2 key is only seeded on master by the nightlye2e-staging. So this affects every push of a PR that changesPackage.resolved, and every PR between a master dependency bump and the next nightly. Integration loses little, becauseunit-testson the same PR still saves the Xcode 16.4 key into the PR scope. I confirmed the behavior from the cache-mode reference, not from a hosted miss. If cache-mode accepts an expression,readonly wheninputs.retarget_runis set would keep the protection where it matters. Otherwise this is a cost to accept knowingly. Codex still sees it:.github/workflows/e2e-tests.yml:81still applies read-only caching to ordinary PR builds. The response explicitly accepts losing new per-PR cache saves; the rejected conditional expressions do not remove or rebut that non-blocking cost.
Retargeting an iOS stacked PR to
mastercurrently leaves two CI gaps: E2E runs through a separate dispatch whose result is absent from the PR checks, and integration tests never start. This PR makes the retarget helper start both suites and publish their actual outcomes as required PR checks.Observed cases at the investigated heads:
88f75ea4828cb0a8Description
e2e-statusandRun Integration Testschecks on the PR head before dispatching tests, then updates those same check IDs as the suites run and finish.master, while preserving the feature branch used to select companion E2E coverage.Out of Scope
Design
N/A — no UI changes.
Preview
N/A
QA Notes
Setup
GitHub access to edit a same-repository ready PR into
master. No device setup is required to verify workflow routing. After merge, use the normal parent-to-master retarget event, or manually dispatche2e-retarget.ymlwith the PR number and default workflow refmaster.Already-retargeted PRs do not replay their earlier retarget events when this fix merges. After merge, backfill #1039 and #1119 by dispatching the helper with
pr=1039andpr=1119respectively, using workflow refmaster.Pre-merge reporting validation uses
gh workflow run e2e-retarget.yml --repo synonymdev/bitkit-ios --ref ci/ios-retarget-checks -f pr=1161 -f workflow_ref=ci/ios-retarget-checks. The workflow-ref override selects the proposed definitions; the app checkout still uses the verified PR merge commit.Journeys
N/A — no user-visible behaviour change.
Manual Tests
1. Retarget a ready PR from a parent branch to
master→ E2E and integration each have a real required check that progresses from queued/running to the suite's actual outcome — GitHub PR editing is not in Capabilities.2. While validation is running, edit only the PR title or description → no new E2E/integration workflow runs or required-check copies appear, and active validation continues — GitHub PR editing is not in Capabilities.
3. Rerun a completed dispatched E2E build or shard → the old attempt stops and requests fresh helper validation with a new check for only that suite; the other suite's completed check is retained — GitHub Actions reruns are not in Capabilities.
4. Rerun the retarget helper → its module tests pass at workflow attempt 2 and eligible validation starts — GitHub Actions reruns are not in Capabilities.
5. Manually recover a draft, closed, fork or non-master PR → the helper fails with an eligibility message — GitHub Actions dispatch is not in Capabilities.
6. Recover an older PR whose base metadata differs from its merge parent → verify master ancestry and test the pinned merge; reporter loading does not depend on the app merge containing this CI fix — GitHub Actions dispatch is not in Capabilities.
7. Retarget a docs-only PR → no E2E app build or suite starts; the PR check says
No E2E code changes— GitHub PR editing is not in Capabilities.8. Dispatch
e2e-tests.ymlwith onlypr=<number>→ change detection compares the checked-out merge's parent/head SHAs and starts E2E when code changed; detection errors faile2e-status— GitHub Actions dispatch is not in Capabilities.Automated Checks
retarget-tests.test.cjs— 40 tests cover retarget filtering, stale-base ancestry, later helper attempts, dispatch errors, failure/cancellation mapping, check ownership, suite-specific retries, no-code results and manual eligibility.node --test .github/scripts/retarget-tests.test.cjsnormally and withGITHUB_RUN_ATTEMPT=2— 40 passed in each run, zero failures/skips.actionlint1.7.12 on all three changed workflows with the existing custom runner label configured; passed after narrowly ignoring its unknowncache-modekey, which is documented by GitHub but unsupported by this linter version. Hosted GitHub accepted the syntax and started the jobs. Shellcheck and pyflakes were not run.git diff --check; passed.Evidence
Current-head
679d9b57hosted results: E2E 40768441460 passed on its first test attempt; integration 40768440554, unit tests 40768440511, lint and translation validation passed. Talos re-review on this head reported no findings.Follow-up
679d9b57fixes PR-number-only manual dispatch by passing the local merge parent/head SHAs to paths-filter, and makes nativee2e-statusfail when detection does not succeed. Hosted isolated probe 40768094210 used the exact updated detection job with onlypr=1039, passed the real checkout/filter and explicit SHA/code assertions, and launched no app suite or PR-head check. Scoped actionlint and diff checks passed; independent review found no defects. The module is unchanged from its 40-test validation at4491e326. The new signed commit is GitHub Verified.Review fixes at
4491e326pass all 40 module tests normally and at attempt 2, scoped workflow lint andgit diff --check. Independent review found no further defects after the changes. A read-only harness against live #1039/#1119 accepted their verified master-ancestor merge parents and selected both pinned merges with writes mocked; neither backfill was launched. Hosted CI started for that revision; see current-head follow-up below. GitHub reports the signed commit as Verified.At preceding source
f7bc57ca, the implementation passed 25 module tests, actionlint on all three workflows andgit diff --check. Independent reviews found and corrected stale-result races, companion-branch selection, cross-PR concurrency and completed-check lifecycle handling. All published fix commits are signed and GitHub reports Verified.Native retarget was exercised in temporary validation PR #1162: pull_request helper 40742671425 dispatched E2E 40742705214 and integration 40742708445. GitHub's PR required-check list showed queued
e2e-status(123008197780) andRun Integration Tests(123008202069), with no skipped required copies. A probe-only adapter selected the proposed workflow definitions before merge; the reporter code was the final implementation.At preceding source
b3c0b8cf, actual child workflows updated their dedicated checks to in progress. The intentional integration cancellation in run 40738808201 completed its check with failure, and invalid-ref dispatch controls produced failed checks. No app-test pass is inferred from those controls.GitHub preserves completed check conclusions. The final retry guard therefore requests a new helper validation rather than trying to reopen a completed check. Isolated closed-check probe 40742192584 triggered fresh helper 40742226481, which created new queued checks and dispatched both suites while retaining the old failure. The diagnostic adapter is confined to #1162 and is not part of this PR.
Hosted CI on
f7bc57ca: E2E, integration, unit tests, lint and translation validation passed. The E2E job completed successfully on its second test attempt.Gaps
All applicable hosted wallet CI passed at current head
679d9b57. Results at older revisions remain historical evidence. Runtime cache-token enforcement and the expanded retarget routing still need hosted observation. E2E/integration jobs now restore caches only on normal runs as well; other cache producers are unchanged. Isolated dispatch probes confirmed GitHub rejectsinputsandgithubcontexts incache-modewith HTTP422, so a conditional read/write policy cannot be used here. This knowingly loses new per-PR Xcode26.2 cache saves on a miss; restores remain available.The automatic production dispatcher will use workflow definitions from
masterafter merge; pre-merge probes selected the proposed definitions explicitly. App code and existing build/test commands are unchanged; app/device tests were not run locally.Models used
gpt-6.1-sol(reasoning:high)gpt-6.1-sol(reasoning:high)gpt-6.1-sol(reasoning:high)