worktree.migration_plan
Jeden krok na každý špatně umístěný worktree s větví: kde je, kam patří, jak by se přesunul, necommitnutá práce, která se přesouvá s ním, a co ho blokuje; plus výjimky, které migrace z podstaty nemůže řešit — detached worktrees, zastaralé registrace, primární checkout mimo trunk — každá s tím, co s ní člověk udělá. Plánování nic nemění; `majordomus worktree migrate` jej aplikuje s otiskem pořízeným před každým přesunem i po něm.
Jeden krok na každý špatně umístěný worktree s větví: kde je, kam patří, jak by se přesunul, necommitnutá práce, která se přesouvá s ním, a co ho blokuje; plus výjimky, které migrace z podstaty nemůže řešit — detached worktrees, zastaralé registrace, primární checkout mimo trunk — každá s tím, co s ní člověk udělá. Plánování nic nemění; `majordomus worktree migrate` jej aplikuje s otiskem pořízeným před každým přesunem i po něm.
- query
- behaviorally_verified
- module worktree
- #worktree
- #git
- #topology
- #migration
Zpřístupnění
Kde je tato jedna definice dosažitelná. Absence je explicitní: povrch, který není uveden, ji nenese.
| povrch | jako |
|---|---|
| MCP | nástroj majordomus_worktree_migration_plan |
| HTTP | GET /api/v1/worktrees/migration operationId worktree.migration_plan |
| příkazová řádka | majordomus worktree migrate |
Schémata
Kanonický vstup a výstup z typů Rustu; schéma nástroje MCP a parametry a odpovědi OpenAPI se odvozují z nich.
vstup · Prázdné
Žádné vlastnosti: schopnost nebere žádný vstup.
JSON Schema
{
"additionalProperties": false,
"description": "No input.",
"title": "Empty",
"type": "object"
}výstup · MigrationPlan
| vlastnost | typ | povinné | popis |
|---|---|---|---|
| aplikováno | boolean | ano | Zda se cokoli změnilo. |
| blokováno | integer | ano | Kroky, které nemohou. |
| kontejner | string | ano | Kontejner, do kterého se vše přesouvá. |
| výjimky | array | ano | Worktree, které migrace z principu nemůže adresovat: detached, chybějící, primární checkout mimo trunk. Každý říká, co s tím člověk udělá. |
| selhalo | integer | ano | Kroky, které byly zkoušeny a nebyly ověřeny. |
| přesunutelné | integer | ano | Kroky, které lze za současného stavu provést. |
| přesunuto | integer | ano | Provedené a ověřené kroky. |
| moved_current | string | null | ne | Nová cesta worktree, ze kterého byl příkaz spuštěn, když se přesunul. |
| schema | string | ano | SCHEMA. |
| kroky | array | ano | Jeden krok na každý špatně umístěný worktree s větví, nejdřív obyvatelé kontejneru. |
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"
}
]
},
"HooksPath": {
"description": "What became of the hooks directory of a worktree that was just created, found or moved.\n\nIt travels in the JSON of `worktree create`, `ensure`, `migrate` and `repair`, tagged by\n`outcome`, so a reader branches on one word rather than parsing the line:\n\n```\nuse majordomus_cli::worktree::HooksPath;\n\nlet set = HooksPath::Set {\n path: \"/r-wt/fix/x/.githooks\".into(),\n enabled: vec![],\n};\nlet json = serde_json::to_value(&set).unwrap();\nassert_eq!(json[\"outcome\"], \"set\");\nassert_eq!(json[\"path\"], \"/r-wt/fix/x/.githooks\");\nlet back: HooksPath = serde_json::from_value(json).unwrap();\nassert_eq!(back, set);\n```",
"oneOf": [
{
"description": "The repository's configuration sets no `core.hooksPath`: git's own hooks directory\nin the common directory (or a value of the user's) serves every worktree, and there\nis no tracked directory to follow.",
"properties": {
"outcome": {
"const": "not_configured",
"type": "string"
}
},
"required": [
"outcome"
],
"type": "object"
},
{
"description": "Git already resolves this worktree's hooks to its own directory; nothing was set.",
"properties": {
"outcome": {
"const": "own",
"type": "string"
},
"path": {
"description": "The directory git runs the hooks from.",
"type": "string"
}
},
"required": [
"outcome",
"path"
],
"type": "object"
},
{
"description": "This worktree's `core.hooksPath` was set, per worktree, to its own directory.",
"properties": {
"enabled": {
"description": "Repository settings switched on so that a per-worktree value is honoured, as\n`key=value`; empty when they were on already.",
"items": {
"type": "string"
},
"type": "array"
},
"outcome": {
"const": "set",
"type": "string"
},
"path": {
"description": "The directory it now runs the hooks from.",
"type": "string"
}
},
"required": [
"outcome",
"path",
"enabled"
],
"type": "object"
},
{
"description": "The hooks directory is outside the primary checkout — one directory shared on\npurpose — and every worktree runs it; nothing was set.",
"properties": {
"outcome": {
"const": "shared",
"type": "string"
},
"path": {
"description": "The directory every worktree runs the hooks from.",
"type": "string"
}
},
"required": [
"outcome",
"path"
],
"type": "object"
},
{
"description": "The primary checkout's hooks directory has no counterpart in this worktree's tree,\nso the worktree keeps running the primary's: pointing it at a directory that does\nnot exist would switch its hooks off.",
"properties": {
"missing": {
"description": "The directory that would be the worktree's own, and is not there.",
"type": "string"
},
"outcome": {
"const": "untracked",
"type": "string"
},
"runs": {
"description": "The directory the worktree runs the hooks from instead.",
"type": "string"
}
},
"required": [
"outcome",
"missing",
"runs"
],
"type": "object"
},
{
"description": "Git was asked and refused, or could not be run; the message is its own.",
"properties": {
"message": {
"description": "What went wrong.",
"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"
]
},
"hooks": {
"anyOf": [
{
"$ref": "#/$defs/HooksPath"
},
{
"type": "null"
}
],
"description": "Which hooks it runs at its new path: a per-worktree `core.hooksPath` names the old\none, so a moved worktree is bound again to its own tree's (I2718). Only on a moved\nstep."
},
"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"
}Politiky
- benchmark
- povinné — cíl na každém transportu, který expozice deklaruje; případy jsou ty ze vstupního typu
- cache
- vypnuto — každé volání spustí handler
Cíle benchmarku
Odvozeno z registru pro tento repozitář: jeden požadavek na transport a případy, které poskytuje typ vstupu. Celá matice je na stránce měření výkonu.