Skip to content

Commit c7f1975

Browse files
committed
docs: address reviewer methodology concerns
1 parent fcf2a9d commit c7f1975

26 files changed

Lines changed: 530 additions & 206 deletions

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The Agentic Epistemology Framework (AEF) provides a principled approach to model
1313
- **Facet Influence Ledger**: Records selected facets, prompt hashes, runtime weights, marker coverage, contradictions, and recommended debug actions.
1414
- **Counterfactual Diagnosis**: Supports facet removal/swap probes to estimate whether persona behavior changes in the expected direction.
1515
- **Observer Pattern**: Comprehensive tracing of epistemic events for transparency and debugging.
16-
- **Public Benchmarks**: Deterministic benchmark harnesses for root-cause diagnosis, facet-frame faithfulness, and the AEF audit service.
16+
- **Public Harnesses**: Deterministic trace-sensitivity harnesses for root-cause diagnosis, facet-frame faithfulness, and the AEF audit service.
1717

1818
## Installation
1919

@@ -28,11 +28,11 @@ npm run build
2828

2929
## Getting Started
3030

31-
Run the public benchmarks:
31+
Run the public harnesses:
3232

3333
```bash
3434
npx ts-node --transpile-only examples/root-cause-benchmark.ts --seed=42 --cases=160
35-
npx ts-node --transpile-only examples/facet-frame-faithfulness-benchmark.ts --seed=42 --cases=200
35+
npx ts-node --transpile-only examples/facet-frame-faithfulness-benchmark.ts --seed=42 --seed-count=20 --cases=200
3636
npx ts-node --transpile-only examples/facet-faithfulness-audit-experiment.ts
3737
```
3838

benchmarks/README.md

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
# AEF Public Benchmarks
1+
# AEF Public Harnesses
22

3-
This directory documents the reproducible benchmark harnesses included with the Agentic Epistemology Framework.
3+
This directory documents the reproducible trace-sensitivity harnesses included with the Agentic Epistemology Framework.
44

5-
The benchmark code lives in `examples/` so it can run directly against the TypeScript source without a package publish step.
5+
The harness code lives in `examples/` so it can run directly against the TypeScript source without a package publish step.
66

7-
## Benchmarks
7+
## Harnesses
88

9-
### 1. Generic root-cause benchmark
9+
### 1. Generic root-cause harness
1010

1111
Tests whether structured epistemic traces expose fields needed to localize injected agent failure labels in a deterministic harness.
1212

@@ -28,14 +28,14 @@ results/root-cause-benchmark/
2828
└── accuracy-by-condition.svg
2929
```
3030

31-
Primary metric: diagnosis accuracy by trace condition.
31+
Primary metric: diagnosis accuracy by trace condition. This is an information-availability check, not an external-validity estimate.
3232

33-
### 2. Facet-frame faithfulness benchmark
33+
### 2. Facet-frame faithfulness harness
3434

35-
Tests whether facet-aware traces improve diagnosis of synthetic persona failures such as facet omission, facet misweighting, facet conflict, persona drift, and response-style violation.
35+
Tests whether facet-aware traces expose fields needed to localize synthetic persona failures such as facet omission, facet misweighting, facet conflict, persona drift, and response-style violation.
3636

3737
```bash
38-
npx ts-node --transpile-only examples/facet-frame-faithfulness-benchmark.ts --seed=42 --cases=200
38+
npx ts-node --transpile-only examples/facet-frame-faithfulness-benchmark.ts --seed=42 --seed-count=20 --cases=200
3939
```
4040

4141
Outputs:
@@ -46,15 +46,17 @@ results/facet-frame-faithfulness/
4646
├── metrics.json
4747
├── metrics.csv
4848
├── metrics-table.tex
49+
├── metrics-summary.json
50+
├── metrics-summary-table.tex
4951
├── qualitative-example.json
5052
└── accuracy-by-condition.svg
5153
```
5254

53-
Primary metric: diagnosis accuracy and macro F1 by trace condition.
55+
Primary metrics: diagnosis accuracy, macro F1, and coverage by trace condition.
5456

55-
### 3. Facet faithfulness audit service experiment
57+
### 3. Facet faithfulness audit service case study
5658

