Skip to content

🤖 fix: let built-in forked explore tasks run in parallel#3576

Merged
ethanndickson merged 1 commit into
mainfrom
parallel-tools-k5nv
Jun 22, 2026
Merged

🤖 fix: let built-in forked explore tasks run in parallel#3576
ethanndickson merged 1 commit into
mainfrom
parallel-tools-k5nv

Conversation

@ethanndickson

@ethanndickson ethanndickson commented Jun 16, 2026

Copy link
Copy Markdown
Member

Summary

Sub-agent exploration regained its parallelism: built-in task calls to the explore agent now run concurrently with each other again, while every mutating tool stays strictly serialized as before. The agent could emit several sibling tool calls intending parallel execution, but only the first actually ran — the rest serialized despite the provider advertising parallelToolCalls: true.

Background

PR #2906 (commit 386346261) wrapped every tool's execute() in a single shared per-stream AsyncMutex (withSequentialExecution). That made all sibling tool calls run one-at-a-time, which is the safe default for mutating tools (file edits, bash, config writes) but also defeated parallel sub-agent fan-out — the most visible casualty being the task tool spawning explore sub-agents.

A full revert was rejected because broad parallelism re-introduces real races that #2906 quietly fixed: shared-checkout task collisions, background-process ID collisions, and concurrent config read-modify-write. This change keeps all of those protections and only carves out the one case that is provably safe to overlap.

Implementation

The per-stream mutex is replaced with a fair reader-writer lock (SharedExecutionLock):

  • Writers (exclusive): every tool except the narrow exception below. Mutating tools keep their original one-at-a-time guarantee, and a writer never overlaps a reader.
  • Readers (shared): only built-in task calls that target agentId: "explore" and do not request isolation: "none". These overlap with each other but never with a writer.

The exception is gated on three independent conditions so it can't widen accidentally:

  1. The tool is the built-in task tool, identified by a non-forgeable Symbol marker (markBuiltInTaskTool / isBuiltInTaskTool) rather than by tool name. A user/MCP tool that happens to be named task does not qualify.
  2. The requested agent is explore (read-only by contract).
  3. The call does not use a shared workspace (isolation: "none"), so forked-checkout explore tasks can't race on a shared working tree.

The lock uses a turnstile pattern (turnstile + room-empty + reader-count mutexes) so writers can't be starved by a steady stream of readers and ordering stays fair. Abort handling reuses the existing acquireLockOrAbort path.

Risks

Scoped to tool-call scheduling within a single stream. The only behavioral change is that two-or-more concurrent built-in explore task calls may now overlap; all mutating tools retain identical serialized behavior. Because the exception excludes shared-checkout tasks and is keyed off a symbol (not a name), the shared-checkout and background-process-ID races that motivated #2906 remain closed.


Generated with mux • Model: anthropic:claude-opus-4-8 • Thinking: xhigh • Cost: $29.64

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79919ddffb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

Addressed in 5db9e90. The exemption is now per-call and runtime-aware instead of blanket.

A new pure helper taskCallSharesParentWorkspace(mode, isolation) decides, for each task call, whether it runs in the parent checkout (shared working tree) or forks into an isolated workspace:

  • local (or unknown runtime): forking is a no-op, so every task shares the parent checkout → serialized.
  • worktree/ssh: shares only when the model passes isolation: "none" → serialized; default/omitted/"fork" forks → exempt.
  • docker/devcontainer: always forks → exempt.

withSequentialExecution now acquires the lock for a task call only when taskCallSharesParentWorkspace is true; all other tools remain fully serialized. The runtime mode is threaded from the AIService send path into the stream-request builder and is undefined-safe (treated as shared → serialize) so any caller that doesn't supply it stays conservative.

Behavioral tests cover the matrix: worktree default/fork task calls overlap; worktree isolation:"none", local, and undefined-runtime task calls serialize; non-task tools always serialize.

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Please take another look. The blanket task exemption is now per-call and runtime-aware (only provably-forked task calls skip the serialization mutex; shared-checkout task calls and all other tools stay serialized).

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Pushed a formatting-only fix (Prettier) on top of the runtime-aware change. No behavioral difference.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c4ade72cc8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

Addressed in 1505b69. You're right that a forked task still touches the parent checkout during create() (agent frontmatter + git branch --show-current in WorktreeManager.forkWorkspace), so it must not overlap a mutating sibling.

