* feat: rename task inline from the top bar via double-click
Double-clicking the task title in the desktop top bar swaps it for an
inline input; Enter commits the rename through the existing task update
path, Escape or blur cancels. Archived tasks stay read-only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test: fix vi.fn generics in agent usage test for vitest 4
vi.fn dropped the two-type-argument form in the Vitest 4 upgrade; the
old signature made mockResolvedValue infer never and fail typecheck.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: ignore Enter during IME composition in topbar rename input
Review follow-up: without the guard, the Enter that confirms an IME
candidate committed the rename mid-typing. Mirrors the quick-chat tab
rename input and the dialog default-action convention.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: harden topbar rename commit path against IME 229 and mid-edit archive
Independent-review follow-up:
- also treat keyCode 229 as IME composition, matching the documented
convention in dialog-default-action (some IMEs report the accepting
Enter after isComposing flips false)
- re-check isArchived on Enter so a task archived while the inline
editor is open cannot be renamed from it
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: make topbar rename title keyboard-operable
Addresses PR #1702 review: the renameable title exposed role="link" with
aria-disabled="false" but only a double-click handler. Add tabIndex, Enter
to open the rename input, and focus restoration on keyboard exits.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: surface agent subscription usage in settings and chat tooltip
Adds live subscription rate-limit visibility for Claude Code and Codex:
- GET /api/v1/agents/usage lists per-agent utilization windows (plan, percent,
reset time) for host agents with subscription credentials; ?fresh=true
bypasses the 5-minute cache with a 15s per-provider clamp.
- Fixes both existing usage clients: Claude parsed float utilization as int
(decode failure) and now reads the richer limits[] array incl. per-model
weekly windows; Codex read a nonexistent auth.json field and response
headers - now reads tokens.access_token, parses the body windows, and
refreshes OAuth tokens on 401. Token refresh persists without dropping
unknown credential fields.
- Settings > Agents gains a Subscription Usage section; the chat context
doughnut tooltip shows the session agent's windows, fetched fresh on hover.
- Shared UsageWindowRows component (bars, Good/High/Critical status,
reset countdowns) keeps settings, tooltip, and office surfaces consistent.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: recompute agent billing type on every read
Subscription billing detection for Claude and Codex was cached with
sync.OnceValue for the process lifetime, so logging in with OAuth after
the backend started never flipped billing badges or office usage checks
until restart. Detection now re-reads the credential files on each call
and reuses the usage clients' HasSubscriptionCredentials checks. Also
adds a regression assertion that fractional-second resets_at timestamps
parse under the RFC3339 layout.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: address subscription usage review feedback
- serialize empty utilization windows as arrays, not null
- sanitize per-agent usage errors in the API (raw provider errors are
logged server-side; they can carry credential paths/response bodies)
- persist refreshed CLI credentials via atomic temp-file rename
- keep previous settings usage on transient refresh failure; drop stale
tooltip usage (and its memo) when a fresh fetch fails
- add controller tests for SubscriptionUsage mapping and fresh propagation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: coalesce concurrent usage fetches and guard codex token refresh
- serialize usage-cache fetches per key with a double-checked lock so
concurrent fresh requests make one provider call instead of a burst
- reject codex refresh responses with an empty access_token instead of
persisting them and wiping working credentials
- pin the usage-rows reset fixture 30s under the day boundary so the
formatted value is deterministic on fast runners
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: coalesce failed usage fetches with short negative caching
Concurrent lookups after a fetch error each retried the provider once
the per-key lock rotated. Failures are now cached for 15 seconds (never
longer than the caller's staleness bound), so bursts share one error
result and the provider gets a breather before the next retry.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: keep stale usage through failed refreshes and skip caching cancellations
Track the last success and last failure independently in the usage
cache: a failed fresh refresh no longer evicts a still-valid success
(non-fresh callers keep the stale value while fresh callers share the
recent error), and a caller-cancelled context no longer records a
negative entry that would penalize other callers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test: synchronize concurrent usage-cache tests with a channel barrier
Replaces the sleep-widened race window in the coalescing tests with a
started/release barrier per the backend testing guidelines, and dedupes
the two concurrent-caller tests into one helper.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: unarchive tasks with worktree branch recovery
Archived tasks can now be restored. Unarchive works for manual/legacy
archives (empty cascade id, root-only) and cascade archives. Archive
deletes the local branch, so worktree recreate now falls back to
fetching the branch from origin, and unarchive writes the old branch
back as checkout_branch so a fresh session resumes the prior work.
Unrecoverable branches (never pushed) surface a warning. WS archive now
routes through the handoff cascade so it stays stamped and reversible.
UI: unarchive action on /tasks archived rows and the task top bar.
* fix: address PR review feedback on unarchive recovery
Forward PRNumber to the recreate fetch so fork-PR heads (only reachable
via pull/<N>/head) are recoverable, publish task.updated per task in the
cascade unarchive loop so the UI restores without a reload, and
re-publish task.updated after a checkout_branch restore since the
unarchive event goes out with the pre-restore repository rows.
* fix: harden unarchive recovery per review feedback
Propagate branch-probe errors instead of misreporting recoverable work
as gone, and reserve ErrBranchUnrecoverable for a confirmed-missing
remote ref (transient fetch failures keep their own error). Validate
the archive root exists so WS/HTTP archive no longer reports success
for unknown task IDs, CAS-guard manual unarchive on an empty cascade
stamp, detach branch recovery from the request context, and skip
checkout_branch restore for multi-branch repos. UI: in-flight guard on
the list unarchive button, pluralized unrecoverable-branch toast.
* docs: document CAS guard on UnarchiveTask interface contract
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
* fix(sidebar): keep created subtasks during hydration
* fix(sidebar): preserve placeholder subtasks during hydration
* fix(sidebar): mark websocket placeholder snapshots
* fix(web): require confirmation before archiving from PR merged/closed banners
The Archive link in the PR merged/closed status-bar banners archived the
task immediately, unlike every other archive surface. Route it through the
shared TaskArchiveConfirmDialog (cleanup summary + subtask cascade), and
move the banners into pr-archive-banners.tsx since chat-input-area.tsx was
over the file-size lint limit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(web): cover cascade passthrough in banner archive confirmation
Review follow-up: the subtask cascade checkbox is an acceptance criterion
for the banner archive flow, but tests only asserted cascade: false.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(e2e): verify cancel path of PR banner archive confirmation
QA follow-up: exercise the dialog cancel path in a real browser — cancel
must close the dialog, keep the banner, and archive nothing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(web): expose pending state on banner archive confirmation
Thread isPending from useBannerArchiveConfirm into
TaskArchiveConfirmDialog as isArchiving, matching the other archive
surfaces. Guards double-submit when the dialog is reopened while an
archive is still in flight on a slow connection.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test(e2e): scope archive-cancel click to the alertdialog
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* 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
* feat: allow multiline custom answers in clarification overlay
Swap the single-line custom-answer input for an auto-growing textarea so users
can type multi-line replies to ask_user_question. Enter submits, Shift+Enter
inserts a newline; the box grows to ~6 lines then scrolls. Adds unit and e2e
coverage.
* fix: address review feedback on multiline clarification input
- Always preventDefault on desktop plain Enter so an empty draft can't leak a
stray newline before the trim guard (Claude/CodeRabbit).
- On coarse-pointer devices let Enter insert a newline and submit via the
existing Submit button; hide the keyboard hints on touch (mobile parity).
- Preserve newlines in the resolved clarification history message via
whitespace-pre-wrap + items-start.
- Strengthen e2e to guard against fused lines; add Ctrl+Enter and touch tests.
* fix: touch submit button and IME guard for clarification input
- Guard against submitting on the Enter that confirms an IME candidate
(e.nativeEvent.isComposing) on CJK keyboards.
- Add an inline Send button on coarse-pointer devices so single-question custom
answers (which have no overlay Submit button) have a touch-reachable send
path. Fixes the regression from switching touch Enter to newline.
* refactor: extract clarification custom-input controls
- Pull the Enter/⇧↵ hints and touch Send button into a CustomInputControls
subcomponent to shrink ClarificationCustomInput.
- Compute the trimmed draft once and reuse it across the keydown handler and the
Send button (disabled state, click, styling) so the conditions can't drift.
- Add a test asserting the touch Send button is disabled while isSubmitting.
* fix: ignore auto-repeat Enter in clarification custom input
A held Enter key emits auto-repeat keydown events; guard the handler with
e.repeat so it can't fire onSubmit more than once. Adds a regression test.
* fix: suppress newline on repeat Enter and add mobile clarification e2e
- Repeat Enter on desktop now calls preventDefault before bailing, so a held key
can't leak newlines into the current or next question's textarea after the
carousel advances; it still never re-fires onSubmit/finalize.
- Add a mobile-chrome (Pixel 5) e2e covering the touch path: Enter inserts a
newline and the inline Send button submits the multiline answer.
* test: consolidate clarification e2e seed helper
Extract the shared seed → navigate → waitForLoad flow into
e2e/helpers/clarification.ts and delegate from the clarification, resize, and
mobile specs instead of duplicating it in each.