ship: v0.2 P0 pre-execution #9
Reference in New Issue
Block a user
Delete Branch "phase/00-pre-execution"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 0 pre-execution ship: SPECIFY→CLARIFY (D-007..D-020)→RESEARCH (RESEARCH-v02.md + PERSONAS v0.2)→PLAN (P1 vertical slices)→GRILL (G-001..G-010, Proceed 0.72)→MVP/UX (PASS). Gates: frontend typecheck/lint/90 tests/build green. Tag target v0.2.0.
---ci--- phase: 0 milestone: v0.2 status: clarify decisions: - id: D-007 decision: Backend layout = backend/ package at repo root, src-layout researchx with config/, methodologies/, adapters/, engine/, evidence/, trust/, api/ per ARCHITECTURE §Components rationale: Matches ARCHITECTURE.md component map 1:1; src-layout avoids import shadowing; uv manages the venv + Python 3.12 confidence: 0.95 alternatives: [flat single-package, api-first layout] - id: D-008 decision: Provision uv + uv-managed Python 3.12 (official installer, user-local ~/.local/bin); system Python is 3.11.2 rationale: REQ-33 mandates uv-managed Python 3.12; uv fetches a managed CPython so the system interpreter is irrelevant confidence: 0.9 alternatives: [system 3.11 venv + pip (deviation from spec)] - id: D-009 decision: Backend serves on 127.0.0.1:8000; frontend dev on :3000 calls backend via NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000; FastAPI CORS allows localhost:3000 rationale: FastAPI/uvicorn defaults for a local-first single-user tool; frontend env var keeps the ApiClient boundary intact confidence: 0.85 alternatives: [single-origin reverse proxy, fixed port 3001] - id: D-010 decision: Run IDs = 8-char nanoid-style lowercase alnum slug (e.g. r-3f9k2q7z), generated by the API layer; storage layout = <storage_dir>/runs/<run_id>/ rationale: Human-referenceable in URLs and folders; nanoid avoids UUID's file-name collisions with 8 chars at 62-alphabet entropy (~10^14) confidence: 0.8 alternatives: [uuid4 hex, monotonic counter] - id: D-011 decision: Ollama endpoints resolve from secrets scopes: base URLs via OLLAMA_BASE_URL (default https://ollama.com/v1) and fallback http://localhost:11434/v1; API key via OLLAMA_API_KEY from .ciagent/.env.secrets only rationale: config.json secrets.model scope already declares OLLAMA_API_KEY + OLLAMA_BASE_URL; env-file secrets-loader is the only resolution path per ship/verify credential rules confidence: 0.9 alternatives: [config.json fields, interactive setup] - id: D-012 decision: DuckDuckGo keyless fallback = HTML-lite endpoint (html.duckduckgo.com/html) scraped conservatively (top results, title+url+snippet); Tavily remains the default search adapter via TAVILY_API_KEY rationale: Keyless fallback must need zero credentials; the html endpoint requires none and is the standard keyless DDG surface; Tavily default per REQ-09 confidence: 0.75 alternatives: [duckduckgo_search python lib, searx instance] - id: D-013 decision: OpenAPI client generation = openapi-typescript (types) + openapi-fetch (typed fetch client) into frontend/src/lib/api/generated/, bound behind the existing ApiClient interface in P3 rationale: Zero-runtime overhead, TS-strict, produces a typed fetch function that wraps cleanly behind ApiClient; avoids heavyweight SDK codegen confidence: 0.8 alternatives: [orval, @openapitools/openapi-generator-cli] - id: D-014 decision: SSE transport = GET /api/runs/{id}/events via sse-starlette EventSourceResponse; typed event bus is asyncio.Queue-fed with pydantic event models (run_started, query_fired, source_visited, passage_extracted, state_changed, run_done, run_error) rationale: sse-starlette is the maintained FastAPI SSE standard; pydantic events give the typed bus REQ-16 demands; matches the MockApiClient replay contract already in the frontend confidence: 0.85 alternatives: [websockets, polling] - id: D-015 decision: Quote-anchoring fuzzy match = normalized token-subset + difflib SequenceMatcher ratio >= 0.85 as the primary check; exact substring match short-circuits; mismatch flagged in the ledger, never silently dropped rationale: difflib is stdlib (zero deps), 0.85 threshold balances recall/precision on quoted prose; flagged mismatches preserve trust-loop transparency confidence: 0.75 alternatives: [rapidfuzz, embedding similarity] - id: D-016 decision: URL liveness pass = HTTP HEAD/GET (follow redirects, 10s timeout) classifying 200-299=live, 3xx-stale-after-redirect-limit/stale-content=stale, 4xx/5xx/timeout/dead-url=dead; runs post-run per REQ-19; recheck at export rationale: Simple, deterministic classification REQ-19 names live/stale/dead; single GET with redirect following captures the common moved-page case confidence: 0.8 alternatives: [HEAD-only, wayback fallback] - id: D-017 decision: Engine durability = JSON state file per run (runs/<id>/state.json) rewritten atomically (tmp+rename) after every state transition + EventBus subscribers receive replay on resume; asyncio tasks checkpointed via state machine position, not mid-task rationale: REQ-15 demands pause/cancel/resume across restarts; atomic rewrite prevents torn files; transitions are natural checkpoint boundaries confidence: 0.85 alternatives: [sqlite, append-only journal] - id: D-018 decision: Run termination semantics for THIS pipeline run: phases ship P1..P4 + final P5; the milestone → main merge HALTS at the owner approval gate (merge_to_main escalation hook) exactly as v0.1 did — the run presents v0.2.5 and stops rationale: Owner-approved run directive (this session): 'P0–P5, halt at owner gate'; config.json escalation_hooks includes merge_to_main; v0.1 precedent (v0.1.8 halted, owner recorded approval in a follow-up) confidence: 1.0 alternatives: [autonomous merge at full autonomy] - id: D-019 decision: Deploy policy for this run = none; no LXC staging without an explicit owner directive (deploy escalation hook) rationale: Owner-approved run directive (this session): 'No deploys without owner directive' confidence: 1.0 alternatives: [stage v0.2.x-uat at P5 gate] - id: D-020 decision: Frontend stays on the v0.1 ApiClient boundary in P1/P2 (MockApiClient), P3 adds a generated OpenAPI client + ApiClient binding switch (env-flag RESEARCHX_API_MODE=mock|live with mock default), no component rewrites (REQ-26/REQ-54) rationale: Keeps REQ-54 zero-throwaway promise explicit; live binding only activated when the backend runs, mock remains default for dev/tests confidence: 0.9 alternatives: [hard swap in P3, dual clients per component] ---/ci--- CLARIFY stage, milestone v0.2: 14 ambiguities resolved at full autonomy (defaults accepted). Key resolutions: backend/ src-layout package, uv + managed Python 3.12, run IDs as short slugs, DDG html-lite keyless fallback, openapi-typescript client gen, sse-starlette event transport, difflib quote anchoring at 0.85, JSON durable state with atomic rewrites, owner-gate halt at P5, no deploys without directive. PROJECT.md + REQUIREMENTS.md updated with the clarified constraints.---ci--- phase: 0 milestone: v0.2 status: grill message: >- Mechanical nine-axis grill, verdict Proceed (0.72). Two internal contradictions + one measurability hole bound as decisions: G-001 REQ-07/12 phase mapping resolved ROADMAP-favor (contracts in P1, live probing in P2); G-002 live-mode surface = core research loop only in v0.2 (Library/Settings-persistence/Suggestions/ Refine/graph stay mock-bound to v0.3+); G-003 pause/resume added to ApiClient as the single planned P3 extension; G-004 REQ-23 liveness = per-run export gate + opt-in keyed tier, not a zero-key CI assertion; G-005 openapi.json snapshot + regen discipline as a P3 must-have; G-006 P2 may split into two patches if it slips; G-007 advisory cost counters via GET /api/config; G-008 DDG = degraded-mode contract; G-009 escalation: owner ratifies the live-mode surface at the P5 gate; G-010 contingency lever: Deep Report deferrable to v0.3 if P2/P4 slip (owner sign-off to pull). decisions: - id: G-001 decision: P1 ships typed probe/warning contracts proven with fakes; live endpoint probing executes in P2 (ROADMAP mapping wins) rationale: PLAN must_haves T-1.10/T-1.11 claim live probing while PLAN frontmatter and ROADMAP map REQ-07/12 to P2 confidence: 0.9 alternatives: [live probing in P1] - id: G-002 decision: v0.2 live-mode surface = core research loop only; Library, Settings persistence, Suggestions, Refine, graph/inbox, profile stay mock-bound until v0.3+ rationale: client.ts documents seven v0.2 endpoint mappings REQ-25 never promised — the P3 swap hidden-scope grenade confidence: 0.85 alternatives: [full-prototype live mode in v0.2] - id: G-003 decision: Add pauseRun/resumeRun to ApiClient in P3 as the single planned interface extension rationale: v0.1 pause/resume is client-side scripted; REQ-15 demands server-side pause across restarts confidence: 0.85 alternatives: [no interface extension] - id: G-004 decision: REQ-23 liveness = runtime per-run export gate + opt-in keyed live-URL test tier rationale: the 99% bar is unprovable in the zero-key fixture suite it was scheduled into confidence: 0.8 alternatives: [zero-key CI assertion of 99%] - id: G-005 decision: Committed openapi.json snapshot, regen only from snapshot, schema-drift gate, stable operation-ids — P3 must-have rationale: regenerating from a live server invites nondeterministic schema drift confidence: 0.85 alternatives: [live-server regen] - id: G-006 decision: P2 (13 REQs) may ship as two patches (P2a engine/SSE, P2b trust/probe); P3 swap endpoint plan drafted at P2 start rationale: heaviest phase; schedule risk needs a sanctioned split lever confidence: 0.7 alternatives: [single P2 patch regardless] escalations: - 'G-009 (axis 2): owner ratification of the live-mode surface (core loop only) required at the P5 gate — must not be discovered by the owner at the gate' ---/ci------ci--- phase: 0 milestone: v0.2 status: mvp_ux_check message: >- MVP/UX CHECK (REQ-MVP-UX-001): PASS — PLAN.md carries all three sections authored at PLAN stage (User-Facing Surface, Happy Path, UX Acceptance Criteria); no auto-generation needed. Grill binding decisions promoted into PLAN.md: G-001 (probe contracts in P1, live probing in P2 — must_haves T-1.10/T-1.11 reworded), G-002 (live-mode surface = core research loop only), G-003 (pauseRun/ resumeRun as the single P3 ApiClient extension), G-004 (liveness = per-run export gate + opt-in keyed tier), G-005 (openapi.json snapshot discipline), G-006 (P2 split lever), G-007 (cost counters), G-008 (DDG degraded-mode contract), G-010 (Deep Report contingency lever). G-009 stays an open escalation for the P5 owner gate. decisions: - id: G-009 decision: Owner ratifies the live-mode surface (core loop only) at the P5 gate — presented, not silently assumed rationale: The approved prototype has surfaces the MVP backend will not serve live; the owner must record acceptance at the gate confidence: 0.85 alternatives: [silent scope reduction] ---/ci---