Replaced the blunt per-stream mutex with a per-stream read/write lock (AsyncRwLock), modeling the actual shared resource — the parent checkout:

  • Writers (exclusive): all non-task tools, plus shared-checkout task calls (local runtime, or worktree/ssh isolation:"none").
  • Readers (shared): forked task calls (worktree/ssh default/fork, docker/devcontainer).

So within a stream: forked task ‖ forked task overlap (both readers), but forked task ‖ bash / file-write are mutually exclusive (read‖write), in either start order — no more concurrent access to the parent checkout. The classifier (needsSerializationtaskCallSharesParentWorkspace) is unchanged; it now just selects read vs write mode.

The RW lock is FIFO-fair (a queued writer blocks later readers from jumping ahead, so writers can't starve). Tests cover reader overlap, both-direction read/write exclusion, writer serialization, queued-writer fairness, and double-dispose safety, plus the task/bash interleaving matrix in withSequentialExecution.test.ts.

One intentional conservatism (documented inline): a foreground forked task holds the read lock across its whole execute chain incl. waitForAgentReport, so it blocks later writers for its duration — same scope as the original mutex, strictly better for task‖task. Upgrade path is to narrow the lock to create()'s checkout-read window if it ever matters.

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Replaced the per-stream mutex with a read/write lock so forked task calls overlap each other (readers) but stay mutually exclusive with mutating tools (writers). Please take another look.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1505b695aa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts Outdated
@ethanndickson ethanndickson changed the title 🤖 fix: exempt task from stream tool mutex 🤖 fix: restore parallel sibling tool execution (revert #2906) Jun 17, 2026
@ethanndickson

Copy link
Copy Markdown
Member Author

Re: Codex P2 on withSequentialExecution.ts (thread PRRT_kwDOPxxmWM6KF5Iu, "Do not exempt arbitrary tools named task") — this is now moot. Rather than special-casing the task tool name (or any per-call/runtime-aware lock), this PR reverts #2906 entirely: withSequentialExecution.ts is deleted and StreamManager passes the tool map straight through. There is no longer any name-based check or stream-level lock that an MCP/extra tool named task could exploit. Resolving the thread.

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c44e031bf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/streamManager.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the create-on-missing race (P2) in 546db28: file_edit_insert now runs its existence-check + create branch under the per-file lock (withFileEditLock) instead of writing outside it, with a regression test that fails when the lock is removed. Also updated the PR body to cover both the revert and this fix.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 546db280a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/streamManager.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the mux_config_write read-modify-write race (P2) in a5f6c39: the read → applyMutations → write cycle now runs under a per-config-document lock (withConfigDocumentLock), mirroring the file_edit fix, with a regression test that fails when the lock is removed. PR body updated to cover all three changes.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5f6c39811

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/streamManager.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the background process-ID allocation race (P2) in 591c134: generateUniqueProcessId now reserves the chosen ID synchronously (scanning a reservedIds set in addition to the registered map) so concurrent spawns can't collide across the spawn/migration awaits, with the reservation released on registration/failure. Keeps spawns parallel — no global mutex. PR body updated to cover all four changes.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 591c134400

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/mux_config_write.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the cross-layer config race (P2) in edd89a3: config.json/providers.jsonc writes now serialize on a single per-file lock (withConfigFileLock, keyed by absolute path) shared by both Config.editConfig (replacing the instance-scoped editConfigQueue) and the config tool's withConfigDocumentLock. So a mux_config_write can no longer interleave with Config.editConfig on the same file. Existing editConfig serialization tests still pass; new test fails if the two layers use separate locks. PR body updated.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edd89a3aa4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/utils/concurrency/configFileLocks.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the providers/secrets locking P2: ProviderService providers.jsonc mutations and Config.updateGlobalSecrets/updateProjectSecrets now run their read-modify-write under the shared withConfigFileLock, with regression tests and a documented one-directional lock-ordering invariant.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 61ed07a05e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/providerService.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the routePriority TOCTOU (P2) in 037f3ae: syncGatewayLifecycle now performs the routePriority read + insert/remove merge inside editConfig's locked callback (based on the locked config), so a concurrent mux_config_write(config) / routing edit can no longer be clobbered by a nextPriority computed from a stale snapshot. A cheap outer snapshot is kept only as a fast-path to skip the redundant write/notification in the steady state. Added a deterministic regression test that injects a concurrent edit in the exact TOCTOU window and asserts both routes survive.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

Reviewed commit: 037f3ae320

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 38dd835e94

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Pushed a comment-only follow-up (01772fe) documenting the maintainer decision behind keying the parallel reader exception on the explore agent id. No behavioral change since the last review request.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01772febe4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

The remaining P2 (local-runtime explore tasks sharing the checkout) is an intentional maintainer decision: explore is read-only by prompt contract, and parallel explore tasks sharing a checkout — including best-effort concurrent bash writes — is explicitly accepted, not a race we guard against. Reader parallelism is gated on the explore agent id; all mutating tools and non-explore forked tasks still take the exclusive write lock. Documented in code (dce6e4f) and resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dce6e4fbad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Addressed the P2 about hook-wrapped task tools: parent-side task hooks now keep the task tool on the exclusive write lock (the parallel-reader marker is stripped when a hook is configured), with integration coverage. The shared-checkout explore-agent overlap remains intentional per maintainer decision. Resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e02165f40

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/task.ts
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Fixed the marker-configurability bug (372487e): the built-in task marker is now defined configurable/writable so unmarkBuiltInTaskTool reliably strips it on hook-wrapped clones, with a direct regression test that fails under the old configurable: false definition. Resolved.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 372487ec24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 372487ec24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts Outdated
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Fixed the agent-id normalization gap (ec9ed56): getRequestedAgentId now trims and lowercases before comparing to "explore", mirroring the task schema, so valid non-canonical explore ids share the reader lock. Test added. Resolved.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: ec9ed563b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: ec9ed563b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Rebased onto latest origin/main (resolved a one-line import conflict in tools.test.ts) and force-pushed. No logic changes from the previously approved revision; the rebase only re-applied the 7 commits on top of main. Local validation green: typecheck, lint, and the focused tests for withSequentialExecution, task, cacheStrategy, and tools.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 95d09a68fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

This push slims the PR to the two load-bearing production files (withSequentialExecution.ts + task.ts). Two fixes from earlier review rounds were intentionally dropped — flagging proactively so the re-review has context.

re: "Preserve the task marker when cache control recreates tools" (P3, previously fixed in cacheStrategy.ts)

Dropped, because the path is unreachable. applyCacheControlToTools only recreates the last function tool, but the built-in task tool is never last: in getToolsForModel it is the first runtime tool (task: wrap(createTaskTool(config))), followed by task_await, bash, web_fetch, the non-runtime tools, desktop tools, and any MCP tools. Cache-control recreation therefore never touches task and never drops the symbol marker in any real configuration, so the marker-copy was dead code. If task ever became orderable to the tail of the tool list this would resurface, but that is not currently reachable.

re: "Keep task hooks serialized for explore fan-out" (P2, previously fixed by stripping the marker in tools.ts)

Dropped, because that logic was itself the regression it was meant to prevent. It gated on "the project has any task hook configured" rather than "the hook actually affects task", so a no-op .mux/tool_post formatter — which this repo itself ships, acting only on file_edit_* — stripped the marker and forced every explore task onto the exclusive write lock, serializing the entire feature in the common case. Running explore hook scripts concurrently is the same accepted best-effort tradeoff as concurrent explore bash/exec: the explore agent is read-only by prompt contract, not by tool removal. This is documented in the MAINTAINER DECISION comment in withSequentialExecution.ts.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0d8bceb7c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/withSequentialExecution.ts
Replace the per-stream AsyncMutex in withSequentialExecution with a fair
reader-writer lock (SharedExecutionLock). Built-in `task` calls targeting the
`explore` agent (without `isolation: "none"`) share the read side and overlap
with each other; every other tool keeps the exclusive write lock and stays
serialized. The built-in task tool is identified by a non-forgeable Symbol
marker set in createTaskTool.

Preserve that Symbol marker through Anthropic cache-control recreation
(applyCacheControlToTools), which rebuilds the last function tool via
createTool() and would otherwise drop the marker — silently serializing
explore fan-out whenever tool-policy filtering leaves `task` as the last tool.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

re: "Preserve the task marker after Anthropic cache wrapping" (P3)

Fixed in 2d45a77. You were correct that tool-policy filtering can leave task as the last function tool, making the cache-control recreation path reachable. applyCacheControlToTools now copies all own-symbol descriptors from the original tool onto the recreated tool, so the built-in task marker survives and explore fan-out stays parallel. Behavioral test added in cacheStrategy.test.ts.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 2d45a776ee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson ethanndickson added this pull request to the merge queue Jun 22, 2026
Merged via the queue into main with commit 9dcfc83 Jun 22, 2026
38 of 42 checks passed
@ethanndickson ethanndickson deleted the parallel-tools-k5nv branch June 22, 2026 06:48
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