* feat: press Enter on a dialog to run its semantic action
* fix: harden dialog Enter-to-confirm from review feedback
* fix: refine dialog Enter guards and fix prettier CI
* fix: coalesce ci auto-fix queue rounds
* fix: centralize ci auto-fix round cap
* fix: keep ci auto-fix state fresh
* fix: refine ci auto-fix round status
* fix: handle ci auto-fix exhaustion edge cases
* fix: reduce ci auto-fix dispatch complexity
* fix: refresh pending ci auto-fix before direct prompt
* fix: harden ci auto-fix queue replacement
---------
Co-authored-by: root <root@kandev.ts.net>
* fix(web): suppress kanban spinner for TODO tasks
A task moved back into TODO can still carry an active primary session
state (CREATED/STARTING/RUNNING). The kanban card was painting the
blue running-spinner in that case, making queued tasks look like they
were executing.
Add an explicit TODO guard at the top of shouldShowTaskRunningSpinner
so the queued column never shows the spinner, regardless of the
session-state desync. Existing decoupling for IN_PROGRESS/REVIEW/etc.
is untouched.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test: clarify spinner test description excludes TODO
Greptile flagged that "returns true when any task state has an actively
running primary session" overstates the invariant now that TODO
short-circuits to false. Reword to "non-TODO task states" so the
description matches behavior.
* ci: retrigger after artifact expiry
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* perf(backend): cap cumulative diff bytes and file count during large rebases
* perf(web): coalesce cumulative-diff refetches and skip redundant status compares
* feat(web): warn when the changes panel hides files from a capped diff
* fix(backend): enforce cumulative diff total byte budget strictly
* fix(web): keep coalesced refetch timer shared across envKey subscribers
* fix(web): drop unsound git-status SHA fast-path that staled live diffs
* fix(web): cancel coalesced timer on mid-flight drain to avoid duplicate refetch
* refactor(web): move changes-panel banner and helper to a sibling file
* docs(backend): clarify cumulative diff truncated-files-count semantics
* fix(web): tighten useSelectedFileKey mode param to the all|file union
* perf(kanban): memoize derived board data to stop re-render storms
The board rebuilt the `tasks` array (and `stepOptions`/`sharedProps`) on every
store change, producing fresh object identities that defeated downstream memos
and re-rendered every card on each WebSocket message. Wrap them in useMemo so
the board only re-renders when its inputs actually change.
* perf(session-runtime): bound runtime memory and dedupe git-status compare
Three runtime-store fixes for the crash a heavy rebase triggered:
- Cap shell + terminal output buffers at 2MB (matching the existing process
buffer) so a chatty shell can't grow the store without limit.
- Purge per-session runtime state (messages, turns, shell/process buffers, and
the bySessionId maps) when a session is removed; env-scoped maps are dropped
only once no other session shares the environment.
- Run setGitStatus's deep per-file diff comparison once per update and return
whether anything changed, instead of recomputing it 2-3x. Under a massive
rebase (thousands of files, frequent updates) that comparison was the
dominant CPU cost and drove the render storm.
* refactor(session-runtime): drop now-unused gitStatusWouldMutate
The git-status handler no longer pre-checks for changes (setGitStatus now
returns whether it changed), leaving gitStatusWouldMutate with no callers.
* fix(session-runtime): enforce terminal cap on first and oversized chunks
appendTerminalChunk only evicted when more than one chunk was buffered, so a
single chunk larger than the 2MB cap slipped through untrimmed; the new-terminal
branch also pushed the first chunk without going through the cap at all. Clamp
each chunk to the tail of the cap and route the new-terminal path through
appendTerminalChunk. Addresses CodeRabbit review.