ship: v0.2 P2 research engine + trust loop #11

Merged
coreci-bot merged 8 commits from phase/02-engine-trust into milestone/v0.2-mvp 2026-09-27 11:48:28 +00:00

8 Commits

Author SHA1 Message Date
coreci f736c0b8b7 chore(P02): remove stray verify-msg file
---ci---
phase: 2
milestone: v0.2
status: verify
---/ci---
2026-09-27 11:47:24 +00:00
coreci 9c3246be87 verify(P02): passed after fixes — 2 P0 + 9 P1 resolved in-phase, 11 P2 flagged
---ci---
phase: 2
milestone: v0.2
status: verify
requirements:
  covered: [REQ-07, REQ-12, REQ-13, REQ-14, REQ-15, REQ-16, REQ-18, REQ-19, REQ-20, REQ-21, REQ-22, REQ-23, REQ-24]
  partial: []
lessons:
  - "P0s both masked by fake tests: SSRF guard existed but was never wired into the fetch boundary; writer prompts had no evidence slot so the visited-only constraint was vacuous - both fixed with regression pins (evidence-in-prompt recording test, refused-fetch test)"
  - "Fake-adapter tests mask integration gaps: the three highest-risk behaviors were exactly the untested ones. P4 adversarial suite must include real-boundary probes"
  - "P2 flags for post-hoc: DNS-rebinding TOCTOU residual risk (getaddrinfo vs connect-time resolution), evidence store not persisted across restarts (renumbered IDs on resume), reflecting step is re-planning (depth>1 loop untested), liveness body accumulation vs HEAD"
---/ci---

Structural: mypy strict 36 files, ruff clean. Behavioral: 108
backend tests (full walk, approval halt, pause/resume mid-run,
cancel pre+post approval, restart from AWAITING_APPROVAL and
SEARCHING, probe wiring both paths, trust thresholds, SSRF
refusals, export gate) + 90 frontend green. REQ-13..24 mapped.
Security: SSRF enforced at every fetch path + per-hop redirect
guarding; no value leaks (probe persists typed data only). The
phase is shippable: both P0s and all blocking P1s resolved with
regression coverage.
2026-09-27 11:47:15 +00:00
coreci 3d97af27f3 fix(P02): verify P0/P1 fixes — SSRF at fetch boundary, evidence in writer prompt, real anchoring, resume dispatch, trace file, export gate
---ci---
phase: 2
milestone: v0.2
status: verify
persona: backend-engineer
task: T-2.5
requirements:
  covered: [REQ-16, REQ-18, REQ-20, REQ-23]
---/ci---

P0-1: SSRF guard now lives in adapters/url_guard.py (IPv4+IPv6
via getaddrinfo, fails closed on unresolvable) and is wired into
Tavily.fetch, DDG.fetch, AND the engine extract step (refused
URLs logged as source_refused events, never fetched). Liveness
redirects followed manually with per-hop re-guarding - a 302 to a
private IP now classifies DEAD, and STALE is reachable (redirect
loop / missing location).

P0-2: writer prompts gain {evidence} slots; render_writer_prompt
requires evidence; regression test proves evidence text reaches
the writer prompt (recording model).

P1s: ledger anchoring now anchors the REPORT's extracted quotes
against all passages (mismatch detection real, REQ-20 testable);
trace.jsonl append-only per run (REQ-16 trace file); _execute is
position-aware - resume works from SEARCHING/EXTRACTING/
REFLECTING/SYNTHESIZING/VERIFYING (mid-run restart test); cancel
honored post-approval via per-iteration checks in the research
loop; REQ-23 export gate (>= 0.99 liveness with failure listing
in the checklist); authority tiers dot-anchored; extracting step
processes ALL sub-questions (breadth fix); AdapterError taxonomy
covers raw httpx errors at the extract boundary. 108 tests.
2026-09-27 11:47:10 +00:00
coreci fa71580e87 feat(P02): live probe wiring + demo + README engine architecture
---ci---
phase: 2
milestone: v0.2
status: execute
persona: backend-engineer
task: T-2.13
requirements:
  covered: [REQ-07, REQ-12]
