DR-102: schema-coverage merges external evidence via sidecar files; declarations are never write proof
DR-102: schema-coverage merges external evidence via sidecar files; declarations are never write proof
Section titled “DR-102: schema-coverage merges external evidence via sidecar files; declarations are never write proof”Context
Section titled “Context”schema-coverage’s verdicts were TypeScript-only; the Python pipeline, its
cocoindex declarative writes (TableSchema/mount_table_target/
declare_row), and the l_records const-SQL layer were static caveats. The
initiative-12 census rule requires wiring verdicts to cover TS chains +
Python + declaratives (+ a pg_proc/migrations scan). Joining the surfaces
needed both a transport (how external evidence reaches the TS verdict
engine) and a semantics (what a data-declared schema column proves).
Shipped in PR #150 ({377.4}).
Decision
Section titled “Decision”External evidence merges through a versioned sidecar file contract
(v1: {schemaVersion: 1, source, rows: [{table, column|"*", direction, confidence, method, file, line, source}]}) consumed by
schema-coverage --evidence <path> (repeatable). Verdict rules are
unchanged by merging — evidence changes, not the rules. Declaration is
never write proof: schema-declaration rows (method table-schema) are
emitted at indirect confidence only, so a declared-but-never-written
column verdicts undecidable, never wired/write-only; only observed
write payloads (declare_row keys, SQL, chain payloads) can be exact.
Table-scoped * rows merge as wildcard-reads / indirect-writes (smoke,
not proof).
Alternatives Considered
Section titled “Alternatives Considered”- Count declarations as writes — rejected on corpus evidence: flow.py
declares source_documents columns “for schema completeness” it
deliberately never populates, and
sd_targetis mounted but written via raw SQL with 26 columns against 22 declared. Declarations lie in both directions. - A new “declared” confidence tier — rejected: it ripples through the envelope types and every consumer; mapping declaration→indirect produces the correct verdicts through the existing engine unchanged.
- In-process/shell-out integration (TS invokes the Python scanner) — deferred, not adopted: sidecar files keep the runtimes decoupled, make any extractor in any language a first-class producer (pg_proc scan, Prisma/Drizzle adapters) without touching the TS core, and the extraction-phase standalone can still add a one-shot convenience wrapper.
Consequences
Section titled “Consequences”- The census three-surface rule is a two-command recipe
(
ast-dataflow-py schema-uses→schema-coverage --evidence); the pg_proc/migrations scan joins by emitting the same contract ({399.1}). - Sidecars are point-in-time files: callers must regenerate them per run —
staleness is the caller’s responsibility, and merged sidecars are named
in
caveats.mergedEvidenceso a verdict’s evidence base is auditable. - Producers must be loud about blindness (unparsed/dynamic SQL, rpc
payloads, unattributable declare_row sites are caveat counts, never
silent drops); the consumer routes unknown tables/columns to
caveats.evidenceUnknownTablesinstead of crashing or dropping.