Expand description
HTTP surface for the Task/Run persistence axis (issue #13 ID hierarchy;
GET /v1/tasks, GET /v1/tasks/:id, POST /v1/tasks/:id/runs,
GET /v1/runs/:id). POST /v1/tasks itself stays in this module (it is
the entry point tasks_start shares with the flow-eval path) — see the
tasks module doc for the split rationale.
HTTP surface for the Task/Run persistence axis (issue #13 ID-hierarchy
reconciliation: Blueprint → Task → Run → Step → Attempt).
GET /v1/tasks— list every persistedTaskRecord, newest first.GET /v1/tasks/:id— aTaskRecordplus everyRunRecordkicked from it.POST /v1/tasks/:id/runs— re-kick an existing Task: mints a freshRunId, re-resolves the storedblueprint_ref(refreshingBlueprint.default_init_ctxexactly like original launch time — issue #19 ST4), 3-layer-merges it withTaskRecord.input_ctxand an optionalRunKickRequestbody’sinit_ctx_override(see [merge_init_ctx_3layer]), dispatches throughTaskApplication::handle_with_run, and returns the new{task_id, run_id}pair. A body-less request (or one that omits both fields) preserves the pre-#19 rekick behavior byte-for-byte.GET /v1/runs/:id— a singleRunRecord(step_entriestrace included).GET /v1/runs/:id/bindings— requested/effective binding explain from the immutable launch snapshot (never from the current Blueprint).POST /v1/runs/:id/resume— resume anInterruptedRun under the SAMErun_id(replay cursor + stored launch-input snapshot).POST /v1/runs/:id/rerun-from— GH #71 Layer A. Rerun a terminal Run (Done/Failed/Interrupted) from a caller-specified step under the SAMErun_id; physically truncates the replay log at the cut point so re-dispatch does not collide with the pre-rerun rows. See [run_rerun_from] for the full contract + Known Limitations.
POST /v1/tasks itself (the flow-eval entry point, tasks_start /
run_flow_form) stays in crate::lib — it is the pre-existing
Operator-inject-aware dispatch path this module’s handlers re-kick
through, not a new one. This module owns the read/list/re-kick surface
plus the [finalize_run] persistence helper both paths share.
Authorization follows the same convention as the existing POST /v1/tasks
entry: no Authorization header is required (the route is open), and the
only Operator-session correlation available is the request-body-level
operator_sid (see crate::TaskLaunchRequest doc) — this module invents no
new auth mechanism.
Structs§
- RunBinding
Difference - Mechanical requested/effective comparison for one immutable binding.
- RunBinding
Explain Entry - Explain view for one agent, derived exclusively from the persisted Run snapshot rather than from the current Blueprint registry.
- RunBindings
Explain Response - Response body for
GET /v1/runs/:id/bindings. - RunKick
Request - Request body for
POST /v1/tasks/:id/runs(issue #19 ST4) — every field is optional, and the body itself is optional (seetask_rekick’sOption<Json<Self>>parameter); a caller that sends no body, or{}, or omits a field gets exactly today’s rekick behavior for that layer. - RunKick
Response - Response body for
POST /v1/tasks/:id/runs. - RunRerun
From Request - Request body for
POST /v1/runs/:id/rerun-from(GH #71 Layer A). - RunRerun
From Response - Response body for
POST /v1/runs/:id/rerun-from(GH #71 Layer A). - RunResume
Response - Response body for
POST /v1/runs/:id/resume. - Task
Detail Response - Response body for
GET /v1/tasks/:id. - Tasks
List Query - Query params for
GET /v1/tasks.
Enums§
- RunBinding
Status - Whether a Run-scoped binding has only a declaration or also carries a provider attestation accepted by Core.
Functions§
- run_
bindings_ explain GET /v1/runs/:id/bindings. Explains the exact immutable agent bindings used by this Run. The handler never reads or resolves the current Blueprint; old Runs without a binding snapshot return422instead of guessed state.- run_get
GET /v1/runs/:id. Returns a singleRunRecord(itsstep_entriestrace included).- run_
rerun_ from POST /v1/runs/:id/rerun-from— GH #71 Layer A. Re-executes a specific step (and every downstream step) of a terminal Run under the SAMErun_id. Mirrorsrun_resume, with two deltas: it accepts any terminal status (Done/Failed/Interrupted) rather than onlyInterrupted, and it physically truncates the replay log at the cut point (viacrate::AppState::replay_store’sdelete_from) so that re-dispatch’sappenddoes not collide with the pre-rerun row and solist_by_runreflects the rerun’s real history rather than the pre-rerun ghost.- run_
resume POST /v1/runs/:id/resume. Resumes anInterruptedRun under the SAMErun_id(no newRunIdis minted): the stored launch-input snapshot (RunRecord.input_json) is rebuilt into aTaskApplicationInput, aReplayCursoris built from the Run’s logged step snapshots (ReplayStore::list_by_run), and the flow is re-dispatched with both wired into a freshRunContext. On dispatch the engine’s replay path returns each already-completed step’s stored value verbatim (cursor hit, no Adapter spawn) and dispatches only the steps that never finished — reconstructing the same final Ctx a restart-free run would have reached.- task_
get GET /v1/tasks/:id. Returns theTaskRecordplus everyRunRecordkicked from it (RunStore::list_by_task, oldest kick first).- task_
rekick POST /v1/tasks/:id/runs. Re-kicks an existing Task: reads its storedblueprint_ref, re-resolves it through [TaskApplication::resolve] (issue #19 ST4 — refreshesBlueprint.default_init_ctxexactly like original launch time, rather than replaying a launch-time-only snapshot), 3-layer-merges{bp default, TaskRecord.input_ctx, an optional per-Run override}viamerge_init_ctx_3layer, resolves the Task-level canonical fields (RunKickRequest.task_input_override, falling back toTaskRecord.task_input_spec), mints a freshRunId, dispatches throughTaskApplication::handle_with_run(the unadorned Operator-default path — no per-request Operator override support here, unlikePOST /v1/tasks; the stored Task carries no such preferences) plus a freshly-builtRunContext(issue #13 run_id propagation, so this kick’s steps get their ownstep_entriestrace), and persists the outcome via [finalize_run].- tasks_
list GET /v1/tasks?limit=N. Lists every persistedTaskRecord, newest first.