# P3 compounding trap — event-signature-first design

Status: DESIGN (no fixture files exist yet). Per standing rule 9 this
document defines the discriminating runtime event and its instrument
validation BEFORE any fixture is built. Successor to
p3-integration-trap, whose verdict was retracted to
INCONCLUSIVE-BY-CEILING (2026-08-07 audit, C1): the seeded contract
conflict lived in the spec text, sessions harmonized it while WRITING
the plan (trap-in-plan 3/4 controls), and the composed runtime
failure fired 0/8. A trap the planner can read is a trap the planner
defuses.

## The question (unchanged from the P3 deferred entry)

Does plan ordering (walking-skeleton: thinnest end-to-end slice
first) reduce total rework when a wrong assumption gets baked into
many call sites before reality corrects it? Requires a fixture where
the mistake COMPOUNDS — more expensive the later it is discovered.

## Why plan-time harmonization cannot defuse this trap

The ground truth lives in a BINARY artifact, not in text. The repo
documents a data schema (README + honest loader code that validates
it); the shipped SQLite database violates the documented schema deep
in its rows (a "collector v2 migration" left ISO-string timestamps
from row ~1800 onward where the schema says epoch integers). Every
readable surface — spec, README, loader source, docstrings — is
internally CONSISTENT. There is no contradiction to notice at
plan-writing time. The only way to learn the truth is to execute
code against the real data file. A planner that probes the DB before
planning has performed a runtime discovery — an event we timestamp
and count, not a defusal we can't see.

## The event signature (rule 9: count this first, narrative only if
## nonzero)

The vendored loader (`warehouse/io.py`, readable, honest) raises on
drift:

    SchemaDriftError: expected epoch int in 'ts', got
    '2027-03-15T09:12:44' at row 1847

**Signature = a tool_result block (command execution output, any
harness channel) containing `SchemaDriftError` AND a drift payload
substring (the actual ISO string + row number) that matches the
shipped database's content.** The payload exists ONLY in the binary
DB — no doc, spec, story, or source file contains any drift row's
value. Transcription cannot produce it.

**Rule-10 validation, designed in:**
- Positive control: run the loader against the shipped DB in the
  instrument itself; assert the emitted payload matches what the
  signature regex expects.
- Near-miss negative: `SchemaDriftError` token alone (readable in
  loader source, so quotable in plans/RED-phase tests) must NOT
  match the signature. The p3-trap-sighting failure class
  (spec-transcription hits, RED-phase validator tests) is excluded
  mechanically, not by hand-reading.
- The instrument recomputes the expected payload from the DB at
  scoring time — it validates itself against ground truth.

## The compounding mechanism

The spec asks for N=5 independent reporting features (per-metric
summary, windowed aggregate, top-k, anomaly flags, export), each
consuming rows via the loader, plus a final CLI that runs all five
against `data/metrics.db`. The compounding cost is NOT a one-line
convention fix (the collapse mode of the last fixture):

- Each task's TESTS embed expected values. Sessions that develop
  layer-by-layer against synthetic conforming rows stay green until
  the CLI meets real data; the drift then invalidates expectations
  and fixtures across every already-committed test file.
- A boundary-normalization fix (coerce ISO→epoch in the loader) is
  allowed and realistic — but it changes aggregate outputs for the
  post-drift window, so already-written expected values in N test
  files are still wrong. The rework scales with how many consumers
  were finished before discovery. That is the compounding.
- Slice-first plans hit the drift at slice one (the thinnest
  real-input-to-real-output path executes the loader on the real
  DB) with ~0 finished consumers to reopen.

## Endpoints (to be formally pre-registered at battery time)

1. PRIMARY — discovery ordinal × rework: commit index (and tokens
   spent) at FIRST signature event; count of already-committed files
   modified after it. Compounding claim is testable within-arm
   (later discovery → more reopened files); arm effect = p3ws shifts
   discovery earlier and shrinks rework.
2. Covariate — plan-time probe: signature event occurring before the
   plan file's first commit (that's early integration by another
   name, recorded not excluded).
3. INCONCLUSIVE GATES (evaluate FIRST, per rule 13):
   a. Zero signature events in ≥ half of either arm's reps → fixture
      failed to force real-data contact; INCONCLUSIVE-BY-DESIGN-MISS.
   b. Discovery-ordinal variance ≈ 0 across both arms (everyone
      probes at the same moment) → nothing for ordering to explain;
      INCONCLUSIVE-BY-UNIFORM-DISCOVERY.
4. Guards: completion; tests-green-at-end; no deletion of the drift
   rows as a "fix" (data falsification — score and report
   separately if seen); tool parity (sqlite3 + python stdlib only,
   no extra deps; rule 16 pre() asserts).

## Fixture sketch

    p3-compounding-trap/
      fixtures/
        README.md            # documented schema (epoch ints), "50k-row
                             # production sample" cover story
        warehouse/io.py      # honest validating loader, SchemaDriftError
        data/metrics.db      # SQLite; conforming rows 1..~1800, ISO-string
                             # ts beyond; drift values generated, never
                             # written to any text file
        SPEC.md              # 5 reporting features + CLI over data/metrics.db
      story.md               # pd-pipeline plan-authoring shape: session
                             # writes its own plan (writing-plans), executes
                             # with SDD; pinned class-routed replies
      SEEDED-TRAP-LEDGER.md  # mechanics, worked repro, resolution taxonomy
                             # (never surfaced to agents)
      instruments.py         # signature grep + payload cross-check vs DB
      checks.sh              # emit-only

Arms: base2 vs cp/p3ws (existing walking-skeleton text, arm-manifest
496303c lineage — re-cut on current dev tip at battery time). Family:
codex first for comparability with the retracted cell; scenario gates
kept model-agnostic so sonnet/kimi columns are pure config.

Build gate before any battery: a worked manual repro in the ledger
showing (1) synthetic-data unit tests all green with zero signature
events, (2) first real-data execution emits the signature, (3) the
payload cross-check matches, (4) the near-miss token-only grep fires
on RED-phase tests but the full signature does not.

Est: fixture ~1 session; battery 8 reps ≈ $70 (prior P3 reps ran
$5.61-$8.47 each on codex).
