Failure-summary PR comments with log tails; /ui/merge-queue page #27

Manually merged
krisbuild merged 4 commits from failure-comments into main 2026-09-27 22:57:53 +02:00
Owner

Makes CI failures legible from where users actually are (the forge), for clients that can't reach the web UI.

  • Failure-summary comment on PRs (SPEC §8.1): when a graph on a PR's head fails, one comment lists each culprit task with its infra/verdict wording (failed: exit 1 on ares / infra: spawn-error on ares), a link to its instance page, and the last 30 log lines (≤4 KiB; ANSI and control chars stripped, fence longer than any backtick run in the log). Later failures edit the same comment; a later green graph edits it to "Resolved". Merge-queue candidates, push-only graphs and failure_comments = false pipelines post nothing. Delivery is durable: what's owed is written with the graph's completion and a worker posts/edits it, so restarts and forge outages only delay it. New additive table pr_summaries.
  • /ui/merge-queue: per (repo, base) queue in run order with state, priority, approver, PR/head links, candidate graph and failure reason; testing entry highlighted, recent merges folded. GET /api/merge-queue gains pr_url/head_url.

Note: #14 (durable forge outbox) is not on main yet, so this keeps its own delivery state (an edit needs the created comment's id, which fire-and-forget outbox rows can't carry). Expect a merge in forgejo/api.rs, state.rs, scheduler/status.rs, lib.rs and the fake forge when #14 lands — whichever is second takes it.

🤖 Generated with Claude Code

Makes CI failures legible from where users actually are (the forge), for clients that can't reach the web UI. - **Failure-summary comment on PRs** (SPEC §8.1): when a graph on a PR's head fails, one comment lists each culprit task with its infra/verdict wording (`failed: exit 1 on ares` / `infra: spawn-error on ares`), a link to its instance page, and the last 30 log lines (≤4 KiB; ANSI and control chars stripped, fence longer than any backtick run in the log). Later failures edit the same comment; a later green graph edits it to "Resolved". Merge-queue candidates, push-only graphs and `failure_comments = false` pipelines post nothing. Delivery is durable: what's owed is written with the graph's completion and a worker posts/edits it, so restarts and forge outages only delay it. New additive table `pr_summaries`. - **`/ui/merge-queue`**: per (repo, base) queue in run order with state, priority, approver, PR/head links, candidate graph and failure reason; testing entry highlighted, recent merges folded. `GET /api/merge-queue` gains `pr_url`/`head_url`. Note: #14 (durable forge outbox) is not on main yet, so this keeps its own delivery state (an edit needs the created comment's id, which fire-and-forget outbox rows can't carry). Expect a merge in `forgejo/api.rs`, `state.rs`, `scheduler/status.rs`, `lib.rs` and the fake forge when #14 lands — whichever is second takes it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
A failed graph on a PR's head posts one comment naming each culprit, whether
the failure is infra or the task's own verdict, a link to its log page and the
last 30 lines of its log (ANSI stripped, fenced so it cannot break out). Later
graphs for the head edit the same comment; a green one resolves it. Any graph
on the tracked head speaks for the PR, so the push graph a PR event was
deduplicated onto counts too. Merge-queue candidates, push-only graphs and
`failure_comments = false` pipelines post nothing.

The owed edit is recorded on a new `pr_summaries` row in the transaction that
finishes the graph and delivered by a worker off the scheduler, so a restart
or a forge outage delays the comment without losing it. The Forgejo client
gains create-with-id and edit-comment calls; the fake forge serves edits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ui: /ui/merge-queue page (SPEC §8.2)
Some checks failed
krisbuild/kris/krisbuild/nix/workspace-deps cached
krisbuild/kris/krisbuild/nix/hello cached
krisbuild/kris/krisbuild/nix/test-deps cached
krisbuild/kris/krisbuild/nix/build cached
krisbuild/kris/krisbuild/nix/test cached
krisbuild/kris/krisbuild/nix/world cached
krisbuild/kris/krisbuild/nix/clippy cached
krisbuild/kris/krisbuild/nix/kb-check succeeded
krisbuild/kris/krisbuild krisbuild kris/krisbuild: all tasks succeeded
krisbuild/queue the merge conflicts in SPEC.md, crates/kb-control-plane/src/db.rs, crates/kb-control-plane/src/forge/forgejo/api.rs, cra
608f3b8c3d
Each (repo, base) queue in run order, the entry under test highlighted, a
failed entry's reason beneath it, links to the PR, its head commit and the
candidate graph, and the ten most recent merges folded into a <details>.
Linked from the nav. GET /api/merge-queue gains the forge's pr_url and
head_url per entry when a forge is configured.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner
@krisbuild r+
Collaborator

