@@ -3741,54 +3741,12 @@ function formatPurityPercent(value) {
37413741
37423742function buildPurityObservations ( summary ) {
37433743 const lines = [ ] ;
3744- if ( ! summary ) {
3745- return lines ;
3746- }
3747- const totalRuns = Number . isFinite ( summary . totalRuns ) ? summary . totalRuns : 0 ;
3748- const pureRuns = Number . isFinite ( summary . pureRuns ) ? summary . pureRuns : 0 ;
3749- const impureRuns = Number . isFinite ( summary . impureRuns ) ? summary . impureRuns : 0 ;
3750- const statusLabel = summary . didCheckerError
3751- ? 'ERROR'
3752- : summary . hasAnyError
3753- ? 'FAILED'
3754- : 'OK' ;
3755- if ( totalRuns > 0 ) {
3756- const statusParts = [ `Purity status: ${ statusLabel } .` ] ;
3757- if ( summary . didCheckerError ) {
3758- statusParts . push ( 'Checker encountered errors.' ) ;
3759- } else if ( impureRuns > 0 ) {
3760- statusParts . push ( `${ impureRuns } /${ totalRuns } runs show drift between raw and share totals.` ) ;
3761- } else {
3762- statusParts . push ( `All ${ pureRuns } /${ totalRuns } runs are pure.` ) ;
3763- }
3764- lines . push ( `Overall: ${ statusParts . join ( ' ' ) } ` ) ;
3765- }
3766-
3767- const analysis = summary . analysis ;
3744+ const analysis = summary ?. analysis ;
3745+ const totalRuns = Number . isFinite ( summary ?. totalRuns ) ? summary . totalRuns : 0 ;
37683746 if ( ! analysis || ! totalRuns ) {
37693747 return lines ;
37703748 }
37713749
3772- if ( Number . isFinite ( analysis . avgRawTotal ) ) {
3773- const avgRaw = formatPurityMinutes ( analysis . avgRawTotal ) ;
3774- const avgShare = formatPurityMinutes ( analysis . avgShareTotal ) ;
3775- const avgSequence = formatPurityMinutes ( analysis . avgSequenceTotal ) ;
3776- lines . push (
3777- `Overall: Average total minutes per run: raw=${ avgRaw } , share=${ avgShare } , sequence=${ avgSequence } .`
3778- ) ;
3779-
3780- const shareDiff = analysis . avgShareTotal - analysis . avgRawTotal ;
3781- const percentDiff = analysis . avgRawTotal === 0 ? null : shareDiff / analysis . avgRawTotal ;
3782- if ( Math . abs ( shareDiff ) >= 1 ) {
3783- const direction = shareDiff < 0 ? 'missing' : 'over-reporting' ;
3784- const percentText = formatPurityPercent ( percentDiff ) ;
3785- const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${ percentText } ).` ;
3786- const driftMinutesText = formatPurityMinutes ( Math . abs ( shareDiff ) ) ;
3787- const baseText = `Overall: On average, share is ${ direction } ${ driftMinutesText } minutes per run compared to raw` ;
3788- lines . push ( percentSuffix ? `${ baseText } ${ percentSuffix } ` : `${ baseText } .` ) ;
3789- }
3790- }
3791-
37923750 const activityThresholdMinutes = 60 ;
37933751 const activityThresholdPercent = 0.1 ;
37943752 const activityAnalyses = Array . isArray ( analysis . activities ) ? analysis . activities . slice ( ) : [ ] ;
@@ -3810,14 +3768,14 @@ function buildPurityObservations(summary) {
38103768 . slice ( 0 , 3 ) ;
38113769
38123770 significantActivities . forEach ( ( activity ) => {
3813- const driftMinutes = activity . avgShareDriftMinutes || 0 ;
3814- const direction = driftMinutes < 0 ? 'undercounted' : 'overcounted' ;
38153771 const label = activity . label || activity . key || 'activity' ;
3772+ const avgRawText = formatPurityMinutes ( activity . avgRawPerRun ) ;
3773+ const avgShareText = formatPurityMinutes ( activity . avgSharePerRun ) ;
3774+ const driftMinutesText = formatPurityMinutes ( activity . avgShareDriftMinutes || 0 ) ;
38163775 const percentText = formatPurityPercent ( activity . avgShareDriftPercent ) ;
3817- const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${ percentText } vs raw)` ;
3818- const driftMinutesText = formatPurityMinutes ( Math . abs ( driftMinutes ) ) ;
3776+ const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${ percentText } )` ;
38193777 lines . push (
3820- `Activity ' ${ label } ' is ${ direction } in share by an average of ${ driftMinutesText } minutes per run ${ percentSuffix } . `
3778+ `ACTIVITY | ${ label } | avg raw/ share per run: ${ avgRawText } / ${ avgShareText } | drift: ${ driftMinutesText } min ${ percentSuffix } `
38213779 ) ;
38223780 } ) ;
38233781
@@ -3842,38 +3800,49 @@ function buildPurityObservations(summary) {
38423800 }
38433801 const minMagnitudeText = formatPurityMinutes ( minMagnitude ) ;
38443802 lines . push (
3845- `Runs: Largest total drift in runs ${ runLabels . join ( ', ' ) } (share ${ descriptor } ≥ ${ minMagnitudeText } minutes each). `
3803+ `RUNS | worst total drift: ${ runLabels . join ( ', ' ) } (share ${ descriptor } ≥ ${ minMagnitudeText } min each)`
38463804 ) ;
38473805 }
38483806
38493807 return lines ;
38503808}
38513809
38523810function buildPuritySummaryLines ( summary , observations ) {
3811+ const lines = [ ] ;
38533812 const totalRuns = Number . isFinite ( summary ?. totalRuns ) ? summary . totalRuns : 0 ;
38543813 const pureRuns = Number . isFinite ( summary ?. pureRuns ) ? summary . pureRuns : 0 ;
38553814 const impureRuns = Number . isFinite ( summary ?. impureRuns ) ? summary . impureRuns : 0 ;
38563815 const runs = Array . isArray ( summary ?. runs ) ? summary . runs : [ ] ;
38573816 const checkerErrorRuns = runs . filter ( ( run ) => run && run . didError ) . length ;
38583817 const hasCheckerError = Boolean ( summary ?. didCheckerError ) ;
38593818 const errorCount = hasCheckerError ? Math . max ( 1 , checkerErrorRuns ) : checkerErrorRuns ;
3860- const headerStats = [ `Batch size: ${ totalRuns } ` , `Pure: ${ pureRuns } ` , `Impure: ${ impureRuns } ` ] ;
3819+ const statusLabel = hasCheckerError ? 'ERROR' : summary ?. hasAnyError ? 'FAILED' : 'OK' ;
3820+ const statusParts = [ `runs: ${ totalRuns } total, ${ pureRuns } pure, ${ impureRuns } impure` ] ;
38613821 if ( errorCount > 0 ) {
3862- headerStats . push ( `Checker errors: ${ errorCount } ` ) ;
3822+ statusParts . push ( `checker errors: ${ errorCount } ` ) ;
38633823 }
3864- const summaryLines = Array . isArray ( observations ) && observations . length > 0
3865- ? observations
3866- : [ '(No observations available.)' ] ;
3867- const headerLine = '============================================================' ;
3868- const separatorLine = '------------------------------------------------------------' ;
3869- const lines = [
3870- headerLine ,
3871- `PURITY REPORT | ${ headerStats . join ( ' | ' ) } ` ,
3872- headerLine ,
3873- ...summaryLines . map ( ( line ) => `Overall: ${ line } ` ) ,
3874- separatorLine ,
3875- '(Full raw purity data continues below…)' ,
3876- ] ;
3824+ lines . push ( `STATUS | ${ statusLabel } | ${ statusParts . join ( ' | ' ) } ` ) ;
3825+
3826+ const analysis = summary ?. analysis ;
3827+ if ( analysis && totalRuns > 0 ) {
3828+ const avgRaw = formatPurityMinutes ( analysis . avgRawTotal ) ;
3829+ const avgShare = formatPurityMinutes ( analysis . avgShareTotal ) ;
3830+ const avgSequence = formatPurityMinutes ( analysis . avgSequenceTotal ) ;
3831+ lines . push ( `TOTALS | avg raw/share/sequence per run: ${ avgRaw } / ${ avgShare } / ${ avgSequence } ` ) ;
3832+
3833+ const shareDiff = ( Number ( analysis . avgShareTotal ) || 0 ) - ( Number ( analysis . avgRawTotal ) || 0 ) ;
3834+ const percentDiff = analysis . avgRawTotal === 0 ? null : shareDiff / analysis . avgRawTotal ;
3835+ const driftMinutesText = formatPurityMinutes ( shareDiff ) ;
3836+ const percentText = formatPurityPercent ( percentDiff ) ;
3837+ const percentSuffix = percentText === 'n/a' ? '' : ` (≈ ${ percentText } )` ;
3838+ lines . push ( `TOTALS | avg drift (share vs raw): ${ driftMinutesText } min per run${ percentSuffix } ` ) ;
3839+ }
3840+
3841+ if ( Array . isArray ( observations ) && observations . length > 0 ) {
3842+ lines . push ( ...observations ) ;
3843+ }
3844+
3845+ lines . push ( 'NOTE | Full raw purity data continues below…' ) ;
38773846 return lines ;
38783847}
38793848
0 commit comments