taskgit

package
v0.35.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package taskgit owns the git plumbing an autonomous run needs, deterministically.

The division of labour is the point: the model decides WHAT should change; this package decides where that happens and how it is recorded. No model output reaches a git command here. Unattended `git` driven by generated text is where autonomous coding goes wrong, and the failure is silent — a wrong branch, a lost commit, a dirty checkout someone else was using.

Milestone 4 covers isolation and revisions. Branch, commit, push and PR are milestone 5 and deliberately absent.

Index

Constants

View Source
const DefaultRemote = "origin"

DefaultRemote is where an autonomous branch is published.

Variables

This section is empty.

Functions

func BaseMoved

func BaseMoved(ctx context.Context, repo, remote, defaultBranch, base string) bool

BaseMoved reports whether the remote default branch has advanced past the commit this run was based on. Informational: drift alone is normal and fine, and only a CONFLICT is a problem.

func BranchName

func BranchName(pattern, taskName, runID string, now time.Time) string

BranchName renders a run's branch from the task's pattern. {name} and {date} are substituted; {run} disambiguates two runs of one task on one day, so a retry never collides with the run it is retrying.

func Commit

func Commit(ctx context.Context, w Worktree, message string) (sha string, created bool, err error)

Commit records the staged work and returns the new commit.

Idempotent: a worktree already advanced past its base with nothing left staged has been committed by a previous attempt, and that commit is returned rather than a second empty one being made.

func CommitMessage

func CommitMessage(p Provenance) string

CommitMessage renders a deterministic commit message. Derived from the task, never from model output: a commit subject generated per-run drifts in style and can carry whatever the model felt like saying, and the one thing this message must do is identify what made the change.

func DefaultBranch

func DefaultBranch(ctx context.Context, repo, remote string) string

DefaultBranch resolves the remote's default branch, falling back through the conventional names. Used to refuse publishing onto it and as the PR base.

func Fetch

func Fetch(ctx context.Context, repo, remote string) error

Fetch updates remote-tracking refs so drift and conflict checks see the current state of the remote rather than a stale local view.

func FindPR

func FindPR(ctx context.Context, dir, branch string) (number int, url string, found bool)

FindPR returns an existing open pull request for a branch.

This is what makes PR creation idempotent. A retry, a restart, or a second attempt inside one run must find the pull request the previous attempt opened instead of opening a duplicate — duplicates are noise a human then has to clean up, and they make the run record ambiguous about which one is real.

func HeadRevision

func HeadRevision(ctx context.Context, dir string) (string, error)

HeadRevision resolves the repository's current commit.

func IsRepo

func IsRepo(ctx context.Context, dir string) bool

IsRepo reports whether dir is inside a git working tree.

func MergeConflicts

func MergeConflicts(ctx context.Context, repo, remote, defaultBranch, head string) (conflicts bool, ok bool)

MergeConflicts reports whether merging head into the remote's default branch would conflict — i.e. whether the base moved under the run in a way that makes the change unmergeable.

It NEVER rebases or rewrites anything. Rewriting history under an unattended run is how work disappears; the honest response to drift is to say so and let a human decide. ok=false means the check could not be made (an old git), and the caller treats that as "no conflict detected" rather than blocking.

func OpenPR

func OpenPR(ctx context.Context, dir, branch, base, title, body string) (number int, url string, created bool, err error)

OpenPR creates a pull request, or returns the one already open for the branch.

func PRBody

func PRBody(p Provenance) string

PRBody renders the pull request body.

Provenance is carried automatically so an autonomous change is auditable from GitHub alone — what made it, which revision of the task, what it was based on, and what was actually verified. Someone reviewing this should not have to open memcode's local database to find out where it came from.

func PRTitle

func PRTitle(p Provenance) string

PRTitle renders the pull request title.

func Prune

func Prune(ctx context.Context, repo string) error

Prune clears worktree registrations whose directories are gone.

func Push

func Push(ctx context.Context, w Worktree, remote, commit string, ownedByRun bool) (created bool, err error)

Push publishes the run's branch. NEW BRANCHES ONLY.

Three refusals, in order of how bad they would be:

  • never the default branch, or the conventional names for it
  • never a remote branch this run did not create
  • never a force update of anything

