ship: v0.2 P0 pre-execution #9
Merged
coreci-bot
merged 8 commits from 2026-09-27 10:58:36 +00:00
phase/00-pre-execution into milestone/v0.2-mvp
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
61c099e97f |
decision(P00): mvp/ux gate — PASS; grill decisions G-001..G-010 promoted
---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---
|
||
|
|
6f232476d6 |
docs(grill): adversarial review — 17 challenges, 10 binding decisions (G-001..G-010), 1 escalation
---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---
|
||
|
|
05662e0eb9 |
docs(P00): checkpoint — grill stage
---ci--- phase: 0 milestone: v0.2 status: grill ---/ci--- |
||
|
|
718b0c30cd |
docs(P00): create phase plans — P1 vertical-slice plan + ROADMAP v0.2 refresh
---ci--- phase: 0 milestone: v0.2 status: plan message: >- PLAN stage complete: PLAN.md rewritten as the P1 (Methodology Framework + Adapter Layer) vertical-slice plan — 4 waves, 14 tasks, must_haves, REQ-01..06/08..11/31 mapping, User-Facing Surface + Happy Path + UX Acceptance Criteria authored for the MVP/UX gate. ROADMAP.md v0.2 section unblocked: P0 in progress, phase mapping clarified (REQ-07/12 live probing ships in P2), task waves anchored to PLAN.md. Plans for P2..P4 refresh at each phase boundary (v0.1 practice). ---/ci--- |
||
|
|
5765b605ec |
docs(P00): research findings + persona assessment for v0.2
---ci--- phase: 0 milestone: v0.2 status: research message: >- RESEARCH stage complete. RESEARCH-v02.md records 8 topic areas (uv/FastAPI foundation, Ollama endpoints, Tavily/DDG search, SSE + durability, state machine patterns, quote anchoring + liveness, OpenAPI client gen, monorepo ergonomics) with 14 conclusions consumed by PLAN and 4 refinements to D-007..D-020 (hatchling packages key, openapi.json snapshot discipline, single-worker uvicorn, structured-output smoke-test detection). PERSONAS.md rewritten for v0.2: backend-engineer + data-engineer activated, frontend-engineer retained (P3 client swap + P4 E2E), phase-specific security-engineer added for P2 trust loop (deactivates after P2). ---/ci--- |
||
|
|
c5e9cb1b3f |
docs(P00): clarify — PROJECT.md + REQUIREMENTS.md updated with D-007..D-020 resolutions
---ci--- phase: 0 milestone: v0.2 status: clarify message: >- Clarify-stage file updates: PROJECT.md gains the v0.2 Key Decisions section (14 decisions D-007..D-020); REQUIREMENTS.md gains the clarified-constraints block binding the decisions to REQ-01..34. ---/ci--- |
||
|
|
e79102b901 |
decision(P00): clarification — v0.2 MVP ambiguities resolved (D-007..D-020)
---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.
|
||
|
|
9a005f5c64 |
docs(init): validate specification — milestone v0.2-mvp
---ci--- phase: 0 milestone: v0.2 status: specify message: >- Branch gate ran: milestone/v0.2-mvp created from main (v0.1 complete and owner-approved, checkpoint cleared), phase/00-pre-execution checked out. Specification validated: PROJECT.md two-milestone objective, REQUIREMENTS.md REQ-01..34 (MVP) defined and traceable, milestone v0.2-mvp established in config.json (feature, tag line v0.2.x). Checkpoint written at stage specify. requirements: covered: [] partial: [] ---/ci--- |