branch_inventory — AgentTeamsModule¶
Read-only branch inventory and deletion plan. It is the classifier behind
--branch-inventory, and the executable form of the
emitted references/branch-lifecycle.reference.md.
Source:
agentteams/branch_inventory.py(integrity-pinned)
Why it exists. baseAgent's 2026-10-04 audit found 66 of 67 branch refs already merged, with no
layer of the generated team ever deleting one (references/branch-lifecycle-policy.handoff.md).
The handoff's ancestry-only rule fits local --no-ff merges. On a squash-merging repository
(agentteams itself) it misclassifies nearly every merged branch: a squash rewrites the commits,
and git cherry only recognizes a squash of a single-commit branch. This module therefore adds
the Merged-by-PR state, verified through the GitHub API.
Public API¶
| Name | Purpose |
|---|---|
InventoryConfig |
Inputs: repo, push_remote, default_branch, stale_days, release_pattern, maintained_patterns, operator_emails, use_api, fetch, cite_exclude, now |
build_inventory(cfg, *, api=None, api_factory=None) -> dict |
{"meta", "refs", "plan"}. Runs only git fetch --prune and read commands; never writes a ref |
deletion_plan(meta, refs) -> dict |
Plan items, each with run and restore commands, plus sha256 over its binding fields |
plan_digest(plan) -> str |
Recomputes the sha256 used to detect an edited plan and to bind a clearance |
item_commands(item, remote) -> dict |
The exact leased commands, and the restore commands, for one item |
write_reports(inventory, out_dir) -> list[Path] |
Writes branch-inventory.csv, branch-inventory.json and branch-deletion-plan.json |
summary_line(inventory) -> str |
The Output Contract value (clean or N merged-undeleted \| …) |
GitHubAPI(repo) |
Read-only REST client. It uses GH_TOKEN/GITHUB_TOKEN over urllib, otherwise the gh CLI. get returns ok, notfound or unknown |
github_repo_of(url) |
owner/name for a github.com remote, else None |
STATES, CSV_COLUMNS |
The ten states in evaluation order, and the CSV column order |
State model¶
States are evaluated in order, and the first match wins:
1. default
2. protected (API)
3. evergreen: a workflow branch:/branch= name. A templated name becomes a prefix pattern;
a name that is variable from its first character is ignored.
4. release-maintained
5. release-finished
6. merged: an ancestor that owns at least one commit off the default branch's first-parent
history. The owned commits are found by binary search for the merge point. An ancestor that
owns none and is idle beyond N days is also merged (a fast-forward or abandoned empty
branch).
7. merged-by-pr: the PR's head repository is the push remote's, its base is the default
branch, it is merged, head.sha equals the tip, and its merge commit is reachable from the
default branch.
8. patch-equivalent
9. active: last activity within N days. Activity is the tip's commit date or, for local
refs, the reflog entry time.
10. stale-unmerged
Holds keep a branch whatever its state (holds column):
- owner:<emails>
- link
- open-pr:head, open-pr:base
- worktree, worktree:prunable
- pinned
- pr-lookup-unknown
- api-unknown: blocks every remote deletion when open PRs or protection could not be checked
- pr-ref-missing
Actions: keep, delete, tag-then-delete, or ask-operator (patch-equivalent and
stale-unmerged).