ownership
¶
Full name: tenets.core.examiner.ownership
ownership¶
Code ownership tracking module for examination.
This module analyzes code ownership patterns by examining git history, identifying primary contributors, tracking knowledge distribution, and detecting bus factor risks. It helps understand team dynamics and knowledge silos within a codebase.
The ownership tracker integrates with git to provide insights into who knows what parts of the code and where knowledge gaps might exist.
Classes¶
ContributorInfodataclass
¶
ContributorInfo(name: str, email: str, total_commits: int = 0, total_lines_added: int = 0, total_lines_removed: int = 0, files_touched: Set[str] = set(), files_created: Set[str] = set(), primary_languages: Dict[str, int] = dict(), expertise_areas: List[str] = list(), first_commit_date: Optional[datetime] = None, last_commit_date: Optional[datetime] = None, active_days: int = 0, commit_frequency: float = 0.0, review_participation: int = 0, collaboration_score: float = 0.0, bus_factor_risk: float = 0.0, knowledge_domains: Set[str] = set())
Information about a code contributor.
Tracks detailed statistics and patterns for individual contributors including their areas of expertise, contribution patterns, and impact.
ATTRIBUTE | DESCRIPTION |
---|---|
name | Contributor name TYPE: |
email | Contributor email TYPE: |
total_commits | Total number of commits TYPE: |
total_lines_added | Total lines added TYPE: |
total_lines_removed | Total lines removed TYPE: |
files_touched | Set of files modified |
files_created | Set of files created |
primary_languages | Languages most frequently used |
expertise_areas | Areas of codebase expertise |
first_commit_date | Date of first contribution |
last_commit_date | Date of most recent contribution |
active_days | Number of days with commits TYPE: |
commit_frequency | Average commits per active day TYPE: |
review_participation | Number of reviews participated in TYPE: |
collaboration_score | Score indicating collaboration level TYPE: |
bus_factor_risk | Risk score for bus factor TYPE: |
knowledge_domains | Specific knowledge domains |
Attributes¶
net_lines_contributedproperty
¶
Calculate net lines contributed.
RETURNS | DESCRIPTION |
---|---|
int | Lines added minus lines removed TYPE: |
productivity_scoreproperty
¶
Calculate productivity score.
Combines various metrics to assess productivity.
RETURNS | DESCRIPTION |
---|---|
float | Productivity score (0-100) TYPE: |
FileOwnershipdataclass
¶
FileOwnership(path: str, primary_owner: Optional[str] = None, ownership_percentage: float = 0.0, contributors: List[Tuple[str, int]] = list(), total_changes: int = 0, last_modified: Optional[datetime] = None, last_modified_by: Optional[str] = None, creation_date: Optional[datetime] = None, created_by: Optional[str] = None, complexity: Optional[float] = None, is_orphaned: bool = False, knowledge_concentration: float = 0.0, change_frequency: float = 0.0)
Ownership information for a single file.
Tracks who owns and maintains specific files, including primary owners, contributors, and change patterns.
ATTRIBUTE | DESCRIPTION |
---|---|
path | File path TYPE: |
primary_owner | Main contributor to the file |
ownership_percentage | Primary owner's contribution percentage TYPE: |
contributors | List of all contributors |
total_changes | Total number of changes TYPE: |
last_modified | Last modification date |
last_modified_by | Last person to modify |
creation_date | File creation date |
created_by | Original creator |
complexity | File complexity if available |
is_orphaned | Whether file lacks active maintainer TYPE: |
knowledge_concentration | How concentrated knowledge is TYPE: |
change_frequency | How often file changes TYPE: |
Attributes¶
contributor_countproperty
¶
Get number of unique contributors.
RETURNS | DESCRIPTION |
---|---|
int | Unique contributor count TYPE: |
TeamOwnershipdataclass
¶
TeamOwnership(teams: Dict[str, List[str]] = dict(), team_territories: Dict[str, List[str]] = dict(), cross_team_files: List[str] = list(), collaboration_matrix: Dict[Tuple[str, str], int] = dict(), team_expertise: Dict[str, Set[str]] = dict(), team_bus_factor: Dict[str, int] = dict())
Team-level ownership patterns.
Aggregates ownership information across teams or groups, identifying collaboration patterns and knowledge distribution.
ATTRIBUTE | DESCRIPTION |
---|---|
teams | Dictionary of team members |
team_territories | Areas owned by each team |
cross_team_files | Files touched by multiple teams |
collaboration_matrix | Team collaboration frequencies |
team_expertise | Expertise areas by team |
team_bus_factor | Bus factor by team |
OwnershipReportdataclass
¶
OwnershipReport(total_contributors: int = 0, total_files_analyzed: int = 0, active_contributors: int = 0, contributors: List[ContributorInfo] = list(), file_ownership: Dict[str, FileOwnership] = dict(), orphaned_files: List[str] = list(), high_risk_files: List[Dict[str, Any]] = list(), knowledge_silos: List[Dict[str, Any]] = list(), bus_factor: int = 0, team_ownership: Optional[TeamOwnership] = None, ownership_distribution: Dict[str, float] = dict(), collaboration_graph: Dict[Tuple[str, str], int] = dict(), expertise_map: Dict[str, List[str]] = dict(), recommendations: List[str] = list(), risk_score: float = 0.0)
Comprehensive code ownership analysis report.
Provides detailed insights into code ownership patterns, knowledge distribution, bus factor risks, and team dynamics.
ATTRIBUTE | DESCRIPTION |
---|---|
total_contributors | Total number of contributors TYPE: |
active_contributors | Currently active contributors TYPE: |
contributors | List of contributor information TYPE: |
file_ownership | Ownership by file TYPE: |
orphaned_files | Files without active maintainers |
high_risk_files | Files with bus factor risks |
knowledge_silos | Areas with concentrated knowledge |
bus_factor | Overall project bus factor TYPE: |
team_ownership | Team-level ownership patterns TYPE: |
ownership_distribution | Distribution of ownership |
collaboration_graph | Collaboration relationships |
expertise_map | Map of expertise areas |
recommendations | Actionable recommendations |
risk_score | Overall ownership risk score TYPE: |
Attributes¶
health_scoreproperty
¶
Calculate ownership health score.
Higher scores indicate better knowledge distribution.
RETURNS | DESCRIPTION |
---|---|
float | Health score (0-100) TYPE: |
Functions¶
to_dict¶
Convert report to dictionary.
RETURNS | DESCRIPTION |
---|---|
Dict[str, Any] | Dict[str, Any]: Dictionary representation |
Source code in tenets/core/examiner/ownership.py
def to_dict(self) -> Dict[str, Any]:
"""Convert report to dictionary.
Returns:
Dict[str, Any]: Dictionary representation
"""
data = {
"total_contributors": self.total_contributors,
"total_files_analyzed": self.total_files_analyzed,
"active_contributors": self.active_contributors,
"bus_factor": self.bus_factor,
"orphaned_files": len(self.orphaned_files),
"high_risk_files": len(self.high_risk_files),
"knowledge_silos": len(self.knowledge_silos),
"risk_score": round(self.risk_score, 2),
"top_contributors": [
{
"name": c.name,
"commits": c.total_commits,
"files": len(c.files_touched),
"expertise": c.expertise_level,
}
for c in sorted(self.contributors, key=lambda x: x.total_commits, reverse=True)[:10]
],
"ownership_distribution": self.ownership_distribution,
"recommendations": self.recommendations,
}
# Some tests expect total_files_analyzed when no repo
if not data.get("total_files_analyzed") and hasattr(self, "total_files_analyzed"):
try:
data["total_files_analyzed"] = int(self.total_files_analyzed)
except Exception:
pass
return data
OwnershipTracker¶
Tracker for code ownership patterns.
Analyzes git history to understand code ownership, knowledge distribution, and collaboration patterns within a codebase.
ATTRIBUTE | DESCRIPTION |
---|---|
config | Configuration object |
logger | Logger instance |
git_analyzer | Git analyzer instance TYPE: |
Initialize ownership tracker.
PARAMETER | DESCRIPTION |
---|---|
config | TenetsConfig instance TYPE: |
Source code in tenets/core/examiner/ownership.py
Functions¶
track¶
track(repo_path: Path, since_days: int = 365, include_tests: bool = True, team_mapping: Optional[Dict[str, List[str]]] = None) -> OwnershipReport
Track code ownership for a repository.
Analyzes git history to determine ownership patterns, identify risks, and provide insights into knowledge distribution.
PARAMETER | DESCRIPTION |
---|---|
repo_path | Path to git repository TYPE: |
since_days | Days of history to analyze TYPE: |
include_tests | Whether to include test files TYPE: |
team_mapping | Optional mapping of team names to members |
RETURNS | DESCRIPTION |
---|---|
OwnershipReport | Comprehensive ownership analysis TYPE: |
Example
tracker = OwnershipTracker(config) report = tracker.track(Path("."), since_days=90) print(f"Bus factor: {report.bus_factor}")
Source code in tenets/core/examiner/ownership.py
def track(
self,
repo_path: Path,
since_days: int = 365,
include_tests: bool = True,
team_mapping: Optional[Dict[str, List[str]]] = None,
) -> OwnershipReport:
"""Track code ownership for a repository.
Analyzes git history to determine ownership patterns, identify
risks, and provide insights into knowledge distribution.
Args:
repo_path: Path to git repository
since_days: Days of history to analyze
include_tests: Whether to include test files
team_mapping: Optional mapping of team names to members
Returns:
OwnershipReport: Comprehensive ownership analysis
Example:
>>> tracker = OwnershipTracker(config)
>>> report = tracker.track(Path("."), since_days=90)
>>> print(f"Bus factor: {report.bus_factor}")
"""
self.logger.debug(f"Tracking ownership for {repo_path}")
# Initialize git analyzer
self.git_analyzer = GitAnalyzer(repo_path)
if not self.git_analyzer.is_repo():
self.logger.warning(f"Not a git repository: {repo_path}")
return OwnershipReport()
report = OwnershipReport()
# Analyze contributors
self._analyze_contributors(report, since_days)
# Analyze file ownership
self._analyze_file_ownership(report, include_tests)
# Identify risks
self._identify_ownership_risks(report)
# Analyze team patterns if mapping provided
if team_mapping:
self._analyze_team_ownership(report, team_mapping)
# Calculate collaboration patterns
self._calculate_collaboration_patterns(report)
# Generate expertise map
self._generate_expertise_map(report)
# Calculate overall metrics
self._calculate_overall_metrics(report)
# Generate recommendations
report.recommendations = self._generate_recommendations(report)
self.logger.debug(
f"Ownership tracking complete: {report.total_contributors} contributors, "
f"bus factor: {report.bus_factor}"
)
return report
analyze_ownership¶
Analyze ownership for a repository path.
This is an alias for the track() method to maintain backward compatibility.
PARAMETER | DESCRIPTION |
---|---|
repo_path | Path to repository TYPE: |
**kwargs | Additional arguments passed to track() TYPE: |
RETURNS | DESCRIPTION |
---|---|
OwnershipReport | Comprehensive ownership analysis TYPE: |
Source code in tenets/core/examiner/ownership.py
def analyze_ownership(self, repo_path: Path, **kwargs: Any) -> OwnershipReport:
"""Analyze ownership for a repository path.
This is an alias for the track() method to maintain backward compatibility.
Args:
repo_path: Path to repository
**kwargs: Additional arguments passed to track()
Returns:
OwnershipReport: Comprehensive ownership analysis
"""
return self.track(repo_path, **kwargs)
Functions¶
track_ownership¶
track_ownership(repo_path: Path, since_days: int = 90, include_tests: bool = True, team_mapping: Optional[Dict[str, List[str]]] = None, config: Optional[TenetsConfig] = None) -> OwnershipReport
Track code ownership for a repository path.
A convenient functional API that uses OwnershipTracker under the hood.
PARAMETER | DESCRIPTION |
---|---|
repo_path | Path to repository TYPE: |
since_days | How many days of history to analyze TYPE: |
include_tests | Whether to include test files in analysis TYPE: |
team_mapping | Optional mapping of team names to member emails |
config | Optional TenetsConfig TYPE: |
RETURNS | DESCRIPTION |
---|---|
OwnershipReport | Comprehensive ownership analysis TYPE: |
Source code in tenets/core/examiner/ownership.py
def track_ownership(
repo_path: Path,
since_days: int = 90,
include_tests: bool = True,
team_mapping: Optional[Dict[str, List[str]]] = None,
config: Optional[TenetsConfig] = None,
) -> OwnershipReport:
"""Track code ownership for a repository path.
A convenient functional API that uses OwnershipTracker under the hood.
Args:
repo_path: Path to repository
since_days: How many days of history to analyze
include_tests: Whether to include test files in analysis
team_mapping: Optional mapping of team names to member emails
config: Optional TenetsConfig
Returns:
OwnershipReport: Comprehensive ownership analysis
"""
tracker = OwnershipTracker(config or TenetsConfig())
return tracker.track(
repo_path=repo_path,
since_days=since_days,
include_tests=include_tests,
team_mapping=team_mapping,
)