feat: Ralph idle-watch mode — auto-poll for new work after board clears#28
Merged
bradygaster merged 1 commit intobradygaster:mainfrom Feb 13, 2026
Merged
Conversation
When Ralph clears the board, instead of fully stopping he now enters idle-watch mode: automatically re-checking for new work every N minutes (default: 10). The polling interval is configurable via natural language (e.g., 'Ralph, check every 30 minutes'). - Add idle-watch polling behavior to Ralph's state machine - Add 'Ralph, check every N minutes' trigger command - Update Ralph state: active/idle/watching + poll_interval - Distinguish idle-watch (automatic on board clear) from full idle (explicit 'Ralph, idle' / 'stop') - Update docs/features/ralph.md with idle-watch documentation
tamirdresher
added a commit
to tamirdresher/squad
that referenced
this pull request
Mar 2, 2026
P0 fixes: - #2: EISDIR crash — directory check before createReadStream in static handler - bradygaster#8: Unhandled createReadStream errors — add stream error handler - bradygaster#18: decodeURIComponent crash on malformed URLs — wrap in try/catch P1 fixes: - bradygaster#10: Session TTL bypass — enforce periodically via setInterval - bradygaster#14: Audit log writes cleartext — apply redactSecrets to pty_input data - bradygaster#16: Dashboard XSS — replace inline onclick with data attributes + addEventListener - bradygaster#17: Add Referrer-Policy: no-referrer and Cache-Control: no-store headers - bradygaster#21: Audit log write stream error handler - bradygaster#24: Audit dir permissions 0o700 - bradygaster#28: Origin substring bypass — use URL parsing instead of .includes() - bradygaster#30: Ticket GC — clean expired tickets every 30s Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster
added a commit
that referenced
this pull request
Mar 4, 2026
…547) * feat: migrate SDK + CLI source files into workspace packages Phase 1 (SDK): - Copy 15 directories + 4 standalone files from src/ into packages/squad-sdk/src/ - Remove CLI re-exports from SDK barrel (src/index.ts) - Update SDK package.json exports map with all subpath exports Phase 2 (CLI): - Copy src/cli/ and src/cli-entry.ts into packages/squad-cli/src/ - Copy templates/ into packages/squad-cli/templates/ - Rewrite 6 cross-package imports to use @bradygaster/squad-sdk/* package imports - Intra-CLI imports left as relative paths Root src/ preserved for now (cleanup after tests pass). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: complete SDK/CLI workspace migration and publish to npm - Updated tsconfigs with composite builds and project references - Fixed package.json exports maps, dependencies, and build scripts - Aligned versions to 0.8.0 (clean break from 0.7.0 stubs) - Root package now private workspace orchestrator - SDK: 306 files, 18 subpath exports, pure library - CLI: 204 files, ink/react UI, templates included - Both packages published to npm as @bradygaster/squad-sdk@0.8.0 and @bradygaster/squad-cli@0.8.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(ai-team): sdk-cli-split execution, version alignment, test verification Session: 2026-02-22T041800Z-npm-publish-migration Orchestration: Keaton (sync), Fenster (sync), Edie (background), Rabin (background), Kobayashi (background), Hockney (background), Coordinator (background) Changes: - Logged 7 orchestration entries (.squad/orchestration-log/) and session summary (.squad/log/) - Merged 8 decision inbox files to .squad/decisions.md (keaton-sdk-cli-split-plan, kobayashi-version-alignment, hockney-test-import-migration, edie-build-system-migration, edie-subpath-exports, kujan-barrel-files, copilot-directive repo scope) - Cleared .squad/decisions/inbox/ (all 8 files merged) - Updated 5 agent histories with team updates (keaton, fenster, edie, rabin, kobayashi, hockney) - Verified: Build clean, 1719 tests passing, SDK/CLI split complete, versions aligned to 0.8.0, packages published to npm Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: clean up stale root artifacts - Removed 13 orphaned .test-cli-* temporary directories from pre-migration era - Removed stale root dist/ directory (each package has its own dist/) - .test-cli-* and dist/ already in .gitignore, no changes needed there - Verified build succeeds after cleanup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add coverage config and package exports integration test - Configure @vitest/coverage-v8 with text, text-summary, and html reporters - Add coverage include/exclude patterns for src and packages - Create package-exports.test.ts verifying SDK exports map (8 subpaths) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: migrate test imports to workspace packages Migrate all 56 test files from relative ../src/ imports to workspace package imports (@bradygaster/squad-sdk and @bradygaster/squad-cli). SDK imports use subpath exports (e.g., @bradygaster/squad-sdk/config, @bradygaster/squad-sdk/agents, @bradygaster/squad-sdk/runtime). CLI imports use @bradygaster/squad-cli subpath exports for shell, core, and command modules. Changes: - 173 import path replacements across 56 test files - Added 8 new SDK subpath exports (adapter/errors, config/migrations, runtime/event-bus, runtime/benchmarks, runtime/i18n, runtime/telemetry, runtime/offline, runtime/cost-tracker) - Added 16 CLI subpath exports for shell, core, and command modules - Added missing barrel re-exports: selectResponseTier/getTier in coordinator/index.ts, onboardAgent/addAgentToConfig in agents/index.ts - Updated consumer-imports test to import CLI functions from @bradygaster/squad-cli instead of SDK barrel - All 1727 tests pass across 57 test files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * main to dev (#299) * test artifact (#183) * Bradygaster/dev (#184) * test artifact * fixed readme * chore: remove squad-main-guard workflow The .squad folder is already excluded from npm distribution via the files field in workspace package.json configs. The guard that prevented .squad/ from reaching protected branches is no longer needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add Squad Remote Control — bridge, CLI command, and PWA client Phase 1 MVP implementation: - RemoteBridge class (SDK): WebSocket server, EventBus integration, message history buffer, streaming delta broadcast - Wire protocol: 15 message types (server events + client commands), JSON-based, versioned - squad rc CLI command: starts bridge, creates devtunnel with squad labels, shows QR code for phone access - PWA client: chat UI with streaming, agent sidebar, tool call visibility, permission dialogs, dark theme, mobile-optimized - Devtunnel helper: create/host/cleanup lifecycle with labels for discovery (repo, branch, machine hostname) New files: 11 | Modified: 4 | Zero breaking changes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use http protocol for devtunnel port (bridge is plain HTTP, tunnel handles TLS) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: wire Phase 2 — agent roster, streaming responses, /commands, @agent routing - Load team.md roster on startup (8 Star Trek agents loaded) - onPrompt routes to lead agent with simulated streaming response - onDirectMessage routes to specific @agent (e.g. @Worf) - /status and /agents slash commands return live session info - Agent status updates (idle→streaming→idle) broadcast to PWA - Full conversation history maintained and synced to new clients Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove manifest.json link causing blank screen on mobile via devtunnel Devtunnel's auth interceptor redirects manifest.json requests, causing mobile browsers to show a blank page. Also added: - Visible 'Connecting...' system message on startup - Exponential backoff reconnection (1s → 30s max) - Better error display in chat area Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add Copilot ACP bridge with version compatibility check - CopilotBridge spawns copilot --acp --stdio and relays JSON-RPC - Static checkCompatibility() method tests if copilot responds to initialize request before attempting connection - Graceful fallback to simulated responses when ACP isn't available - Current Copilot CLI v0.0.419 doesn't support ACP stdio yet Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: switch to dumb pipe architecture for Copilot ACP Bridge now transparently relays WebSocket ↔ copilot stdin/stdout. The ACP protocol (initialize, session/new, session/prompt) is driven by the PWA client, not the server — matching Uplink's architecture. Added setPassthrough() and passthroughFromAgent() to RemoteBridge. When passthrough is active, raw JSON-RPC flows through untouched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: rewrite PWA to speak ACP protocol directly PWA now drives the ACP lifecycle over WebSocket: - Sends initialize → session/new → session/prompt (JSON-RPC 2.0) - Handles session/update notifications for streaming chunks - Handles session/request_permission for tool approvals - Bridge is transparent dumb pipe (WebSocket ↔ copilot stdio) Note: copilot --acp --stdio on v0.0.419 doesn't respond to initialize. Architecture is correct (matches Uplink) but blocked on Copilot CLI version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: real Copilot responses working! Fix ACP startup + cwd injection Key fixes: - Use native copilot.exe path for reliable stdio on Windows - Bridge intercepts session/new to inject correct cwd (PWA doesn't know server filesystem paths) - PWA retries initialize 5x with 5s delays (Copilot needs ~20s to load MCP servers before responding) - Increased timeouts: 60s for initialize, 120s for prompts Tested: real Copilot response received through dumb pipe relay! Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: terminal-style UI + ACP event recording for history replay Major rewrite: - Raw terminal renderer (monospace, dark bg, green prompt, blinking cursor) - Tool calls as collapsible cards with icons (📖read, ✏️edit,▶️ shell, 🔍search) - Diff rendering (red/green) for file edits - Streaming text with live cursor animation - Bridge records all ACP events and replays to late-joining clients - Permission dialogs as overlay modals - User input echoed with ❯ prompt (CLI-style) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: permission dialog overflow — truncate raw JSON, add scroll limits Permission dialogs now show clean title + first line of command instead of raw JSON blob. Added max-height with scroll to prevent blocking the entire viewport on mobile. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: permission dialog pinned to bottom, max 40vh, buttons always visible Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: session dashboard — list all running Squad RC sessions - Bridge serves /api/sessions endpoint (runs devtunnel list --labels squad) - PWA shows dashboard with session cards: repo, branch, machine, online status - Tap a session card → navigates to that session's tunnel URL - Toggle between Dashboard and Terminal views via header button - Sessions from any machine show up (devtunnel scoped to user identity) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: session dashboard with filter + cleanup - By default only shows online sessions - 'Show offline' toggle reveals stale sessions - 'Clean offline' bulk-deletes all stale tunnels - Individual ✕ button to delete single offline sessions - Refresh button to reload session list - Delete API: /api/sessions/:id (DELETE) - Fixed devtunnel delete flag (--force not -y) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: squad start — local CLI + remote mirror (bidirectional) New command: squad start [--tunnel] [--port <n>] - Spawns copilot --acp with full capabilities (/plugin, /skills, /agent etc.) - Local readline with green ❯ prompt — type in terminal as usual - Renders streaming responses, tool calls, permissions in terminal - Remote bridge mirrors ALL output to phone via tunnel - Phone can send messages INTO the same session (bidirectional) - Auto-approves permissions in terminal mode - Initializes ACP with retry (waits for MCP servers) Usage: squad start --tunnel # start with remote access squad start # local only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: PTY mirror mode — see exact Copilot CLI output remotely Rewrote squad start to use node-pty instead of ACP mode: - Copilot runs in a PTY with full TUI (diffs, colors, progress bars) - Raw terminal output mirrored to phone via WebSocket - ANSI escape codes converted to HTML colors on phone - Bidirectional: phone input injected as PTY keystrokes - Local terminal shows exact same output as running copilot directly - stdin in raw mode for full terminal experience (Ctrl+C, arrows, etc.) All copilot features work: /plugin, /skills, /agent, interactive prompts, file edits with diffs — the real deal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: xterm.js integration — real terminal emulator on phone Replace DIV-based ANSI renderer with xterm.js — a full terminal emulator running in the browser. Renders ALL ANSI escape codes correctly: colors, cursor movement, screen clearing, box drawing. The phone shows the EXACT same output as the CLI terminal. Keyboard input from xterm.js goes directly to the PTY. Loaded from CDN: @xterm/xterm@5.5.0 + @xterm/addon-fit@0.10.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: sync PTY terminal size with phone's xterm.js dimensions When phone connects, xterm.js sends its cols/rows to the bridge, which resizes the PTY. This fixes spinner animations appearing as new lines instead of overwriting — copilot now knows the correct terminal dimensions for cursor positioning. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: include port in tunnel labels so dashboard generates correct URLs Each tunnel now gets a 'port-NNNN' label. The sessions API reads it back to construct the correct URL (e.g., port-3457 → -3457 in URL). Fixes session 2 showing unreachable URL when using different port. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: pass copilot flags through squad start squad start --tunnel --yolo → copilot --yolo squad start --tunnel --model gpt-5.2 → copilot --model gpt-5.2 All flags after squad's own (--tunnel, --port) pass to copilot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: mobile key bar + --command flag for custom CLI Mobile: added toolbar with ↑↓→← Tab Enter Esc Ctrl+C Space ⌫ buttons above the input for navigating copilot menus on phone. Custom CLI: --command flag to use a different binary: squad start --tunnel --command 'agency copilot' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add start command to help, remove rc, add 18 tests - Added 'start' to squad --help with usage examples - Removed 'rc' command (superseded by 'start' with PTY mode) - Added 18 tests covering: - Protocol serialization/parsing (5 tests) - Bridge lifecycle, WebSocket, broadcasting (4 tests) - Message history + cap (2 tests) - Streaming deltas, agent roster (2 tests) - Passthrough mode, event recording/replay (2 tests) - Ping/pong, HTTP serving, cwd injection (3 tests) All 18 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: sanitize dots in tunnel labels (devtunnel only allows [\w-=]) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: escape hyphen in label regex character class Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: keep key bar visible in PTY mode — only hide text input form Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: apply security audit fixes to remote control bridge CRITICAL-1: OS Command Injection - Replace execSync with execFileSync array syntax in handleDeleteSession, add regex validation for tunnel IDs HIGH-1: CDN without SRI - Add integrity/crossorigin attributes to all CDN script/link tags (xterm CSS, xterm JS, addon-fit JS) HIGH-2: CORS wildcard - Remove Access-Control-Allow-Origin: * from handleSessionsAPI and handleDeleteSession response headers HIGH-7: Path traversal - Add decodeURIComponent, reject '..' in URLs, use path.resolve in static file handler HIGH-8: Rate limiting - Add per-connection WebSocket message rate limit (100 msg/sec, disconnect with 1008 if exceeded) MEDIUM-2: Unbounded WS - Add maxPayload: 1048576 to WebSocketServer MEDIUM-3: XSS - Add single quote escaping to escapeHtml function MEDIUM-4: PTY resize - Clamp cols [1,500] and rows [1,200] on pty_resize messages MEDIUM-5: Security headers - Add CSP, X-Frame-Options, and X-Content-Type-Options to all HTTP responses LOW-1: Reconnection - Replace fixed 3s reconnect delay with exponential backoff (1s initial, 30s max, reset on connect) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * security: apply 5 remaining security fixes CRITICAL-2: WebSocket authentication token (crypto.randomUUID, verified on connect) CRITICAL-4: PTY input audit logging to temp file CRITICAL-5: ACP JSON-RPC method allowlist for passthrough mode HIGH-3: Redact secrets from replay events before sending to late-joining clients HIGH-5: Filter sensitive environment variables from PTY spawn Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: update tests to use WebSocket auth token Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address P0/P1/P2 security findings from red team audit - F-01: Add session token auth check on all /api/* routes - F-03: Fix redactSecrets regex that preserved matched secrets via \$& backreference - F-04: Bind HTTP server to 127.0.0.1 instead of 0.0.0.0 - F-05: Add WebSocket Origin header validation in verifyClient - F-07: Expand env var sensitive patterns filter (auth, bearer, db, cert, signing) - F-08: Log and limit non-JSON raw PTY input in catch blocks - F-09: Replace all execSync template-literal devtunnel calls with execFileSync - F-10: Add max 5 WebSocket connections cap - F-14/F-15: Fix XSS in dashboard error and permission dialog (escapeHtml, remove inline onclick) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: apply 5 security hardening fixes to remote control bridge 1. Enhanced redaction: expand redactSecrets with OpenAI sk-, GitHub ghp_, AWS AKIA, Azure connection strings, database URLs, Bearer tokens 2. Audit log location: move from tmpdir to ~/.cli-tunnel/audit/ with JSONL format 3. Replay opt-in: add enableReplay config option, disable replay by default 4. CSP tighten: restrict connect-src to ws://localhost:* wss://*.devtunnels.ms 5. XSS: verified app.js already escapes err.message and msg.id via escapeHtml() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * security: implement F-02 ticket auth, F-07 env allowlist, F-18 session expiry F-02: Token out of URL — one-time ticket-based WebSocket auth. POST /api/auth/ticket exchanges session token for single-use 60s ticket. verifyClient accepts both ticket (preferred) and token (backward compat). PWA connect() uses ticket flow with token fallback. F-07: Env var allowlist — replace denylist pattern filter with explicit SAFE_ENV_VARS allowlist for PTY environment. F-13: No code change needed — SRI hashes on CDN scripts already protect against CDN compromise. F-18: Session TTL — 24-hour session expiry enforced in verifyClient and HTTP handler. Session expiry time printed on startup. Added getSessionExpiry() to RemoteBridge. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: apply P0+P1 security audit findings for remote-control P0 fixes: - #2: EISDIR crash — directory check before createReadStream in static handler - #8: Unhandled createReadStream errors — add stream error handler - #18: decodeURIComponent crash on malformed URLs — wrap in try/catch P1 fixes: - #10: Session TTL bypass — enforce periodically via setInterval - #14: Audit log writes cleartext — apply redactSecrets to pty_input data - #16: Dashboard XSS — replace inline onclick with data attributes + addEventListener - #17: Add Referrer-Policy: no-referrer and Cache-Control: no-store headers - #21: Audit log write stream error handler - #24: Audit dir permissions 0o700 - #28: Origin substring bypass — use URL parsing instead of .includes() - #30: Ticket GC — clean expired tickets every 30s Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: add EISDIR, NaN, stream error, non-JSON PTY, and decodeURI guards - #2: Add statSync directory check before createReadStream in start.ts - #7: Add Number.isFinite guard for pty_resize cols/rows in start.ts - #8: Add error handler on createReadStream stream in start.ts - #3: Remove raw non-JSON PTY write in bridge.ts and start.ts catch blocks - #18: Wrap decodeURIComponent in try/catch in start.ts static handler Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * security: backport 10 security fixes from cli-tunnel Backported from cli-tunnel v1.2.0-beta.12 security audits: 1. HSTS header added to all responses 2. Session TTL reduced from 24h to 4h 3. Secret redaction extended (JWT, Slack, npm, PEM patterns) 4. Per-IP WS connection limit (2 per IP) 5. WS ping/pong heartbeat (30s interval) 6. Env var filtering: allowlist → blocklist approach 7. CSP: removed unsafe-inline from script-src 8. escapeHtml: added double-quote escaping (XSS fix) 9. Origin validation moved before ticket check 10. HTTP rate limiting (30 req/min per IP, 429 response) All 18 remote-control tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: enhanced redaction + heartbeat backport from cli-tunnel Cherry-picked from cli-tunnel PR #15: - stripInvisible(): ANSI escape bypass protection - NFKC normalization before redaction - 6 new token patterns (GitLab, Vault, GitHub PAT, Databricks, HuggingFace, credential-in-URL) - Heartbeat interval 30s → 120s (prevents phone disconnect in background) 18/18 remote-control tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: add 74 comprehensive tests for remote control feature Coverage added for: - Security: auth (token/ticket), rate limiting (HTTP 429), connection limits (5 global, 2/IP), origin validation, ACP method allowlist, session expiry - Secret redaction: 18 patterns tested via replay (OpenAI, GitHub, AWS, Azure, DB URLs, JWT, Slack, npm, GitLab, Vault, Databricks, HuggingFace, PEM, credentials-in-URL, generic key=value) - ANSI/invisible char stripping: ESC CSI, C1 codes, zero-width chars, braille blank - Client commands: prompt, direct, slash command, permission response callbacks - Static file serving: security headers, path traversal, MIME types - Tunnel utilities: getMachineId, getGitInfo, isDevtunnelAvailable - Protocol edge cases: empty input, ping, permission_response, extra fields - Error handling: double start, stopped bridge ops, sendError, sendToolCall, sendPermissionRequest, sendUsage, updateAgentStatus - Replay buffer: enable/disable toggle, 2000-event cap Total: 92 tests (18 existing + 74 new), all passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: 404 on phone — strip query params from static file URL + PTY-only client - Static handler now uses URL.pathname instead of raw req.url, so ?token=xxx no longer becomes part of the file path (caused 404) - Fixed in both start.ts and rc.ts static handlers - Enabled replay buffer (enableReplay: true) so late-joining phones get terminal history instead of a blank screen - Removed ACP protocol code from client — PTY terminal only - Stripped ~270 lines of unused ACP code (sendRequest, initializeACP, streaming, tool calls, permission dialog, formatText) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: bradygaster <bradyg@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Brady Gaster <41929050+bradygaster@users.noreply.github.com>
williamhallatt
added a commit
to williamhallatt/squad
that referenced
this pull request
Mar 16, 2026
…er#341) Add 39 tests covering 5 SDK features that were previously untested: - bradygaster#27 Manual Ceremonies: trigger types, schedule, hooks, defineSquad composition - bradygaster#28 Ceremony Cooldown: schedule-gated cadence, multi-ceremony schedules - bradygaster#36 Human Team Members: agent status lifecycle (active/inactive/retired) - bradygaster#49 Constraint Budget: ask_user rate limiter, file-write path guards, shell command restrictions, combined constraints, defineHooks builder - bradygaster#50 Multi-Agent Artifact: per-artifact lockout, handoff, HookPipeline integration All tests exercise real SDK implementations (builders, HookPipeline, ReviewerLockoutHook) — no stubs.
This was referenced Mar 16, 2026
bradygaster
pushed a commit
that referenced
this pull request
Mar 16, 2026
joniba
pushed a commit
to joniba/squad
that referenced
this pull request
Mar 26, 2026
This comprehensive research document covers: - .NET Aspire architecture and why it's transformational for AI-assisted development - MCP integration patterns for system-wide agent visibility - Port isolation problem (blocker for parallel worktrees) and Tamir Dresher's solution - Four strategies for port isolation with trade-off analysis - Distributed tracing (OpenTelemetry) and health checks patterns - Squad infrastructure integration recommendations - Production readiness assessment for ms-pa - References to Tamir Dresher's blog posts, code samples, and official documentation Key finding: Adopt Aspire + MCP for Squad observability, implementing dynamic port allocation + MCP proxy pattern. This enables true parallel multi-agent development with system-wide visibility into distributed tracing, logs, and health checks. Research validates Issue bradygaster#28 acceptance criteria: 1. Aspire capabilities for AppHost orchestration ✅ 2. MCP integration for observability ✅ 3. Port isolation solution (3+ strategies documented) ✅ 4. Distributed tracing approach (OpenTelemetry built-in) ✅ 5. Squad infrastructure integration recommendations ✅ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When Ralph is active in a Copilot CLI session and clears the board, he previously entered a full idle state — meaning the user had to manually say "Ralph, go" again when new work appeared. This PR adds idle-watch mode: when the board clears, Ralph automatically re-checks for new work on a configurable timer instead of fully stopping.
Problem
Ralph's work loop was one-shot: scan → work → scan → board clear → stop. If new issues were filed while Ralph was idle, nobody noticed until the user manually triggered another scan. This created a gap between "the board is clear" and "new work arrives" where the team sat idle unnecessarily.
Solution: Idle-Watch Mode
When Ralph clears the board, he now enters idle-watch instead of full idle:
Configurable Interval
The default poll interval is 10 minutes, configurable via natural language:
Ralph, check every 5 minutesRalph, check every 30 minutesRalph, poll every 15 minutesThe interval can be set at any time — during active mode, idle-watch, or before activation.
Idle-Watch vs. Full Idle
Changes
.github/agents/squad.agent.mdRalph, check every N minutesto intent router and triggers tablepoll_intervaland three-state model (active/idle/watching)docs/features/ralph.mdRalph, check every N minutesto Talking to Ralph tableTesting
This is a behavioral spec change (agent markdown) — no code logic to unit test. The changes are validated by reviewing the spec for consistency across all Ralph references in both files.