---ci---
phase: 4
milestone: v0.2
status: verify
persona: ci-lead-developer
task: T-4.1
requirements:
covered: [REQ-32, REQ-34]
---/ci---
The adversarial verify attacked the adversarial suite itself and
found honesty gaps — all fixed:
1. Export gate now fails on unanchored claims (was liveness-only:
a fully fabricated report passed vacuously - now attack-tested:
unknown-passage citations must FAIL the gate; checklist shows
an explicit Anchoring gate line).
2. Weak band pinned with a real 0.80-0.85 input (ratio 0.82
asserted weak=True - the band was previously claimed but never
proven).
3. Fully-fabricated-report attack added (p-7/p-42 unknown ids
fail export).
4. REQ-34 honest: markdown export now carries citation URLs as
real links; JSON export uses the BACKEND ledger schema
(run_id/entries/health/authority_tier snake_case) and
round-trips into the CitationLedger pydantic model.
5. dev_bridge prints READY only after uvicorn startup (was
before bind - a port-8000 squatter would be silently driven
by E2E); paused_seen assertion restored (was deleted to dodge
lint).
Also: ruff gate unblocked (unused import), live-tier os.environ
fallback documented as test-only deviation. 126 backend (11
adversarial) + 97 frontend green.
---ci---
phase: 4
milestone: v0.2
status: execute
persona: frontend-engineer
task: T-4.5
requirements:
covered: [REQ-17, REQ-34]
---/ci---
E2E (REQ-17): the live ApiClient binding drives a REAL FastAPI
engine via researchx.api.dev_bridge (uvicorn loopback, port 8000,
inexhaustible scripted model, fake search corpus) — create run →
awaiting_approval → approve → SSE run_done → done → artifacts.
Click-budget assertion pins the ≤3 user actions (submit question,
pick methodology, approve plan) on defaults only — validated on
the real stack per REQ-17, not the mock.
Round-trip (REQ-34): markdown export carries [p-N] citation
markers; JSON export carries the ledger with real https URLs and
live/stale/dead health that validates back through the frontend
types. Node-env vitest suite with an eventsource polyfill; bridge
port matches the client's default base URL so the SSE path is
exercised end-to-end. Frontend 97/97.