Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.0] - 2026-07-22

Ledger → **lens**. repo-cli now *discovers* every worktree across your registered clone roots — whoever created it — instead of only tracking the ones it made itself, and auto-links each branch's live PR.

### Added
- **Discovery engine + provenance** - `repo list` and every worktree-taking verb resolve through a discovery layer that scans all registered roots. Each worktree is tagged with its origin: `repo-cli`, `codex`, `claude`, or `manual` (multi-signal classification; unknown falls back to `manual`, nothing breaks).
- **`repo root add/list/remove`** - Register additional clone roots per repo so discovery spans a bare clone plus any normal checkouts. `root add` canonicalizes any path inside a clone (a subdirectory or one of its linked worktrees) to the clone root discovery actually enumerates, and asks before registering a clone whose `origin` is a different repo than the alias — declining when there is no terminal to ask on. `root remove` refuses to drop a repo's last root (a rootless repo is invisible to the lens and nothing reseeds it) and warns when the removed root was repo-cli's own bare clone. `root list` reports per-root health.
- **Automatic PR linking** - Each branch's best-matching GitHub PR is resolved automatically via batched `gh api graphql` (one call per repo, chunked at 30 branches, concurrent with per-repo failure isolation). 5-minute cache with atomic per-writer writes, self-healing against malformed entries, and offline stale-serve; degrades to `—` when `gh` is unavailable. Results carry their own confidence: `stale` (served past TTL), `truncated` (the branch had more PRs than the page returned), and per-branch "unresolved" are tracked separately from "no PR", so a partial GraphQL response is never read as an answer. Branch-scoped `pr_overrides` win over auto-detection.
- **`repo list` 2.0** - New columns Repo · Branch · Source · PR · Age · Path. PR cell shows the state word (`#123 Open|Merged|Closed|Draft`, dim `(cached)` when stale). New `--source`, `--prs` (incl. `override`/`none`), `--refresh`, and `--json` (stable per-row schema) options. Pure, IO-free render layer.
- **`repo env`** - Run Codex-compatible environment files (`list`/`use`/`up`/`down`/`run`/`actions`/`status`). Scripts run in the worktree with `CODEX_*`/`REPO_*` vars injected; non-zero exits propagate as the CLI exit code. The injected source tree is the checkout that *owns* the worktree (its own root when non-bare, else the repo's first non-bare root, else the worktree itself), so a worktree never reads another root's env files or helpers. Selection persists per-worktree via `git config --worktree` (enabling `extensions.worktreeConfig`, verified safe on bare roots). repo-cli never writes `codex.*` state and never prints env-file contents.
- **`.worktreeinclude` seeding** - `repo create` copies a clone's gitignored `.env`-type files into new worktrees (globs filtered to git-ignored only, nested-worktree matches excluded, `..`-traversal and symlink escapes rejected). `repo env seed` backfills existing worktrees. Seeding fails closed: if the source clone's worktree list cannot be taken, nothing is copied, because a file inside another worktree cannot be excluded without it. Only file names are surfaced; contents are never read for display.
- **`repo clean`** - One reviewed list of (a) non-root worktrees whose PR has merged (or closed, with `--include-closed`), (b) each root's stale worktree records as a single row (`git worktree prune` is root-wide, so the row names every record it clears), and (c) orphaned `claude/*` branches (no worktree in any root, no open PR). Agent rows are opt-in; `--yes` accepts exactly the pre-selected rows; dirty worktrees need `--force`, as do branches whose commits are on no remote ref and whose PR did not merge (a verified merge is the proof the work landed, since squash/rebase merges rewrite SHAs); `--dry-run` mutates nothing. Branch identity is `(root, branch)`. Deletion requires PR evidence established this run: stale-cached, truncated, unresolved, and manually-overridden branches are reported and left alone, fork roots (origin ≠ the alias repo) are excluded, and a repo whose worktree scan was incomplete gets no orphan rows. Config is re-read before saving, so a long run never reverts a concurrent registration.
- **`repo doctor` v2** - Adds a git-version floor (2.31, for `--path-format=absolute` and `extensions.worktreeConfig`), registered-root health (missing / non-git / origin mismatch), worktree drift, PR-cache age, and `gh` auth status.

### Changed
- **Version 2.0.0** - App version and config `version` stamp both track 2.0.0.
- **`repo sync`** - Provenance-gated: rebases only repo-cli-owned worktrees that carry a `start_point` annotation; fetch-only for everything else, so it never rebases agent worktrees.
- **`repo delete`** - Safely refuses agent-owned and root checkouts.
- **`repo unregister`** - Now asks the lens, not just the config: it refuses when discovery finds worktrees under the repo's roots that have no config entry (listing each with its provenance), and when a root could not be scanned at all — an unreadable root cannot be shown to be empty. `--force` still overrides.
- **Worktree annotations** are keyed by resolved path (M2), and PR overrides are branch-scoped in a `pr_overrides` section.

### Deprecated
- **`repo pr link`** - Manual PR linking is rarely needed now that the lens auto-links every branch. It remains only as an override for when auto-detection picks the wrong PR or can't reach GitHub.

### Migrations
- **M1** seeds `repos.*.roots` from the existing bare layout. **M2** re-keys worktree annotations by resolved path and lifts a legacy `pr:` field into `pr_overrides` (coercing a digit-string value rather than dropping it). Both are presence-based, idempotent, chained, and take a timestamped backup before writing — one copy per load, however many migrations run, since they all rewrite the same untouched file. The config version stamps to `2.0.0`, which is also what a fresh `repo init` writes. No manual steps.

### Testing
- Two-tier strategy: fast unit tests with injected seams (subprocess runner, prompt, PR-lookup callable, clock, platform, home) plus real-git integration tests (temp clones, local bare remotes, agent-style worktree fixtures). No live GitHub calls in CI. **743 passing tests**; ruff check + format clean.

## [0.3.0] - 2026-04-29

### Added
Expand Down
Loading
Loading