---
milestone: v1.4
name: Search Precision
audited: 2026-02-24T08:00:00Z
status: passed
scores:
  requirements: 6/6
  phases: 2/2
  integration: 6/6
  flows: 4/4
gaps: {}
tech_debt:
  - phase: 13-engine-min-score-filter
    items:
      - "SUMMARY.md missing `requirements-completed` YAML frontmatter field (format gap — `provides:` lists FILT-01 but not in canonical field)"
  - phase: 14-api-mcp-cli-parity
    items:
      - "SUMMARY.md (plans 01 and 02) missing `requirements-completed` YAML frontmatter field (format gap — `provides:` lists all 5 requirements by ID)"
      - "FILT-04 (MCP sort_by) and FILT-05 (score normalisation) explicitly deferred to v2 — tracked in REQUIREMENTS.md"
---

# v1.4 Search Precision — Milestone Audit Report

**Audited:** 2026-02-24T08:00:00Z
**Milestone goal:** Give users control over search output — expose relevance scores, add sorting, and filter noise via a minimum-score threshold — across CLI, Python API, and MCP.
**Status:** ✅ PASSED
**Score:** 6/6 requirements satisfied · 2/2 phases passed · 4/4 E2E flows complete

---

## Requirements Coverage

### 3-Source Cross-Reference

| REQ-ID | VERIFICATION.md | SUMMARY `provides:` | REQUIREMENTS.md | Final Status |
|--------|----------------|---------------------|-----------------|-------------|
| FILT-01 | passed (Phase 13, 5/5) | Listed (`FILT-01`) | `[x]` Complete Phase 13 | **satisfied** |
| FILT-02 | passed (Phase 14, 8/8) | Listed (FILT-02 in plan 01) | `[x]` Complete Phase 14 | **satisfied** |
| FILT-03 | passed (Phase 14, 8/8) | Listed (FILT-03 in plan 01) | `[x]` Complete Phase 14 | **satisfied** |
| PARITY-01 | passed (Phase 14, 8/8) | Listed (sort_by param) | `[x]` Complete Phase 14 | **satisfied** |
| PARITY-02 | passed (Phase 14, 8/8) | Listed (min_score param) | `[x]` Complete Phase 14 | **satisfied** |
| PARITY-03 | passed (Phase 14, 8/8) | Listed (MCP min_score) | `[x]` Complete Phase 14 | **satisfied** |

**Note:** All SUMMARY.md files lack the `requirements-completed` YAML frontmatter field. Manual inspection of `provides:` blocks confirms explicit requirement enumeration. Upgraded from "partial" to "satisfied" based on manual verification.

### Orphan Detection

All 6 REQ-IDs (FILT-01..03, PARITY-01..03) appear in at least one VERIFICATION.md. **No orphaned requirements.**

---

## Phase Verification Summary

| Phase | Name | Status | Score | Critical Gaps |
|-------|------|--------|-------|---------------|
| 13 | Engine Min-Score Filter | ✅ passed | 5/5 | None |
| 14 | API / MCP / CLI Parity | ✅ passed | 8/8 | None |

### Phase 13 Detail

- `hybrid_search()` accepts `min_score: float = 0.0` — VERIFIED (engine.py:56)
- `min_score=0.0` is a true no-op — VERIFIED (guard at line 112)
- `min_score=99.0` returns `[]` — VERIFIED (filter comprehension lines 113–116)
- All results above threshold have `_relevance_score >= min_score` — VERIFIED
- 285/285 tests pass (281 pre-existing + 4 new FILT-01 tests)

### Phase 14 Detail

- `--min-score` CLI option with RRF range help text — VERIFIED (cli.py:333–343)
- FILT-03 hint on filtered-all — VERIFIED (cli.py:392–400)
- `--sort-by score|date|title` with translation map — VERIFIED (cli.py:300–305, 367–376)
- Python `search()` gains `sort_by` + `min_score` — VERIFIED (api/public.py:79–128)
- MCP `corpus_search()` gains `min_score: Optional[float]` with None→0.0 — VERIFIED (mcp/server.py:49–77)
- 293/293 tests pass; ruff clean; mypy clean

