@@ -86,6 +86,29 @@ type Config struct {
8686 // Modification is cheaper because architecture is established and patterns are known.
8787 ModificationCostFactor float64
8888
89+ // WeeklyChurnRate is the probability that code becomes stale per week (default: 0.0229 = 2.29%)
90+ // Used to calculate rework percentage for open PRs based on time since last commit.
91+ // Formula: rework = 1 - (1 - weekly_rate)^weeks
92+ //
93+ // Default of 2.29% per week is based on empirical analysis across organizations:
94+ // - 60% of analyzed organizations had churn rates of 2.29%/week or lower
95+ // - 40% had higher churn rates
96+ // - Younger companies tend to have higher churn rates
97+ // - Results in 70% annual churn, reasonable for active development
98+ //
99+ // Examples from empirical data:
100+ // - 0.0018 (0.18%/week) - Adobe (mature, stable codebase)
101+ // - 0.0229 (2.29%/week) - 60th percentile (default)
102+ // - 0.0831 (8.31%/week) - Chainguard (young company, fast-moving)
103+ //
104+ // Recommended values for different project types:
105+ // - 0.010 (1.0%/week) → 41% annual churn - stable projects, mature codebases
106+ // - 0.0229 (2.29%/week) → 70% annual churn - typical active development (default, 60th percentile)
107+ // - 0.030 (3.0%/week) → 78% annual churn - fast-moving projects
108+ // - 0.040 (4.0%/week) → 88% annual churn - very high churn
109+ // - 0.080+ (8%+/week) → 99%+ annual churn - extremely fast-moving, younger companies
110+ WeeklyChurnRate float64
111+
89112 // COCOMO configuration for estimating code writing effort
90113 COCOMO cocomo.Config
91114}
@@ -108,6 +131,7 @@ func DefaultConfig() Config {
108131 MaxCodeDrift : 90 * 24 * time .Hour , // 90 days
109132 ReviewInspectionRate : 275.0 , // 275 LOC/hour (average of optimal 150-400 range)
110133 ModificationCostFactor : 0.4 , // Modified code costs 40% of new code
134+ WeeklyChurnRate : 0.0229 , // 2.29% per week (70% annual, 60th percentile empirical)
111135 COCOMO : cocomo .DefaultConfig (),
112136 }
113137}
@@ -347,29 +371,21 @@ func Calculate(data PRData, cfg Config) Breakdown {
347371 // 2. Code Churn (Rework): Probability-based drift formula
348372 // Only calculated for open PRs - closed PRs won't need future updates
349373 //
350- // Research basis:
351- // - Windows Vista: 4-8% weekly code churn (Nagappan et al., Microsoft Research, 2008)
352- // - Using 4% weekly baseline for active repositories
353- //
354374 // Formula: Probability that a line becomes stale over time
355375 // drift = 1 - (1 - weeklyChurn)^(weeks)
356- // drift = 1 - (0.96)^(days/7)
376+ // Default: weeklyChurn = 2.29% (0.0229) - empirical 60th percentile
357377 //
358378 // This models the cumulative probability that any given line in the PR needs rework
359- // due to codebase changes. Unlike compounding formulas, this accounts for the fact
360- // that the same code areas often change multiple times.
361- //
362- // Expected drift percentages:
363- // - 3 days: ~2% drift
364- // - 7 days: ~4% drift (matches weekly churn)
365- // - 14 days: ~8% drift
366- // - 30 days: ~16% drift
367- // - 60 days: ~29% drift
368- // - 90 days: ~41% drift (days capped at 90)
379+ // due to codebase changes. The weekly churn rate is configurable to match project velocity.
369380 //
370- // Reference:
371- // Nagappan, N., Murphy, B., & Basili, V. (2008). The Influence of Organizational
372- // Structure on Software Quality. ACM/IEEE ICSE. DOI: 10.1145/1368088.1368160
381+ // Default (2.29% per week) drift percentages:
382+ // - 1 week: ~2.3% drift
383+ // - 2 weeks: ~4.5% drift
384+ // - 3 weeks: ~6.7% drift
385+ // - 1 month: ~8.9% drift
386+ // - 2 months: ~16.9% drift
387+ // - 3 months: ~24.3% drift
388+ // - 1 year: ~70% annual churn (empirical data from org analysis)
373389
374390 var reworkLOC int
375391 var codeChurnHours float64
@@ -414,9 +430,11 @@ func Calculate(data PRData, cfg Config) Breakdown {
414430 cappedDriftDays = maxDriftDays
415431 }
416432
417- // Probability-based drift: 1 - (1 - 0.04)^(days/7)
433+ // Probability-based drift using configurable weekly churn rate
434+ // Formula: rework = 1 - (1 - weekly_rate)^weeks
435+ // Default: 1% per week → 41% annual churn
418436 weeks := cappedDriftDays / 7.0
419- reworkPercentage = 1.0 - math .Pow (0.96 , weeks )
437+ reworkPercentage = 1.0 - math .Pow (1.0 - cfg . WeeklyChurnRate , weeks )
420438
421439 reworkLOC = int (float64 (data .LinesAdded ) * reworkPercentage )
422440
0 commit comments