Documentation delivery alignment completing Step 5 of FN-3369, updating the CLI reference, research docs, and research hardening preflight guide with consistent documentation delivery guidance across all three files. Fusion-Task-Id: FN-3599
187 lines
10 KiB
Markdown
187 lines
10 KiB
Markdown
# Research Hardening Preflight Baseline (FN-2999)
|
|
|
|
Date: 2026-05-04
|
|
Task: FN-3266
|
|
|
|
## Scope and intent
|
|
|
|
This document is the verified baseline for FN-2999 hardening work. It reflects **shipped behavior in-repo** and explicitly calls out drift from older assumptions.
|
|
|
|
## 1) Verified module map (Research vs Insights)
|
|
|
|
### Core (`@fusion/core`)
|
|
- `packages/core/src/research-types.ts`
|
|
- Canonical research statuses/types/lifecycle contracts.
|
|
- `packages/core/src/research-store.ts`
|
|
- Persistence-backed run lifecycle, transitions, cancellation request, retry creation, events/sources/results/exports operations.
|
|
- `packages/core/src/research-settings.ts`
|
|
- Feature enablement and resolved runtime limits/provider settings.
|
|
- `packages/core/src/db.ts`
|
|
- Research tables: `research_runs`, `research_run_events`, `research_exports`.
|
|
|
|
### Dashboard API/UI (`@fusion/dashboard`)
|
|
- `packages/dashboard/src/research-routes.ts`
|
|
- Research API endpoints (run CRUD + cancel/retry + results/sources/events + exports + finding-to-task actions).
|
|
- `packages/dashboard/src/routes/register-integrated-routers.ts`
|
|
- Mounts router at `/api/research` via `router.use("/research", createResearchRouter(store))`.
|
|
- `packages/dashboard/app/hooks/useResearch.ts`
|
|
- Dashboard hook consuming `/api/research/*` and run lifecycle updates.
|
|
- `packages/dashboard/app/components/ResearchView.tsx`
|
|
- Standalone Research view, run controls, result display, finding task actions.
|
|
|
|
### Engine (`@fusion/engine`)
|
|
- `packages/engine/src/research-orchestrator.ts`
|
|
- Phase execution (`planning/searching/fetching/synthesizing/finalizing`), cancellation, retry handoff, status/event writes.
|
|
- `packages/engine/src/research-step-runner.ts`
|
|
- Provider adapters with timeout + abort handling and error classification.
|
|
|
|
### CLI + extension (`@runfusion/fusion`)
|
|
- `packages/cli/src/commands/research.ts`
|
|
- `create`, `list`, `show`, `export`, `cancel`, `retry` commands.
|
|
- `packages/cli/src/extension.ts`
|
|
- Research tools: `fn_research_run`, `fn_research_list`, `fn_research_get`, `fn_research_cancel`, `fn_research_retry`.
|
|
|
|
### Boundary with Insights (separate subsystem)
|
|
- Insights files/routes/stores remain separate (`insight-store`, `insights-routes`, `project_insights*` tables).
|
|
- Research is **not** a wrapper around Insights and does not share run tables.
|
|
|
|
## 2) Renamed-path drift and stale assumptions
|
|
|
|
- Older wording referencing `packages/dashboard/src/routes/register-research-routes.ts` is stale.
|
|
- Actual implementation is:
|
|
- route file: `packages/dashboard/src/research-routes.ts`
|
|
- mount file: `packages/dashboard/src/routes/register-integrated-routers.ts`
|
|
- mount path: `/api/research`
|
|
|
|
## 3) Lifecycle/status contract as shipped
|
|
|
|
Canonical `ResearchRunStatus` values in `research-types.ts`:
|
|
- `queued`
|
|
- `running`
|
|
- `cancelling`
|
|
- `retry_waiting`
|
|
- `completed`
|
|
- `failed`
|
|
- `cancelled`
|
|
- `timed_out`
|
|
- `retry_exhausted`
|
|
|
|
### Important mismatch to older baseline text
|
|
Older baseline language (`pending | running | completed | failed | cancelled`) is obsolete. `pending` is normalized to `queued` for compatibility in store code, but not a primary status in current contracts.
|
|
|
|
## 4) Cancel/retry behavior (API + store + orchestrator)
|
|
|
|
### Dashboard route behavior (`research-routes.ts`)
|
|
- `POST /runs/:id/cancel`
|
|
- Rejects terminal statuses (`completed`, `failed`, `cancelled`, `timed_out`, `retry_exhausted`) with `409 INVALID_TRANSITION`.
|
|
- Otherwise calls `ResearchStore.requestCancellation()` → run moves to `cancelling`.
|
|
- `POST /runs/:id/retry`
|
|
- Delegates to `ResearchStore.createRetryRun()`.
|
|
- Maps retry exhaustion to `409 RETRY_EXHAUSTED`, non-retryable failures to `409 NON_RETRYABLE_PROVIDER_ERROR`, invalid state to `409 INVALID_TRANSITION`.
|
|
|
|
### Store behavior (`research-store.ts`)
|
|
- `requestCancellation()`
|
|
- Non-terminal runs transition to `cancelling`, append `cancel_requested` lifecycle event.
|
|
- `createRetryRun()`
|
|
- Only from `failed`/`timed_out`.
|
|
- Enforces retryable + max-attempt budget; can set source run to `retry_exhausted` and throw `not_retryable`.
|
|
- Creates new run and sets new run status to `retry_waiting` with `retry_scheduled` event.
|
|
|
|
### Orchestrator behavior (`research-orchestrator.ts`)
|
|
- `cancelRun(runId)` always calls `store.requestCancellation(runId)` first.
|
|
- If run is active in orchestrator `activeRuns`, abort controller is triggered and final state transitions through cancellation handling.
|
|
- If run is **not** active, orchestrator directly sets status `cancelled`.
|
|
- Practical limitation: orchestrator-side graceful cancellation logic only applies to runs currently tracked in `activeRuns`.
|
|
|
|
## 5) Persistence/storage model (verified)
|
|
|
|
### Tables (`db.ts`)
|
|
- `research_runs`
|
|
- Primary run row including JSON columns: `providerConfig`, `sources`, `events`, `results`, `tokenUsage`, `tags`, `metadata`, `lifecycle`.
|
|
- `research_run_events`
|
|
- Append-only lifecycle/event stream (`seq`, `type`, `message`, optional status/classification/metadata).
|
|
- `research_exports`
|
|
- Export artifacts linked by `runId`.
|
|
|
|
### Read/write shape (`research-store.ts`)
|
|
- Run row stores denormalized snapshots (`sources`, `events`, `results`) in `research_runs` JSON fields.
|
|
- Lifecycle events are also persisted separately in `research_run_events` (durable ordered log).
|
|
- Results/citations/findings are stored in `research_runs.results` JSON.
|
|
|
|
## 6) Provider execution path and abort semantics
|
|
|
|
`research-step-runner.ts`:
|
|
- `runSourceQuery` → provider `search(query, options, signal)`
|
|
- `runContentFetch` → provider `fetchContent(url, options, signal)`
|
|
- `runSynthesis` → configured synthesis runner with model settings + signal
|
|
|
|
All step calls are wrapped by `withTimeout(...)`:
|
|
- timeout classification: `ResearchStepTimeoutError` (`retryable: true`)
|
|
- abort classification: `ResearchStepAbortError` (`retryable: false`)
|
|
- provider failures: `provider_error` (`retryable: true`)
|
|
|
|
Abort propagation uses `AbortSignal` listeners and races promise vs timeout vs abort.
|
|
|
|
## 7) API shape summary (`/api/research`)
|
|
|
|
Key endpoints:
|
|
- `GET /runs`, `POST /runs`, `GET /runs/:id`, `PATCH /runs/:id`, `DELETE /runs/:id`
|
|
- `POST /runs/:id/cancel`, `POST /runs/:id/retry`, `PATCH /runs/:id/status`
|
|
- `POST /runs/:id/events`, `POST /runs/:id/sources`, `PATCH /runs/:id/sources/:sourceId`, `PUT /runs/:id/results`
|
|
- `GET /runs/:id/export`, `POST /runs/:id/exports`, `GET /runs/:id/exports`, `GET /exports/:exportId`
|
|
- `GET /stats`, `GET /search`
|
|
- `POST /runs/:runId/findings/:findingId/task`
|
|
- `POST /runs/:runId/findings/:findingId/tasks/:taskId/enrich`
|
|
|
|
## 8) Hardening pressure points recorded (no fixes in this task)
|
|
|
|
1. **Status drift risk**
|
|
- Some surfaces (notably tool parameter enums in extension) still expose legacy compact status sets while core status domain is broader.
|
|
|
|
2. **Orchestrator cancel scope nuance**
|
|
- Full graceful cancel path is only available when run is in `activeRuns`; non-active cancellation takes direct status path.
|
|
|
|
3. **Dual event storage model complexity**
|
|
- `research_runs.events` JSON snapshot and `research_run_events` append-only log coexist; hardening should preserve consistency guarantees.
|
|
|
|
4. **Export surface asymmetry**
|
|
- Route export endpoint advertises markdown/json/html behavior while core export type includes `pdf`; CLI command accepts `pdf` format but markdown renderer fallback behavior should remain explicitly documented/validated.
|
|
|
|
## 9) FN-3292 boundary stress-test confirmations
|
|
|
|
- Provider ordering assumptions were tightened: content fetch selection can now use source-level provider metadata (`providerType`) and falls back only when that provider is unavailable.
|
|
- Orchestrator/provider seam was validated with behavior-first tests:
|
|
- fallback from failed primary provider to a later provider,
|
|
- partial fetch failure with successful completion when at least one source is fetched,
|
|
- real `ResearchStore` persistence verification at orchestrator level (sources/events/results/lifecycle events persisted end-to-end).
|
|
- Boundary guidance for future work:
|
|
- keep retryability/lifecycle ownership in `ResearchStore` transitions,
|
|
- keep error classification in `ResearchStepRunner`,
|
|
- keep sequencing and policy decisions in `ResearchOrchestrator`.
|
|
|
|
## 10) FN-3370 refinement scope correction
|
|
|
|
- FN-3370 replaces FN-3015's stale insights-backed child scope with the landed research subsystem surfaces in this document (core `ResearchStore` + dashboard `/api/research` + engine orchestrator lifecycle persistence).
|
|
- Regression coverage work should stay bounded to shipped lifecycle/status/export/task-integration contracts and use follow-up tasks for any unshipped behavior instead of feature expansion.
|
|
|
|
## 11) Dashboard regression coverage status (FN-3368 refinement)
|
|
|
|
- Dashboard interaction tests are anchored to landed standalone research surfaces (`ResearchView`, `ResearchTaskActionModal`, `useResearch`, `App` research route wiring).
|
|
- Route regression tests explicitly cover finding-to-task create/enrich provenance metadata, task-document writes, duplicate-attachment skip behavior, archived/missing target guards, and payload validation.
|
|
- There is no placeholder/optional assumption that research dashboard files or `/api/research` routes are absent.
|
|
|
|
## 12) FN-3369/FN-3599 verification lock note
|
|
|
|
- Extension research tool contracts are now explicitly locked for missing-run errors and completed-run structured details (`summary`, `findings`, `citations`) across `fn_research_get` / `fn_research_cancel` / `fn_research_retry` behavior.
|
|
- Server-level `/api/research` integration assertions are locked through `createServer` coverage for cancel/retry success paths, structured `400`/`404`/`409` envelopes, and export response contract checks.
|
|
- CLI routing + docs alignment are locked to shipped behavior, including intentional CLI/core vs server export-format asymmetry documentation (no forced unification).
|
|
|
|
## 13) Validation references used for this baseline
|
|
|
|
- `packages/dashboard/src/__tests__/research-routes.test.ts`
|
|
- `packages/core/src/__tests__/research-store.test.ts`
|
|
- `packages/engine/src/__tests__/research-orchestrator.test.ts`
|
|
- `packages/cli/src/commands/__tests__/research.test.ts`
|
|
|
|
These tests were used as behavioral evidence while preparing this baseline.
|