Skip to content

fix(ownership): configurable strategy-driven branch ownership detection#376

Merged
avihut merged 20 commits intomasterfrom
fix/ownership-detection
Apr 21, 2026
Merged

fix(ownership): configurable strategy-driven branch ownership detection#376
avihut merged 20 commits intomasterfrom
fix/ownership-detection

Conversation

@avihut
Copy link
Copy Markdown
Owner

@avihut avihut commented Apr 21, 2026

Summary

Replaces fragile tip-author-email ownership detection with a configurable strategy-driven resolver over the base..branch commit range.

  • Six strategies configurable via daft.ownership.strategy: tip, any, first, plurality, majority, recency-plurality (new default). The default gently weights recent commits (1/(k+1)) so a branch where you authored most commits is still yours even if a teammate wrote the tip — the original complaint that motivated this.
  • Owner column now shows author name (matching the go completions' behavior) instead of email. Sort keys on (name, email) for stable ordering.
  • JSON owner becomes an object ({name, email} or null). Breaking change — scripts consuming .[].owner as a string need to read .[].owner.email or .[].owner.name.
  • Empty-range fallback chain for fresh branches with no commits yet: base..branchbase..<remote>/<branch> → local reflog creator → blank. Base branches (where branch == base, e.g., master) intentionally skip all fallbacks and render blank, since ownership doesn't apply to shared trunks.

Spec and plan are committed under docs/superpowers/. All six strategies, the fallback chain, and parsing edge cases (tabs in author names, case-insensitive email collapse, nondeterministic tie-breaks) are covered by unit tests in src/core/ownership.rs plus YAML scenarios in tests/manual/scenarios/list/ and tests/manual/scenarios/sync/.

Test plan

  • mise run test:unit — 1062 lib tests pass
  • mise run test:integration — 394 scenarios, 1435 steps, full matrix (default/gitoxide × bash/yaml) green
  • mise run clippy — zero warnings
  • mise run fmt:check — clean
  • mise run ci — full CI simulation green
  • Reviewer: sanity-check that daft list shows author names and base branches (master) show blank Owner
  • Reviewer: confirm daft list --json emits {name, email} objects (breaking change acknowledged)
  • Reviewer: try git config daft.ownership.strategy tip (or other values) and verify the Owner column changes accordingly

🤖 Generated with Claude Code

avihut and others added 20 commits April 21, 2026 10:17
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire ownership::fetch_commit_records + resolve_owner_from_records into
collect_worktree_info and collect_branch_info, adding the owner: Option<BranchOwner>
field alongside the existing owner_email during the transitional period.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
During the ownership transition, prune.rs was deriving owner_email from
the resolved owner instead of tip-author like the collect_* paths. This
caused inconsistent behavior for gone-branch stubs versus other entries.
Align by using list::get_author_email_for_ref() to maintain consistent
semantics until the legacy owner_email field is removed in Task 11.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SortColumn::Owner now compares owners by name (case-insensitive), with ties
broken by email. Updated the test helper to populate the `owner` field
instead of `owner_email`, and updated test assertions accordingly.

The `owner_email` field is retained for now; it will be removed in Task 11.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… plumbing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delete the `owner_email` field from `WorktreeInfo`, the
`get_author_email_for_ref` helper, and all call sites. Every consumer
now reads the `owner: Option<BranchOwner>` field populated by the new
ownership strategy instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update daft-list, daft-sync, configuration, and SKILL.md to reflect
strategy-based ownership: Owner column shows author name (not email),
JSON owner field is {name,email}|null, and daft.ownership.strategy
config key is documented with all six strategies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…se..branch is empty

When `base..branch` yields no commits (e.g. freshly-created branches,
branches merged into base), resolve owner via two fallbacks in order:
1. `base..<remote>/<branch>` — remote-tracking range.
2. Local reflog oldest entry — the committer identity that ran
   `git checkout -b` / `git worktree add -b` for this branch.

Skips all fallbacks when `branch == base` (default branch) to avoid
crediting the repo cloner as the default branch's owner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@avihut avihut added this to the Public Launch milestone Apr 21, 2026
@avihut avihut added the fix Bug fix label Apr 21, 2026
@avihut avihut self-assigned this Apr 21, 2026
@avihut avihut merged commit 96a4ed6 into master Apr 21, 2026
8 checks passed
@avihut avihut deleted the fix/ownership-detection branch April 21, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant