Manual Repository Transfer
Transfer Git history when it exists plus a verified local-state overlay. Size, age, naming, and ignored status never prove data disposable.
Invariants
- For a committed repository, Git covers required commits/refs; the overlay covers selected local state. An unborn repository has no
HEADhistory to claim, so its overlay and Git metadata are evidence only. - Inventory is all-or-nothing: the no-follow census is the sole enumerator and classifies its exact
./-prefixed NUL-delimited paths in boundedgit check-ignore --stdin -zbatches. Traverse ordinary directories, record reparse entries as metadata without descending, and admit only non-reparse regular files. An unreadable subtree or entry, named pipe, socket, device, or unknown filesystem type blocks inventory before output. - Inventory and selection JSON inputs are each one identity-bound ordinary file from classification through bounded parse. The inventory alone has a 256 MiB cap and is canonically streamed to its output; selection and every other control document retain the 8 MiB cap. POSIX opens the no-follow leaf nonblocking before
fstat, so a FIFO without a writer cannot stall classification; Windows rejects reparse points, directories, devices, alternate data streams, and namespace aliases before reading. Type, size, held identity, parent identity, and pathname binding must remain stable through parse. - Each selected ZIP payload is one identity-bound ordinary file from no-follow, nonblocking classification through chunked hashing and ZIP emission. The helper streams the already-open descriptor, never reopens the pathname for content, and requires the held leaf, parents, size, digest, and final pathname binding to remain stable before close; FIFOs, sockets, links, directories, devices, alternate data streams, and reparse points fail promptly.
- One manifest assigns every local file or link one non-overlapping disposition.
- ZIP contains regular-file bytes. Restricted data and links use content-bound external receipts.
- A Lead or human selects and verifies one explicit absolute Git executable outside the repository before invoking the helper; the helper never resolves
gitfrom PATH, the current directory, or an environment override. - Before the first process launch, the helper resolves a repository alias or subdirectory to the nearest physical root with a strict ordinary
.gitdirectory or gitfile marker, then binds one physically canonical, reparse-free Git executable outside that root by identity and SHA-256. It discards the alias for process working directories, requires Git's reported top-level to match, and rechecks the executable around later Git launches. Failures useTRANSFER-REPOSITORY-BOUNDARY-INVALID,TRANSFER-GIT-BINDING-INVALID,TRANSFER-GIT-ROOT-MISMATCH, orTRANSFER-GIT-BINDING-DRIFT; a same-user replacement after the final pre-open check remains outside this guarantee. - UTF-8
surrogateescapepath bytes round-trip in canonical JSON by escaping onlyU+DC80..U+DCFF; ordinary Unicode keeps the existing Version 1 bytes and digests, while every other lone surrogate fails asTRANSFER-PATH-ENCODING-INVALID. Such paths are hostile metadata-only entries requiring one exact external receipt; payload, deletion, ancestor inclusion, or ZIP placement fails asTRANSFER-HOSTILE-PATH-EXTERNAL-REQUIRED. - The helper verifies and previews; only a repository/lifecycle owner applies an authorized deletion plan.
inventoryandbundlerefuse an existing output by default; only their explicit--forcereplaces one output. The helper binds the ordinary parent and, when present, the exact ordinary output identity before generation. After the completed temporary is flushed and synchronized, an absent output is published by one atomic no-replace link, while a forced existing output is published by rechecking that same parent and exact ordinary identity immediately before oneos.replace. Raced outputs, links, reparse points, directories, unsafe ancestors, and identity drift fail closed. A same-user substitution after the final identity check is outside the 1.x guarantee.verifyandcleanupnever accept--force.- Any Git, lifecycle, recovery, or tool-state mutation invalidates the inventory. Rebuild.
Receiving from repository cleanup
When $repo-cleanup transfer mode invokes this skill, accept a current-invocation RepoCleanupReportV1, bound to the same physical repository identity and HEAD/unborn state, only when it has PASS or its sole nonpassing cause is the shared host-policy-denial exception for explicitly deferred, freshly proven harmless empty agent-owned directory residue. In the exception case, cleanup and zero-residue predicates remain fail; every transfer gate must independently pass, transfer must not depend on the directory, and the final inventory and selection process must explicitly account for the deferred target and prove that no valuable data is silently omitted. Then own exactly cleanup PASS or qualifying deferred residue accounted -> final inventory -> bundle -> trusted verify -> post-transfer classification. This skill does not run cleanup again, and neither the cleanup report nor the exception authorizes bundle creation, copying, deletion, wipe, publication, or removal. Report the exact residue and resume condition in the transfer handoff. A direct explicit $manual-repo-transfer request without cleanup intent continues to enter this skill directly.
Workflow
Read repository governance and validation docs. Discover dot-directories, ignored/untracked state, and self-ignored workspaces. A clean
git statusis insufficient. Query owning tools through API/MCP; validate stored config/memory against the active project. Use local-state categories.Discover requested project indices, project settings, and configuration through their available owner, Model Context Protocol (MCP), or tool. Record whether each is portable, requires an external backup receipt, or must be rebuilt on the receiver. Do not create indices, install providers, or transfer global authentication or provider credentials as project state.
Have the owning roles finish or explicitly freeze all authorized source, Git, lifecycle, and recovery changes that must reach the receiver. Preserve selected dirty, staged, untracked, and local-only Git state; do not clean, reset, commit, or publish merely to simplify transfer. Run an earlier full inventory, bundle, and verification rehearsal only when a recorded actual risk justifies it; its output is non-handoff evidence, and every later mutation invalidates it.
Quiesce writers. After the last source, Git, or lifecycle change, refresh or revalidate each requested index, project setting, and configuration with its documented owner command; require fresh successful output and settle its writers. Preserve fresh portable state in the overlay. Preserve nonportable state through its appropriate backup plus an explicit receiver rebuild. A failed refresh is not fresh, and any change after freeze invalidates index freshness and the inventory snapshot. Freeze this state, then record repository history state,
HEADwhen committed, refs, credential-redacted remotes, dirty/index state, reparse points, lifecycle state, stashes, registered worktrees, and Git recovery surfaces. The helper excludes.git; audit it separately. Launch every inventory, bundle, verification, and diagnostic import withpython -Band withPYTHONDONTWRITEBYTECODE=1set in that subprocess before imports; do not change an interpreter, process-global, or user environment.-Bprevents new bytecode but does not remove existing caches; classification and cleanup ownership are unchanged.Generate the final inventory outside the worktree:
python -B <skill>/scripts/repo_transfer.py inventory --repo <repo> --git-executable <absolute-git-executable> --output <inventory.json> [--force]Create a selection using the manifest schema. Assign every required entry exactly one disposition:
Disposition Meaning includePreserve ordinary unique local state in the ZIP. externalPreserve restricted data or link metadata in separately verified storage. deleteAdd a content-bound, evidence-backed item to the preview-only deletion plan. Rows may not overlap. Ambiguity means
include. Never follow a link; classify its target separately.For a committed repository, use the selected remote's local-tracking evidence plus policy-required server probes. Otherwise create and verify a Git bundle; copying
.gitis not the default. For an unborn repository, select onlygitStrategy.mode: none: no remote can cover a nonexistentHEAD, and a standard Git bundle cannot preserve nonexistent history.Build and source-verify the overlay from that final inventory:
python -B <skill>/scripts/repo_transfer.py bundle --repo <repo> --git-executable <absolute-git-executable> --inventory <inventory.json> --selection <selection.json> --output <transfer.zip> [--force] python -B <skill>/scripts/repo_transfer.py verify --bundle <transfer.zip> --git-executable <absolute-git-executable> --inventory <inventory.json> --selection <selection.json> --source <repo>Store the artifact independently from the source PC. If the receiver is unavailable, rehearse a clean local restore of the final artifact before authorizing a wipe. Generate the deletion preview with
cleanup; after separate authorization, the owner applies it and proves the resulting census. Only this post-freeze, verified artifact is the handoff.On the receiver: verify the ZIP against its separate SHA-256; restore Git and regular-file overlay entries; run payload/source verification; restore external artifacts through receipts; regenerate dependencies/caches; run repository checks. For an unborn inventory, the ZIP preserves file bytes plus staged/unstaged/status evidence but does not recreate index equivalence or fabricate an initial commit. Retain artifacts until acceptance.
Stop conditions
Unclassified or incompletely enumerated state, unreadable or unsupported filesystem entries, overlap, drift, unsafe archive members, missing hashes, live writers, path escapes, unexpected links, unverifiable receipts, or failed restore checks block cleanup and wipe. Copy success, listing, size, or callback is not integrity evidence. Transfer preparation never grants publication, wipe, or deletion authority.
Terms and Abbreviations
- Local-state overlay: selected state outside verified Git history.
- Reparse point: Windows link-like filesystem object, including a junction.
- SHA-256: Secure Hash Algorithm 256-bit digest.