golangLAKEHOUSE/reports/scrum/claim-coverage-table.md
root 91edd43164 scrum audit: 5 reports under reports/scrum/ · score 35/60
Adapts docs/SCRUM.md framework (originally written for the
matrix-agent-validated repo) to the Go rewrite. Five deliverables:

  golang-lakehouse-scrum-test.md  top-line + scoring + verdict
  risk-register.md                12 findings, R-001..R-012
  claim-coverage-table.md         claim/test/risk for Sprint 2
  sprint-backlog.md               5 sprints, ~2 weeks of work
  acceptance-gates.md             DoD as runnable commands

Every claim cites file:line, command output, or "missing evidence."
Smoke chain ran clean (33s wall, all 9 PASS) and is captured in
reports/scrum/_evidence/smoke_chain.log (gitignored — runtime artifact).

Scoring:
  Reproducibility       7/10  9 smokes deterministic, no just/CI gate
  Test Coverage         6/10  internal/ packages tested, 6/7 cmd/ aren't
  Trust Boundary        7/10  escapes ok, zero auth, /sql is RCE-eq off-loopback
  Memory Correctness    3/10  pathway/playbook/observer not yet ported
  Deployment Readiness  4/10  no REPLICATION, no env template, no systemd
  Maintainability       8/10  no god-files, 7 lean binaries, ADRs current

Top three risks:
  R-001 HIGH  queryd /sql + DuckDB + non-loopback bind = RCE-equivalent
  R-002 HIGH  internal/shared (server.go + config.go) zero tests
  R-003 HIGH  internal/storeclient zero tests, used by 2 services
  R-004 MED   9-smoke chain green but not gated (no justfile/hook)

The audit is the work; refactors come after. Sprint 0 owns coverage
+ CI gating; Sprint 1 owns trust-boundary decisions; Sprints 2-3 are
mostly design-bar work for unbuilt agent components.

.gitignore exception: /reports/* + !/reports/scrum/ keeps reports/
a runtime-artifact directory while exposing reports/scrum/ as
tracked documentation. Mirrors the pattern future audit passes will
land in.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 04:51:47 -05:00

101 lines
8.8 KiB
Markdown

# golangLAKEHOUSE — Claim-Coverage Table
Per SCRUM.md §3, mapping each agent / memory claim from the upstream system to its current status in the Go rewrite. Many rows are "not yet ported" — those become Sprint 2 design bars rather than current-state failures. Risk IDs reference `risk-register.md`.
---
## Format
| Claim | Code Location | Existing Test | Missing Test | Risk |
A claim with status **"not yet ported"** in Code Location means the upstream Rust system implements it but the Go rewrite has not. These rows define design bars for when the port lands.
---
## Vector retrieval
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| HNSW search returns top-K by cosine similarity | `internal/vectord/index.go` (Add/Search/Lookup with RWMutex per memory `b8c072c`) | `internal/vectord/index_test.go` (13 funcs, including recall search per `g1_smoke.sh:7`) | Concurrent-search-during-add stress test (RWMutex contention behavior); cross-binary search via gateway latency budget | LOW (covered) |
| Index recall = 1.0 on round-trip with same vectors | `cmd/vectord/main.go` add+search handlers | `g1_smoke.sh` line 7 (recall-search assertion); `g2_smoke.sh` end-to-end at distance 5.96e-8 | None — covered by 2 smokes | LOW (covered) |
| Cross-corpora retrieval (multi-index search in one query) | **not yet ported** — Rust `vectord` had federated-corpus search, Go vectord is per-index only | — | All — design bar | DESIGN-BAR (Sprint 2) |
| Dimension mismatch on add → 400 | `internal/vectord/index.go` (Validates per memory) | `g1_smoke.sh:7` (dim-mismatch-400 assertion) | Unit test with explicit dimension assertion | MED (smoke covers, no go-test) |
| Zero-norm vector under cosine → reject | `internal/vectord/index.go` (Validates per memory `b8c072c`) | `internal/vectord/index_test.go` (13 funcs — likely covers; not verified by reading every test) | Audit which of the 13 funcs covers this; if none, add | LOW |
## Vector persistence (G1P)
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Save → kill → restart → search returns dist=0 | `internal/vectord/persistor.go` + `cmd/vectord/main.go` boot path | `g1p_smoke.sh` (kill+restart preserves state, 8/8 PASS per memory `8b92518`); `internal/vectord/persistor_test.go` (5 funcs) | None — covered | LOW (covered) |
| Single-Put framed format prevents torn-write half-state | `internal/vectord/persistor.go` LHV1 single-Put per memory (3-way convergent scrum fix) | `persistor_test.go` likely covers | Failure-injection test: PUT-fails-mid-stream → Load returns "no state" rather than half-loaded state | MED |
| Persistence above 256 MiB single-key (≈150K vectors @ d=768) | **NOT IMPLEMENTED** — storaged's MaxBytesReader 256 MiB caps single-file LHV1 (cited in head commit `1f700e7` and memory) | — | Test asserting persistence works at 200K+ vectors | DESIGN-BAR (Sprint 2 / G3) |
| Save failure logged-not-fatal (in-memory still source of truth) | `cmd/vectord/main.go` boot per memory `8b92518` | not verified by reading test | Unit test injecting storaged-down → Save returns nil error, log line emitted | MED |
## Embedding (G2)
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Text → 768-d vector via Ollama nomic-embed-text | `internal/embed/ollama.go` + `cmd/embedd/main.go:59` | `internal/embed/ollama_test.go` (6 funcs); `g2_smoke.sh` end-to-end | None — covered | LOW (covered) |
| Provider interface allows swap (OpenAI/Voyage/etc.) | `internal/embed/embed.go:20` (`Embed` interface) per memory `9ee7fc5` | Interface-only — provider selection in `cmd/embedd/main.go` not unit-tested | Test that wiring swaps providers based on config | LOW |
| Bad model → 502 from upstream | `cmd/embedd/main.go` error mapping | `g2_smoke.sh:103-106` (bad-model → 502 assertion) | Unit test on the error-mapping branch | LOW (smoke covers) |
| Float64 → float32 narrowing at boundary | `internal/embed/ollama.go` per memory `9ee7fc5` | `ollama_test.go` likely covers | Verify test with adversarial near-overflow inputs | LOW |
## SQL truth path
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Query catalog list → CREATE OR REPLACE VIEW per manifest | `internal/queryd/registrar.go:139` | `internal/queryd/registrar_test.go` (7 funcs incl. drop-before-create order, idempotency) | None — covered | LOW |
| Updated_at as implicit etag prevents repeated CREATE | `internal/queryd/registrar.go:114` (`prior.Equal(m.UpdatedAt)`) | `registrar_test.go` covers Skipped count | None — covered | LOW |
| Schema-drift CSV → 409, view unchanged | `cmd/ingestd/main.go` + `cmd/queryd/main.go` | `d4_smoke.sh` (schema-drift 409); `d5_smoke.sh` (view unchanged through drift) | None — covered | LOW |
| Arbitrary SQL via /sql is safe (it isn't — by design) | `cmd/queryd/main.go:142` | none | Auth boundary test (R-001) | **HIGH (R-001)** |
## Mem0-style memory semantics (ADD / UPDATE / REVISE / RETIRE / HISTORY)
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| ADD a new pathway trace | **not yet ported** — Rust has `pathway_memory` crate, Go does not | — | All | DESIGN-BAR (Sprint 2) |
| UPDATE replaces existing trace by uid | **not yet ported** | — | All | DESIGN-BAR |
| REVISE creates a new revision linked via history chain | **not yet ported** | — | All | DESIGN-BAR |
| RETIRE marks a trace excluded from retrieval | **not yet ported** | — | All — including retrieval-must-not-return-retired test | DESIGN-BAR |
| HISTORY chain is cycle-safe | **not yet ported** | — | All — explicit cycle injection + detection test | DESIGN-BAR |
| Replay count increments on duplicate ADD | **not yet ported** | — | All | DESIGN-BAR |
| Corrupted memory row recovery | **not yet ported** | — | All — fixture with poison row | DESIGN-BAR |
**Sprint 2 design bar:** when pathway memory ports to Go, the test fixture must include all 7 rows above on day one. This is the lesson from the Rust system having shipped these features ahead of their tests.
## Observer / hand-review
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Observer gates candidates before they reach playbook seal | **not yet ported** — Rust `mcp-server/observer.ts` exists, Go does not | — | All | DESIGN-BAR (Sprint 3) |
| Observer review failure does NOT auto-accept | **not yet ported** — but R-007 verdict pre-decided: Go observer must default `degraded=true, verdict=cycle` on internal error. ADR-002 design bar. | — | Test injecting observer-side error → response has `degraded: true`, never `verdict: "accept"` | DESIGN-BAR (Sprint 3) |
| Health endpoint content-type matches consumer expectation (the Rust `r.json()` on text/plain crash-loop bug from memory) | `internal/shared/server.go:61` returns plain string `"<service> ok"` per the existing pattern | none — but the bug it would catch already exists in the Rust system's history (memory `54689d5`) | Regression test: consumer of `/health` accepts text/plain or 502s loudly, never silently nulls | MED (Sprint 3) |
## Playbook seal + retrieval
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Successful playbooks are sealed for later retrieval | **not yet ported** | — | All | DESIGN-BAR (Sprint 3) |
| Second-run retrieval surfaces prior playbook | **not yet ported** | — | All | DESIGN-BAR (Sprint 3) |
| Negative case: observer rejects hallucinated claim | **not yet ported** | — | All | DESIGN-BAR (Sprint 3) |
| Agent claims verifiable against SQL truth | partial — `cmd/queryd/main.go` is the SQL truth surface; no agent layer above it yet | none for the agent layer | All | DESIGN-BAR (Sprint 3) |
## Cloud-only adaptation
| Claim | Code Location | Existing Test | Missing Test | Risk |
|---|---|---|---|---|
| Embed works without local Ollama (cloud Provider) | `internal/embed/embed.go:20` interface allows it; no cloud Provider implemented yet | none | All | DESIGN-BAR (Sprint 4 — once cloud Provider lands) |
| Persistence works without local MinIO (real S3 / R2) | `internal/storaged/bucket.go` uses aws-sdk-go-v2 — should work against real S3 with no code changes | not exercised in smokes | Smoke variant pointing at AWS S3 in addition to MinIO | LOW |
---
## Summary counts
- **Claims covered by existing tests + smokes:** 14
- **Claims partially covered (smoke only, no go-test):** 5
- **Claims uncovered but component built:** 2 (concurrent-search stress, large LHV1 persistence)
- **Claims marked "not yet ported" (design bars):** 14
- **Claims with HIGH-risk gaps in current code:** 1 (R-001, the queryd /sql boundary)
The 14 design-bar rows are the primary Sprint 2-3 backlog. The 5 partially-covered + 2 uncovered rows are Sprint 0 follow-ups. The 1 HIGH-risk gap is Sprint 1's anchor.