---

## Integration Verification

### Cross-Phase Wiring

| From | To | Connection | Status |
|------|----|-----------|--------|
| Phase 13 `engine.py:hybrid_search()` | Phase 14 `cli.py:386` | `min_score=min_score` kwarg | ✅ WIRED |
| Phase 13 `engine.py:hybrid_search()` | Phase 14 `api/public.py:128` | `min_score=min_score, sort_by=_API_SORT_MAP[sort_by]` | ✅ WIRED |
| Phase 13 `engine.py:hybrid_search()` | Phase 14 `mcp/server.py:77` | `min_score=effective_min_score` | ✅ WIRED |
| Phase 14 FILT-03 branch | CLI output | `cli.py:392–400` empty+filtered check | ✅ WIRED |
| Phase 14 `_API_SORT_MAP` | Python API validation | `ValueError` on invalid `sort_by` | ✅ WIRED |
| Phase 14 MCP None→0.0 | Engine call | `effective_min_score` computation | ✅ WIRED |

**Orphaned exports:** 0 / **Missing connections:** 0

### E2E Flow Verification

| Flow | Path | Status |
|------|------|--------|
| `corpus search "q" --min-score 0.02` | CLI option → `min_score=0.02` → engine filter → results displayed | ✅ COMPLETE |
| `corpus search "q" --min-score 99` | CLI option → engine returns `[]` → FILT-03 hint printed | ✅ COMPLETE |
| `search(q, min_score=0.02, sort_by="score")` Python API | `sort_by` translated via `_API_SORT_MAP` → both forwarded to engine | ✅ COMPLETE |
| MCP `corpus_search(query="q", min_score=0.02)` | `None`→`0.0` guard → forwarded → filtered results returned | ✅ COMPLETE |

---

## Tech Debt

No blockers. The following non-critical items are noted for awareness:

### By Phase

**Phase 13: Engine Min-Score Filter**
- `13-01-SUMMARY.md` missing `requirements-completed` YAML frontmatter field (executor template gap — `provides:` block correctly lists FILT-01)

**Phase 14: API / MCP / CLI Parity**
- `14-01-SUMMARY.md` and `14-02-SUMMARY.md` missing `requirements-completed` YAML frontmatter field (same template gap — `provides:` blocks list all 5 requirements by ID)

### Deferred Requirements (by design)

| REQ-ID | Description | Reason Deferred |
|--------|-------------|----------------|
| FILT-04 | MCP `corpus_search` accepts `sort_by` | Agents rarely need explicit sort; low value |
| FILT-05 | Score normalisation to 0–1 range | Per-query minmax misleading for cross-query comparisons; if UX testing shows confusion |

These are tracked in `REQUIREMENTS.md` under "v2 Requirements" — not blockers.

### Pre-Existing Tech Debt (outside milestone scope)

Phase 14 anti-pattern scan found TODOs/placeholders only in pre-existing files outside milestone scope:
- `llm/rewriter.py`, `generators/advanced_rewriter.py`, `ingest/chunker.py` — legitimate template placeholder handling in LLM subsystem; not introduced by this milestone.

---

## Summary

Milestone v1.4 Search Precision is complete. All 6 requirements are satisfied across all three consumer surfaces (CLI, Python API, MCP). Cross-phase wiring from the Phase 13 engine parameter to Phase 14 callers is verified at every call site. Four E2E user flows trace cleanly end-to-end. Test suite: 293 passed with zero regressions; ruff and mypy both clean.

The only tech debt is a SUMMARY.md frontmatter format gap (missing `requirements-completed` field) present in all three plan summaries — a documentation template issue, not a functional gap.

---

*Audited: 2026-02-24T08:00:00Z*
*Auditor: Claude (gsd-audit-milestone)*
