From 902e303c40b446ca3b446b46d098a0e0b7638bbd Mon Sep 17 00:00:00 2001 From: Fabro Date: Wed, 15 Apr 2026 11:54:35 -0400 Subject: [PATCH] checkpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚒️ Generated with [Fabro](https://fabro.sh) --- checkpoint.json | 25 ++++++++++++++++----- nodes/preflight_compile/script_timing.json | 7 ++++++ nodes/preflight_compile/status.json | 6 +++++ nodes/preflight_lint/script_invocation.json | 5 +++++ 4 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 nodes/preflight_compile/script_timing.json create mode 100644 nodes/preflight_compile/status.json create mode 100644 nodes/preflight_lint/script_invocation.json diff --git a/checkpoint.json b/checkpoint.json index 6ac22753e..d14c6d1f5 100644 --- a/checkpoint.json +++ b/checkpoint.json @@ -1,14 +1,16 @@ { - "timestamp": "2026-04-15T15:54:08.186983Z", - "current_node": "preflight_compile", + "timestamp": "2026-04-15T15:54:35.496300Z", + "current_node": "preflight_lint", "completed_nodes": [ "start", "toolchain", - "preflight_compile" + "preflight_compile", + "preflight_lint" ], "node_retries": {}, "context_values": { "command.stderr": "", + "internal.retry_count.preflight_lint": 0, "graph.model_stylesheet": "\n * { model: claude-opus-4-6; }\n ", "graph.rankdir": "LR", "failure_signature": "", @@ -16,7 +18,8 @@ "thread.toolchain.current_node": "preflight_compile", "internal.fidelity": "compact", "internal.run_id": "01KP8XFY02RXHCR69H9FQ02X64", - "internal.thread_id": "toolchain", + "thread.preflight_compile.current_node": "preflight_lint", + "internal.thread_id": "preflight_compile", "internal.retry_count.start": 0, "outcome": "success", "internal.retry_count.preflight_compile": 0, @@ -24,7 +27,7 @@ "internal.node_visit_count": 1, "failure_class": "", "thread.start.current_node": "toolchain", - "current_node": "preflight_compile", + "current_node": "preflight_lint", "graph.goal": "# Canonical `Blocked` Run Status Plan\n\n## Summary\n\n- Make `Blocked` a first-class shared run status across the durable projection, server, OpenAPI, generated TypeScript client, web UI, and CLI.\n- Keep `Paused` separate. `Paused` remains operator intent; `Blocked` means the run cannot proceed until an external condition is resolved.\n- This is a full status-unification pass: align the shared contract on `submitted`, `queued`, `starting`, `running`, `blocked`, `paused`, `removing`, `completed`, `failed`, and `cancelled`; remove `dead` from the canonical serialized lifecycle.\n- No alerting/email in this pass. `BlockedReason` is introduced now so notification work can key off a stable domain contract later.\n\n## Key Changes\n\n- Canonical status contract: update [docs/api-reference/fabro-api.yaml](/Users/bhelmkamp/p/fabro-sh/fabro/docs/api-reference/fabro-api.yaml), [lib/crates/fabro-types/src/status.rs](/Users/bhelmkamp/p/fabro-sh/fabro/lib/crates/fabro-types/src/status.rs), and the generated models under `lib/packages/fabro-api-client/src/models/`.\n- Public/internal type changes:\n - Add `Queued`, `Blocked`, `Completed`, and `Cancelled` to the shared Rust `RunStatus`.\n - Rename shared/internal `Succeeded` usages to `Completed`.\n - Add nullable `blocked_reason` with a new `BlockedReason` enum; initial value set is `human_input_required`.\n - Remove `Dead` from OpenAPI and generated API/client status enums. Callers that currently fall back to `Dead` must instead treat status as missing/unknown locally.\n - Add `blocked` to the `RunStatus` and `InternalRunStatus` enums in `fabro-api.yaml`.\n- Projection and summary behavior: update [lib/crates/fabro-store/src/run_state.rs](/Users/bhelmkamp/p/fabro-sh/fabro/lib/crates/fabro-store/src/run_state.rs), `lib/crates/fabro-store/src/types.rs`, and `lib/crates/fabro-store/src/slate/mod.rs`.\n - Persist `Queued` as a real durable state by appending/projecting a `run.queued` transition when a run is start-requested and enqueued.\n - Project `run.failed` with `reason=cancelled` to canonical `Cancelled`.\n - Set canonical `Blocked` on `interview.started` with `blocked_reason=human_input_required`.\n - Clear `blocked_reason` and return to `Running` on `interview.completed`, `interview.timeout`, or `interview.interrupted` when no pending interviews remain.\n - Keep `Paused` driven only by pause/unpause control events; interview events must never produce `Paused`.\n - Update transition helpers so `Blocked` is non-terminal and `Completed`/`Failed`/`Cancelled` are terminal.\n- Server/live read model: update [lib/crates/fabro-server/src/server.rs](/Users/bhelmkamp/p/fabro-sh/fabro/lib/crates/fabro-server/src/server.rs) and `lib/crates/fabro-server/src/demo/mod.rs`.\n - Remove the ad-hoc API remap layer; server responses should expose the canonical shared status directly.\n - Extend run status payloads and durable summaries to include `blocked_reason` alongside `status_reason` and `pending_control`.\n - Extend `update_live_run_from_event()` so `InterviewStarted` drives `Blocked`, and interview resolution (`InterviewCompleted`/`InterviewTimeout`/`InterviewInterrupted`) returns live runs to `Running` when no pending interviews remain.\n - Keep `/runs/{id}/questions` and answer submission unchanged; those endpoints remain the detailed question surface behind a blocked run.\n- Board/UI model:\n - Change board columns to `working`, `blocked`, `review`, `merge`.\n - Map `Running` and `Paused` to `working`; map `Blocked` to `blocked`; map `Completed` to `merge`; keep `Submitted`, `Queued`, `Starting`, `Failed`, and `Cancelled` off-board.\n - Keep paused runs in the working lane with no extra indicator in this pass.\n - Update web mappings in `apps/fabro-web/app/{data/runs.ts,routes/run-detail.tsx,routes/runs.tsx}` so `blocked` is a real lifecycle/board value and `waiting` is removed.\n - Because this pass does not add a new `run.blocked` event family, update `STATUS_EVENTS` in `apps/fabro-web/app/routes/runs.tsx` to include `interview.started`, `interview.completed`, `interview.timeout`, and `interview.interrupted` as status-affecting events.\n- CLI consumers: update `lib/crates/fabro-cli/src/{commands/run/wait.rs,commands/runs/list.rs,server_runs.rs}`.\n - Replace `Succeeded`/`Dead` handling with `Completed` plus explicit missing-status handling.\n - Add display/color handling for `Blocked`, `Queued`, and `Cancelled`.\n\n## Test Plan\n\n- `lib/crates/fabro-store/src/run_state.rs`:\n - `interview.started` sets `status=Blocked` and `blocked_reason=HumanInputRequired`.\n - interview completion/timeout/interruption returns the run to `Running` when no pending interviews remain.\n - pause/unpause still yields `Paused`/`Running` and never routes through `Blocked`.\n - cancelled failures project to `Cancelled`.\n - queued state round-trips through projection serialization.\n- `lib/crates/fabro-store/src/slate/mod.rs` and `lib/crates/fabro-server/src/server.rs`:\n - durable summaries and `/runs/{id}` responses expose unified statuses plus `blocked_reason`.\n - no serialized API/store status is `dead`.\n - live managed runs enter `Blocked` while a pending interview exists.\n - board response emits a `blocked` column, places blocked runs there with question text, and keeps paused runs in `working`.\n- `apps/fabro-web/app/data/runs.test.ts` and a new `apps/fabro-web/app/routes/runs.test.tsx`:\n - summary mapping accepts `blocked`, `paused`, `completed`, and `cancelled`.\n - blocked runs render in the blocked lane with the existing answer-question affordance.\n - paused runs stay in the working lane.\n - no UI code depends on `waiting`.\n- CLI tests in `lib/crates/fabro-cli/src/commands/run/wait.rs` and `lib/crates/fabro-cli/src/commands/runs/list.rs`:\n - `Completed` is the success exit state.\n - `Blocked`, `Queued`, and `Cancelled` render correctly.\n - missing status no longer masquerades as `Dead`.\n - `Succeeded` is no longer accepted or displayed; all success paths use `Completed`.\n\n## Assumptions\n\n- `BlockedReason` starts with one value only: `human_input_required`.\n- Notification behavior is intentionally deferred; this plan only makes blocked state canonical and queryable.\n- `RunListItem.question` stays optional and unchanged in shape; `Blocked` plus `question` is sufficient for current UI behavior.\n- `Paused` remains visible in the working board column for now; the paused-specific visual indicator is a separate follow-up.\n" }, "node_outcomes": { @@ -37,6 +40,15 @@ "notes": "Script completed: cargo check -q --workspace 2>&1", "usage": null }, + "preflight_lint": { + "status": "success", + "context_updates": { + "command.output": "", + "command.stderr": "" + }, + "notes": "Script completed: cargo clippy -q --workspace -- -D warnings 2>&1", + "usage": null + }, "start": { "status": "success", "usage": null @@ -51,8 +63,9 @@ "usage": null } }, - "next_node_id": "preflight_lint", + "next_node_id": "implement", "node_visits": { + "preflight_lint": 1, "start": 1, "toolchain": 1, "preflight_compile": 1 diff --git a/nodes/preflight_compile/script_timing.json b/nodes/preflight_compile/script_timing.json new file mode 100644 index 000000000..11503d475 --- /dev/null +++ b/nodes/preflight_compile/script_timing.json @@ -0,0 +1,7 @@ +{ + "stdout": "", + "stderr": "", + "exit_code": 0, + "duration_ms": 92359, + "timed_out": false +} \ No newline at end of file diff --git a/nodes/preflight_compile/status.json b/nodes/preflight_compile/status.json new file mode 100644 index 000000000..dcbf36930 --- /dev/null +++ b/nodes/preflight_compile/status.json @@ -0,0 +1,6 @@ +{ + "status": "success", + "notes": "Script completed: cargo check -q --workspace 2>&1", + "failure_reason": null, + "timestamp": "2026-04-15T15:54:08.186736Z" +} \ No newline at end of file diff --git a/nodes/preflight_lint/script_invocation.json b/nodes/preflight_lint/script_invocation.json new file mode 100644 index 000000000..110dc7c37 --- /dev/null +++ b/nodes/preflight_lint/script_invocation.json @@ -0,0 +1,5 @@ +{ + "script": "cargo clippy -q --workspace -- -D warnings 2>&1", + "command": "cargo clippy -q --workspace -- -D warnings 2>&1", + "language": "shell" +} \ No newline at end of file