2026-05-10 23:51:24 +02:00
import { isKtxRelationshipBenchmarkTuningEligible } from './relationship-benchmarks.js' ;
2026-05-10 23:12:26 +02:00
import type {
2026-05-10 23:51:24 +02:00
KtxRelationshipBenchmarkCaseResult ,
KtxRelationshipBenchmarkFixture ,
KtxRelationshipBenchmarkMode ,
KtxRelationshipBenchmarkSuiteResult ,
2026-05-10 23:12:26 +02:00
} from './relationship-benchmarks.js' ;
2026-05-10 23:51:24 +02:00
export type KtxRelationshipBenchmarkReportCaseStatus = 'run' | 'validation_blocked' | 'not_run' ;
2026-05-10 23:12:26 +02:00
2026-05-10 23:51:24 +02:00
export interface KtxRelationshipBenchmarkReportCase {
2026-05-10 23:12:26 +02:00
fixtureId : string ;
fixtureName : string ;
tier : string ;
2026-05-10 23:51:24 +02:00
mode : KtxRelationshipBenchmarkMode ;
status : KtxRelationshipBenchmarkReportCaseStatus ;
2026-05-10 23:12:26 +02:00
reason : string | null ;
tuningEligible : boolean ;
metrics : {
pkRecall : number | null ;
fkRecall : number | null ;
acceptedOrReviewRecall : number | null ;
acceptedFalsePositiveCount : number | null ;
sqlQueries : number | null ;
llmCalls : number | null ;
runtimeSeconds : number | null ;
} ;
falsePositives : {
pk : string [ ] ;
fk : string [ ] ;
} ;
falseNegatives : {
pk : string [ ] ;
fk : string [ ] ;
} ;
skippedComposite : {
pk : string [ ] ;
fk : string [ ] ;
} ;
}
2026-05-10 23:51:24 +02:00
export interface KtxRelationshipBenchmarkReport {
2026-05-10 23:12:26 +02:00
generatedAt : string ;
headline : {
caseCount : number ;
headlineCaseCount : number ;
headlinePkRecall : number ;
headlineFkRecall : number ;
headlineAcceptedOrReviewRecall : number ;
acceptedFalsePositiveCount : number ;
validationBlockedCount : number ;
} ;
2026-05-10 23:51:24 +02:00
cases : KtxRelationshipBenchmarkReportCase [ ] ;
2026-05-10 23:12:26 +02:00
}
2026-05-10 23:51:24 +02:00
function key ( fixtureId : string , mode : KtxRelationshipBenchmarkMode ) : string {
2026-05-10 23:12:26 +02:00
return ` ${ fixtureId } : ${ mode } ` ;
}
function fixed ( value : number | null ) : string {
return value === null ? '-' : value . toFixed ( 3 ) ;
}
function reportCaseReason ( input : {
2026-05-10 23:51:24 +02:00
fixture : KtxRelationshipBenchmarkFixture ;
result : KtxRelationshipBenchmarkCaseResult ;
2026-05-10 23:12:26 +02:00
} ) : string | null {
if ( input . result . validationBlocked ) {
return 'validation unavailable for this benchmark mode' ;
}
if ( input . fixture . validationBudget !== undefined && input . result . predicted . reviewFk . length > 0 ) {
return ` review candidate validation reasons: validation_unattempted ( ${ input . result . predicted . reviewFk . length } ) ` ;
}
return null ;
}
function reportCaseFromResult ( input : {
2026-05-10 23:51:24 +02:00
fixture : KtxRelationshipBenchmarkFixture ;
mode : KtxRelationshipBenchmarkMode ;
result : KtxRelationshipBenchmarkCaseResult ;
} ) : KtxRelationshipBenchmarkReportCase {
2026-05-10 23:12:26 +02:00
const status = input . result . validationBlocked ? 'validation_blocked' : 'run' ;
return {
fixtureId : input.fixture.id ,
fixtureName : input.fixture.name ,
tier : input.fixture.tier ,
mode : input.mode ,
status ,
reason : reportCaseReason ( { fixture : input.fixture , result : input.result } ) ,
2026-05-10 23:51:24 +02:00
tuningEligible : isKtxRelationshipBenchmarkTuningEligible ( {
2026-05-10 23:12:26 +02:00
fixture : input.fixture ,
mode : input.mode ,
validationBlocked : input.result.validationBlocked ,
} ) ,
metrics : {
pkRecall : input.result.metrics.pkRecall ,
fkRecall : input.result.metrics.fkRecall ,
acceptedOrReviewRecall : input.result.metrics.acceptedOrReviewRecall ,
acceptedFalsePositiveCount : input.result.metrics.acceptedFalsePositiveCount ,
sqlQueries : input.result.metrics.sqlQueries ,
llmCalls : input.result.metrics.llmCalls ,
runtimeSeconds : input.result.metrics.runtimeSeconds ,
} ,
falsePositives : input.result.falsePositives ,
falseNegatives : input.result.falseNegatives ,
skippedComposite : input.result.skippedComposite ,
} ;
}
function notRunCase ( input : {
2026-05-10 23:51:24 +02:00
fixture : KtxRelationshipBenchmarkFixture ;
mode : KtxRelationshipBenchmarkMode ;
2026-05-10 23:12:26 +02:00
reason : string ;
2026-05-10 23:51:24 +02:00
} ) : KtxRelationshipBenchmarkReportCase {
2026-05-10 23:12:26 +02:00
return {
fixtureId : input.fixture.id ,
fixtureName : input.fixture.name ,
tier : input.fixture.tier ,
mode : input.mode ,
status : 'not_run' ,
reason : input.reason ,
tuningEligible : false ,
metrics : {
pkRecall : null ,
fkRecall : null ,
acceptedOrReviewRecall : null ,
acceptedFalsePositiveCount : null ,
sqlQueries : null ,
llmCalls : null ,
runtimeSeconds : null ,
} ,
falsePositives : { pk : [ ] , fk : [ ] } ,
falseNegatives : { pk : [ ] , fk : [ ] } ,
skippedComposite : { pk : [ ] , fk : [ ] } ,
} ;
}
2026-05-10 23:51:24 +02:00
export function buildKtxRelationshipBenchmarkReport ( input : {
fixtures : readonly KtxRelationshipBenchmarkFixture [ ] ;
suite : KtxRelationshipBenchmarkSuiteResult ;
modes : readonly KtxRelationshipBenchmarkMode [ ] ;
2026-05-10 23:12:26 +02:00
generatedAt? : string ;
2026-05-10 23:51:24 +02:00
} ) : KtxRelationshipBenchmarkReport {
2026-05-10 23:12:26 +02:00
const resultsByKey = new Map ( input . suite . cases . map ( ( result ) = > [ key ( result . fixtureId , result . mode ) , result ] ) ) ;
2026-05-10 23:51:24 +02:00
const cases : KtxRelationshipBenchmarkReportCase [ ] = [ ] ;
2026-05-10 23:12:26 +02:00
for ( const fixture of input . fixtures ) {
const selectedModes = new Set ( fixture . defaultModes ) ;
for ( const mode of input . modes ) {
const result = resultsByKey . get ( key ( fixture . id , mode ) ) ;
if ( result ) {
cases . push ( reportCaseFromResult ( { fixture , mode , result } ) ) ;
continue ;
}
cases . push (
notRunCase ( {
fixture ,
mode ,
reason : selectedModes.has ( mode ) ? 'mode produced no benchmark result' : 'mode not selected by fixture defaultModes' ,
} ) ,
) ;
}
}
return {
generatedAt : input.generatedAt ? ? new Date ( ) . toISOString ( ) ,
headline : {
caseCount : input.suite.aggregate.caseCount ,
headlineCaseCount : input.suite.aggregate.headlineCaseCount ,
headlinePkRecall : input.suite.aggregate.headlinePkRecall ,
headlineFkRecall : input.suite.aggregate.headlineFkRecall ,
headlineAcceptedOrReviewRecall : input.suite.aggregate.headlineAcceptedOrReviewRecall ,
acceptedFalsePositiveCount : input.suite.cases.reduce (
( sum , result ) = > sum + result . metrics . acceptedFalsePositiveCount ,
0 ,
) ,
validationBlockedCount : input.suite.validationBlockedCases.length ,
} ,
cases ,
} ;
}
2026-05-10 23:51:24 +02:00
type KtxRelationshipBenchmarkFailureSelector = (
item : KtxRelationshipBenchmarkReportCase ,
2026-05-10 23:12:26 +02:00
) = > readonly string [ ] ;
function sortedFailureLines ( input : {
2026-05-10 23:51:24 +02:00
cases : readonly KtxRelationshipBenchmarkReportCase [ ] ;
select : KtxRelationshipBenchmarkFailureSelector ;
2026-05-10 23:12:26 +02:00
} ) : string [ ] {
return input . cases
. flatMap ( ( item ) = >
input . select ( item ) . map ( ( value ) = > ( {
fixtureId : item.fixtureId ,
mode : item.mode ,
status : item.status ,
value ,
} ) ) ,
)
. sort ( ( left , right ) = > {
const leftKey = ` ${ left . fixtureId } : ${ left . mode } : ${ left . status } : ${ left . value } ` ;
const rightKey = ` ${ right . fixtureId } : ${ right . mode } : ${ right . status } : ${ right . value } ` ;
return leftKey . localeCompare ( rightKey ) ;
} )
. map ( ( item ) = > ` - \` ${ item . fixtureId } \` / \` ${ item . mode } \` / \` ${ item . status } \` : ${ item . value } ` ) ;
}
function failureBlock ( input : {
title : string ;
2026-05-10 23:51:24 +02:00
cases : readonly KtxRelationshipBenchmarkReportCase [ ] ;
select : KtxRelationshipBenchmarkFailureSelector ;
2026-05-10 23:12:26 +02:00
} ) : string [ ] {
const values = sortedFailureLines ( { cases : input.cases , select : input.select } ) ;
return [ '' , ` ### ${ input . title } ` , '' , . . . ( values . length > 0 ? values : [ '- none' ] ) ] ;
}
2026-05-10 23:51:24 +02:00
function headlineFailureContextBlocks ( report : KtxRelationshipBenchmarkReport ) : string [ ] {
2026-05-10 23:12:26 +02:00
const headlineCases = report . cases . filter ( ( item ) = > item . tuningEligible ) ;
const remainingPkMisses = sortedFailureLines ( {
cases : headlineCases ,
select : ( item ) = > item . falseNegatives . pk ,
} ) ;
const remainingFkMisses = sortedFailureLines ( {
cases : headlineCases ,
select : ( item ) = > item . falseNegatives . fk ,
} ) ;
return [
'' ,
'## Headline Failure Context' ,
'' ,
'Remaining headline misses after this run are listed here so recall gains and still-open algorithmic gaps are visible in the regenerated evidence report.' ,
'' ,
` - Remaining headline false-negative PKs: ${ remainingPkMisses . length } ` ,
` - Remaining headline false-negative FKs: ${ remainingFkMisses . length } ` ,
'' ,
'### Remaining Headline False Negative PKs' ,
'' ,
. . . ( remainingPkMisses . length > 0 ? remainingPkMisses : [ '- none' ] ) ,
'' ,
'### Remaining Headline False Negative FKs' ,
'' ,
. . . ( remainingFkMisses . length > 0 ? remainingFkMisses : [ '- none' ] ) ,
] ;
}
2026-05-10 23:51:24 +02:00
function failureDetailBlocks ( report : KtxRelationshipBenchmarkReport ) : string [ ] {
2026-05-10 23:12:26 +02:00
const headlineCases = report . cases . filter ( ( item ) = > item . tuningEligible ) ;
const otherCases = report . cases . filter ( ( item ) = > ! item . tuningEligible ) ;
return [
'' ,
'## Failure Details' ,
. . . failureBlock ( {
title : 'Headline False Positive PKs' ,
cases : headlineCases ,
select : ( item ) = > item . falsePositives . pk ,
} ) ,
. . . failureBlock ( {
title : 'Headline False Positive FKs' ,
cases : headlineCases ,
select : ( item ) = > item . falsePositives . fk ,
} ) ,
. . . failureBlock ( {
title : 'Headline False Negative PKs' ,
cases : headlineCases ,
select : ( item ) = > item . falseNegatives . pk ,
} ) ,
. . . failureBlock ( {
title : 'Headline False Negative FKs' ,
cases : headlineCases ,
select : ( item ) = > item . falseNegatives . fk ,
} ) ,
. . . failureBlock ( {
title : 'Other False Positive PKs' ,
cases : otherCases ,
select : ( item ) = > item . falsePositives . pk ,
} ) ,
. . . failureBlock ( {
title : 'Other False Positive FKs' ,
cases : otherCases ,
select : ( item ) = > item . falsePositives . fk ,
} ) ,
. . . failureBlock ( {
title : 'Other False Negative PKs' ,
cases : otherCases ,
select : ( item ) = > item . falseNegatives . pk ,
} ) ,
. . . failureBlock ( {
title : 'Other False Negative FKs' ,
cases : otherCases ,
select : ( item ) = > item . falseNegatives . fk ,
} ) ,
] ;
}
2026-05-10 23:51:24 +02:00
function compositeSkipBlocks ( report : KtxRelationshipBenchmarkReport ) : string [ ] {
2026-05-10 23:12:26 +02:00
const headlineCases = report . cases . filter ( ( item ) = > item . tuningEligible ) ;
return [
'' ,
'## Composite Ground Truth Skips' ,
. . . failureBlock ( {
title : 'Skipped Composite PKs' ,
cases : headlineCases ,
select : ( item ) = > item . skippedComposite . pk ,
} ) ,
. . . failureBlock ( {
title : 'Skipped Composite FKs' ,
cases : headlineCases ,
select : ( item ) = > item . skippedComposite . fk ,
} ) ,
] ;
}
2026-05-10 23:51:24 +02:00
export function formatKtxRelationshipBenchmarkReportMarkdown ( report : KtxRelationshipBenchmarkReport ) : string {
2026-05-10 23:12:26 +02:00
const lines = [
2026-05-10 23:51:24 +02:00
'# KTX Relationship Discovery Benchmark Evidence' ,
2026-05-10 23:12:26 +02:00
'' ,
` Generated: ${ report . generatedAt } ` ,
'' ,
'## Headline' ,
'' ,
` - Cases run: ${ report . headline . caseCount } ` ,
` - Headline cases: ${ report . headline . headlineCaseCount } ` ,
` - Headline PK recall: ${ fixed ( report . headline . headlinePkRecall ) } ` ,
` - Headline FK recall: ${ fixed ( report . headline . headlineFkRecall ) } ` ,
` - Headline accepted-or-review recall: ${ fixed ( report . headline . headlineAcceptedOrReviewRecall ) } ` ,
` - Accepted false positives: ${ report . headline . acceptedFalsePositiveCount } ` ,
` - Validation-blocked cases: ${ report . headline . validationBlockedCount } ` ,
'' ,
'## Cases' ,
'' ,
'| Fixture | Tier | Mode | Status | Tuning Eligible | PK Recall | FK Recall | Accepted+Review Recall | Accepted FP | Reason |' ,
'| --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: | --- |' ,
] ;
for ( const item of report . cases ) {
lines . push (
[
` | ${ item . fixtureId } ` ,
item . tier ,
item . mode ,
item . status ,
item . tuningEligible ? 'yes' : 'no' ,
fixed ( item . metrics . pkRecall ) ,
fixed ( item . metrics . fkRecall ) ,
fixed ( item . metrics . acceptedOrReviewRecall ) ,
String ( item . metrics . acceptedFalsePositiveCount ? ? '-' ) ,
` ${ item . reason ? ? '' } | ` ,
] . join ( ' | ' ) ,
) ;
}
lines . push ( . . . headlineFailureContextBlocks ( report ) ) ;
lines . push ( . . . failureDetailBlocks ( report ) ) ;
lines . push ( . . . compositeSkipBlocks ( report ) ) ;
lines . push ( '' ) ;
return ` ${ lines . join ( '\n' ) } \ n ` ;
}