Bob 2.0 driver observability: review-findings capture + last_dispatch health signal - #47
Merged
Merged
Conversation
A review dispatched by the 2.0 driver landed only a one-line summary on the board — no structured bob-review note — because two steps the 1.x worker does were missing on the 2.0 path: - finalize() never called persistReviewFindings, so the bob-review note was never written, regardless of the result text. - readResultText returns only Bob's LAST assistant message, which for a review is often the closing summary rather than the findings (they sit in an earlier message). Added readReviewText to join the task's assistant messages so the parser sees the whole transcript. The 2.0 driver now parses the full review text into reviewFindings for review mode, and finalize() persists them via the same path the 1.x worker uses.
…atus
A logged-out Bob still heartbeats (the 2.0 in-process loop keeps running), so
worker_draining reads healthy while every dispatch aborts on a provider
auth/network error — the foreman can't tell "draining" from "draining but
failing" and dispatches into a guaranteed abort.
Record each dispatch's outcome onto the worker's heartbeat row and surface the
freshest one among live drainers as worker_draining.last_dispatch ({status,
detail, seconds_ago}). A status of "aborted" now flags "alive but not
completing work" up front. Proactive login state can't be probed (Bob exposes
no auth API), so this is the reactive signal the driver already has.
- db: three heartbeat columns + recordDispatchOutcome; getWorkerLiveness picks
the freshest outcome among live rows (a dead worker's stale one doesn't leak).
- driver-loop: finalize() stamps every dispatch outcome via the loop's worker id.
…ning - The standalone CLI worker never stamped last_dispatch, so the new board_status health signal stayed null on the documented dispatch path. runOne now stamps every outcome (and main's catch stamps error), mirroring the 2.0 loop's finalize(). - recordDispatchOutcome stores detail only for a non-completed status: on success the caller's text is Bob's last assistant message, and task content must not leak into board_status. - parseReviewFindings skips a ### section with no severity and no Location/Category field: the 2.0 path feeds the whole transcript, where a reasoning turn's headed markdown became phantom info findings on the board note. - Webhook: the overflow warning re-arms when capacity returns (below cap, not zero, which a busy-but-alive endpoint may never reach); the payload carries worker.run (the heartbeat id) so seq scopes per process run and a restart isn't read as data loss; post() survives a synchronously-throwing fetch; --webhook-secret without --webhook fails loud instead of silently not signing. - CHANGELOG: --webhook moved out of the published 2.1.0 notes (it merged after the npm publish and is not in that package) into a new Unreleased section, alongside the last_dispatch and 2.0 review-capture entries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On 2.0 in-process dispatch, two things were invisible:
readResultTextreturns only Bob's closing summary, but a review's findings live in earlier assistant messages — so review-mode tasks completed with no structuredbob-reviewnote.board_statushad no way to show it.Changes
###section with no severity and noLocation/Categoryfield, so a reasoning turn's headed markdown can't become phantom "info" findings.board_status.worker_draining.last_dispatch— each live drainer's most recent dispatch outcome (status, failure detail, freshness), stamped by both the 2.0 in-process loop and the standalone CLI worker.detailis stored only for failures, so success text (task content) never reachesboard_status.worker.run(the heartbeat id) soseqscopes per process run — a receiver can tell a restart from data loss, and events correlate to board heartbeats;post()survives a synchronously-throwing fetch (never-throws contract);--webhook-secretwithout--webhookfails loud instead of silently not signing.--webhookentry moved out of the published 2.1.0 notes into a new Unreleased section (npm 2.1.0 was built from the pre-merge commit and does not contain it), alongside entries forlast_dispatchand the review capture.Why
The board is only trustworthy if it reflects what Bob actually did: a review that silently drops its findings, a drainer that fails every dispatch while reading "draining", or a changelog claiming a feature the published package lacks all break that. New coverage: an end-to-end test that
runDriverLoopstamps its own heartbeat, detail-gating on success, warning re-arm, sync-throw, and prose-heading tests (718 tests green).