An existing remote branch whose tip is already our commit is a completed previous attempt, and succeeds without doing anything.

func RemoteBranchExists

func RemoteBranchExists(ctx context.Context, repo, remote, branch string) (bool, error)

RemoteBranchExists reports whether the remote already has this branch.

func RemoteExists

func RemoteExists(ctx context.Context, repo, remote string) bool

RemoteExists reports whether the repository has a remote by this name. A repo with no remote is a normal local repo, not a broken one: a task there commits its work and stops, rather than failing every run over a setup fact.

func Remove

func Remove(ctx context.Context, w Worktree) error

Remove deletes the worktree and its branch.

Called only for runs whose result nobody needs to look at. A failed or needs-attention run KEEPS its worktree: that checkout is the evidence, and deleting it to stay tidy destroys the thing a human is about to ask for.

func Stage

func Stage(ctx context.Context, w Worktree) (bool, error)

Stage adds the run's work to the index. Returns whether anything was staged.

func WorktreeRoot

func WorktreeRoot(repo string) string

WorktreeRoot is where run worktrees live: inside the repo's own .memcode, so they are ignored by git, obviously disposable, and easy to find when a failed run needs inspecting.

Types

type ErrBranchNotOurs

type ErrBranchNotOurs struct{ Branch, Remote string }

ErrBranchNotOurs means the remote branch exists and this run did not create it. Refusing is the whole point: an autonomous push must never land on a branch a human is using, and a name collision is indistinguishable from one.

func (ErrBranchNotOurs) Error

func (e ErrBranchNotOurs) Error() string

type ErrPRUnsupported

type ErrPRUnsupported struct{ Reason string }

ErrPRUnsupported means a pull request cannot be opened HERE — gh is missing, not signed in, or the remote is not a GitHub host.

This is deliberately distinct from a PR that failed to open. The work is already pushed and reachable either way, and a repository that simply is not on GitHub should not make every run of every task report a problem. It is reported plainly on the run instead.

func (ErrPRUnsupported) Error

func (e ErrPRUnsupported) Error() string

type Provenance

type Provenance struct {
	Task         string
	RunID        string
	TaskRevision string
	Base         string
	Occurrence   string
	Verification string
	Description  string
}

Provenance is what an autonomous change must say about itself.

type Publication

type Publication struct {
	Remote        string
	Branch        string
	Commit        string
	PRNumber      int
	PRURL         string
	CreatedBranch bool
	CreatedCommit bool
	CreatedPR     bool
}

Publication is what a run left behind, and who created it. The "created" flags matter for idempotency: reusing something is not the same as making it, and a retry must be able to tell.

type Worktree

type Worktree struct {
	// Path is the checkout the run works in. Never the user's own.
	Path string
	// Branch is the ref created for this run.
	Branch string
	// Base is the commit the worktree was created from, resolved at EXECUTION
	// time. A Monday occurrence recovered on Wednesday builds on Wednesday's
	// HEAD, and recording it is what keeps that honest rather than implying the
	// repository was frozen at the occurrence.
	Base string
	// Repo is the repository the worktree belongs to.
	Repo string
}

Worktree is an isolated checkout a run executes in.

func Create

func Create(ctx context.Context, repo, branch string) (Worktree, error)

Create makes a fresh worktree on a new branch off current HEAD.

A mutating run NEVER executes in the user's active checkout. Isolation is not politeness: an unattended process editing the tree someone is working in can destroy uncommitted work, and a failed run would leave that tree wrecked with no obvious cause.

func (Worktree) Changed

func (w Worktree) Changed(ctx context.Context) (bool, error)

Changed reports whether the run produced anything at all: a new commit, or uncommitted edits. This is a FACT about the repository, not a claim from the agent, and it is what separates a no_change outcome from a success.

func (Worktree) Dirty

func (w Worktree) Dirty(ctx context.Context) (bool, error)

Dirty reports whether the worktree has uncommitted changes, which is how a run that edited files but committed nothing is still recognised as having done something.

func (Worktree) Revision

func (w Worktree) Revision(ctx context.Context) (string, error)

Revision resolves the worktree's current commit — the same as Base when the run committed nothing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL