Documentation
ΒΆ
Overview ΒΆ
Package verification provides independent recompute verification for commitgraph.
This package implements Verification Gate 2 from docs/plan/plan.md: "For a sample of repos, recompute the rollup directly from the corpus Parquet with a separate implementation path and assert it matches what Postgres holds."
CRITICAL: This implementation shares NO code with the production write path (pkg/rollup and pkg/pg/rollup_write.go). This is intentional β the verification must be a truly independent implementation to catch bugs in the production code.
The recompute logic: 1. Reads a repo's Parquet artifact from ARMOR 2. Parses each commit's message trailer for AI tool detection 3. Applies date quarantine filtering (exclude commits outside [2005-01-01, today+1]) 4. Aggregates by (author_email, tool, day) β count 5. Resolves author_email to user_id via email_resolution 6. Produces independent (user_id, repo_id, tool, day, count) rows
This is then compared against Postgres rollup data to detect divergence.
Index ΒΆ
- Constants
- func ExampleVerification()
- type BatchResult
- type BatchVerifier
- type CIReporter
- type ClaudeCodeDiscrepancy
- type ClaudeLeaderboardResolver
- type Commit
- type CommitReader
- type DetailedVerificationResult
- type EnhancedVerifier
- type JSONReporter
- type ParquetCommit
- type ParquetCommitReader
- type ParquetReaderConfig
- type PostgresEmailResolver
- type PostgresReader
- type PostgresRollup
- type RecomputedRollup
- type Recomputer
- type RepoKey
- type Reporter
- type RollupDifference
- type SampleConfig
- type SampleStrategy
- type VerificationResult
- type Verifier
Constants ΒΆ
const (
MinQuarantineDate = "2005-01-01T00:00:00Z"
)
Quarantine bounds match the production system exactly. See pkg/rollup/rollup.go for the production implementation.
Variables ΒΆ
This section is empty.
Functions ΒΆ
Types ΒΆ
type BatchResult ΒΆ
type BatchResult struct {
TotalRepos int
PassedRepos int
FailedRepos int
TotalCommits int
TotalDifferences int
Duration time.Duration
RepoResults []*DetailedVerificationResult
}
BatchResult contains aggregated batch verification results.
type BatchVerifier ΒΆ
type BatchVerifier struct {
// contains filtered or unexported fields
}
BatchVerifier runs verification on multiple repos and aggregates results.
func NewBatchVerifier ΒΆ
func NewBatchVerifier(verifier *EnhancedVerifier, reporter *Reporter) *BatchVerifier
NewBatchVerifier creates a new batch verifier.
func (*BatchVerifier) VerifyBatch ΒΆ
func (bv *BatchVerifier) VerifyBatch(ctx context.Context, repos []RepoKey) (*BatchResult, error)
VerifyBatch verifies multiple repositories in sequence.
type CIReporter ΒΆ
type CIReporter struct {
// contains filtered or unexported fields
}
CIReporter outputs verification results in a CI-friendly format.
func NewCIReporter ΒΆ
func NewCIReporter(output io.Writer) *CIReporter
NewCIReporter creates a new CI reporter.
func (*CIReporter) ReportResult ΒΆ
func (cir *CIReporter) ReportResult(result *DetailedVerificationResult) error
ReportResult writes a CI-friendly verification report.
type ClaudeCodeDiscrepancy ΒΆ
type ClaudeCodeDiscrepancy struct {
UserEmail string
RecomputedCount int
PostgresCount int
ClaudeLeaderboardCount int // Authoritative count from claude-leaderboard
Day time.Time
Conclusion string // "commitgraph_correct", "claude_leaderboard_correct", "needs_investigation"
}
ClaudeCodeDiscrepancy details a Claude Code-specific discrepancy. See docs/notes/cg-37gw-claude-leaderboard-canonical-rule.md
type ClaudeLeaderboardResolver ΒΆ
type ClaudeLeaderboardResolver struct {
}
ClaudeLeaderboardResolver handles the canonical rule for Claude Code discrepancies. See docs/notes/cg-37gw-claude-leaderboard-canonical-rule.md
func NewClaudeLeaderboardResolver ΒΆ
func NewClaudeLeaderboardResolver() *ClaudeLeaderboardResolver
NewClaudeLeaderboardResolver creates a new resolver.
func (*ClaudeLeaderboardResolver) IsClaudeCodeTool ΒΆ
func (clr *ClaudeLeaderboardResolver) IsClaudeCodeTool(tool string) bool
IsClaudeCodeTool returns true if the tool is Claude Code or a variant.
func (*ClaudeLeaderboardResolver) ResolveCanonicalCount ΒΆ
func (clr *ClaudeLeaderboardResolver) ResolveCanonicalCount(ctx context.Context, repoID int64, userEmail string, day time.Time) (int, error)
ResolveCanonicalCount would query claude-leaderboard for the authoritative count. For now, it returns a placeholder implementation.
type Commit ΒΆ
type Commit struct {
SHA string
AuthorEmail string
AuthorName string
CommittedAt time.Time
Message string
}
Commit represents a single commit read from Parquet for recomputation. This is intentionally independent of any production data structures.
type CommitReader ΒΆ
CommitReader reads commit data from a Parquet file. This is a simplified interface β the actual implementation will need to handle ARMOR decryption and Parquet decoding.
type DetailedVerificationResult ΒΆ
type DetailedVerificationResult struct {
RepoID int64
Provider string
RepoFullName string
TotalCommits int
AICommits int
QuarantineExcluded int
TotalRecomputed int
TotalPostgres int
MatchCount int
MissingInPostgres int
MissingInRecompute int
CountMismatches int
UserMismatches int
ClaudeCodeDiffs []ClaudeCodeDiscrepancy
Differences []RollupDifference
VerificationDuration time.Duration
}
VerificationResult contains the detailed outcome of a verification run. This extends the basic VerificationResult with more detailed analysis.
func (*DetailedVerificationResult) MarshalJSON ΒΆ
func (dvr *DetailedVerificationResult) MarshalJSON() ([]byte, error)
MarshalJSON implements JSON marshaling for DetailedVerificationResult.
func (*DetailedVerificationResult) Summary ΒΆ
func (dvr *DetailedVerificationResult) Summary() string
Summary returns a human-readable summary of the verification result.
type EnhancedVerifier ΒΆ
type EnhancedVerifier struct {
// contains filtered or unexported fields
}
EnhancedVerifier provides detailed verification with email resolution and Claude Code canonical rule.
func NewEnhancedVerifier ΒΆ
func NewEnhancedVerifier( recomputer *Recomputer, pgReader *PostgresReader, commitReader *ParquetCommitReader, emailResolver *PostgresEmailResolver, ) *EnhancedVerifier
NewEnhancedVerifier creates a new enhanced verifier.
func (*EnhancedVerifier) VerifyRepoDetailed ΒΆ
func (ev *EnhancedVerifier) VerifyRepoDetailed(ctx context.Context, repo RepoKey) (*DetailedVerificationResult, error)
VerifyRepoDetailed performs a detailed verification of a single repository.
type JSONReporter ΒΆ
type JSONReporter struct {
// contains filtered or unexported fields
}
JSONReporter outputs verification results as JSON for machine processing.
func NewJSONReporter ΒΆ
func NewJSONReporter(output io.Writer) *JSONReporter
NewJSONReporter creates a new JSON reporter.
func (*JSONReporter) ReportResult ΒΆ
func (jr *JSONReporter) ReportResult(result *DetailedVerificationResult) error
ReportResult writes verification result as JSON.
type ParquetCommit ΒΆ
type ParquetCommit struct {
SchemaVersion int32 // Schema version identifier
SHA string // Commit SHA
Provider string // Git provider (e.g., "github")
Repo string // Repository full name (e.g., "owner/repo")
Username string // Git username (may be empty or noreply@)
AuthorName string // Git author name
AuthorEmail string // Git author email
CommittedAt int64 // Commit timestamp (microseconds since Unix epoch)
Subject string // Commit subject line
Message string // Full commit message
}
Commit represents a row from the Parquet commit artifact. This matches the production Parquet schema (see commitgraph-deprecated/containers/clone-worker/worker.py)
type ParquetCommitReader ΒΆ
type ParquetCommitReader struct {
// contains filtered or unexported fields
}
ParquetCommitReader reads commit data from Parquet artifacts stored in ARMOR.
This implementation is completely independent of any production code path that might read Parquet files. It implements only the minimal functionality needed for verification: reading per-repo Parquet artifacts and extracting commit SHA, author email/name, committed_at, and message.
The ARMOR key structure for per-rejo Parquet artifacts is: commitgraph/repo/<provider>/<repo_full_name>/commits.parquet
func NewParquetCommitReader ΒΆ
func NewParquetCommitReader(config ParquetReaderConfig) *ParquetCommitReader
NewParquetCommitReader creates a new Parquet commit reader.
func (*ParquetCommitReader) ParquetArtifactKey ΒΆ
func (r *ParquetCommitReader) ParquetArtifactKey(repo RepoKey) string
ParquetArtifactKey returns the ARMOR key for a repo's Parquet commit artifact.
func (*ParquetCommitReader) ReadCommits ΒΆ
ReadCommits reads all commits for a repository from its Parquet artifact.
This is a stub implementation. The real implementation would: 1. Construct the ARMOR object key from repo info 2. Make an HTTP GET request to ARMOR with decryption credentials 3. Stream the decrypted Parquet data 4. Use PyArrow or similar to read the Parquet file 5. Extract commit rows and return them as []Commit
For now, this returns an error to indicate it needs implementation.
type ParquetReaderConfig ΒΆ
type ParquetReaderConfig struct {
// ARMOREndpoint is the ARMOR proxy endpoint
ARMOREndpoint string
// ARMORBucket is the ARMOR bucket name
ARMORBucket string
// ARMORPrefix is the ARMOR prefix (e.g., "commitgraph/")
ARMORPrefix string
}
ParquetReaderConfig configures the Parquet commit reader.
type PostgresEmailResolver ΒΆ
type PostgresEmailResolver struct {
// contains filtered or unexported fields
}
PostgresEmailResolver resolves author emails to user_ids using Postgres email_resolution table.
This is needed because the Postgres rollup table uses user_id (surrogate key) while the recomputed rollup starts from author_email. We need to resolve emails to user_ids for accurate comparison.
func NewPostgresEmailResolver ΒΆ
func NewPostgresEmailResolver(conn *pgx.Conn) *PostgresEmailResolver
NewPostgresEmailResolver creates a new email resolver.
func (*PostgresEmailResolver) ResolveEmail ΒΆ
func (per *PostgresEmailResolver) ResolveEmail(ctx context.Context, email string) (int64, bool, error)
ResolveEmail resolves a single author email to its user_id. Returns (user_id, true, nil) if resolved, (0, false, nil) if not found.
type PostgresReader ΒΆ
type PostgresReader struct {
// contains filtered or unexported fields
}
PostgresReader reads rollup data from Postgres for comparison.
func NewPostgresReader ΒΆ
func NewPostgresReader(conn *pgx.Conn) *PostgresReader
NewPostgresReader creates a new Postgres rollup reader.
func (*PostgresReader) ReadRepoRollup ΒΆ
func (pr *PostgresReader) ReadRepoRollup(ctx context.Context, repoID int64) ([]PostgresRollup, error)
ReadRepoRollup reads all rollup rows for a specific repo from Postgres.
type PostgresRollup ΒΆ
type PostgresRollup struct {
UserID int64 // Resolved user_id
RepoID int64 // Repository ID
Tool string // AI tool name
Day time.Time // Day (UTC midnight)
Count int // Number of commits
}
PostgresRollup represents a rollup row read from Postgres.
type RecomputedRollup ΒΆ
type RecomputedRollup struct {
UserEmail string // Author email (pre-resolution)
RepoID int64 // Repository ID
Tool string // AI tool name
Day time.Time // Day (UTC midnight)
Count int // Number of commits
}
RecomputedRollup represents a single independently-computed rollup row. This is the verification-side equivalent of pg.RollupRow but computed via a completely separate code path.
type Recomputer ΒΆ
type Recomputer struct {
// contains filtered or unexported fields
}
Recomputer handles independent rollup recomputation from Parquet data.
func NewRecomputer ΒΆ
func NewRecomputer(today time.Time) *Recomputer
NewRecomputer creates a new Recomputer for verification.
func (*Recomputer) RecomputeFromCommits ΒΆ
func (r *Recomputer) RecomputeFromCommits(commits []Commit, repoID int64) []RecomputedRollup
RecomputeFromCommits independently computes rollup rows from raw commits. This is a complete reimplementation of pkg/rollup.ComputeRollup to maintain true independence for verification.
type RepoKey ΒΆ
type RepoKey struct {
Provider string // e.g., "github"
RepoFullName string // e.g., "owner/repo"
RepoID int64 // Internal repository ID
}
RepoKey describes a repository's location in ARMOR.
type Reporter ΒΆ
type Reporter struct {
// contains filtered or unexported fields
}
Reporter formats and outputs verification results.
func NewReporter ΒΆ
NewReporter creates a new verification reporter.
func (*Reporter) ReportResult ΒΆ
func (r *Reporter) ReportResult(result *DetailedVerificationResult) error
ReportResult writes a human-readable verification report.
type RollupDifference ΒΆ
type RollupDifference struct {
Recomputed *RecomputedRollup // May be nil if row only exists in Postgres
Postgres *PostgresRollup // May be nil if row only exists in recomputed
DifferenceType string // "missing_in_postgres", "missing_in_recompute", "count_mismatch", "user_mismatch"
}
RollupDifference represents a single row difference between recomputed and Postgres rollup.
type SampleConfig ΒΆ
type SampleConfig struct {
Strategy SampleStrategy
Count int // Number of repos to sample
Seed int64 // Random seed (for reproducibility)
MinCommits int // Minimum AI commits to include (filters out inactive repos)
}
SampleConfig configures repo sampling for verification.
func DefaultSampleConfig ΒΆ
func DefaultSampleConfig() SampleConfig
DefaultSampleConfig returns a reasonable default sampling configuration.
type SampleStrategy ΒΆ
type SampleStrategy string
SampleStrategy defines how to sample repos for verification.
const ( // SampleRandom picks random repos from the corpus SampleRandom SampleStrategy = "random" // SampleTopByCommits picks repos with the most AI commits SampleTopByCommits SampleStrategy = "top_commits" // SampleRecent picks the most recently scanned repos SampleRecent SampleStrategy = "recent" // SampleClaudeCode picks repos with Claude Code activity (for canonical rule testing) SampleClaudeCode SampleStrategy = "claude_code" )
type VerificationResult ΒΆ
type VerificationResult struct {
RepoID int64
TotalRecomputed int
TotalPostgres int
MatchCount int
Differences []RollupDifference
ClaudeCodeNotes []string // Notes about Claude Code canonical rule application
}
VerificationResult contains the outcome of a verification run.
type Verifier ΒΆ
type Verifier struct {
// contains filtered or unexported fields
}
Verifier orchestrates the full verification process.
func NewVerifier ΒΆ
func NewVerifier(recomputer *Recomputer, pgReader *PostgresReader, commitReader CommitReader) *Verifier
NewVerifier creates a new Verifier.
func (*Verifier) VerifyRepo ΒΆ
VerifyRepo verifies a single repository's rollup.