3.1 KiB
3.1 KiB
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
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
idTEXT PKnameTEXT NOT NULLprojectIdTEXTstatusTEXT NOT NULL (active|finalizing|finalized|archived)metricTEXT NOT NULL (JSON)currentSegmentINTEGER NOT NULL DEFAULT1maxIterationsINTEGERworkingDirTEXTbaselineRunIdTEXTbestRunIdTEXTkeptRunIdsTEXT NOT NULL DEFAULT'[]'tagsTEXT NOT NULL DEFAULT'[]'metadataTEXTcreatedAtTEXT NOT NULLupdatedAtTEXT NOT NULLfinalizedAtTEXT
Indexes: status, projectId, createdAt.
experiment_session_records
idTEXT PKsessionIdTEXT NOT NULL FK →experiment_sessions(id)ON DELETE CASCADEsegmentINTEGER NOT NULLseqINTEGER NOT NULLtypeTEXT NOT NULL (config|run|hook|finalize)payloadTEXT NOT NULL (JSON)createdAtTEXT 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.
seqis allocated monotonically per session inside a transaction.- Appending is rejected for
finalizedandarchivedsessions. - Transitioning to
finalizedsetsfinalizedAtif 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 |
Store API Notes
recordKept(sessionId, runRecordId)is idempotent and only appends missing run IDs.updateRecordPayload(recordId, patch)applies additive payload patches for existing records (used by executor to backfill run commit SHA after keep commits).
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.