Documentation
¶
Overview ¶
Package wt wraps the git operations behind worktree orchestration. All functions shell out to git (worktree/merge plumbing via a library is far riskier than the battle-tested CLI); commits are authored as "spectackle" so agent commits are attributable.
The invariant the whole merge strategy rests on: CommitCode excludes every .spectackle directory, so branches carry CODE ONLY — spec state reaches main exclusively through the semantic replay, and .spectackle files are never textually merged.
Index ¶
- Variables
- func Add(mainRoot, wtRoot, branch, startPoint, base string, force bool) error
- func BranchExists(dir, branch string) bool
- func CommitCode(wtRoot, msg string) (bool, error)
- func CommitRecords(wtRoot, msg string) (bool, error)
- func CommonRoot(dir string) (main string, isWT bool, err error)
- func CurrentBranch(dir string) (string, error)
- func DefaultBranch(dir string) (string, error)
- func DeleteBranch(mainRoot, branch string) error
- func DirtyFiles(wtRoot string) ([]string, error)
- func DirtyOverlap(mainRoot string, files []string) []string
- func DiscardBranch(mainRoot, branch, base string) error
- func EnsureBranch(dir, branch, startPoint string) error
- func FFMain(mainRoot, branch string) error
- func FFMainPreservingRecords(mainRoot, branch string) (err error)
- func HasUnpushedCommits(dir, remote, branch string) (bool, error)
- func Head(dir string) (string, error)
- func HeadSHA(dir, branch string) (string, error)
- func HeadShortSHA(dir string) string
- func HookPath(dir string) string
- func HookReferencesSpectackle(dir string) bool
- func IdentityConfigured(dir string) bool
- func InitTestRepo(dir string) error
- func InstallPrePushHook(dir string) error
- func IsAheadOf(dir, branch, base string) (bool, error)
- func IsAheadOfRemote(dir, branch, remote, base string) (bool, error)
- func IsRepo(dir string) bool
- func MergeInProgress(wtRoot string) bool
- func MergeMain(wtRoot string) (conflicts []string, err error)
- func Push(dir, remote, branch string) error
- func RemoteURL(dir, remote string) (string, error)
- func Remove(mainRoot, wtRoot string) error
- func ShowFile(mainRoot, ref, relPath string) ([]byte, error)
- func TouchedFiles(mainRoot, base, branch string) ([]string, error)
Constants ¶
This section is empty.
Variables ¶
var FallbackIdentity = []string{"-c", "user.name=spectackle", "-c", "user.email=spectackle@localhost"}
FallbackIdentity is the placeholder -c pair used ONLY when no identity resolves from any git config scope, so automation can still commit on a bare host (CI containers) instead of dying at "tell me who you are". It must never override a configured identity — withIdentity guards that — and per git precedence GIT_AUTHOR_*/GIT_COMMITTER_* environment identity still wins over these flags.
Functions ¶
func Add ¶
Add creates a worktree at wtRoot on a fresh branch from startPoint, recovering from leftovers of a crashed prior run. force clears a dirty ledgerless stray at the target path; without it such a stray refuses.
func BranchExists ¶ added in v0.2.0
BranchExists reports whether a local branch ref exists. A query, not a gate: any git failure reads as "absent", and the caller's subsequent EnsureBranch surfaces real breakage loudly.
func CommitCode ¶
CommitCode stages and commits everything EXCEPT .spectackle state. committed=false means the tree had no code changes (still fine to replay).
func CommitRecords ¶ added in v0.2.0
CommitRecords stages and commits ONLY .spectackle record state, the exact complement of CommitCode's pathspec split. committed=false means no record file was dirty.
It exists because the split left a hole: CommitCode runs mechanically on every transition and excludes .spectackle (B-0006), so after a full lifecycle the record delta sat uncommitted in the checkout with nobody mechanical responsible for it — the one thing the always-pushed policy forbids. This is the other half of that responsibility.
The files are enumerated first and then added AND committed by explicit path list. That is not a style choice: commit-by-explicit-pathspec is what guarantees a user's concurrently staged unrelated work is never swept into a records commit, and enumerating first avoids the pathspec-did-not-match failure that a blind glob add hits in a workspace with no nested context dirs. ls-files --others lists every untracked file individually, so a brand-new context dir cannot be collapsed into one directory entry the filter never sees.
func CommonRoot ¶
CommonRoot resolves the MAIN repository root for a dir that may be inside a linked worktree. isWT reports whether dir lives in a linked worktree.
func CurrentBranch ¶
CurrentBranch returns the checked-out branch name of dir.
func DefaultBranch ¶ added in v0.2.0
DefaultBranch resolves the branch checked out at dir via HEAD's symbolic ref rather than CurrentBranch's rev-parse: workspace.Config.Git.Base reads this at config-load time, which can run before the repo has a single commit yet (rev-parse --abbrev-ref HEAD errors on an unborn HEAD; symbolic-ref resolves regardless) — and it exists at all so that default never has to be a hardcoded "main" (see MergeMain's B-0004 fix for the same principle applied to merge targets).
func DeleteBranch ¶
DeleteBranch removes a branch (post-abort cleanup).
func DirtyFiles ¶ added in v0.2.1
DirtyFiles lists uncommitted paths in a worktree — tracked modifications plus untracked files, enumerated the CommitRecords way (name-only diff + ls-files --others; porcelain's positional columns are trim-hostile, see the comment there). Used by the never-destroy guard (B-01KYH8JBB): a worktree holding any of these must not be recreated without an explicit force.
func DirtyOverlap ¶
DirtyOverlap returns uncommitted main-checkout paths that intersect files.
func DiscardBranch ¶ added in v0.2.0
DiscardBranch deletes an item branch whose work is being thrown away (abort, orphan adoption), vacating it from the main checkout first when it is checked out there — `branch -D` fails on a checked-out branch, and the two discard sites used to swallow that failure, after which the attach path (B-01KYED3D) would resurrect the surviving commits on the next start (B-01KYEEJKE). The returned error is for the caller to SAY, not to swallow: a branch that outlives its discard changes what the next start resumes.
func EnsureBranch ¶ added in v0.2.0
EnsureBranch makes branch the checked-out branch of dir: creates it from startPoint if it doesn't exist yet, otherwise just checks it out. A retried transition (e.g. a task re-entering active after a reopen) must land on the SAME branch it used before, not fail because that branch is already there — so the second call on an existing branch is an ordinary checkout, never an error.
func FFMain ¶
FFMain fast-forwards main to the branch. Under the integrate lock (main was just merged into the branch) this cannot conflict; git still aborts safely if the user's main checkout is dirty on touched files.
func FFMainPreservingRecords ¶ added in v0.2.0
FFMainPreservingRecords fast-forwards branch into the main checkout with the same records dance MergeMain performs on the worktree side (B-0006): live .spectackle files are preserved, cleared for the merge, and put back. Needed since B-01KYED3D let worktrees attach to gitflow-created branches, which CARRY records commits — the plain ff collided with the main checkout's live untracked records exactly where the worktree-side merge used to, and replay stays the sole owner of record-state reconciliation either way.
func HasUnpushedCommits ¶ added in v0.2.0
HasUnpushedCommits reports whether branch carries commits remote does not have yet. Before the first Push there is no remote-tracking ref to compare against at all, so every local commit trivially counts as unpushed; after Push lands them, the comparison is a straight rev-list.
func HeadSHA ¶ added in v0.2.0
HeadSHA resolves a local branch to its commit. The gitflow reads it right after pushing, so the CI await polls the exact commit that was pushed rather than a branch ref the forge may briefly resolve to the predecessor.
func HeadShortSHA ¶ added in v0.3.0
HeadShortSHA returns the short hash of dir's HEAD commit — the offline edge render's evidence line (T-01KYHAH1GJ). Callers invoke it right after a successful commit, so a rev-parse failure is near-impossible; it degrades to "?" rather than turning a successful commit into an error.
func HookPath ¶ added in v0.2.0
HookPath returns the repo's pre-push hook path, honoring core.hooksPath being ABSENT (the default layout); a custom hooksPath repo is left to its owner — the recommendation hint stays silent there.
func HookReferencesSpectackle ¶ added in v0.2.0
HookReferencesSpectackle reports whether an existing pre-push hook already runs the spectackle gate.
func IdentityConfigured ¶ added in v0.2.0
IdentityConfigured reports whether dir resolves a commit identity (user.name AND user.email non-empty) from any config scope. An upfront check rather than a retry on the commit failure: git's tell-me-who-you-are prose localizes with the host locale, and error-text matching would make the fallback fire (or not) depending on LC_ALL.
func InitTestRepo ¶
InitTestRepo creates a git repo with an initial commit on branch main — used by tests and nowhere else.
func InstallPrePushHook ¶ added in v0.2.0
InstallPrePushHook writes the hook, refusing to clobber a foreign one — an existing hook without a spectackle reference belongs to the operator.
func IsAheadOf ¶ added in v0.2.0
IsAheadOf reports whether branch carries commits base does not have.
It answers the question a forge asks before accepting a pull request: is there anything here to review? An unknown base (never fetched, or a fresh repository) counts as not-ahead rather than an error — the caller's response either way is to wait rather than to complain.
func IsAheadOfRemote ¶ added in v0.2.0
IsAheadOfRemote is IsAheadOf against the REMOTE-tracking ref for base, falling back to the local ref when there is no remote-tracking one.
This is the question a forge actually answers before accepting a pull request, and the local ref is the wrong oracle for it: in a worktree the local base branch is often stale — the primary checkout owns it and it is not updated by fetching — so a task branch can read as fifty commits ahead of a local base while the forge, comparing against its own current base, sees no commits at all and refuses the pull request. Asking the remote-tracking ref asks what the forge will say.
func MergeInProgress ¶
MergeInProgress reports whether a conflicted merge awaits resolution.
func MergeMain ¶
MergeMain merges the primary checkout's current branch INTO the worktree branch. On conflict the merge is left in progress (resumable) and the conflicted files are returned. The target is resolved, never assumed: a hardcoded "main" silently merged a stale ref in repos developing on a differently named branch, and the submit then died at the fast-forward with a diverging-branches error (B-0004).
func Push ¶ added in v0.2.0
Push pushes branch to remote, setting upstream tracking so HasUnpushedCommits can later read it back. Safe to call on every submit round, not just the first: -u on an already-tracked branch just re-affirms the tracking config, it does not error.
func RemoteURL ¶ added in v0.2.0
RemoteURL returns the configured URL of a named remote.
It exists so the forge client can derive owner and repository from the same remote git itself pushes to, rather than from a second source that could disagree with it — a workspace whose remote was re-pointed must open pull requests against the repository it actually pushes to.
func ShowFile ¶
ShowFile reads a file's content at a ref ("" content for a missing path — the delta baseline for journals that did not exist at branch point).
func TouchedFiles ¶
TouchedFiles lists the files a branch changed relative to a base commit.
Types ¶
This section is empty.