Skip to content

Harden assign_to_agent concurrency: isolate handler state and serialize MCP stdin dispatch - #52034

Open
pelikhan with Copilot wants to merge 14 commits into
mainfrom
copilot/concurrency-fix-assign-to-agent
Open

Harden assign_to_agent concurrency: isolate handler state and serialize MCP stdin dispatch#52034
pelikhan with Copilot wants to merge 14 commits into
mainfrom
copilot/concurrency-fix-assign-to-agent

Conversation

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

assign_to_agent relied on module-global mutable results and a check-then-await max gate, which allowed cross-invocation state bleed and a TOCTOU race under concurrent dispatch. In parallel, MCP stdio processing could interleave processReadBuffer executions when clients pipelined requests.

  • State isolation in assign_to_agent

    • Moved assignment result storage from module scope to per-main() closure state.
    • Bound summary/output accessors to the returned handler instance (getAssignToAgentAssigned, getAssignToAgentErrors, getAssignToAgentErrorCount, writeAssignToAgentSummary) so data is scoped to a single handler lifecycle.
  • TOCTOU fix for max enforcement

    • Made max gating atomic with early slot reservation (processedCount++ before any await).
    • Preserved defer behavior by releasing the reserved slot when an unresolved temporary ID causes deferral.
  • Serialized MCP stdio dispatch

    • Updated mcp_server_core.start() to chain processReadBuffer calls through a promise queue, preventing overlapping reads/dispatch from concurrent stdin data events.
  • Handler-manager integration update

    • safe_output_handler_manager now reads assign-to-agent outputs/summaries from the loaded handler instance instead of module-level exported state.
  • Regression coverage

    • Added tests for concurrent assign_to_agent invocation with max: 1.
    • Added tests proving independent main() handlers do not share results.
    • Added test verifying pipelined stdin chunks are processed without overlapping tool handler execution.
// before: check then await created a race window
if (processedCount >= maxCount) return skipped;
await sleep(10000);
processedCount++;

// after: reserve before await (atomic gate)
if (processedCount >= maxCount) return skipped;
processedCount++;
if (processedCount > 1) await sleep(10000);

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 19.7 AIC · ⌖ 5.12 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Run: https://github.com/github/gh-aw/actions/runs/31511130973> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.27 AIC · ⌖ 5.37 AIC · ⊞ 8.5K ·

Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 11.1 AIC · ⌖ 3.4 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Requested branch update from https://github.com/github/gh-aw/actions/runs/31535473039.> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.59 AIC · ⌖ 5.18 AIC · ⊞ 8.5K ·

Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 14.9 AIC · ⌖ 5.12 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Run report: https://github.com/github/gh-aw/actions/runs/31554759452> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 13.6 AIC · ⌖ 7.61 AIC · ⊞ 8.5K ·

Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.6 AIC · ⌖ 5.36 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.46 AIC · ⌖ 5.23 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 22 AIC · ⌖ 5.29 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Run context: https://github.com/github/gh-aw/actions/runs/31616336935> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 12.9 AIC · ⌖ 5.25 AIC · ⊞ 8.5K ·

Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.32 AIC · ⌖ 5.15 AIC · ⊞ 8.5K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 13.8 AIC · ⌖ 5.19 AIC · ⊞ 8.5K ·
Comment /souschef to run again



✨ PR Review Safe Output Test - Run 31732491833> [!WARNING]

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

💥 [THE END] — Illustrated by Smoke Claude · sonnet46 · 64.1 AIC · ⌖ 8.64 AIC · ⊞ 6.3K ·
Comment /smoke-claude to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 14.4 AIC · ⌖ 5.73 AIC · ⊞ 8.5K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix concurrency safety in assign_to_agent module Harden assign_to_agent concurrency: isolate handler state and serialize MCP stdin dispatch Aug 11, 2026
Copilot AI requested a review from pelikhan August 11, 2026 12:43
@pelikhan
pelikhan marked this pull request as ready for review August 11, 2026 13:01
Copilot AI balanced review requested due to automatic review settings August 11, 2026 13:01

Copilot AI 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.

Pull request overview

Hardens assign_to_agent and MCP stdio concurrency, addressing #51997.

Changes:

  • Isolates assignment results per handler instance.
  • Atomically reserves assignment slots and serializes MCP dispatch.
  • Adds concurrency and state-isolation regression tests.
Show a summary per file
File Description
actions/setup/js/assign_to_agent.cjs Isolates state and changes max enforcement.
actions/setup/js/assign_to_agent.test.cjs Adds concurrency and isolation tests.
actions/setup/js/mcp_server_core.cjs Queues stdin processing.
actions/setup/js/mcp_server_core.test.cjs Tests serialized dispatch.
actions/setup/js/safe_output_handler_manager.cjs Reads results from handler instances.

Review details

Tip

Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 5/5 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread actions/setup/js/assign_to_agent.cjs Outdated
allResults.push({ issue_number: message.issue_number || null, pull_number: message.pull_number || null, agent: agentNameForSkip, owner: null, repo: null, success: false, skipped: true });
return { success: false, skipped: true };
}
processedCount++;
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please refresh this branch, verify checks, and use the pr-finisher skill before handing back.

No failed checks were reported in the compact candidate set for this run.
Branch update was requested by sous-chef in run https://github.com/github/gh-aw/actions/runs/31497194249.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 19.7 AIC · ⌖ 5.12 AIC · ⊞ 8.5K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please refresh this branch, verify checks, and use the pr-finisher skill before handing back.

No failed checks were reported in the compact candidate set for this run....

Refreshed the branch with current main in 10d2cbc. Local formatting, lint, unit, full test, recompilation, and final PR validation passed; the cited Sous Chef run completed successfully.

Copilot AI requested a review from gh-aw-bot August 11, 2026 14:34
@pelikhan

Copy link
Copy Markdown
Collaborator

/matt

@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions github-actions 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.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — requesting changes on correctness of the deferral-rollback logic and test coverage gaps.

📋 Key Themes & Highlights

Key Issues

  • Deferral-rollback race (correctness): The processedCount-- on deferral creates a window where two concurrent deferred messages can both decrement back below the max gate and both complete on retry — violating max.
  • Test doesn't exercise the real race: The Promise.all concurrent test uses instant mocks, so the gate is already respected before any await; the pre-fix race is never actually reproduced.
  • Delay guard boundary test missing: The processedCount > 1 change to the delay guard lacks a dedicated test for the 1→2 transition.

Positive Highlights

  • ✅ Moving allResults to closure scope is a clean, correct fix for state isolation — no more module-level bleed between invocations.
  • ✅ Attaching accessors directly to the handler function is an elegant pattern that avoids threading an extra argument through call sites.
  • ✅ Promise-chaining for MCP stdio serialization is the right approach and the new test correctly verifies sequential dispatch.
  • ✅ Extraction of formatAssignedOutput, formatErrorsOutput, countHardFailures, and writeAssignSummary as pure functions improves testability.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 42.7 AIC · ⌖ 7.4 AIC · ⊞ 7.1K
Comment /matt to run again

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the open review feedback, refresh the branch if needed, and use the pr-finisher skill before handing back.

Open review threads (newest reviewer feedback first):

No failed checks were reported in the compact candidate set for this run.
Branch update was requested by sous-chef in run https://github.com/github/gh-aw/actions/runs/31511130973.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 8.27 AIC · ⌖ 5.37 AIC · ⊞ 8.5K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the open review feedback, refresh the branch if needed, and use the pr-finisher skill before handing back.

Open review threads (newest reviewer feedback first):...

Addressed the max-slot review feedback in 2b675e6: validation and deferral occur before reservation, and the delayed concurrent 1→2 boundary is regression-tested. The branch already includes current main; local validation and the pr-finisher checks passed.

@github-actions

Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot - AOAI (Entra) is now investigating this pull request. Sources say the story is developing...

@github-actions

Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot - AOAI (apikey) is now investigating this pull request. Sources say the story is developing...

@github-actions
github-actions Bot deployed to aoai-model August 13, 2026 18:48 Active
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Smoke OTEL completed successfully!

Generated by Smoke OTEL

@github-actions

Copy link
Copy Markdown
Contributor

Race conditions hide,
State locked, one slot reserved now,
Queue keeps calm in dark.

Inspired by this PR's fix for shared state races and serialized stdin dispatch in assign_to_agent.

Generated by 🌸 Smoke Copilot Auto for #52034 · auto · 9.69 AIC · ⌖ 7.31 AIC · ⊞ 5.9K ·
Add label smoke to run again

@github-actions

Copy link
Copy Markdown
Contributor

Caution

agentic threat detected
Threat detection flagged this output in warn mode. Manual review is REQUIRED before any follow-up automation.

Details

Potential security threats were detected in the agent output.

Review the workflow run logs for details.

Smoke test FAIL

  • PR fetch ✅
  • Web fetch ❌
  • File write ✅
  • Bash verify ✅
  • Build ❌

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • proxy.golang.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "proxy.golang.org"

See Network Configuration for more information.

🥧 Smoke Pi — Powered by Pi · gpt54 · 2.4 AIC · ⌖ 4.04 AIC · ⊞ 5.6K ·
Comment /smoke-pi to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke test summary: recent commits focus on security hardening, policy validation, and workflow robustness, with additional docs and lint-rule updates.
Overall status: PASS
Run URL: https://github.com/github/gh-aw/actions/runs/31732554364

Generated by ⚡ Smoke Copilot MAI · mai10 · 2.54 AIC · ⌖ 1.11 AIC · ⊞ 18.8K ·
Comment /smoke-copilot-mai to run again
Add label smoke to run again

@github-actions

Copy link
Copy Markdown
Contributor

Agent Container Tool Check

Tool Status Version
bash 5.2.21
sh available
git 2.54.0
jq 1.7
yq v4.53.3
curl 8.5.0
gh 2.96.0
node v24.18.0
python3 3.11.15
go 1.24.13
java 21.0.11 (Temurin)
dotnet 10.0.302

Result: 12/12 tools available ✅ — Overall status: PASS

🔧 Tool validation by Agent Container Smoke Test · auto · 18.3 AIC · ⌖ 2.64 AIC · ⊞ 8.3K ·
Comment /smoke-test-tools to run again

@github-actions
github-actions Bot deployed to aoai-model August 13, 2026 18:54 Active
@github-actions

Copy link
Copy Markdown
Contributor

Commit pushed: acf7c8a

Generated by Changeset Generator · gpt54 · 50.1 AIC · ⌖ 8.32 AIC · ⊞ 14.2K

@github-actions

Copy link
Copy Markdown
Contributor
Smoke Test Codex: FAIL

Merged PRs: #52540 Add regression tests preventing committed tool binaries; #52539 Fail closed on unrecognized autonomy/write-scope values when seeding compiled policy

  1. ❌ GitHub MCP 2. ✅ Serena 3. ✅ Playwright 4. ❌ Web Fetch
  2. ✅ File write 6. ✅ Bash readback 7. ✅ Build 8. ✅ Comment memory 9. ✅ Cache memory 10. ✅ Issue field
    Overall: FAIL

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • www.google.com
  • www.gstatic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "www.google.com"
    - "www.gstatic.com"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex · gpt54 · 56 AIC · ⊞ 11.9K ·
Comment /smoke-codex to run again

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

Mist drifts through build logs
Quiet symbols wake and align
Dawn commits no noise

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • www.google.com
  • www.gstatic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "www.google.com"
    - "www.gstatic.com"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex · gpt54 · 56 AIC · ⊞ 11.9K ·
Comment /smoke-codex to run again

@github-actions

Copy link
Copy Markdown
Contributor

💨 Smoke Test Run 31732491833

Core Tests #1–12: ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅

Test Status Notes
13 Update PR
14 Review Comments 2 comments added
15 Submit Review
16 Resolve Thread ⚠️ GraphQL access denied
17 Add Reviewer copilot added
18 Push Branch Allowed-files restriction
19 Close PR ⚠️ Skipped

Overall: PARTIAL

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

💥 [THE END] — Illustrated by Smoke Claude · sonnet46 · 64.1 AIC · ⌖ 8.64 AIC · ⊞ 6.3K ·
Comment /smoke-claude to run again

@github-actions github-actions 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.

💥 Automated smoke test review - all systems nominal! (Run 31732491833)

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

💥 [THE END] — Illustrated by Smoke Claude · sonnet46 · 64.1 AIC · ⌖ 8.64 AIC · ⊞ 6.3K
Comment /smoke-claude to run again

Comments that could not be inline-anchored

actions/setup/js/assign_to_agent.cjs:28

🔍 The token precedence logic here looks good — using a dedicated per-handler PAT before falling back to step-level token is a solid security pattern. Smoke test agent approves! (Run 31732491833)

actions/setup/js/mcp_server_core.cjs:9

✅ Logging at module load time is a great debugging aid. This helps trace initialization order in complex pipelines. Smoke test agent confirms! (Run 31732491833)

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test Copilot - PR Summary

PR: Harden assign_to_agent concurrency: isolate handler state and serialize MCP stdin dispatch

Results: 15✅ / 1❌ (test #3 Serena timeout)

Overall: FAIL

Author: app/copilot-swe-agent | Assignees: @pelikhan @Copilot

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • www.google.com
  • www.gstatic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "www.google.com"
    - "www.gstatic.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · auto · 46.6 AIC · ⌖ 2.41 AIC · ⊞ 8.5K ·
Comment /smoke-copilot to run again
Add label smoke to run again

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

Copilot runs test
Code flows through silent circuits
Green checks light the way

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • www.google.com
  • www.gstatic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "www.google.com"
    - "www.gstatic.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · auto · 46.6 AIC · ⌖ 2.41 AIC · ⊞ 8.5K ·
Comment /smoke-copilot to run again
Add label smoke to run again

@github-actions github-actions 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.

Smoke test review: build good. Me approve as comment only.

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • www.google.com
  • www.gstatic.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "www.google.com"
    - "www.gstatic.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · auto · 46.6 AIC · ⌖ 2.41 AIC · ⊞ 8.5K
Comment /smoke-copilot to run again
Add label smoke to run again

@github-actions

Copy link
Copy Markdown
Contributor

Smoke test 31732550397 results:
1,2: ✅ ✅
3,4: ❌ ❌
5,6: ✅ ✅
Tests 7–15: ❌
Overall: FAIL
cc @app/copilot-swe-agent @pelikhan @Copilot

📰 BREAKING: Report filed by Smoke Copilot - AOAI (apikey) · o40mini · 27 AIC · ⌖ 3.12 AIC · ⊞ 20.3K ·
Comment /smoke-copilot-aoai-apikey to run again
Add label smoke to run again

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Triage nudge from sous-chef. Please inspect the latest smoke failures, refresh the branch if needed, and run the pr-finisher skill before handing this PR back to maintainers.

Failed checks from the candidate set:

  • None listed in the compact candidate set, but recent smoke comments on the PR show failures. Please investigate the latest smoke runs linked on the thread.

Branch update was requested automatically for this run.
Run: https://github.com/github/gh-aw/actions/runs/31734986091

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 14.4 AIC · ⌖ 5.73 AIC · ⊞ 8.5K ·
Comment /souschef to run again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[concurrency] Concurrency safety: assign_to_agent module-level state + unserialized MCP stdio dispatch

4 participants