Documentation
¶
Overview ¶
Package trunk reads entity ids visible in git refs for the allocator's cross-branch view. Its primary surface, Read, scans the configured trunk ref's tree, applying the policy from id-allocation.md:
Not a git repository at all → skip. Tooling that legitimately runs outside a repo (test fixtures, exploratory invocations on plain directories) has no cross-branch surface to police.
Configured trunk ref resolves → return the (kind, id, path) triples found under work/ and docs/adr/ in that ref's tree.
Trunk ref missing AND was explicitly set in aiwf.yaml → hard error. The user named a specific ref; if it doesn't exist they should fix the typo or fetch it. Silent degradation would defeat their explicit intent.
Trunk ref missing AND was the default (no allocate.trunk in aiwf.yaml) AND no refs/remotes/* tracking refs exist → skip. Covers "no remote configured" (sandbox repos), "remote configured but never fetched" (transient setup), and "freshly cloned an empty bare" (canonical first-push setup, where the bare has no branches so the clone has none either). None has anything to collide with.
Trunk ref missing AND was the default AND tracking refs DO exist → hard error. The remote has been populated; an unresolvable default trunk is a real misconfiguration (the team's trunk is named something other than main, or the consumer hasn't fetched it). Setting allocate.trunk in aiwf.yaml fixes it.
LocalRefIDs is the second surface: it widens that view to every local branch ref (refs/heads/*) for the allocator only — never the ids-unique check — so a sibling worktree's freshly-committed id is seen at allocation time (M-0212).
LocalRefHits/RemoteRefHits and detectCollisions (M-0259) widen this further into a second consumer beyond the allocator: the per-id path/ref view they carry, plus blob-content comparison across refs, feed the check layer's cross-branch-pending/cross-branch-collision classification (ADR-0030) — so the package's scope is no longer "for the allocator" alone, but every read-only consumer of "what ids are visible where, across every locally-knowable ref."
The package is read-only and has no per-process cache; callers invoke once per verb run.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DistinctRefs ¶ added in v0.27.0
DistinctRefs returns the distinct ref names carried by hits, in first-seen order — the candidate-ref list a caller surfaces when hits disagree (M-0259/AC-3's cross-branch-collision finding, M-0260/AC-3's aiwf show/list refusal to arbitrate between them).
func HitIDStrings ¶ added in v0.27.0
HitIDStrings returns just the id strings from hits, in order. Convenience for LocalRefIDs/RemoteRefIDs, which only need id values.
func LocalRefIDs ¶ added in v0.20.0
LocalRefIDs returns the entity id strings reachable from every local branch ref (refs/heads/*) in workdir's repository. It is the allocator's broadened cross-branch view (M-0212): a sibling git worktree's freshly-committed entity already lives in the shared local refs, so unioning these ids into the allocator's max keeps the next allocation from colliding with it (G-0272 class 1).
Best-effort and read-only: it never returns an error. On any odd repo state — not a git repository, no local branches, or a ref that lists but fails to read — it degrades to the ids it could collect (down to none), never blocking or failing the caller's allocation (M-0212/AC-2). The scan narrows the collision window; it is not a correctness gate, and the irreducible cross-machine race stays `aiwf reallocate`'s to cure.
Unlike Read, the result feeds the allocator ONLY — never the ids-unique trunk-collision check, which keeps its working-tree-vs- trunk basis. Folding every sibling branch into the uniqueness comparison would false-flag the same entity present on two branches (e.g. a feature branch forked from main); E-0052's decision is to take only the prevention half here.
Cost is one `git ls-tree` per local branch — O(local branches) subprocesses per call. Trivial at the solo / handful-of-branches scale this targets; it grows linearly, so a repo carrying hundreds of stale local branches would pay for them on every allocation.
Derived from LocalRefHits (M-0259/AC-1) by dropping path/ref — additive widening only, this function's shape and behavior are unchanged from before AC-1.
func RemoteRefIDs ¶ added in v0.20.0
RemoteRefIDs returns the entity id strings reachable from every remote-tracking ref (refs/remotes/*) in workdir's repository — the remote-side mirror of LocalRefIDs (M-0214). An entity pushed to any remote branch (a teammate's not-yet-merged work, a CI checkout) is visible in the local remote-tracking refs, so unioning these ids into the allocator's max keeps the next allocation from colliding with it (G-0316).
Same best-effort, allocation-only contract as LocalRefIDs: it never returns an error, degrades to nil on odd repo states, and feeds the allocator ONLY — never the ids-unique check, which keeps its working-tree-vs-trunk basis.
Derived from RemoteRefHits (M-0259/AC-1) by dropping path/ref — additive widening only.
Types ¶
type CrossBranchScan ¶ added in v0.27.0
type CrossBranchScan struct {
// LocalHits is every entity-id hit on a local branch ref
// (refs/heads/*) — the allocator's LocalRefIDs view (M-0212).
LocalHits []RefHit
// RemoteHits is every hit on a remote-tracking ref (refs/remotes/*)
// — the allocator's RemoteRefIDs view (M-0214).
RemoteHits []RefHit
// Hits is LocalHits followed by RemoteHits: the cross-branch union
// the read-side resolver (crossBranchIndex / show / list) groups by
// id on a local-tree miss (ADR-0030).
Hits []RefHit
// Collisions is the canonicalized-id set whose hits carry divergent
// blob content across refs (detectCollisions, G-0415), consulted on
// a local-tree miss to escalate cross-branch-pending to
// cross-branch-collision (D-0036). Domain bound: only ids ABSENT from
// the local tree (per ScanCrossBranch's presentLocally) can appear
// here — a locally-present diverging id is deliberately omitted by the
// lazy filter, so a bare Collisions[id] lookup returns false even for
// a genuinely diverging present id. Read it only after a local-tree
// miss (as every consumer does).
Collisions map[string]bool
}
CrossBranchScan is the outcome of one cross-branch ref scan: the per-ref-class hit slices the allocator's id view needs (LocalHits / RemoteHits), their union (Hits — the cross-branch read-side index), and the divergent-content id set among them (Collisions). Composed once by ScanCrossBranch so no consumer re-derives the union or re-runs detectCollisions (E-0067, G-0418).
func ScanCrossBranch ¶ added in v0.27.0
func ScanCrossBranch(ctx context.Context, workdir string, presentLocally func(canonicalID string) bool) CrossBranchScan
ScanCrossBranch composes the local + remote ref-hit union once and detects content collisions among them, returning both the union (for the cross-branch read-side index) and its per-ref-class halves (for the allocator's id view). It is the single composition point for the cross-branch scan E-0060 shipped copied across three call sites (cliutil.LoadTreeWithTrunk, list.crossBranchListRows, show.buildCrossBranchShowView); consolidating it here keeps the "hits scanned equal the hits handed to detectCollisions" coupling in one place (G-0418).
Collision detection is lazy: only hits whose id is absent from the local tree (presentLocally reports false) are handed to detectCollisions, so the O(entities×refs) blob-stat pass shrinks to the locally-absent id set — nothing in the common all-merged state, where every id resolves locally. This is behavior-preserving because every consumer reads a collision result only after a local-tree miss (ADR-0030): a locally-present id's collision entry is never observed, so declining to compute it changes no output. A nil presentLocally disables the filter (every id treated as absent, collisions computed over the full union) — nil-safety for absentHits, not a mode any production caller uses; all three callers pass a real predicate.
Best-effort and read-only, inheriting LocalRefHits/RemoteRefHits/ detectCollisions' contract: it never errors, degrading to empty slices and an empty collision map on odd repo state.
type ID ¶
ID names one entity that exists in the trunk ref's tree, by kind, id string, and the repo-relative path the trunk has it at.
type RefHit ¶ added in v0.27.0
RefHit names one entity id visible on a specific local or remote-tracking git ref (M-0259/AC-1): the same (kind, id, path) triple as trunk.ID, tagged with the originating ref name. Widens LocalRefIDs/RemoteRefIDs' bare-id view so a consumer beyond the allocator (the check-side cross-branch-pending tier, the read-side show/list resolver) can tell WHICH ref and path a hit came from, not just that the id exists somewhere.
func LocalRefHits ¶ added in v0.27.0
LocalRefHits is LocalRefIDs' widened form (M-0259/AC-1): every hit on every local branch ref, carrying kind/path/ref alongside the id. Same best-effort, read-only, allocation-plus-check-consumer contract as LocalRefIDs — never errors, degrades to nil on odd repo states.
type Result ¶
Result carries the trunk ids visible to the allocator and the cross-tree check. Skipped is true when the repo has no remotes and the trunk read was deliberately bypassed.