Conversation
pedramamini
commented
Feb 7, 2026
- validate agent prompt before auto-run: require Markdown task references
- group chat recovery, SSH history guard, and tour shortcut fix
Code Review: 0.15.0 PolishThis PR includes three main improvements: agent prompt validation for Auto Run, group chat recovery enhancements, and SSH history path fixes. Overall the changes are well-structured with good test coverage. Here's my detailed feedback: ✅ Strengths1. Comprehensive Test Coverage
2. Defensive Programming
3. User Experience
🔍 Issues & RecommendationsHigh Priority1. Prompt Validation May Be Too Strict// src/renderer/hooks/batch/batchUtils.ts:54-68
export function validateAgentPromptHasTaskReference(prompt: string): boolean {
const patterns = [
/markdown\s+task/i,
/- \[ \]/,
/- \[x\]/i,
// ...
];
return patterns.some((pattern) => pattern.test(prompt));
}Concern: This validation uses heuristics that could produce false negatives. A prompt like Recommendation: Consider either:
2. Regex Escaping Issue/- \[ \]/, // literal checkbox syntax
/- \[x\]/i, // checked checkbox syntaxIssue: Square brackets in regex are special characters for character classes. While this works by coincidence (matches literal Fix: /-\s*\\\[\s*\\\]/, // Properly escaped checkbox
/-\s*\\\[[xX]\\\]/i, // Properly escaped checked boxMedium Priority3. Missing Null Check in Exit Listener// src/main/process-listeners/exit-listener.ts:292
groupChatEmitters.emitMessage?.(groupChatId, {
timestamp: new Date().toISOString(),
from: 'system',
content: `Session expired for ${participantName}. Creating a new session...`,
});Observation: Uses optional chaining ( Recommendation: Log a warning if if (groupChatEmitters.emitMessage) {
groupChatEmitters.emitMessage(groupChatId, { ... });
} else {
logger.warn('[GroupChat] Cannot notify UI - emitMessage unavailable', 'ProcessListener');
}4. Session ID Format Coupling// src/main/process-listeners/exit-listener.ts:263
const isRecoverySession = sessionId.includes('-recovery-');Concern: This string-based check is fragile. If the session ID format changes elsewhere, this guard could fail silently. Recommendation: Use the session parser utility: import { parseParticipantSessionId } from '../group-chat/session-parser';
const parsed = parseParticipantSessionId(sessionId);
const isRecoverySession = parsed && sessionId.includes('-recovery-');Or add a dedicated 5. Inconsistent Error Handling// src/renderer/App.tsx:2955
if (agentError.type === 'session_not_found') {
console.log('[onAgentError] Suppressing session_not_found...');
return; // Early return suppresses error handling
}Concern: Silent suppression could mask issues if recovery fails. The exit listener handles recovery, but if that code path has bugs, the UI won't show any error state. Recommendation: Add a timeout mechanism to detect recovery failures: if (agentError.type === 'session_not_found') {
// Set a timeout to show error if recovery doesn't complete
const timeoutId = setTimeout(() => {
setGroupChatError({ groupChatId, participantName, error: 'Recovery timed out' });
}, 30000); // 30s timeout
// Store timeoutId to clear it when recovery succeeds
return;
}Low Priority6. Code Duplication in SSH GuardsThe SSH history path guard is duplicated in two places:
Recommendation: Extract to a shared utility: // src/renderer/utils/historyUtils.ts
export async function getHistoryFilePathForSession(
sessionId: string,
sshRemoteConfig?: { enabled: boolean }
): Promise<string | undefined> {
const isSSH = sshRemoteConfig?.enabled;
if (isSSH) return undefined;
try {
const path = await window.maestro.history.getFilePath(sessionId);
return path ?? undefined;
} catch {
return undefined;
}
}7. Tour Shortcut Fix Context// src/renderer/App.tsx:14549
shortcuts={{ ...shortcuts, ...tabShortcuts }}Question: The PR description mentions "tour shortcut fix" but doesn't explain what was broken. Consider adding a comment explaining why 🔒 Security✅ No security concerns identified. The validation logic prevents injection attacks by constraining prompts to task-related content. ⚡ Performance✅ No performance concerns. Regex validation is O(n) on prompt length and runs only on user input (not hot path). 📝 DocumentationMissing:
🎯 Overall AssessmentVerdict: Good PR with solid improvements. The validation feature is valuable but needs regex fixes and possibly relaxed heuristics. Recovery enhancements are well-implemented with good safeguards. Action Items:
Recommendation: ✅ Approve with suggestions - Changes are production-ready but would benefit from the regex fix before merge. Reviewed with guidance from CLAUDE.md conventions |
Code Review - PR #324: 0.15.0 PolishThis is a well-structured polish PR with good test coverage and thoughtful fixes. Here's my detailed review: ✅ Strengths
🔍 Issues & Concerns1. Regex Pattern Coverage (Medium Priority)The Too Broad:
Potentially Missing:
Recommendation: Add test cases for false positives (e.g., "This tool doesn't support checkboxes") and expand coverage for all markdown checkbox variants from 2. modalStore Migration Bug Fix - Potential Race Condition (Low Priority)The fix changes setters to use src/renderer/stores/modalStore.ts:864-877 setRenameTabId: (tabId: string | null) => {
if (!tabId) return;
const current = useModalStore.getState().getData('renameTab');
openModal('renameTab', { tabId, initialName: current?.initialName ?? '' });
},
setRenameTabInitialName: (initialName: string) => {
const current = useModalStore.getState().getData('renameTab');
if (current) {
updateModalData('renameTab', { initialName });
} else {
openModal('renameTab', { tabId: '', initialName });
}
},Problem: If callers do: Better approach: Always use setRenameTabInitialName: (initialName: string) => {
const current = useModalStore.getState().getData('renameTab');
openModal('renameTab', { tabId: current?.tabId ?? '', initialName });
},Same pattern applies to 3. SSH History Guard - Incomplete Check (Medium Priority)src/renderer/hooks/input/useInputProcessing.ts:798-808 const isSSH = freshSession.sshRemote || freshSession.sessionSshRemoteConfig?.enabled;
if (!isSSH) {
try {
historyFilePath = (await window.maestro.history.getFilePath(freshSession.id)) || undefined;
} catch {
// Ignore history errors
}
}Issue: This checks Looking at the similar code in const isSSH = sessionSshRemoteConfig?.enabled;Recommendation: Verify which field is correct by checking session type definitions, and standardize the SSH check across both files. Also add a comment explaining why 4. TabBar Tests - Misleading Test Name (Low Priority)src/tests/renderer/components/TabBar.test.tsx:167-175 it('does not show Send to Agent button for tabs without logs', async () => {
const tabs = [
createTab({
id: 'tab-1',
name: '',
agentSessionId: undefined,
logs: [],
}),
];The test name says "without logs" but it also has {(tab.logs?.length ?? 0) >= 1 && onSendToAgent && (So it's checking for logs, not 5. Group Chat Recovery - Missing Edge Cases (Low Priority)src/main/process-listeners/exit-listener.ts:429-435 const isRecoverySession = sessionId.includes('-recovery-');
const chat = await groupChatStorage.loadGroupChat(groupChatId);
const agentType = chat?.participants.find((p) => p.name === participantName)?.agentId;
if (!isRecoverySession && sessionRecovery.needsSessionRecovery(bufferedOutput, agentType)) {Potential Issues:
Recommendation: Add null checks: if (!chat) {
debugLog('GroupChat:Debug', `Group chat ${groupChatId} not found, skipping recovery`);
return;
}
const participant = chat.participants.find((p) => p.name === participantName);
if (!participant) {
debugLog('GroupChat:Debug', `Participant ${participantName} not found in chat, skipping recovery`);
return;
}6. Tour Shortcut Fix - Verify Spread Order (Low Priority)src/renderer/App.tsx:14512-14513 shortcuts={{ ...shortcuts, ...tabShortcuts }}This spreads 🔒 Security ConsiderationsNo security issues found. The validation logic prevents injection by being purely heuristic (no eval/exec). SSH guards prevent path leakage across boundaries. ⚡ Performance ConsiderationsThe validation function runs 8 regex patterns on every prompt change. For long prompts (>10KB), this could cause input lag. Consider:
Performance impact should be negligible. 📝 SummaryApprove with Recommendations:
Test Coverage: Excellent (+237 lines of tests) The infinite loop prevention and user messaging for group chat recovery are particularly well-implemented. The modalStore fix directly addresses the root cause rather than symptoms. |
Pull Request Review: 0.15.0 PolishThis PR contains several quality improvements across batch processing, group chat recovery, SSH handling, and modal state management. Overall, the changes are well-structured with good test coverage. Below are my findings organized by severity. ✅ Strengths
🔴 Critical Issues1. Regex Pattern Incomplete in validateAgentPromptHasTaskReferenceFile: src/renderer/hooks/batch/batchUtils.ts:54-69 The checkbox validation patterns do not match the actual checkbox formats used elsewhere in the codebase: Lines 59-60 use patterns like /- [ ]/ which require EXACTLY one space inside brackets, but lines 12, 15, 19 in the same file use [\s*] and [[xX✓✔]] allowing variable spacing. Users could write - [] or - [ ] (zero or multiple spaces) which would be incorrectly rejected. Impact: Valid prompts with slightly different spacing will be incorrectly rejected, blocking users from running batch operations. 2. Potential Race Condition in Modal StoreFile: src/renderer/stores/modalStore.ts:840-862 The rename setter pattern reads current state, then calls openModal. If setRenameTabId and setRenameTabInitialName are called in rapid succession (which the commit message documents as the expected call pattern: setId → setName → setModalOpen), there is a timing window where stale data could be used. Impact: Intermittent modal failures where fields appear empty despite being set.
|
Code Review for PR #324: 0.15.0 PolishSummaryThis PR introduces three main improvements:
Overall, this is a solid polish PR with good test coverage and thoughtful implementation. Below are detailed findings organized by category. ✅ Strengths1. Excellent Test Coverage
2. Well-Documented Code
3. Good User Experience
4. Defensive Programming
🔍 Issues & Concerns1. Potential Regex False Positives in Prompt Validation
|
| Priority | Issue | Action |
|---|---|---|
| High | InputArea performance (Bug #5) | Verify inputValue dependency is necessary; remove if redundant |
| Medium | Tab overlay inconsistency (Issue #4) | Clarify intended behavior for tabs with agentSessionId but no logs |
| Medium | Modal store complexity (Issue #2) | Document call sequence requirement; consider future refactor |
| Low | Regex false positives (Issue #1) | Add comment explaining lenient validation tradeoff |
| Low | Recovery name collision (Issue #3) | Add comment about unsupported "-recovery" suffix in participant names |
| Low | Changelog update (Issue #8) | Add release notes |
✅ Approval Recommendation
Approve with minor follow-up. This PR delivers valuable polish and has excellent test coverage. The issues identified are mostly minor (documentation, edge cases, potential future maintenance burden). The core functionality is solid.
Suggested follow-up:
- Address the InputArea performance question (Bug docs: enhance CLAUDE.md with work items and contribution workflow #5) - this is the only potential runtime issue
- Clarify tab overlay behavior (Issue Major Feature: Web Interface #4) to ensure consistency
- Add changelog entries
Great work on the test coverage and defensive programming! 🎉
Review conducted using repository CLAUDE.md conventions and architecture guidelines.
Pull Request Review: 0.15.0 PolishSummaryThis PR implements several important fixes and enhancements across batch processing, group chat recovery, SSH support, and modal interactions. The changes are well-tested with 117 new test cases and comprehensive coverage of edge cases. Strengths1. Excellent Test Coverage ✅
2. Strong Error Prevention ✅
3. Proper SSH Awareness ✅
4. Well-Documented Changes ✅
Issues & Recommendations1. Validation Regex Patterns May Be Too Permissive
|
78735be to
d4c1885
Compare
PR #324 Review - 0.15.0 PolishExecutive SummaryThis is a solid polish PR with three main improvements:
The PR demonstrates good engineering practices with comprehensive test coverage (+860 lines of tests). Most changes are well-structured, but there are several concerns that should be addressed. Critical Issues1. Regex Escaping Bug in Validation (MUST FIX)File: Problem: Square brackets are regex metacharacters for character classes. These patterns work accidentally but are incorrect. Current (incorrect): /- \[ \]/, // literal checkbox syntax
/- \[x\]/i, // checked checkbox syntaxFix: /-\s*\\\[\s*\\\]/, // escaped checkbox: - [ ]
/-\s*\\\[[xX]\\\]/i, // escaped checked: - [x]Impact: Current code works by luck but is fragile and could break with regex engine changes. 2. Validation Too Strict - False Negatives (SHOULD FIX)File: The validation rejects valid prompts like:
Recommendations:
3. Silent Error Suppression Risk (SHOULD FIX)File: Problem: If the exit-listener recovery mechanism fails or has bugs, the UI shows nothing to the user. This creates a silent failure mode. Recommendation: Add a fallback timeout to show an error if recovery does not complete within 30 seconds. High Priority Issues4. Infinite Loop Prevention is String-BasedFile: Problem: The check Better approach: Extract to a dedicated helper function in 5. Missing Null Safety in Group Chat RecoveryFile: Problem: If the group chat was deleted while a participant process was running, Fix: Add explicit null checks before proceeding with recovery. 6. SSH Check InconsistencyThe SSH detection logic differs between files:
Recommendation: Extract to a shared utility function and document the correct approach. Medium Priority Issues7. Code Duplication in SSH GuardsThe SSH history path guard is duplicated in two files. Extract to a shared utility function. 8. Modal Store Pattern InconsistencyFile: The 9. Missing Validation Test CasesThe test suite is comprehensive but missing edge cases:
Positive Observations
RecommendationREQUEST CHANGES - Fix the regex escaping bug before merge. Other issues are suggestions for improvement but not blockers. Priority Fixes:
Estimated Risk: Low-Medium (regex bug is technical debt, recovery edge cases could cause crashes) Test Coverage: Excellent (comprehensive unit + integration tests) Code Quality: High (well-structured, follows patterns) |
Code Review: PR #324 "0.15.0 polish"OverviewThis PR includes 33 files with +1132/-431 lines, focusing on:
Overall Assessment: ⭐⭐⭐⭐ (4/5) - APPROVE with suggestions ✅ StrengthsBatch Runner Validation
Group Chat Recovery
SSH History Guard
Debug Package
|
PR Review: 0.15.0 PolishThis is a solid polish PR with 1,439 additions and 516 deletions across 45 files. The changes focus on three main areas: auto-run validation, group chat recovery, and SSH/history improvements. Overall, the code quality is high with good test coverage. ✅ Strengths1. Excellent Test Coverage
2. Good Error Prevention
3. User Experience Improvements
4. Clean Architecture
🔍 Issues & Concerns1. Potential False Positives in Validation (Medium Priority)Location: The validation patterns might be too strict. Edge case: "Process all items in the checklist and mark them complete" would FAIL validation but could be valid. Recommendation: Consider adding a warning mode vs hard block, or add an "Advanced" toggle to bypass validation for power users. 2. Race Condition in Group Chat Recovery (Low-Medium Priority)Location: The recovery logic uses an async IIFE which means errors might not propagate properly. If two participants fail simultaneously, race conditions could occur. Recommendation: Consider using a recovery queue or mutex to serialize recovery attempts per group chat. 3. Magic String for Recovery Detection (Low Priority)Location: const isRecoverySession = sessionId.includes('-recovery-');This is fragile - if session ID format changes elsewhere, this breaks. Recommendation: Create a helper function 🔒 Security Review✅ No security concerns identified
🚀 Performance Considerations✅ No significant performance issues
📝 Code QualityPositive
Suggestions
Recommendations SummaryMust Fix Before MergeNone - no blocking issues identified. Should Fix Before Merge
Nice to Have (Future PRs)
Overall AssessmentVerdict: ✅ Approve with minor suggestions This PR demonstrates strong engineering practices:
The infinite loop prevention and validation features are well-designed. The suggested improvements are minor and can be addressed in follow-up PRs if needed. Great work on the polish! 🎉 |
- Add validateAgentPromptHasTaskReference() in batchUtils with regex heuristics (checks for "markdown task", "- [ ]", "checkbox", "unchecked task", etc.) - Disable Go button when prompt is empty or lacks task references - Show inline validation warnings below the prompt textarea - Fall back to DEFAULT_BATCH_PROMPT when loading a playbook with empty prompt - Move DEFAULT_BATCH_PROMPT to batchUtils to break circular dependency - Add 16 new test cases covering validation logic and UI behavior
- Add session recovery messaging and infinite-loop prevention for group
chat participant respawns (exit-listener, session-parser, types)
- Suppress session_not_found errors in group chat UI when recovery is
handling respawn (App.tsx)
- Skip local history file path for SSH remote sessions in both input
processing and inline wizard flows
- Add SSH caveat note to History Help modal
- Merge tabShortcuts into TourOverlay props so {{newTab}}, {{closeTab}},
{{reopenClosedTab}} render as keyboard badges instead of raw text
…uard Use sshRemoteId (string) instead of sshRemote (object) to match all other SSH checks in useInputProcessing.ts. Fix indentation of the SSH guard block to align with surrounding code at the correct nesting level.
…tore, history paste) Previously the resize effect only fired on tab switch, leaving the textarea at the wrong height when inputValue was set programmatically.
Remove the 40% context usage threshold for showing the reset button. The button is now always visible when a group chat context exists, which is useful for disconnected sessions and not just high context. Claude ID: 485578d0-0162-4286-acca-d7f4cbe8ae1d Maestro ID: be2891eb-de89-4c1d-90bb-0475a692e77b
…stall dirs) Users reported debug packages contained prompts, messages, agent installation paths, and directory listings. Centralizes sanitization into a shared sanitize.ts module and hardens all collectors: - Logs/errors: sanitize messages (path scrub + 500-char truncation), drop data field - Agents: remove binary paths, binaryName, customPaths map - Windows diagnostics: remove agent probing, where results, PATH dirs, file listings - External tools: remove shell paths and ghPath - Sessions: remove user-given session names - Group chats: remove chat names and participant names
Images were silently dropped when spawning agents over SSH. This adds two paths: stream-json agents (Claude Code) embed base64 images in the stdin JSON message, while file-based agents (Codex, OpenCode) decode images into remote temp files via heredoc + base64 in the SSH script. Includes regression tests for both paths and updates integration tests to use the production stdin passthrough approach. Claude ID: c6821a69-e903-416c-9af7-ec294c46604c Maestro ID: be2891eb-de89-4c1d-90bb-0475a692e77b
Filter out --dangerously-skip-permissions from agent args when spawning the tab naming process. This allows the agent to run with --permission-mode plan only, which doesn't acquire a workspace lock and can execute in parallel with other agent instances working in the same directory.
…opens
- StderrHandler: filter Codex Rust tracing lines (TRACE/DEBUG/INFO/WARN/ERROR)
from stderr instead of displaying as errors; re-emit remaining content as data
- ConfirmModal: make title, icon, destructive flag, and confirmLabel configurable
(was hardcoded to "Confirm Delete" with destructive styling)
- App/hooks: replace three-step confirm modal pattern (setMessage + setOnConfirm +
setOpen) with atomic openModal('confirm', data) to prevent race conditions
- AutoRunExpandedModal: add unsaved-changes confirmation on close/Escape
- DocumentsPanel: always show remove button (remove conditional invisible placeholder)
- Tests updated for StderrHandler tracing filter and ConfirmModal title change
Update sanitization test to import sanitizePath from the new collectors/sanitize module after it was extracted from settings.ts. Remove the unused "Quit & Delete Working Dirs" feature from QuitConfirmModal, including the agent name confirmation input and onConfirmQuitAndDelete prop threading through App and AppModals.
Error handlers in group chat, history, agent detector, and all session storage implementations were logging errors locally but never reporting to Sentry. Added captureException calls alongside existing logger calls so production crashes and failures are visible in Sentry dashboards.
f590a74 to
11d0c67
Compare
Pull Request Review: 0.15.0 PolishSummaryThis PR includes 11 commits addressing various polish items for the 0.15.0 release, including auto-run validation, group chat recovery, SSH improvements, debug package sanitization, Codex stderr filtering, and modal improvements. ✅ Strengths1. Excellent Test Coverage
2. Security & Privacy Improvements
3. SSH Remote Execution Robustness
4. Better Error Reporting
5. Code Quality Improvements
🔍 Issues & RecommendationsCritical Issues1. Regex Delimiter Collision Risk (
|
…tings The header context bar used hardcoded 60/80% thresholds while the bottom warning sash used configurable thresholds from settings, causing color mismatches (e.g., green bar at top but yellow warning at bottom).
Claude Code --print mode may not immediately exit on SIGINT alone, causing the Stop button to show "Canceled by user" while the process continues running. Now escalates to SIGTERM after 2s if needed.
Fixes the issue where group chat moderator responses containing markdown-style
bullet points (e.g., '- Run tests') would cause PowerShell to misinterpret lines
as code, resulting in exit code 1.
The problem occurred because:
- Moderator responses are passed as prompts to participant agents
- On Windows, these prompts are sent via stdin in raw mode
- PowerShell was interpreting lines starting with '-' as unary operators
- This caused syntax errors about missing expressions after operator
Solution:
- Added escapePowerShellPromptContent() function in shellEscape.ts
- This function prefixes lines starting with PowerShell operators with '# '
- Escaping is applied in ChildProcessSpawner.ts before stdin write
- Only applied on Windows with PowerShell (not cmd.exe or SSH remotes)
Changes:
- src/main/process-manager/utils/shellEscape.ts: Add escapePowerShellPromptContent()
- src/main/process-manager/spawners/ChildProcessSpawner.ts: Apply escaping before stdin write
- src/__tests__/main/process-manager/utils/shellEscape.test.ts: Add 25 test cases
The fix prevents operators that would cause PowerShell syntax errors:
-, @, $, +, &, |, <, >, (, ), [, ], {, }, !, %, ^, backtick, ;
This also resolves similar issues in regular chat on Windows when using PowerShell.
Fixes issues with shell selection and argument escaping on Windows for both group chat and normal chat modes: - Centralize Windows shell selection logic using getWindowsShellForAgentExecution() - Export shell escaping utilities from process-manager utils for reuse - Apply PowerShell shell configuration consistently to group chat agents - Fix group chat moderator and router to use proper shell handling on Windows - Ensure command-line argument escaping works correctly with PowerShell This fixes: - Group chat moderator responses with special characters causing exit code 1 - Normal chat on Windows with shell-based argument escaping - Inconsistent shell selection between chat modes
PowerShell treats stdin input as literal text, not executable code, so special characters like dashes don't need escaping. The previous escapePowerShellPromptContent() implementation incorrectly converted markdown lists to comments, breaking group chat moderator prompts. Fixes: - Messages starting with '-' no longer show CLI help text - Group chat moderator no longer hangs on startup - Markdown formatting preserved in agent prompts Tests: Updated all 54 shell escape tests to expect no escaping.
…oderator responses Three critical fixes for Windows PowerShell group chat: 1. Fix isStreamJsonMode condition (ChildProcessSpawner.ts) - sendPromptViaStdinRaw was incorrectly enabling JSON streaming mode - Raw text mode (sendPromptViaStdinRaw) should NOT trigger JSON parsing - This caused OpenCode to receive stream-JSON when expecting raw text - Result: "SyntaxError: Unexpected end of JSON input" failures - Now OpenCode receives raw text prompts correctly 2. Remove duplicate routeModeratorResponse calls (exit-listener.ts) - Catch block was calling routeModeratorResponse() as fallback on chat load failure - This caused the same moderator response to be routed twice - Result: Moderator would answer multiple times for a single user message - Now only routes response if chat loads successfully - If chat load fails, error is logged without attempting to route 3. Update test expectations (ChildProcessSpawner.test.ts) - Test was expecting raw text mode to set isStreamJsonMode=true - Changed to expect isStreamJsonMode=false for raw text mode - Added comments explaining the distinction between raw text and JSON modes Root causes identified: - Confusion between sendPromptViaStdinRaw (text) vs sendPromptViaStdin (JSON) - Error recovery code attempting fallback routing on legitimate errors Fixes: - ✅ Group chat participants no longer get JSON parse errors - ✅ Moderator now responds exactly once per message (no duplicates) - ✅ All process manager and group chat tests passing
The renderer was sending sendPromptViaStdin and sendPromptViaStdinRaw flags from inlineWizardConversation, but the IPC handler's config type definition didn't include these fields. This caused them to be lost when spreading ...config to the process manager. Fix: - Add sendPromptViaStdin field to IPC config type (for stream-json mode) - Add sendPromptViaStdinRaw field to IPC config type (for raw text mode) - Now these flags properly flow from renderer to process manager - Messages starting with '-' in regular chat will now be sent via stdin instead of as CLI args, preventing them from being interpreted as flags This fixes the issue where regular chat messages starting with '-' would cause 'claude-code' to display help instead of processing the message.
OpenCode doesn't support --input-format stream-json, so when sending prompts via stdin on Windows, it was receiving JSON-formatted messages it couldn't parse. This caused messages starting with "-" to be interpreted as CLI flags, showing help text instead of processing. Now the code distinguishes between: - sendPromptViaStdin: for stream-json agents (Claude Code, Codex) - sendPromptViaStdinRaw: for raw text agents (OpenCode, etc.) This ensures each agent receives prompts in the format it expects. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…agents Standard chat was passing prompts as CLI arguments on Windows, causing messages starting with "-" to be interpreted as CLI flags. This showed the agent's help text instead of processing the message. Now standard chat uses the same stdin approach as inline wizard: - sendPromptViaStdin for stream-json agents (Claude Code, Codex) - sendPromptViaStdinRaw for raw text agents (OpenCode, etc.) Also added the missing stdin fields to global.d.ts ProcessConfig. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added 6 new tests to verify the Windows stdin behavior: - sendPromptViaStdin is used for claude-code (stream-json agents) - sendPromptViaStdinRaw is used for opencode (non-stream-json agents) - Neither flag is used on non-Windows platforms - --input-format stream-json is added only for stream-json agents Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove no-op escapePowerShellPromptContent function and its 145 test cases - Replace hardcoded agent IDs with capabilities-based system (supportsStreamJsonInput) - Fix stdin mode selection: use sendPromptViaStdin for stream-json agents, sendPromptViaStdinRaw for others - Improve cmd.exe detection to check basename only (prevents false positives like commander\bash.exe) - Consolidate duplicate callback pattern into shared group-chat-config module - Add retry logic to exit listener with logging for transient I/O failures
… Windows shell config CRITICAL FIX: - Promote sendPromptViaStdinRaw to its own top-level branch in ChildProcessSpawner The raw stdin write was nested under isStreamJsonMode check, which is FALSE when sendPromptViaStdinRaw=true (since that flag is for non-stream-json agents). This caused prompts to be silently dropped for all non-stream-json agents (OpenCode, Gemini CLI, Qwen3 Coder) on Windows in group chat. HIGH PRIORITY: - Extract getWindowsSpawnConfig() helper to group-chat-config.ts Consolidates ~15 lines of duplicated shell config + stdin flag logic that was copy-pasted across 5 spawn locations in group-chat-router.ts and group-chat-agent.ts. - Fix inconsistent SSH exclusion in synthesis and recovery spawns Synthesis (~line 1230) and recovery (~line 1407) spawns were applying Windows shell config unconditionally, even when moderator runs on remote Linux host via SSH. Now properly checks sshRemoteConfig before applying. MEDIUM PRIORITY: - Fix early returns in spawnModeratorSynthesis leaving UI stuck Four early returns (chat not found, moderator not active, no session ID, agent not available) now properly emit 'idle' state change and remove power block reason. - Add PowerShell existence fallback to ComSpec getWindowsShellForAgentExecution now checks multiple PowerShell paths (PSHOME, System32, PowerShell Core) and falls back to ComSpec (cmd.exe) as last resort with warning. Handles rare Windows Server Core scenarios. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests cover: - Stream-json vs non-stream-json agent detection - SSH exclusion (Windows config NOT applied when SSH is enabled) - Platform detection (Windows vs Linux/macOS) - Custom shell path callback integration - Agent capability detection for stdin mode selection These tests ensure the consolidated Windows spawn config helper works correctly, especially the critical SSH exclusion logic that prevents applying Windows-specific settings when running on remote Linux hosts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR #324 Review: 0.15.0 PolishSummaryThis is a well-executed polish release with 74 files changed (+2,678/-731 lines) that introduces important security hardening, reliability improvements, and UX enhancements. The changes are thoroughly tested with excellent coverage for critical security-sensitive code. Key Features Reviewed1. ✅ Auto-Run Prompt ValidationFiles: Validates that agent prompts contain Markdown task references before allowing Auto-Run execution. Uses 8 regex patterns to detect task-related syntax ( Verdict: Clean implementation with appropriate error messaging. No issues found. 2. ✅ Group Chat Session RecoveryFiles: Automatically detects when a participant's agent session expires and creates a new session with recovery context from chat history. Prevents infinite loops with Strengths:
Minor Concern: Lines 260-320 in Verdict: Solid implementation, no blocking issues. 3.
|
The test set PSHOME but fs.existsSync returned false on macOS, causing fallthrough to the bare powershell.exe fallback.
PR #324 Review: 0.15.0 Polish ReleaseExecutive SummaryThis is a substantial polish release with 2,683 additions and 732 deletions across 74 files. The changes focus on critical bug fixes, SSH remote execution improvements, Windows PowerShell compatibility, error handling enhancements, and debug package sanitization. Overall code quality is high with good test coverage, but I've identified several areas requiring attention before merge. 🔴 Critical Issues1. Debug Package API Key Sanitization (SECURITY)Location: Issue: The Fix needed: export function sanitizeLogMessage(message: string): string {
let sanitized = sanitizeText(message);
// Redact sensitive patterns BEFORE truncating
sanitized = sanitized
.replace(/sk-[a-zA-Z0-9]{32,}/g, 'sk-***REDACTED***') // Anthropic API keys
.replace(/Bearer [a-zA-Z0-9_\-\.]+/g, 'Bearer ***') // Bearer tokens
.replace(/Authorization:.*$/gm, 'Authorization: ***'); // Auth headers
if (sanitized.length > 500) {
sanitized = sanitized.slice(0, 500) + ' [TRUNCATED]';
}
return sanitized;
}Risk: Medium - User API keys could leak in debug packages. 2. Agent Prompt Validation Too BroadLocation: Issue: The
Recommendation: // Add more specific instruction patterns:
/mark.*task.*complete/i, // "mark tasks as complete"
/check.*off.*task/i, // "check off completed tasks"
/update.*\[x\]/i, // "update checkboxes to [x]"Risk: Medium - Could block valid prompts or allow non-functional ones. 3. SSH History Write Error HandlingLocation: Question: Does Verification needed: try {
await writeHistoryFile(...);
} catch (error) {
await captureException(error, { operation: 'history:write', sessionId });
// Don't throw - history write failure shouldn't break session
}Risk: Medium - SSH disconnects could crash main process if not caught. 🟡 Moderate Issues4. Process Termination Timer LeakLocation: Issue: Escalation timer could leak if Fix: // Store timer reference in process object
if (!process.escalationTimer) {
process.escalationTimer = escalationTimer;
}
// Clean up in kill() method
if (process.escalationTimer) {
clearTimeout(process.escalationTimer);
delete process.escalationTimer;
}Risk: Low - No functional impact, but wastes resources. 5. Group Chat Recovery UX GapLocation: Good: Infinite loop prevention is excellent! Gap: If recovery spawn itself fails with Recommendation: groupChatEmitters.emitMessage?.(groupChatId, {
timestamp: new Date().toISOString(),
from: 'system',
content: `⚠️ ${participantName} session could not be recovered. Please remove and re-add the participant.`
});Risk: Low - Edge case, but poor UX. 6. SSH Heredoc Delimiter Collision (Theoretical)Location: Issue: Heredoc delimiter Probability: Extremely low, but not zero. Bulletproof fix: const delimiter = `MAESTRO_IMG_${i}_${Date.now()}_EOF`;Risk: Very Low - Practically impossible, but trivial to prevent. ✅ Major Strengths1. Excellent Test Coverage
2. Proper Sentry IntegrationMultiple files now correctly use } catch (error) {
logger.error(...);
captureException(error, { operation: '...', ... });
}This follows CLAUDE.md guidelines perfectly! ✅ 3. SSH Remote Execution AwarenessGroup chat router correctly applies 4. Windows Shell Selection Priority
This directly addresses the "Die Befehlszeile ist zu lang" error. Excellent! 5. Performance OptimizationFast path in const isGroupChatSession = sessionId.startsWith(GROUP_CHAT_PREFIX);Avoids expensive regex for 99% of sessions. Smart! 🚀 📋 Testing Gaps1. Missing: Agent Prompt Validation Tests
Needed: it('should accept prompt with markdown task instruction');
it('should reject prompt without task reference');
it('should handle checkbox syntax variations');2. Missing: Session Recovery Infinite Loop TestThe guard at it('should not attempt recovery for recovery sessions');3. Missing: Process Escalation Timer Testit('should escalate to SIGTERM if SIGINT does not terminate process');🔒 Security Assessment✅ Shell Escaping: Both cmd.exe and PowerShell escaping follow best practices. Comprehensive test coverage. ✅ SSH Command Injection: stdin passthrough approach eliminates shell parsing entirely. Gold standard! ✅ Path Sanitization: Properly replaces home directory with 📝 Code Style Compliance✅ Tabs for indentation
🎯 RecommendationsHigh Priority (Before Merge)
Medium Priority (Can address in follow-up)
Low Priority (Nice to have)
📊 Final VerdictStatus: ✅ Approve with Minor Changes This is high-quality work that addresses real production issues. The SSH improvements, Windows compatibility fixes, and error handling enhancements are excellent. However, the debug package API key sanitization (Critical Issue #1) should be addressed before merge as it's a potential security issue. The other issues are lower risk and can be handled in follow-up PRs. Metrics
Key Achievements✨ Comprehensive SSH remote execution support Great work on this release! The codebase is measurably more robust after these changes. 🎉 |