Skip to content

ci: run and block on orchestration e2e for orchestration-source PRs - #19815

Open
Jinwoo-H wants to merge 2 commits into
mainfrom
ci/orchestration-e2e-pr-gate
Open

Jinwoo-H wants to merge 2 commits into
mainfrom
ci/orchestration-e2e-pr-gate

Conversation

@Jinwoo-H

@Jinwoo-H Jinwoo-H commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​301 $\color{#cf222e}{\Huge{\mathbf{−}}}$​2 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​299
Prod 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​125 $\color{#cf222e}{\Huge{\mathbf{−}}}$​12 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​113

What the user notices

Before: A PR that changes only orchestration source merges with zero e2e specs run.
That is what happened to #19542 on 2026-09-08: its e2e job reported skipping, it merged, and
orca orchestration send --to <handle> between two plain terminals — the first command the
orchestration skill guide teaches — started failing with Run is required. Users reported
"orchestration stopped working after updating". The spec that catches it,
tests/e2e/orchestration-idle-mail-delivery.spec.ts "keeps unbound direct mail durable", had
existed since #12584 in August. It went red on main's scheduled e2e for two runs, which blocks
nothing, and #19684 then renamed it to "refuses unbound direct mail" and asserted the error —
merged as a test-only change hours before the first user report.

After: The same PR selects the 10 orchestration/worker specs, runs them in a new
orchestration e2e (blocking) check, and verify — the required aggregate — fails if any of
them fails. The author sees a red required check on the PR instead of a user seeing the error
after updating.

The delete question

Net add. What was deliberately not added is where the work went.

  • No new path list. hasOrchestrationE2eChange is derived from the route's own spec list,
    not from a second copy of the prefixes. That is the mistake hasSshSourceChange's comment
    already documents ("two lists that must agree is how that drifted").
  • No special case in pr-code-change-scope.mjs. Naming the code_paths output
    orchestration_e2e rather than orchestration_e2e_should_run means verify's existing strict
    loop — which derives every <JOB>_SHOULD_RUN from code_paths.outputs.<job> — enforces the
    job with zero new mechanism. The only line added to verify's script is one check_job call.
  • No duplicate run. The advisory e2e job's test_files is now the selection minus this
    lane's specs, so no PR pays for the same 10 specs twice. selectPrE2eSpecs is unchanged and
    still the single authority; the two lanes are a partition of its output, and a contract test
    asserts advisory ∪ blocking == the full selection for every case it exercises.
  • One assertion deleted, not added. release-e2e-dispatch-contract.test.mjs pinned the
    literal e2e-build-out on the upload and on both downloads. Three literals became one
    comparison against the upload's own name, which is what the test was really guarding: upload
    and download must agree. Strictly stronger — a mutant that renames one download still fails it.
  • No config/reliability-gates.jsonc entry. The existing "keeps source-routed sentinels
    registered to their reliability gates" test names five specific gate ids and does not demand
    one per route. Every gate in that manifest is a per-invariant record with an oracle,
    assertion refs, and evidence runs; this change adds no invariant and no spec, so an entry
    would be fabricated provenance. pnpm run check:reliability-gates passes unchanged.

Proof

The gate cannot be executed locally — GitHub Actions is not runnable here — so the proof is in
two halves: the routing output that decides which specs the job runs, and the spec itself going
red on the reintroduced regression. Both were run on a local scratch state that re-applies the
#19542 deletion in src/main/runtime/orchestration/db/messages/message-insert.ts (the unbound-Run
INSERT OR IGNORE block replaced by const runId = msg.runId; if (!runId) throw new Error('Run is required')), never committed and reverted afterwards with
git checkout -- src/main/runtime/orchestration/db/messages/message-insert.ts.

1. Routing: the file #19542 broke now selects the orchestration specs

$ printf 'src/main/runtime/orchestration/db/messages/message-insert.ts\n' | node config/scripts/pr-e2e-source-routing.mjs
[pr-e2e] orchestration.runtime-and-cli: tests/e2e/completed-worker-retirement-resume.spec.ts, tests/e2e/orchestration-idle-mail-delivery.spec.ts, tests/e2e/orchestration-idle-mail-restore.spec.ts, tests/e2e/orchestration-legacy-worker-missing-terminal-recovery.spec.ts, tests/e2e/orchestration-legacy-worker-restart-recovery.spec.ts, tests/e2e/orchestration-low-level-dispatch-release.spec.ts, tests/e2e/orchestration-worker-settlement-release-cli.spec.ts, tests/e2e/orchestration-worker-terminal-visibility.spec.ts, tests/e2e/orchestration-worker-transcript-providers.spec.ts, tests/e2e/settled-worker-tab-survives-restart.spec.ts
["tests/e2e/completed-worker-retirement-resume.spec.ts","tests/e2e/orchestration-idle-mail-delivery.spec.ts","tests/e2e/orchestration-idle-mail-restore.spec.ts","tests/e2e/orchestration-legacy-worker-missing-terminal-recovery.spec.ts","tests/e2e/orchestration-legacy-worker-restart-recovery.spec.ts","tests/e2e/orchestration-low-level-dispatch-release.spec.ts","tests/e2e/orchestration-worker-settlement-release-cli.spec.ts","tests/e2e/orchestration-worker-terminal-visibility.spec.ts","tests/e2e/orchestration-worker-transcript-providers.spec.ts","tests/e2e/settled-worker-tab-survives-restart.spec.ts"]

$ ... --orchestration-source
true
$ ... --orchestration-specs
["tests/e2e/completed-worker-retirement-resume.spec.ts", ... same 10 ...]
$ ... --advisory-specs
[]

--orchestration-source true is what turns code_paths.outputs.orchestration_e2e into 'true',
which is what makes the job run and what verify's strict loop requires to be success.
--advisory-specs [] is the no-duplicate-run half: the advisory e2e job does not start.

On origin/main today the same input prints [] and selects nothing.

2. The routed spec is red on the regression

$ ORCA_BACKGROUND_LAUNCH=1 npx playwright test tests/e2e/orchestration-idle-mail-delivery.spec.ts \
    --config tests/playwright.config.ts --project electron-headless --workers=1 -g "unbound direct mail"
[e2e] Building Electron app with electron-vite build --mode e2e...
  ✘  1 [electron-headless] › tests/e2e/orchestration-idle-mail-delivery.spec.ts:356:7 › orchestration push-on-idle mail delivery › keeps unbound direct mail durable without pointing to an unsafe check (4.5s)

  1) ... keeps unbound direct mail durable without pointing to an unsafe check

    Error: Run is required Orchestration mutation request ID: c4545dac-d3ad-4d9b-871e-820ac540cc46.

        at RuntimeClient.call (src/cli/runtime/client.ts:172:13)
        at sendMail (tests/e2e/orchestration-idle-mail-delivery.spec.ts:190:16)
        at tests/e2e/orchestration-idle-mail-delivery.spec.ts:368:23

  1 failed
EXIT=1

That is the user's error string, produced by the real runtime through the real RPC path — not a
mocked client. (src/cli/handlers/orchestration.test.ts and src/cli/index-orchestration.test.ts
vi.mock the runtime client, which is why the unit layer stayed green through #19542.)

3. Same command, same rebuild, after reverting the scratch edit

$ git checkout -- src/main/runtime/orchestration/db/messages/message-insert.ts
$ ORCA_BACKGROUND_LAUNCH=1 npx playwright test tests/e2e/orchestration-idle-mail-delivery.spec.ts \
    --config tests/playwright.config.ts --project electron-headless --workers=1 -g "unbound direct mail"
[e2e] Building Electron app with electron-vite build --mode e2e...
  ✓  1 [electron-headless] › tests/e2e/orchestration-idle-mail-delivery.spec.ts:356:7 › ... keeps unbound direct mail durable without pointing to an unsafe check (9.7s)
  1 passed (26.7s)
EXIT=0

Both runs rebuilt out/ (no SKIP_BUILD), so neither read a stale bundle.

Two callers, one run

pr.yml now invokes the reusable e2e.yml twice. Both invocations start its build job, and
actions/upload-artifact v4+ fails when two jobs in one workflow run upload the same name.
Without a fix, a PR touching orchestration source and any other routed source would kill
whichever build uploaded e2e-build-out second — taking the new required check red for a
reason unrelated to the PR. playwright-traces-changed had the same collision when a spec failed
in both lanes.

e2e.yml gains an optional artifact_suffix workflow_call input (default ''), appended to
every artifact name it uploads or downloads — all nine steps, not only the two that can collide
today. A bare name left behind would fail only when a spec fails in both lanes, i.e. exactly when
the suite is already telling you something, and would hide it.

Job Artifact Suffixed
build e2e-build-out (upload) yes
e2e shards, changed-e2e, ssh-docker-watcher-isolation, ssh-localhost e2e-build-out (download ×4) yes
e2e shards playwright-traces-${{ matrix.shard_name }} yes
changed-e2e playwright-traces-changed yes
ssh-docker-watcher-isolation playwright-traces-ssh-docker-watcher-isolation yes
ssh-localhost localhost-ssh-traces yes

The advisory e2e caller passes nothing; orchestration_e2e passes -orchestration. Schedule
and dispatch runs pass no inputs at all, so they keep the artifact names they have always used.
e2e.yml has no concurrency: at workflow or job level (confirmed — a group would serialize or
cancel one call against the other), and a contract test now asserts it stays that way. pr.yml
holds the only two callers of e2e.yml in the repo.

Two new contract tests plus the reworked one, each mutation-checked:

$ # mutant: orchestration_e2e drops artifact_suffix
  × gives each caller of e2e.yml its own artifact namespace
    AssertionError: duplicate artifact_suffix among , : expected 1 to be 2

$ # mutant: one trace name loses the suffix
  × suffixes every artifact e2e.yml uploads or downloads
    AssertionError: {"name":"playwright-traces-changed",...}: expected 'playwright-traces-changed' to match /\$\{\{ inputs\.artifact_suffix \}\}$/

$ # mutant: one download drifts from the upload name
  × hands the built relay artifact to every E2E run command
    AssertionError: expected 'e2e-build-out-typo${{ inputs.artifact...' to be 'e2e-build-out${{ inputs.artifact_suff...'

actionlint resolves the caller/callee input contract, so a typo in the input name is a hard
error rather than a silently ignored with: key:

$ actionlint .github/workflows/pr.yml     # with `artifact_suffixx:` deliberately typo'd
.github/workflows/pr.yml:969:7: input "artifact_suffixx" is not defined in "./.github/workflows/e2e.yml" reusable workflow. defined inputs are "artifact_suffix", "ref", "ssh_source_changed", "test_files" [workflow-call]

Wire / SSH / folder workspace

  • Remote wire: not affected. Nothing here changes an RPC param, a stream frame, or what a
    host publishes. It is CI routing plus one workflow job.
  • SSH: not affected, and deliberately not covered. None of the 10 routed specs runs against an
    SSH host; the Docker-SSH lane is selected by hasSshSourceChange, which this change does not
    touch (the new call to selectAdvisoryPrE2eSpecs inside shouldRunReusablePrE2e sits behind an
    unchanged hasSshSourceChange(...) || short-circuit, so an SSH-source PR still starts the
    reusable workflow even when the advisory list is empty). An orchestration change that only
    breaks on a remote execution host still merges green — see the report.
  • Folder (non-git) workspaces: not affected. The routed specs use whatever workspace their
    own fixtures build; no new assumption about git worktrees is introduced here.
  • Cross-platform: the new job runs on ubuntu-latest through the existing e2e.yml
    changed-e2e lane. Nothing added assumes macOS. orchestration_e2e is a plain reusable-workflow
    call with no new shell.

Testing

Gate Result
pnpm tc tc EXIT=0
pnpm test on the 6 affected test files run 1: Test Files 6 passed (6) / Tests 109 passed (109)
same command, second run (flake) run 2: Test Files 6 passed (6) / Tests 109 passed (109)
pnpm test config/scripts (whole directory) run 1: Test Files 184 passed | 2 skipped (186) / Tests 1539 passed | 10 skipped (1549)
same, second run (flake) run 2: Test Files 184 passed | 2 skipped (186) / Tests 1539 passed | 10 skipped (1549)
pnpm run check:code-quality:changed code quality: 0 new finding(s) across 4 changed file(s). / type-aware code quality: 0 new finding(s) / React Doctor: 0 new finding(s) / Changed-code quality gate passed since aac38d698ff7.
pnpm run check:react-doctor:changed orca no score 0 issues
actionlint .github/workflows/pr.yml .github/workflows/e2e.yml actionlint EXIT=0, no output (v1.7.12 from Homebrew — not present in node_modules/.bin)
npx oxlint <changed files> oxlint-exit=0
npx oxfmt --check <changed files> All matched files use the correct format.
pnpm run check:max-lines-ratchet max-lines ratchet OK — 7 grandfathered suppression(s), no new bypasses.
pnpm run check:reliability-gates Reliability gate manifest check passed for 118 gate(s).
git diff --check / git diff --cached --check both exit 0
git status clean, nothing untracked

The changed-code gate caught one real finding on the first pass of the follow-up commit —
typescript(restrict-template-expressions) on an array interpolated into an assertion message —
fixed with an explicit String(...) + .join(', '); the output above is the re-run.

The blocking subset, run end to end twice

Both runs: --project electron-headless --workers=1, all 10 specs. Run 1 built out/; run 2
used SKIP_BUILD=1 against that build.

Run Result
1 (with build) 1 failed / 23 passed (4.8m) — orchestration-idle-mail-delivery.spec.ts:356
2 (SKIP_BUILD=1) 1 failed / 23 passed (4.6m) — completed-worker-retirement-resume.spec.ts:39

Both failures are the same shared fixture predicate, not an orchestration assertion:

Error: Active terminal pane did not receive a PTY binding
expect(received).not.toBeNull()
Received: null
Call Log:
- Timeout 15000ms exceeded while waiting on the predicate

That is waitForActivePanePtyId in tests/e2e/helpers/terminal.ts:87, a 15s budget on the app's
first pane binding, used by 355 call sites across the suite. Follow-up isolation runs:

$ ... orchestration-idle-mail-delivery.spec.ts -g "unbound direct mail" --repeat-each=5
  5 passed (42.4s)      EXIT=0

$ ... completed-worker-retirement-resume.spec.ts --repeat-each=3
  4 passed, 1 failed (1.0m)   EXIT=1   (same PTY-binding predicate)

The run-1 failure was self-inflicted: pnpm test config/scripts (1547 tests) was running
concurrently. The run-2 and repeat failures were not — but this host was at load average 6.5–7.4
on 18 cores with 146 competing Electron/node processes from other agent worktrees, and 261% CPU
already consumed by other work. So: orchestration-idle-mail-delivery is 6/6 green here;
completed-worker-retirement-resume is 6/8 green here, failing only in the first-pane-binding
wait.

I did not quarantine either spec and did not widen the shared 15s budget. Quarantining a
spec that is green on CI would delete exactly the coverage this PR exists to add, and raising the
default in tests/e2e/helpers/terminal.ts touches 355 call sites whose behaviour I cannot measure
from this change (it would add 15s to every genuinely-failing test in the suite). The evidence
that matters for a gate that runs on ubuntu-latest is main's scheduled e2e: across the last four
runs (34380808516, 34284171625, 34255148958, 34165484966) the only orchestration/worker spec that
failed was orchestration-idle-mail-delivery.spec.ts, on the two runs before #19696 landed — a
real regression, not flake — and the latest run has zero orchestration failures.
completed-worker-retirement-resume.spec.ts has not failed on CI in that window. This is the top
open risk in the report; confirming it against a real CI runner is the user's call. If it does
flake on CI, the fix is at the fixture-budget layer, not here.

PR #19542 changed only orchestration source. `pr-e2e-source-routing.mjs` had no
route matching any of those paths, so the PR selected zero e2e specs, and `e2e`
is deliberately absent from `verify.needs` anyway. The spec that would have
caught the break -- "keeps unbound direct mail durable", in
orchestration-idle-mail-delivery.spec.ts since #12584 -- never ran, and
`orca orchestration send --to <handle>` between two plain terminals shipped
failing with "Run is required".

Route orchestration source at the 10 orchestration/worker specs, and give that
subset its own `orchestration_e2e` job that IS in `verify.needs`. The whole
suite stays advisory because it is red on main from unrelated specs; this
subset is green on main's scheduled runs, so blocking on it does not inherit
that redness.

The blocking signal is the selected orchestration spec list being non-empty,
not "orchestration source changed" the way hasSshSourceChange works: editing
one of those specs alone selects it with no source match, and keying the split
on source would drop it from the advisory lane while never adding it to the
blocking one. The advisory `e2e` job gets the selection minus this lane's, so
no PR pays for the same specs twice.

Naming the code_paths output `orchestration_e2e` rather than
`orchestration_e2e_should_run` is what lets verify's existing strict loop
enforce the job with no new mechanism -- it derives every SHOULD_RUN from
`code_paths.outputs.<job>`.
pr.yml now calls the reusable e2e.yml twice in one workflow run: the advisory
`e2e` job and the blocking `orchestration_e2e` job. Both start e2e.yml's
`build` job, and both would upload `e2e-build-out`. upload-artifact v4+ fails
outright when two jobs in one run upload the same name, so a PR touching
orchestration source AND any other routed source would kill whichever build
finished second -- taking the new required check red for a reason that has
nothing to do with the PR. `playwright-traces-changed` had the same collision
on failure in both lanes.

Add an optional `artifact_suffix` workflow_call input, default '', and append
it to every artifact name e2e.yml uploads or downloads -- not just the two that
can collide today, because a bare name left behind would fail only when a spec
fails in both lanes, hiding the signal exactly when it matters. The advisory
caller passes nothing; schedule and dispatch runs pass no inputs at all, so
both keep the names they have always used. `orchestration_e2e` passes
`-orchestration`.

release-e2e-dispatch-contract's "hands the built relay artifact to every E2E
run command" pinned the literal `e2e-build-out` on the upload and both
downloads. It now compares the downloads against the upload's own name, which
is what the test was really guarding: upload and download must agree. A mutant
that renames one download still fails it.

Verified: actionlint resolves the caller/callee input contract (a deliberately
typo'd input name is reported), and both new assertions were mutation-checked.
@coderabbitai

coderabbitai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

📝 Walkthrough

Walkthrough

The change adds orchestration-specific E2E source routing and separates orchestration specs from advisory specs. The PR workflow runs orchestration specs in a blocking orchestration_e2e job and includes that job in verify. The reusable E2E workflow accepts an optional artifact_suffix and applies it to build and trace artifacts. New tests validate routing, workflow wiring, artifact isolation, and release dispatch contracts.

Priority: ⬇️ Low

Severity of issue fixed: Low

Merge Risk: 🟡 Moderate · up to 0d5ab

Deletion-only or rename-away orchestration changes can bypass the intended blocking E2E coverage. This routing gap should be fixed before merge so affected pull requests cannot pass without running the required specifications.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides detailed context, motivation, implementation details, risks, and testing results. However, it does not follow the repository template and omits the required Linked Issue with … Add the required template sections and headings. Include a Linked Issue section with a valid Fixes # reference, state N/A with a reason under Visual Proof if no visual proof applies, complete or mark the AI Disclosure and Agent skill upstre…
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: adding a blocking orchestration E2E lane for orchestration-source pull requests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description provides detailed context, motivation, implementation details, risks, and testing results. However, it does not follow the repository template and omits the required Linked Issue with a Fixes reference, Visual Proof section with N/A if applicable, AI Disclosure, Review, Agent skill upstream boundary, Notes, and checklist confirmations.

Resolution

Add the required template sections and headings. Include a Linked Issue section with a valid Fixes # reference, state N/A with a reason under Visual Proof if no visual proof applies, complete or mark the AI Disclosure and Agent skill upstream boundary sections as applicable, add Review and Notes content, and complete the checklist items.

Full details: Docstring Coverage

Explanation

Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 7ccb56ea-75ab-43ec-a3c0-10c8c39adfcc

📥 Commits

Reviewing files that changed from the base of the PR and between aac38d6 and 0d5ab3f.

📒 Files selected for processing (6)
  • .github/workflows/e2e.yml
  • .github/workflows/pr.yml
  • config/scripts/pr-e2e-orchestration-routing.test.mjs
  • config/scripts/pr-e2e-source-routing.mjs
  • config/scripts/pr-workflow-parallelism.test.mjs
  • config/scripts/release-e2e-dispatch-contract.test.mjs

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.

Comment thread .github/workflows/pr.yml
@@ -82,8 +86,16 @@ jobs:
CHANGED="$(git diff --name-only --diff-filter=AMCR --merge-base "$BASE" "$HEAD")"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Include deleted orchestration source paths in routing.

Line 86 excludes D paths and keeps rename detection. A PR that only deletes, or renames away, a matched orchestration source file produces orchestration_e2e=false. The blocking job then skips, and verify accepts that skipped result.

Pass source-side deletions and renames to route matching. Keep deleted E2E spec paths out of the runnable spec list. Add a workflow-level regression case for a deletion-only orchestration change.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

This run reviewed the full six-file diff: the blocking orchestration e2e gate, the spec-route partition, the per-caller artifact namespace, and the contract tests that pin all three.

  • Blocking orchestration e2e job — a new orchestration_e2e reusable-workflow call in pr.yml, gated on orchestration source, wired into verify's strict check_job loop so it fails the required aggregate when any of the 10 specs fail.
  • Spec-route partition — pr-e2e-source-routing.mjs gains an orchestration.runtime-and-cli route plus selectOrchestrationPrE2eSpecs / selectAdvisoryPrE2eSpecs / hasOrchestrationE2eChange, making the advisory and blocking lanes an exact partition of the full selection so no spec runs twice.
  • Artifact namespace suffix — e2e.yml gains an optional artifact_suffix input applied to all nine upload/download steps, so two callers of the workflow in one run can't collide on e2e-build-out.
  • Contract tests — one new test file asserts the routing, partition, verify wiring, and artifact-namespace invariants; two existing tests are updated for the partition and suffix.

I verified the routing script end-to-end (message-insert.ts and a bare orchestration spec edit both gate true; an unrelated file gates false), confirmed the orchestration route regex covers all on-disk orchestration/worker product source, and ran the three changed test files (35 passed).

ℹ️ One deliberate central coverage gap

The gate fires only when ORCHESTRATION_PRODUCT_SOURCE matches a changed file, and src/main/runtime/orca-runtime.ts and src/shared/agents-orchestration-steps.ts are named, tested exclusions. orca-runtime.ts is the runtime's central entry point, so an orchestration regression that lands there (or in any file the regex misses) merges with zero gate coverage — the exact #19542 shape this PR exists to stop. The cost rationale (routing it runs the gate on most PRs) is sound, but the coverage boundary is now a review-checklist item, and worth an explicit note that "orchestration source" downstream of orca-runtime.ts is not guarded.

Technical details
# Orchestration route coverage boundary

## Affected sites
- config/scripts/pr-e2e-source-routing.mjs:17-18 — ORCHESTRATION_PRODUCT_SOURCE regex
- config/scripts/pr-e2e-orchestration-routing.test.mjs:160-167 — asserts orca-runtime.ts and agents-orchestration-steps.ts select nothing

## Required outcome
- Human sign-off that the orca-runtime.ts gap is acceptable, or a narrower authority for it.

## Suggested approach (optional)
- None required if the gap is accepted as-is.

ℹ️ Required gate carries first-run flake risk

The blocking lane serializes the 10 specs (--workers=1) on one ubuntu-latest runner, and your own local runs reproduced the shared waitForActivePanePtyId 15s first-pane-binding predicate (tests/e2e/helpers/terminal.ts:87) flaking under load. It is green on main's scheduled runs — the only red being the real #19542 regression — and declining to quarantine or widen the budget was the right call. But a required check has no continue-on-error, so if that predicate flakes on a busy CI runner, orchestration PRs block for a reason unrelated to their diff. The fix would live at the fixture-budget layer, not here; just confirming the reliability assumption is explicit before a gate lands on every orchestration PR.

Technical details
# Required-gate flake watch

## Affected sites
- .github/workflows/pr.yml:954-969 — orchestration_e2e required via verify.needs + strict check_job
- tests/e2e/helpers/terminal.ts:87 — waitForActivePanePtyId 15s budget, 355 call sites

## Required outcome
- Watch the first few orchestration-source PRs after merge; if waitForActivePanePtyId flakes on CI, raise the fixture budget there rather than quarantining specs or removing the gate.

## Open questions for the human (optional)
- Is a retry (e.g. a single rerun on flake) acceptable for a required gate, or is first-attempt determinism the bar?

Pullfrog  | Fix it ➔ | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

This branch has not been deployed

No deployments
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