Skip to content

feat: GitHub Issues intake, PRD mode, and human team members#2

Closed
spboyer wants to merge 1 commit intobradygaster:mainfrom
spboyer:feature/issues-prd-humans
Closed

feat: GitHub Issues intake, PRD mode, and human team members#2
spboyer wants to merge 1 commit intobradygaster:mainfrom
spboyer:feature/issues-prd-humans

Conversation

@spboyer
Copy link
Copy Markdown
Contributor

@spboyer spboyer commented Feb 8, 2026

Summary

Three new capabilities added to the Squad coordinator prompt (squad.agent.md), plus 27 validation tests.

1. 🐙 GitHub Issues Mode

Connect Squad to a GitHub repo's issues and manage the full lifecycle:

  • Connect: User says "pull issues from owner/repo" → Squad lists open issues as a backlog table
  • Filter: Optional label/milestone filtering
  • Route: User picks issues → coordinator routes to agents based on routing.md
  • Branch: Agents create squad/{issue-number}-{slug} feature branches
  • PR: Agents open PRs with Closes #{issue-number} linking
  • Review: User says "there's feedback on PR #X" → coordinator spawns agent to address comments
  • Merge: User says "merge PR #X" → gh pr merge --squash --delete-branch, auto-closes linked issue

Issue source is stored in team.md under a new ## Issue Source section.

2. 📄 PRD Mode

Ingest a Product Requirements Document and use it to drive the team's work:

  • File path: "read the PRD at docs/prd.md" → reads and processes
  • Inline: User pastes spec content directly in chat
  • Decomposition: Lead agent (sync) breaks PRD into prioritized work items (WI-1, WI-2, etc.) with size estimates, agent assignments, and dependencies
  • Approval gate: Work items presented to user before routing begins
  • Mid-project updates: "the PRD changed" → Lead diffs old vs new decomposition, surfaces added/modified/removed items

PRD reference stored in team.md under a new ## PRD section.

3. 👤 Human Team Members

Humans can join the Squad roster alongside AI agents:

  • Add: "add Brady as PM" or "I'm on the team as designer"
  • Roster: Humans get a 👤 Human badge (vs ✅ Active for AI agents)
  • No casting: Humans use their real names — not drawn from fictional universes
  • No charter: Humans don't have charter.md or history.md files
  • Routing: When work routes to a human, coordinator pauses: "This one's for {Name} — {what's needed}. Let me know when it's done."
  • Blocked tracking: Coordinator tracks items waiting on humans, sends stale reminders
  • Multiple humans: Fully supported (e.g., Brady as PM, Sarah as Designer)

4. 🔧 Init Mode Updates

Init Mode (step 3) now asks three new questions after "What are you building?":

  • "Do you have a PRD or spec document?"
  • "Is there a GitHub repo with issues I should pull from?"
  • "Are any humans joining the team?"

All are optional/skippable. Post-setup wiring (step 9) automatically runs the relevant intake flows.

5. 🗺️ Routing Table

Three new routing signals added to the Team Mode routing table for issues, PRD, and human member management.


Files Changed

File Change
.github/agents/squad.agent.md +316 lines — three new sections, Init Mode updates, routing table entries
test/index.test.js +128 lines — 27 new prompt validation tests

How to Test

Automated tests (prompt validation)

