docs/adr/ADR-164-adr-corpus-gap-analysis.md
The corpus has grown to 162 ADR entries across 156 distinct files (ADR-001 through ADR-171; the 5 duplicate-number collisions / 6 displaced files originally noted here were RESOLVED by renumbering the displaced files to ADR-166…171 — see Gap Register G1). It now spans nine subsystems — signal/DSP, NN/training, ESP32 firmware, RuvSense multistatic, RuView desktop, Cognitum cogs, HOMECORE (HA reimplementation), BFLD privacy, and the streaming engine — written over roughly a year by many agent-driven sessions.
Two forces motivate a corpus-wide gap analysis now:
Proposed while their own commit-pinned Implementation-Status notes report them built and tested; 6 ADR numbers collide; 3 files have no Status header at all. An auditor reading headers would conclude "not built" for landed code, and "built/Accepted" for unvalidated capability.The detailed lens outputs and the full per-ADR census live in docs/adr/gap-analysis/ (lens-findings.md, census.md). This ADR is the authoritative summary and remediation backlog.
This ADR is the authoritative gap ledger and remediation backlog for the ADR corpus as of 2026-06-12. It does not change any subsystem behavior. It records, with cited ADR ids:
Until the Gap Register items are worked, treat the ADR Status header as advisory, not authoritative, and treat any accuracy number authored before ADR-155 landed as CLAIMED (not MEASURED) until re-derived through the post-155 leak-free validation split.
Counts are approximate (~) where a status string is non-canonical or dual-valued; the per-ADR breakdown is in census.md.
| Status bucket | Count | impl_state | Count |
|---|---|---|---|
| Accepted (incl. partial/in-progress/Phase-1 variants) | ~56 | implemented | ~36 |
| Proposed (incl. conditional/research-only) | ~88 | partial | ~50 |
| Superseded | 1 (ADR-002) | proposed-only | ~64 |
| Rejected | 1 (ADR-098) | stale-or-contradicted | 3 (029/030/031) |
| Missing / no Status header | 3 (ADR-168-proof [was 147], ADR-167-ddd [was 052], ADR-134) | unknown | 5 (034/044/167-ddd/168-proof/…) |
| Mixed/dual status in one ADR | 3 (115, 149×2, 133) | superseded | 1 (ADR-002) |
Headline: ~114 of 162 ADRs (≈70%) are decisions that never fully landed (proposed-only + partial + stale + unknown). The dominant failure mode is stale Status headers, not abandoned work.
Severity: CRITICAL (corpus integrity / tooling-breaking / life-safety / security) · HIGH · MEDIUM · LOW. Action vocabulary: implement · supersede · mark-stale · write-missing-ADR · close-as-gated · renumber · reconcile-docs.
| ID | Gap | Severity | Affected ADRs | Recommended action |
|---|---|---|---|---|
| G1 | /adr tooling) | CRITICAL | 050×2, 052×2, 147×3, 148×2, 149×2; 134 (identity split, separate) | |
| G2 | 3 files with no Status header (cannot triage) — INVESTIGATED in docs/adr-gap-remediation-1: only 2 genuinely lack one, both owner-gated | CRITICAL | ADR-168-benchmark-proof (was 147), ADR-167-ddd-appendix (was 052), | add canonical ## Status; relocate ADR-168-proof to benchmarks/; label ADR-167-ddd as appendix — NOTE: ADR-134-CIR DOES have a Status (| Status | Proposed | in its header table) — mislabeled here. The two real misses (ADR-168-benchmark-proof [was 147], ADR-167-ddd [was 052]) were inside the owner-gated duplicate-number collisions (147×3, 052×2); those collisions are now resolved (G1) but the missing Status headers themselves remain owner-gated, so left untouched pending owner. The early ADRs (048/049/068/070 etc.) use | Status | not | **Status** | — different-format-but-present, not missing. Net: 0 headers added. |
| G3 | docs/adr-gap-remediation-1 | CRITICAL | homecore-recorder→"ADR-132" (no file); homecore-migrate→"ADR-134" (file is CIR) | |
| G4 | Anti-slop retractions: accuracy/security/function provably false until sweep landed | CRITICAL | 155, 154, 079, 161 (see Contradictions) | already fixed in-code by 154/155/161/162; this ledger records the retraction |
| G5 | Proposed while §Impl-Status reports Built + commits + testsdocs/adr-gap-remediation-1 | HIGH | 136–145 | |
| G6 | Stale Proposed headers on built+published code | HIGH | 029/030/031, 095/096, 152, 154–157, 024/027/072, 150 | mark-stale; reconcile with downstream/CLAUDE.md evidence |
| G7 | Status-graph inversion: Accepted ADR depends on Proposed parent | HIGH | 032→029/030/031; 053→052; 048→045; 077→075/076; 104→103 | promote parents to match built reality, or downgrade dependents |
| G8 | ADR-002 supersession not reciprocated by successors; 5 children stranded | HIGH | 002→016/017; children 003/007/008/009/010 | reconcile-docs (add reciprocal language or downgrade); split 002 to "partially superseded" |
| G9 | Streaming-engine integrator crate has no governing ADR (composition/back-pressure/live-path seam) | HIGH | wifi-densepose-engine (composes 135–146) | write-missing-ADR |
| G10 | CLAUDE.md doc-vs-header drift (doc says one status, header another) | HIGH | 017, 024, 027, 072, 152 | reconcile-docs |
| G11 | fix/adr-080-sensing-server-security) | HIGH | 080 (XFF bypass, leaked stack traces, JWT-in-URL CWE-598) | wifi-densepose-sensing-server. #2 leaked errors was the one live exposure — 6 main.rs handlers serialized internal Display/JoinError into response bodies; fixed via a new error_response module (generic body + correlation id, detail logged server-side only). #1 XFF and #3 JWT-in-URL were verified absent on the Rust boundary (no IP-rate-limit/allowlist reads XFF; token is header-only, WS handlers take no query token) and pinned with regression tests that fail if either is re-introduced. ADR-080 P0 §1–3 marked RESOLVED. |
| G12 | ADR-052→054 edge unacknowledged by successor; likely mis-modeled (impl, not replacement) | MEDIUM | 052-tauri, 054 | reconcile-docs (054 is the impl plan for 052, not a replacement) |
| G13 | Capability governed only by remediation/deploy ADR, no creation/architecture ADR | MEDIUM | wasm-edge (only 160/163); occworld-candle (147 blessed Python path only); pointcloud (094 = viewer deploy only) | write-missing-ADR (taxonomy/ABI for wasm-edge; Candle backend swap; pointcloud data contract) |
| G14 | Conflicting decisions on one topic, none superseding the others | MEDIUM | person-count 037/075/103; PQ-sign 007/109; fed key-exchange 107/108; provisioning 050/060/052; audit 010/028; RVF-WASM 009-vs-shipped | reconcile (pick one, supersede the rest) |
| G15 | ~50 Proposed-forever chains pollute every gap analysis | MEDIUM | 003/007–010, 105–109, 118–125, HOMECORE 124–133, 033/046/049/067/074/085 | close-as-gated or mark Deferred/Rejected + open tracking issues |
| G16 | De-facto supersessions never recorded (lifecycle graph incomplete) | MEDIUM | 098/099, 063/064, 042/153, 050/060, 035/023, 100/109, 117 retracts PyPI v1.1.0 | reconcile (add supersedes/superseded_by fields) |
| G17 | Accepted but no implementation evidence ("unverified done") | MEDIUM | 034 (FieldView app — no crate); 044 (wifi-densepose-geo — bare Accepted, no Date/Deciders) | implement or downgrade to Proposed |
| G18 | Workspace has ~38 crates; CLAUDE.md publishing list (12-step) and crate table (15) are stale | MEDIUM | corpus-wide (crate-graph topology) | write-missing-ADR (crate-graph / publish boundaries) + reconcile CLAUDE.md |
Only 3 formal supersession edges exist; all three are defective (see G8/G12; full detail in lens-findings.md Lens 2):
supersedes:["ADR-002"] on 016/017 is file-unsupported — the superseded ADR points up at two successors that do not point back.Proposed. ADR-016/017 realize only the training/signal/MAT integration points; the RVF-container (003), PQ-crypto (007), Raft (008), WASM-edge-runtime (009), and witness-chains (010) decisions are neither implemented nor formally superseded. Marking the parent fully "Superseded" silently buries 5 live-but-abandoned child decisions. Recommended: split ADR-002 to "partially superseded."The four CRITICAL items are the corpus's load-bearing AI-slop admissions — each an accepted-or-shipped surface whose stated accuracy/security/function was provably false until the sweep landed. Every accuracy number predating ADR-155 should be treated as CLAIMED until re-derived through the post-155 leak-free split. Source-cited evidence is in lens-findings.md Lens 3.
grad += v*0.01 in the TTA path (§2.3); a self-certifying proof that blessed whatever the pipeline emitted and PASSed on 1e-9 float noise (§2.4).SubcarrierMismatch, 0 Ok / 8 mismatch), silently degrading coherence to freq-only. Any "CIR-enhanced coherence/ToF" claim before this fix overstated reality.training_class1_accuracy = 0.343 and renames "learned multi-person counter" → "presence detector," gutting ADR-103/104's claim.homecore-recorder (SQLite state history + semantic search) cites "ADR-132", which does not exist. The durable-state backbone is ungoverned. → write HOMECORE-RECORDER ADR.docs/adr-gap-remediation-1: ADR-132 written (ADR-132-homecore-recorder-history-semantic-search.md, Status: Accepted — reverse-documented from the shipped crate).homecore-migrate (reads untrusted Python-HA .storage/*.json) cites "ADR-134", but on-disk ADR-134 is CIR. A data-integrity-sensitive importer governed by a phantom identity. → resolve 134 collision + write HOMECORE-MIGRATE ADR (trust boundary).docs/adr-gap-remediation-1: ADR-165 written (ADR-165-homecore-migrate-from-home-assistant.md, Status: Accepted — P1 scaffold); crate's ADR-134 refs repointed → ADR-165; on-disk ADR-134 (CIR) left intact. ADR-126's series-map row (which labels the role "ADR-134 HOMECORE-MIGRATE") is owner-gated and unchanged.wifi-densepose-engine composes ADR-135..146 onto the live 20 Hz path but no ADR governs the integrator contract (ordering, back-pressure, "one pipeline cycle" boundary).wasm-edge (~70 skills) governed only by remediation ADRs 160/163 — no creation/taxonomy/ABI ADR. occworld-candle is a Rust-native backend swap ADR-147 explicitly deferred. pointcloud has only a viewer-deploy ADR (094), no data-format contract.The ADR-154–163 sweep was narrowly scoped. The two largest capability gaps it did not touch:
error_response generic bodies); XFF bypass and JWT-in-URL were verified absent and regression-pinned. See ADR-080 P0 §1–3.Positive. One authoritative ledger replaces scattered, drifting status fields. The anti-slop retractions are recorded in a citable place, so the "AI slop" accusation is met with a structured admission + fix-trail rather than denial. The Gap Register is a concrete, severity-ordered work queue. Batch-fixing G5 (10 streaming-engine headers) and G1/G2 (numbering + missing headers) is high-ROI and unblocks ADR tooling.
Negative. This ADR is a snapshot; it goes stale the moment the next ADR lands. Counts marked ~ are approximate and a few impl_state values are needs verification (downstream-prose-derived, not file-confirmed). Acting on the register (renumbering, status flips, supersession edits) touches ~30 files and risks transient cross-reference breakage if not done atomically.
Neutral. No subsystem behavior changes. Renumbering decisions (which of the colliding files keeps each number) are deferred to the follow-up remediation PR — this ADR records the collision, not the resolution. Whether to close abandoned chains as Rejected vs Deferred is a judgment call left to the deciders per chain.
docs/adr/gap-analysis/census.md — full per-ADR census (162 entries).docs/adr/gap-analysis/lens-findings.md — five-lens findings (status-distribution, supersession-chains, contradictions, coverage-gaps, data-hardware-gated), verbatim.