Skip to content

worktree.migration_plan

One step per misplaced worktree with a branch: where it is, where it belongs, how it would move, the uncommitted work that moves with it, and what blocks it; plus the exceptions the migration cannot address by design — detached worktrees, stale registrations, the primary checkout off the trunk — each with what a person does about it. Planning changes nothing; `majordomus worktree migrate` applies it with a fingerprint taken before and after every move.

One step per misplaced worktree with a branch: where it is, where it belongs, how it would move, the uncommitted work that moves with it, and what blocks it; plus the exceptions the migration cannot address by design — detached worktrees, stale registrations, the primary checkout off the trunk — each with what a person does about it. Planning changes nothing; `majordomus worktree migrate` applies it with a fingerprint taken before and after every move.

  • query
  • behaviorally_verified
  • module worktree
  • #worktree
  • #git
  • #topology
  • #migration

Exposure

Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.

surfaceas
MCPtool majordomus_worktree_migration_plan
HTTPGET /api/v1/worktrees/migration operationId worktree.migration_plan
command linemajordomus worktree migrate

Schemas

The canonical input and output, from the Rust types; the MCP tool schema and the OpenAPI parameters and responses are derived from these.

input · Empty

No input.

No properties: the capability takes no input.

JSON Schema
{
  "additionalProperties": false,
  "description": "No input.",
  "title": "Empty",
  "type": "object"
}

output · MigrationPlan

A migration, planned or applied.

propertytyperequireddescription
applied boolean yes Whether anything was changed.
blocked integer yes Steps that cannot.
container string yes The container everything moves into.
exceptions array yes Worktrees the migration cannot address by design: detached, missing, the primary checkout off the trunk. Each says what a person does about it.
failed integer yes Steps attempted and not verified.
movable integer yes Steps that can be carried out as things stand.
moved integer yes Steps carried out and verified.
moved_current string | null no The new path of the worktree the command was run from, when that one moved.
schema string yes [`SCHEMA`].
steps array yes One step per misplaced worktree with a branch, container occupants first.
JSON Schema
{
  "$defs": {
    "DiagnosticCode": {
      "description": "The stable machine name of everything that can be wrong with the topology. One code per\ncondition, reused by the command line, the API, MCP, the Cockpit, the tests and the\ndocumentation; the prose beside a code is rendered from the typed state.",
      "oneOf": [
        {
          "const": "worktree.path_mismatch",
          "description": "A linked work tree is not at its branch's canonical path.",
          "type": "string"
        },
        {
          "const": "worktree.container_occupied",
          "description": "A linked work tree occupies the container path itself.",
          "type": "string"
        },
        {
          "const": "worktree.nested",
          "description": "A linked work tree sits inside the primary checkout or inside another work tree.",
          "type": "string"
        },
        {
          "const": "worktree.destination_conflict",
          "description": "The canonical path of a branch is occupied by something that is not its work tree.",
          "type": "string"
        },
        {
          "const": "worktree.missing",
          "description": "A registered work tree's directory does not exist.",
          "type": "string"
        },
        {
          "const": "worktree.stale_registration",
          "description": "Git reports the registration as prunable.",
          "type": "string"
        },
        {
          "const": "worktree.branch_already_checked_out",
          "description": "A branch is checked out somewhere other than its canonical path.",
          "type": "string"
        },
        {
          "const": "worktree.detached",
          "description": "A linked work tree has no branch.",
          "type": "string"
        },
        {
          "const": "worktree.ephemeral",
          "description": "A linked work tree is a session's scratch checkout: under the temporary directory or\nunder the primary checkout's `.claude/worktrees/`.",
          "type": "string"
        },
        {
          "const": "worktree.primary_on_non_trunk",
          "description": "The primary checkout holds a branch that is not the trunk.",
          "type": "string"
        },
        {
          "const": "worktree.trunk_in_linked_worktree",
          "description": "The trunk is checked out in a linked work tree rather than the primary checkout.",
          "type": "string"
        },
        {
          "const": "worktree.path_escape",
          "description": "A derived path would leave the container. Cannot happen for a valid branch name.",
          "type": "string"
        },
        {
          "const": "worktree.invalid_branch_name",
          "description": "A branch name git accepted that this executable cannot derive a path for.",
          "type": "string"
        },
        {
          "const": "worktree.locked",
          "description": "A work tree is locked, so it cannot be moved until it is unlocked.",
          "type": "string"
        },
        {
          "const": "worktree.migration_verification_failed",
          "description": "A move happened and the fingerprint after it differs from the one before.",
          "type": "string"
        },
        {
          "const": "worktree.trunk_unknown",
          "description": "The trunk could not be determined.",
          "type": "string"
        },
        {
          "const": "worktree.case_collision",
          "description": "Two branch names map to one directory on a case-insensitive filesystem.",
          "type": "string"
        },
        {
          "const": "worktree.cross_device",
          "description": "A move crossed devices and was made by copy, repair and verification.",
          "type": "string"
        }
      ]
    },
    "DirtyState": {
      "description": "Uncommitted work in a work tree, counted from `git status --porcelain`. Untracked\ncontent counts: it is exactly what a careless move loses.",
      "properties": {
        "clean": {
          "description": "Nothing above is non-zero.",
          "type": "boolean"
        },
        "conflicted": {
          "description": "Entries with an unresolved merge conflict.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "in_progress": {
          "description": "A merge, rebase, cherry-pick, revert or bisect is in progress here.",
          "type": [
            "string",
            "null"
          ]
        },
        "staged": {
          "description": "Entries with a change in the index.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "unstaged": {
          "description": "Entries with a change in the work tree that is not in the index.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "untracked": {
          "description": "Untracked, not ignored, files.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "staged",
        "unstaged",
        "untracked",
        "conflicted",
        "clean"
      ],
      "type": "object"
    },
    "EnvrcApproval": {
      "description": "What became of the `.envrc` of a worktree that was just created, found, or moved.",
      "oneOf": [
        {
          "description": "direnv accepted it: the next `cd` loads the environment.",
          "properties": {
            "outcome": {
              "const": "approved",
              "type": "string"
            }
          },
          "required": [
            "outcome"
          ],
          "type": "object"
        },
        {
          "description": "The worktree has no `.envrc`; there is nothing to approve and nothing is blocked.",
          "properties": {
            "outcome": {
              "const": "no_envrc",
              "type": "string"
            }
          },
          "required": [
            "outcome"
          ],
          "type": "object"
        },
        {
          "description": "direnv is not on the PATH; nothing was done, and nothing is blocked either, because\nnothing would load the file.",
          "properties": {
            "outcome": {
              "const": "direnv_absent",
              "type": "string"
            }
          },
          "required": [
            "outcome"
          ],
          "type": "object"
        },
        {
          "description": "The worktree's `.envrc` is not the primary checkout's, so the approval given there\ndoes not carry. `direnv allow` in the worktree, after reading it, is the person's.",
          "properties": {
            "outcome": {
              "const": "differs",
              "type": "string"
            }
          },
          "required": [
            "outcome"
          ],
          "type": "object"
        },
        {
          "description": "The primary checkout's `.envrc` is not approved, so there is no approval to carry.",
          "properties": {
            "outcome": {
              "const": "not_approved_in_primary",
              "type": "string"
            }
          },
          "required": [
            "outcome"
          ],
          "type": "object"
        },
        {
          "description": "direnv was asked and refused, or could not be run; the message is its own.",
          "properties": {
            "message": {
              "description": "direnv's standard error, or the error running it.",
              "type": "string"
            },
            "outcome": {
              "const": "failed",
              "type": "string"
            }
          },
          "required": [
            "outcome",
            "message"
          ],
          "type": "object"
        }
      ]
    },
    "MigrationAction": {
      "description": "How a step moves its worktree.",
      "oneOf": [
        {
          "const": "move",
          "description": "One `git worktree move`.",
          "type": "string"
        },
        {
          "const": "move_via_staging",
          "description": "The worktree is the container itself: out to a staging path, then into the container.",
          "type": "string"
        },
        {
          "const": "copy_and_repair",
          "description": "The move crossed devices: copy, `git worktree repair`, verify, remove the original.",
          "type": "string"
        },
        {
          "const": "none",
          "description": "Nothing: the step is blocked.",
          "type": "string"
        }
      ]
    },
    "MigrationStep": {
      "description": "One worktree to bring home.",
      "properties": {
        "action": {
          "$ref": "#/$defs/MigrationAction",
          "description": "How it moves."
        },
        "after": {
          "anyOf": [
            {
              "$ref": "#/$defs/WorktreeFingerprint"
            },
            {
              "type": "null"
            }
          ],
          "description": "The fingerprint after it."
        },
        "before": {
          "anyOf": [
            {
              "$ref": "#/$defs/WorktreeFingerprint"
            },
            {
              "type": "null"
            }
          ],
          "description": "The fingerprint before the move."
        },
        "blockers": {
          "description": "Why it cannot move, when it cannot.",
          "items": {
            "$ref": "#/$defs/TopologyDiagnostic"
          },
          "type": "array"
        },
        "branch": {
          "description": "The branch it holds.",
          "type": "string"
        },
        "differences": {
          "description": "What differs between the two; empty when verified.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "dirty": {
          "$ref": "#/$defs/DirtyState",
          "description": "Its uncommitted work, which moves with it."
        },
        "envrc": {
          "anyOf": [
            {
              "$ref": "#/$defs/EnvrcApproval"
            },
            {
              "type": "null"
            }
          ],
          "description": "What became of its `.envrc` under direnv once it was at its new path: the primary\ncheckout's approval carried there, or why it was not. Only on a moved step."
        },
        "from": {
          "description": "Where it is.",
          "type": "string"
        },
        "head": {
          "description": "The commit checked out.",
          "type": [
            "string",
            "null"
          ]
        },
        "message": {
          "description": "What happened, in words, when it was not simply moved.",
          "type": [
            "string",
            "null"
          ]
        },
        "outcome": {
          "$ref": "#/$defs/StepOutcome",
          "description": "What happened."
        },
        "to": {
          "description": "Where it belongs.",
          "type": "string"
        }
      },
      "required": [
        "branch",
        "from",
        "to",
        "action",
        "dirty",
        "blockers",
        "outcome",
        "differences"
      ],
      "type": "object"
    },
    "Severity": {
      "description": "How bad a diagnostic is. `Error` excludes the file it concerns from the index and puts\nthe index into the degraded state; `Warning` and `Info` do neither.",
      "oneOf": [
        {
          "const": "info",
          "description": "Worth knowing; changes nothing.",
          "type": "string"
        },
        {
          "const": "warning",
          "description": "Something to look at; the object is still served.",
          "type": "string"
        },
        {
          "const": "error",
          "description": "The file is excluded and the index is degraded.",
          "type": "string"
        }
      ]
    },
    "StepOutcome": {
      "description": "What became of a step.",
      "oneOf": [
        {
          "const": "planned",
          "description": "Planned and not applied.",
          "type": "string"
        },
        {
          "const": "blocked",
          "description": "Not carried out, with the blockers on the step.",
          "type": "string"
        },
        {
          "const": "moved",
          "description": "Moved, and the fingerprint after equals the one before.",
          "type": "string"
        },
        {
          "const": "failed",
          "description": "Attempted and not completed, or completed and not verified; the message says which.",
          "type": "string"
        }
      ]
    },
    "TopologyDiagnostic": {
      "description": "One thing wrong with, or worth knowing about, the topology.",
      "properties": {
        "branch": {
          "description": "The branch involved.",
          "type": [
            "string",
            "null"
          ]
        },
        "code": {
          "$ref": "#/$defs/DiagnosticCode",
          "description": "The stable code."
        },
        "expected": {
          "description": "Where the work tree belongs.",
          "type": [
            "string",
            "null"
          ]
        },
        "message": {
          "description": "What is wrong, in one line.",
          "type": "string"
        },
        "path": {
          "description": "The work tree involved.",
          "type": [
            "string",
            "null"
          ]
        },
        "remedy": {
          "description": "The command that addresses it.",
          "type": "string"
        },
        "severity": {
          "$ref": "#/$defs/Severity",
          "description": "How serious it is."
        }
      },
      "required": [
        "code",
        "severity",
        "message",
        "remedy"
      ],
      "type": "object"
    },
    "WorktreeFingerprint": {
      "description": "What a work tree held at one moment, reduced to digests.",
      "properties": {
        "branch": {
          "description": "The branch, or none when detached.",
          "type": [
            "string",
            "null"
          ]
        },
        "head": {
          "description": "The commit.",
          "type": [
            "string",
            "null"
          ]
        },
        "ignored_manifest_digest": {
          "description": "A digest of every ignored entry: path, kind and size, never content.",
          "type": "string"
        },
        "in_progress": {
          "description": "The operation in progress, if any.",
          "type": [
            "string",
            "null"
          ]
        },
        "index_digest": {
          "description": "A digest of the index: every tracked path with its mode, blob and stage.",
          "type": "string"
        },
        "staged_diff_digest": {
          "description": "A digest of the staged diff against HEAD.",
          "type": "string"
        },
        "tree_manifest_digest": {
          "description": "A digest of every entry of the directory tree, ignored included: path, kind, size\nand link target. Taken only for a move made by copying, where the rename guarantee\ndoes not hold.",
          "type": [
            "string",
            "null"
          ]
        },
        "unstaged_diff_digest": {
          "description": "A digest of the unstaged diff against the index.",
          "type": "string"
        },
        "untracked_files": {
          "description": "How many untracked files the manifest holds.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "untracked_manifest_digest": {
          "description": "A digest of every untracked file: path, kind, size and content.",
          "type": "string"
        }
      },
      "required": [
        "index_digest",
        "staged_diff_digest",
        "unstaged_diff_digest",
        "untracked_manifest_digest",
        "untracked_files",
        "ignored_manifest_digest"
      ],
      "type": "object"
    }
  },
  "description": "A migration, planned or applied.",
  "properties": {
    "applied": {
      "description": "Whether anything was changed.",
      "type": "boolean"
    },
    "blocked": {
      "description": "Steps that cannot.",
      "format": "uint",
      "minimum": 0,
      "type": "integer"
    },
    "container": {
      "description": "The container everything moves into.",
      "type": "string"
    },
    "exceptions": {
      "description": "Worktrees the migration cannot address by design: detached, missing, the primary\ncheckout off the trunk. Each says what a person does about it.",
      "items": {
        "$ref": "#/$defs/TopologyDiagnostic"
      },
      "type": "array"
    },
    "failed": {
      "description": "Steps attempted and not verified.",
      "format": "uint",
      "minimum": 0,
      "type": "integer"
    },
    "movable": {
      "description": "Steps that can be carried out as things stand.",
      "format": "uint",
      "minimum": 0,
      "type": "integer"
    },
    "moved": {
      "description": "Steps carried out and verified.",
      "format": "uint",
      "minimum": 0,
      "type": "integer"
    },
    "moved_current": {
      "description": "The new path of the worktree the command was run from, when that one moved.",
      "type": [
        "string",
        "null"
      ]
    },
    "schema": {
      "description": "[`SCHEMA`].",
      "type": "string"
    },
    "steps": {
      "description": "One step per misplaced worktree with a branch, container occupants first.",
      "items": {
        "$ref": "#/$defs/MigrationStep"
      },
      "type": "array"
    }
  },
  "required": [
    "schema",
    "container",
    "steps",
    "exceptions",
    "movable",
    "blocked",
    "moved",
    "failed",
    "applied"
  ],
  "title": "MigrationPlan",
  "type": "object"
}

Policies

benchmark
required — a target on every transport the exposure declares; the cases are the input type's
cache
disabled — every call runs the handler

Benchmark targets

Derived from the registry for this repository: one requirement per transport, and the cases the input type provides. The whole matrix is on the benchmarks page.

transportstatecasestargets
directcovered1default
mcpcovered1default
httpcovered1default

The moments this answers