---/ci---

REQ-07/12 COMPLETE: probe results attach to run state (persisted
in state.json, surfaced via probe_attached event); probe failure
degrades honestly - the run proceeds without probe data, never
crashes (MockTransport-proven both paths). README gains the engine
architecture section (state machine, artifacts, trust loop, demo
command). 101 tests green.
2026-09-27 11:33:16 +00:00
coreci 340abe9335 feat(P02): resume-across-restart, demo script, run-id consolidation
---ci---
phase: 2
milestone: v0.2
status: execute
persona: backend-engineer
task: T-2.6
requirements:
  covered: [REQ-15, REQ-31]
---/ci---

Actor is position-aware: a restored state past PLANNING skips the
planning phase and re-enters at the approval/research boundary with
its persisted plan (state file round-trip proven: state, cursor,
plan all survive). researchx.engine.demo walks the full pipeline on
fakes into a temp runs dir (state.json, report.md, ledger.json,
checklist.md + 10 events). make_run_config now uses the storage
adapter's reduced-alphabet run-id generator (verify P2 flag
resolved: dual generators consolidated). 99 tests green.
2026-09-27 11:32:26 +00:00
coreci bf152f5ff8 feat(P02): research engine + trust loop — state machine, durable state, evidence, liveness, anchoring, ledger
---ci---
phase: 2
milestone: v0.2
status: execute
persona: backend-engineer
task: T-2.3
requirements:
  covered: [REQ-13, REQ-14, REQ-15, REQ-16, REQ-18, REQ-19, REQ-20, REQ-21, REQ-22, REQ-24]
---/ci---

Engine: typed state machine (PLANNING → AWAITING_APPROVAL →
SEARCHING → EXTRACTING → REFLECTING depth loop → SYNTHESIZING →
VERIFYING → DONE/CANCELLED/FAILED with a legal-transition table),
RunActor with plan approval halt, asyncio pause/resume gates,
cancel persisting terminal state, CancelledError re-raised after
shielded persist, durable state.json rewritten atomically per
transition. Typed EventBus (run_started, query_fired,
source_found, source_visited, passage_extracted, state_changed,
run_done, run_error) + trace artifacts. Evidence store: stable
p-<n> passage IDs, paragraph extraction, writer context =
stored passages only (visited-only by construction). Trust loop:
SSRF-guarded liveness (live/stale/dead, redirect-follow, 10s,
2MB cap), quote anchoring (NFC/casefold/whitespace normalize,
exact-substring short-circuit, SequenceMatcher ≥ 0.85,
weak_match flags), citation ledger JSON (url, visited_at,
passages, claims, health, authority tier), exportable
verification checklist, single-source vs corroborated confidence
labels. 96 tests green on fakes — zero API keys.
2026-09-27 11:31:26 +00:00
coreci 0d5866ae20 feat(P02): evidence store — stable passage IDs, visited-only writer context
---ci---
phase: 2
milestone: v0.2
status: execute
persona: data-engineer
task: T-2.1
requirements:
  covered: [REQ-18]
---/ci---
2026-09-27 11:29:15 +00:00
coreci ae8f99ad34 docs(P02): P2 plan — engine + trust loop vertical slices (5 waves, 15 tasks)
---ci---
phase: 2
milestone: v0.2
status: plan
message: >-
  Phase-boundary PLAN refresh (v0.1 practice): P2 plan written —
  evidence store, state machine, event bus, RunActor with
  AWAITING_APPROVAL halt, durable pause/resume, trust loop
  (liveness, anchoring, ledger, checklist, confidence labels),
  SSRF guard (P1 verify flag promoted to mandatory), live probe
  wiring (REQ-07/12 complete here), demo script, run-id
  consolidation. MVP/UX sections authored. G-006 split lever
  noted.
requirements:
  covered: []
  partial: []
---/ci---
2026-09-27 11:28:48 +00:00