Removed from the merge queue: the merge conflicts in SPEC.md, crates/kb-control-plane/src/db.rs, crates/kb-control-plane/src/forge/forgejo/api.rs, crates/kb-control-plane/src/forge/forgejo/mod.rs, crates/kb-control-plane/src/forge/mod.rs, crates/kb-control-plane/src/http.rs, crates/kb-control-plane/src/lib.rs, crates/kb-control-plane/src/scheduler/status.rs, crates/kb-control-plane/src/state.rs, crates/kb-control-plane/tests/it/common/mod.rs, docs/TODO.md.

Removed from the merge queue: the merge conflicts in SPEC.md, crates/kb-control-plane/src/db.rs, crates/kb-control-plane/src/forge/forgejo/api.rs, crates/kb-control-plane/src/forge/forgejo/mod.rs, crates/kb-control-plane/src/forge/mod.rs, crates/kb-control-plane/src/http.rs, crates/kb-control-plane/src/lib.rs, crates/kb-control-plane/src/scheduler/status.rs, crates/kb-control-plane/src/state.rs, crates/kb-control-plane/tests/it/common/mod.rs, docs/TODO.md.
Merge origin/main into failure-comments; route the failure summary through the forge outbox
All checks were successful
krisbuild/kris/krisbuild/nix/hello cached
krisbuild/kris/krisbuild/nix/test-deps cached
krisbuild/kris/krisbuild/nix/workspace-deps cached
krisbuild/kris/krisbuild/nix/clippy cached
krisbuild/kris/krisbuild/nix/test cached
krisbuild/kris/krisbuild/nix/build cached
krisbuild/kris/krisbuild/nix/world cached
krisbuild/kris/krisbuild/nix/deployed succeeded
krisbuild/kris/krisbuild/nix/kb-check succeeded
krisbuild/kris/krisbuild krisbuild kris/krisbuild: all tasks succeeded
5fc4e0bff8
The outbox (#14) now carries the summary: a `summary` row naming only the PR,
enqueued in the transaction that finishes the graph and coalesced per PR. When
it comes due it is rendered from `pr_summaries` (the newest graph, the recorded
comment id) and sent as an edit, or as a create whose id the writer now
reports (`Delivery::Created`); an edit that 404s (`Delivery::Gone`) falls back
to a create. The summary's own worker, sweep and attempt counting are gone.

Which PR a graph speaks for now comes from `forge_refs`, which webhooks and
reconciliation both maintain, so the summary's own head tracking and its
webhook hooks are gone too; `pr_summaries` loses `head_sha` and
`synced_graph`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Merge origin/main into failure-comments
All checks were successful
krisbuild/kris/krisbuild/nix/test-deps cached
krisbuild/kris/krisbuild/nix/workspace-deps cached
krisbuild/kris/krisbuild/nix/hello cached
krisbuild/kris/krisbuild/nix/world cached
krisbuild/kris/krisbuild/nix/build cached
krisbuild/kris/krisbuild/nix/clippy cached
krisbuild/kris/krisbuild/nix/test cached
krisbuild/kris/krisbuild/nix/deployed succeeded
krisbuild/kris/krisbuild/nix/kb-check succeeded
krisbuild/kris/krisbuild krisbuild kris/krisbuild: all tasks succeeded
krisbuild/queue merged
2923f5878d
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

Merged main (#14 outbox, #15, #24, #26). The failure summary now rides the durable outbox (new summary kind; the writer returns created comment ids and reports edits of deleted comments as gone) instead of its own worker, and PR heads come from #14's forge_refs. Reviewed.

@krisbuild r+

Merged main (#14 outbox, #15, #24, #26). The failure summary now rides the durable outbox (new `summary` kind; the writer returns created comment ids and reports edits of deleted comments as gone) instead of its own worker, and PR heads come from #14's `forge_refs`. Reviewed. @krisbuild r+
krisbuild manually merged commit 8a5757d01d into main 2026-09-27 22:57:53 +02:00
Collaborator

Merged as 8a5757d01d.

Merged as 8a5757d01db9.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kris/krisbuild!27
No description provided.