Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions docs/hooks/tools.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -675,16 +675,18 @@ If a value is too large for the environment, it may be omitted (not set). Mux al
</details>

<details>
<summary>task_apply_git_patch (6)</summary>

| Env var | JSON path | Type | Description |
| ---------------------------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `MUX_TOOL_INPUT_DRY_RUN` | `dry_run` | boolean | When true, attempt to apply the patch in a temporary git worktree and then discard it (does not modify the current workspace). |
| `MUX_TOOL_INPUT_EXPECTED_HEAD_SHA` | `expected_head_sha` | string | When provided, refuse to apply unless the target repository HEAD matches this SHA. |
| `MUX_TOOL_INPUT_FORCE` | `force` | boolean | When true, allow apply even if the patch was previously applied. |
| `MUX_TOOL_INPUT_PROJECT_PATH` | `project_path` | string | When provided, apply only the patch artifact for this project path. |
| `MUX_TOOL_INPUT_TASK_ID` | `task_id` | string | Child task ID whose patch artifact should be applied |
| `MUX_TOOL_INPUT_THREE_WAY` | `three_way` | boolean | When true, run git am with --3way |
<summary>task_apply_git_patch (8)</summary>

| Env var | JSON path | Type | Description |
| ----------------------------------------------- | -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MUX_TOOL_INPUT_ACKNOWLEDGE_PARTIAL_RECOVERY` | `acknowledge_partial_recovery` | boolean | When true, acknowledge that a PARTIALLY applied artifact (commit series landed, uncommitted-changes patch failed) was completed manually: clears the partial marker and records the artifact as applied without applying anything. Use after resolving the remaining changes by hand, e.g. a merged conflict resolution the automatic already-present detection cannot recognize. |
| `MUX_TOOL_INPUT_ACKNOWLEDGE_UNCAPTURED_CHANGES` | `acknowledge_uncaptured_changes` | boolean | When true, apply the captured content even though the child ended with uncommitted changes that were NOT captured into the artifact (see worktreePatchSkippedReason). Without this flag such applies fail so the uncaptured work cannot be silently omitted. Use after recovering the uncaptured changes manually from the preserved child workspace, or after deciding they are not needed. |
| `MUX_TOOL_INPUT_DRY_RUN` | `dry_run` | boolean | When true, attempt to apply the patch in a temporary git worktree and then discard it (does not modify the current workspace). |
| `MUX_TOOL_INPUT_EXPECTED_HEAD_SHA` | `expected_head_sha` | string | When provided, refuse to apply unless the target repository HEAD matches this SHA. |
| `MUX_TOOL_INPUT_FORCE` | `force` | boolean | When true, allow apply even if the patch was previously applied. |
| `MUX_TOOL_INPUT_PROJECT_PATH` | `project_path` | string | When provided, apply only the patch artifact for this project path. |
| `MUX_TOOL_INPUT_TASK_ID` | `task_id` | string | Child task ID whose patch artifact should be applied |
| `MUX_TOOL_INPUT_THREE_WAY` | `three_way` | boolean | When true, run git am with --3way |

</details>

Expand Down
41 changes: 41 additions & 0 deletions src/common/utils/tools/toolDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,36 @@ export const SubagentGitProjectPatchArtifactSchema = z
headCommitSha: z.string().optional(),
commitCount: z.number().int().nonnegative().optional(),
mboxPath: z.string().optional(),
hadUncommittedChanges: z.boolean().optional(),
worktreePatchPath: z.string().optional(),
worktreePatchBytes: z.number().int().nonnegative().optional(),
worktreePatchSkippedReason: z.string().optional(),
error: z.string().optional(),
appliedAtMs: z.number().int().nonnegative().optional(),
// Target HEAD after the full application; replay-safe retries verify the
// applied work is still present against it before skipping.
appliedHeadSha: z.string().optional(),
// Application asserted via acknowledge_partial_recovery: the manual
// recovery may not be reverse-applicable, so replay-safe validation
// skips the content check for it (ancestry still applies).
appliedAcknowledged: z.boolean().optional(),
// True when only the commit series landed (worktree patch failed); replay
// integrations must not treat this as a completed application.
appliedPartial: z.boolean().optional(),
// Target HEAD when the partial application was recorded. Completion
// requires it to still be an ancestor of HEAD, so a reset/rebased target
// cannot clear the marker while the applied commit series is missing.
appliedPartialHeadSha: z.string().optional(),
// "am-started": persisted BEFORE git am runs (fence = pre-am HEAD), so a
// crash after git am cannot leave applied commits unrecorded. Recovery
// retries fresh only when HEAD still equals the fence, else fails
// closed. "commits-applied" (or absent, for markers written before this
// field existed): the series landed; retries complete the worktree
// patch only. "unknown" is never written by an apply: sanitizers map a
// present-but-unreadable stage to it (dropping the field would misread
// an interrupted am-started record as commits-applied and skip git am),
// and recovery fails closed until acknowledged.
appliedPartialStage: z.enum(["am-started", "commits-applied", "unknown"]).optional(),
})
.strict();

Expand Down Expand Up @@ -920,6 +948,18 @@ export const TaskApplyGitPatchToolArgsSchema = z
.boolean()
.nullish()
.describe("When true, allow apply even if the patch was previously applied."),
acknowledge_partial_recovery: z
.boolean()
.nullish()
.describe(
"When true, acknowledge that a PARTIALLY applied artifact (commit series landed, uncommitted-changes patch failed) was completed manually: clears the partial marker and records the artifact as applied without applying anything. Use after resolving the remaining changes by hand, e.g. a merged conflict resolution the automatic already-present detection cannot recognize."
),
acknowledge_uncaptured_changes: z
.boolean()
.nullish()
.describe(
"When true, apply the captured content even though the child ended with uncommitted changes that were NOT captured into the artifact (see worktreePatchSkippedReason). Without this flag such applies fail so the uncaptured work cannot be silently omitted. Use after recovering the uncaptured changes manually from the preserved child workspace, or after deciding they are not needed."
),
})
.strict();

Expand Down Expand Up @@ -2058,6 +2098,7 @@ export const TOOL_DEFINITIONS = {
task_apply_git_patch: {
description:
"Apply a completed sub-agent task's git-format-patch artifact to the current workspace using `git am`. " +
"If the child ended with uncommitted changes, they were captured as a worktree diff and are applied after the commits, landing as uncommitted changes. " +
"This is an explicit integration step: mux will not auto-apply patches.",
schema: TaskApplyGitPatchToolArgsSchema,
},
Expand Down
9 changes: 9 additions & 0 deletions src/constants/subagentPatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Untracked files may be arbitrarily large, so capture needs a hard disk-usage bound.
export const SUBAGENT_WORKTREE_PATCH_MAX_BYTES = 10 * 1024 * 1024;

// `git add` materializes whole blobs into the capture's temporary object dir
// before the capped diff produces any output, so staging needs its own bound:
// the diff cap alone would let a multi-gigabyte dirty file fill /tmp. Larger
// than the diff cap because a big tracked file with a small change stages a
// big blob yet can still produce a small, capturable diff.
export const SUBAGENT_WORKTREE_PATCH_MAX_STAGED_BYTES = 256 * 1024 * 1024;
22 changes: 12 additions & 10 deletions src/node/services/agentSkills/builtInSkillContent.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5494,16 +5494,18 @@ export const BUILTIN_SKILL_FILES: Record<string, Record<string, string>> = {
"</details>",
"",
"<details>",
"<summary>task_apply_git_patch (6)</summary>",
"",
"| Env var | JSON path | Type | Description |",
"| ---------------------------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |",
"| `MUX_TOOL_INPUT_DRY_RUN` | `dry_run` | boolean | When true, attempt to apply the patch in a temporary git worktree and then discard it (does not modify the current workspace). |",
"| `MUX_TOOL_INPUT_EXPECTED_HEAD_SHA` | `expected_head_sha` | string | When provided, refuse to apply unless the target repository HEAD matches this SHA. |",
"| `MUX_TOOL_INPUT_FORCE` | `force` | boolean | When true, allow apply even if the patch was previously applied. |",
"| `MUX_TOOL_INPUT_PROJECT_PATH` | `project_path` | string | When provided, apply only the patch artifact for this project path. |",
"| `MUX_TOOL_INPUT_TASK_ID` | `task_id` | string | Child task ID whose patch artifact should be applied |",
"| `MUX_TOOL_INPUT_THREE_WAY` | `three_way` | boolean | When true, run git am with --3way |",
"<summary>task_apply_git_patch (8)</summary>",
"",
"| Env var | JSON path | Type | Description |",
"| ----------------------------------------------- | -------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |",
"| `MUX_TOOL_INPUT_ACKNOWLEDGE_PARTIAL_RECOVERY` | `acknowledge_partial_recovery` | boolean | When true, acknowledge that a PARTIALLY applied artifact (commit series landed, uncommitted-changes patch failed) was completed manually: clears the partial marker and records the artifact as applied without applying anything. Use after resolving the remaining changes by hand, e.g. a merged conflict resolution the automatic already-present detection cannot recognize. |",
"| `MUX_TOOL_INPUT_ACKNOWLEDGE_UNCAPTURED_CHANGES` | `acknowledge_uncaptured_changes` | boolean | When true, apply the captured content even though the child ended with uncommitted changes that were NOT captured into the artifact (see worktreePatchSkippedReason). Without this flag such applies fail so the uncaptured work cannot be silently omitted. Use after recovering the uncaptured changes manually from the preserved child workspace, or after deciding they are not needed. |",
"| `MUX_TOOL_INPUT_DRY_RUN` | `dry_run` | boolean | When true, attempt to apply the patch in a temporary git worktree and then discard it (does not modify the current workspace). |",
"| `MUX_TOOL_INPUT_EXPECTED_HEAD_SHA` | `expected_head_sha` | string | When provided, refuse to apply unless the target repository HEAD matches this SHA. |",
"| `MUX_TOOL_INPUT_FORCE` | `force` | boolean | When true, allow apply even if the patch was previously applied. |",
"| `MUX_TOOL_INPUT_PROJECT_PATH` | `project_path` | string | When provided, apply only the patch artifact for this project path. |",
"| `MUX_TOOL_INPUT_TASK_ID` | `task_id` | string | Child task ID whose patch artifact should be applied |",
"| `MUX_TOOL_INPUT_THREE_WAY` | `three_way` | boolean | When true, run git am with --3way |",
"",
"</details>",
"",
Expand Down
Loading
Loading