mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
6.6 KiB
6.6 KiB
Canonical RunProjection Simplification
Summary
Refactor RunProjection into a stricter canonical run-state type with no compatibility shims. Because there are no production deployments, make the breaking JSON/API changes directly and remove old field names, tuple encodings, default-empty projection states, and generated/client traces.
The end state: a RunProjection always represents a real run initialized from run.created; it has required spec, status, status_updated_at, and last_event_at; checkpoint history is named records; graph source lives in RunSpec; terminal diff lives in Conclusion; checkpoint diff lives on checkpoint records.
Key Type And API Changes
- Change
RunProjection:spec: RunSpec, notOption<RunSpec>.status: RunStatus, notOption<RunStatus>.status_updated_at: DateTime<Utc>andlast_event_at: DateTime<Utc>, not optional.- Remove top-level
graph_source,checkpoint,final_patch, anddiff_summary. - Keep
start,sandbox,pending_control,conclusion,pull_request, andsuperseded_byoptional because those are genuinely conditional lifecycle facts.
- Change
RunSpec:- Add
graph_source: Option<String>. - Keep existing optional git/provenance/blob/fork fields as optional.
- Add
- Change
StartRecord:- Remove redundant
run_id; keepstart_time,run_branch,base_sha.
- Remove redundant
- Add canonical types:
CheckpointRecord { seq: u32, checkpoint: Checkpoint, diff: RunDiff }.RunDiff { patch: Option<String>, summary: Option<DiffSummary> }.
- Change
RunProjection.checkpoints:- From
Vec<(u32, Checkpoint)>toVec<CheckpointRecord>. - Replace
current_checkpoint()withcheckpoints.last().map(|record| &record.checkpoint).
- From
- Change
Conclusion:- Add
diff: RunDiff. - Store terminal
final_patchasconclusion.diff.patch. - Store terminal
diff_summaryasconclusion.diff.summary.
- Add
- Change
PendingInterviewRecord.started_atto requiredDateTime<Utc>. - Change
StageProjection.stateto requiredStageState; initialize new stage projections asRunningunless immediately set to a terminal/skipped/retrying state.
Implementation Changes
- Rework projection construction:
- Remove
DefaultfromRunProjection. - Replace
RunProjection::default() + apply_eventwith initialization from the firstrun.createdevent. apply_events([])should error at the reducer level; store/cache code may still returnNonewhen a run has no events.- The first valid projection state is
Submitted, with both timestamps set to therun.createdtimestamp. run.submittedonly attachesdefinition_blob; it should not be needed to make the projection valid.
- Remove
- Rework incremental projection caches:
- Store projection cache state as
Option<RunProjection>untilrun.createdarrives. - Applying any non-
run.createdevent before initialization is an invalid event error.
- Store projection cache state as
- Update reducer mappings:
run.created.workflow_source->projection.spec.graph_source.run.started->StartRecord { start_time, run_branch, base_sha }.checkpoint.completed-> pushCheckpointRecord { seq, checkpoint, diff }.run.completed/run.failed-> setconclusion.diff.- Checkpoint diff summaries should be sourced from
checkpoints.last().diff.summary; terminal summaries fromconclusion.diff.summary.
- Keep
RunSummary.diff_summaryas a summary/list convenience field, derived from terminal conclusion diff when present, otherwise latest checkpoint diff. Do not reintroduce a top-level projection diff field. - Update OpenAPI and generated clients:
- Update
RunProjection,RunSpec,Conclusion,PendingInterviewRecord,StageProjection. - Add
CheckpointRecordandRunDiff. - Remove tuple checkpoint schema and generated
run-projection-checkpoints-inner-inner.ts. - Regenerate Rust API and TypeScript client after schema changes.
- Update
Cleanup: Leave No Trace
- Remove all code references to:
RunProjection::default().projection.graph_source.projection.checkpoint.projection.final_patch.projection.diff_summary.state.status.unwrap_or(...).- tuple checkpoint destructuring like
(seq, checkpoint).
- Remove obsolete tests and snapshots that assert old raw projection JSON with
graph_source,checkpoint,final_patch, nullablespec, nullablestatus, or tuple checkpoints. - Remove compatibility aliases, legacy deserializers, serde aliases, and migration logic for the old projection shape.
- Remove stale OpenAPI schemas and generated TypeScript models produced solely by the old tuple/nullable shape.
- Update comments and docs that refer to
RunProjection.final_patch; useconclusion.diff.patch. - Update dump/export code so
run.jsonuses the new canonical projection, graph source is read fromspec.graph_source, and checkpoint dump entries iterateCheckpointRecord.
Test Plan
- Rust type/API parity:
- Update
fabro-apiround-trip tests forRunProjection,StageProjection,PendingInterviewRecord, and add tests forCheckpointRecordandRunDiff. - Ensure
fabro-apigenerated types still reuse canonicalfabro_typesreplacements.
- Update
- Reducer behavior:
- Projection initializes only from
run.created. - Empty/missing-created event sequences fail clearly.
- Required timestamps/status/spec are always present after initialization.
- Checkpoint history serializes as named records and
current_checkpoint()derives from the last record. - Terminal events populate
conclusion.diff. - Checkpoint events populate
CheckpointRecord.diff. RunSummary.diff_summaryderives from terminal diff first, latest checkpoint diff otherwise.
- Projection initializes only from
- Server/API behavior:
/api/v1/runs/{id}/statereturns the new non-null canonical shape./api/v1/runs/{id}/checkpointstill returns latest checkpoint or null.- start/resume checks use derived current checkpoint.
- file fallback uses
conclusion.diff.patch.
- Frontend/CLI behavior:
- Update consumers of generated
RunProjection. - CLI inspect/dump/rewind/fork tests use derived current checkpoint and new diff location.
- Web run detail still shows diff summary via
RunSummary.diff_summary.
- Update consumers of generated
Verification
- Run
cargo build -p fabro-apiafter OpenAPI changes. - Regenerate TypeScript API client.
- Run focused tests for
fabro-types,fabro-store,fabro-api,fabro-server,fabro-cli, andapps/fabro-web. - Run
cargo nextest run --workspace. - Run
cd apps/fabro-web && bun test && bun run typecheck. - Finish with searches proving no old traces remain:
graph_sourceonly underRunSpec, noRunProjection::default, noprojection.checkpoint, noprojection.final_patch, no tuple checkpoint generated model.