Fix Copilot CLI e2e Trust Dialog Detection

Claude Code·Opus 4.8[1m]·Soph·3mo ago·19hr 47min·2 Checkpoints·3 file changes·+88/-3·55.6K tokens

can you check the failures for copilot cli here: https://github.com/entireio/cli/actions/runs/27627165391/job/81691920738

3mo ago·1h 25m

All 42 Copilot failures share one root cause — it's not a CLI regression, it's an auth problem in CI.

What's failing

Every copilot-cli E2E test (42 of them) dies the same way before the agent does any work:

The Copilot CLI can't list models, so copilot -p ... exits 1, and the test harness reports the generic agent failed: exit status 1. The handful of tests that "passed" (·) are skips or tests that don't actually invoke Copilot; everything that runs the agent fails.

Root cause

The failing workflow (.github/workflows/e2e.yml:98 and :110) sets:

github.token is a GitHub App installation (server-to-server) token. Copilot CLI's model-listing endpoint now rejects S2S tokens — it requires a user token with Copilot access. The copilot-requests: write permission on the job (e2e.yml:52) isn't sufficient for that endpoint. This is an endpoint behavior, so it would have started failing for everyone at once regardless of code changes — consistent with all 42 failing identically.

Fix

Use a real Copilot-enabled user PAT instead of the workflow token. Notably, the isolated workflow already does this correctly:

  • e2e-isolated.yml:65,76COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} ✅ (user PAT secret)
  • e2e.yml:98,110 and e2e-checkpoints-v2.yml:151,156${{ github.token }} ❌ (S2S token)

So the change is to switch e2e.yml (and e2e-checkpoints-v2.yml) to secrets.COPILOT_GITHUB_TOKEN, matching e2e-isolated.yml. That assumes the COPILOT_GITHUB_TOKEN secret is still valid/non-expired — worth verifying, since a PAT expiry is the other thing that produces exactly this error.

Want me to make that workflow change?

can you look at the latest run, github fixed the token permissions (since this does work with the normal token)

3mo ago·14h 28m

Both failure causes are now confirmed. Here's the full picture.

The token fix worked ✅

Copilot tests now actually run (29–97s durations) instead of failing instantly at auth. Failures dropped from 42 → 6, and the remaining 6 are real test issues, not infra. They fall into two distinct buckets.

Bucket 1: 5 interactive tests — broken trust-dialog handshake (real bug, easy fix)

TestInteractiveMultiStep, TestInteractiveAttributionOnAgentCommit, TestInteractiveAttributionMultiCommitSameSession, TestInteractiveShadowBranchCleanedAfterAgentCommit, TestInteractiveContentOverlapRevertNewFile — all WaitFor("❯"): timed out.

Root cause is in e2e/agents/copilot-cli.go, the StartSession dialog-dismissal loop (around line 305):

Copilot's "Confirm folder trust" dialog renders its selected option as ❯ 1. Yes — the cursor is the same as the input prompt. The guard that's supposed to tell them apart checks for "Enter to select", but Copilot v1.0.63 now renders the footer lowercase as enter to select. I verified this in the captured panes:

  • enter to select (lowercase): 5 occurrences (one per interactive test)
  • Enter to select (capital E): 0 occurrences

So the guard never recognizes the dialog, sets foundPrompt = true, and breaks without sending Enter to dismiss it. The first real prompt then gets swallowed by the still-open trust dialog (the Enter from Send just selects "Yes"), the agent never does the work, and every subsequent WaitFor("❯") desyncs.

Fix: make the guard case-insensitive, or better, key off the dialog title which is more stable than the footer. E.g.:

Bucket 2: TestSubagentCommitFlow — shadow branch not cleaned (known Copilot limitation)

This one is headless -p mode (no trust dialog). The agent did create the file and the commit succeeded — it fails at line 45, WaitForNoShadowBranches. The git log confirms entire/79ed2c9-e3b0c4 survived.

This is the same background-subagent timing issue already documented in the skip at single_session_test.go:95: Copilot runs prompt-mode subagents in the background, so the foreground process returns and fires session-end hooks before the subagent's work settles, leaving the shadow branch uncleaned. That test was skipped for exactly this reason; TestSubagentCommitFlow hits the same Copilot behavior and probably warrants the same treatment (skip for copilot-cli) — unless we want to actually fix shadow-branch cleanup to be robust against late background commits.

Recommendation

Bucket 1 is a clean, high-confidence fix (5 of 6 failures, one-line guard change). Bucket 2 is a pre-existing Copilot quirk that's already acknowledged elsewhere in the suite.

Want me to apply the Bucket 1 fix to copilot-cli.go, and add the copilot skip for TestSubagentCommitFlow (or look into a real cleanup fix)?

ok, can you do 1 as a branch of main doing meaningful commits

3mo ago·2h 34m

Done. Branch soph/copilot-trust-dialog-handshake off main with two meaningful commits:

CommitWhat
2e2ff1303refactor — extract the inline prompt-vs-dialog check into a named isStartupDialog() helper (no behavior change)
0677238fcfix — make detection case-insensitive + title-based, widen the WaitFor regex, and add copilot_trust_test.go with the real v1.0.63 dialog capture as a regression fixture

What it fixes

Copilot v1.0.63 lowercased the trust-dialog footer (Enter to selectenter to select). StartSession's exact-case strings.Contains(content, "Enter to select") stopped matching, so the dismissal loop mistook the dialog's ❯ 1. Yes cursor for the interactive prompt, broke out without pressing Enter, and the still-open dialog swallowed the first prompt — timing out all 5 TestInteractive* copilot-cli tests.

The fix folds case and also keys off the dialog title (Confirm folder trust / Do you trust) so a future footer-wording change can't silently re-break it. I verified detection against the actual captured pane (lowercase footer + cursor), and confirmed the bare interactive prompt is not misclassified.

Verification done

  • go build -tags e2e ./e2e/...
  • go vet -tags e2e ./e2e/agents/
  • go test ./e2e/agents/ ✓ (new tests pass; package builds without the e2e tag, so they run under mise run test)
  • mise run lint → 0 issues ✓

Not included (deliberately)

  • Bucket 2 (TestSubagentCommitFlow shadow-branch cleanup) — that's the separate, pre-existing Copilot background-subagent quirk already acknowledged in the single_session_test.go:95 skip. Left untouched as you scoped this to "1".
  • I did not run real Copilot e2e (costs tokens + needs Copilot auth). The fix is verified by unit test against the captured failing pane; the real proof will be the next CI e2e run.

Want me to push the branch / open a PR, or also tackle Bucket 2?