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.
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.
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.
- 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.
- Enhanced text processing to clean up raw task ID hashes and replace pipe separators with dashes.
- Ensured consistent formatting for comments and inbox messages.
- 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
- 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.
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.
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.
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
- 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.
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.)
- Included a warning regarding an upstream issue in Claude Code affecting the inheritance of external MCP tools by teammates spawned via Agent/Task.
- Noted the impact on bootstrap processes and provided a link to track the issue status.
- 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.
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.
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.