Commit graph

872 commits

Author SHA1 Message Date
iliya
7842b5a01f fix(team): clarify teammate first-contact wording 2026-04-07 10:59:39 +03:00
iliya
3b0fe0bcbf fix(team): stop counting inbox noise as check-ins 2026-04-07 10:48:59 +03:00
iliya
a641d263c0 fix(team): route teammate replies back through inbox 2026-04-07 10:34:18 +03:00
iliya
c20fc1a312 feat(team): clarify teammate check-ins and retry state 2026-04-07 10:28:00 +03:00
iliya
cb9eb5f701 refactor(team): drop dead lead bootstrap launch fields 2026-04-07 02:39:39 +03:00
iliya
bc3b6ae4e6 refactor(team): drop dead bootstrap skip-permissions field 2026-04-07 02:36:35 +03:00
iliya
8c136f0a41 refactor(team): drop dead bootstrap prompt field 2026-04-07 02:34:06 +03:00
iliya
31b5c31df8 refactor(team): declare bootstrap permission seeds in app specs 2026-04-07 02:21:46 +03:00
iliya
233e01847c fix(team): harden bootstrap state reads 2026-04-07 02:04:28 +03:00
iliya
ad56f0e337 fix(team): ignore replayed bootstrap progress events 2026-04-07 01:49:37 +03:00
iliya
ac3475d3be fix(team): support runtime bootstrap prompt sanitizing 2026-04-07 01:33:04 +03:00
iliya
0064380160 refactor(team): move bootstrap prompts into runtime 2026-04-07 01:30:38 +03:00
iliya
d4331300c4 fix(team): harden deterministic bootstrap rollout 2026-04-07 01:13:00 +03:00
iliya
d5ee7717e7 feat(team): move launch path to deterministic bootstrap 2026-04-07 01:06:49 +03:00
iliya
c92bf3a6a5 feat(team): improve degraded bootstrap recovery 2026-04-07 00:49:30 +03:00
iliya
d484f1d62d fix(team): surface unreadable bootstrap journal warnings 2026-04-07 00:46:05 +03:00
iliya
8ef89eefce feat(team): add bootstrap recovery and app integration 2026-04-07 00:43:38 +03:00
iliya
d2cd655c11 fix(team): harden provisioning and team UI state 2026-04-06 21:28:22 +03:00
iliya
ae2ccf2386 fix(team): preserve desktop teammate fallback semantics 2026-04-06 15:58:48 +03:00
iliya
5402ddfe97 fix(team): narrow process teammate override 2026-04-06 15:35:01 +03:00
iliya
d549006aaf fix(team): prefer tmux teammates for desktop launches 2026-04-06 15:13:03 +03:00
iliya
cf8df6b306 feat(app): show tmux install guidance on dashboard 2026-04-06 15:02:11 +03:00
iliya
84e0bdb03e fix member messages empty pagination state 2026-04-05 22:13:45 +03:00
iliya
9296ce3988 refine member message pagination 2026-04-05 22:07:09 +03:00
iliya
0531fc1dbf fix worker lifecycle edge cases 2026-04-05 22:03:11 +03:00
iliya
dc0627c285 fix message pagination consumers 2026-04-05 21:54:52 +03:00
Artem Rootman
5efc3dd63f
fix: pagination correctness and message enrichment
P1: Poller no longer overwrites nextCursor/hasMore — those belong
to the "Load older" flow. Both poller and loadOlder now dedup
messages by messageId or timestamp+from fingerprint.

P1: Cursor is now compound (timestamp|messageId) with stable
tie-breaking sort. Messages sharing the same timestamp at page
boundaries are no longer lost.

P2: getMessagesPage now applies the same enrichment as getTeamData:
leadSessionId propagation and slash-command-result annotation.

P3: Added 3 tests for getMessagesPage covering pagination, cursor
stability with same-timestamp messages, and slash command annotation.
2026-04-05 18:18:03 +00:00
Artem Rootman
bc7981f6b9
fix: use full intervals content in worker cache key, not just length
Two different interval sets with the same length would produce
the same cache key, returning stale results. Serialize each
interval's startedAt~completedAt into the key.
2026-04-05 18:09:59 +00:00
Artem Rootman
270eb547cb
merge: add paginated messages API into oom-issues branch 2026-04-05 18:07:21 +00:00
Artem Rootman
54198e6598
fix: remove capTimerMap that silently drops pending refreshes
capTimerMap was cancelling oldest pending throttle/debounce timers
when the Map exceeded a size limit. Since the schedulers don't
replay dropped keys, this silently lost refresh callbacks — leaving
session/team state stale after high-volume file change events.

These Maps are self-cleaning (entries delete themselves when their
callback fires) and hold ~100 bytes per entry. Even 200 entries
is negligible memory. Removing the cap fixes the data freshness
issue without any memory concern.
2026-04-05 18:06:31 +00:00
Artem Rootman
7d2282c35c
fix: keep 50 messages in getTeamData for backward compatibility
Returning messages: [] broke the slash command annotation test and
any code relying on getTeamData.messages (notifications, dedup).

Keep a small batch (50 newest) in getTeamData for compatibility.
Full message history is available via getMessagesPage() API.
2026-04-05 17:45:44 +00:00
Artem Rootman
0c0e0240a3
feat: paginated messages API (team:getMessagesPage)
New cursor-based IPC endpoint for the messages timeline panel:
- team:getMessagesPage(teamName, { beforeTimestamp?, limit? })
  returns { messages, nextCursor, hasMore }
- Cursor is timestamp-based — stable under live message insertion
- Default page size 50, max 200

getTeamData no longer includes messages in its response, eliminating
the ~1MB messages payload from every team refresh. Messages are now
fetched independently by MessagesPanel.

