- TeamProvisioningServiceRelay: add missing stat fields (mode, dev, ino,
mtimeMs, ctimeMs, birthtimeMs) to fs mock so new fingerprint-based
TeamConfigReader cache can read config in tests
- TeamMcpConfigBuilder: export clearResolvedNodePathForTests() to reset
module-level node path cache between tests; restore execFileMock
implementation in beforeEach after vi.restoreAllMocks() clears it;
broaden node binary regex to accept versioned names (node-22, node-20)
common on Fedora/RHEL systems
- ScheduledTaskExecutor: strip CLAUDECODE at spawn site as last defence
so nested-session detection is prevented even when buildProviderAwareCliEnv
merges it back in from the outer process environment
- Introduced caching mechanism with expiration for message feeds to improve performance.
- Added logging for cache expiration events to aid in debugging.
- Updated MessagesPanel to reopen search bar when participant filters are active.
- Added test cases for handling tmux server errors and message panel behavior with filters.
- Updated `getClaudeLogs` method to support asynchronous fetching of logs.
- Introduced new interfaces for retained logs and transcript cache entries.
- Added logic to retain and retrieve Claude logs even after cleanup of live runs.
- Implemented fallback mechanism to use persisted transcripts when no live run exists.
- Updated tests to cover new log retention and retrieval scenarios.
Remove the SessionDetail.messages stripping and related cache-size
change per maintainer feedback. The session-detail optimization will
follow separately after PR #58 lands with the right architectural
pattern (lightweight snapshot + separate endpoints).
This PR now contains only:
- progressPayload helpers (buildProgressLogsTail, buildProgressAssistantOutput)
- cap applied to emitLogsProgress, updateProgress, stall warning, retry error
- throttle raised 300ms -> 1000ms
- tests for the progress payload behavior
Users with long-running teams (37+ tasks, 10+ agents for an hour) were
hitting constant renderer crashes (issue #36). Two hot paths were
serializing unbounded histories across IPC on every tick:
- Provisioning progress: emitLogsProgress and updateProgress both
joined the full provisioningOutputParts array (~20 event-driven call
sites) plus the full CLI log tail, then fanned that out to the
renderer. After an hour, each tick shipped multi-megabyte payloads
and Zustand OOM'd on the immutable state clone.
- Session detail cache: SessionDetail.messages (the raw parsed JSONL)
was being cached and returned over IPC/HTTP even though the renderer
only reads session/chunks/processes/metrics. This roughly doubled
the per-entry cache footprint on large sessions.
Fixes:
- Add progressPayload helpers that cap the log tail to 200 lines and
assistant output to the last 20 parts; empty/whitespace joins
collapse to undefined so the noop guard is explicit rather than
coincidental.
- Apply the cap inside emitLogsProgress, updateProgress, and the two
inline emission paths (stall warning, retry error). Throttle the
log-progress tick 300ms -> 1000ms so Zustand can keep up.
- Add stripSessionDetailMessages and call it at every SessionDetail
production site that crosses IPC/HTTP (both sessions.ts routes,
both cache stores).
- Raise MAX_CACHE_SESSIONS 5 -> 20 now that the per-entry SessionDetail
footprint is bounded. Previously 5 forced constant re-parsing on
every session switch.
Tests: 15 new unit tests covering the helpers (tail slicing, empty
parts, whitespace-only parts, non-mutation of inputs).
- Added support for live runtime model metadata in team provisioning.
- Implemented functions to extract and manage CLI flag values for team members.
- Updated member specifications to include effective models based on provider defaults.
- Enhanced UI dialogs to check selected providers in parallel, improving responsiveness.
- Added tests for handling model unavailability during team bootstrap and launch processes.
- Introduced CLI_INSTALLER_VERIFY_PROVIDER_MODELS IPC channel for on-demand model verification.
- Implemented handler for verifying provider models in the CliInstallerService.
- Enhanced CLI installation status management with model verification state and availability.
- Updated related components to support model verification feedback in the UI.
- Updated components in the agent-graph renderer to utilize context hooks instead of the store for accessing team data.
- Introduced `useGraphActivityContext` and `useGraphMemberPopoverContext` hooks to streamline data management.
- Refactored `GraphBlockingEdgePopover`, `GraphNodePopover`, and `GraphTaskCard` components for improved performance and readability.
- Enhanced imports in `MemberDetailDialog` for better organization.
* fix(team): resolve stuck "reconciling" state and skip resume when teammates never spawned
Addresses #54.
When a team launch fails to bootstrap teammates, the team gets stuck showing
"Last launch is still reconciling" indefinitely, and retrying with --resume
reconnects the lead but does not re-spawn the dead teammates. The only
workaround was enabling "Clear context (fresh session)", which loses the
lead's prior conversation context.
Two root causes addressed:
1. createPersistedLaunchSnapshot counted members still in 'starting' state
(agentToolAccepted=false) as 'pending' regardless of launchPhase. When
launchPhase was 'finished' with never-spawned members, the aggregate
state stayed as 'partial_pending' forever, rendered as "still reconciling".
Fix: when launchPhase != 'active', promote such members to
'failed_to_start' so the aggregate becomes 'partial_failure'
("Launch failed partway"), which correctly signals a terminal state.
2. TeamProvisioningService._launchTeamInner always used --resume when a
previous leadSessionId existed, even if the previous launch had no
teammates successfully spawned. The CLI's deterministic reconnect path
restores lead context but does not re-spawn dead teammates, so the team
stays broken across relaunches. Fix: before adding --resume, read the
persisted launch state. If every expected teammate is 'starting' (never
spawned) or 'failed_to_start', skip --resume so the CLI performs a full
fresh bootstrap that spawns all teammates.
Verified manually on Linux: a team stuck in "still reconciling" correctly
transitions to "failed partway" after the first fix, and the next Launch
(without "Clear context") fully bootstraps and brings teammates online.
* fix(team): narrow skip resume to never-spawned teammates
---------
Co-authored-by: 777genius <quantjumppro@gmail.com>
The test races stale and fresh worker calls to verify that invalidation
prevents stale results from populating the cache. On slow CI, the
fresh worker mock could be reached before the stale deferred was
resolved, causing the version guard to mismatch.
Flush microtasks after starting freshPromise so it advances past
internal awaits and reaches the worker mock before we resolve the
stale deferred.
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.
- 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.
- 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.
- 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.
Split setTracking(enabled) into separate enableTracking/disableTracking
public methods per sonarjs/no-selector-parameter rule. Update all callers
and test mocks accordingly.
- 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)
- Replaced `ensureTracking` and `stopTracking` with a single `setTracking` function in `TeamDataService` to streamline task change presence tracking.
- Updated related tests to reflect the new tracking logic and ensure proper function calls.
- Added `activeToolCalls` property to various service interfaces to improve state management during provisioning operations.
- 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.
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
- 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.
- 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.
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
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.
- 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.
- 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
- Updated tests to ensure legacy inbox rows without messageId generate a deterministic hash-based messageId.
- Modified test descriptions for clarity and accuracy regarding messageId generation.
- Adjusted expectations in tests to reflect the new behavior of relaying legacy lead inbox rows with generated messageIds.
- Updated package versions in pnpm-lock.yaml, including rollup and sass dependencies.
- Added new 'landing' package to pnpm-workspace.yaml.
- Enhanced README with additional images for better visual representation.