Skip to content

Fix backport AI permission, surface infra failures, and allow manual dispatch#1943

Merged
TooTallNate merged 3 commits intomainfrom
fix-backport-ai-permission-and-infra-failure
May 5, 2026
Merged

Fix backport AI permission, surface infra failures, and allow manual dispatch#1943
TooTallNate merged 3 commits intomainfrom
fix-backport-ai-permission-and-infra-failure

Conversation

@TooTallNate
Copy link
Copy Markdown
Member

@TooTallNate TooTallNate commented May 5, 2026

Summary

Four related improvements to the backport workflow, triggered by the failed run on #1935 (run 25397238001) that ended green despite the conflict-resolution AI step actually failing:

1. Fix OPENCODE_PERMISSION for external_directory

Switch from the bare-string shortcut '"allow"' to the explicit object form '{"*":"allow","external_directory":"allow"}'. The shortcut was observed not to override external_directory (which defaults to "ask" and auto-rejects in non-interactive opencode run), causing:

! permission requested: external_directory (/tmp/*); auto-rejecting
✗ read failed
Error: The user rejected permission to use this specific tool call.

…when the conflict-resolution AI tried to read a scratch file it had just created under /tmp/. The conflict-resolution prompt + scratch files are also moved into the workspace (.backport-conflict-prompt.txt etc.) so opencode never needs external_directory access at all — same pattern the decision step already uses.

2. Fail loud on conflict-resolution infra failures

Previously the Resolve conflicts with opencode step had continue-on-error: true, so an opencode infra failure (auth error, rejected tool call, crash) would silently mark the step as success, leave resolved unset, and the workflow would post a misleading "AI couldn't resolve conflicts" comment on the source PR — making it look like a legitimate "needs human resolution" outcome.

Now the step distinguishes three cases via an AI-written outcome file (.backport-conflict-outcome.json):

Outcome Action
{"status":"resolved"} Cherry-pick continues; backport PR is opened.
{"status":"unresolved","reason":"..."} resolved=false is set; the conflict-failure comment is posted on the source PR (the legitimate "needs human help" path).
Missing / malformed / unknown Treated as infra failure. Step exits non-zero (no continue-on-error), workflow fails red, and the misleading "couldn't resolve" comment is suppressed (Comment on conflict failure is now gated on resolved == 'false' instead of != 'true').

The decision step's existing fail-loud behavior already handled this for the AI-decision path; this brings the conflict-resolution step in line.

3. Hoist AI_MODEL to a single env var

Added a top-level env: { AI_MODEL: ... } so the model is specified in exactly one place. Both opencode run invocations now use --model "vercel/${AI_MODEL}" (the vercel/ provider prefix stays at the use site). The PR body's conflict-resolution attribution also interpolates ${AI_MODEL} (e.g. "opencode with anthropic/claude-opus-4.7") instead of hardcoding "Claude Opus", so the text stays accurate if we change models later.

4. Allow manual workflow_dispatch with ref + model inputs

Added a workflow_dispatch trigger with two optional inputs:

  • ref — commit SHA on main to back-port (defaults to main HEAD; resolved via gh api repos/.../commits/<ref>)
  • model — overrides the AI model for that one run (e.g. quick A/B against a different model)

The top-level AI_MODEL is now ${{ inputs.model || 'anthropic/claude-opus-4.7' }}, keeping a single source of truth. Manual dispatch (like the backport-stable label) always forces a backport regardless of any AI verdict — operator intent is explicit by virtue of triggering the workflow. The PR body shows "Triggered manually via workflow_dispatch." in that case.

AGENTS.md is updated to document the new manual-dispatch trigger and its inputs.

…loud on AI infra errors

Three related fixes triggered by the failed run on #1935:

1. Hoist the AI model name to a top-level `AI_MODEL` env var
   (`anthropic/claude-opus-4.7`); both `opencode run` invocations
   now interpolate `vercel/${AI_MODEL}` so the model is specified in
   exactly one place.

2. Switch `OPENCODE_PERMISSION` from the bare-string shortcut
   `"allow"` to the explicit object form
   `{"*":"allow","external_directory":"allow"}`. The shortcut
   was observed not to override `external_directory` (which defaults to
   "ask" and auto-rejects in non-interactive `opencode run`),
   causing the conflict-resolution AI to fail when reading scratch files
   it created under `/tmp/`.

3. The `Resolve conflicts with opencode` step no longer uses
   `continue-on-error`, and now distinguishes two outcomes via an AI-
   written outcome file (`.backport-conflict-outcome.json`):

   - `{"status":"resolved"}` — the legitimate clean path; cherry-pick
     continues and the backport PR is opened.
   - `{"status":"unresolved", ...}` — the legitimate "AI couldn't
     do it, hand off to a human" path; `resolved=false` is set and the
     conflict-failure comment is posted on the source PR.
   - Anything else (missing file, malformed JSON, unknown status) is
     treated as an opencode/AI Gateway infra failure: the step exits
     non-zero, the workflow fails red, and the misleading
     "couldn't resolve" comment is suppressed.

   The prompt + scratch files are also moved into the workspace so
   opencode never needs `external_directory` access anyway.
Copilot AI review requested due to automatic review settings May 5, 2026 19:45
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 5, 2026

⚠️ No Changeset found

Latest commit: e50bccc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment May 5, 2026 8:54pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment May 5, 2026 8:54pm
example-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-astro-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-express-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-fastify-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-hono-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-nitro-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-nuxt-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-sveltekit-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-tanstack-start-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workbench-vite-workflow Ready Ready Preview, Comment May 5, 2026 8:54pm
workflow-docs Ready Ready Preview, Comment, Open in v0 May 5, 2026 8:54pm
workflow-swc-playground Ready Ready Preview, Comment May 5, 2026 8:54pm
workflow-tarballs Ready Ready Preview, Comment May 5, 2026 8:54pm
workflow-web Ready Ready Preview, Comment May 5, 2026 8:54pm

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.034s (-21.8% 🟢) 1.006s (~) 0.972s 10 1.00x
💻 Local Express 0.036s (-19.4% 🟢) 1.009s (~) 0.974s 10 1.06x
🐘 Postgres Nitro 0.103s (+8.7% 🔺) 1.046s (~) 0.942s 10 3.07x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 0.267s (-34.8% 🟢) 2.409s (-4.0%) 2.142s 10 1.00x
▲ Vercel Next.js (Turbopack) 0.775s (+208.2% 🔺) 2.493s (+6.9% 🔺) 1.718s 10 2.90x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.069s (-5.5% 🟢) 2.006s (~) 0.936s 10 1.00x
💻 Local Express 1.075s (-4.4%) 2.006s (~) 0.931s 10 1.01x
🐘 Postgres Nitro 1.212s (+6.3% 🔺) 2.054s (+2.2%) 0.842s 10 1.13x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.566s (-59.8% 🟢) 3.581s (-39.4% 🟢) 2.015s 10 1.00x
▲ Vercel Next.js (Turbopack) 2.649s (+30.2% 🔺) 4.075s (+6.4% 🔺) 1.426s 10 1.69x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 10.417s (-4.8%) 11.023s (~) 0.605s 3 1.00x
💻 Local Express 10.434s (-4.5%) 11.022s (~) 0.589s 3 1.00x
🐘 Postgres Nitro 11.211s (+3.1%) 11.687s (+6.0% 🔺) 0.476s 3 1.08x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 13.329s (-43.8% 🟢) 15.439s (-38.5% 🟢) 2.111s 2 1.00x
▲ Vercel Next.js (Turbopack) 15.963s (-7.8% 🟢) 16.828s (-13.3% 🟢) 0.865s 2 1.20x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 13.441s (-10.8% 🟢) 14.027s (-12.5% 🟢) 0.586s 5 1.00x
💻 Local Express 13.521s (-9.7% 🟢) 14.029s (-6.7% 🟢) 0.507s 5 1.01x
🐘 Postgres Nitro 15.400s (+5.5% 🔺) 16.307s (+8.5% 🔺) 0.907s 4 1.15x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 23.827s (-63.0% 🟢) 25.952s (-61.0% 🟢) 2.125s 3 1.00x
▲ Vercel Next.js (Turbopack) 26.067s (-50.4% 🟢) 27.554s (-49.5% 🟢) 1.487s 3 1.09x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 11.927s (-28.9% 🟢) 12.398s (-27.2% 🟢) 0.472s 8 1.00x
💻 Local Express 12.030s (-27.5% 🟢) 12.523s (-26.5% 🟢) 0.494s 8 1.01x
🐘 Postgres Nitro 15.217s (+8.9% 🔺) 15.700s (+9.7% 🔺) 0.483s 6 1.28x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 33.097s (-92.2% 🟢) 35.378s (-91.7% 🟢) 2.281s 3 1.00x
▲ Vercel Next.js (Turbopack) 36.152s (-90.8% 🟢) 38.033s (-90.4% 🟢) 1.882s 3 1.09x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.176s (-27.9% 🟢) 2.006s (-3.3%) 0.830s 15 1.00x
💻 Local Express 1.189s (-20.1% 🟢) 2.007s (~) 0.818s 15 1.01x
🐘 Postgres Nitro 1.556s (+22.1% 🔺) 2.072s (+3.1%) 0.517s 15 1.32x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.770s (-1.7%) 4.334s (~) 1.563s 7 1.00x
▲ Vercel Next.js (Turbopack) 4.580s (+34.8% 🔺) 6.330s (+28.3% 🔺) 1.750s 6 1.65x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.564s (-33.5% 🟢) 2.239s (-25.6% 🟢) 0.675s 14 1.00x
💻 Local Nitro 1.693s (-46.1% 🟢) 2.005s (-48.4% 🟢) 0.312s 15 1.08x
💻 Local Express 1.842s (-37.6% 🟢) 2.074s (-40.0% 🟢) 0.232s 15 1.18x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.981s (-1.7%) 5.613s (-5.2% 🟢) 1.631s 6 1.00x
▲ Vercel Next.js (Turbopack) 5.491s (-22.7% 🟢) 7.006s (-21.3% 🟢) 1.515s 5 1.38x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.059s (-40.8% 🟢) 2.933s (-26.8% 🟢) 0.873s 11 1.00x
💻 Local Nitro 4.515s (-45.9% 🟢) 5.011s (-44.5% 🟢) 0.496s 7 2.19x
💻 Local Express 5.505s (-34.0% 🟢) 6.014s (-33.4% 🟢) 0.508s 6 2.67x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 6.272s (+77.9% 🔺) 8.479s (+53.2% 🔺) 2.207s 4 1.00x
▲ Vercel Next.js (Turbopack) 6.682s (-25.1% 🟢) 8.160s (-25.6% 🟢) 1.478s 4 1.07x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.465s (-22.6% 🟢) 2.006s (-15.1% 🟢) 0.541s 15 1.00x
🐘 Postgres Nitro 1.582s (+25.9% 🔺) 2.170s (+8.1% 🔺) 0.587s 14 1.08x
💻 Local Nitro 1.769s (-5.2% 🟢) 2.391s (+2.2%) 0.622s 13 1.21x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.539s (+3.3%) 4.292s (+2.9%) 1.752s 8 1.00x
▲ Vercel Next.js (Turbopack) 4.649s (+58.6% 🔺) 6.215s (+33.9% 🔺) 1.566s 6 1.83x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.810s (-22.6% 🟢) 2.506s (-16.8% 🟢) 0.696s 12 1.00x
💻 Local Nitro 1.972s (-35.7% 🟢) 2.392s (-38.4% 🟢) 0.420s 13 1.09x
💻 Local Express 2.139s (-31.7% 🟢) 2.509s (-33.3% 🟢) 0.371s 12 1.18x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.713s (+14.8% 🔺) 5.522s (+8.8% 🔺) 1.808s 6 1.00x
▲ Vercel Next.js (Turbopack) 5.111s (+62.6% 🔺) 6.902s (+52.6% 🔺) 1.791s 5 1.38x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.140s (-38.5% 🟢) 3.057s (-23.7% 🟢) 0.917s 11 1.00x
💻 Local Nitro 5.144s (-43.7% 🟢) 5.683s (-43.3% 🟢) 0.539s 6 2.40x
💻 Local Express 6.329s (-28.1% 🟢) 6.815s (-26.5% 🟢) 0.485s 5 2.96x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.876s (-4.3%) 6.559s (-3.8%) 1.683s 5 1.00x
▲ Vercel Next.js (Turbopack) 6.296s (-6.8% 🟢) 7.961s (-6.8% 🟢) 1.665s 4 1.29x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.469s (-52.2% 🟢) 1.004s (-8.2% 🟢) 0.535s 60 1.00x
💻 Local Express 0.498s (-49.4% 🟢) 1.005s (-6.6% 🟢) 0.507s 60 1.06x
🐘 Postgres Nitro 0.801s (-2.4%) 1.238s (+23.0% 🔺) 0.437s 49 1.71x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.619s (-74.5% 🟢) 7.541s (-68.6% 🟢) 1.922s 9 1.00x
▲ Vercel Next.js (Turbopack) 7.365s (-49.2% 🟢) 8.740s (-45.7% 🟢) 1.375s 7 1.31x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.201s (-60.4% 🟢) 2.005s (-46.6% 🟢) 0.805s 45 1.00x
💻 Local Express 1.267s (-58.0% 🟢) 2.006s (-44.0% 🟢) 0.740s 45 1.06x
🐘 Postgres Nitro 2.745s (+42.4% 🔺) 3.213s (+53.0% 🔺) 0.469s 29 2.29x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 13.452s (-65.9% 🟢) 15.949s (-61.4% 🟢) 2.497s 6 1.00x
▲ Vercel Next.js (Turbopack) 15.424s (-69.0% 🟢) 16.803s (-67.5% 🟢) 1.380s 6 1.15x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 2.716s (-70.8% 🟢) 3.007s (-70.0% 🟢) 0.292s 40 1.00x
💻 Local Express 2.818s (-69.4% 🟢) 3.110s (-69.0% 🟢) 0.292s 39 1.04x
🐘 Postgres Nitro 4.739s (+15.5% 🔺) 5.311s (+15.3% 🔺) 0.571s 23 1.75x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 42.524s (-56.1% 🟢) 45.447s (-53.8% 🟢) 2.922s 3 1.00x
▲ Vercel Next.js (Turbopack) 48.635s (-54.6% 🟢) 50.571s (-53.6% 🟢) 1.936s 3 1.14x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.341s (+20.5% 🔺) 1.046s (+3.8%) 0.705s 58 1.00x
💻 Local Nitro 0.463s (-23.4% 🟢) 1.004s (-1.7%) 0.541s 60 1.36x
💻 Local Express 0.537s (-4.3%) 1.022s (+1.7%) 0.485s 59 1.57x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.436s (+46.6% 🔺) 4.330s (+29.2% 🔺) 1.894s 15 1.00x
▲ Vercel Next.js (Turbopack) 156.932s (+7659.3% 🔺) 159.964s (+4116.8% 🔺) 3.032s 2 64.43x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 0.732s (+47.5% 🔺) 1.245s (+23.7% 🔺) 0.513s 73 1.00x
💻 Local Nitro 2.230s (-12.1% 🟢) 2.912s (-3.2%) 0.682s 31 3.05x
💻 Local Express 2.432s (-3.2%) 3.043s (+1.1%) 0.611s 30 3.32x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 7.696s (+138.6% 🔺) 9.777s (+102.8% 🔺) 2.081s 10 1.00x
▲ Vercel Next.js (Turbopack) 108.907s (+2980.5% 🔺) 110.455s (+2027.0% 🔺) 1.549s 3 14.15x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 1.675s (+111.9% 🔺) 2.230s (+121.4% 🔺) 0.556s 54 1.00x
💻 Local Nitro 10.132s (-9.5% 🟢) 10.529s (-9.7% 🟢) 0.397s 12 6.05x
💻 Local Express 11.096s (-0.8%) 11.578s (-3.0%) 0.482s 11 6.63x
🐘 Postgres Express ⚠️ missing - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - -

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 20.552s (+99.0% 🔺) 22.070s (+79.6% 🔺) 1.518s 6 1.00x
▲ Vercel Nitro 98.228s (+1171.9% 🔺) 100.445s (+968.5% 🔺) 2.217s 4 4.78x
▲ Vercel Express ⚠️ missing - - - -

🔍 Observability: Next.js (Turbopack) | Nitro

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.135s (+431.1% 🔺) 2.005s (+99.6% 🔺) 0.010s (-17.6% 🟢) 2.018s (+98.0% 🔺) 0.883s 10 1.00x
💻 Local Express 1.142s (+473.5% 🔺) 2.005s (+99.6% 🔺) 0.012s (+2.5%) 2.020s (+98.4% 🔺) 0.878s 10 1.01x
🐘 Postgres Nitro 1.486s (+624.6% 🔺) 1.993s (+99.3% 🔺) 0.292s (+19366.7% 🔺) 2.335s (+130.9% 🔺) 0.849s 10 1.31x
🐘 Postgres Express ⚠️ missing - - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.336s (-39.1% 🟢) 3.642s (-31.0% 🟢) 1.927s (+159.6% 🔺) 6.031s (-7.0% 🟢) 3.695s 10 1.00x
▲ Vercel Next.js (Turbopack) 5.028s (-26.6% 🟢) 4.738s (-45.2% 🟢) 1.447s (+129.1% 🔺) 7.994s (-18.3% 🟢) 2.966s 10 2.15x
▲ Vercel Express ⚠️ missing - - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 1.581s (+108.9% 🔺) 2.011s (+95.5% 🔺) 0.011s (+17.9% 🔺) 2.024s (+94.7% 🔺) 0.443s 30 1.00x
💻 Local Nitro 1.718s (+104.8% 🔺) 2.011s (+98.7% 🔺) 0.010s (+5.2% 🔺) 2.202s (+97.3% 🔺) 0.484s 28 1.09x
🐘 Postgres Nitro 3.326s (+432.9% 🔺) 3.750s (+272.5% 🔺) 0.017s (+321.6% 🔺) 3.855s (+277.1% 🔺) 0.530s 16 2.10x
🐘 Postgres Express ⚠️ missing - - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 5.971s (-79.7% 🟢) 7.648s (-75.2% 🟢) 0.380s (+239.3% 🔺) 8.645s (-72.8% 🟢) 2.674s 7 1.00x
▲ Vercel Next.js (Turbopack) 13.592s (-19.7% 🟢) 13.778s (-24.5% 🟢) 0.228s (+7.7% 🔺) 15.337s (-19.0% 🟢) 1.745s 4 2.28x
▲ Vercel Express ⚠️ missing - - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 1.390s (+13.7% 🔺) 2.015s (~) 0.000s (+100.0% 🔺) 2.017s (~) 0.627s 30 1.00x
💻 Local Express 1.437s (+17.3% 🔺) 2.015s (~) 0.000s (-40.0% 🟢) 2.017s (~) 0.580s 30 1.03x
🐘 Postgres Nitro 1.888s (+94.9% 🔺) 2.352s (+88.5% 🔺) 0.000s (-4.0%) 2.427s (+93.0% 🔺) 0.540s 25 1.36x
🐘 Postgres Express ⚠️ missing - - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.728s (+55.0% 🔺) 6.199s (+41.1% 🔺) 0.000s (+477.8% 🔺) 6.717s (+39.7% 🔺) 1.989s 9 1.00x
▲ Vercel Next.js (Turbopack) 6.025s (-40.8% 🟢) 6.449s (-44.0% 🟢) 0.001s (+Infinity% 🔺) 7.594s (-37.0% 🟢) 1.569s 9 1.27x
▲ Vercel Express ⚠️ missing - - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Express 3.245s (-6.4% 🟢) 3.844s (-4.7%) 0.001s (-37.5% 🟢) 3.846s (-4.7%) 0.601s 16 1.00x
💻 Local Nitro 3.262s (-3.7%) 3.966s (-1.6%) 0.002s (+310.2% 🔺) 3.972s (-1.6%) 0.710s 16 1.01x
🐘 Postgres Nitro 3.342s (+86.5% 🔺) 3.937s (+83.9% 🔺) 0.000s (+75.0% 🔺) 3.986s (+83.3% 🔺) 0.645s 16 1.03x
🐘 Postgres Express ⚠️ missing - - - - -
💻 Local Next.js (Turbopack) ⚠️ missing - - - - -
🐘 Postgres Next.js (Turbopack) ⚠️ missing - - - - -

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 6.606s (+61.4% 🔺) 8.059s (+50.0% 🔺) 0.000s (-100.0% 🟢) 8.527s (+47.2% 🔺) 1.921s 8 1.00x
▲ Vercel Next.js (Turbopack) 8.668s (+54.3% 🔺) 8.905s (+27.6% 🔺) 0.000s (+166.7% 🔺) 10.055s (+33.4% 🔺) 1.386s 6 1.31x
▲ Vercel Express ⚠️ missing - - - - -

🔍 Observability: Nitro | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Nitro 18/21
🐘 Postgres Nitro 21/21
▲ Vercel Nitro 20/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 💻 Local 21/21
Next.js (Turbopack) ▲ Vercel 21/21
Nitro 💻 Local 13/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: failure
  • Vercel: failure

Check the workflow run for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
❌ ▲ Vercel Production 1196 4 219 1419
✅ 💻 Local Development 1587 0 219 1806
✅ 📦 Local Production 1587 0 219 1806
✅ 🐘 Local Postgres 1587 0 219 1806
✅ 🪟 Windows 129 0 0 129
✅ 📋 Other 727 0 176 903
Total 6813 4 1052 7869

❌ Failed Tests

▲ Vercel Production (4 failed)

nextjs-turbopack (1 failed):

  • pages router sleepingWorkflow via pages router

nitro (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

sveltekit (2 failed):

  • webhookWorkflow | wrun_01KQWYNJB4WNPVM47PTET8P94T | 🔍 observability
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 103 0 26
✅ example 103 0 26
✅ express 103 0 26
✅ fastify 103 0 26
✅ hono 103 0 26
❌ nextjs-turbopack 126 1 2
✅ nextjs-webpack 127 0 2
❌ nitro 102 1 26
✅ nuxt 103 0 26
❌ sveltekit 120 2 7
✅ vite 103 0 26
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 104 0 25
✅ express-stable 104 0 25
✅ fastify-stable 104 0 25
✅ hono-stable 104 0 25
✅ nextjs-turbopack-canary 110 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 129 0 0
✅ nextjs-webpack-canary 110 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 129 0 0
✅ nitro-stable 104 0 25
✅ nuxt-stable 104 0 25
✅ sveltekit-stable 123 0 6
✅ vite-stable 104 0 25
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 104 0 25
✅ express-stable 104 0 25
✅ fastify-stable 104 0 25
✅ hono-stable 104 0 25
✅ nextjs-turbopack-canary 110 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 129 0 0
✅ nextjs-webpack-canary 110 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 129 0 0
✅ nitro-stable 104 0 25
✅ nuxt-stable 104 0 25
✅ sveltekit-stable 123 0 6
✅ vite-stable 104 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 104 0 25
✅ express-stable 104 0 25
✅ fastify-stable 104 0 25
✅ hono-stable 104 0 25
✅ nextjs-turbopack-canary 110 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 129 0 0
✅ nextjs-webpack-canary 110 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 129 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 129 0 0
✅ nitro-stable 104 0 25
✅ nuxt-stable 104 0 25
✅ sveltekit-stable 123 0 6
✅ vite-stable 104 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 129 0 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 104 0 25
✅ e2e-local-dev-tanstack-start- 104 0 25
✅ e2e-local-postgres-nest-stable 104 0 25
✅ e2e-local-postgres-tanstack-start- 104 0 25
✅ e2e-local-prod-nest-stable 104 0 25
✅ e2e-local-prod-tanstack-start- 104 0 25
✅ e2e-vercel-prod-tanstack-start 103 0 26

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: success
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the backport.yml GitHub Actions workflow so AI-driven decisioning and conflict resolution are more reliable and don’t silently succeed when the underlying opencode/AI infrastructure fails.

Changes:

  • Hoists the AI model into a single top-level AI_MODEL env var and uses it consistently across opencode run calls.
  • Fixes OPENCODE_PERMISSION to an explicit JSON object form to ensure external_directory is actually allowed in headless runs.
  • Removes continue-on-error from the conflict-resolution step and introduces an AI-written outcome file to distinguish “legitimate unresolved conflicts” from infra/tool failures (and gates the “manual resolution needed” comment accordingly).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/backport.yml Outdated
… PR body

Add a `workflow_dispatch` trigger to the backport workflow with two
optional inputs:

- `ref` — commit SHA on `main` to back-port (defaults to `main` HEAD)
- `model` — overrides the default AI model used by opencode for the
  decision and conflict-resolution steps (defaults to the workflow's
  hardcoded `AI_MODEL`)

The top-level `AI_MODEL` env var now uses
`${{ inputs.model || 'anthropic/claude-opus-4.7' }}` so manual runs
pick up the override without changing anything else.

Manual dispatch (like the `backport-stable` label) always forces a
backport regardless of any AI verdict — the operator's intent is
explicit by virtue of triggering the workflow. The PR body shows
"Triggered manually via `workflow_dispatch`." in that case.

The PR body's conflict-resolution attribution also now interpolates
`${AI_MODEL}` (e.g. "opencode with `anthropic/claude-opus-4.7`")
instead of hardcoding "Claude Opus" so the text stays accurate if the
default model is later changed.
The previous `Resolve conflicts with opencode` sanity check used
`git diff --diff-filter=U` to detect unresolved cherry-pick conflicts,
which only catches unmerged index entries. That misses the case where
the AI runs `git add` on a file that still has `<<<<<<<` /
`=======` / `>>>>>>>` markers in its content — git happily stages
the broken file as a normal modification.

Add a second check using `git diff --check --cached`, which emits
`leftover conflict marker` lines when any staged content still has
the standard markers. Grep specifically for that phrase so unrelated
whitespace warnings don't trip the check. Also update the inline
comment to accurately describe what each check covers (per Copilot's
review on #1943).
@TooTallNate TooTallNate merged commit 4c165b6 into main May 5, 2026
106 of 112 checks passed
@TooTallNate TooTallNate deleted the fix-backport-ai-permission-and-infra-failure branch May 5, 2026 20:55
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

No backport to stable for 4c165b6 (AI decision).

This commit only modifies the backport workflow itself (.github/workflows/backport.yml) and its documentation in AGENTS.md. The backport workflow runs against main and is release plumbing — it doesn't need to exist on stable.

To override, add the backport-stable label to this PR.

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.

3 participants