forkctl
Audited, mise-provisioned lifecycle control for downstream forks carried as StGit patch stacks.
Forkctl is a small Rust policy CLI over real git and stg commands. Git remains canonical history; StGit remains responsible for patch mechanics and conflicts. Forkctl declares policy, verifies reproducibility, records review evidence, and publishes rewritten history only under an exact lease.
The repository publishes:
forkctl— the CLI;tasks/fork.toml— immutable remote mise tasks forfork:init,fork:status,fork:new,fork:verify,fork:rebase, andfork:publish;examples/— copy-ready manifest and mise configuration.
Consumer setup
A fork owns one manifest, generated PATCHES.md, and any declared patch exports. Pin the task catalog to an immutable release or commit:
= "2026.7.7"
[]
= true
= true
[]
= "patches/downstream/fork.json"
[]
= [
"git::https://github.com/victor-software-house/forkctl.git//tasks/fork.toml?ref=<immutable-ref>",
"mise-tasks",
]
task_config.includes replaces mise's default task directories, so list mise-tasks when the repository also has local file tasks.
Workflow
fork:new creates a documented empty patch. Add and refresh its implementation, restore the bookkeeping patch, then run mise run fork:new -- --finish to regenerate declared exports and verify it. Rebase creates an annotated recovery tag and Git-private no-color range-diff report but never publishes. Publish verifies again and atomically pushes the recovery tag plus branch with an explicit --force-with-lease=<ref>:<sha>.
forkctl instructions prints the agent/operator contract without requiring a Git repository.
Manifest
Every patch commit must carry trailers matching its manifest metadata:
Downstream-Reason: Describe why this downstream change exists.
Upstream-Status: not-submitted
Drop-When: Upstream provides the required behavior.
Source patches precede tooling patches. The final tooling patch owns manifest, ledger, export, and task bookkeeping. A tooling-only stack is valid. Exports are optional independent reconstruction evidence.
Verification and recovery
Verification fails closed on dirty state, wrong branch/tracking, remote drift, base drift, patch order, unapplied or empty patches, undeclared per-patch paths, trailer drift, ledger drift, export drift, reconstruction drift, and missing source contracts.
If rebase conflicts, forkctl preserves the normal StGit state, pending lease, Git-private manifest snapshot, and recovery tag. Resolve explicitly:
Forkctl never stashes or resolves conflict content.
Direct installation
Mise tasks provision exact Rust, StGit, and forkctl versions. For direct use:
Provide supported git and stg executables on PATH.
Version synchronization
[workspace.package].version in Cargo.toml is the sole version source. mise run version:sync updates the six task tool pins and examples/mise.toml. Lefthook synchronizes and stages them before commits; mise run verify rejects drift.
Development
The gate runs rustfmt, workspace-wide Clippy all and pedantic with warnings denied, unit tests, and disposable real Git/StGit lifecycle tests. No test requires a consumer repository or network access.