worktreeend

package
v0.95.1 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package worktreeend closes one task's worktrees: the verb every lane contract already tells an agent to finish with.

It exists because "the agent is done" had no sanctioned expression. An agent that finished either left its checkout for a later sweep — the residue `wb worktree gc` has to clean up — or hand-rolled `git worktree remove`, which loses the claim, the Work Log seal and any uncommitted work in one step. `wb worktree end` is the one verb that does all three correctly.

It owns no new mechanics. Removal is the existing cleanup transaction, the claim release is the existing remote-claim path, and the closing note is the existing Work Log prompt journal. What this package adds is the order, the refusal, and the guarantee that uncommitted work is captured *before* anything is removed.

Implements: dependency-streams#req:sessions-and-tasks-have-explicit-ends, dependency-streams#req:merge-refuses-a-linked-worktree (its end-of-task half).

Index

Constants

View Source
const RefusalLiveLink = "live-link"

RefusalLiveLink is the one condition that stops a task from ending: a worktree still building against an unpublished library working tree.

Variables

This section is empty.

Functions

This section is empty.

Types

type Capture

type Capture interface {
	// DirtyPaths lists uncommitted paths, tracked and untracked.
	DirtyPaths(ctx context.Context, worktree string) ([]string, error)
	// Preserve captures the uncommitted work and returns a reference the
	// operator can recover it from. It must not depend on the worktree
	// surviving: the whole point is that removal follows.
	Preserve(ctx context.Context, worktree, message string) (ref string, err error)
}

Capture preserves uncommitted work before anything is removed.

type Claims

type Claims interface {
	Release(projectsRoot, task string) string
}

Claims releases the task's fleet-wide claim once every worktree is retired.

type Engine

type Engine struct {
	ProjectsRoot string
	Inventory    Inventory
	Links        LinkGuard
	Capture      Capture
	Notes        Notes
	Retirer      Retirer
	Claims       Claims
	Now          func() time.Time
}

Engine performs `wb worktree end` against injected ports.

func (*Engine) End

func (engine *Engine) End(ctx context.Context, options Options) (Result, error)

End closes a task.

The order is the contract:

  1. refuse while any worktree holds a live local link — landing or discarding a checkout that builds against an unpublished working tree is the one thing end must never do silently;
  2. capture uncommitted work and print where it went, BEFORE any removal;
  3. seal the closing note into the Work Log;
  4. retire each worktree through the existing cleanup transaction;
  5. release the fleet-wide claim, but only once every worktree is gone.

A dirty worktree is not a refusal. Refusing one would leave the agent with exactly the choice this verb exists to remove: hand-roll the removal, or leave residue. Capturing first makes retiring it safe.

type Inventory

type Inventory interface {
	Worktrees(ctx context.Context, projectsRoot, task, repository string) ([]Worktree, error)
}

Inventory lists the task's worktrees.

type LinkGuard

type LinkGuard interface {
	// LiveLinks returns a human-readable reason per live link, and the
	// command that clears each. An empty result means the worktree is free
	// to be retired.
	LiveLinks(worktree string) (reasons []string, sanctioned []string, err error)
}

LinkGuard answers whether a worktree still holds a live local link.

type MemberResult

type MemberResult struct {
	Repository string `json:"repository"`
	Worktree   string `json:"worktree"`
	// Dirty lists the uncommitted paths found before anything was removed.
	Dirty []string `json:"dirty,omitempty"`
	// CaptureRef is where the uncommitted work was preserved. It is printed
	// so the operator can recover it; a capture nobody can find is not a
	// capture.
	CaptureRef string `json:"capture_ref,omitempty"`
	NotePath   string `json:"note_path,omitempty"`
	Removed    bool   `json:"removed"`
	Action     string `json:"action"`
	Detail     string `json:"detail,omitempty"`
}

MemberResult is one worktree's retirement.

type Notes

type Notes interface {
	Seal(worktree, note string) (path string, err error)
}

Notes seals the task's closing statement into the Work Log.

type Options

type Options struct {
	Task string
	// Repository narrows a coordinated task to one owner/repository.
	Repository string
	// Note is recorded in the Work Log as the task's closing statement.
	Note string
	// Apply performs the retirement. Without it nothing is changed and the
	// report says exactly what would happen — including which worktrees carry
	// uncommitted work that would be captured.
	Apply bool
	// KeepCapture stops the capture from being taken. It is not a bypass of
	// anything: it is for a caller that has already preserved the work and
	// does not want a second copy.
	KeepCapture bool
}

Options is one `wb worktree end` invocation.

type Refusal

type Refusal struct {
	Code       string
	Message    string
	Sanctioned []string
}

Refusal is a guard that fired, carrying the command that satisfies it.

func (*Refusal) Error

func (refusal *Refusal) Error() string

type Result

type Result struct {
	Task         string         `json:"task"`
	Applied      bool           `json:"applied"`
	Members      []MemberResult `json:"members"`
	ClaimOutcome string         `json:"claim_outcome,omitempty"`
	Errors       []string       `json:"errors,omitempty"`
}

Result is the whole invocation's report.

func (Result) Failed

func (result Result) Failed() bool

Failed reports whether any worktree could not be retired.

type Retirer

type Retirer interface {
	Retire(ctx context.Context, projectsRoot, task, repository, worktree string) error
}

Retirer runs the existing cleanup transaction.

type Worktree

type Worktree struct {
	Repository string
	Path       string
	Branch     string
}

Worktree is one checkout belonging to the task.

Jump to

Keyboard shortcuts

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