Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sandcastle-first-class-sandbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bradygaster/squad-cli": minor
---

Add first-class sandcastle sandbox execution support across watch/triage/loop/start/bridge, including `--sandbox-flags` passthrough, centralized execution config validation, updated CLI/help/docs, and acceptance/unit test coverage.
65 changes: 65 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Squad Runtime Context

Shared language for how Squad chooses and configures execution environments for agent work.

## Language

**Sandbox Provider**:
The execution environment family used for an agent session, with a stable behavior and security model.
_Avoid_: runner, shell mode, host mode

**Sandcastle Sandbox**:
A Sandbox Provider backed by Sandcastle for isolated execution, selected as a first-class option rather than an ad hoc flag bundle.
_Avoid_: custom flags, one-off command override

**Sandbox Selector**:
A dedicated user-facing option for choosing a Sandbox Provider, independent from raw Copilot flag passthrough.
_Avoid_: hidden flag parsing, implicit provider inference

**Permission Profile**:
A separate user-facing option that controls tool-consent behavior for a session, independent from Sandbox Provider selection.
_Avoid_: sandbox-implies-permissions, bundled execution mode

**Sandbox Availability Policy**:
The rule applied when a selected Sandbox Provider cannot be used. Default policy is fail fast with a clear error.
_Avoid_: silent fallback, best-effort provider swap

**Sandbox Coverage**:
The requirement that Sandbox Selector behavior applies uniformly to every Squad-managed Copilot spawn path.
_Avoid_: partial command support, path-specific semantics

**Sandbox Provider Enum**:
The canonical allowed Sandbox Provider values are `copilot` and `sandcastle`.
_Avoid_: free-form provider strings, implicit provider aliases

**Sandbox Precedence**:
When multiple sources specify sandbox, resolution order is CLI flag, then config file, then environment variable, then default `copilot`.
_Avoid_: source-order ambiguity, hidden precedence rules

**Sandcastle Profile Scope**:
Version 1 exposes Sandcastle as a single default profile. Provider-internal engine selection is deferred to a later version.
_Avoid_: multi-axis v1 configuration, premature engine-specific UX

**Sandbox Override Conflict Policy**:
Selecting a sandbox and specifying a custom agent command override at the same time is invalid by default and fails fast.
_Avoid_: override-bypasses-sandbox, silent command precedence

**Permission Profile Enum**:
The canonical allowed Permission Profile values are `interactive`, `yolo`, and `autopilot`.
_Avoid_: free-form approval flags, implicit permission modes

**Execution Surface Flags**:
The canonical CLI options are `--sandbox <copilot|sandcastle>` and `--permission-profile <interactive|yolo|autopilot>`.
_Avoid_: command-specific naming drift, hidden aliases

**Execution Surface Environment Variables**:
The canonical environment variable options are `SQUAD_SANDBOX` and `SQUAD_PERMISSION_PROFILE`.
_Avoid_: undocumented env aliases, mismatched naming with CLI flags

**Execution Error Codes**:
Fail-fast execution configuration errors use stable machine-readable codes: `SQUAD_SANDBOX_UNAVAILABLE`, `SQUAD_SANDBOX_OVERRIDE_CONFLICT`, `SQUAD_SANDBOX_INVALID_VALUE`, and `SQUAD_PERMISSION_PROFILE_INVALID_VALUE`.
_Avoid_: message-only error contracts, unstable code names

**Execution Telemetry Dimensions**:
Each Squad-managed spawn records low-cardinality execution config fields: `sandbox_provider`, `permission_profile`, `source_of_truth`, and `conflict_blocked`.
_Avoid_: high-cardinality payloads, opaque precedence telemetry
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ Say **"squad commands"** in chat to see a categorized menu of common operations
| `squad upgrade` | Update Squad-owned files to latest; never touches your team state; use `--global` to upgrade personal squad, `--migrate-directory` to rename `.ai-team/` → `.squad/` |
| `squad upgrade --self` | Update the Squad CLI package itself; add `--insider` for dev-channel prerelease builds |
| `squad status` | Show which squad is active and why |
| `squad triage` | **Watch mode** — poll for issues and auto-triage to team (aliases: `watch`, `loop`); use `--interval <minutes>` to set polling frequency (default: 10); with `--execute` dispatch Copilot agents; use `--agent-cmd`, `--copilot-flags`, `--auth-user` to customize agent execution; `--health` shows watch status; `--log-file` for diagnostics |
| `squad triage` | **Watch mode** — poll for issues and auto-triage to team (alias: `watch`); use `--interval <minutes>` to set polling frequency (default: 10); with `--execute` dispatch Copilot agents; use `--sandbox`, `--permission-profile`, `--agent-cmd`, `--copilot-flags`, `--auth-user` to customize execution; `--health` shows watch status; `--log-file` for diagnostics |
| `squad copilot` | Add/remove the Copilot coding agent (@copilot); use `--off` to remove, `--auto-assign` to enable auto-assignment |
| `squad doctor` | Check your setup and diagnose issues (alias: `heartbeat`) |
| `squad link <team-repo-path>` | Connect to a remote team |
Expand All @@ -163,6 +163,8 @@ Say **"squad commands"** in chat to see a categorized menu of common operations

Ralph continuously polls for work and dispatches agents to handle it. Watch mode helps a human team stay responsive — Ralph automates triage, execution handoffs, and monitoring, then escalates back to people when judgment or approval is needed.

For full sandbox and permission-profile behavior (resolution precedence, validation rules, and error codes), see [SANDBOX.md](SANDBOX.md).

### Quick Start

```bash
Expand All @@ -178,6 +180,12 @@ npx @bradygaster/squad-cli watch --execute \
--copilot-flags "--yolo --autopilot --mcp mail --agent squad" \
--auth-user myaccount

# Run with Sandcastle sandbox and autopilot profile
npx @bradygaster/squad-cli watch --execute \
--sandbox sandcastle \
--sandbox-flags "--your-sandcastle-flag value" \
--permission-profile autopilot

# Run watch with diagnostics
npx @bradygaster/squad-cli watch --execute --log-file ./watch.log --verbose

Expand All @@ -191,6 +199,9 @@ npx @bradygaster/squad-cli watch --health
|------|-------------|
| `--execute` | Enable agent execution (spawn Copilot sessions for actionable issues) |
| `--interval N` | Poll every N minutes (default: 10) |
| `--sandbox <provider>` | Execution sandbox (`copilot` or `sandcastle`; default: `copilot`) |
| `--sandbox-flags "..."` | Extra provider flags passed to `sandcastle` when sandbox is `sandcastle` |
| `--permission-profile <mode>` | Copilot permission profile (`interactive`, `yolo`, `autopilot`; default: `yolo`) |
| `--agent-cmd` | Custom agent command (default: `gh copilot`) |
| `--copilot-flags` | Flags passed to the agent runner (e.g., `--yolo --autopilot`) |
| `--auth-user` | GitHub/Azure DevOps account to use for agent auth |
Expand All @@ -202,6 +213,32 @@ npx @bradygaster/squad-cli watch --health
| `--notify-level` | Control output verbosity (`all` / `important` / `none`, default: `important`) |
| `--state-backend` | Persistence strategy (`git-notes` or `orphan-branch`, default: in-memory) |

### Sandbox Resolution and Validation

Watch (`squad watch` / `squad triage`) and loop (`squad loop`) resolve execution settings with this precedence:

1. CLI flags (`--sandbox`, `--permission-profile`)
2. `.squad/config.json` values
3. Environment variables (`SQUAD_SANDBOX`, `SQUAD_PERMISSION_PROFILE`)
4. Built-in defaults (`sandbox=copilot`, `permission-profile=yolo`)

Validation rules:

- `--sandbox` supports `copilot` and `sandcastle`.
- With `--sandbox sandcastle`, Squad maps prompt args to Sandcastle (`-p/--prompt` -> `--prompt`) and does not forward Copilot-only permission flags.
- `--sandbox-flags` is passed to sandcastle when `--sandbox sandcastle` is active.
- `--permission-profile` supports `interactive`, `yolo`, and `autopilot`.
- `sandcastle` requires the `sandcastle` binary to be available on PATH.
- `squad start` and `squad copilot-bridge` require `sandbox=copilot` because they depend on Copilot ACP/PTY behavior.
- Explicit sandbox selection conflicts with `--agent-cmd` overrides.

Stable error codes surfaced by the CLI:

- `SQUAD_SANDBOX_UNAVAILABLE`
- `SQUAD_SANDBOX_OVERRIDE_CONFLICT`
- `SQUAD_SANDBOX_INVALID_VALUE`
- `SQUAD_PERMISSION_PROFILE_INVALID_VALUE`

### How Watch Decides What to Execute

Ralph uses an **agent-delegated selection pattern**:
Expand Down
173 changes: 173 additions & 0 deletions SANDBOX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Sandbox and Permission Profiles

This document explains how Squad chooses an execution sandbox and permission profile for agent runs.

## Why This Exists

Squad supports two execution controls:

- Sandbox provider: where the agent process runs (`copilot` or `sandcastle`)
- Permission profile: how permissive the agent run should be (`interactive`, `yolo`, `autopilot`)

These controls are first-class for watch/triage and loop flows, with deterministic precedence and stable error codes.

## Supported Values

Sandbox providers:

- `copilot` (default)
- `sandcastle`

Permission profiles:

- `interactive`
- `yolo` (default)
- `autopilot`

## Install Sandcastle

Sandcastle is not bundled with Squad. Install it separately and make sure the
`sandcastle` executable is on your PATH.

Project: https://github.com/mattpocock/sandcastle

Install command:

```bash
npm install -g @ai-hero/sandcastle
```

Important: install the scoped package `@ai-hero/sandcastle`. There are unrelated
packages named `sandcastle` on npm that do not provide the expected CLI surface.

Verify install:

```bash
sandcastle --help
```

If this command fails, Squad will fail fast with `SQUAD_SANDBOX_UNAVAILABLE`
when `sandcastle` is selected.

## Resolution Precedence

Execution config is resolved in this order:

1. CLI flags
2. Project config (`.squad/config.json`)
3. Environment variables
4. Built-in defaults

Concrete inputs:

- CLI: `--sandbox`, `--permission-profile`
- Config: `sandbox`, `permissionProfile`
- Env: `SQUAD_SANDBOX`, `SQUAD_PERMISSION_PROFILE`, `SQUAD_SANDBOX_FLAGS`
- Defaults: `sandbox=copilot`, `permissionProfile=yolo`

## Validation Rules

- Invalid sandbox value fails fast.
- Invalid permission profile value fails fast.
- `sandcastle` requires a working `sandcastle` binary on PATH.
- Explicit sandbox selection conflicts with `--agent-cmd` override.

## Stable Error Codes

These codes are intentionally stable for automation and CI checks:

- `SQUAD_SANDBOX_UNAVAILABLE`
- `SQUAD_SANDBOX_OVERRIDE_CONFLICT`
- `SQUAD_SANDBOX_INVALID_VALUE`
- `SQUAD_PERMISSION_PROFILE_INVALID_VALUE`

## Permission Profile Behavior

Permission profiles normalize flags passed to Copilot CLI:

- `interactive`: strips `--yolo` and `--autopilot`
- `yolo`: ensures `--yolo`
- `autopilot`: ensures both `--yolo` and `--autopilot`

This makes behavior deterministic even if user-provided extra flags include permission switches.

Note: permission profile flags are a Copilot concern. They are not forwarded to
Sandcastle.

## Using Sandcastle Options from Squad

Current status:

- First-class sandbox selection (`--sandbox sandcastle`) validates and selects
the sandcastle executable for supported execution paths.
- Provider-specific sandcastle flags are supported via `--sandbox-flags "..."`.
- Prompt arguments are mapped for sandcastle compatibility:
- `-p <text>` / `--prompt <text>` -> `--prompt <text>`
- `--prompt-file <path>` is passed through
- Copilot-specific flags (for example `--yolo`, `--autopilot`, MCP-injection flags)
are not forwarded to sandcastle.

What you can do today:

1. Use first-class sandbox/profile controls for policy and validation:
- `--sandbox sandcastle`
- `--sandbox-flags "..."`
- `--permission-profile <interactive|yolo|autopilot>`
2. Do not combine explicit sandbox selection with `--agent-cmd` in the same
invocation; that combination is blocked by design (`SQUAD_SANDBOX_OVERRIDE_CONFLICT`).

Example watch invocation with provider flags:

```bash
squad watch --execute \
--sandbox sandcastle \
--sandbox-flags "--your-flag value" \
--permission-profile autopilot
```

## Where It Applies

Primary command paths:

- `squad watch`
- `squad triage` (watch alias)
- `squad loop`

Additional spawn paths also use the same execution resolver for consistency:

- `squad start` (requires `sandbox=copilot`)
- `squad copilot-bridge` (requires `sandbox=copilot`)

## Examples

Watch with Sandcastle + autopilot:

```bash
squad watch --execute --sandbox sandcastle --permission-profile autopilot
```

Loop with interactive profile:

```bash
squad loop --permission-profile interactive
```

Environment-driven defaults:

```bash
export SQUAD_SANDBOX=sandcastle
export SQUAD_PERMISSION_PROFILE=yolo
squad watch --execute
```

## Troubleshooting

If you see sandbox/profile errors:

1. Run `squad watch --help` or `squad loop --help` to verify accepted values.
2. Confirm `sandcastle` is installed and available in PATH if selected.
3. Remove `--agent-cmd` when using explicit sandbox selection.
4. Check for unexpected env vars:
- `SQUAD_SANDBOX`
- `SQUAD_PERMISSION_PROFILE`
5. Check `.squad/config.json` for stale values overriding your defaults.
Loading