Skip to content

fix(kanban): stop truncating worker handoff in terminal-state notifications - #45

Merged
exiao merged 4 commits into
live-configfrom
fix/kanban-notify-untruncate
Jun 27, 2026
Merged

fix(kanban): stop truncating worker handoff in terminal-state notifications#45
exiao merged 4 commits into
live-configfrom
fix/kanban-notify-untruncate

Conversation

@exiao

@exiao exiao commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Symptom

Kanban terminal-state pings on Signal arrive cut off mid-sentence, e.g.:

@dev Kanban t_4198860a blocked: B1 XSS fix is staged + verified + byte-equal, ready for Eric to deploy. BLOCKING on the re-scoped work (comments #48/#49): (1) the relayed "deploy green-lit / c…

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_watcher built terminal-state text with hard slices: blocked reason [:160], gave_up error [:200], completed summary 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 = 4000 and 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.py drives the real _kanban_notifier_watcher against a temp DB:

  • a >160-char blocked reason survives intact (fail-before: sliced at 160)
  • a >200-char gave_up error survives intact (fail-before: sliced at 200)
  • a >4000-char reason gets the visible truncation suffix (bound still holds)

Verified fail-before (3 failed with the old slices) / pass-after (3 passed). ruff clean.

…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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread gateway/kanban_watchers.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread gateway/kanban_watchers.py
…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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread gateway/kanban_watchers.py
Comment thread gateway/kanban_watchers.py
…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
@exiao

exiao commented Jun 27, 2026

Copy link
Copy Markdown
Owner Author

Both P2s fixed in 6fa6e23. The notifier untruncation was incomplete: complete_task (summary [:400]) and _record_task_failure (error [:500]) pre-sliced the event payload below the notifier's 3500 visible cap, so the tail was dropped before the notifier saw it and the 'see board' suffix never fired. Added _EVENT_PAYLOAD_DETAIL_MAX=4000 above the notify cap and applied it to every terminal-event payload detail. Rewrote both tests to drive the real producers (not _append_event) with >500/>400-char payloads — fail-before/pass-after verified. Also fixed a latent IndexError on whitespace-only summaries surfaced by the real-producer path.

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
@exiao
exiao merged commit 8898b9d into live-config Jun 27, 2026
2 checks passed
@exiao
exiao deleted the fix/kanban-notify-untruncate branch June 27, 2026 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant