1039 lines
30 KiB
Markdown
1039 lines
30 KiB
Markdown
# MarketAlly.GitCommitEditor API Reference
|
|
|
|
Complete API documentation for developers and AI assistants.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
- [Services](#services)
|
|
- [IGitMessageImproverService](#igitmessageimproverservice)
|
|
- [IRepositoryManager](#irepositorymanager)
|
|
- [ICommitAnalysisService](#icommitanalysisservice)
|
|
- [ISuggestionService](#isuggestionservice)
|
|
- [ICommitRewriteService](#icommitrewriteservice)
|
|
- [IGitPushService](#igitpushservice)
|
|
- [IHistoryHealthService](#ihistoryhealthservice)
|
|
- [ICommitMessageAnalyzer](#icommitmessageanalyzer)
|
|
- [ICleanupExecutor](#icleanupexecutor)
|
|
- [Models](#models)
|
|
- [ManagedRepo](#managedrepo)
|
|
- [CommitAnalysis](#commitanalysis)
|
|
- [MessageQualityScore](#messagequalityscore)
|
|
- [QualityIssue](#qualityissue)
|
|
- [CommitContext](#commitcontext)
|
|
- [RewriteOperation](#rewriteoperation)
|
|
- [RewriteSafetyInfo](#rewritesafetyinfo)
|
|
- [BatchResult](#batchresult)
|
|
- [BatchRewriteResult](#batchrewriteresult)
|
|
- [BranchInfo](#branchinfo)
|
|
- [Result Types](#result-types)
|
|
- [History Health Models](#history-health-models)
|
|
- [HistoryHealthReport](#historyhealthreport)
|
|
- [HealthScore](#healthscore)
|
|
- [HealthIssue](#healthissue)
|
|
- [CleanupOperation](#cleanupoperation)
|
|
- [CleanupSuggestions](#cleanupsuggestions)
|
|
- [Options](#options)
|
|
- [GitImproverOptions](#gitimproveroptions)
|
|
- [CommitMessageRules](#commitmessagerules)
|
|
- [AiOptions](#aioptions)
|
|
- [HistoryAnalysisOptions](#historyanalysisoptions)
|
|
- [CleanupExecutionOptions](#cleanupexecutionoptions)
|
|
- [Enumerations](#enumerations)
|
|
- [Extensions](#extensions)
|
|
- [Usage Patterns](#usage-patterns)
|
|
- [Error Handling](#error-handling)
|
|
|
|
---
|
|
|
|
## Services
|
|
|
|
### IGitMessageImproverService
|
|
|
|
The main facade interface that composes all functionality. This is the primary entry point for most use cases.
|
|
|
|
**Implements:** `IRepositoryManager`, `ICommitAnalysisService`, `ISuggestionService`, `ICommitRewriteService`, `IGitPushService`, `IHistoryHealthService`, `IDisposable`
|
|
|
|
```csharp
|
|
public interface IGitMessageImproverService : IDisposable
|
|
{
|
|
// State Management
|
|
Task LoadStateAsync(CancellationToken ct = default);
|
|
string GenerateSummaryReport();
|
|
|
|
// All methods from composed interfaces (see below)
|
|
}
|
|
```
|
|
|
|
#### Factory Method
|
|
|
|
```csharp
|
|
// Create service without DI container
|
|
public static Task<GitMessageImproverService> CreateAsync(GitImproverOptions options);
|
|
```
|
|
|
|
#### Additional Methods on Implementation
|
|
|
|
```csharp
|
|
// Branch management
|
|
Task<bool> CheckoutBranchAsync(ManagedRepo repo, string branchName);
|
|
IEnumerable<BackupBranchInfo> GetBackupBranches(string repoPath);
|
|
bool DeleteBranch(string repoPath, string branchName);
|
|
int DeleteAllBackupBranches(string repoPath);
|
|
|
|
// Safety checks
|
|
RewriteSafetyInfo GetRewriteSafetyInfo(string repoPath, IEnumerable<CommitAnalysis> commits);
|
|
|
|
// Batch rewrite with safety
|
|
Task<BatchRewriteResult> ExecuteBatchRewriteAsync(
|
|
string repoPath,
|
|
IEnumerable<CommitAnalysis> commits,
|
|
bool createBackup = true,
|
|
IProgress<(int Current, int Total, string CommitHash)>? progress = null,
|
|
CancellationToken ct = default);
|
|
```
|
|
|
|
---
|
|
|
|
### IRepositoryManager
|
|
|
|
Manages git repository discovery and registration.
|
|
|
|
```csharp
|
|
public interface IRepositoryManager
|
|
{
|
|
/// <summary>Gets all registered repositories.</summary>
|
|
IReadOnlyList<ManagedRepo> Repos { get; }
|
|
|
|
/// <summary>Scans WorkspaceRoot for git repos and registers new ones.</summary>
|
|
Task<IReadOnlyList<ManagedRepo>> ScanAndRegisterReposAsync(CancellationToken ct = default);
|
|
|
|
/// <summary>Manually register a repository by path.</summary>
|
|
Task<ManagedRepo> RegisterRepoAsync(string repoPath);
|
|
|
|
/// <summary>Unregister a repository by ID or path.</summary>
|
|
Task<bool> UnregisterRepoAsync(string repoIdOrPath);
|
|
|
|
/// <summary>Get all branches (local and remote) for a repository.</summary>
|
|
IEnumerable<BranchInfo> GetBranches(string repoPath);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### ICommitAnalysisService
|
|
|
|
Provides commit message quality analysis.
|
|
|
|
```csharp
|
|
public interface ICommitAnalysisService
|
|
{
|
|
/// <summary>Analyze commits across all registered repositories.</summary>
|
|
/// <param name="onlyNeedsImprovement">If true, only return commits with quality issues.</param>
|
|
/// <param name="progress">Reports (RepoName, CommitCount) as repos are processed.</param>
|
|
Task<IReadOnlyList<CommitAnalysis>> AnalyzeAllReposAsync(
|
|
bool onlyNeedsImprovement = true,
|
|
IProgress<(string Repo, int Processed)>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Analyze commits in a single repository.</summary>
|
|
IEnumerable<CommitAnalysis> AnalyzeRepo(ManagedRepo repo);
|
|
|
|
/// <summary>Analyze a specific commit by hash.</summary>
|
|
CommitAnalysis AnalyzeCommit(string repoPath, string commitHash);
|
|
|
|
/// <summary>Update and persist repo analysis statistics.</summary>
|
|
Task UpdateRepoAnalysisAsync(
|
|
ManagedRepo repo,
|
|
int totalCommits,
|
|
int commitsNeedingImprovement,
|
|
CancellationToken ct = default);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### ISuggestionService
|
|
|
|
Generates AI-powered commit message suggestions.
|
|
|
|
```csharp
|
|
public interface ISuggestionService
|
|
{
|
|
/// <summary>Generate AI suggestions for multiple commits.</summary>
|
|
/// <returns>Result with success/failure counts and individual failures.</returns>
|
|
Task<BatchSuggestionResult> GenerateSuggestionsAsync(
|
|
IEnumerable<CommitAnalysis> analyses,
|
|
IProgress<int>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Generate AI suggestion for a single commit.</summary>
|
|
Task<SuggestionResult> GenerateSuggestionAsync(
|
|
CommitAnalysis analysis,
|
|
CancellationToken ct = default);
|
|
}
|
|
```
|
|
|
|
**Throws:** `ApiKeyNotConfiguredException` if AI provider API key is not set.
|
|
|
|
---
|
|
|
|
### ICommitRewriteService
|
|
|
|
Handles commit message rewriting operations.
|
|
|
|
```csharp
|
|
public interface ICommitRewriteService
|
|
{
|
|
/// <summary>History of all rewrite operations.</summary>
|
|
IReadOnlyList<RewriteOperation> History { get; }
|
|
|
|
/// <summary>Create RewriteOperation objects for commits with suggestions.</summary>
|
|
IReadOnlyList<RewriteOperation> PreviewChanges(IEnumerable<CommitAnalysis> analyses);
|
|
|
|
/// <summary>Apply commit message changes.</summary>
|
|
/// <param name="dryRun">If true, validate but don't modify commits.</param>
|
|
Task<BatchResult> ApplyChangesAsync(
|
|
IEnumerable<RewriteOperation> operations,
|
|
bool dryRun = true,
|
|
IProgress<(int Processed, int Total)>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Apply suggested message for a single commit.</summary>
|
|
Task<RewriteOperation> ApplyChangeAsync(
|
|
CommitAnalysis analysis,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Undo a commit amend by resetting to original commit.</summary>
|
|
bool UndoCommitAmend(string repoPath, string originalCommitHash);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### IGitPushService
|
|
|
|
Handles git push operations and remote tracking.
|
|
|
|
```csharp
|
|
public interface IGitPushService
|
|
{
|
|
/// <summary>Check if a commit exists on the remote tracking branch.</summary>
|
|
bool IsCommitPushed(string repoPath, string commitHash);
|
|
|
|
/// <summary>Get tracking information for current branch.</summary>
|
|
TrackingInfo GetTrackingInfo(string repoPath);
|
|
|
|
/// <summary>Push current branch to remote.</summary>
|
|
GitPushResult Push(string repoPath);
|
|
|
|
/// <summary>Force push current branch to remote (overwrites remote history).</summary>
|
|
GitPushResult ForcePush(string repoPath);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### IHistoryHealthService
|
|
|
|
Service for analyzing and reporting on git repository history health.
|
|
|
|
```csharp
|
|
public interface IHistoryHealthService
|
|
{
|
|
/// <summary>Analyzes repository history health and generates a comprehensive report.</summary>
|
|
Task<HistoryHealthReport> AnalyzeHistoryHealthAsync(
|
|
string repoPath,
|
|
HistoryAnalysisOptions? options = null,
|
|
IProgress<AnalysisProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Analyzes history health for a managed repository.</summary>
|
|
Task<HistoryHealthReport> AnalyzeHistoryHealthAsync(
|
|
ManagedRepo repo,
|
|
HistoryAnalysisOptions? options = null,
|
|
IProgress<AnalysisProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Exports a health report to the specified format (Json, Markdown, Html, Console).</summary>
|
|
Task<string> ExportHealthReportAsync(
|
|
HistoryHealthReport report,
|
|
ReportFormat format,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Exports a health report to a file.</summary>
|
|
Task ExportHealthReportToFileAsync(
|
|
HistoryHealthReport report,
|
|
ReportFormat format,
|
|
string outputPath,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Executes a single cleanup operation.</summary>
|
|
Task<CleanupExecutionResult> ExecuteCleanupAsync(
|
|
ManagedRepo repo,
|
|
CleanupOperation operation,
|
|
CleanupExecutionOptions? options = null,
|
|
IProgress<CleanupProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Executes all cleanup operations from suggestions.</summary>
|
|
Task<BatchCleanupResult> ExecuteAllCleanupsAsync(
|
|
ManagedRepo repo,
|
|
CleanupSuggestions suggestions,
|
|
CleanupExecutionOptions? options = null,
|
|
IProgress<CleanupProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Creates a backup branch before cleanup operations.</summary>
|
|
Task<string> CreateBackupBranchAsync(
|
|
ManagedRepo repo,
|
|
string? branchName = null,
|
|
CancellationToken ct = default);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### ICommitMessageAnalyzer
|
|
|
|
Analyzes commit message quality against configured rules.
|
|
|
|
```csharp
|
|
public interface ICommitMessageAnalyzer
|
|
{
|
|
/// <summary>Analyze message without change context.</summary>
|
|
MessageQualityScore Analyze(string message);
|
|
|
|
/// <summary>Analyze message with context about actual changes.</summary>
|
|
/// <remarks>Enables detection of vague messages for significant changes.</remarks>
|
|
MessageQualityScore Analyze(string message, CommitContext context);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### ICleanupExecutor
|
|
|
|
Executes cleanup operations on git repositories.
|
|
|
|
```csharp
|
|
public interface ICleanupExecutor
|
|
{
|
|
/// <summary>Executes a single cleanup operation.</summary>
|
|
Task<CleanupExecutionResult> ExecuteAsync(
|
|
ManagedRepo repo,
|
|
CleanupOperation operation,
|
|
CleanupExecutionOptions? options = null,
|
|
IProgress<CleanupProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Executes multiple cleanup operations in sequence.</summary>
|
|
Task<BatchCleanupResult> ExecuteBatchAsync(
|
|
ManagedRepo repo,
|
|
IEnumerable<CleanupOperation> operations,
|
|
CleanupExecutionOptions? options = null,
|
|
IProgress<CleanupProgress>? progress = null,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Previews what a cleanup operation will do without executing it.</summary>
|
|
Task<CleanupPreview> PreviewAsync(
|
|
ManagedRepo repo,
|
|
CleanupOperation operation,
|
|
CancellationToken ct = default);
|
|
|
|
/// <summary>Creates a backup branch before cleanup operations.</summary>
|
|
Task<string> CreateBackupBranchAsync(
|
|
ManagedRepo repo,
|
|
string? branchName = null,
|
|
CancellationToken ct = default);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Models
|
|
|
|
### ManagedRepo
|
|
|
|
Represents a registered git repository.
|
|
|
|
```csharp
|
|
public sealed class ManagedRepo
|
|
{
|
|
public string Id { get; } // GUID
|
|
public string Name { get; set; } // Directory name
|
|
public string Path { get; set; } // Full path
|
|
public string? RemoteUrl { get; set; } // Origin URL
|
|
public string? CurrentBranch { get; set; }
|
|
public DateTimeOffset? LastScannedAt { get; set; }
|
|
public DateTimeOffset? LastAnalyzedAt { get; set; }
|
|
public int TotalCommits { get; set; }
|
|
public int CommitsNeedingImprovement { get; set; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### CommitAnalysis
|
|
|
|
Complete analysis of a single commit.
|
|
|
|
```csharp
|
|
public sealed class CommitAnalysis
|
|
{
|
|
public string RepoId { get; }
|
|
public string RepoName { get; }
|
|
public string RepoPath { get; }
|
|
public string CommitHash { get; }
|
|
public string ShortHash { get; } // First 7 characters
|
|
public string OriginalMessage { get; }
|
|
public string? SuggestedMessage { get; set; } // Populated by AI
|
|
public DateTimeOffset CommitDate { get; }
|
|
public string Author { get; }
|
|
public string AuthorEmail { get; }
|
|
public MessageQualityScore Quality { get; }
|
|
public IReadOnlyList<string> FilesChanged { get; }
|
|
public string? DiffSummary { get; }
|
|
public IReadOnlyDictionary<string, string> FileDiffs { get; } // Path -> Diff
|
|
public int LinesAdded { get; }
|
|
public int LinesDeleted { get; }
|
|
public bool IsLatestCommit { get; }
|
|
public AnalysisStatus Status { get; set; } // Pending, Analyzed, Applied, Failed, Skipped
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### MessageQualityScore
|
|
|
|
Quality assessment with detailed issues.
|
|
|
|
```csharp
|
|
public sealed class MessageQualityScore
|
|
{
|
|
public int OverallScore { get; } // 0-100
|
|
public IReadOnlyList<QualityIssue> Issues { get; }
|
|
public bool NeedsImprovement { get; } // Score < 70 or has Error severity
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### QualityIssue
|
|
|
|
Individual quality problem found in a message.
|
|
|
|
```csharp
|
|
public sealed class QualityIssue
|
|
{
|
|
public required string Code { get; init; } // e.g., "SUBJECT_TOO_SHORT"
|
|
public required string Message { get; init; } // Human-readable description
|
|
public required IssueSeverity Severity { get; init; }
|
|
public int ScoreImpact { get; init; } // Points deducted
|
|
}
|
|
```
|
|
|
|
**Issue Codes:**
|
|
- `SUBJECT_TOO_SHORT` - Subject line below minimum length
|
|
- `SUBJECT_TOO_LONG` - Subject line exceeds maximum length
|
|
- `BODY_TOO_SHORT` - Body below minimum length (if required)
|
|
- `MISSING_CONVENTIONAL_TYPE` - Missing conventional commit type prefix
|
|
- `BANNED_PHRASE` - Contains banned/vague phrase
|
|
- `MISSING_ISSUE_REFERENCE` - Missing issue/ticket reference (if required)
|
|
- `VAGUE_FOR_CHANGES` - Message too vague for significant code changes
|
|
|
|
---
|
|
|
|
### CommitContext
|
|
|
|
Context about commit changes for smarter analysis.
|
|
|
|
```csharp
|
|
public sealed class CommitContext
|
|
{
|
|
public int FilesChanged { get; init; }
|
|
public int LinesAdded { get; init; }
|
|
public int LinesDeleted { get; init; }
|
|
public IReadOnlyList<string> FileNames { get; init; }
|
|
|
|
public int TotalLinesChanged { get; } // Added + Deleted
|
|
public bool HasSignificantChanges { get; } // Files > 0 or Lines > 0
|
|
|
|
public static CommitContext Empty { get; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### RewriteOperation
|
|
|
|
Represents a commit rewrite operation.
|
|
|
|
```csharp
|
|
public sealed class RewriteOperation
|
|
{
|
|
public string Id { get; } // GUID
|
|
public string RepoId { get; set; }
|
|
public string RepoPath { get; set; }
|
|
public string CommitHash { get; set; }
|
|
public string? NewCommitHash { get; set; } // After rewrite
|
|
public string OriginalMessage { get; set; }
|
|
public string NewMessage { get; set; }
|
|
public bool IsLatestCommit { get; set; }
|
|
public OperationStatus Status { get; set; } // Pending, Applied, Failed, Undone
|
|
public string? ErrorMessage { get; set; }
|
|
public DateTimeOffset CreatedAt { get; }
|
|
public DateTimeOffset? AppliedAt { get; set; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### RewriteSafetyInfo
|
|
|
|
Safety information for batch rewrite operations.
|
|
|
|
```csharp
|
|
public sealed class RewriteSafetyInfo
|
|
{
|
|
public bool HasUncommittedChanges { get; init; }
|
|
public bool HasPushedCommits { get; init; }
|
|
public int PushedCommitCount { get; init; }
|
|
public int LocalOnlyCommitCount { get; init; }
|
|
public int TotalCommitCount { get; init; }
|
|
public bool HasRemoteTracking { get; init; }
|
|
public string? RemoteTrackingBranch { get; init; }
|
|
public int? AheadOfRemote { get; init; }
|
|
public int? BehindRemote { get; init; }
|
|
public bool BackupBranchCreated { get; init; }
|
|
public string? BackupBranchName { get; init; }
|
|
|
|
// Computed properties
|
|
public bool CanProceedSafely { get; } // !HasUncommittedChanges && !HasPushedCommits
|
|
public bool CanProceedWithWarnings { get; } // !HasUncommittedChanges
|
|
|
|
// Methods
|
|
public IReadOnlyList<string> GetWarnings();
|
|
public string GetSummary();
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### BatchResult
|
|
|
|
Result of batch operations (ApplyChangesAsync).
|
|
|
|
```csharp
|
|
public sealed class BatchResult
|
|
{
|
|
public int TotalProcessed { get; init; }
|
|
public int Successful { get; init; }
|
|
public int Failed { get; init; }
|
|
public int Skipped { get; init; }
|
|
public IReadOnlyList<RewriteOperation> Operations { get; init; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### BatchRewriteResult
|
|
|
|
Result of ExecuteBatchRewriteAsync.
|
|
|
|
```csharp
|
|
public sealed class BatchRewriteResult
|
|
{
|
|
public bool Success { get; init; }
|
|
public int SuccessCount { get; init; }
|
|
public int FailedCount { get; init; }
|
|
public int SkippedCount { get; init; }
|
|
public string? ErrorMessage { get; init; }
|
|
public bool RequiresForcePush { get; init; }
|
|
public string? BackupBranchName { get; init; }
|
|
public IReadOnlyList<RewriteOperation> Operations { get; init; }
|
|
|
|
public static BatchRewriteResult Failure(string error);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### BranchInfo
|
|
|
|
Information about a git branch.
|
|
|
|
```csharp
|
|
public sealed class BranchInfo
|
|
{
|
|
public string Name { get; init; } // e.g., "main"
|
|
public string FullName { get; init; } // e.g., "refs/heads/main"
|
|
public bool IsRemote { get; init; }
|
|
public bool IsCurrentHead { get; init; }
|
|
public string? LastCommitSha { get; init; }
|
|
public DateTimeOffset? LastCommitDate { get; init; }
|
|
public string? RemoteName { get; init; } // e.g., "origin"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Result Types
|
|
|
|
```csharp
|
|
// Push operation result
|
|
public sealed record GitPushResult(bool Success, string Message)
|
|
{
|
|
public static GitPushResult Ok(string message = "Push successful");
|
|
public static GitPushResult Fail(string message);
|
|
}
|
|
|
|
// Branch tracking information
|
|
public sealed record TrackingInfo(string? UpstreamBranch, int? AheadBy, int? BehindBy)
|
|
{
|
|
public static TrackingInfo None { get; }
|
|
public bool HasUpstream { get; }
|
|
public bool IsInSync { get; } // AheadBy == 0 && BehindBy == 0
|
|
}
|
|
|
|
// AI suggestion result
|
|
public sealed record SuggestionResult(
|
|
CommitAnalysis? Analysis,
|
|
string? Suggestion,
|
|
string? ErrorMessage = null,
|
|
string? RawResponse = null,
|
|
bool ReturnedOriginal = false,
|
|
int InputTokens = 0,
|
|
int OutputTokens = 0,
|
|
decimal EstimatedCost = 0)
|
|
{
|
|
public bool Success { get; }
|
|
public int TotalTokens { get; }
|
|
|
|
public static SuggestionResult Ok(CommitAnalysis analysis, string suggestion, ...);
|
|
public static SuggestionResult Succeeded(string suggestion, ...);
|
|
public static SuggestionResult Fail(CommitAnalysis analysis, string error);
|
|
public static SuggestionResult Failed(string error, string? rawResponse = null);
|
|
}
|
|
|
|
// Batch suggestion result
|
|
public sealed class BatchSuggestionResult
|
|
{
|
|
public IReadOnlyList<CommitAnalysis> Analyses { get; init; }
|
|
public int SuccessCount { get; init; }
|
|
public int FailedCount { get; init; }
|
|
public IReadOnlyList<SuggestionFailure> Failures { get; init; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## History Health Models
|
|
|
|
### HistoryHealthReport
|
|
|
|
Complete health report with scoring, issues, and recommendations.
|
|
|
|
```csharp
|
|
public sealed class HistoryHealthReport
|
|
{
|
|
public required string RepoId { get; init; }
|
|
public required string RepoName { get; init; }
|
|
public required string RepoPath { get; init; }
|
|
public required string CurrentBranch { get; init; }
|
|
public DateTimeOffset GeneratedAt { get; init; }
|
|
public int CommitsAnalyzed { get; init; }
|
|
|
|
// Summary score
|
|
public required HealthScore Score { get; init; }
|
|
|
|
// Detailed metrics
|
|
public required DuplicateCommitMetrics DuplicateMetrics { get; init; }
|
|
public required MergeCommitMetrics MergeMetrics { get; init; }
|
|
public required BranchComplexityMetrics BranchMetrics { get; init; }
|
|
public required MessageQualityDistribution MessageDistribution { get; init; }
|
|
public required AuthorshipMetrics AuthorshipMetrics { get; init; }
|
|
|
|
// Issues and recommendations
|
|
public IReadOnlyList<HealthIssue> Issues { get; init; }
|
|
public IReadOnlyList<HealthRecommendation> Recommendations { get; init; }
|
|
|
|
// Cleanup opportunities
|
|
public CleanupSuggestions? CleanupSuggestions { get; init; }
|
|
|
|
// Convenience properties
|
|
public int CriticalIssueCount { get; }
|
|
public int ErrorCount { get; }
|
|
public int WarningCount { get; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### HealthScore
|
|
|
|
```csharp
|
|
public sealed class HealthScore
|
|
{
|
|
public int OverallScore { get; init; } // 0-100
|
|
public HealthGrade Grade { get; init; } // Excellent, Good, Fair, Poor, Critical
|
|
public int MessageQualityScore { get; init; }
|
|
public int DuplicateScore { get; init; }
|
|
public int MergeHealthScore { get; init; }
|
|
public int BranchComplexityScore { get; init; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### HealthIssue
|
|
|
|
```csharp
|
|
public sealed class HealthIssue
|
|
{
|
|
public required string Code { get; init; }
|
|
public required string Category { get; init; }
|
|
public required HealthIssueSeverity Severity { get; init; } // Info, Warning, Error, Critical
|
|
public required string Title { get; init; }
|
|
public required string Description { get; init; }
|
|
public int ImpactScore { get; init; }
|
|
public IReadOnlyList<string> AffectedCommits { get; init; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### CleanupOperation
|
|
|
|
```csharp
|
|
public sealed class CleanupOperation
|
|
{
|
|
public required string Id { get; init; }
|
|
public required string Title { get; init; }
|
|
public required string Description { get; init; }
|
|
public required CleanupType Type { get; init; }
|
|
public required CleanupAutomationLevel AutomationLevel { get; init; }
|
|
public EstimatedEffort Effort { get; init; }
|
|
public RiskLevel Risk { get; init; }
|
|
public int ExpectedScoreImprovement { get; init; }
|
|
public IReadOnlyList<string> AffectedCommits { get; init; }
|
|
public string? GitCommand { get; init; }
|
|
public CleanupOperationStatus Status { get; set; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### CleanupSuggestions
|
|
|
|
```csharp
|
|
public sealed class CleanupSuggestions
|
|
{
|
|
public IReadOnlyList<CleanupOperation> AutomatedOperations { get; init; }
|
|
public IReadOnlyList<CleanupOperation> SemiAutomatedOperations { get; init; }
|
|
public IReadOnlyList<CleanupOperation> ManualOperations { get; init; }
|
|
|
|
public int TotalOperations { get; }
|
|
public int TotalExpectedImprovement { get; }
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Options
|
|
|
|
### GitImproverOptions
|
|
|
|
Main configuration object.
|
|
|
|
```csharp
|
|
public sealed class GitImproverOptions
|
|
{
|
|
public string WorkspaceRoot { get; set; } // Required
|
|
public string StateFilePath { get; set; } // Default: "git-improver-state.json"
|
|
public CommitMessageRules Rules { get; set; }
|
|
public AiOptions Ai { get; set; }
|
|
public int MaxCommitsPerRepo { get; set; } // Default: 100
|
|
public DateTimeOffset? AnalyzeSince { get; set; }
|
|
public string[] ExcludedAuthors { get; set; } // Default: []
|
|
|
|
public void ValidateAndThrow();
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### CommitMessageRules
|
|
|
|
Quality rules configuration.
|
|
|
|
```csharp
|
|
public sealed class CommitMessageRules
|
|
{
|
|
public int MinSubjectLength { get; set; } // Default: 10
|
|
public int MaxSubjectLength { get; set; } // Default: 72
|
|
public int MinBodyLength { get; set; } // Default: 0
|
|
public bool RequireConventionalCommit { get; set; } // Default: false
|
|
public bool RequireIssueReference { get; set; } // Default: false
|
|
public string[] BannedPhrases { get; set; } // Default: common vague words
|
|
public string[] ConventionalTypes { get; set; } // Default: feat, fix, docs, etc.
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### AiOptions
|
|
|
|
AI provider configuration.
|
|
|
|
```csharp
|
|
public sealed class AiOptions
|
|
{
|
|
[JsonIgnore]
|
|
public string ApiKey { get; set; } // Not persisted
|
|
public string Provider { get; set; } // Default: "Claude"
|
|
public string Model { get; set; } // Default: "claude-sonnet-4-20250514"
|
|
public bool IncludeDiffContext { get; set; } // Default: true
|
|
public int MaxDiffLines { get; set; } // Default: 200
|
|
public int MaxTokens { get; set; } // Default: 500
|
|
public int RateLimitDelayMs { get; set; } // Default: 500
|
|
|
|
public static AIProvider ParseProvider(string? provider);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### HistoryAnalysisOptions
|
|
|
|
```csharp
|
|
public sealed class HistoryAnalysisOptions
|
|
{
|
|
public AnalysisDepth Depth { get; set; } // Quick, Standard, Deep, Full
|
|
public DateTimeOffset? Since { get; set; }
|
|
public string[]? IncludeBranches { get; set; }
|
|
public string[]? ExcludeAuthors { get; set; }
|
|
public bool AnalyzeMerges { get; set; } // Default: true
|
|
public bool DetectDuplicates { get; set; } // Default: true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### CleanupExecutionOptions
|
|
|
|
```csharp
|
|
public sealed record CleanupExecutionOptions
|
|
{
|
|
public bool CreateBackup { get; init; } // Default: true
|
|
public string? BackupBranchName { get; init; }
|
|
public bool AllowPushedCommits { get; init; } // Default: false
|
|
public bool AutoForcePush { get; init; } // Default: false
|
|
public bool UseAiForMessages { get; init; } // Default: true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Enumerations
|
|
|
|
### Analysis & Quality
|
|
|
|
```csharp
|
|
public enum AnalysisStatus { Pending, Analyzed, Applied, Failed, Skipped }
|
|
public enum IssueSeverity { Info, Warning, Error }
|
|
public enum OperationStatus { Pending, Applied, Failed, Undone }
|
|
```
|
|
|
|
### Health Grades
|
|
|
|
```csharp
|
|
public enum HealthGrade
|
|
{
|
|
Excellent, // 90-100: Best practices followed
|
|
Good, // 70-89: Minor issues, generally healthy
|
|
Fair, // 50-69: Noticeable issues, needs attention
|
|
Poor, // 30-49: Significant problems, cleanup recommended
|
|
Critical // 0-29: Severe issues, immediate action required
|
|
}
|
|
|
|
public enum HealthIssueSeverity { Info, Warning, Error, Critical }
|
|
```
|
|
|
|
### Cleanup
|
|
|
|
```csharp
|
|
public enum CleanupType
|
|
{
|
|
SquashDuplicates,
|
|
RewordMessages,
|
|
SquashMerges,
|
|
RebaseLinearize,
|
|
ArchiveBranches,
|
|
FixAuthorship,
|
|
ConsolidateMerges
|
|
}
|
|
|
|
public enum CleanupAutomationLevel
|
|
{
|
|
FullyAutomated, // Can run with one click
|
|
SemiAutomated, // Requires user review/approval
|
|
Manual // Requires manual git commands
|
|
}
|
|
|
|
public enum CleanupOperationStatus { Suggested, Approved, InProgress, Completed, Failed, Skipped }
|
|
public enum RiskLevel { None, Low, Medium, High, VeryHigh }
|
|
public enum EstimatedEffort { Minimal, Low, Medium, High, VeryHigh }
|
|
```
|
|
|
|
### Analysis Depth & Format
|
|
|
|
```csharp
|
|
public enum AnalysisDepth
|
|
{
|
|
Quick, // Sample 200 commits, basic metrics
|
|
Standard, // 1000 commits, all metrics
|
|
Deep, // 5000 commits, comprehensive
|
|
Full // All commits (slow for large repos)
|
|
}
|
|
|
|
public enum ReportFormat { Json, Markdown, Html, Console }
|
|
```
|
|
|
|
---
|
|
|
|
## Extensions
|
|
|
|
### ServiceCollectionExtensions
|
|
|
|
```csharp
|
|
public static class ServiceCollectionExtensions
|
|
{
|
|
/// <summary>
|
|
/// Registers all GitMessageImprover services with the DI container.
|
|
/// </summary>
|
|
public static IServiceCollection AddGitMessageImprover(
|
|
this IServiceCollection services,
|
|
Action<GitImproverOptions> configureOptions);
|
|
}
|
|
```
|
|
|
|
**Registered Services:**
|
|
- `GitImproverOptions` (Singleton)
|
|
- `CommitMessageRules` (Singleton)
|
|
- `AiOptions` (Singleton)
|
|
- `IStateRepository` (Singleton)
|
|
- `ICommitMessageAnalyzer` (Singleton)
|
|
- `IGitOperationsService` (Singleton)
|
|
- `ICommitMessageRewriter` (Singleton)
|
|
- `IGitMessageImproverService` (Singleton)
|
|
|
|
---
|
|
|
|
## Usage Patterns
|
|
|
|
### Pattern 1: CLI Tool
|
|
|
|
```csharp
|
|
var options = new GitImproverOptions { WorkspaceRoot = args[0] };
|
|
await using var service = await GitMessageImproverService.CreateAsync(options);
|
|
|
|
var repos = await service.ScanAndRegisterReposAsync();
|
|
var analyses = await service.AnalyzeAllReposAsync(onlyNeedsImprovement: true);
|
|
|
|
foreach (var analysis in analyses)
|
|
{
|
|
Console.WriteLine($"[{analysis.Quality.OverallScore}] {analysis.ShortHash}: {analysis.OriginalMessage}");
|
|
}
|
|
```
|
|
|
|
### Pattern 2: MAUI/WPF App with DI
|
|
|
|
```csharp
|
|
// In MauiProgram.cs
|
|
services.AddGitMessageImprover(opt =>
|
|
{
|
|
opt.WorkspaceRoot = Preferences.Get("workspace", "");
|
|
opt.Ai.ApiKey = SecureStorage.GetAsync("api_key").Result ?? "";
|
|
});
|
|
|
|
// In ViewModel
|
|
public class CommitViewModel(IGitMessageImproverService service)
|
|
{
|
|
public async Task LoadAsync()
|
|
{
|
|
await service.LoadStateAsync();
|
|
Repos = new ObservableCollection<ManagedRepo>(service.Repos);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pattern 3: Focused Interface Usage
|
|
|
|
```csharp
|
|
// Only need push operations - inject the focused interface
|
|
public class PushHandler(IGitPushService pushService)
|
|
{
|
|
public bool SafePush(string repoPath, string commitHash)
|
|
{
|
|
if (pushService.IsCommitPushed(repoPath, commitHash))
|
|
return true;
|
|
|
|
return pushService.Push(repoPath).Success;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Pattern 4: Health Analysis Pipeline
|
|
|
|
```csharp
|
|
// Analyze -> Review -> Cleanup
|
|
var report = await service.AnalyzeHistoryHealthAsync(repoPath);
|
|
|
|
if (report.Score.Grade <= HealthGrade.Fair)
|
|
{
|
|
// Export for review
|
|
var markdown = await service.ExportHealthReportAsync(report, ReportFormat.Markdown);
|
|
await File.WriteAllTextAsync("health-report.md", markdown);
|
|
|
|
// Execute safe automated cleanups
|
|
if (report.CleanupSuggestions?.AutomatedOperations.Any() == true)
|
|
{
|
|
var result = await service.ExecuteAllCleanupsAsync(
|
|
repo,
|
|
report.CleanupSuggestions,
|
|
new CleanupExecutionOptions { CreateBackup = true, AllowPushedCommits = false });
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
| Exception | Cause | Resolution |
|
|
|-----------|-------|------------|
|
|
| `ApiKeyNotConfiguredException` | AI API key not configured | Set `AiOptions.ApiKey` |
|
|
| `ValidationException` | Invalid `GitImproverOptions` | Check required fields |
|
|
| `InvalidOperationException` | No suggested message for commit | Generate suggestion first |
|
|
| `ArgumentException` | Commit or repository not found | Verify paths and hashes |
|
|
|
|
---
|
|
|
|
## Thread Safety Notes
|
|
|
|
- Repository cache uses `ConcurrentDictionary` with LRU eviction
|
|
- All async methods support `CancellationToken`
|
|
- State operations are serialized through `IStateRepository`
|
|
- Dispose the service when done to release git handles
|
|
|
|
```csharp
|
|
// Always dispose
|
|
await using var service = await GitMessageImproverService.CreateAsync(options);
|
|
// or
|
|
using var service = ...;
|
|
// or explicitly
|
|
service.Dispose();
|
|
```
|