Skip to content

fix: plan_review raw-JSON leak, empty-response done bug, blocked status, gzip - #20

Merged
Its-My-Work merged 4 commits into
mainfrom
fix/plan-review-raw-json-leak
Sep 22, 2026
Merged

Its-My-Work merged 4 commits into
mainfrom
fix/plan-review-raw-json-leak

Conversation

@Its-My-Work

Copy link
Copy Markdown
Owner

Three fixes from this session, all found from live use of the real deployed board:

1. Raw JSON under the plan_review card

A reloaded chat re-rendering a plan_review message from its DB row inserted the card
in front of the raw-JSON message bubble instead of replacing it — both stayed visible.
Reported live with a screenshot. Now folded into the same if/else-if chain agent_plan
already uses.

2. A task can be marked "done" with a genuinely empty final answer

Real incident: task T-001 ("Спайк Easypanel API") hit the built-in WebSearch's
"connectors disabled" error a few times, found real results eventually, then its final
CLI turn produced literally empty text — twice in a row — and the run just stopped.
subtype was still 'success', so it was marked done with failure_reason: null. Zero
findings, no report, no escalation to a human, green checkmark on the board.

  • lastTurnText tracks each loop iteration's own text (not the whole run's cumulative
    text, which can be non-empty from earlier turns/errors/notices). An empty last turn on
    an otherwise-successful run is no longer done — it becomes failure_reason:'empty_response'.
  • report_result({blocked:true, reason}) is now the correct way for an agent to escalate
    instead of ending silently or claiming success — a new blocked status, distinct from
    both done and cancelled, with its own Kanban column/badge/chain-icon (5 languages)
    so a card that genuinely needs a human doesn't get lost among finished work.

3. Kanban/API responses were served fully uncompressed

Found live while investigating a "the board loads slowly" report: kanban.html (~140KB)
and /api/tasks (~190KB+ for 26 tasks, growing with every task — description/context
dominate) went out with no Content-Encoding at all, verified with curl -H 'Accept-Encoding: gzip' directly against the running container. One line
(compression middleware) fixes it.

Testing

  • New test/task-blocked-and-empty-response.test.js: boots a real server + a real
    scripted claude binary end to end (not source-text pattern matching) and covers all
    four scenarios — empty final turn, blocked, a normal run is unaffected, gzip headers.
  • Extended test/render/plan-review.test.mjs for the raw-JSON-leak fix.
  • Full npm test run: everything green except one pre-existing tmux-timing flake
    (test/engine-spawn-cmd.test.js, unrelated file, confirmed passing in isolation).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y2ZSHUdJHqVsvSNQ5ZeQ3f

Its-My-Work and others added 4 commits September 22, 2026 18:28
The DB-restore path (a reloaded chat re-rendering a plan_review message from
its stored row) inserted the card with .before() in front of the message
bubble instead of replacing its content. The generic assistant-message branch
still rendered the raw JSON into that bubble first, so both stayed visible —
reported live with a screenshot ("что за странное сообщение под карточкой").

Folded plan_review into the same if/else-if chain agent_plan already uses,
replacing .msg's innerHTML directly instead of inserting before it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2ZSHUdJHqVsvSNQ5ZeQ3f
…d status; gzip responses

Real incident (T-001, 2026-09-22): a research task hit the built-in
WebSearch's "connectors disabled" error a few times, eventually found real
results, then the CLI's final turn produced literally empty text — twice in
a row — and the run just stopped. subtype was still 'success', so the task
was marked 'done' with failure_reason:null: zero findings, no report, no
escalation, and a green checkmark on the board.

  - lastTurnText tracks each loop iteration's OWN text contribution (not the
    whole run's). isSuccess with an empty last turn is no longer 'done' —
    it flows into the existing failure path as failure_reason:'empty_response'.
  - report_result({blocked:true, reason}) is now the correct way to escalate:
    a new 'blocked' status, distinct from both 'done' and 'cancelled', with
    its own Kanban column/badge/chain-icon (5 languages) so a card that
    needs a human does not get lost among finished work.
  - gzip: found live while investigating a "kanban loads slowly" report —
    kanban.html (~140KB) and /api/tasks (~190KB+ for 26 tasks, growing with
    every task) went out completely uncompressed, verified with curl against
    the real container. One line (compression middleware) fixes it.

Verified end-to-end against a real server + scripted `claude` binary
(test/task-blocked-and-empty-response.test.js), not just the source text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2ZSHUdJHqVsvSNQ5ZeQ3f
…rn/blocked code

CI caught it: 'API run receives effort' failed because the previous commit added
~700 chars ahead of cli.send(...) inside startTask, pushing its effort: field
(19850 -> 20019) past the pinned test's fixed 20000-char window. Not a real
behavioural regression — cli.send still passes effort exactly as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2ZSHUdJHqVsvSNQ5ZeQ3f
Same failure mode as the previous commit, different pinned window: the
'blocked' status work added a blockedInfo/blockedBadge pair ahead of the
footer template inside makeCard, pushing \${cfgBadges} (originally ~2450)
past the old 2600-char window. Full local suite (70 files) is green after
this — nothing else was hit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2ZSHUdJHqVsvSNQ5ZeQ3f
@Its-My-Work
Its-My-Work merged commit 6682c02 into main Sep 22, 2026
1 check passed
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