57-
Tests the implemented `FacetFaithfulnessAuditService` on Vurvey-style persona cases with prompt provenance, marker coverage, contradictions, counterfactual sensitivity, calibration, and signal-to-noise scoring.
59+
Tests the implemented `FacetFaithfulnessAuditService` on Vurvey-style persona fixtures with prompt provenance, marker coverage, contradictions, counterfactual sensitivity, and calibration scoring.
5860

5961
```bash
6062
npx ts-node --transpile-only examples/facet-faithfulness-audit-experiment.ts
@@ -68,20 +70,22 @@ results/facet-faithfulness-audit-experiment/
6870
├── audits.json
6971
├── metrics.json
7072
├── metrics-table.tex
71-
└── diagnosis-accuracy.svg
73+
├── calibration.json
74+
├── calibration-table.tex
75+
└── calibration.svg
7276
```
7377

74-
Primary metric: diagnosis accuracy by evidence condition.
78+
Primary metric: diagnosis accuracy by evidence condition. The calibration artifacts are a fixture sanity check, not a deployment reliability diagram.
7579

7680
## Reproducibility notes
7781

78-
- All public benchmark inputs are synthetic fixtures.
82+
- All public harness inputs are synthetic fixtures.
7983
- The harnesses require no Vurvey credentials, no private database, and no model API calls.
8084
- The Vurvey real-generation counterfactual results included in the paper are reported only as sanitized aggregates under `results/vurvey-*`; raw persona text and raw database fixture rows are intentionally excluded.
8185

8286
## Current reference results
8387

84-
### Generic root-cause benchmark
88+
### Generic root-cause harness
8589

8690
| Condition | Accuracy | Macro F1 | Coverage |
8791
|---|---:|---:|---:|
@@ -90,33 +94,32 @@ Primary metric: diagnosis accuracy by evidence condition.
9094
| no_justification | 0.500 | 0.500 | 0.500 |
9195
| event_only | 0.000 | 0.000 | 0.000 |
9296

93-
### Facet-frame faithfulness benchmark
97+
### Facet-frame faithfulness harness
9498

9599
| Condition | Accuracy | Macro F1 | Coverage |
96100
|---|---:|---:|---:|
97-
| full | 0.865 | 0.898 | 0.865 |
98-
| no_facet_weights | 0.665 | 0.678 | 0.735 |
101+
| full | 1.000 | 1.000 | 1.000 |
102+
| no_facet_weights | 0.800 | 0.772 | 0.866 |
99103
| no_facet_prompts | 0.400 | 0.400 | 0.400 |
100104
| event_only | 0.000 | 0.000 | 0.000 |
101105

102-
### Facet faithfulness audit service experiment
106+
### Facet faithfulness audit service case study
103107

104108
| Condition | Accuracy | Faithfulness | Marker Coverage | Counterfactual |
105109
|---|---:|---:|---:|---:|
106-
| prompt_only | 0.125 | 0.162 | 0.000 | 0.500 |
110+
| response_only | 0.125 | 0.162 | 0.000 | 0.500 |
107111
| facet_list | 0.125 | 0.382 | 0.000 | 0.500 |
108-
| facet_weights | 0.750 | 0.526 | 0.281 | 0.500 |
112+
| facet_markers_weights | 0.750 | 0.526 | 0.281 | 0.500 |
109113
| full_aef | 1.000 | 0.536 | 0.281 | 0.660 |
110114

111-
## How to add a new benchmark
115+
## How to add a new harness
112116

113-
1. Add a new `examples/<benchmark-name>.ts` runner.
117+
1. Add a new `examples/<harness-name>.ts` runner.
114118
2. Make it deterministic by accepting `--seed`.
115-
3. Write outputs under `results/<benchmark-name>/`.
119+
3. Write outputs under `results/<harness-name>/`.
116120
4. Include at least `cases.json`, `metrics.json`, and a qualitative example.
117121
5. Add a short section to this README with the command and expected outputs.
118122

119-
120123
## Reviewer caveat
121124

122125
These public harnesses are deterministic trace-sensitivity tests. They are not external-validity estimates for deployed personas. Use them to check that a trace schema carries enough information for a diagnoser, then validate real persona behavior with independent labels, noisy traces, and live model outputs.

examples/custom-frame-example.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
FrameRegistry,
1515
createFrameConfig,
1616
getFrameSystemInfo,
17-
initializeFrameSystem
17+
initializeFrameSystem,
18+
ObservationJustificationElement
1819
} from '../src/epistemic';
1920

2021
// ============================================================================
@@ -179,7 +180,7 @@ class DevilsAdvocateFrame extends ComposableBaseFrame implements IDebateFrame {
179180
try {
180181
// Get base strength evaluation
181182
const baseStrength = await this.llmProvider.judgeEvidenceStrength(
182-
{ id: '', type: 'argument', content: argument, source: 'debate' },
183+
new ObservationJustificationElement('debate', { argument }),
183184
debateContext.topic
184185
);
185186

@@ -322,7 +323,8 @@ export function exampleUsage(): void {
322323
// ============================================================================
323324
324325
// 1. Initialize the frame system (once at startup)
325-
import { initializeFrameSystem } from '../src/epistemic';
326+
import { initializeFrameSystem ObservationJustificationElement
327+
} from '../src/epistemic';
326328
import { registerCustomFrames, createOptimismFrame } from './custom-frame-example';
327329
328330
initializeFrameSystem();

examples/facet-faithfulness-audit-experiment.ts

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Failure =
1212
| 'response_style_violation'
1313
| 'low_counterfactual_sensitivity';
1414

15-
type Condition = 'prompt_only' | 'facet_list' | 'facet_weights' | 'full_aef';
15+
type Condition = 'response_only' | 'facet_list' | 'facet_markers_weights' | 'full_aef';
1616

1717
interface Scenario {
1818
id: string;
@@ -30,6 +30,14 @@ interface MetricRow {
3030
meanCalibrationScore: number;
3131
}
3232

33+
interface CalibrationRow {
34+
bin: string;
35+
count: number;
36+
meanConfidence: number;
37+
meanFaithfulness: number;
38+
absoluteGap: number;
39+
}
40+
3341
const service = new FacetFaithfulnessAuditService();
3442

3543
const crisisFacet = (): FacetAuditFacet => ({
@@ -203,7 +211,7 @@ function scenarios(): Scenario[] {
203211

204212
function applyCondition(input: FacetAuditInput, condition: Condition): FacetAuditInput {
205213
if (condition === 'full_aef') return input;
206-
if (condition === 'facet_weights') {
214+
if (condition === 'facet_markers_weights') {
207215
return { ...input, renderedPrompt: undefined, counterfactuals: undefined };
208216
}
209217
if (condition === 'facet_list') {
@@ -234,10 +242,75 @@ function round(value: number): number {
234242
return Math.round(value * 1000) / 1000;
235243
}
236244

245+
function calibrationRows(cases: Scenario[]): CalibrationRow[] {
246+
const bins = [
247+
{ label: '0.00-0.33', min: 0, max: 0.33 },
248+
{ label: '0.34-0.66', min: 0.34, max: 0.66 },
249+
{ label: '0.67-1.00', min: 0.67, max: 1 },
250+
];
251+
const audits = cases.map((item) => ({ item, audit: service.audit(item.input) }));
252+
return bins.map((bin) => {
253+
const matching = audits.filter(({ item }) => {
254+
const confidence = item.input.selfReportedConfidence ?? 0;
255+
return confidence >= bin.min && confidence <= bin.max;
256+
});
257+
if (matching.length === 0) {
258+
return { bin: bin.label, count: 0, meanConfidence: 0, meanFaithfulness: 0, absoluteGap: 0 };
259+
}
260+
const meanConfidence = mean(matching.map(({ item }) => item.input.selfReportedConfidence ?? 0));
261+
const meanFaithfulness = mean(matching.map(({ audit }) => audit.faithfulnessScore));
262+
return {
263+
bin: bin.label,
264+
count: matching.length,
265+
meanConfidence: round(meanConfidence),
266+
meanFaithfulness: round(meanFaithfulness),
267+
absoluteGap: round(Math.abs(meanConfidence - meanFaithfulness)),
268+
};
269+
});
270+
}
271+
272+
function calibrationLatex(rows: CalibrationRow[]): string {
273+
return [
274+
'\\begin{tabular}{lrrrr}',
275+
'\\toprule',
276+
'Confidence bin & Count & Mean confidence & Mean faithfulness & Gap \\\\',
277+
'\\midrule',
278+
...rows.map((row) => `${row.bin} & ${row.count} & ${row.meanConfidence.toFixed(3)} & ${row.meanFaithfulness.toFixed(3)} & ${row.absoluteGap.toFixed(3)} \\\\`),
279+
'\\bottomrule',
280+
'\\end{tabular}',
281+
'',
282+
].join('\n');
283+
}
284+
285+
function writeCalibrationFigure(rows: CalibrationRow[], outputPath: string): void {
286+
const width = 640;
287+
const height = 420;
288+
const margin = { left: 80, right: 40, top: 40, bottom: 70 };
289+
const plotWidth = width - margin.left - margin.right;
290+
const plotHeight = height - margin.top - margin.bottom;
291+
const points = rows.filter((row) => row.count > 0).map((row) => {
292+
const x = margin.left + row.meanConfidence * plotWidth;
293+
const y = margin.top + plotHeight - row.meanFaithfulness * plotHeight;
294+
return `<circle cx="${x}" cy="${y}" r="8" fill="#0072B2" />\n<text x="${x + 10}" y="${y - 10}" font-size="12">${row.bin} (n=${row.count})</text>`;
295+
}).join('\n');
296+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
297+
<rect width="100%" height="100%" fill="white"/>
298+
<text x="${width / 2}" y="24" text-anchor="middle" font-size="18" font-family="Arial">Calibration: confidence vs. measured faithfulness</text>
299+
<line x1="${margin.left}" y1="${margin.top + plotHeight}" x2="${width - margin.right}" y2="${margin.top}" stroke="#999" stroke-dasharray="5,5" />
300+
<line x1="${margin.left}" y1="${margin.top}" x2="${margin.left}" y2="${margin.top + plotHeight}" stroke="#333" />
301+
<line x1="${margin.left}" y1="${margin.top + plotHeight}" x2="${width - margin.right}" y2="${margin.top + plotHeight}" stroke="#333" />
302+
<text x="${margin.left + plotWidth / 2}" y="${height - 25}" text-anchor="middle" font-size="14">Self-reported confidence</text>
303+
<text transform="translate(24,${margin.top + plotHeight / 2}) rotate(-90)" text-anchor="middle" font-size="14">Measured faithfulness</text>
304+
${points}
305+
</svg>\n`;
306+
fs.writeFileSync(outputPath, svg);
307+
}
308+
237309

238310
function run(): void {
239311
const cases = scenarios();
240-
const conditions: Condition[] = ['prompt_only', 'facet_list', 'facet_weights', 'full_aef'];
312+
const calibration = calibrationRows(cases);
313+
const conditions: Condition[] = ['response_only', 'facet_list', 'facet_markers_weights', 'full_aef'];
241314
const metrics: MetricRow[] = conditions.map((condition) => {
242315
const results = cases.map((item) => {
243316
const audit = service.audit(applyCondition(item.input, condition));
@@ -260,6 +333,9 @@ function run(): void {
260333
fs.writeFileSync(path.join(outDir, 'metrics.json'), JSON.stringify(metrics, null, 2));
261334
fs.writeFileSync(path.join(outDir, 'cases.json'), JSON.stringify(cases, null, 2));
262335
fs.writeFileSync(path.join(outDir, 'audits.json'), JSON.stringify(cases.map((item) => ({ id: item.id, expectedFailure: item.expectedFailure, audit: service.audit(item.input) })), null, 2));
336+
fs.writeFileSync(path.join(outDir, 'calibration.json'), JSON.stringify(calibration, null, 2));
337+
fs.writeFileSync(path.join(outDir, 'calibration-table.tex'), calibrationLatex(calibration));
338+
writeCalibrationFigure(calibration, path.join(outDir, 'calibration.svg'));
263339
fs.writeFileSync(path.join(outDir, 'metrics-table.tex'), [
264340
'\\begin{tabular}{lrrrrr}',
265341
'\\toprule',
@@ -271,7 +347,7 @@ function run(): void {
271347
'',
272348
].join('\n'));
273349

274-
console.log(JSON.stringify({ metrics, outDir }, null, 2));
350+
console.log(JSON.stringify({ metrics, calibration, outDir }, null, 2));
275351
}
276352

277353
run();

0 commit comments

Comments
 (0)