# Pairset audit and Markdown source

## Goal

Audit the hand-authored pairsets for clean contrastive construction and provenance,
decide which are useful for headline extraction versus diagnostics, and replace the
scattered hand-authored JSON/build-script sources with one or two human-readable
Markdown sources.

## Scope

In: hand-authored mechanism, intent, semantic-framing, honesty, and placebo pairsets;
their loaders/builders/recipes; pair-level audit evidence.

Out: pool-derived or oracle-labelled pair generation, changing experiment results,
and rewriting pair content before the audit identifies a specific defect.

## Requirements

- R1: Audit same-prompt, provenance, style/length confounds, and hack-axis strength.
  Done means: a per-pair table and pairset-level recommendation exist.
- R2: Distinguish no-cheat headline supervision from diagnostics and controls.
  Done means: each retained section has an explicit role and provenance.
- R3: Use at most two human-readable Markdown source files for hand-authored pairsets.
  Done means: runtime loading selects a named Markdown heading and scattered generated
  JSON is no longer the source of truth.
- R4: Fail fast on malformed Markdown or missing headings/fields.
  Done means: verification deliberately checks malformed and missing sections fail.

## Tasks

- [x] T1 (R1-R2): Audit every hand-authored pairset.
  - verify: audit table reports every pair and pairset summary.
  - success: same-prompt is universal; provenance and confounds are explicit.
  - likely_fail: a set is omitted; summary counts disagree with source counts.
  - sneaky_fail: pairset name implies an isolated axis but another systematic contrast
    dominates; manual evidence records the actual contrast.
  - UAT: open the audit and see a recommendation with reasons for each pairset.
- [x] T2 (R3-R4): Implement a minimal heading-based Markdown pair loader and sources.
  - verify: each named heading loads the expected count and exact pair bytes.
  - success: one or two Markdown files contain all hand-authored pairs.
  - likely_fail: fenced code inside completions breaks parsing; exact-byte comparison fails.
  - sneaky_fail: configs silently load the wrong heading; missing-heading test must raise.
  - UAT: one path plus heading identifies a pairset and prints its expected first pair.
- [x] T3 (R3): Update active recipes/docs and remove superseded hand-authored JSON/builders.
  - verify: repository search finds no active references to removed JSON pairsets.
  - success: active runs name Markdown sections; pool-derived JSON remains separate.
  - likely_fail: an active recipe still names removed JSON.
  - sneaky_fail: cached v_hack identity hashes the whole Markdown file instead of selected
    pair bytes; selected-pair hash verification catches this.
- [x] T4 (R1-R4): Run verification, smoke, and fresh-eyes review.
  - verify: targeted verifier and `just smoke` pass; review has no unresolved blocker.
  - UAT: linked logs and audit show the result.

## Context

- A pair is `gradient(prompt + hack) - gradient(prompt + clean)`, so prompt equality is
  structural within a pair.
- Hand-authored off-distribution pairs are no-cheat. Pool-derived or live-rollout-labelled
  pairs are not headline-clean.
- `philosophical`, `moral`, `intent_vs_spec`, and `eval_aware` currently vary semantic
  comments and test strength together, so their names overstate axis isolation.

## Log

- `pairs_authored.json` and `prog_wide_clean.json` have uncommitted user edits; preserve
  their current working-tree bytes as audit inputs.
- The current authored working-tree rows were migrated byte-exactly before deleting the
  duplicate JSON source. `prog_wide_clean.json` remains a separate generated/sensitivity
  artifact.
- No audited prompt is byte-identical to current train/eval prompts, but intent and framing
  sets overlap with several corpus problem concepts. “Not in train/test” was too strong.

## TODO

## Errors

| Task | Error | Resolution |
|---|---|---|

## Results

- Audit and recommendations: `docs/personas/pairset_audit.md`.
- Authored/manual sources: `data/pairs/hack_pairs.md` and
  `data/pairs/pair_diagnostics.md`.
- Deleted 13 duplicate manual JSON files and 3 Python data builders.
- The initial migration used `#mechanism-authored`; it was superseded by the later
  multi-view design in `docs/spec/20260610_multiview_hack_pairs.md`.

## Verify

`uv run python scripts/verify_science_invariants.py`:

| invariant | success |
|---|---|
| selected Markdown pair bytes | True |
| malformed Markdown fails | True |
| authored/control/generated pairsets load | True |
| exactly one prompt hint | True |
| deterministic disjoint val/test | True |

`just smoke`:

- Full log: `/tmp/claude-1000/pairset_markdown_smoke.log`
- routeV loaded `data/pairs/hack_pairs.md#mechanism-authored -> 11 pairs`.
- Routing band mean width `+0.354`; `13/14` modules included.
- All verify gates and the 30-step routeV smoke completed successfully.

## Failure mode check

- likely_fail: nested code fences corrupt Markdown parsing. Exact migration checks loaded all
  13 sections and matched every prior JSON row byte-for-byte. PASS.
- sneaky_fail: hash tracks the whole Markdown file or the wrong heading. The verifier mutates
  an unrelated section without changing the selected hash, then mutates the selected section
  and confirms cached-v-hack loading fails. PASS.
- malformed duplicate fields or missing headings are rejected. PASS.

## Review

Fresh-eyes external review: `docs/reviews/20260610_pairset_external.md`.

- No scientific audit, data-loss, parser, or hash findings.
- Fixed its one low-severity finding: result tables now label a Markdown pairset by
  selected heading rather than the full `hack_pairs.md#heading` reference.
