fix(kanban): stop truncating worker handoff in terminal-state notifications - #45
Conversation
…ations Blocked-reason and gave_up-error pings were sliced at 160/200 chars, cutting the worker's explanation of WHY it stopped off mid-sentence on Signal/Telegram. The full text was always preserved in the kanban DB; only the delivered ping was clipped, forcing the reader to query sqlite to read the rest. Route the blocked reason, gave_up error, and completed summary through a bounded _clip_notify_detail() helper (cap 4000 chars, visible 'see board' suffix past it) so a full handoff arrives intact while a pathological multi-KB summary still can't flood the channel. Patch note: ~/.hermes/plans/hermes-patches/kanban-notify-untruncate.md
There was a problem hiding this comment.
Code Review
This pull request introduces a helper function _clip_notify_detail to truncate kanban terminal-state notification details (such as blocked reasons, gave_up errors, and completed summaries) to a generous limit of 4000 characters with an explicit truncation message, replacing the previous silent 160/200 character limits. Regression tests are also added to verify this behavior. The reviewer noted that if the payload summary or task result contains only whitespace, an empty detail string is returned, which results in an unnecessary newline in the final notification message; they suggested a fix to only prepend the newline when the detail is non-empty.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27fa7a1504
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…wline Address two PR #45 review findings on gateway/kanban_watchers.py: - codex P2 (line 146): _clip_notify_detail capped the inline detail at 4000, but the caller prepends the envelope (emoji + @assignee + "Kanban <id> done — " + title[:120] + "\n"), so the total could exceed a hard-4000 adapter cap (WeCom content[:4000]) and silently re-clip the advertised "see board" suffix off the tail. Lower _NOTIFY_DETAIL_MAX 4000 -> 3500 to reserve envelope room so the truncation stays visible on capped platforms. - gemini medium (line 574): a whitespace-only summary/result clips to "" after strip, and the unconditional f"\n{detail}" left a dangling trailing newline on the completed headline. Only prepend the newline when the detail is non-empty. Add two regression tests: whitespace-only summary -> no trailing newline, and capped handoff + envelope -> total stays <= 4000 chars.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8047832546
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…just the notifier Round-2 fix for PR #45 (Codex P2s). The notifier untruncation alone was incomplete: complete_task sliced the completed summary first-line at 400 and _record_task_failure sliced the gave_up error at 500 in the EVENT PAYLOAD, below the notifier's 3500 visible cap — so a long handoff was cut before the notifier saw it and the advertised 'see board' suffix never fired. Add _EVENT_PAYLOAD_DETAIL_MAX=4000 (above the notify cap) and apply it to every terminal-event payload detail (completed summary at both sites incl. the edited result-update; gave_up error at both sites). DB storage columns keep their own caps — they aren't the notifier path. Now the notifier is the single place truncation shows visibly. Also fix a latent IndexError surfaced by testing through the real producer: a whitespace-only summary made strip().splitlines()[0] index an empty list; guard now checks the post-strip line list (same pattern at the sibling edited site). Rewrite the gave_up/completed tests to drive the REAL producers (complete_task, _record_task_failure failure_limit=1) instead of _append_event, with payloads exceeding the old producer caps so they guard producer pre-truncation, not just the notifier slice. Fail-before/pass-after verified; full kanban suite (235) green. Patch note: ~/.hermes/plans/hermes-patches/kanban-notify-untruncate.md
|
Both P2s fixed in 6fa6e23. The notifier untruncation was incomplete: |
Fourth pre-truncation site. _end_run stores verbatim, but its two gave_up callers sliced error[:500] before storing on task_runs.error — the durable attempt record build_worker_context feeds to the next retry (capped 4KB there). Asymmetric with the completed path, which stores summary in full: a retrying worker saw only the first 500 chars of the prior failure. Raise both _end_run(error=...) gave_up calls to _EVENT_PAYLOAD_DETAIL_MAX; leave the last_failure_error quick-glance column at 500. Add a test driving the real breaker that asserts the full >500-char error survives on the run row. Fail-before/pass-after verified; kanban suite green. Patch note: ~/.hermes/plans/hermes-patches/kanban-notify-untruncate.md
Symptom
Kanban terminal-state pings on Signal arrive cut off mid-sentence, e.g.:
The rest of the worker's handoff is gone. The full text was always preserved in the kanban DB (
task_comments/ event payload); only the delivered notification was clipped, so the reader has to go query sqlite to find out why a task actually blocked.Root cause
gateway/kanban_watchers.py::_kanban_notifier_watcherbuilt terminal-state text with hard slices:blockedreason[:160],gave_uperror[:200],completedsummary first-line[:200]/[:160]. Those caps date from when the pings were one-liners. But the blocked reason and gave_up error are the worker's full human-facing handoff (why it stopped, what it needs from Eric) — the whole point of the ping is to read that without opening the board.Fix
Add
_NOTIFY_DETAIL_MAX = 4000and a_clip_notify_detail()helper, and route the blocked reason / gave_up error / completed summary through it. Generous enough for a full handoff, still bounded so a pathological multi-KB summary can't flood the channel — past the cap it appends a visible… (N more chars; see board)instead of a silent mid-sentence cut. Presentation-only change in the notifier watcher: no schema, payload, or delivery-path change.Test
tests/gateway/test_kanban_notify_untruncate.pydrives the real_kanban_notifier_watcheragainst a temp DB:Verified fail-before (3 failed with the old slices) / pass-after (3 passed).
ruffclean.