feat(FN-4218): complete Steps 2-5 — schema, store, tests, and docs
Fusion-Task-Id: FN-4218 Fusion-Task-Lineage: 0b50d7f4-5001-4eb6-9633-7b24b00097fd
This commit is contained in:
88
docs/research/experiment-session-model.md
Normal file
88
docs/research/experiment-session-model.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Experiment Session Domain Model
|
||||
|
||||
## Motivation
|
||||
|
||||
`pi-autoresearch` parity requires a persistent session model for iterative experiment loops (configure → run → evaluate keep/discard → finalize). Existing `research_runs` is query/synthesis-oriented and cannot represent session segments, metric direction, or append-only experiment records.
|
||||
|
||||
## Entity Model
|
||||
|
||||
```text
|
||||
experiment_sessions (1) ──< (many) experiment_session_records
|
||||
|
||||
Session
|
||||
├─ metric definition (name/unit/direction)
|
||||
├─ currentSegment
|
||||
├─ baselineRunId / bestRunId
|
||||
└─ keptRunIds[]
|
||||
|
||||
Record (append-only by seq per session)
|
||||
├─ config (segment headers)
|
||||
├─ run (metric outcomes + keep/discard/checks_failed/etc.)
|
||||
├─ hook (before/after hook execution)
|
||||
└─ finalize (kept/discarded summary + branch metadata)
|
||||
```
|
||||
|
||||
## SQLite Schema
|
||||
|
||||
### `experiment_sessions`
|
||||
- `id` TEXT PK
|
||||
- `name` TEXT NOT NULL
|
||||
- `projectId` TEXT
|
||||
- `status` TEXT NOT NULL (`active|finalizing|finalized|archived`)
|
||||
- `metric` TEXT NOT NULL (JSON)
|
||||
- `currentSegment` INTEGER NOT NULL DEFAULT `1`
|
||||
- `maxIterations` INTEGER
|
||||
- `workingDir` TEXT
|
||||
- `baselineRunId` TEXT
|
||||
- `bestRunId` TEXT
|
||||
- `keptRunIds` TEXT NOT NULL DEFAULT `'[]'`
|
||||
- `tags` TEXT NOT NULL DEFAULT `'[]'`
|
||||
- `metadata` TEXT
|
||||
- `createdAt` TEXT NOT NULL
|
||||
- `updatedAt` TEXT NOT NULL
|
||||
- `finalizedAt` TEXT
|
||||
|
||||
Indexes: status, projectId, createdAt.
|
||||
|
||||
### `experiment_session_records`
|
||||
- `id` TEXT PK
|
||||
- `sessionId` TEXT NOT NULL FK → `experiment_sessions(id)` ON DELETE CASCADE
|
||||
- `segment` INTEGER NOT NULL
|
||||
- `seq` INTEGER NOT NULL
|
||||
- `type` TEXT NOT NULL (`config|run|hook|finalize`)
|
||||
- `payload` TEXT NOT NULL (JSON)
|
||||
- `createdAt` TEXT NOT NULL
|
||||
|
||||
Constraints/indexes:
|
||||
- `UNIQUE(sessionId, seq)`
|
||||
- `(sessionId, segment, seq)` index
|
||||
- `(sessionId, type)` index
|
||||
|
||||
## Status State Machine
|
||||
|
||||
`active` → `finalizing` → `finalized` → `archived`
|
||||
|
||||
Rules:
|
||||
- Records are append-only.
|
||||
- `seq` is allocated monotonically per session inside a transaction.
|
||||
- Appending is rejected for `finalized` and `archived` sessions.
|
||||
- Transitioning to `finalized` sets `finalizedAt` if unset.
|
||||
|
||||
## Upstream Mapping
|
||||
|
||||
| Upstream concept (`pi-autoresearch`) | Fusion model |
|
||||
|---|---|
|
||||
| `ExperimentState` | `ExperimentSession` |
|
||||
| Metric (`name/unit/direction`) | `ExperimentMetricDefinition` + `experiment_sessions.metric` |
|
||||
| Segment reset via config row | `startNewSegment()` + `config` record |
|
||||
| Iteration result | `run` record payload |
|
||||
| Hook log entry | `hook` record payload |
|
||||
| Keep/discard ledger | `run.status` + session `keptRunIds[]` |
|
||||
| Baseline/current best pointers | `baselineRunId`, `bestRunId` |
|
||||
| Finalization summary | `finalize` record payload + session status/finalizedAt |
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- **FN-4219**: executor/orchestrator loop (`init/run/log`) and runtime integration.
|
||||
- **FN-4221**: unify dashboard/CLI/extension/engine surfaces with one execution contract.
|
||||
- **FN-4222**: finalize workflow and branch-splitting parity.
|
||||
@@ -98,7 +98,7 @@ Important execution nuance:
|
||||
- **Backend settings keys defined in `@fusion/core`:** **78** total
|
||||
- **Global settings:** 17 (`GlobalSettings`)
|
||||
- **Project settings:** 61 (`ProjectSettings`)
|
||||
- **SQLite tables in project DB schema (`packages/core/src/db.ts`):** **43** (including migration-created tables)
|
||||
- **SQLite tables in project DB schema (`packages/core/src/db.ts`):** **45** (including migration-created tables)
|
||||
- **Issues identified:** **9**
|
||||
- High: 2
|
||||
- Medium: 5
|
||||
@@ -310,6 +310,8 @@ The `tasks.githubTracking` JSON column stores per-task GitHub tracking state (`e
|
||||
| `research_runs` | Research run state (query, topic, status, lifecycle, sources, results, citations, events, exports, token usage). Supports project-scoped active-run uniqueness via `(projectId, trigger, status)` index. Terminal runs are immutable. |
|
||||
| `research_exports` | Persisted export records for research runs (`runId` FK cascade). Stores format, content, and optional file path. |
|
||||
| `research_run_events` | Append-only event log for research run lifecycle tracking (`runId` FK cascade, ordered by `seq`). Records status transitions, phase changes, step lifecycle, and failure classifications. |
|
||||
| `experiment_sessions` | Experiment-loop session envelope for pi-autoresearch parity (`name`, metric definition JSON, status, current segment, baseline/best run pointers, kept run IDs, tags/metadata, timestamps). |
|
||||
| `experiment_session_records` | Append-only ordered experiment records per session (`config`/`run`/`hook`/`finalize`) with per-session contiguous `seq`, segment number, JSON payload, and cascade delete via `sessionId` FK. |
|
||||
| `eval_runs` | Eval run lifecycle state (status, trigger, scope, evaluation window boundaries, evaluated task IDs/counts, aggregate scores, provenance). |
|
||||
| `eval_task_results` | Per-task eval outcomes linked to runs (`runId` FK cascade), including durable task snapshots and structured score payloads. `categoryScores[]` stores canonical per-category fields (`category`, `deterministicScore`, `aiScore`, `finalScore`, `weight`, `band`, `rationale`, `evidence[]`), plus `overallScore` derived from category finals. Also stores deterministic/AI signal payloads, summary rationale, structured follow-up suggestions (`suggestionId`, `dedupeKey`, recommendation, lifecycle state, suppression fields, optional `createdTaskId` linkage), and a bounded `TaskEvaluationEvidenceBundle` (fixed source-order groups, capped entry counts, max 500-char excerpts with truncation marker) embedded in result metadata for backward-compatible persistence. |
|
||||
| `eval_run_events` | Append-only eval run event trail (`runId` FK cascade, ordered by `seq`) for orchestration/debug auditing and downstream API/UI drill-down. |
|
||||
|
||||
Reference in New Issue
Block a user