diff --git a/src/hooks/atlas/tool-execute-before.ts b/src/hooks/atlas/tool-execute-before.ts
index f4e03ad65..d9ede7484 100644
--- a/src/hooks/atlas/tool-execute-before.ts
+++ b/src/hooks/atlas/tool-execute-before.ts
@@ -1,4 +1,5 @@
import { log } from "../../shared/logger"
+import { replaceToolArgs } from "../../shared/replace-tool-args"
import { SYSTEM_DIRECTIVE_PREFIX } from "../../shared/system-directive"
import { isCallerOrchestrator } from "../../shared/session-utils"
import type { PluginInput } from "@opencode-ai/plugin"
@@ -179,7 +180,7 @@ export function createToolExecuteBeforeHandler(input: {
const prompt = toolOutput.args.prompt as string | undefined
if (prompt && !prompt.includes(SYSTEM_DIRECTIVE_PREFIX)) {
- toolOutput.args.prompt = `${SINGLE_TASK_DIRECTIVE}\n` + prompt
+ replaceToolArgs(toolOutput, { prompt: `${SINGLE_TASK_DIRECTIVE}\n` + prompt })
log(`[${HOOK_NAME}] Injected single-task directive to task`, {
sessionID: toolInput.sessionID,
})
diff --git a/src/plugin/tool-execute-before.ts b/src/plugin/tool-execute-before.ts
index ce1129ccc..508f40dde 100644
--- a/src/plugin/tool-execute-before.ts
+++ b/src/plugin/tool-execute-before.ts
@@ -100,21 +100,20 @@ export function createToolExecuteBeforeHandler(args: {
}
if (input.tool === "task") {
- const argsObject = output.args
- const category = typeof argsObject.category === "string" ? argsObject.category : undefined
- const subagentType = typeof argsObject.subagent_type === "string" ? argsObject.subagent_type : undefined
- const taskId = typeof argsObject.task_id === "string" ? argsObject.task_id : undefined
+ const category = typeof output.args.category === "string" ? output.args.category : undefined
+ const subagentType = typeof output.args.subagent_type === "string" ? output.args.subagent_type : undefined
+ const taskId = typeof output.args.task_id === "string" ? output.args.task_id : undefined
if (category) {
- argsObject.subagent_type = "sisyphus-junior"
+ replaceToolArgs(output, { subagent_type: "sisyphus-junior" })
} else if (!subagentType && taskId) {
const resolvedAgent = await resolveSessionAgent(ctx.client, taskId)
- argsObject.subagent_type = resolvedAgent ?? "continue"
+ replaceToolArgs(output, { subagent_type: resolvedAgent ?? "continue" })
}
const normalizedSubagentType =
- typeof argsObject.subagent_type === "string" ? stripInvisibleAgentCharacters(argsObject.subagent_type) : undefined
- const prompt = typeof argsObject.prompt === "string" ? argsObject.prompt : ""
+ typeof output.args.subagent_type === "string" ? stripInvisibleAgentCharacters(output.args.subagent_type) : undefined
+ const prompt = typeof output.args.prompt === "string" ? output.args.prompt : ""
const loopState = typeof ctx.directory === "string" ? readState(ctx.directory) : null
const shouldInjectOracleVerification =
normalizedSubagentType === "oracle"
@@ -136,12 +135,14 @@ export function createToolExecuteBeforeHandler(args: {
verification_attempt_id: verificationAttemptId,
verification_session_id: undefined,
})
- argsObject.run_in_background = false
- argsObject.prompt = buildUltraworkOracleVerificationPrompt(
- prompt,
- loopState.prompt,
- verificationAttemptId,
- )
+ replaceToolArgs(output, {
+ run_in_background: false,
+ prompt: buildUltraworkOracleVerificationPrompt(
+ prompt,
+ loopState.prompt,
+ verificationAttemptId,
+ ),
+ })
}
}
diff --git a/src/shared/replace-tool-args.audit.test.ts b/src/shared/replace-tool-args.audit.test.ts
index 4c14faf34..1c85ee6d9 100644
--- a/src/shared/replace-tool-args.audit.test.ts
+++ b/src/shared/replace-tool-args.audit.test.ts
@@ -23,8 +23,10 @@ async function collectTsFiles(dir: string): Promise {
const HELPER_FILE = "shared/replace-tool-args.ts"
-const DIRECT_MUTATION_PATTERN = /output\.args\.\w+\s*=[^=]/g
-const OBJECT_ASSIGN_PATTERN = /Object\.assign\(\s*output\.args/g
+// Matches direct mutations like `output.args.foo =` or `toolOutput.args.foo =`
+// but excludes comparisons (===, !==, ==)
+const DIRECT_MUTATION_PATTERN = /\w*[Oo]utput\.args\.\w+\s*=[^=]/g
+const OBJECT_ASSIGN_PATTERN = /Object\.assign\(\s*\w*[Oo]utput\.args/g
describe("replace-tool-args audit", () => {
it("#given src/**/*.ts files #when scanning for direct output.args mutation #then no matches found outside the helper", async () => {