# All 55 tests should pass (28 existing + 27 new)
node --test test/*.test.js

The 27 new tests validate that squad.agent.md contains all expected sections, trigger phrases, formats, and routing entries. They catch regressions if sections are accidentally removed during upgrades.

Manual smoke test — GitHub Issues Mode

# 1. Create a test project
mkdir /tmp/squad-issues-test && cd /tmp/squad-issues-test && git init

# 2. Install squad (from this branch)
npx github:spboyer/squad#feature/issues-prd-humans

# 3. Open Copilot, select Squad agent
copilot

# 4. Try these prompts:
#    "I'm building a Node.js API"              → normal init
#    "Pull issues from owner/repo"               → should list open issues
#    "Work on issue #1"                           → should route to agent, create branch, open PR
#    "There's feedback on PR #2"               → should spawn agent for review comments
#    "Merge PR #2"                                → should merge and close linked issue
#    "Show the backlog"                           → should re-list open issues

Manual smoke test — PRD Mode

# In same or new test project with Squad initialized:

# Option A: File path
#    Create a docs/prd.md with requirements, then:
#    "Read the PRD at docs/prd.md"
#    → Lead should decompose into work items table
#    → Should ask for approval before routing

# Option B: Inline
#    Paste requirements text, then say "here's the PRD"
#    → Same decomposition flow

Manual smoke test — Human Team Members

# In a Squad-initialized project:
#    "Add Brady as PM"                            → should add to roster with 👤 badge
#    "Sarah is our designer"                      → should add second human
#    Route work that matches a human's domain   → should pause, not spawn
#    "Brady approved" or "Brady is done"          → should unblock waiting items

Manual smoke test — Init Mode

# Fresh project, run Squad init:
#    After "What are you building?" answer, Squad should ask about:
#    1. PRD or spec document
#    2. GitHub repo with issues
#    3. Human team members
#    Skipping all three should work (backward compatible)

Design Decisions

  • Agent prompt only — all features live in squad.agent.md. No CLI changes, no new template files. Keeps the tool lightweight.
  • gh CLI dependency — GitHub Issues features use gh CLI at runtime. This is already available in Copilot CLI environments.
  • Humans are roster-only — they appear in team.md and routing.md but can't be spawned. The coordinator pauses and waits for user relay.
  • PRD decomposition is gated — the Lead proposes work items, but the user must approve before agents start. Prevents runaway work from a misunderstood spec.
  • Backward compatible — all new Init Mode questions are optional. Existing squads work unchanged.

Add three new capabilities to the Squad coordinator prompt:

- GitHub Issues Mode: connect to a repo, list backlog, route issues to
  agents, full branch → PR → review → merge lifecycle via gh CLI
- PRD Mode: ingest from file path or pasted content, Lead decomposes
  into work items, supports mid-project PRD diffs
- Human Team Members: roster with 👤 badge, real names (no casting),
  coordinator pauses for human input, stale reminders

Update Init Mode to ask about PRDs, issues repo, and human members
during team setup (step 3), with post-setup wiring (step 9).

Add routing table entries for all three new modes.

Add 27 prompt-level validation tests covering all new sections.
@bradygaster
Copy link
Copy Markdown
Owner

The Squad squad is working atm, but, they've reviewed this PR and are taking it into account in this afternoon's pre-Super Bowl sprint. We should have it in by halftime. I'll text you, @spboyer

bradygaster added a commit that referenced this pull request Feb 8, 2026
Integrates @spboyer PR #2 with Keaton/Verbal review fixes applied.
New: GitHub Issues Mode, PRD Mode, Human Team Members (prompt-only).
Fixes: gh CLI detection, Init questions post-setup, worktree guidance,
ceremony integration, standard spawn template refs, decomposition guidelines.
33 new tests (61 total). Co-authored-by: Shayne Boyer <shayneboy@hotmail.com>
@bradygaster
Copy link
Copy Markdown
Owner

Hey @spboyer! 🎉 We took your work and integrated it into our wave-2 branch with some review fixes applied (see Proposal 025 for the full review).

What we kept (all of it!):

  • GitHub Issues Mode — full lifecycle, branch naming convention, PR review handling
  • PRD Mode — Lead decomposition, approval gate, mid-project updates
  • Human Team Members — pause-and-present pattern, stale reminders, mixed roster
  • All 33 prompt validation tests (adapted)
  • Routing table additions

Review fixes we applied:

  • Added \gh\ CLI detection (Prerequisites section) before first \gh\ command
  • Moved Init Mode questions to step 8 (post-setup) instead of step 3 (pre-casting) to keep init fast
  • Added worktree guidance for parallel issue work
  • Added ceremony integration note for multi-issue batches
  • Referenced standard spawn template (RESPONSE ORDER) in issue spawn prompts
  • Added decomposition guidelines (granularity targets, priority scheme, splitting rules)
  • Added human block continuation guidance (non-dependent work proceeds)
  • Added human reviewer integration with the rejection protocol

Your branch naming convention (\squad/{issue-number}-{slug}) is particularly brilliant — we love it. And the test suite for prompt validation is infrastructure we didn't have before. Strong contribution. 🙏

Closing this PR since the content has been integrated via commit ea7e24f on wave-2 with \Co-authored-by\ credit. It'll flow through our branch strategy: wave-2 → dev → release → main.

@bradygaster bradygaster closed this Feb 8, 2026
bradygaster added a commit that referenced this pull request Feb 8, 2026
Session: 2026-02-09-pr2-integration
Requested by: Brady

Changes:
- Logged PR #2 integration session (3 features, 33 tests, 61 total passing)
- Merged 6 decisions from inbox into decisions.md
- Consolidated 2 overlapping Kobayashi docs decisions into single entry
- Propagated cross-agent updates to 9 agent history files
@spboyer
Copy link
Copy Markdown
Contributor Author

spboyer commented Feb 9, 2026

Cool thanks for the note, would be better to get actual commit credit here. Perhaps the squad could figure out a way to ask for changes in the PR in lieu of copying the code submitted? @bradygaster

@bradygaster
Copy link
Copy Markdown
Owner

Yes in the future that'll be easier. Velocity got in the way this time. Thanks for the contribution, @spboyer; that was one i just aimed the squad at during development and they brought in as main had moved a lot.

bradygaster added a commit that referenced this pull request Feb 9, 2026
… export/import, history summarization

Wave 2: tiered response modes, smart upgrade with migrations, skills Phase 1, export CLI
Wave 3: import CLI, skills Phase 2, history summarization, lightweight spawn
Content: PR #2 contribution blog post (Shayne Boyer)
Tests: 61 -> 92, all passing

Requested by: bradygaster
bradygaster added a commit that referenced this pull request Feb 10, 2026
Session: 2026-02-10-v030-sprint-planning
Requested by: bradygaster

Changes:
- Logged session to .ai-team/log/2026-02-10-v030-sprint-planning.md
- Merged 11 decision(s) from inbox into decisions.md
- Consolidated 4 overlapping decision groups (silent-success, PR #2, skills phases, blog conventions)
- Removed 2 pre-consolidated incoming queue blocks
- Propagated updates to 9 agent history files
tamirdresher referenced this pull request in tamirdresher/squad 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>
tamirdresher referenced this pull request in tamirdresher/squad Mar 2, 2026
- #2: Add statSync directory check before createReadStream in start.ts
- bradygaster#7: Add Number.isFinite guard for pty_resize cols/rows in start.ts
- bradygaster#8: Add error handler on createReadStream stream in start.ts
- bradygaster#3: Remove raw non-JSON PTY write in bridge.ts and start.ts catch blocks
- bradygaster#18: Wrap decodeURIComponent in try/catch in start.ts static handler

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>
bradygaster added a commit that referenced this pull request Mar 22, 2026
- Add 'squad personal init/list/add/remove' subcommands
- Add 'squad cast' to show merged session cast
- Add --team-root CLI flag for explicit team root override
- Register commands in cli-entry.ts with help text

PR #2 of #508 implementation plan.
Depends on: squad/508-sdk-foundation (PR #1)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster added a commit that referenced this pull request Mar 23, 2026
* feat(sdk): add personal squad resolution and ambient discovery (#508)

- Add personalDir to ResolvedSquadPaths
- Add resolvePersonalSquadDir() with SQUAD_NO_PERSONAL kill switch
- Add PersonalAgentMeta/PersonalAgentManifest types
- Add resolvePersonalAgents() for personal agent discovery
- Add mergeSessionCast() to merge personal into project cast
- Add ensureSquadPathTriple() for triple-root path validation
- Export all new functions and types

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(cli): add personal squad commands and cast display (#508)

- Add 'squad personal init/list/add/remove' subcommands
- Add 'squad cast' to show merged session cast
- Add --team-root CLI flag for explicit team root override
- Register commands in cli-entry.ts with help text

PR #2 of #508 implementation plan.
Depends on: squad/508-sdk-foundation (PR #1)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
atuannguyen1101 pushed a commit to atuannguyen1101/squad that referenced this pull request Mar 24, 2026
Implements Sprint 2 self-improve pair (Issues bradygaster#2 and bradygaster#5).

## Proposals Pipeline (bradygaster#2)

- Risk classifier: classifyProposalRisk() categorizes proposals as
  auto-apply, surface-to-user, or needs-review based on category,
  priority, and target file sensitivity
- Auto-apply engine: safely appends content to existing files in
  safe paths (.squad/skills/, .squad/agents/, .copilot/skills/)
- Surface-to-user: formats proposals as pulse questions for human review
- Effectiveness tracking: records applied proposals in effectiveness.json,
  checks on next auto-sage run whether same detector fired again
- squad_proposals tool: new tool with create/list/update/apply operations
  added to ToolRegistry (6 tools total)

New file: packages/squad-sdk/src/mcp/proposal-pipeline.ts

## Ceremony Execution Engine (bradygaster#5)

- CeremonyRunner class: replaces simple dispatch with structured execution,
  builds role-appropriate prompts, collects responses, saves reports
- Retrospective ceremony: built-in type with classic retro template
  (what went well / what didn't / what to change), enhanced with pulse
  data, error summaries, and applied proposal effectiveness
- Manual trigger API: triggerCeremonyManually() for CLI/REPL use
- Ceremony reports saved to .squad/ceremonies/retros/{timestamp}.md

New files:
  packages/squad-sdk/src/server/ceremony-runner.ts
  packages/squad-sdk/src/server/ceremonies/retrospective.ts

## Integration

- Both systems are aware of each other: retrospectives review which
  proposals were applied and their effectiveness
- CeremonyConfig extended with type, trigger, and idleTimeoutMs fields
- All new types exported from package index and subpath exports
- No cron, no new dependencies, strict mode, ESM-only

## Tests

- 47 proposal pipeline tests (risk classifier, auto-apply, effectiveness)
- 28 ceremony runner tests (dispatch, prompts, reports, manual trigger)
- Updated existing tools.test.ts (56 tools)
- All 105 tests pass
joniba pushed a commit to joniba/squad that referenced this pull request Mar 26, 2026
…ct, format)

Files cherry-picked from branches squad/2-filter-messages, squad/3-extract-decisions,
and squad/4-format-summary. Original PRs bradygaster#31, bradygaster#32, bradygaster#42 had scope pollution from
the worktree clobbering problem.

Closes bradygaster#2, bradygaster#3, bradygaster#4

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
atuannguyen1101 pushed a commit to atuannguyen1101/squad that referenced this pull request Mar 29, 2026
…lti-run support

Implements foundational multi-run isolation architecture:

NEW FILES:
- packages/squad-sdk/src/mcp/run-context.ts: RunContext interface and RunContextManager for per-run state isolation (pulseCollector, intentGraph, pendingUserQuestions, activePipelines, waitResolvers)
- packages/squad-sdk/src/mcp/dispatch-utils.ts: DispatchSemaphore (max 1 concurrent sendAndWait) and safeSendAndWait wrapper with Promise.race + settled flag
- TODO-MULTI-RUN.md: Comprehensive implementation checklist and landmine documentation

MODIFIED FILES:
- packages/squad-sdk/src/server/agent-lifecycle.ts:
  * Added runId field to AgentSessionEntry and ActiveSessionInfo
  * Session keys now use format agentName::runId for isolation
  * Added makeSessionKey() helper function
  * Updated getOrCreateSession() to accept optional runId parameter
  * Updated dispatch() and sendFollowUp() to use safeSendAndWait + semaphore
  * Added closeRunSessions() for bulk session cleanup by runId
  * All session map operations now use composite keys

- packages/squad-sdk/src/mcp/server.ts:
  * Added RunContextManager import and instantiation
  * Creates RunContext on squad_run (currently tracked but not fully wired)

LANDMINES ADDRESSED:
- Landmine bradygaster#2 (sendAndWait timeout unreliable): Fixed with safeSendAndWait using Promise.race (90s timeout) + settled flag to prevent duplicate message pushes
- Landmine bradygaster#5 (concurrent sendAndWait stalls backend): Fixed with DispatchSemaphore limiting to 1 concurrent call
- Landmine bradygaster#4 (SessionPool.findByAgent name collisions): Avoided by using explicit session keys, not pool lookup

REMAINING WORK (Phase 2):
- Complete server.ts tool handler refactoring (squad_ask, squad_respond, squad_wait, squad_cancel all need runId parameters)
- Wire runId through waitForResponse and pipeline callbacks
- Implement auto-close sessions on pipeline completion
- Fix waitForDonePulse deadlock (landmine bradygaster#1)
- Update dashboard for run grouping (Phase 3)

Build:  Passes
Tests:  Pending (Phase 2 completion)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants