feat(FN-3012): add ResearchTaskActionModal, model fallback notifications, a
This merge delivers three coordinated features: it adds a notification when task execution falls back to default AI model settings, scopes ResearchView's safe-area padding to mobile only, and hardens the pi-autoresearch analysis with a target matrix and preflight checks. The changes touch the core s Fusion-Task-Id: FN-3012
This commit is contained in:
@@ -367,3 +367,15 @@ Should be replaced with Fusion-native equivalents:
|
||||
2. Keep DB as source of truth; use filesystem only for oversized artifacts.
|
||||
3. Build a single orchestrator service used by API, CLI, and extension tools.
|
||||
4. Add explicit attribution notes if any upstream code is directly copied.
|
||||
|
||||
## 10. Addendum (FN-3012): Planned target vs current landed state
|
||||
|
||||
This document captures the original porting plan. As of FN-3012 preflight, the repository now has a landed research subsystem in concrete files including:
|
||||
- `packages/core/src/research-types.ts`, `research-store.ts`, `research-settings.ts`
|
||||
- `packages/dashboard/src/research-routes.ts` and `packages/dashboard/app/components/ResearchView.tsx`
|
||||
- `packages/engine/src/research-orchestrator.ts` and `research-step-runner.ts`
|
||||
- `packages/cli/src/commands/research.ts` and extension tools `fn_research_*`
|
||||
|
||||
Important boundary clarification:
|
||||
- The research subsystem and the insights subsystem are both present and remain separate/parallel (`research_runs`/`research_exports` vs `project_insights`/`project_insight_runs`).
|
||||
- Follow-on hardening tasks should target current landed files, not the historical placeholder path examples in the original FN-299x chain.
|
||||
|
||||
231
docs/research/research-hardening-preflight.md
Normal file
231
docs/research/research-hardening-preflight.md
Normal file
@@ -0,0 +1,231 @@
|
||||
# Research Hardening Preflight + Shape Freeze (FN-3012)
|
||||
|
||||
Date: 2026-05-02
|
||||
|
||||
## 1) Preflight verdict (dependency check against FN-2998 contract)
|
||||
|
||||
**Outcome:** **landed research subsystem present** (with naming drift from the FN-2998 prompt examples).
|
||||
|
||||
### Evidence from repository state
|
||||
|
||||
Present research-layer files/routes/types:
|
||||
- `packages/core/src/research-types.ts`
|
||||
- `packages/core/src/research-store.ts`
|
||||
- `packages/core/src/research-settings.ts`
|
||||
- `packages/dashboard/src/research-routes.ts` (**present; named differently than spec example `register-research-routes.ts`**)
|
||||
- `packages/dashboard/src/__tests__/research-routes.test.ts`
|
||||
- `packages/dashboard/app/components/ResearchView.tsx`
|
||||
- `packages/dashboard/app/hooks/useResearch.ts`
|
||||
- `packages/cli/src/commands/research.ts`
|
||||
- `packages/cli/src/commands/__tests__/research.test.ts`
|
||||
- `packages/cli/src/extension.ts` research tool surface (`fn_research_*` tools)
|
||||
- `packages/engine/src/research-orchestrator.ts`
|
||||
- `packages/engine/src/research-step-runner.ts`
|
||||
- `packages/engine/src/research/provider-registry.ts`
|
||||
|
||||
Also mounted in dashboard API integration:
|
||||
- `packages/dashboard/src/routes/register-integrated-routers.ts` mounts `createResearchRouter(store)` at `/api/research`
|
||||
|
||||
Database schema is present:
|
||||
- `packages/core/src/db.ts` includes `research_runs` and `research_exports`
|
||||
- existing insights schema (`project_insights`, `project_insight_runs`) remains present and separate
|
||||
|
||||
### FN-2998 expected-path comparison
|
||||
|
||||
Prompt examples that were expected but differ in exact path/name:
|
||||
- `packages/dashboard/src/routes/register-research-routes.ts` → **actual:** `packages/dashboard/src/research-routes.ts`
|
||||
- `packages/cli/src/commands/research*` → **actual:** `packages/cli/src/commands/research.ts`
|
||||
- `packages/core/src/*research*` modules → **actual:** present (`research-types.ts`, `research-store.ts`, `research-settings.ts`)
|
||||
|
||||
No blocker condition detected in preflight; dependency is considered landed.
|
||||
|
||||
---
|
||||
|
||||
## 2) Verified module/file inventory (present vs absent vs speculative)
|
||||
|
||||
## 2.1 Core persistence/domain surface
|
||||
|
||||
### Present
|
||||
- `packages/core/src/research-types.ts`
|
||||
- Exports: `ResearchRun`, `ResearchRunStatus`, `ResearchSource`, `ResearchResult`, `ResearchExport`, orchestration types (`ResearchOrchestrationConfig`, `ResearchOrchestrationStep`, etc.)
|
||||
- `packages/core/src/research-store.ts`
|
||||
- Class `ResearchStore` with concrete methods:
|
||||
- run lifecycle: `createRun`, `getRun`, `updateRun`, `listRuns`, `deleteRun`, `updateStatus`, `retryRun` support via orchestrator
|
||||
- run detail mutation: `addEvent`/`appendEvent`, `addSource`, `updateSource`, `setResults`
|
||||
- exports: `createExport`, `getExports`, `getExport`
|
||||
- discovery/stats: `searchRuns`, `getStats`
|
||||
- `packages/core/src/store.ts`
|
||||
- `TaskStore.getResearchStore()` and `TaskStore.getInsightStore()` both exist; each lazily instantiates separate stores
|
||||
- `packages/core/src/db.ts`
|
||||
- `research_runs`, `research_exports` schema + indexes
|
||||
- separate insight tables: `project_insights`, `project_insight_runs`
|
||||
|
||||
### Absent
|
||||
- No unified/merged “research+insight” store class. They are separate stores attached to `TaskStore`.
|
||||
|
||||
### Speculative-from-old-contract only
|
||||
- Any imagined `register-research-routes.ts` location (not present under that name)
|
||||
|
||||
## 2.2 Dashboard API surface
|
||||
|
||||
### Present
|
||||
- `packages/dashboard/src/research-routes.ts` (`createResearchRouter`):
|
||||
- run endpoints: `GET /runs`, `POST /runs`, `GET /runs/:id`, `POST /runs/:id/cancel`, `POST /runs/:id/retry`, `PATCH /runs/:id`, `DELETE /runs/:id`
|
||||
- output endpoints: `GET /runs/:id/export`, `POST /runs/:id/exports`, `GET /runs/:id/exports`, `GET /exports/:exportId`
|
||||
- detail endpoints: `POST /runs/:id/events`, `POST /runs/:id/sources`, `PATCH /runs/:id/sources/:sourceId`, `PUT /runs/:id/results`, `PATCH /runs/:id/status`, `GET /stats`, `GET /search`
|
||||
- task integration endpoints from FN-2998 chain:
|
||||
- `POST /runs/:runId/findings/:findingId/task`
|
||||
- `POST /runs/:runId/findings/:findingId/tasks/:taskId/enrich`
|
||||
- `packages/dashboard/src/routes/register-integrated-routers.ts`
|
||||
- mounts research router at `/api/research`
|
||||
- `packages/dashboard/src/insights-routes.ts`
|
||||
- separate insight run/insight CRUD and `/api/insights/run` extraction path
|
||||
|
||||
### Absent
|
||||
- No route file named `register-research-routes.ts`.
|
||||
|
||||
### Speculative-only
|
||||
- Any assumption that research runs are served from `/api/insights/*`.
|
||||
|
||||
## 2.3 Dashboard UI/client surface
|
||||
|
||||
### Present
|
||||
- `packages/dashboard/app/components/ResearchView.tsx`
|
||||
- Research run create/list/detail actions
|
||||
- finding-level task creation/enrichment modal integration
|
||||
- `packages/dashboard/app/hooks/useResearch.ts`
|
||||
- uses `/api/research/*` endpoints via api layer
|
||||
- subscribes to SSE run lifecycle events (`research:run:*`) and polling fallback
|
||||
- `packages/dashboard/app/api/legacy.ts`
|
||||
- concrete research bindings under `/research/...` and insight bindings under `/insights/...` (both under `/api` prefix via shared `api()` helper)
|
||||
- `packages/dashboard/app/App.tsx`
|
||||
- lazy-loads `ResearchView` and `InsightsView` separately; each has distinct `taskView` gate
|
||||
|
||||
### Absent
|
||||
- No single combined “ResearchInsightsView”.
|
||||
|
||||
### Speculative-only
|
||||
- assumption that only insights UI exists and research UI is absent (not true in current repo)
|
||||
|
||||
## 2.4 Engine automation/orchestration surface
|
||||
|
||||
### Present
|
||||
- `packages/engine/src/research-orchestrator.ts`
|
||||
- phased run execution: planning → searching → fetching → synthesizing → finalizing
|
||||
- concurrency guard: `AgentSemaphore`
|
||||
- cancellation: `cancelRun()` via `AbortController`
|
||||
- retry support: `retryRun()`
|
||||
- `packages/engine/src/research-step-runner.ts`
|
||||
- timeout-wrapped provider query/fetch/synthesis with typed error classification
|
||||
- `packages/engine/src/project-engine.ts`
|
||||
- creates `ResearchOrchestrator` when `TaskStore.getResearchStore` exists
|
||||
- also independently wires insight extraction automation via cron + memory-insight pipeline
|
||||
|
||||
### Absent
|
||||
- no evidence that insight extraction cron directly writes research run tables.
|
||||
|
||||
## 2.5 CLI + extension surface
|
||||
|
||||
### Present
|
||||
- `packages/cli/src/commands/research.ts`
|
||||
- commands: run/create, list, show, export, cancel, retry; runtime bootstrap through orchestrator/provider registry
|
||||
- `packages/cli/src/extension.ts`
|
||||
- tools: `fn_research_run`, `fn_research_list`, `fn_research_get`, `fn_research_cancel`
|
||||
- separate insight tool family (`fn_insight_*`) coexists
|
||||
|
||||
### Absent
|
||||
- no extra `research-*` command split files; command is consolidated in one module.
|
||||
|
||||
---
|
||||
|
||||
## 3) Real lifecycle map (entry -> execution -> persistence -> UI)
|
||||
|
||||
## 3.1 Research lifecycle (landed)
|
||||
|
||||
1. Entry points:
|
||||
- Dashboard API: `POST /api/research/runs` (`research-routes.ts`)
|
||||
- CLI: `packages/cli/src/commands/research.ts` (`runResearchCreate`)
|
||||
- Extension tool: `fn_research_run` in `packages/cli/src/extension.ts`
|
||||
|
||||
2. Store creation:
|
||||
- `TaskStore.getResearchStore()` -> `ResearchStore.createRun()` writes `research_runs`
|
||||
|
||||
3. Orchestration execution:
|
||||
- Engine orchestrator (`research-orchestrator.ts`) runs phases with provider-backed `ResearchStepRunner`
|
||||
- statuses and events updated through `ResearchStore.updateStatus`/`addEvent`/`addSource`/`setResults`
|
||||
|
||||
4. Persistence:
|
||||
- run/event/source/result payloads in JSON columns of `research_runs`
|
||||
- exports in `research_exports`
|
||||
|
||||
5. Consumption/UI:
|
||||
- `useResearch.ts` reads `/api/research/runs` + `/api/research/runs/:id`
|
||||
- `ResearchView.tsx` displays summary/findings/events, exports, retry/cancel
|
||||
- finding actions call:
|
||||
- create task: `/api/research/runs/:runId/findings/:findingId/task`
|
||||
- enrich task: `/api/research/runs/:runId/findings/:findingId/tasks/:taskId/enrich`
|
||||
|
||||
6. Task linkage:
|
||||
- provenance uses `sourceType: "research"` and metadata via research route handlers
|
||||
- research markdown goes to task documents (`research-{sanitizedRunId}` key)
|
||||
|
||||
## 3.2 Adjacent insight lifecycle (still separate and landed)
|
||||
|
||||
1. Entry: `POST /api/insights/run` in `insights-routes.ts`
|
||||
2. AI extraction path: `createFnAgent` + `promptWithFallback` using memory extraction prompt
|
||||
3. Persistence path: `InsightStore` (`project_insights`, `project_insight_runs`) + memory-insight file updates
|
||||
4. UI path: `useInsights.ts` + `InsightsView.tsx` and `/api/insights/*`
|
||||
5. Automation path: project engine startup syncs/schedules insight extraction automation (cron)
|
||||
|
||||
---
|
||||
|
||||
## 4) Classification decision: standalone, layered, or absent?
|
||||
|
||||
**Decision: Research is a standalone landed subsystem that coexists with (and is adjacent to) the insights subsystem, not a thin wrapper over insights.**
|
||||
|
||||
Evidence:
|
||||
- Separate core types/stores (`research-*` vs `insight-*`)
|
||||
- Separate DB tables (`research_runs/research_exports` vs `project_insights/project_insight_runs`)
|
||||
- Separate dashboard route families (`/api/research/*` vs `/api/insights/*`)
|
||||
- Separate dashboard hooks/views (`useResearch` + `ResearchView` vs `useInsights` + `InsightsView`)
|
||||
- Separate CLI/extension tool families (`research` commands/tools vs `insight` tools)
|
||||
- Engine contains both research orchestrator path and insight extraction automation path as distinct flows
|
||||
|
||||
Relationship note:
|
||||
- They are **architecturally parallel** subsystems sharing project settings, task store root, and dashboard/engine host infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## 5) Hardening matrix for FN-3013 through FN-3017 (scope-frozen)
|
||||
|
||||
This matrix is bounded to safeguards only (timeouts, cancel, rate limits, error surfaces, regression coverage, verification sequencing).
|
||||
|
||||
| Follow-on | Primary lifecycle stage | Exact file targets (first-pass) | Scope guard |
|
||||
|---|---|---|---|
|
||||
| FN-3013 | Timeouts + cancellation reliability | `packages/engine/src/research-orchestrator.ts`, `packages/engine/src/research-step-runner.ts`, `packages/engine/src/research/providers/page-fetch-provider.ts`, `packages/engine/src/research/providers/web-search-provider.ts`, `packages/engine/src/research/providers/local-docs-provider.ts`, `packages/engine/src/research/providers/github-provider.ts`, `packages/engine/src/research/providers/llm-synthesis-provider.ts`, `packages/dashboard/src/research-routes.ts`, `packages/cli/src/commands/research.ts`, `packages/cli/src/extension.ts` | No new providers/modules; strengthen abort propagation, timeout classification, and route/CLI cancellation semantics |
|
||||
| FN-3014 | Rate limiting/backpressure | `packages/engine/src/research-orchestrator.ts`, `packages/engine/src/research/provider-registry.ts`, `packages/engine/src/research/providers/index.ts`, `packages/engine/src/research/providers/page-fetch-provider.ts`, `packages/engine/src/research/providers/web-search-provider.ts`, `packages/engine/src/research/providers/local-docs-provider.ts`, `packages/engine/src/research/providers/github-provider.ts`, `packages/engine/src/research/providers/llm-synthesis-provider.ts`, `packages/engine/src/agent-tools.ts`, `packages/core/src/research-settings.ts`, `packages/core/src/research-types.ts`, settings consumers in `packages/engine/src/project-engine.ts` | Tune and enforce existing limits; avoid adding novel provider architecture |
|
||||
| FN-3015 | Error surface normalization | `packages/dashboard/src/research-routes.ts`, `packages/dashboard/app/api/legacy.ts`, `packages/dashboard/app/hooks/useResearch.ts`, `packages/dashboard/app/components/ResearchView.tsx`, `packages/cli/src/commands/research.ts`, `packages/cli/src/commands/__tests__/research.test.ts`, `packages/dashboard/src/__tests__/research-routes.test.ts` | Normalize user-facing error payloads/states only; no UX expansion beyond existing view/actions |
|
||||
| FN-3016 | Regression coverage expansion | `packages/dashboard/src/__tests__/research-routes.test.ts`, `packages/cli/src/commands/__tests__/research.test.ts`, `packages/engine/src/__tests__/research-orchestrator.test.ts`, `packages/engine/src/__tests__/research-step-runner.test.ts`, `packages/engine/src/research/providers/__tests__/*.test.ts` | Add behavior tests around cancellations/timeouts/rate-limits/error mapping |
|
||||
| FN-3017 | Full verification and integration gate | workspace verification commands + touched tests around research/insights seams | Verify research hardening does not regress insights flows or task integration endpoints |
|
||||
|
||||
## sequencing
|
||||
1. FN-3013 first (cancel/timeout correctness)
|
||||
2. FN-3014 second (rate/backpressure), because limits interact with cancel behavior
|
||||
3. FN-3015 third (error contract consistency after behavior stabilizes)
|
||||
4. FN-3016 fourth (lock regressions)
|
||||
5. FN-3017 final integration gate
|
||||
|
||||
## non-goals (frozen)
|
||||
- No new research providers
|
||||
- No new research UI surfaces beyond current ResearchView/task-action flows
|
||||
- No schema redesign across research/insights
|
||||
- No migration of insights pipeline into research subsystem
|
||||
|
||||
---
|
||||
|
||||
## 6) Blockers status
|
||||
|
||||
- **No dependency blocker detected for FN-2998 in current repo state.**
|
||||
- Existing research subsystem is landed and test-covered (`research-routes.test.ts`, CLI research tests).
|
||||
- Hardening tasks should target **current concrete files above**, not speculative `register-research-routes.ts` or hypothetical merged insight/research modules.
|
||||
- Architecture docs were updated in this task to add a dedicated `Research Runs` section and explicit research-vs-insights boundary note (`docs/architecture.md`).
|
||||
Reference in New Issue
Block a user