MessagesPanel changes:
- Fetches initial page on mount via getMessagesPage API
- Auto-refreshes newest page every 5s when team is alive
- "Load older messages" button for pagination
- Falls back to prop messages if API fails (graceful degradation)
2026-04-05 17:37:26 +00:00
Artem Rootman
a92390dcc6
style: fix import order in ExtensionStoreView
Move useShallow and lucide-react imports above @renderer/* imports
to follow the project import order convention.
2026-04-05 17:36:03 +00:00
Artem Rootman
f07eb914ae
merge: resolve conflicts with main (ExtensionStoreView, InstallButton)
Merged new fields from main (fetchCliStatus, cliStatusLoading,
openDashboard, authMissing, disableReason) into our useShallow
selectors.
2026-04-05 17:19:41 +00:00
Artem Rootman
f2e1d0e944
fix: suppress worker-not-found warnings in test environment
The TeamDataWorkerClient logged console.warn when the worker file
was not found, which is expected during tests (no build output).
The test setup treats unexpected warnings as failures.

Downgrade to logger.debug for the "not found" message and remove
the eager warning from resolveWorkerPath().
2026-04-05 17:10:03 +00:00
Artem Rootman
e81116b85e
fix: apply exact reviewer suggestions for MemberLogsTab
- Move endRefreshing() outside the !cancelled guard in finally block
  so it always runs even when the effect is torn down mid-refresh.
- Only call load() when isTabActive or on first load — prevents
  unnecessary fetches when a hidden tab's effect re-runs.
2026-04-05 17:01:36 +00:00
Artem Rootman
0e83d99e0a
fix: address PR review feedback (6 issues)
Critical:
- findLogsForTask: call worker directly instead of wrapping in
  wrapTeamHandler, so failures propagate to catch and trigger the
  main-thread fallback correctly.
- TeamDataWorkerClient: scope error/exit handlers to the specific
  worker instance to prevent a stale worker's exit event from
  rejecting pending requests on a replacement worker (race condition).

Major:
- TeamDataWorkerClient: validate teamName and taskId before forwarding
  to worker thread (input sanitization).
- team-data-worker: include status, since, and intervals length in
  cache key to prevent stale results after filter changes.
- team-data-worker: move logsInFlight.delete() into .finally() so
  rejected lookups don't poison the in-flight map permanently.
- MemberLogsTab: reset refreshCountRef and refreshing state in effect
  cleanup to prevent the refresh indicator from latching on permanently
  when the effect tears down mid-refresh (e.g. on tab switch).
2026-04-05 16:59:44 +00:00
iliya
9f7cfb04fa merge: sync origin/main into dev 2026-04-05 19:51:26 +03:00
Artem Rootman
23796cddc3
fix: only filter broadcast inbox (*), keep user inbox
The user inbox (user.json) contains real teammate-to-user messages
generated by Claude Code CLI. Filtering it as a system inbox was
incorrect — it broke message aggregation for user-directed messages.

Only the broadcast inbox (*.json) needs to be excluded since '*'
is not a valid member name and causes a phantom member in the UI.
2026-04-05 16:45:31 +00:00
Artem Rootman
fdc49f475e
fix: filter out system inboxes (*, user) from team member list
The broadcast inbox file (inboxes/*.json) was being parsed by
listInboxNames() as a member named "*", which appeared in the UI
as a phantom team member. Since "*" fails the MEMBER_NAME_PATTERN
validation, it could not be removed through the UI.

Filter system inbox names (*, user) from listInboxNames() so they
are not treated as real team members.
2026-04-05 16:38:09 +00:00
Artem Rootman
da58917032
perf: offload heavy I/O to worker thread, reduce renderer re-renders
Main process — worker thread for team data:
- New team-data-worker thread handles getTeamData and findLogsForTask,
  isolating heavy file I/O (scanning 300+ subagent JSONL files) from
  Electron's main event loop. getTeamData dropped from ~2000ms on the
  main thread to ~110ms via the worker.
- Worker-side dedup and 10s result cache for findLogsForTask prevents
  redundant scans when the same task is queried multiple times.
- Discovery cache TTL raised from 5s to 30s — avoids re-scanning the
  entire project directory on every call.
- Message cap at 200 in TeamDataService to keep IPC payloads under 1MB
  (was sending 2200+ messages / ~3MB, stalling Chromium IPC serialization).
- IPC handlers fall back to main-thread execution if the worker is
  unavailable (graceful degradation).

Renderer — useShallow and memoization (55 files):
- Added useShallow to store selectors across 55 renderer files. Batched
  individual useStore() calls (e.g. 17 calls in ExtensionStoreView,
  10 in ConnectionSection) into single useShallow selectors, cutting
  unnecessary re-render checks on every store update.
- MemberLogsTab: three 5-second polling intervals now pause when the
  parent tab is hidden (display:none). Previously 5 hidden tabs × 3
  intervals = 15 polling timers firing continuously.
- KanbanColumn wrapped in React.memo to skip re-renders when props
  haven't changed.
- MemberList: memoized activeMembers/removedMembers/colorMap; replaced
  O(n×m) per-member task scan with a pre-computed reviewer map.
- Bounded timer Maps in store initialization to prevent unbounded growth
  of debounce/throttle tracking maps during long sessions.
2026-04-05 16:21:05 +00:00
iliya
30fb2501d3 Persist launch-state and duplicate no-op handling 2026-04-05 15:23:41 +03:00
iliya
2959a3d074 Refine launch status and Gemini staging flow 2026-04-05 12:08:13 +03:00
iliya
e9c08c4b6d Stage Gemini team launch hydration 2026-04-04 20:44:33 +03:00
iliya
a591ccf297 Stabilize team provisioning and runtime diagnostics 2026-04-04 20:04:16 +03:00
iliya
074b614469 feat: improve team launch model and status UX 2026-04-02 15:15:32 +03:00
iliya
759cae2669 fix(pricing): include codex and gemini model costs 2026-04-02 10:23:57 +03:00
iliya
3ac46e2861 feat(teams): unify provider-aware create and launch flows 2026-04-02 10:23:14 +03:00
iliya
bae3609561 feat(multimodel): add free-code runtime and provider status UI 2026-04-02 10:22:11 +03:00
iliya
1b3bd8752b refactor: remove enrichMemberBranches method and streamline branch tracking
- Eliminated the enrichMemberBranches method from TeamDataService to simplify member branch enrichment logic.
- Updated TeamDetailView to utilize live branch tracking for both lead and member worktrees, enhancing the accuracy of displayed member branches.
- Adjusted various references to ensure membersWithLiveBranches is used consistently across the component.
2026-04-01 19:11:51 +03:00
iliya
21513bb6f8 Improve Extensions CLI preflight and plugin install diagnostics
Refs: https://github.com/777genius/claude_agent_teams_ui/issues/37
2026-04-01 16:49:07 +03:00
iliya
e26310870c chore: lower session cache size and TTL (5 sessions, 5 min TTL)
Made-with: Cursor
2026-03-31 18:52:15 +03:00
iliya
8cf2d41568 fix(graph): improve text normalization in TeamGraphAdapter
- Enhanced text processing to clean up raw task ID hashes and replace pipe separators with dashes.
- Ensured consistent formatting for comments and inbox messages.
2026-03-31 13:02:05 +03:00
iliya
6621660376 feat(graph): add cross-team ghost nodes and task card improvements
- Cross-team messages now show ghost nodes (dashed hexagons) for external teams
- Ghost nodes have purple color, link icon, and connect to lead via message edge
- Particles flow between ghost node and lead with cross-team message labels
- Cross-team popover shows external team name
- Task click opens full KanbanTaskCard with glow effects and action buttons
- All kanban task actions wired through CustomEvent to TeamDetailView
2026-03-31 01:48:15 +03:00
iliya
16f069fae3 feat(graph): enhance task rendering and interaction features
- Updated task opacity logic to simplify conditions.
- Added comment count and unread count badges to task pills for better visibility.
- Improved layout for unassigned tasks, including a section header and overflow badge.
- Enhanced task interaction by restricting drag functionality to member and lead nodes only.
- Introduced new task action event listeners for better task management in the UI.
- Preserved known task change presence across refreshes to maintain state consistency.
2026-03-31 01:29:59 +03:00
iliya
f7876d89f7 fix(team): seed Write/Edit/NotebookEdit permissions before CLI launch
seedTeammateOperationalPermissionRules already pre-writes MCP tool
rules to settings.local.json before spawning the CLI. But standard
file tools (Write, Edit, NotebookEdit) were missing.

FACT: Teammates requesting Write get setMode: acceptEdits suggestion
but we can't change subprocess session mode. Pre-seeding these tools
as allow rules prevents the permission prompt entirely.
2026-03-30 22:58:22 +03:00
iliya
bd242fac5a fix(team): re-add control_response via stdin for teammate permissions
Belt-and-suspenders approach:
1. Settings file: handles all FUTURE calls (teammate finds rule on retry)
2. control_response via stdin: may unblock CURRENT waiting prompt
   (now includes updatedInput: {} which was the previous ZodError fix)

Without #2, approved teammates stay stuck until team restart because
the CLI doesn't hot-reload settings.local.json for pending prompts.
2026-03-30 21:47:40 +03:00
iliya
9a1ba76324 fix(team): handle setMode permission_suggestions for Write/Edit tools
FACT: Write/Edit permission_requests have permission_suggestions with
type "setMode" (not "addRules"): { type: "setMode", mode: "acceptEdits" }
Our code only handled "addRules", so Write/Edit approvals were no-ops.

Translate setMode suggestions to settings rules:
- acceptEdits → add Edit, Write, NotebookEdit to allow list
- bypassPermissions → add all common tools to allow list
2026-03-30 20:27:03 +03:00
iliya
92968b45ad refactor(graph): simplify comment particle rendering with dedicated bubble function
- Replaced inline drawing logic for task comments with a new `drawCommentBubble` function to enhance readability and maintainability.
- The new function encapsulates the drawing of a speech-bubble icon, including the rounded rectangle body, tail, and inner dots to suggest text.
2026-03-30 20:02:05 +03:00
iliya
485327d077 fix(graph): correct particle direction + remove system message filter
Particle direction:
- Added `reverse` flag to GraphParticle — when true, particle flies
  from target → source (reverse of edge direction)
- Messages FROM teammate TO lead now fly member→lead (was lead→member)
- draw-particles.ts swaps from/to nodes when reverse=true

Reverted system message filter:
- Removed #isSystemMessage — all messages shown as particles again
  (user wants to see idle_notification etc.)
2026-03-30 19:20:53 +03:00
iliya
27b1a4fd9a fix(graph): filter system messages from particles + fix direction
- Skip idle_notification, shutdown, and other JSON system messages
  (was showing {"type":"idle_notificatio... as particle labels)
- Skip system_notification source messages
- Skip messages with < 3 chars
2026-03-30 19:07:16 +03:00
iliya
53dd857e0f Merge branch 'dev' of https://github.com/777genius/claude_agent_teams_ui into dev 2026-03-30 18:59:42 +03:00
iliya
822bbac23c feat(agent-teams): integrate MCP tool catalog and enhance tool registration
- Added mcpToolCatalog to the agent-teams-controller, exporting new types and constants for MCP tool groups and names.
- Updated tools registration to utilize AGENT_TEAMS_MCP_TOOL_GROUPS for streamlined tool management.
- Enhanced tests to validate the new operational permissions and ensure correct tool registration behavior.
2026-03-30 17:58:17 +03:00
iliya
1f28ee5021 fix(ci): stabilize provisioning test and clear lint errors 2026-03-30 16:45:14 +03:00
iliya
9241970b02 fix(graph): format recent tools — clean names + extract readable preview
- Tool names: "mcp__agent-teams__task_create" → "Task Create"
  (strip MCP prefixes, snake_case → Title Case)
- Tool preview: raw JSON → extract subject/name/path field
  (was showing { "id": "19ebbdd5-...", "displayId": ... })
- Compact single-line layout with status dot + name + preview
2026-03-30 16:00:34 +03:00
iliya
34f1f0d612 fix(team): proactively add all agent-teams MCP tools on first approval
When user approves any mcp__agent-teams__* tool, also add all other
agent-teams tools to settings.local.json preemptively. This prevents
teammates from getting stuck on subsequent tool calls (task_get,
task_start, task_complete, etc.) since each generates a separate
permission_request and the teammate blocks until resolved.

FACT: Settings file approach only prevents FUTURE blocks, not current
ones. Pre-adding all tools on first approval covers the common case.
2026-03-30 15:59:53 +03:00
iliya
d2487e41c9 fix(team): trim verbose MCP description from permission noise rows
Remove tool description from permission_request noise label - tool name
alone is clear enough. MCP tools have long technical descriptions that
flood the Messages panel.
2026-03-30 15:56:49 +03:00
iliya
8808a3ab88 fix(graph): disable context bar in lead popover — data unreliable 2026-03-30 15:49:18 +03:00
iliya
664bdbf0cc fix(graph): fullscreen overlay actions work — pass dispatchers to TeamGraphOverlay 2026-03-30 15:44:52 +03:00
iliya
e741b1f603 feat(team): default action mode 'delegate' instead of 'do' for teams 2026-03-30 15:40:54 +03:00
iliya
f08885d58f fix(updater): prevent installation of non-newer versions and enhance update notifications
- Added checks to ensure that only newer versions are installed during the update process.
- Updated the notification logic to suppress alerts for non-newer updates.
- Introduced a new method to compare version numbers, improving version management in the UpdaterService.
- Enhanced the release workflow by removing unnecessary file uploads and adding canonical updater metadata publishing for better asset management.
2026-03-30 15:24:23 +03:00
iliya
e4c9a100f3 fix(graph): remove pt-8 from fullscreen overlay — no padding in fullscreen 2026-03-30 13:50:04 +03:00
iliya
f36501bdef fix(graph): fullscreen overlay pt-8 to clear macOS title bar 2026-03-30 13:48:56 +03:00
iliya
dcf775d86c fix(team): add updatedInput: {} to all allow control_responses
Claude Code CLI Zod schema requires updatedInput to be a record
when behavior is 'allow'. Without it, MCP tool approvals fail with
'Tool permission request failed: ZodError: expected record, received
undefined'.

Add empty updatedInput: {} to all allow responses (autoAllow,
timeout-allow, and manual allow).
2026-03-30 13:45:09 +03:00
iliya
7258de90c3 fix(team): apply permission_suggestions to settings instead of writing to inbox
FACT: Claude Code runtime ignores permission_response in teammate inbox.
FACT: permission_request contains permission_suggestions from runtime
with instructions to add rules to project settings.
FACT: destination "localSettings" = {cwd}/.claude/settings.local.json.

When user clicks Allow for teammate permission_request:
- Parse permission_suggestions from the request
- Add tool rules to {cwd}/.claude/settings.local.json
- Creates directory/file if missing, merges with existing rules
- Teammate retries tool call, finds rule, succeeds

Removed: inbox permission_response write (didn't work)
Removed: control_response via stdin fallback (didn't work)
2026-03-30 12:45:03 +03:00
iliya
1c5ba3041c fix(team): skip stale permission_request messages from previous runs
Inbox files persist across team runs. Permission_request messages from
a previous run (e.g. when team was launched without auto-approve) were
being reprocessed on the next launch, showing false ToolApprovalSheet
popups even when the new run has bypassPermissions enabled.

Filter by timestamp: skip permission_request messages older than
run.startedAt.
2026-03-30 00:09:48 +03:00
iliya
228572a1f8 fix(team): target correct team in Allow all and Settings panel
Allow all button and ToolApprovalSettingsPanel now use current
approval's teamName instead of selectedTeamName. Prevents applying
settings to wrong team when approval comes from a different team
than the one currently viewed.
2026-03-29 22:56:19 +03:00
iliya
58bd7cc507 feat(team): per-team tool approval settings
Tool approval settings (autoAllowAll, autoAllowFileEdits, etc.) are
now stored per-team instead of globally. Clicking 'Allow all' in one
team no longer affects other teams.

- localStorage key: 'team:toolApprovalSettings:{teamName}'
- Settings loaded on team select, initialized on create/launch
- skipPermissions=false -> defaults (autoAllowAll:false)
- skipPermissions=true -> autoAllowAll:true for that team
- Main process: Map<teamName, settings> instead of single instance
- IPC: teamName parameter added to updateToolApprovalSettings
2026-03-29 22:46:25 +03:00
iliya
8c08087337 fix(team): reset autoAllowAll when launching team with manual approval
When the user previously clicked 'Allow all', autoAllowAll persists
globally in localStorage. New teams launched with skipPermissions=false
(manual tool approval) would silently auto-approve everything.

Now createTeam/launchTeam reset autoAllowAll to false when
skipPermissions is explicitly false, ensuring the ToolApprovalSheet
appears for the new team.
2026-03-29 22:32:30 +03:00
iliya
c91a886d49 fix(ci): resolve no-selector-parameter lint error in TeamLogSourceTracker
Split setTracking(enabled) into separate enableTracking/disableTracking
public methods per sonarjs/no-selector-parameter rule. Update all callers
and test mocks accordingly.
2026-03-29 12:59:52 +03:00
iliya
388a24d715 fix(ci): resolve regex complexity lint error and Windows path test failure
- Simplify LAUNCH_RE by pre-stripping optional (resume) prefix to bring
  regex complexity from 23 to within the allowed 20
- Use RegExp.exec() instead of String.match() per lint rules
- Use path.normalize() in BranchStatusService tests for cross-platform
  compatibility (fixes \repo vs /repo on Windows)
2026-03-29 12:40:16 +03:00
iliya
93f160d731 fix(team): ensure MCP config cleanup on spawn failures
- Added logic to remove generated MCP config files when team creation or launch fails due to spawn errors.
- Updated tests to verify that MCP config files are correctly removed in failure scenarios, ensuring no leftover configurations persist.
- Enhanced error handling in the TeamProvisioningService to maintain clean state during provisioning operations.
2026-03-29 01:53:16 +02:00
iliya
e1f0d61dc5 Merge branch 'worktree-fix+mcp-config-storage' into dev 2026-03-29 01:30:01 +02:00
iliya
1ce6ace8b8 fix(team): move MCP config storage from /tmp to userData
MCP config files were stored in os.tmpdir() with no cleanup, and
the MCP server ran from the AppImage FUSE mount path which could
be inaccessible to Claude CLI subprocesses on Linux (fixes #31).

Changes:
- Store MCP configs in app.getPath('userData')/mcp-configs/ with
  pid+timestamp filenames for safe multi-instance operation
- Copy MCP server to userData/mcp-server/<version>/ via atomic
  temp-dir + rename (eliminates FUSE mount dependency)
- Add per-run cleanup in cleanupRun(), startup stale GC (7d TTL),
  and shutdown own-pid GC
- Add --mcp-config recovery in respawnAfterAuthFailure()
- Add setAppDataBasePath(null) reset for test isolation
2026-03-29 01:29:48 +02:00
iliya
7ea8289c5b feat(team): add support for task comment notifications
- Introduced 'task_comment_notification' message kind to enhance message handling in the team services.
- Updated TeamDataService, TeamInboxReader, and TeamSentMessagesStore to accommodate the new message kind.
- Modified filtering logic to exclude task comment notifications from the displayed messages.
- Added tests to ensure correct handling and filtering of task comment notifications.
2026-03-29 01:29:13 +02:00
iliya
46355d87df refactor(session): improve session label formatting and enhance session item display
- Replaced direct access to session.firstMessage with formatSessionLabel for consistent label formatting across components.
- Updated SessionItem, TeamSessionsSection, and KanbanFilterPopover to utilize the new formatting function.
- Enhanced display logic in SessionItem to differentiate between regular and team sessions, improving user experience.
- Added new icons for team sessions and adjusted metadata display for better clarity.
2026-03-29 01:16:04 +02:00
iliya
304a2a7f79 feat(graph): enhance GraphControls with settings toggle and improved zoom functionality
- Added a settings toggle to the GraphControls for better user interaction.
- Implemented event listeners to close settings when clicking outside or pressing Escape.
- Improved zoom controls to mark user interaction, preventing auto-fit adjustments during user actions.
- Refactored GraphOverlay to streamline rendering and position updates for selected nodes.
- Updated GraphView to utilize new layout effects for better performance and responsiveness.
2026-03-29 00:05:29 +02:00
iliya
26f7b9158f fix(graph): enhance particle rendering for task comments
- Added visual differentiation for 'task_comment' particles, adjusting size and glow effects.
- Updated drawing functions to handle new particle kind, ensuring proper rendering in the graph.
- Introduced a merge function for particles to prevent duplicates during state updates.
- Enhanced color constants for better visual representation of different particle types.
2026-03-28 22:55:01 +02:00
iliya
ccd11a5eb0 fix(team): mark permission_request inbox messages as read after scan
Restored markInboxMessagesRead for permission_request messages in the
early scan. Without this, processed permission_request messages stayed
read=false forever, potentially showing stale unread indicators in UI.
2026-03-28 20:36:10 +02:00
iliya
e431cfd02c fix(team): deduplicate permission_request processing across all entry paths
Root cause: handleTeammatePermissionRequest was called from 3 paths
(early inbox scan, Category 4 relay scan, stdout/native) but only
the early scan checked processedPermissionRequestIds, causing
duplicate ToolApprovalRequests and extra permission_responses.

Fix:
- Move processedPermissionRequestIds check INTO handleTeammatePermissionRequest
  so ALL callers are protected by the same dedup gate
- Remove duplicate Category 4 scan that re-processed inbox messages
  (early scan already covers all messages including read=true)
- Category 4 now only builds a filter Set to exclude permission_request
  from relay to lead
2026-03-28 20:32:42 +02:00
iliya
f286468dac fix(team): stable context % + show "% of context" + graph improvements
Context window fix:
- Derive initial contextWindow from model selection (haiku=200K, else=1M)
- Use limitContext flag from request
- Updated to exact value from modelUsage on result.success
- Formula: input_tokens + cache_creation + cache_read (all three needed)

TokenUsageDisplay:
- New contextWindowSize prop → shows "X% of context" (not "X% of input")

Graph improvements:
- Pending approval: pulsing amber ring on member nodes
- Working spinner: spinning arc when member has active task
- Current task indicator in popover (Loader2 + "working on" + task name)
- GraphNode: added currentTaskId, currentTaskSubject, pendingApproval, activeTool fields
- Adapter: passes pendingApprovalAgents + currentTaskId from store
2026-03-28 18:32:10 +02:00
iliya
11506c6ea8 fix(team): fix AskUserQuestion edge cases in ToolApprovalSheet
- Option keys now include question index prefix ("qi:label") to prevent
  cross-question collisions when multiple questions share option labels
- Single-select clears only options from the same question, not all
- answersMessage built as per-question JSON map instead of flat join
- Backend parses JSON answers and maps to correct questions
- Fallback label "Option N" for options with undefined label
2026-03-28 17:00:06 +02:00
iliya
75a36b5cd2 fix(team): deliver AskUserQuestion answers via updatedInput + fix Enter bypass
- Enter key now respects isAskQuestion selection requirement
- Selected option labels sent as message to respondToToolApproval
- control_response includes updatedInput with answers for AskUserQuestion
- useCallback/useEffect deps updated for selectedOptions and hasSelection
2026-03-28 16:54:22 +02:00
iliya
1e80f3db52 feat(team): interactive AskUserQuestion options in ToolApprovalSheet
- Options are clickable: single-select (radio) and multi-select (checkbox)
- Selected options highlighted with green border and filled indicator
- Submit button replaces Allow for AskUserQuestion - disabled until
  at least one option is selected
- Human-readable tool display names (AskUserQuestion -> Question, etc.)
- Selection resets when approval changes
2026-03-28 16:49:24 +02:00
iliya
daef2db07c fix(team): prevent hooks ordering crash in ToolInputPreview
Move useMemo/variable declarations BEFORE the AskUserQuestion early
return to ensure hooks are called in consistent order regardless of
which tool type is being displayed.
2026-03-28 16:44:26 +02:00
iliya
6b09b59d88 feat(team): render AskUserQuestion tool as readable UI in ToolApprovalSheet
Instead of showing raw JSON for AskUserQuestion, render each question
with header badge, question text, and options list showing labels and
descriptions. Supports multiSelect indicator (checkbox vs radio style).
Add MessageCircleQuestion icon for the tool.
2026-03-28 16:40:18 +02:00
iliya
e2000d0900 feat(agent-graph): show pulsing amber ring on agents awaiting approval
- Add pendingApproval field to GraphNode type
- Pass pendingApprovalAgents Set from store through adapter
- Draw pulsing amber ring + subtle glow on agent nodes that have
  pending tool approval requests
- Include approval state in adapter cache hash for reactivity
2026-03-28 16:17:39 +02:00
iliya
70b5f1962f feat(team): add Skip button to pre-flight CLI check in launch/create dialogs
Users can now skip the CLI warmup check and launch immediately.
Sets prepareState to 'ready' so the Launch button unlocks.
2026-03-28 16:10:32 +02:00
iliya
d01bce2101 feat(team): show approval status icons on permission_request noise rows
- Add resolvedApprovals Map to store (request_id -> allowed/denied)
- Record result in respondToToolApproval and autoResolved events
- NoiseRow accepts optional icon prop
- Permission request rows show: check (approved), x (denied),
  clock (pending), or faded check (pre-existing/unknown)
2026-03-28 15:52:12 +02:00
iliya
9f2a7c950a fix(team): fix hooks ordering crash in ToolApprovalSheet
Move useMemo for sourceColor BEFORE the early return (if !current),
and restore teamSummary/teamColor/displayName variables that were
accidentally removed. Fixes 'Rendered fewer/more hooks' React crash.
2026-03-28 15:40:56 +02:00
iliya
ff8b844abe fix(team): show MemberBadge with avatar in ToolApprovalSheet header
Replace plain text teammate name with MemberBadge component showing
avatar + colored name badge, consistent with how members are displayed
in the Messages panel.
2026-03-28 15:24:07 +02:00
iliya
ee5b7b5888 feat(graph): current task indicator + working spinner on member nodes
Popover:
- Shows "working on [task subject]" with spinning Loader2 when member
  has currentTaskId (same pattern as CurrentTaskIndicator in MemberCard)
- Click task subject → opens TaskDetailDialog

Canvas:
- Active members with currentTaskId get subtle spinning arc around hexagon
- Spinner only shows when state is active/thinking/tool_calling

Adapter:
- Passes currentTaskId + currentTaskSubject from ResolvedTeamMember
- Looks up task subject from data.tasks

Port types:
- Added currentTaskId, currentTaskSubject to GraphNode
2026-03-28 15:18:23 +02:00
iliya
add9df2006 fix(graph): Profile opens member dialog (not message) + Add Task button
- Profile button dispatches 'graph:open-profile' → MemberDetailDialog
  (was incorrectly mapped to 'graph:send-message')
- Double-click on member → opens profile (was: send message)
- New "Add Task" button on member popover → CreateTaskDialog with owner pre-filled
- New events: graph:open-profile, graph:create-task
- TeamDetailView listens for both new events
2026-03-28 15:08:32 +02:00
iliya
26fe42739b refactor(graph): fix SOLID/DRY violations from audit
DRY fixes:
- GraphOverlay.tsx: 539 LOC → 85 LOC minimal fallback (was dead code)
- COLUMN_LABELS: import from COLORS instead of hardcoded hex duplicates
- Alpha hex LUT: consolidated to single source in colors.ts
- TeamGraphTab: extract typed dispatchOpenTask/dispatchSendMessage helpers
  (was 8 repeated CustomEvent dispatches)

SOLID fixes:
- D-1: lucide-react added to peerDependencies in package.json
- S-1: GraphOverlay no longer has 8 responsibilities (now just 1 fallback)

Architecture:
- renderOverlay prop properly used by both Tab and Overlay
- Popover rendering lives in features/ layer only (no duplication with package)
2026-03-28 14:41:24 +02:00
iliya
54c259b017 refactor(graph): extract popover to features layer — reuse project UI (DRY)
- New: GraphNodePopover.tsx in features/agent-graph/ui/
  Uses @renderer/components/ui/badge, button, agentAvatarUrl
  No code duplication with MemberCard/MemberHoverCard patterns

- GraphView: added renderOverlay prop — host app injects its own popover
  Falls back to built-in GraphOverlay if renderOverlay not provided

- TeamGraphTab + TeamGraphOverlay pass renderOverlay with GraphNodePopover
  Member popover: avatar, status dot, role, context bar, badges, Message/Profile
  Task popover: displayId, status/review badges, Open button
  Process popover: label, URL link
2026-03-28 14:27:55 +02:00
iliya
cb17e2158f feat(graph): default to tab mode + fullscreen button in tab
- Graph button opens dedicated tab (was: overlay)
- Cmd+Shift+G opens tab (was: toggle overlay)
- Tab mode has Fullscreen button → opens overlay on top
- Tab actions (Message, Open) dispatch CustomEvents to TeamDetailView
  which opens corresponding dialogs (SendMessage, TaskDetail)
- Overlay still available via Fullscreen button or TeamGraphOverlay
2026-03-28 14:17:10 +02:00
iliya
8a9121fc3e fix(graph): toggle buttons visually distinct — active gets border + glow, inactive dimmed 2026-03-28 14:11:28 +02:00
iliya
98a1155635 feat(graph): wire popover actions to real dialogs (Message, Open task/member)
- TeamGraphOverlay accepts onSendMessage, onOpenTaskDetail, onOpenMemberProfile
- TeamDetailView passes dialog openers to overlay:
  - Message → opens SendMessageDialog with recipient pre-filled
  - Open (task) → opens TaskDetailDialog with task found by ID
  - Open (member) → opens SendMessageDialog for that member
  - Double-click → same as Open
- Removed console.log stubs
2026-03-28 12:56:43 +02:00
iliya
d85058f198 feat(graph): robohash avatars inside member hexagons + center column headers
- Member/lead nodes show robohash avatar image clipped to circle inside hex
- Async image loading with cache (fallback to first letter while loading)
- avatarUrl field added to GraphNode type + adapter passes agentAvatarUrl()
- Column headers now centered over pill center (was offset by half pill width)
2026-03-28 12:46:25 +02:00
iliya
6866f003dc feat(graph): spawn/edge/task/comment animations
1. Member spawn animation: rotating dashed ring for 'spawning' status,
   pulsing hex outline for 'waiting' status
2. Edge flash: active edges pulse brighter (0.1-0.5 alpha) with glow
   shadow when particles travel along them
3. Smooth task positioning: tasks LERP to target position (0.15 factor)
   instead of teleporting when kanban column changes
4. Comment flight particles: when a member adds a comment to a task,
   a purple particle with speech bubble flies from member to task node
2026-03-28 12:27:37 +02:00
iliya
17e9be99dd fix(ui): change auto-approve banner from warning to info style 2026-03-28 12:23:28 +02:00
Илия
11bb49c53e
feat(graph): force-directed agent graph visualization with kanban-zone task layout
Force-directed graph visualization for agent teams.

Package: @claude-teams/agent-graph (isolated workspace package)
- Space theme: bloom, particles, hex grid, depth stars
- Members as hexagonal nodes with breathing glow
- Tasks as pill cards in kanban columns (todo/wip/done/review/approved) per owner
- Message particles along edges (real-time only)
- Deterministic layout, Figma-style pan, scroll/pinch zoom
- Clean Architecture: ports/adapters/strategies, ES #private classes

Integration: features/agent-graph/ (adapter + overlay + tab)
- Full-screen overlay (Cmd+Shift+G) + Pin as Tab
- Graph button in Team section header
- Frustum culling, zero per-frame allocations, adaptive fps
- Performance overlay via ?perf query param

Also: CI runs on all PR branches, features/CLAUDE.md architecture guide
2026-03-28 12:03:42 +02:00
iliya
dd42cf0069 fix(team): scan inbox for permission_request during provisioning
relayLeadInboxMessages only processes unread messages after
provisioningComplete, but CLI marks permission_request messages as
read after native delivery -- before our relay runs.

Move permission_request inbox scan BEFORE provisioningComplete check.
Scan ALL messages (including read=true), track processed IDs via
processedPermissionRequestIds Set on ProvisioningRun to prevent
re-emitting. Also look up both alive and provisioning runs so the
scan works during team bootstrap.
2026-03-27 23:35:52 +02:00
iliya
df6a23e3a2 Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 22:04:55 +02:00
iliya
d0b9c4f529 fix(team): settings panel opens below buttons instead of beside them
Split ToolApprovalSettingsPanel into ToolApprovalSettingsToggle (inline
button) and ToolApprovalSettingsContent (full-width expandable panel).
Toggle sits in the actions row, content renders below it inside the popup.
2026-03-27 22:04:44 +02:00
iliya
5c0eb1fa38 Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 20:16:14 +02:00
iliya
c0c20d07f8 fix(team): add backdrop overlay to ToolApprovalSheet and move Settings inline
- Add semi-transparent backdrop (bg-black/40) behind the approval popup
  to draw attention and dim surrounding UI
- Refactor ToolApprovalSettingsPanel to render toggle button inline
  (fragment-based) so it can sit in the actions row next to pending count
- Settings button now appears right-aligned at the same level as
  Allow/Deny buttons; expanded panel renders below
2026-03-27 20:16:03 +02:00
iliya
f2eabf3866 Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 20:09:09 +02:00
iliya
bdd0dc6f39 fix(team): add permission_request interception in stdout handler + diagnostic logging
- Parse raw user text for permission_request in handleStreamJsonMessage
  (covers case where permission_request arrives without <teammate-message> wrapper)
- Add [PERM-TRACE] logger.warn diagnostics to trace the exact flow:
  where permission_request is detected, whether it reaches handleTeammatePermissionRequest,
  and whether relay or stdout interception triggers
- These logs will help diagnose why ToolApprovalSheet may not appear
2026-03-27 20:09:01 +02:00
iliya
148823e284 Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 18:45:07 +02:00
iliya
ed1726c298 fix(team): intercept permission_request in native stdout delivery path
relayLeadInboxMessages only runs after provisioningComplete, but
teammate permission_request messages arrive during bootstrap (before
provisioning finishes). Claude Code delivers them natively via stdout
type:"user" messages, bypassing the relay entirely.

Add permission_request interception in handleNativeTeammateUserMessage
which processes stdout user messages at all times, including during
provisioning. This ensures ToolApprovalSheet appears immediately when
teammates need tool permission.
2026-03-27 18:44:58 +02:00
iliya
373f2aac9b Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 18:13:06 +02:00
iliya
8ea470b1ae fix(team): intercept permission_request regardless of native delivery status
When Claude Code runtime natively delivers permission_request to the
lead via stdout, the message was excluded from interception by the
nativeMatchedMessageIds filter. This caused the ToolApprovalSheet to
not appear for teammate requests.

Remove nativeMatchedMessageIds check from the permission_request
filter so interception works even for natively delivered messages.
2026-03-27 18:12:58 +02:00
iliya
085147ffc0 Merge branch 'worktree-fix-permission-request-ui' into dev 2026-03-27 17:56:08 +02:00
iliya
924bcd8b99 fix(team): render teammate permission requests in ToolApprovalSheet instead of raw JSON
When auto-approve is disabled, teammate tool requests arrived as
permission_request JSON via SendMessage and rendered as "Raw JSON"
with no way to approve/deny (#29).

- Intercept permission_request in lead inbox relay, convert to
  ToolApprovalRequest and show in existing ToolApprovalSheet
- Respond via teammate inbox (permission_response) + control_response
  via stdin as fallback
- Show teammate name in approval header (e.g. "bob — Bash")
- Compact noise label in Messages panel for permission_request/response
- Proper file locking, race condition protection, idempotency checks
2026-03-27 17:55:59 +02:00
iliya
507bf798eb improvement(task-change): improve task change presence tracking and related IPC handlers
- Added support for tracking task change presence with new IPC channels: TEAM_GET_TASK_CHANGE_PRESENCE and TEAM_SET_CHANGE_PRESENCE_TRACKING.
- Introduced JsonTaskChangePresenceRepository and TeamLogSourceTracker to manage task change presence data.
- Enhanced ChangeExtractorService to utilize task change presence services for improved task change detection.
- Updated TeamDataService to integrate task change presence tracking and resolve task change presence states.
- Modified UI components to reflect task change presence status in Kanban and task detail views.

This feature aims to provide real-time insights into task changes, enhancing user experience and task management capabilities.
2026-03-27 17:52:39 +02:00
iliya
ecba775c76 Improve macOS title bar drag area 2026-03-27 17:21:18 +02:00
iliya
e1413a32bd Guard renderer IPC sends during crash recovery 2026-03-27 17:07:40 +02:00
iliya
9f8287755c fix(updater): improve update dialog layout and strip downloads section
Widen dialog (max-w-lg → max-w-2xl), remove prose max-width constraint
that caused empty space on the right, and filter out the Downloads
heading with everything below it from release notes.
2026-03-26 13:13:50 +02:00
iliya
344bf41fe5 fix(updater): verify platform asset exists before showing update notification
HEAD-request the expected installer URL (DMG/EXE/AppImage) before
notifying the user about a new version. If CI hasn't finished
uploading the artifact for the current OS yet, the notification is
suppressed and retried on the next periodic check.
2026-03-26 00:50:12 +02:00
iliya
c7ee51884d Merge branch 'worktree-upstream-merge' into dev 2026-03-25 15:44:54 +02:00
iliya
bd90de8e81 fix(team): notify lead on task create with startImmediately
Extract sendUserTaskStartNotification as reusable private method.
When a task is created via UI directly in "In Progress" column
(startImmediately=true), the controller's maybeNotifyAssignedOwner
skips the lead. Now createTask sends the notification to the lead
with full description, prompt, and task_get instructions.
2026-03-25 15:03:44 +02:00
iliya
58f3ccd4b4 feat(dashboard): add auth troubleshooting guide to CLI status banner
Add "Already logged in?" button next to Login that expands a
step-by-step troubleshooting panel: re-check status, terminal
commands, re-login instructions, and binary path display.
Also clarifies that browsing works without login.
2026-03-25 15:00:42 +02:00
iliya
141d0e22d9 feat(team): implement startTaskByUser functionality
- Added a new IPC handler for starting tasks triggered by users, ensuring that the task owner is always notified.
- Introduced `startTaskByUser` method in `TeamDataService` to handle task initiation and notifications.
- Updated relevant components and API interfaces to support the new functionality, including changes in the UI to call `startTaskByUser` instead of the previous `startTask`.
- Documented agent block usage for internal instructions in CLAUDE.md.

This enhancement improves user interaction with task management by providing a clear mechanism for user-initiated task starts.
2026-03-25 14:47:27 +02:00
iliya
22387ca0cb perf: add search debounce and increase global search timeout
- SearchBar: 300ms debounce with local input state, flush on Enter
- CommandPalette: global search debounce 200→400ms
- Show "500+" when search results are capped
- Fix: syncSearchMatchesWithRendered now updates searchMatchItemIds

Ported from upstream 5c7f921e (SearchBar/CommandPalette parts).
2026-03-25 14:38:07 +02:00
iliya
c21350713c perf: replace remark-based search with plain text indexOf
Manually ported from upstream 5c7f921e. Key changes:
- SessionSearcher: indexOf instead of remark AST, batch size 8→16
- conversationSlice: indexOf with MAX_SEARCH_MATCHES=500 cap
- Item-scoped store selectors (searchMatchItemIds Set) to skip re-renders
- Pre-filter in markdownTextSearch (skip parse if no raw match)
- SearchTextCache: 200→1000 entries
- ProjectScanner: 30s search project cache, batch 4→8
2026-03-25 14:32:37 +02:00
iliya
e30f6482bf fix: WSL mount path translation + Windows drive letter normalization
Manually ported from upstream:
- c239cda6: translateWslMountPath() converts /mnt/X/... → X:/... on Windows
- 7f5fbdab: normalizeDriveLetter() uppercases drive letter (c:/ → C:/)

Both are no-op on macOS/Linux. Fixes session fragmentation on Windows+WSL.
2026-03-25 14:22:04 +02:00
iliya
aeed5a0873 feat: add syntax highlighting for R, Ruby, PHP, and SQL
Cherry-picked from upstream 022c75da with conflict resolution.
Merged our codeClassName support with upstream per-line highlighting.
2026-03-25 14:05:53 +02:00
iliya
b87082a915 fix: requestId dedup to prevent ~2x cost overcounting + stale session detection
Manually ported from upstream:
- ef2e0868: deduplicate streaming JSONL entries by requestId
- 4f21f267: mark stale ongoing sessions as dead after 5min inactivity
2026-03-25 14:05:01 +02:00
iliya
aaa766b2ba perf: replace 8 filter passes with single-pass message categorization
Cherry-picked from upstream 9fa2590e
2026-03-25 13:59:03 +02:00
iliya
6fa075de51 fix: sidebar header repo/branch not syncing when switching tabs
Cherry-picked from upstream d2341d50
2026-03-25 13:58:48 +02:00
iliya
4946a65a7b feat: cherry-pick upstream CollapsibleOutputSection + TriggerMatcher regex cache
Cherry-picked from upstream:
- 516d0f6b: CollapsibleOutputSection with markdown preview toggle
- e51c1fd1: cache compiled regexes in TriggerMatcher (perf)
2026-03-25 13:58:38 +02:00
iliya
7324b5236d fix(team): update tool references from Task to Agent in provisioning messages
- Changed references in messages to use the **Agent** tool instead of the Task tool for spawning teammates.
- Added warnings for missing team_name to ensure agents are persistent rather than ephemeral.
- Updated documentation within the code to reflect the new requirements for spawning teammates.
2026-03-25 13:38:26 +02:00
iliya
b8aa2d9f14 fix(auth): enrich PTY env and invalidate status cache after login
- Use buildEnrichedEnv() in PtyTerminalService so login terminal gets
  full PATH (Homebrew, nvm, etc.) and USER for Keychain lookup
- Add cliInstaller:invalidateStatus IPC to clear cached auth status
  after successful login, preventing stale "not logged in" responses
- Show "Verifying authentication..." spinner instead of flashing
  the "Not logged in" banner between modal close and status refresh

Ref #27
2026-03-25 13:36:12 +02:00
iliya
60d80cde70 fix(auth): avoid setting CLAUDE_CONFIG_DIR when it matches default path
On macOS, the Claude CLI uses a Keychain namespace derived from the
presence of CLAUDE_CONFIG_DIR env var. Setting it to the default
~/.claude creates a different Keychain key than when the var is absent,
causing "not logged in" errors even after successful `claude auth login`.

Only set CLAUDE_CONFIG_DIR when the user has configured a custom path
that differs from the auto-detected default.

Fixes #27
2026-03-25 12:23:57 +02:00
iliya
896c749e76 fix: add recursive option to fs.rm for directory removal
fs.rm() without { recursive: true } throws ERR_FS_EISDIR on directories,
unlike the deprecated fs.rmdir() which handled empty dirs. Also fix
broken roadmap bullet in README.
2026-03-24 21:43:43 +02:00
iliya
08be8590da fix: electron 28→40 migration fixes
- Replace deprecated fs.rmdir with fs.rm (Node 22+ deprecation)
- Update electron-builder 25.1.8 → 26.8.1 (required for Electron 35+)
- Add macOS minimumSystemVersion 12.0 (Electron 38+ requirement)
- Update React 18 → 19 in README.md tech stack
2026-03-24 21:13:06 +02:00
iliya
3b65dc4e3b fix(lint): resolve import sort errors and update tech stack in CLAUDE.md
- ProjectScanner.ts, cliEnv.ts: fix simple-import-sort/imports order
- CLAUDE.md: update tech stack to Electron 40.x, React 19.x
2026-03-24 18:23:00 +02:00
iliya
368f42f04f fix(hooks): resolve react-hooks/refs lint errors breaking CI
- useMarkCommentsRead: replace useRef().current with useCallback for
  stable ref callback (accessing ref during render is not allowed)
- useAttachments: add eslint-disable for intentional ref sync pattern
2026-03-24 18:06:08 +02:00
iliya
94fc564bf5 feat: UI improvements, bug fixes, and protocol noise filtering
- Fix incorrect error message when attaching files to team lead while team is offline
- Kanban columns: color only on headers, body with 30% alpha tint per user preference
- Worktree projects now correctly detected on Dashboard via path-based detection
- Filter raw protocol messages (idle_notification, teammate-message) from lead thoughts
- Consistent text styles in Attachments section (From original message / From comments)
- Secondary sort for teams by lastActivity timestamp with alphabetical fallback
- Remove colored background from team cards, keep only left border
- Dynamic member color in Add Members dialog based on next available palette color
- Stylized @-mentions in task comments with colored MemberBadge
- Refactor CLI env resolution to shared utility
2026-03-24 17:47:15 +02:00