Let reviews be stopped, and fail stuck reviewers automatically

This commit is contained in:
Ian Gulliver
2026-10-17 07:24:08 -07:00
parent 00cd1ed958
commit 9b3f775dac
11 changed files with 397 additions and 220 deletions
+15
View File
@@ -694,6 +694,21 @@ paths:
"400": { $ref: "#/components/responses/Error" } "400": { $ref: "#/components/responses/Error" }
"404": { $ref: "#/components/responses/Error" } "404": { $ref: "#/components/responses/Error" }
/api/reviews/{reviewId}/stop:
parameters:
- { name: reviewId, in: path, required: true, schema: { type: string } }
post:
operationId: stopReview
description: Ends a running review's reviewer and records the review as failed. Refused unless the review is running.
responses:
"200":
description: The review.
content:
application/json:
schema: { $ref: "#/components/schemas/Review" }
"404": { $ref: "#/components/responses/Error" }
"409": { $ref: "#/components/responses/Error" }
/api/tasks/{taskId}/snapshots/{n}/fork: /api/tasks/{taskId}/snapshots/{n}/fork:
parameters: parameters:
- { name: taskId, in: path, required: true, schema: { type: string } } - { name: taskId, in: path, required: true, schema: { type: string } }
+2 -2
View File
@@ -310,9 +310,9 @@ Every new snapshot of a task gets a review: a separate agent session on the vend
- **Starting.** After `takeSnapshot` creates a snapshot, `afterSnapshot` runs `startReviewer`: it picks the vendor opposite the task's latest implementer session (`reviewVendor`) and that vendor's model in `reviewModels`, checks the snapshot's commit out detached at `worktrees/<project-id>/review-<review-id>`, creates an `agent_sessions` row with `role` `reviewer` on the task (created by the task's creator), a `reviews` row (`running`, one per snapshot), and sends `reviewPrompt` as its first turn (actor `byre`): the change as `git diff` from the previous snapshot (the merge-base with the default branch for the first) with its changed files, the merge-base diff of all the task's work for context, and the task's first message to its agent. - **Starting.** After `takeSnapshot` creates a snapshot, `afterSnapshot` runs `startReviewer`: it picks the vendor opposite the task's latest implementer session (`reviewVendor`) and that vendor's model in `reviewModels`, checks the snapshot's commit out detached at `worktrees/<project-id>/review-<review-id>`, creates an `agent_sessions` row with `role` `reviewer` on the task (created by the task's creator), a `reviews` row (`running`, one per snapshot), and sends `reviewPrompt` as its first turn (actor `byre`): the change as `git diff` from the previous snapshot (the merge-base with the default branch for the first) with its changed files, the merge-base diff of all the task's work for context, and the task's first message to its agent.
- **Running.** Reviewer sessions get `reviewGuidance` and only the `submit_review` tool, whose arguments (`reviewSchema`: `change`, a few sentences of Markdown on what the change does, required and non-empty; a Markdown `summary`, which the guidance and schema require to be exactly "No significant findings." when there are no findings and otherwise a bulleted list with one line per finding; `findings`, each with `severity`, `category`, `title`, `detail`, `path`, `line`, `end_line` and `images`; and top-level `images`) become the review's `result` and mark it `done`. The guidance encourages, without requiring, Mermaid blocks for a data flow, call graph, state machine or schema the change alters, and screenshots when the change alters something visible. - **Running.** Reviewer sessions get `reviewGuidance` and only the `submit_review` tool, whose arguments (`reviewSchema`: `change`, a few sentences of Markdown on what the change does, required and non-empty; a Markdown `summary`, which the guidance and schema require to be exactly "No significant findings." when there are no findings and otherwise a bulleted list with one line per finding; `findings`, each with `severity`, `category`, `title`, `detail`, `path`, `line`, `end_line` and `images`; and top-level `images`) become the review's `result` and mark it `done`. The guidance encourages, without requiring, Mermaid blocks for a data flow, call graph, state machine or schema the change alters, and screenshots when the change alters something visible.
- **Forwarding.** When a submitted review has findings, byre sends them to the task's live agent as a `byre` message (`forwardFindings` and `findingsMessage` in `internal/agents/review.go`): each finding's severity, title, location and detail, under a preamble asking the agent to check each one against the code and its brief, act on those that hold up, and say in its final message which it acted on and which it left and why. It goes through `Manager.Message`, so it is queued like any message while the agent is mid-turn. A task with no live agent session gets nothing, and the log says `review findings not forwarded`. Forwarding doesn't set any finding's state; **fix** and **ignore** stay available. - **Forwarding.** When a submitted review has findings, byre sends them to the task's live agent as a `byre` message (`forwardFindings` and `findingsMessage` in `internal/agents/review.go`): each finding's severity, title, location and detail, under a preamble asking the agent to check each one against the code and its brief, act on those that hold up, and say in its final message which it acted on and which it left and why. It goes through `Manager.Message`, so it is queued like any message while the agent is mid-turn. A task with no live agent session gets nothing, and the log says `review findings not forwarded`. Forwarding doesn't set any finding's state; **fix** and **ignore** stay available.
- **Screenshots.** Reviewer sessions also get the Playwright MCP server (`playwrightMCP` in `internal/agents/review.go`: `npx @playwright/mcp` at a pinned version, headless Chrome, isolated profile, absolute file paths), passed to Claude as a `stdio` entry in `--mcp-config` and to Codex as `mcp_servers` in the thread's `config`. Its automatically named files go to `worktrees/<project-id>/review-<review-id>-media`, removed with the checkout. Each `images` entry is `{path, caption}`, the path absolute or relative to the checkout; at `submit_review` byre reads every one, refuses the whole submission (nothing recorded) for a missing file or one that isn't one of `store.ImageTypes` within `store.MaxBlobBytes`, then stores each as a blob and replaces its `path` with `blob`, since the files are deleted with the checkout. They run without the Stop-hook bounce, mid-turn delivery, end-of-turn commit, snapshots or turn summaries, and their `user.message` events carry no `head`. When the reviewer's turn ends byre completes its session, kills its process and removes the worktree; a review still `running` then fails with why (no submission, with the final message; an error; an interrupt). A process that exits mid-turn fails the review the same way. Merging or discarding the task fails its running reviews ("the task was closed") and ends their reviewers. On startup, a running reviewer resumes like any session, and a running review whose reviewer isn't `running` fails. - **Screenshots.** Reviewer sessions also get the Playwright MCP server (`playwrightMCP` in `internal/agents/review.go`: `npx @playwright/mcp` at a pinned version, headless Chrome, isolated profile, absolute file paths), passed to Claude as a `stdio` entry in `--mcp-config` and to Codex as `mcp_servers` in the thread's `config`. Its automatically named files go to `worktrees/<project-id>/review-<review-id>-media`, removed with the checkout. Each `images` entry is `{path, caption}`, the path absolute or relative to the checkout; at `submit_review` byre reads every one, refuses the whole submission (nothing recorded) for a missing file or one that isn't one of `store.ImageTypes` within `store.MaxBlobBytes`, then stores each as a blob and replaces its `path` with `blob`, since the files are deleted with the checkout. They run without the Stop-hook bounce, mid-turn delivery, end-of-turn commit, snapshots or turn summaries, and their `user.message` events carry no `head`. When the reviewer's turn ends byre completes its session, kills its process and removes the worktree; a review still `running` then fails with why (no submission, with the final message; an error; an interrupt). A process that exits mid-turn fails the review the same way. `StopReview` (`POST /api/reviews/{reviewId}/stop`, the Stop button on a running review's card) ends the reviewer the same way and fails the review ("the reviewer was stopped"), and `Watch` calls it for a reviewer whose process the health check finds `stuck` (no stream event for `StuckAfter`), which is how a reviewer whose connection died while the machine slept gets cleared. Merging or discarding the task fails its running reviews ("the task was closed") and ends their reviewers. On startup, a running reviewer resumes like any session, and a running review whose reviewer isn't `running` fails.
- **Events.** `review.started`, `review.finished` (state `done`, `failed` or `skipped`; a skipped review emits only `review.finished`) and `review.finding` (a finding's state set, with the user as actor) carry the whole review, with the task's ids and no `agent_session_id`. A reviewer's own events carry its session id and the task's ids: the transcript skips every event of a session whose `session.created` has `role` `reviewer`, and draws each `review.finished` as a note with its outcome; the lead's `read_transcript` leaves the reviewer's events out and shows each `review.finished` with its summary and findings (`reviewLine`). `GET /api/tasks/{taskId}/sessions` and everything that looks for the task's agent (`ListSessions`) see only implementer sessions. - **Events.** `review.started`, `review.finished` (state `done`, `failed` or `skipped`; a skipped review emits only `review.finished`) and `review.finding` (a finding's state set, with the user as actor) carry the whole review, with the task's ids and no `agent_session_id`. A reviewer's own events carry its session id and the task's ids: the transcript skips every event of a session whose `session.created` has `role` `reviewer`, and draws each `review.finished` as a note with its outcome; the lead's `read_transcript` leaves the reviewer's events out and shows each `review.finished` with its summary and findings (`reviewLine`). `GET /api/tasks/{taskId}/sessions` and everything that looks for the task's agent (`ListSessions`) see only implementer sessions.
- **UI.** The **Reviews** tab (`web/src/reviews.ts`) shows one review at a time, picked by snapshot (see "Snapshots" for the picker): its snapshot, state or severity counts, error, summary, screenshots and findings. The `change` field is not shown; it goes to the lead and into notes. A finding with `path` and `line` shows, under its title, the lines `line` to `end_line` plus 3 either side from that file's diff for the snapshot's step (`changes?snapshot=<n>&step=true`, the diff the reviewer was given), with new-file line numbers and the finding's own lines marked; it shows nothing when those lines aren't in the diff, and "diff not available" with the error once the task is closed. Screenshots link to the full image. Each open finding has **fix** and **ignore** buttons (also on review cards in the inbox). **fix** sends the finding's severity, title, location and detail to the task's agent as a message from the user: through `POST /api/sessions/{id}/messages` to its latest live session (queued like any message while the agent is mid-turn, see "Agent sessions"), or starting a session when it has none; the view stays where it is, so several findings can be sent in a row. Then it, or **ignore** on its own, records the finding's state (`fixed` or `ignored`) with `PUT /api/reviews/{reviewId}/findings/{index}`, the index being the finding's position in `result.findings`; the review's `finding_states` (the `reviews.finding_states` column, a JSON object from index to state) holds them, and the buttons give way to "fix sent" or "ignored". Only a `done` review's findings take a state, and there is no way to clear one. The tab loads when it opens, when the task changes, and on each `review.*` event in the task's stream. The tab follows the latest `review.*` event of the highest-numbered snapshot: while that review runs, the tab label (and its entry in the More menu) carries a spinner in place of any earlier review's count; once it finishes with open findings (those with no state), the tab (or the More menu holding it) is highlighted with a badge of their count. Each snapshot row's **review** button carries a mark over its top-right corner from that snapshot's latest `review.*` event: a spinner while the review runs, a grey ● when it was skipped, a green ✓ when it finished with no open findings, and, when it has open findings, the button highlighted with their count in a badge. A failed review leaves the button unmarked. While any of a task's reviews is `running` and its agent is idle, the task's state is `reviewing` (see "Task state in the store"), which the task switcher and the Project tab show as **Working** (see "Task state"). `GET /api/tasks/{taskId}/reviews` lists a task's reviews oldest first. `sqlite3 byre.db "SELECT id, task_id, snapshot_n, vendor, state, error FROM reviews ORDER BY created_at DESC LIMIT 20"` shows recent ones. - **UI.** The **Reviews** tab (`web/src/reviews.ts`) shows one review at a time, picked by snapshot (see "Snapshots" for the picker): its snapshot, state or severity counts, error, summary, screenshots and findings, and, while it runs, a **Stop** button (`POST /api/reviews/{reviewId}/stop`). The `change` field is not shown; it goes to the lead and into notes. A finding with `path` and `line` shows, under its title, the lines `line` to `end_line` plus 3 either side from that file's diff for the snapshot's step (`changes?snapshot=<n>&step=true`, the diff the reviewer was given), with new-file line numbers and the finding's own lines marked; it shows nothing when those lines aren't in the diff, and "diff not available" with the error once the task is closed. Screenshots link to the full image. Each open finding has **fix** and **ignore** buttons (also on review cards in the inbox). **fix** sends the finding's severity, title, location and detail to the task's agent as a message from the user: through `POST /api/sessions/{id}/messages` to its latest live session (queued like any message while the agent is mid-turn, see "Agent sessions"), or starting a session when it has none; the view stays where it is, so several findings can be sent in a row. Then it, or **ignore** on its own, records the finding's state (`fixed` or `ignored`) with `PUT /api/reviews/{reviewId}/findings/{index}`, the index being the finding's position in `result.findings`; the review's `finding_states` (the `reviews.finding_states` column, a JSON object from index to state) holds them, and the buttons give way to "fix sent" or "ignored". Only a `done` review's findings take a state, and there is no way to clear one. The tab loads when it opens, when the task changes, and on each `review.*` event in the task's stream. The tab follows the latest `review.*` event of the highest-numbered snapshot: while that review runs, the tab label (and its entry in the More menu) carries a spinner in place of any earlier review's count; once it finishes with open findings (those with no state), the tab (or the More menu holding it) is highlighted with a badge of their count. Each snapshot row's **review** button carries a mark over its top-right corner from that snapshot's latest `review.*` event: a spinner while the review runs, a grey ● when it was skipped, a green ✓ when it finished with no open findings, and, when it has open findings, the button highlighted with their count in a badge. A failed review leaves the button unmarked. While any of a task's reviews is `running` and its agent is idle, the task's state is `reviewing` (see "Task state in the store"), which the task switcher and the Project tab show as **Working** (see "Task state"). `GET /api/tasks/{taskId}/reviews` lists a task's reviews oldest first. `sqlite3 byre.db "SELECT id, task_id, snapshot_n, vendor, state, error FROM reviews ORDER BY created_at DESC LIMIT 20"` shows recent ones.
## Workflows ## Workflows
+1
View File
@@ -291,6 +291,7 @@ func (m *Manager) Watch() {
slog.Error("check agent health", "err", err) slog.Error("check agent health", "err", err)
continue continue
} }
m.stopStuckReviewers(context.Background(), h)
now := problems(h) now := problems(h)
if slices.Equal(now, seen) { if slices.Equal(now, seen) {
+45
View File
@@ -525,6 +525,51 @@ func (m *Manager) cancelReviews(ctx context.Context, task api.Task, project api.
} }
} }
func (m *Manager) StopReview(ctx context.Context, reviewID, reason string) (api.Review, error) {
m.reviewMu.Lock()
defer m.reviewMu.Unlock()
r, err := m.store.GetReview(ctx, reviewID)
if err != nil {
return api.Review{}, err
}
if r.State != api.ReviewStateRunning {
return api.Review{}, fmt.Errorf("%w: review %s is %s, not running", ErrConflict, r.Id, r.State)
}
task, err := m.store.GetTask(ctx, r.TaskId)
if err != nil {
return api.Review{}, err
}
project, err := m.store.GetProject(ctx, task.ProjectId)
if err != nil {
return api.Review{}, err
}
m.endReviewer(ctx, r.AgentSessionId, project, r.Id)
m.failReview(ctx, r.Id, reason)
return m.store.GetReview(ctx, r.Id)
}
func (m *Manager) stopStuckReviewers(ctx context.Context, h Health) {
for _, p := range h.Processes {
if p.Health != api.HealthStuck {
continue
}
m.mu.Lock()
l := m.live[p.SessionId]
reviewID := ""
if l != nil {
reviewID = l.reviewID
}
m.mu.Unlock()
if reviewID == "" {
continue
}
_, err := m.StopReview(ctx, reviewID, fmt.Sprintf("the reviewer went %d minutes without an event", int(StuckAfter/time.Minute)))
if err != nil && !errors.Is(err, ErrConflict) {
slog.Error("stop stuck reviewer", "review", reviewID, "session", p.SessionId, "err", err)
}
}
}
func (m *Manager) recoverReviews(ctx context.Context) error { func (m *Manager) recoverReviews(ctx context.Context) error {
err := m.store.ClearReviewRequests(ctx) err := m.store.ClearReviewRequests(ctx)
if err != nil { if err != nil {
+247 -216
View File
@@ -1510,6 +1510,9 @@ type ServerInterface interface {
// (PUT /api/reviews/{reviewId}/findings/{index}) // (PUT /api/reviews/{reviewId}/findings/{index})
SetFindingState(w http.ResponseWriter, r *http.Request, reviewId string, index int) SetFindingState(w http.ResponseWriter, r *http.Request, reviewId string, index int)
// (POST /api/reviews/{reviewId}/stop)
StopReview(w http.ResponseWriter, r *http.Request, reviewId string)
// (GET /api/sessions/{sessionId}) // (GET /api/sessions/{sessionId})
GetSession(w http.ResponseWriter, r *http.Request, sessionId string) GetSession(w http.ResponseWriter, r *http.Request, sessionId string)
@@ -2251,6 +2254,32 @@ func (siw *ServerInterfaceWrapper) SetFindingState(w http.ResponseWriter, r *htt
handler.ServeHTTP(w, r) handler.ServeHTTP(w, r)
} }
// StopReview operation middleware
func (siw *ServerInterfaceWrapper) StopReview(w http.ResponseWriter, r *http.Request) {
var err error
_ = err
// ------------- Path parameter "reviewId" -------------
var reviewId string
err = runtime.BindStyledParameterWithOptions("simple", "reviewId", r.PathValue("reviewId"), &reviewId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
if err != nil {
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "reviewId", Err: err})
return
}
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
siw.Handler.StopReview(w, r, reviewId)
}))
for _, middleware := range siw.HandlerMiddlewares {
handler = middleware(handler)
}
handler.ServeHTTP(w, r)
}
// GetSession operation middleware // GetSession operation middleware
func (siw *ServerInterfaceWrapper) GetSession(w http.ResponseWriter, r *http.Request) { func (siw *ServerInterfaceWrapper) GetSession(w http.ResponseWriter, r *http.Request) {
@@ -3417,6 +3446,7 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/snapshots", wrapper.ListSnapshots) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/snapshots", wrapper.ListSnapshots)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/reviews", wrapper.ListReviews) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/reviews", wrapper.ListReviews)
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/reviews/{reviewId}/findings/{index}", wrapper.SetFindingState) m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/reviews/{reviewId}/findings/{index}", wrapper.SetFindingState)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/reviews/{reviewId}/stop", wrapper.StopReview)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/snapshots/{n}/fork", wrapper.ForkSnapshot) m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/snapshots/{n}/fork", wrapper.ForkSnapshot)
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/sessions", wrapper.ListSessions) m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}/sessions", wrapper.ListSessions)
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/sessions", wrapper.CreateSession) m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/sessions", wrapper.CreateSession)
@@ -3444,224 +3474,225 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H
// const string: with thousands of chunks the chained `+` fold is several // const string: with thousands of chunks the chained `+` fold is several
// times slower for the Go compiler than parsing a slice literal. // times slower for the Go compiler than parsing a slice literal.
var swaggerSpec = []string{ var swaggerSpec = []string{
"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",
} }
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes, // decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
+9
View File
@@ -22,6 +22,15 @@ func (s *Server) ListReviews(w http.ResponseWriter, r *http.Request, taskID stri
writeJSON(w, http.StatusOK, reviews) writeJSON(w, http.StatusOK, reviews)
} }
func (s *Server) StopReview(w http.ResponseWriter, r *http.Request, reviewID string) {
review, err := s.agents.StopReview(r.Context(), reviewID, "the reviewer was stopped")
if err != nil {
writeAgentError(w, err)
return
}
writeJSON(w, http.StatusOK, review)
}
func (s *Server) SetFindingState(w http.ResponseWriter, r *http.Request, reviewID string, index int) { func (s *Server) SetFindingState(w http.ResponseWriter, r *http.Request, reviewID string, index int) {
req := api.FindingStateUpdate{} req := api.FindingStateUpdate{}
if !readJSON(w, r, &req) { if !readJSON(w, r, &req) {
+15 -1
View File
@@ -40,7 +40,21 @@ function stateText(r) {
} }
} }
export function reviewCard(r, taskId) { export function reviewCard(r, taskId) {
return h("article", { class: `review ${r.state}` }, h("header", {}, h("span", { class: "review-snapshot" }, `snapshot #${r.snapshot_n}`), h("span", { class: `review-state ${r.state}` }, stateText(r)), h("time", { dateTime: r.created_at, title: r.created_at }, ago(r.created_at))), r.state === "failed" ? h("p", { class: "error-text" }, r.error) : null, r.state === "done" ? reviewResult(r, taskId) : null); return h("article", { class: `review ${r.state}` }, h("header", {}, h("span", { class: "review-snapshot" }, `snapshot #${r.snapshot_n}`), h("span", { class: `review-state ${r.state}` }, stateText(r)), h("time", { dateTime: r.created_at, title: r.created_at }, ago(r.created_at)), r.state === "running" ? stopButton(r) : null), r.state === "failed" ? h("p", { class: "error-text" }, r.error) : null, r.state === "done" ? reviewResult(r, taskId) : null);
}
function stopButton(r) {
const b = h("button", { type: "button", class: "danger review-stop", title: "End the reviewer and record this review as failed" }, "Stop");
b.onclick = async () => {
b.disabled = true;
try {
await post("/api/reviews/{reviewId}/stop", { path: { reviewId: r.id } });
}
catch (err) {
b.disabled = false;
void showAlert(errorText(err));
}
};
return b;
} }
function reviewResult(r, taskId) { function reviewResult(r, taskId) {
const res = (r.result ?? {}); const res = (r.result ?? {});
+1 -1
View File
File diff suppressed because one or more lines are too long
+43
View File
@@ -664,6 +664,25 @@ export interface paths {
patch?: never; patch?: never;
trace?: never; trace?: never;
}; };
"/api/reviews/{reviewId}/stop": {
parameters: {
query?: never;
header?: never;
path: {
reviewId: string;
};
cookie?: never;
};
get?: never;
put?: never;
/** @description Ends a running review's reviewer and records the review as failed. Refused unless the review is running. */
post: operations["stopReview"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/tasks/{taskId}/snapshots/{n}/fork": { "/api/tasks/{taskId}/snapshots/{n}/fork": {
parameters: { parameters: {
query?: never; query?: never;
@@ -2549,6 +2568,30 @@ export interface operations {
404: components["responses"]["Error"]; 404: components["responses"]["Error"];
}; };
}; };
stopReview: {
parameters: {
query?: never;
header?: never;
path: {
reviewId: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description The review. */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Review"];
};
};
404: components["responses"]["Error"];
409: components["responses"]["Error"];
};
};
forkSnapshot: { forkSnapshot: {
parameters: { parameters: {
query?: never; query?: never;
+15
View File
@@ -62,12 +62,27 @@ export function reviewCard(r: Review, taskId: string | undefined): HTMLElement {
h("span", { class: "review-snapshot" }, `snapshot #${r.snapshot_n}`), h("span", { class: "review-snapshot" }, `snapshot #${r.snapshot_n}`),
h("span", { class: `review-state ${r.state}` }, stateText(r)), h("span", { class: `review-state ${r.state}` }, stateText(r)),
h("time", { dateTime: r.created_at, title: r.created_at }, ago(r.created_at)), h("time", { dateTime: r.created_at, title: r.created_at }, ago(r.created_at)),
r.state === "running" ? stopButton(r) : null,
), ),
r.state === "failed" ? h("p", { class: "error-text" }, r.error) : null, r.state === "failed" ? h("p", { class: "error-text" }, r.error) : null,
r.state === "done" ? reviewResult(r, taskId) : null, r.state === "done" ? reviewResult(r, taskId) : null,
); );
} }
function stopButton(r: Review): HTMLElement {
const b = h("button", { type: "button", class: "danger review-stop", title: "End the reviewer and record this review as failed" }, "Stop");
b.onclick = async () => {
b.disabled = true;
try {
await post("/api/reviews/{reviewId}/stop", { path: { reviewId: r.id } });
} catch (err) {
b.disabled = false;
void showAlert(errorText(err));
}
};
return b;
}
function reviewResult(r: Review, taskId: string | undefined): HTMLElement { function reviewResult(r: Review, taskId: string | undefined): HTMLElement {
const res = (r.result ?? {}) as Record<string, unknown>; const res = (r.result ?? {}) as Record<string, unknown>;
const findings = findingsOf(r); const findings = findingsOf(r);
+4
View File
@@ -1904,6 +1904,10 @@ pre.file-text .line::before {
margin-left: auto; margin-left: auto;
} }
.review-stop {
align-self: center;
}
.review-snapshot { .review-snapshot {
font-weight: 700; font-weight: 700;
color: var(--text); color: var(--text);