diff --git a/.changeset/add-rework-rate-metric.md b/.changeset/add-rework-rate-metric.md new file mode 100644 index 000000000..20d83e64c --- /dev/null +++ b/.changeset/add-rework-rate-metric.md @@ -0,0 +1,5 @@ +--- +"@bradygaster/squad-sdk": minor +--- + +Add rework rate OTEL metrics (#265) — tracks PR revision patterns as the emerging 5th DORA metric diff --git a/.changeset/add-session-recovery-skill.md b/.changeset/add-session-recovery-skill.md new file mode 100644 index 000000000..53d80c9c1 --- /dev/null +++ b/.changeset/add-session-recovery-skill.md @@ -0,0 +1,4 @@ +--- +--- + +Add session-recovery skill for detecting and resuming interrupted Copilot CLI sessions diff --git a/.changeset/add-skill-script-loader.md b/.changeset/add-skill-script-loader.md new file mode 100644 index 000000000..d36276e9f --- /dev/null +++ b/.changeset/add-skill-script-loader.md @@ -0,0 +1,5 @@ +--- +"@bradygaster/squad-sdk": minor +--- + +Add SkillScriptLoader, handler types, and applySkillHandlers for executable skill handler scripts diff --git a/.changeset/ado-configurable-items.md b/.changeset/ado-configurable-items.md new file mode 100644 index 000000000..b1b2e0cec --- /dev/null +++ b/.changeset/ado-configurable-items.md @@ -0,0 +1,14 @@ +--- +"@bradygaster/squad-sdk": minor +--- + +ADO configurable work item types, area paths, and iteration support (#240) + +- Add `getAvailableWorkItemTypes(org, project)` for process template introspection +- Add `validateWorkItemType(org, project, typeName)` for pre-creation validation +- Add `WorkItemTypeInfo` interface for type metadata +- Enhance `AzureDevOpsAdapter` with instance-level `getAvailableWorkItemTypes()` and `validateWorkItemType()` methods +- Support optional `validateType` flag in `createWorkItem()` to check type before creation +- Enhance `squad init` to introspect available work item types and store `_availableTypes` hint in `.squad/config.json` +- Support `adoConfig` in `InitOptions` for explicit work item type, area path, and iteration path during init +- Graceful fallback to default types (User Story, Bug, Task) when az CLI is unavailable diff --git a/.changeset/config.json b/.changeset/config.json index b8213321c..e18afe4e1 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -5,7 +5,7 @@ "fixed": [], "linked": [], "access": "public", - "baseBranch": "main", + "baseBranch": "dev", "updateInternalDependencies": "patch", "ignore": [] } diff --git a/.changeset/cooperative-rate-limiting.md b/.changeset/cooperative-rate-limiting.md new file mode 100644 index 000000000..524a58109 --- /dev/null +++ b/.changeset/cooperative-rate-limiting.md @@ -0,0 +1,11 @@ +--- +"@bradygaster/squad-sdk": minor +--- + +feat: Cooperative rate limiting with predictive circuit breaker + +Added cooperative rate limiting patterns for multi-agent deployments: +- Traffic Light, Predictive Circuit Breaker, Priority Retry Windows +- Cooperative Token Pool for shared quota management + +Closes #515 diff --git a/.changeset/cross-squad-orchestration.md b/.changeset/cross-squad-orchestration.md new file mode 100644 index 000000000..c22bde31a --- /dev/null +++ b/.changeset/cross-squad-orchestration.md @@ -0,0 +1,6 @@ +--- +"@bradygaster/squad-sdk": minor +"@bradygaster/squad-cli": minor +--- + +Cross-squad orchestration — discovery, delegation, and manifest (#316). Adds manifest schema, `squad discover` / `squad delegate` commands, and runtime module for coordinating work across multiple Squad instances. diff --git a/.changeset/fix-readme-migration-guide-link.md b/.changeset/fix-readme-migration-guide-link.md new file mode 100644 index 000000000..84d732067 --- /dev/null +++ b/.changeset/fix-readme-migration-guide-link.md @@ -0,0 +1,5 @@ +--- +"@bradygaster/squad-cli": patch +--- + +docs: point README migration guide links to the published docs site \ No newline at end of file diff --git a/.changeset/keda-scaler-docs.md b/.changeset/keda-scaler-docs.md new file mode 100644 index 000000000..f838ef7d8 --- /dev/null +++ b/.changeset/keda-scaler-docs.md @@ -0,0 +1,10 @@ +--- +"@bradygaster/squad-cli": patch +--- + +docs: Add KEDA external scaler template for GitHub issue-driven autoscaling + +New template documenting how to use keda-copilot-scaler for scaling +agent pods to zero when idle, with rate-limit-aware polling. + +Closes #516 diff --git a/.changeset/machine-capability-routing.md b/.changeset/machine-capability-routing.md new file mode 100644 index 000000000..2ac99caf7 --- /dev/null +++ b/.changeset/machine-capability-routing.md @@ -0,0 +1,15 @@ +--- +"@bradygaster/squad-sdk": minor +"@bradygaster/squad-cli": minor +--- + +feat: Machine capability discovery and `needs:*` label-based issue routing + +Added capability filtering to Ralph's watch command. Issues with `needs:*` labels +(e.g., `needs:gpu`, `needs:browser`) are only processed by Ralph instances whose +machine has those capabilities declared in `machine-capabilities.json`. + +This enables multi-machine Squad deployments where different machines handle +different types of work based on their available tooling. + +Closes #514 \ No newline at end of file diff --git a/.changeset/persistent-ralph.md b/.changeset/persistent-ralph.md new file mode 100644 index 000000000..35d94bbd8 --- /dev/null +++ b/.changeset/persistent-ralph.md @@ -0,0 +1,11 @@ +--- +'@bradygaster/squad-sdk': minor +'@bradygaster/squad-cli': minor +--- + +Enable persistent Ralph — heartbeat cron + healthCheck timer + +- Enable cron schedule in squad-heartbeat.yml (all 5 sync locations) +- Enable RalphMonitor healthCheck timer (previously commented out pre-migration) +- Add platform detection tests for getRalphScanCommands (GitHub/ADO/Planner) +- Add healthCheck timer tests with fake timers (start/stop/interval/stale detection) diff --git a/.changeset/sdk-parity-batch2-tests.md b/.changeset/sdk-parity-batch2-tests.md new file mode 100644 index 000000000..5a06207d4 --- /dev/null +++ b/.changeset/sdk-parity-batch2-tests.md @@ -0,0 +1,5 @@ +--- +"@bradygaster/squad-sdk": patch +--- + +Add SDK feature parity batch 2 — 64 tests covering manual ceremonies (#27), ceremony cooldown (#28), human team members (#36), constraint budget enforcement (#49 — rate limiter, file-write guards, shell restrictions, PII scrubbing), multi-agent artifact coordination (#50), and builder validation edge cases. diff --git a/.changeset/sdk-parity-batch3-tests.md b/.changeset/sdk-parity-batch3-tests.md new file mode 100644 index 000000000..79aa07c39 --- /dev/null +++ b/.changeset/sdk-parity-batch3-tests.md @@ -0,0 +1,11 @@ +--- +"@bradygaster/squad-sdk": patch +--- + +test: SDK feature parity batch 3 — 46 tests for #31, #47, #45, #46 + +Adds 46 automated tests covering 4 SDK features from the #341 parity matrix: +- RalphMonitor idle-watch mode (#31): construction, event handling, stale session detection +- Platform detection (#47): GitHub/Azure DevOps URL parsing, detectPlatformFromUrl +- Reviewer lockout (#45): rejection protocol, per-artifact scope, persistence +- Deadlock handling (#46): all-agents-locked detection, clearLockout escalation, recovery diff --git a/.changeset/squad-scheduler.md b/.changeset/squad-scheduler.md new file mode 100644 index 000000000..c008a8920 --- /dev/null +++ b/.changeset/squad-scheduler.md @@ -0,0 +1,6 @@ +--- +"@bradygaster/squad-sdk": minor +"@bradygaster/squad-cli": minor +--- + +Generic, provider-agnostic scheduler for Squad (#296) — unified schedule.json manifest with LocalPolling and GitHubActions provider adapters, CLI commands (list, run, init, status), schema validation, and cron/interval trigger evaluation. diff --git a/.copilot/skills/agent-collaboration/SKILL.md b/.copilot/skills/agent-collaboration/SKILL.md new file mode 100644 index 000000000..054463cf8 --- /dev/null +++ b/.copilot/skills/agent-collaboration/SKILL.md @@ -0,0 +1,42 @@ +--- +name: "agent-collaboration" +description: "Standard collaboration patterns for all squad agents — worktree awareness, decisions, cross-agent communication" +domain: "team-workflow" +confidence: "high" +source: "extracted from charter boilerplate — identical content in 18+ agent charters" +--- + +## Context + +Every agent on the team follows identical collaboration patterns for worktree awareness, decision recording, and cross-agent communication. These were previously duplicated in every charter's Collaboration section (~300 bytes × 18 agents = ~5.4KB of redundant context). Now centralized here. + +The coordinator's spawn prompt already instructs agents to read decisions.md and their history.md. This skill adds the patterns for WRITING decisions and requesting help. + +## Patterns + +### Worktree Awareness +Use the `TEAM ROOT` path provided in your spawn prompt. All `.squad/` paths are relative to this root. If TEAM ROOT is not provided (rare), run `git rev-parse --show-toplevel` as fallback. Never assume CWD is the repo root. + +### Decision Recording +After making a decision that affects other team members, write it to: +`.squad/decisions/inbox/{your-name}-{brief-slug}.md` + +Format: +``` +### {date}: {decision title} +**By:** {Your Name} +**What:** {the decision} +**Why:** {rationale} +``` + +### Cross-Agent Communication +If you need another team member's input, say so in your response. The coordinator will bring them in. Don't try to do work outside your domain. + +### Reviewer Protocol +If you have reviewer authority and reject work: the original author is locked out from revising that artifact. A different agent must own the revision. State who should revise in your rejection response. + +## Anti-Patterns +- Don't read all agent charters — you only need your own context + decisions.md +- Don't write directly to `.squad/decisions.md` — always use the inbox drop-box +- Don't modify other agents' history.md files — that's Scribe's job +- Don't assume CWD is the repo root — always use TEAM ROOT diff --git a/.copilot/skills/agent-conduct/SKILL.md b/.copilot/skills/agent-conduct/SKILL.md new file mode 100644 index 000000000..87ef3fda3 --- /dev/null +++ b/.copilot/skills/agent-conduct/SKILL.md @@ -0,0 +1,24 @@ +--- +name: "agent-conduct" +description: "Shared hard rules enforced across all squad agents" +domain: "team-governance" +confidence: "high" +source: "reskill extraction — Product Isolation Rule and Peer Quality Check appeared in all 20 agent charters" +--- + +## Context + +Every squad agent must follow these two hard rules. They were previously duplicated in every charter. Now they live here as a shared skill, loaded once. + +## Patterns + +### Product Isolation Rule (hard rule) +Tests, CI workflows, and product code must NEVER depend on specific agent names from any particular squad. "Our squad" must not impact "the squad." No hardcoded references to agent names (Flight, EECOM, FIDO, etc.) in test assertions, CI configs, or product logic. Use generic/parameterized values. If a test needs agent names, use obviously-fake test fixtures (e.g., "test-agent-1", "TestBot"). + +### Peer Quality Check (hard rule) +Before finishing work, verify your changes don't break existing tests. Run the test suite for files you touched. If CI has been failing, check your changes aren't contributing to the problem. When you learn from mistakes, update your history.md. + +## Anti-Patterns +- Don't hardcode dev team agent names in product code or tests +- Don't skip test verification before declaring work done +- Don't ignore pre-existing CI failures that your changes may worsen diff --git a/.squad/skills/architectural-proposals/SKILL.md b/.copilot/skills/architectural-proposals/SKILL.md similarity index 100% rename from .squad/skills/architectural-proposals/SKILL.md rename to .copilot/skills/architectural-proposals/SKILL.md diff --git a/.copilot/skills/ci-validation-gates/SKILL.md b/.copilot/skills/ci-validation-gates/SKILL.md new file mode 100644 index 000000000..61c07d73e --- /dev/null +++ b/.copilot/skills/ci-validation-gates/SKILL.md @@ -0,0 +1,84 @@ +--- +name: "ci-validation-gates" +description: "Defensive CI/CD patterns: semver validation, token checks, retry logic, draft detection — earned from v0.8.22" +domain: "ci-cd" +confidence: "high" +source: "extracted from Drucker and Trejo charters — earned knowledge from v0.8.22 release incident" +--- + +## Context + +CI workflows must be defensive. These patterns were learned from the v0.8.22 release disaster where invalid semver, wrong token types, missing retry logic, and draft releases caused a multi-hour outage. Both Drucker (CI/CD) and Trejo (Release Manager) carried this knowledge in their charters — now centralized here. + +## Patterns + +### Semver Validation Gate +Every publish workflow MUST validate version format before `npm publish`. 4-part versions (e.g., 0.8.21.4) are NOT valid semver — npm mangles them. + +```yaml +- name: Validate semver + run: | + VERSION="${{ github.event.release.tag_name }}" + VERSION="${VERSION#v}" + if ! npx semver "$VERSION" > /dev/null 2>&1; then + echo "❌ Invalid semver: $VERSION" + echo "Only 3-part versions (X.Y.Z) or prerelease (X.Y.Z-tag.N) are valid." + exit 1 + fi + echo "✅ Valid semver: $VERSION" +``` + +### NPM Token Type Verification +NPM_TOKEN MUST be an Automation token, not a User token with 2FA: +- User tokens require OTP — CI can't provide it → EOTP error +- Create Automation tokens at npmjs.com → Settings → Access Tokens → Automation +- Verify before first publish in any workflow + +### Retry Logic for npm Registry Propagation +npm registry uses eventual consistency. After `npm publish` succeeds, the package may not be immediately queryable. +- Propagation: typically 5-30s, up to 2min in rare cases +- All verify steps: 5 attempts, 15-second intervals +- Log each attempt: "Attempt 1/5: Checking package..." +- Exit loop on success, fail after max attempts + +```yaml +- name: Verify package (with retry) + run: | + MAX_ATTEMPTS=5 + WAIT_SECONDS=15 + for attempt in $(seq 1 $MAX_ATTEMPTS); do + echo "Attempt $attempt/$MAX_ATTEMPTS: Checking $PACKAGE@$VERSION..." + if npm view "$PACKAGE@$VERSION" version > /dev/null 2>&1; then + echo "✅ Package verified" + exit 0 + fi + [ $attempt -lt $MAX_ATTEMPTS ] && sleep $WAIT_SECONDS + done + echo "❌ Failed to verify after $MAX_ATTEMPTS attempts" + exit 1 +``` + +### Draft Release Detection +Draft releases don't emit `release: published` event. Workflows MUST: +- Trigger on `release: published` (NOT `created`) +- If using workflow_dispatch: verify release is published via GitHub API before proceeding + +### Build Script Protection +Set `SKIP_BUILD_BUMP=1` (or `$env:SKIP_BUILD_BUMP = "1"` on Windows) before ANY release build. bump-build.mjs is for dev builds ONLY — it silently mutates versions. + +## Known Failure Modes (v0.8.22 Incident) + +| # | What Happened | Root Cause | Prevention | +|---|---------------|-----------|------------| +| 1 | 4-part version published, npm mangled it | No semver validation gate | `npx semver` check before every publish | +| 2 | CI failed 5+ times with EOTP | User token with 2FA | Automation token only | +| 3 | Verify returned false 404 | No retry logic for propagation | 5 attempts, 15s intervals | +| 4 | Workflow never triggered | Draft release doesn't emit event | Never create draft releases | +| 5 | Version mutated during release | bump-build.mjs ran in release | SKIP_BUILD_BUMP=1 | + +## Anti-Patterns +- ❌ Publishing without semver validation gate +- ❌ Single-shot verification without retry +- ❌ Hard-coded secrets in workflows +- ❌ Silent CI failures — every error needs actionable output with remediation +- ❌ Assuming npm publish is instantly queryable diff --git a/.squad/skills/cli-wiring/SKILL.md b/.copilot/skills/cli-wiring/SKILL.md similarity index 100% rename from .squad/skills/cli-wiring/SKILL.md rename to .copilot/skills/cli-wiring/SKILL.md diff --git a/.squad/skills/client-compatibility/SKILL.md b/.copilot/skills/client-compatibility/SKILL.md similarity index 100% rename from .squad/skills/client-compatibility/SKILL.md rename to .copilot/skills/client-compatibility/SKILL.md diff --git a/.copilot/skills/distributed-mesh/SKILL.md b/.copilot/skills/distributed-mesh/SKILL.md new file mode 100644 index 000000000..b2e924450 --- /dev/null +++ b/.copilot/skills/distributed-mesh/SKILL.md @@ -0,0 +1,287 @@ +--- +name: "distributed-mesh" +description: "How to coordinate with squads on different machines using git as transport" +domain: "distributed-coordination" +confidence: "high" +source: "multi-model-consensus (Opus 4.6, Sonnet 4.5, GPT-5.4)" +--- + +## SCOPE + +**✅ THIS SKILL PRODUCES (exactly these, nothing more):** + +1. **`mesh.json`** — Generated from user answers about zones and squads (which squads participate, what zone each is in, paths/URLs for each), using `mesh.json.example` in this skill's directory as the schema template +2. **`sync-mesh.sh` and `sync-mesh.ps1`** — Copied from this skill's directory into the project root (these are bundled resources, NOT generated code) +3. **Zone 2 state repo initialization** (if applicable) — If the user specified a Zone 2 shared state repo, run `sync-mesh.sh --init` to scaffold the state repo structure +4. **A decision entry** in `.squad/decisions/inbox/` documenting the mesh configuration for team awareness + +**❌ THIS SKILL DOES NOT PRODUCE:** + +- **No application code** — No validators, libraries, or modules of any kind +- **No test files** — No test suites, test cases, or test scaffolding +- **No GENERATING sync scripts** — They are bundled with this skill as pre-built resources. COPY them, don't generate them. +- **No daemons or services** — No background processes, servers, or persistent runtimes +- **No modifications to existing squad files** beyond the decision entry (no changes to team.md, routing.md, agent charters, etc.) + +**Your role:** Configure the mesh topology and install the bundled sync scripts. Nothing more. + +## Context + +When squads are on different machines (developer laptops, CI runners, cloud VMs, partner orgs), the local file-reading convention still works — but remote files need to arrive on your disk first. This skill teaches the pattern for distributed squad communication. + +**When this applies:** +- Squads span multiple machines, VMs, or CI runners +- Squads span organizations or companies +- An agent needs context from a squad whose files aren't on the local filesystem + +**When this does NOT apply:** +- All squads are on the same machine (just read the files directly) + +## Patterns + +### The Core Principle + +> "The filesystem is the mesh, and git is how the mesh crosses machine boundaries." + +The agent interface never changes. Agents always read local files. The distributed layer's only job is to make remote files appear locally before the agent reads them. + +### Three Zones of Communication + +**Zone 1 — Local:** Same filesystem. Read files directly. Zero transport. + +**Zone 2 — Remote-Trusted:** Different host, same org, shared git auth. Transport: `git pull` from a shared repo. This collapses Zone 2 into Zone 1 — files materialize on disk, agent reads them normally. + +**Zone 3 — Remote-Opaque:** Different org, no shared auth. Transport: `curl` to fetch published contracts (SUMMARY.md). One-way visibility — you see only what they publish. + +### Agent Lifecycle (Distributed) + +``` +1. SYNC: git pull (Zone 2) + curl (Zone 3) — materialize remote state +2. READ: cat .mesh/**/state.md — all files are local now +3. WORK: do their assigned work (the agent's normal task, NOT mesh-building) +4. WRITE: update own billboard, log, drops +5. PUBLISH: git add + commit + push — share state with remote peers +``` + +Steps 2–4 are identical to local-only. Steps 1 and 5 are the entire distributed extension. **Note:** "WORK" means the agent performs its normal squad duties — it does NOT mean "build mesh infrastructure." + +### The mesh.json Config + +```json +{ + "squads": { + "auth-squad": { "zone": "local", "path": "../auth-squad/.mesh" }, + "ci-squad": { + "zone": "remote-trusted", + "source": "git@github.com:our-org/ci-squad.git", + "ref": "main", + "sync_to": ".mesh/remotes/ci-squad" + }, + "partner-fraud": { + "zone": "remote-opaque", + "source": "https://partner.dev/squad-contracts/fraud/SUMMARY.md", + "sync_to": ".mesh/remotes/partner-fraud", + "auth": "bearer" + } + } +} +``` + +Three zone types, one file. Local squads need only a path. Remote-trusted need a git URL. Remote-opaque need an HTTP URL. + +### Write Partitioning + +Each squad writes only to its own directory (`boards/{self}.md`, `squads/{self}/*`, `drops/{date}-{self}-*.md`). No two squads write to the same file. Git push/pull never conflicts. If push fails ("branch is behind"), the fix is always `git pull --rebase && git push`. + +### Trust Boundaries + +Trust maps to git permissions: +- **Same repo access** = full mesh visibility +- **Read-only access** = can observe, can't write +- **No access** = invisible (correct behavior) + +For selective visibility, use separate repos per audience (internal, partner, public). Git permissions ARE the trust negotiation. + +### Phased Rollout + +- **Phase 0:** Convention only — document zones, agree on mesh.json fields, manually run `git pull`/`git push`. Zero new code. +- **Phase 1:** Sync script (~30 lines bash or PowerShell) when manual sync gets tedious. +- **Phase 2:** Published contracts + curl fetch when a Zone 3 partner appears. +- **Phase 3:** Never. No MCP federation, A2A, service discovery, message queues. + +**Important:** Phases are NOT auto-advanced. These are project-level decisions — you start at Phase 0 (manual sync) and only move forward when the team decides complexity is justified. + +### Mesh State Repo + +The shared mesh state repo is a plain git repository — NOT a Squad project. It holds: +- One directory per participating squad +- Each directory contains at minimum a SUMMARY.md with the squad's current state +- A root README explaining what the repo is and who participates + +No `.squad/` folder, no agents, no automation. Write partitioning means each squad only pushes to its own directory. The repo is a rendezvous point, not an intelligent system. + +If you want a squad that *observes* mesh health, that's a separate Squad project that lists the state repo as a Zone 2 remote in its `mesh.json` — it does NOT live inside the state repo. + +## Examples + +### Developer Laptop + CI Squad (Zone 2) + +Auth-squad agent wakes up. `git pull` brings ci-squad's latest results. Agent reads: "3 test failures in auth module." Adjusts work. Pushes results when done. **Overhead: one `git pull`, one `git push`.** + +### Two Orgs Collaborating (Zone 3) + +Payment-squad fetches partner's published SUMMARY.md via curl. Reads: "Risk scoring v3 API deprecated April 15. New field `device_fingerprint` required." The consuming agent (in payment-squad's team) reads this information and uses it to inform its work — for example, updating payment integration code to include the new field. Partner can't see payment-squad's internals. + +### Same Org, Shared Mesh Repo (Zone 2) + +Three squads on different machines. One shared git repo holds the mesh. Each squad: `git pull` before work, `git push` after. Write partitioning ensures zero merge conflicts. + +## AGENT WORKFLOW (Deterministic Setup) + +When a user invokes this skill to set up a distributed mesh, follow these steps **exactly, in order:** + +### Step 1: ASK the user for mesh topology + +Ask these questions (adapt phrasing naturally, but get these answers): + +1. **Which squads are participating?** (List of squad names) +2. **For each squad, which zone is it in?** + - `local` — same filesystem (just need a path) + - `remote-trusted` — different machine, same org, shared git access (need git URL + ref) + - `remote-opaque` — different org, no shared auth (need HTTPS URL to published contract) +3. **For each squad, what's the connection info?** + - Local: relative or absolute path to their `.mesh/` directory + - Remote-trusted: git URL (SSH or HTTPS), ref (branch/tag), and where to sync it to locally + - Remote-opaque: HTTPS URL to their SUMMARY.md, where to sync it, and auth type (none/bearer) +4. **Where should the shared state live?** (For Zone 2 squads: git repo URL for the mesh state, or confirm each squad syncs independently) + +### Step 2: GENERATE `mesh.json` + +Using the answers from Step 1, create a `mesh.json` file at the project root. Use `mesh.json.example` from THIS skill's directory (`.copilot/skills/distributed-mesh/mesh.json.example`) as the schema template. + +Structure: + +```json +{ + "squads": { + "": { "zone": "local", "path": "" }, + "": { + "zone": "remote-trusted", + "source": "", + "ref": "", + "sync_to": ".mesh/remotes/" + }, + "": { + "zone": "remote-opaque", + "source": "", + "sync_to": ".mesh/remotes/", + "auth": "" + } + } +} +``` + +Write this file to the project root. Do NOT write any other code. + +### Step 3: COPY sync scripts + +Copy the bundled sync scripts from THIS skill's directory into the project root: + +- **Source:** `.copilot/skills/distributed-mesh/sync-mesh.sh` +- **Destination:** `sync-mesh.sh` (project root) + +- **Source:** `.copilot/skills/distributed-mesh/sync-mesh.ps1` +- **Destination:** `sync-mesh.ps1` (project root) + +These are bundled resources. Do NOT generate them — COPY them directly. + +### Step 4: RUN `--init` (if Zone 2 state repo exists) + +If the user specified a Zone 2 shared state repo in Step 1, run the initialization: + +**On Unix/Linux/macOS:** +```bash +bash sync-mesh.sh --init +``` + +**On Windows:** +```powershell +.\sync-mesh.ps1 -Init +``` + +This scaffolds the state repo structure (squad directories, placeholder SUMMARY.md files, root README). + +**Skip this step if:** +- No Zone 2 squads are configured (local/opaque only) +- The state repo already exists and is initialized + +### Step 5: WRITE a decision entry + +Create a decision file at `.squad/decisions/inbox/-mesh-setup.md` with this content: + +```markdown +### : Mesh configuration + +**By:** (via distributed-mesh skill) + +**What:** Configured distributed mesh with squads across zones + +**Squads:** +- `` — Zone — +- `` — Zone — +- ... + +**State repo:** + +**Why:** +``` + +Write this file. The Scribe will merge it into the main decisions file later. + +### Step 6: STOP + +**You are done.** Do not: +- Generate sync scripts (they're bundled with this skill — COPY them) +- Write validator code +- Write test files +- Create any other modules, libraries, or application code +- Modify existing squad files (team.md, routing.md, charters) +- Auto-advance to Phase 2 or Phase 3 + +Output a simple completion message: + +``` +✅ Mesh configured. Created: +- mesh.json ( squads) +- sync-mesh.sh and sync-mesh.ps1 (copied from skill bundle) +- Decision entry: .squad/decisions/inbox/ + +Run `bash sync-mesh.sh` (or `.\sync-mesh.ps1` on Windows) before agents start to materialize remote state. +``` + +--- + +## Anti-Patterns + +**❌ Code generation anti-patterns:** +- Writing `mesh-config-validator.js` or any validator module +- Writing test files for mesh configuration +- Generating sync scripts instead of copying the bundled ones from this skill's directory +- Creating library modules or utilities +- Building any code that "runs the mesh" — the mesh is read by agents, not executed + +**❌ Architectural anti-patterns:** +- Building a federation protocol — Git push/pull IS federation +- Running a sync daemon or server — Agents are not persistent. Sync at startup, publish at shutdown +- Real-time notifications — Agents don't need real-time. They need "recent enough." `git pull` is recent enough +- Schema validation for markdown — The LLM reads markdown. If the format changes, it adapts +- Service discovery protocol — mesh.json is a file with 10 entries. Not a "discovery problem" +- Auth framework — Git SSH keys and HTTPS tokens. Not a framework. Already configured +- Message queues / event buses — Agents wake, read, work, write, sleep. Nobody's home to receive events +- Any component requiring a running process — That's the line. Don't cross it + +**❌ Scope creep anti-patterns:** +- Auto-advancing phases without user decision +- Modifying agent charters or routing rules +- Setting up CI/CD pipelines for mesh sync +- Creating dashboards or monitoring tools diff --git a/.copilot/skills/distributed-mesh/mesh.json.example b/.copilot/skills/distributed-mesh/mesh.json.example new file mode 100644 index 000000000..7f5730a88 --- /dev/null +++ b/.copilot/skills/distributed-mesh/mesh.json.example @@ -0,0 +1,30 @@ +{ + "squads": { + "auth-squad": { + "zone": "local", + "path": "../auth-squad/.mesh" + }, + "api-squad": { + "zone": "local", + "path": "../api-squad/.mesh" + }, + "ci-squad": { + "zone": "remote-trusted", + "source": "git@github.com:our-org/ci-squad.git", + "ref": "main", + "sync_to": ".mesh/remotes/ci-squad" + }, + "data-squad": { + "zone": "remote-trusted", + "source": "git@github.com:our-org/data-pipeline.git", + "ref": "main", + "sync_to": ".mesh/remotes/data-squad" + }, + "partner-fraud": { + "zone": "remote-opaque", + "source": "https://partner.example.com/squad-contracts/fraud/SUMMARY.md", + "sync_to": ".mesh/remotes/partner-fraud", + "auth": "bearer" + } + } +} diff --git a/.copilot/skills/distributed-mesh/sync-mesh.ps1 b/.copilot/skills/distributed-mesh/sync-mesh.ps1 new file mode 100644 index 000000000..5f409ef37 --- /dev/null +++ b/.copilot/skills/distributed-mesh/sync-mesh.ps1 @@ -0,0 +1,111 @@ +# sync-mesh.ps1 — Materialize remote squad state locally +# +# Reads mesh.json, fetches remote squads into local directories. +# Run before agent reads. No daemon. No service. ~40 lines. +# +# Usage: .\sync-mesh.ps1 [path-to-mesh.json] +# .\sync-mesh.ps1 -Init [path-to-mesh.json] +# Requires: git +param( + [switch]$Init, + [string]$MeshJson = "mesh.json" +) +$ErrorActionPreference = "Stop" + +# Handle -Init mode +if ($Init) { + if (-not (Test-Path $MeshJson)) { + Write-Host "❌ $MeshJson not found" + exit 1 + } + + Write-Host "🚀 Initializing mesh state repository..." + $config = Get-Content $MeshJson -Raw | ConvertFrom-Json + $squads = $config.squads.PSObject.Properties.Name + + # Create squad directories with placeholder SUMMARY.md + foreach ($squad in $squads) { + if (-not (Test-Path $squad)) { + New-Item -ItemType Directory -Path $squad | Out-Null + Write-Host " ✓ Created $squad/" + } else { + Write-Host " • $squad/ exists (skipped)" + } + + $summaryPath = "$squad/SUMMARY.md" + if (-not (Test-Path $summaryPath)) { + "# $squad`n`n_No state published yet._" | Set-Content $summaryPath + Write-Host " ✓ Created $summaryPath" + } else { + Write-Host " • $summaryPath exists (skipped)" + } + } + + # Generate root README.md + if (-not (Test-Path "README.md")) { + $readme = @" +# Squad Mesh State Repository + +This repository tracks published state from participating squads. + +## Participating Squads + +"@ + foreach ($squad in $squads) { + $zone = $config.squads.$squad.zone + $readme += "- **$squad** (Zone: $zone)`n" + } + $readme += @" + +Each squad directory contains a ``SUMMARY.md`` with their latest published state. +State is synchronized using ``sync-mesh.sh`` or ``sync-mesh.ps1``. +"@ + $readme | Set-Content "README.md" + Write-Host " ✓ Created README.md" + } else { + Write-Host " • README.md exists (skipped)" + } + + Write-Host "" + Write-Host "✅ Mesh state repository initialized" + exit 0 +} + +$config = Get-Content $MeshJson -Raw | ConvertFrom-Json + +# Zone 2: Remote-trusted — git clone/pull +foreach ($entry in $config.squads.PSObject.Properties | Where-Object { $_.Value.zone -eq "remote-trusted" }) { + $squad = $entry.Name + $source = $entry.Value.source + $ref = if ($entry.Value.ref) { $entry.Value.ref } else { "main" } + $target = $entry.Value.sync_to + + if (Test-Path "$target/.git") { + git -C $target pull --rebase --quiet 2>$null + if ($LASTEXITCODE -ne 0) { Write-Host "⚠ ${squad}: pull failed (using stale)" } + } else { + New-Item -ItemType Directory -Force -Path (Split-Path $target -Parent) | Out-Null + git clone --quiet --depth 1 --branch $ref $source $target 2>$null + if ($LASTEXITCODE -ne 0) { Write-Host "⚠ ${squad}: clone failed (unavailable)" } + } +} + +# Zone 3: Remote-opaque — fetch published contracts +foreach ($entry in $config.squads.PSObject.Properties | Where-Object { $_.Value.zone -eq "remote-opaque" }) { + $squad = $entry.Name + $source = $entry.Value.source + $target = $entry.Value.sync_to + $auth = $entry.Value.auth + + New-Item -ItemType Directory -Force -Path $target | Out-Null + $params = @{ Uri = $source; OutFile = "$target/SUMMARY.md"; UseBasicParsing = $true } + if ($auth -eq "bearer") { + $tokenVar = ($squad.ToUpper() -replace '-', '_') + "_TOKEN" + $token = [Environment]::GetEnvironmentVariable($tokenVar) + if ($token) { $params.Headers = @{ Authorization = "Bearer $token" } } + } + try { Invoke-WebRequest @params -ErrorAction Stop } + catch { "# ${squad} — unavailable ($(Get-Date))" | Set-Content "$target/SUMMARY.md" } +} + +Write-Host "✓ Mesh sync complete" diff --git a/.copilot/skills/distributed-mesh/sync-mesh.sh b/.copilot/skills/distributed-mesh/sync-mesh.sh new file mode 100644 index 000000000..802fd2d8d --- /dev/null +++ b/.copilot/skills/distributed-mesh/sync-mesh.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# sync-mesh.sh — Materialize remote squad state locally +# +# Reads mesh.json, fetches remote squads into local directories. +# Run before agent reads. No daemon. No service. ~40 lines. +# +# Usage: ./sync-mesh.sh [path-to-mesh.json] +# ./sync-mesh.sh --init [path-to-mesh.json] +# Requires: jq (https://github.com/jqlang/jq), git, curl + +set -euo pipefail + +# Handle --init mode +if [ "${1:-}" = "--init" ]; then + MESH_JSON="${2:-mesh.json}" + + if [ ! -f "$MESH_JSON" ]; then + echo "❌ $MESH_JSON not found" + exit 1 + fi + + echo "🚀 Initializing mesh state repository..." + squads=$(jq -r '.squads | keys[]' "$MESH_JSON") + + # Create squad directories with placeholder SUMMARY.md + for squad in $squads; do + if [ ! -d "$squad" ]; then + mkdir -p "$squad" + echo " ✓ Created $squad/" + else + echo " • $squad/ exists (skipped)" + fi + + if [ ! -f "$squad/SUMMARY.md" ]; then + echo -e "# $squad\n\n_No state published yet._" > "$squad/SUMMARY.md" + echo " ✓ Created $squad/SUMMARY.md" + else + echo " • $squad/SUMMARY.md exists (skipped)" + fi + done + + # Generate root README.md + if [ ! -f "README.md" ]; then + { + echo "# Squad Mesh State Repository" + echo "" + echo "This repository tracks published state from participating squads." + echo "" + echo "## Participating Squads" + echo "" + for squad in $squads; do + zone=$(jq -r ".squads.\"$squad\".zone" "$MESH_JSON") + echo "- **$squad** (Zone: $zone)" + done + echo "" + echo "Each squad directory contains a \`SUMMARY.md\` with their latest published state." + echo "State is synchronized using \`sync-mesh.sh\` or \`sync-mesh.ps1\`." + } > README.md + echo " ✓ Created README.md" + else + echo " • README.md exists (skipped)" + fi + + echo "" + echo "✅ Mesh state repository initialized" + exit 0 +fi + +MESH_JSON="${1:-mesh.json}" + +# Zone 2: Remote-trusted — git clone/pull +for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-trusted") | .key' "$MESH_JSON"); do + source=$(jq -r ".squads.\"$squad\".source" "$MESH_JSON") + ref=$(jq -r ".squads.\"$squad\".ref // \"main\"" "$MESH_JSON") + target=$(jq -r ".squads.\"$squad\".sync_to" "$MESH_JSON") + + if [ -d "$target/.git" ]; then + git -C "$target" pull --rebase --quiet 2>/dev/null \ + || echo "⚠ $squad: pull failed (using stale)" + else + mkdir -p "$(dirname "$target")" + git clone --quiet --depth 1 --branch "$ref" "$source" "$target" 2>/dev/null \ + || echo "⚠ $squad: clone failed (unavailable)" + fi +done + +# Zone 3: Remote-opaque — fetch published contracts +for squad in $(jq -r '.squads | to_entries[] | select(.value.zone == "remote-opaque") | .key' "$MESH_JSON"); do + source=$(jq -r ".squads.\"$squad\".source" "$MESH_JSON") + target=$(jq -r ".squads.\"$squad\".sync_to" "$MESH_JSON") + auth=$(jq -r ".squads.\"$squad\".auth // \"\"" "$MESH_JSON") + + mkdir -p "$target" + auth_flag="" + if [ "$auth" = "bearer" ]; then + token_var="$(echo "${squad}" | tr '[:lower:]-' '[:upper:]_')_TOKEN" + [ -n "${!token_var:-}" ] && auth_flag="--header \"Authorization: Bearer ${!token_var}\"" + fi + + eval curl --silent --fail $auth_flag "$source" -o "$target/SUMMARY.md" 2>/dev/null \ + || echo "# ${squad} — unavailable ($(date))" > "$target/SUMMARY.md" +done + +echo "✓ Mesh sync complete" diff --git a/.squad/skills/git-workflow/SKILL.md b/.copilot/skills/git-workflow/SKILL.md similarity index 100% rename from .squad/skills/git-workflow/SKILL.md rename to .copilot/skills/git-workflow/SKILL.md diff --git a/.copilot/skills/github-multi-account/SKILL.md b/.copilot/skills/github-multi-account/SKILL.md new file mode 100644 index 000000000..0a2158f33 --- /dev/null +++ b/.copilot/skills/github-multi-account/SKILL.md @@ -0,0 +1,95 @@ +--- +name: github-multi-account +description: Detect and set up account-locked gh aliases for multi-account GitHub. The AI reads this skill, detects accounts, asks the user which is personal/work, and runs the setup automatically. +confidence: high +source: https://github.com/tamirdresher/squad-skills/tree/main/plugins/github-multi-account +author: tamirdresher +--- + +# GitHub Multi-Account — AI-Driven Setup + +## When to Activate +When the user has multiple GitHub accounts (check with `gh auth status`). If you see 2+ accounts listed, this skill applies. + +## What to Do (as the AI agent) + +### Step 1: Detect accounts +Run: `gh auth status` +Look for multiple accounts. Note which usernames are listed. + +### Step 2: Ask the user +Ask: "I see you have multiple GitHub accounts: {list them}. Which one is your personal account and which is your work/EMU account?" + +### Step 3: Run the setup automatically +Once the user confirms, do ALL of this for them: + +```powershell +# 1. Define the functions +$personal = "THEIR_PERSONAL_USERNAME" +$work = "THEIR_WORK_USERNAME" + +# 2. Add to PowerShell profile +$profilePath = $PROFILE.CurrentUserAllHosts +if (!(Test-Path $profilePath)) { New-Item -Path $profilePath -Force | Out-Null } +$existing = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue +if ($existing -notmatch "gh-personal") { + $block = @" + +# === GitHub Multi-Account Aliases === +function gh-personal { gh auth switch --user $personal 2>`$null | Out-Null; gh @args } +function gh-work { gh auth switch --user $work 2>`$null | Out-Null; gh @args } +Set-Alias ghp gh-personal +Set-Alias ghw gh-work +"@ + Add-Content -Path $profilePath -Value $block +} + +# 3. Create CMD wrappers +$binDir = Join-Path $env:USERPROFILE ".squad\bin" +if (!(Test-Path $binDir)) { New-Item -ItemType Directory -Path $binDir -Force | Out-Null } +"@echo off`ngh auth switch --user $personal >nul 2>&1`ngh %*" | Out-File "$binDir\ghp.cmd" -Encoding ascii +"@echo off`ngh auth switch --user $work >nul 2>&1`ngh %*" | Out-File "$binDir\ghw.cmd" -Encoding ascii + +# 4. Add to PATH +$userPath = [Environment]::GetEnvironmentVariable("PATH", "User") +if ($userPath -notmatch [regex]::Escape($binDir)) { + [Environment]::SetEnvironmentVariable("PATH", "$binDir;$userPath", "User") + $env:PATH = "$binDir;$env:PATH" +} + +# 5. Load in current session +function gh-personal { gh auth switch --user $personal 2>$null | Out-Null; gh @args } +function gh-work { gh auth switch --user $work 2>$null | Out-Null; gh @args } +Set-Alias ghp gh-personal +Set-Alias ghw gh-work +``` + +### Step 4: Verify for the user +Run these and show the results: +```powershell +ghp api user --jq '.login' # should show personal username +ghw api user --jq '.login' # should show work username +``` + +### Step 5: Tell the user +"All set! From now on use `ghp` for personal repos and `ghw` for work repos. I'll use them too." + +## After Setup — Usage Rules + +1. **NEVER** use bare `gh` for repo operations — always `ghp` or `ghw` +2. **NEVER** manually `gh auth switch` — the aliases handle it +3. Determine alias by repo owner: + - Personal account repos → `ghp` / `gh-personal` + - Work/EMU account repos → `ghw` / `gh-work` + +## Repo-Specific Account Binding + +This repo (`bradygaster/squad`) is bound to the **bradygaster** (personal) account. +All `gh` operations in this repo MUST use `ghp` / `gh-personal`. + +## For Squad Agents +At the TOP of any script touching GitHub, define: +```powershell +function gh-personal { gh auth switch --user bradygaster 2>$null | Out-Null; gh @args } +function gh-work { gh auth switch --user bradyg_microsoft 2>$null | Out-Null; gh @args } +``` diff --git a/.squad/skills/history-hygiene/SKILL.md b/.copilot/skills/history-hygiene/SKILL.md similarity index 100% rename from .squad/skills/history-hygiene/SKILL.md rename to .copilot/skills/history-hygiene/SKILL.md diff --git a/.squad/skills/init-mode/SKILL.md b/.copilot/skills/init-mode/SKILL.md similarity index 96% rename from .squad/skills/init-mode/SKILL.md rename to .copilot/skills/init-mode/SKILL.md index cefddc415..4dce6628c 100644 --- a/.squad/skills/init-mode/SKILL.md +++ b/.copilot/skills/init-mode/SKILL.md @@ -26,7 +26,7 @@ No team exists yet. Propose one — but **DO NOT create any files until the user - Determine team size (typically 4–5 + Scribe). - Determine assignment shape from the user's project description. - Derive resonance signals from the session and repo context. - - Select a universe. Allocate character names from that universe. + - Select a universe. If the universe is custom, allocate character names from that universe based on the related list found in the `.squad/templates/casting/` directory. Prefer custom universes when available. - Scribe is always "Scribe" — exempt from casting. - Ralph is always "Ralph" — exempt from casting. 4. Propose the team with their cast names. Example (names will vary per cast): diff --git a/.copilot/skills/model-selection/SKILL.md b/.copilot/skills/model-selection/SKILL.md new file mode 100644 index 000000000..611941bab --- /dev/null +++ b/.copilot/skills/model-selection/SKILL.md @@ -0,0 +1,143 @@ +--- +name: "model-selection" +description: "Per-agent model selection with 4-layer hierarchy and fallback chains" +domain: "orchestration" +confidence: "high" +source: "extracted" +--- + +## Context + +Before spawning an agent, the coordinator determines which model to use. This skill codifies the 4-layer hierarchy, role-to-model mappings, task complexity adjustments, and fallback chains. Applies to all agent spawns in Team Mode. + +## Patterns + +### 4-Layer Hierarchy + +Check these layers in order — first match wins: + +**Layer 1 — User Override:** Did the user specify a model? ("use opus", "save costs", "use gpt-5.2-codex for this"). If yes, use that model. Session-wide directives ("always use haiku") persist until contradicted. + +**Layer 2 — Charter Preference:** Does the agent's charter have a `## Model` section with `Preferred` set to a specific model (not `auto`)? If yes, use that model. + +**Layer 3 — Task-Aware Auto-Selection:** Use the governing principle: **cost first, unless code is being written.** Match the agent's task to determine output type, then select accordingly: + +| Task Output | Model | Tier | Rule | +|-------------|-------|------|------| +| Writing code (implementation, refactoring, test code, bug fixes) | `claude-sonnet-4.6` | Standard | Quality and accuracy matter for code. Use standard tier. | +| Writing prompts or agent designs (structured text that functions like code) | `claude-sonnet-4.6` | Standard | Prompts are executable — treat like code. | +| NOT writing code (docs, planning, triage, logs, changelogs, mechanical ops) | `claude-haiku-4.5` | Fast | Cost first. Haiku handles non-code tasks. | +| Visual/design work requiring image analysis | `claude-opus-4.5` | Premium | Vision capability required. Overrides cost rule. | + +**Role-to-model mapping** (applying cost-first principle): + +| Role | Default Model | Why | Override When | +|------|--------------|-----|---------------| +| Core Dev / Backend / Frontend | `claude-sonnet-4.6` | Writes code — quality first | Heavy code gen → `gpt-5.3-codex` | +| Tester / QA | `claude-sonnet-4.6` | Writes test code — quality first | Simple test scaffolding → `claude-haiku-4.5` | +| Lead / Architect | auto (per-task) | Mixed: code review needs quality, planning needs cost | Architecture proposals → premium; triage/planning → haiku | +| Prompt Engineer | auto (per-task) | Mixed: prompt design is like code, research is not | Prompt architecture → sonnet; research/analysis → haiku | +| Copilot SDK Expert | `claude-sonnet-4.6` | Technical analysis that often touches code | Pure research → `claude-haiku-4.5` | +| Designer / Visual | `claude-opus-4.6` | Vision-capable model required | — (never downgrade — vision is non-negotiable) | +| DevRel / Writer | `claude-haiku-4.5` | Docs and writing — not code | — | +| Scribe / Logger | `claude-haiku-4.5` | Mechanical file ops — cheapest possible | — (never bump Scribe) | +| Git / Release | `claude-haiku-4.5` | Mechanical ops — changelogs, tags, version bumps | — (never bump mechanical ops) | + +**Task complexity adjustments** (apply at most ONE — no cascading): +- **Bump UP to premium:** architecture proposals, reviewer gates, security audits, multi-agent coordination (output feeds 3+ agents) +- **Bump DOWN to fast/cheap:** typo fixes, renames, boilerplate, scaffolding, changelogs, version bumps +- **Switch to code specialist (`gpt-5.3-codex`):** large multi-file refactors, complex implementation from spec, heavy code generation (500+ lines) +- **Switch to analytical diversity (`gemini-3-pro-preview`):** code reviews where a second perspective helps, security reviews, architecture reviews after a rejection + +**Layer 4 — Default:** If nothing else matched, use `claude-haiku-4.5`. Cost wins when in doubt, unless code is being produced. + +### Fallback Chains + +If a spawn fails because the selected model is unavailable (plan restriction, org policy, rate limit, deprecation, or any other reason), silently retry with the next model in the chain. Do NOT tell the user about fallback attempts. Maximum 3 retries before jumping to the nuclear fallback. + +``` +Premium: claude-opus-4.6 → claude-opus-4.6-fast → claude-opus-4.5 → claude-sonnet-4.6 → (omit model param) +Standard: claude-sonnet-4.6 → gpt-5.4 → claude-sonnet-4.5 → gpt-5.3-codex → claude-sonnet-4 → (omit model param) +Fast: claude-haiku-4.5 → gpt-5.1-codex-mini → gpt-4.1 → gpt-5-mini → (omit model param) +``` + +`(omit model param)` = call the `task` tool WITHOUT the `model` parameter. The platform uses its built-in default. This is the nuclear fallback — it always works. + +**Fallback rules:** +- If the user specified a provider ("use Claude"), fall back within that provider only before hitting nuclear +- Never fall back UP in tier — a fast/cheap task should not land on a premium model +- Log fallbacks to the orchestration log for debugging, but never surface to the user unless asked + +### Passing the Model to Spawns + +Pass the resolved model as the `model` parameter on every `task` tool call: + +``` +agent_type: "general-purpose" +model: "{resolved_model}" +mode: "background" +description: "{emoji} {Name}: {brief task summary}" +prompt: | + ... +``` + +Only set `model` when it differs from the platform default (`claude-sonnet-4.6`). If the resolved model IS `claude-sonnet-4.6`, you MAY omit the `model` parameter — the platform uses it as default. + +If you've exhausted the fallback chain and reached nuclear fallback, omit the `model` parameter entirely. + +### Spawn Output Format + +When spawning, include the model in your acknowledgment: + +``` +🔧 Fenster (claude-sonnet-4.6) — refactoring auth module +🎨 Redfoot (claude-opus-4.6 · vision) — designing color system +📋 Scribe (claude-haiku-4.5 · fast) — logging session +⚡ Keaton (claude-opus-4.6 · bumped for architecture) — reviewing proposal +📝 McManus (claude-haiku-4.5 · fast) — updating docs +``` + +Include tier annotation only when the model was bumped or a specialist was chosen. Default-tier spawns just show the model name. + +### Valid Models + +**Premium:** `claude-opus-4.6`, `claude-opus-4.6-fast`, `claude-opus-4.5` +**Standard:** `claude-sonnet-4.6`, `claude-sonnet-4.5`, `claude-sonnet-4`, `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.2`, `gpt-5.1-codex-max`, `gpt-5.1-codex`, `gpt-5.1`, `gpt-5`, `gemini-3-pro-preview` +**Fast/Cheap:** `claude-haiku-4.5`, `gpt-5.1-codex-mini`, `gpt-5-mini`, `gpt-4.1` + +## Examples + +**Example 1: Backend dev writing API endpoints** +- Role: Backend Dev +- Task: "implement REST endpoints for user management" +- Layer 3 decision: writing code → `claude-sonnet-4.6` (standard tier) +- Spawn: `🔧 Fenster (claude-sonnet-4.6) — implementing user API endpoints` + +**Example 2: User override** +- User says: "use haiku for everything this session" +- Layer 1 overrides all other layers +- All spawns use `claude-haiku-4.5` regardless of role or task + +**Example 3: Complex refactor** +- Role: Backend Dev +- Task: "refactor 15 auth-related files to use new token system" +- Layer 3 base: `claude-sonnet-4.5` +- Task complexity: heavy multi-file refactor → switch to `gpt-5.2-codex` +- Spawn: `🔧 Fenster (gpt-5.2-codex · code specialist) — refactoring auth to new token system` + +**Example 4: Scribe logging** +- Role: Scribe +- Task: "log session to decisions.md" +- Layer 3: NOT writing code → `claude-haiku-4.5` +- Role mapping: Scribe always haiku, never bump +- Spawn: `📋 Scribe (claude-haiku-4.5 · fast) — logging session` + +## Anti-Patterns + +- ❌ Falling back UP in tier (fast task landing on premium model) +- ❌ Telling the user about fallback attempts ("Opus failed, trying Sonnet") +- ❌ Bumping Scribe or mechanical ops agents to higher tiers +- ❌ Using premium models for documentation or planning tasks +- ❌ Applying multiple complexity adjustments (cascading bumps) +- ❌ Forgetting to include model in spawn acknowledgment +- ❌ Downgrading vision-required tasks from opus diff --git a/.squad/skills/release-process/SKILL.md b/.copilot/skills/release-process/SKILL.md similarity index 100% rename from .squad/skills/release-process/SKILL.md rename to .copilot/skills/release-process/SKILL.md diff --git a/.copilot/skills/reskill/SKILL.md b/.copilot/skills/reskill/SKILL.md new file mode 100644 index 000000000..ab6571010 --- /dev/null +++ b/.copilot/skills/reskill/SKILL.md @@ -0,0 +1,92 @@ +--- +name: "reskill" +description: "Team-wide charter and history optimization through skill extraction" +domain: "team-optimization" +confidence: "high" +source: "manual — Brady directive to reduce per-agent context overhead" +--- + +## Context + +When the coordinator hears "team, reskill" (or similar: "optimize context", "slim down charters"), trigger a team-wide optimization pass. The goal: reduce per-agent context consumption by extracting shared patterns from charters and histories into reusable skills. + +This is a periodic maintenance activity. Run whenever charter/history bloat is suspected. + +## Process + +### Step 1: Audit +Read all agent charters and histories. Measure byte sizes. Identify: + +- **Boilerplate** — sections repeated across ≥3 charters with <10% variation (collaboration, model, boundaries template) +- **Shared knowledge** — domain knowledge duplicated in 2+ charters (incident postmortems, technical patterns) +- **Mature learnings** — history entries appearing 3+ times across agents that should be promoted to skills + +### Step 2: Extract +For each identified pattern: +1. Create or update a skill at `.copilot/skills/{skill-name}/SKILL.md` +2. Follow the skill template format (frontmatter + Context + Patterns + Examples + Anti-Patterns) +3. Set confidence: low (first observation), medium (2+ agents), high (team-wide) + +### Step 3: Trim +**Charters** — target ≤1.5KB per agent: +- Remove Collaboration section entirely (spawn prompt + agent-collaboration skill covers it) +- Remove Voice section (tagline blockquote at top of charter already captures it) +- Trim Model section to single line: `Preferred: {model}` +- Remove "When I'm unsure" boilerplate from Boundaries +- Remove domain knowledge now covered by a skill — add skill reference comment if helpful +- Keep: Identity, What I Own, unique How I Work patterns, Boundaries (domain list only) + +**Histories** — target ≤8KB per agent: +- Apply history-hygiene skill to any history >12KB +- Promote recurring patterns (3+ occurrences across agents) to skills +- Summarize old entries into `## Core Context` section +- Remove session-specific metadata (dates, branch names, requester names) + +### Step 4: Report +Output a savings table: + +| Agent | Charter Before | Charter After | History Before | History After | Saved | +|-------|---------------|---------------|----------------|---------------|-------| + +Include totals and percentage reduction. + +## Patterns + +### Minimal Charter Template (target format after reskill) + +``` +# {Name} — {Role} + +> {Tagline — one sentence capturing voice and philosophy} + +## Identity +- **Name:** {Name} +- **Role:** {Role} +- **Expertise:** {comma-separated list} + +## What I Own +- {bullet list of owned artifacts/domains} + +## How I Work +- {unique patterns and principles — NOT boilerplate} + +## Boundaries +**I handle:** {domain list} +**I don't handle:** {explicit exclusions} + +## Model +Preferred: {model} +``` + +### Skill Extraction Threshold +- **1 charter** → leave in charter (unique to that agent) +- **2 charters** → consider extracting if >500 bytes of overlap +- **3+ charters** → always extract to a shared skill + +## Anti-Patterns +- Don't delete unique per-agent identity or domain-specific knowledge +- Don't create skills for content only one agent uses +- Don't merge unrelated patterns into a single mega-skill +- Don't remove Model preference line (coordinator needs it for model selection) +- Don't touch `.squad/decisions.md` during reskill +- Don't remove the tagline blockquote — it's the charter's soul in one line diff --git a/.squad/skills/reviewer-protocol/SKILL.md b/.copilot/skills/reviewer-protocol/SKILL.md similarity index 100% rename from .squad/skills/reviewer-protocol/SKILL.md rename to .copilot/skills/reviewer-protocol/SKILL.md diff --git a/.squad/skills/secret-handling/SKILL.md b/.copilot/skills/secret-handling/SKILL.md similarity index 100% rename from .squad/skills/secret-handling/SKILL.md rename to .copilot/skills/secret-handling/SKILL.md diff --git a/.copilot/skills/squad-conventions/SKILL.md b/.copilot/skills/squad-conventions/SKILL.md new file mode 100644 index 000000000..eae1d1f6e --- /dev/null +++ b/.copilot/skills/squad-conventions/SKILL.md @@ -0,0 +1,69 @@ +--- +name: "squad-conventions" +description: "Core conventions and patterns used in the Squad codebase" +domain: "project-conventions" +confidence: "high" +source: "manual" +--- + +## Context +These conventions apply to all work on the Squad CLI tool (`create-squad`). Squad is a zero-dependency Node.js package that adds AI agent teams to any project. Understanding these patterns is essential before modifying any Squad source code. + +## Patterns + +### Zero Dependencies +Squad has zero runtime dependencies. Everything uses Node.js built-ins (`fs`, `path`, `os`, `child_process`). Do not add packages to `dependencies` in `package.json`. This is a hard constraint, not a preference. + +### Node.js Built-in Test Runner +Tests use `node:test` and `node:assert/strict` — no test frameworks. Run with `npm test`. Test files live in `test/`. The test command is `node --test test/`. + +### Error Handling — `fatal()` Pattern +All user-facing errors use the `fatal(msg)` function which prints a red `✗` prefix and exits with code 1. Never throw unhandled exceptions or print raw stack traces. The global `uncaughtException` handler calls `fatal()` as a safety net. + +### ANSI Color Constants +Colors are defined as constants at the top of `index.js`: `GREEN`, `RED`, `DIM`, `BOLD`, `RESET`. Use these constants — do not inline ANSI escape codes. + +### File Structure +- `.squad/` — Team state (user-owned, never overwritten by upgrades) +- `.squad/templates/` — Template files copied from `templates/` (Squad-owned, overwritten on upgrade) +- `.github/agents/squad.agent.md` — Coordinator prompt (Squad-owned, overwritten on upgrade) +- `templates/` — Source templates shipped with the npm package +- `.copilot/skills/` — Team skills in SKILL.md format (user-owned) +- `.squad/decisions/inbox/` — Drop-box for parallel decision writes + +### Windows Compatibility +Always use `path.join()` for file paths — never hardcode `/` or `\` separators. Squad must work on Windows, macOS, and Linux. All tests must pass on all platforms. + +### Init Idempotency +The init flow uses a skip-if-exists pattern: if a file or directory already exists, skip it and report "already exists." Never overwrite user state during init. The upgrade flow overwrites only Squad-owned files. + +### Copy Pattern +`copyRecursive(src, target)` handles both files and directories. It creates parent directories with `{ recursive: true }` and uses `fs.copyFileSync` for files. + +## Examples + +```javascript +// Error handling +function fatal(msg) { + console.error(`${RED}✗${RESET} ${msg}`); + process.exit(1); +} + +// File path construction (Windows-safe) +const agentDest = path.join(dest, '.github', 'agents', 'squad.agent.md'); + +// Skip-if-exists pattern +if (!fs.existsSync(ceremoniesDest)) { + fs.copyFileSync(ceremoniesSrc, ceremoniesDest); + console.log(`${GREEN}✓${RESET} .squad/ceremonies.md`); +} else { + console.log(`${DIM}ceremonies.md already exists — skipping${RESET}`); +} +``` + +## Anti-Patterns +- **Adding npm dependencies** — Squad is zero-dep. Use Node.js built-ins only. +- **Hardcoded path separators** — Never use `/` or `\` directly. Always `path.join()`. +- **Overwriting user state on init** — Init skips existing files. Only upgrade overwrites Squad-owned files. +- **Raw stack traces** — All errors go through `fatal()`. Users see clean messages, not stack traces. +- **Inline ANSI codes** — Use the color constants (`GREEN`, `RED`, `DIM`, `BOLD`, `RESET`). diff --git a/.github/agents/squad.agent.md b/.github/agents/squad.agent.md index a42f2ec0a..12f47139c 100644 --- a/.github/agents/squad.agent.md +++ b/.github/agents/squad.agent.md @@ -27,16 +27,69 @@ Check: Does `.squad/team.md` exist? (fall back to `.ai-team/team.md` for repos m --- -## Init Mode +## Init Mode — Phase 1: Propose the Team -**Skill:** Read `.squad/skills/init-mode/SKILL.md` when entering Init Mode (team.md missing or empty). +No team exists yet. Propose one — but **DO NOT create any files until the user confirms.** -**Core rules (always loaded):** -- Phase 1: Propose team → use `ask_user` → **STOP** and wait for confirmation -- Phase 2 trigger: User confirms OR user gives a task (implicit yes) -- Phase 2: Create `.squad/` structure, initialize casting state, seed agents -- **`## Members`** header is required (not "Team Roster") — GitHub workflows depend on it -- Never read or store `git config user.email` (PII violation) +1. **Identify the user.** Run `git config user.name` to learn who you're working with. Use their name in conversation (e.g., *"Hey Brady, what are you building?"*). Store their name (NOT email) in `team.md` under Project Context. **Never read or store `git config user.email` — email addresses are PII and must not be written to committed files.** +2. Ask: *"What are you building? (language, stack, what it does)"* +3. **Cast the team.** Before proposing names, run the Casting & Persistent Naming algorithm (see that section): + - Determine team size (typically 4–5 + Scribe). + - Determine assignment shape from the user's project description. + - Derive resonance signals from the session and repo context. + - Select a universe. Allocate character names from that universe. + - Scribe is always "Scribe" — exempt from casting. + - Ralph is always "Ralph" — exempt from casting. +4. Propose the team with their cast names. Example (names will vary per cast): + +``` +🏗️ {CastName1} — Lead Scope, decisions, code review +⚛️ {CastName2} — Frontend Dev React, UI, components +🔧 {CastName3} — Backend Dev APIs, database, services +🧪 {CastName4} — Tester Tests, quality, edge cases +📋 Scribe — (silent) Memory, decisions, session logs +🔄 Ralph — (monitor) Work queue, backlog, keep-alive +``` + +5. Use the `ask_user` tool to confirm the roster. Provide choices so the user sees a selectable menu: + - **question:** *"Look right?"* + - **choices:** `["Yes, hire this team", "Add someone", "Change a role"]` + +**⚠️ STOP. Your response ENDS here. Do NOT proceed to Phase 2. Do NOT create any files or directories. Wait for the user's reply.** + +--- + +## Init Mode — Phase 2: Create the Team + +**Trigger:** The user replied to Phase 1 with confirmation ("yes", "looks good", or similar affirmative), OR the user's reply to Phase 1 is a task (treat as implicit "yes"). + +> If the user said "add someone" or "change a role," go back to Phase 1 step 3 and re-propose. Do NOT enter Phase 2 until the user confirms. + +6. Create the `.squad/` directory structure (see `.squad/templates/` for format guides or use the standard structure: team.md, routing.md, ceremonies.md, decisions.md, decisions/inbox/, casting/, agents/, orchestration-log/, skills/, log/). + +**Casting state initialization:** Copy `.squad/templates/casting-policy.json` to `.squad/casting/policy.json` (or create from defaults). Create `registry.json` (entries: persistent_name, universe, created_at, legacy_named: false, status: "active") and `history.json` (first assignment snapshot with unique assignment_id). + +**Seeding:** Each agent's `history.md` starts with the project description, tech stack, and the user's name so they have day-1 context. Agent folder names are the cast name in lowercase (e.g., `.squad/agents/ripley/`). The Scribe's charter includes maintaining `decisions.md` and cross-agent context sharing. + +**Team.md structure:** `team.md` MUST contain a section titled exactly `## Members` (not "## Team Roster" or other variations) containing the roster table. This header is hard-coded in GitHub workflows (`squad-heartbeat.yml`, `squad-issue-assign.yml`, `squad-triage.yml`, `sync-squad-labels.yml`) for label automation. If the header is missing or titled differently, label routing breaks. + +**Merge driver for append-only files:** Create or update `.gitattributes` at the repo root to enable conflict-free merging of `.squad/` state across branches: +``` +.squad/decisions.md merge=union +.squad/agents/*/history.md merge=union +.squad/log/** merge=union +.squad/orchestration-log/** merge=union +``` +The `union` merge driver keeps all lines from both sides, which is correct for append-only files. This makes worktree-local strategy work seamlessly when branches merge — decisions, memories, and logs from all branches combine automatically. + +7. Say: *"✅ Team hired. Try: '{FirstCastName}, set up the project structure'"* + +8. **Post-setup input sources** (optional — ask after team is created, not during casting): + - PRD/spec: *"Do you have a PRD or spec document? (file path, paste it, or skip)"* → If provided, follow PRD Mode flow + - GitHub issues: *"Is there a GitHub repo with issues I should pull from? (owner/repo, or skip)"* → If provided, follow GitHub Issues Mode flow + - Human members: *"Are any humans joining the team? (names and roles, or just AI for now)"* → If provided, add per Human Team Members section + - Copilot agent: *"Want to include @copilot? It can pick up issues autonomously. (yes/no)"* → If yes, follow Copilot Coding Agent Member section and ask about auto-assignment + - These are additive. Don't block — if the user skips or gives a task instead, proceed immediately. --- @@ -59,31 +112,30 @@ When triggered: **Casting migration check:** If `.squad/team.md` exists but `.squad/casting/` does not, perform the migration described in "Casting & Persistent Naming → Migration — Already-Squadified Repos" before proceeding. -### SDK Mode Detection +### Personal Squad (Ambient Discovery) -**On session start**, detect SDK mode: check if a `squad/` directory (TypeScript source) or `squad.config.ts` exists at the project root. If either is present, SDK mode is active. +Before assembling the session cast, check for personal agents: -**When SDK mode is active:** -1. **Edit redirection** — structural changes (agent charters, team config, routing rules) target `squad/*.ts` source files, NOT `.squad/*.md`. The `.squad/` directory is generated output. -2. **Build reminder** — after any agent modifies files under `squad/*.ts`, append: _"Run `squad build` to regenerate `.squad/` from source."_ -3. **Config source** — typed config from `defineAgent()` / `defineSquad()` provides richer agent metadata (skills, capabilities, model preferences). Prefer it over markdown parsing when available. +1. **Kill switch check:** If `SQUAD_NO_PERSONAL` is set, skip personal agent discovery entirely. +2. **Resolve personal dir:** Call `resolvePersonalSquadDir()` — returns the user's personal squad path or null. +3. **Discover personal agents:** If personal dir exists, scan `{personalDir}/agents/` for charter.md files. +4. **Merge into cast:** Personal agents are additive — they don't replace project agents. On name conflict, project agent wins. +5. **Apply Ghost Protocol:** All personal agents operate under Ghost Protocol (read-only project state, no direct file edits, transparent origin tagging). -**Principle:** SDK mode *extends* markdown mode — generated `.squad/` files remain the runtime format. The SDK adds a typed authoring layer on top. +**Spawn personal agents with:** +- Charter from personal dir (not project) +- Ghost Protocol rules appended to system prompt +- `origin: 'personal'` tag in all log entries +- Consult mode: personal agents advise, project agents execute ### Issue Awareness -**On every session start (after resolving team root):** Check for open issues/work items assigned to squad members. Detect the platform first: +**On every session start (after resolving team root):** Check for open GitHub issues assigned to squad members via labels. Use the GitHub CLI or API to list issues with `squad:*` labels: -**GitHub:** Use `gh` CLI or GitHub MCP tools: ``` gh issue list --label "squad:{member-name}" --state open --json number,title,labels,body --limit 10 ``` -**Azure DevOps:** Read `.squad/config.json` for `ado.org`/`ado.project`, then use WIQL: -``` -az boards query --wiql "SELECT [System.Id],[System.Title],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:{member-name}' AND [System.State] <> 'Closed' AND [System.TeamProject] = '{project}'" --org "https://dev.azure.com/{org}" --project "{project}" --output json -``` - For each squad member with assigned issues, note them in the session context. When presenting a catch-up or when the user asks for status, include pending issues: ``` @@ -180,6 +232,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | Signal | Action | |--------|--------| | Names someone ("Ripley, fix the button") | Spawn that agent | +| Personal agent by name (user addresses a personal agent) | Route to personal agent in consult mode — they advise, project agent executes changes | | "Team" or multi-domain question | Spawn 2-3+ relevant agents in parallel, synthesize | | Human member management ("add Brady as PM", routes to human) | Follow Human Team Members (see that section) | | Issue suitable for @copilot (when @copilot is on the roster) | Check capability profile in team.md, suggest routing to @copilot if it's a good fit | @@ -195,6 +248,14 @@ The routing table determines **WHO** handles work. After routing, use Response M **Skill-aware routing:** Before spawning, check `.squad/skills/` for skills relevant to the task domain. If a matching skill exists, add to the spawn prompt: `Relevant skill: .squad/skills/{name}/SKILL.md — read before starting.` This makes earned knowledge an input to routing, not passive documentation. +### Consult Mode Detection + +When a user addresses a personal agent by name: +1. Route the request to the personal agent +2. Tag the interaction as consult mode +3. If the personal agent recommends changes, hand off execution to the appropriate project agent +4. Log: `[consult] {personal-agent} → {project-agent}: {handoff summary}` + ### Skill Confidence Lifecycle Skills use a three-level confidence model. Confidence only goes up, never down. @@ -257,7 +318,13 @@ description: "{emoji} {Name}: {brief task summary}" prompt: | You are {Name}, the {Role} on this project. TEAM ROOT: {team_root} + WORKTREE_PATH: {worktree_path} + WORKTREE_MODE: {true|false} **Requested by:** {current user name} + + {% if WORKTREE_MODE %} + **WORKTREE:** Working in `{WORKTREE_PATH}`. All operations relative to this path. Do NOT switch branches. + {% endif %} TASK: {specific task description} TARGET FILE(S): {exact file path(s)} @@ -273,24 +340,147 @@ For read-only queries, use the explore agent: `agent_type: "explore"` with `"You ### Per-Agent Model Selection -**Skill:** Read `.squad/skills/model-selection/SKILL.md` before spawning any agent. +Before spawning an agent, determine which model to use. Check these layers in order — first match wins: -**Core rules (always loaded):** -- 4-layer hierarchy: User Override → Charter Preference → Task-Aware Auto → Default (haiku) -- Governing principle: **cost first, unless code is being written** -- Code tasks → `claude-sonnet-4.5` (standard), non-code → `claude-haiku-4.5` (fast) -- Fallback chains: silently retry within tier, never fall UP, log but don't surface to user -- Always include model in spawn acknowledgment: `🔧 Fenster (claude-sonnet-4.5) — task` +**Layer 0 — Persistent Config (`.squad/config.json`):** On session start, read `.squad/config.json`. If `agentModelOverrides.{agentName}` exists, use that model for this specific agent. Otherwise, if `defaultModel` exists, use it for ALL agents. This layer survives across sessions — the user set it once and it sticks. + +- **When user says "always use X" / "use X for everything" / "default to X":** Write `defaultModel` to `.squad/config.json`. Acknowledge: `✅ Model preference saved: {model} — all future sessions will use this until changed.` +- **When user says "use X for {agent}":** Write to `agentModelOverrides.{agent}` in `.squad/config.json`. Acknowledge: `✅ {Agent} will always use {model} — saved to config.` +- **When user says "switch back to automatic" / "clear model preference":** Remove `defaultModel` (and optionally `agentModelOverrides`) from `.squad/config.json`. Acknowledge: `✅ Model preference cleared — returning to automatic selection.` + +**Layer 1 — Session Directive:** Did the user specify a model for this session? ("use opus for this session", "save costs"). If yes, use that model. Session-wide directives persist until the session ends or contradicted. + +**Layer 2 — Charter Preference:** Does the agent's charter have a `## Model` section with `Preferred` set to a specific model (not `auto`)? If yes, use that model. + +**Layer 3 — Task-Aware Auto-Selection:** Use the governing principle: **cost first, unless code is being written.** Match the agent's task to determine output type, then select accordingly: + +| Task Output | Model | Tier | Rule | +|-------------|-------|------|------| +| Writing code (implementation, refactoring, test code, bug fixes) | `claude-sonnet-4.5` | Standard | Quality and accuracy matter for code. Use standard tier. | +| Writing prompts or agent designs (structured text that functions like code) | `claude-sonnet-4.5` | Standard | Prompts are executable — treat like code. | +| NOT writing code (docs, planning, triage, logs, changelogs, mechanical ops) | `claude-haiku-4.5` | Fast | Cost first. Haiku handles non-code tasks. | +| Visual/design work requiring image analysis | `claude-opus-4.5` | Premium | Vision capability required. Overrides cost rule. | + +**Role-to-model mapping** (applying cost-first principle): + +| Role | Default Model | Why | Override When | +|------|--------------|-----|---------------| +| Core Dev / Backend / Frontend | `claude-sonnet-4.5` | Writes code — quality first | Heavy code gen → `gpt-5.2-codex` | +| Tester / QA | `claude-sonnet-4.5` | Writes test code — quality first | Simple test scaffolding → `claude-haiku-4.5` | +| Lead / Architect | auto (per-task) | Mixed: code review needs quality, planning needs cost | Architecture proposals → premium; triage/planning → haiku | +| Prompt Engineer | auto (per-task) | Mixed: prompt design is like code, research is not | Prompt architecture → sonnet; research/analysis → haiku | +| Copilot SDK Expert | `claude-sonnet-4.5` | Technical analysis that often touches code | Pure research → `claude-haiku-4.5` | +| Designer / Visual | `claude-opus-4.5` | Vision-capable model required | — (never downgrade — vision is non-negotiable) | +| DevRel / Writer | `claude-haiku-4.5` | Docs and writing — not code | — | +| Scribe / Logger | `claude-haiku-4.5` | Mechanical file ops — cheapest possible | — (never bump Scribe) | +| Git / Release | `claude-haiku-4.5` | Mechanical ops — changelogs, tags, version bumps | — (never bump mechanical ops) | + +**Task complexity adjustments** (apply at most ONE — no cascading): +- **Bump UP to premium:** architecture proposals, reviewer gates, security audits, multi-agent coordination (output feeds 3+ agents) +- **Bump DOWN to fast/cheap:** typo fixes, renames, boilerplate, scaffolding, changelogs, version bumps +- **Switch to code specialist (`gpt-5.2-codex`):** large multi-file refactors, complex implementation from spec, heavy code generation (500+ lines) +- **Switch to analytical diversity (`gemini-3-pro-preview`):** code reviews where a second perspective helps, security reviews, architecture reviews after a rejection + +**Layer 4 — Default:** If nothing else matched, use `claude-haiku-4.5`. Cost wins when in doubt, unless code is being produced. + +**Fallback chains — when a model is unavailable:** + +If a spawn fails because the selected model is unavailable (plan restriction, org policy, rate limit, deprecation, or any other reason), silently retry with the next model in the chain. Do NOT tell the user about fallback attempts. Maximum 3 retries before jumping to the nuclear fallback. + +``` +Premium: claude-opus-4.6 → claude-opus-4.6-fast → claude-opus-4.5 → claude-sonnet-4.5 → (omit model param) +Standard: claude-sonnet-4.5 → gpt-5.2-codex → claude-sonnet-4 → gpt-5.2 → (omit model param) +Fast: claude-haiku-4.5 → gpt-5.1-codex-mini → gpt-4.1 → gpt-5-mini → (omit model param) +``` + +`(omit model param)` = call the `task` tool WITHOUT the `model` parameter. The platform uses its built-in default. This is the nuclear fallback — it always works. + +**Fallback rules:** +- If the user specified a provider ("use Claude"), fall back within that provider only before hitting nuclear +- Never fall back UP in tier — a fast/cheap task should not land on a premium model +- Log fallbacks to the orchestration log for debugging, but never surface to the user unless asked + +**Passing the model to spawns:** + +Pass the resolved model as the `model` parameter on every `task` tool call: + +``` +agent_type: "general-purpose" +model: "{resolved_model}" +mode: "background" +description: "{emoji} {Name}: {brief task summary}" +prompt: | + ... +``` + +Only set `model` when it differs from the platform default (`claude-sonnet-4.5`). If the resolved model IS `claude-sonnet-4.5`, you MAY omit the `model` parameter — the platform uses it as default. + +If you've exhausted the fallback chain and reached nuclear fallback, omit the `model` parameter entirely. + +**Spawn output format — show the model choice:** + +When spawning, include the model in your acknowledgment: + +``` +🔧 Fenster (claude-sonnet-4.5) — refactoring auth module +🎨 Redfoot (claude-opus-4.5 · vision) — designing color system +📋 Scribe (claude-haiku-4.5 · fast) — logging session +⚡ Keaton (claude-opus-4.6 · bumped for architecture) — reviewing proposal +📝 McManus (claude-haiku-4.5 · fast) — updating docs +``` + +Include tier annotation only when the model was bumped or a specialist was chosen. Default-tier spawns just show the model name. + +**Valid models (current platform catalog):** + +Premium: `claude-opus-4.6`, `claude-opus-4.6-fast`, `claude-opus-4.5` +Standard: `claude-sonnet-4.5`, `claude-sonnet-4`, `gpt-5.2-codex`, `gpt-5.2`, `gpt-5.1-codex-max`, `gpt-5.1-codex`, `gpt-5.1`, `gpt-5`, `gemini-3-pro-preview` +Fast/Cheap: `claude-haiku-4.5`, `gpt-5.1-codex-mini`, `gpt-5-mini`, `gpt-4.1` ### Client Compatibility -**Skill:** Read `.squad/skills/client-compatibility/SKILL.md` for platform detection and adaptive spawning patterns. +Squad runs on multiple Copilot surfaces. The coordinator MUST detect its platform and adapt spawning behavior accordingly. See `docs/scenarios/client-compatibility.md` for the full compatibility matrix. -**Core rules (always loaded):** -- Platform detection: `task` available → CLI (full control), `runSubagent` → VS Code (session model, parallel in one turn), neither → inline fallback -- VS Code adaptations: drop `agent_type`/`mode`/`model`, spawn all parallel agents in ONE turn, batch Scribe last, skip launch table -- SQL tool is CLI-only — use filesystem state for cross-platform workflows -- Prompt structure (charter/identity/task/response order) is surface-independent — never drop it +#### Platform Detection + +Before spawning agents, determine the platform by checking available tools: + +1. **CLI mode** — `task` tool is available → full spawning control. Use `task` with `agent_type`, `mode`, `model`, `description`, `prompt` parameters. Collect results via `read_agent`. + +2. **VS Code mode** — `runSubagent` or `agent` tool is available → conditional behavior. Use `runSubagent` with the task prompt. Drop `agent_type`, `mode`, and `model` parameters. Multiple subagents in one turn run concurrently (equivalent to background mode). Results return automatically — no `read_agent` needed. + +3. **Fallback mode** — neither `task` nor `runSubagent`/`agent` available → work inline. Do not apologize or explain the limitation. Execute the task directly. + +If both `task` and `runSubagent` are available, prefer `task` (richer parameter surface). + +#### VS Code Spawn Adaptations + +When in VS Code mode, the coordinator changes behavior in these ways: + +- **Spawning tool:** Use `runSubagent` instead of `task`. The prompt is the only required parameter — pass the full agent prompt (charter, identity, task, hygiene, response order) exactly as you would on CLI. +- **Parallelism:** Spawn ALL concurrent agents in a SINGLE turn. They run in parallel automatically. This replaces `mode: "background"` + `read_agent` polling. +- **Model selection:** Accept the session model. Do NOT attempt per-spawn model selection or fallback chains — they only work on CLI. In Phase 1, all subagents use whatever model the user selected in VS Code's model picker. +- **Scribe:** Cannot fire-and-forget. Batch Scribe as the LAST subagent in any parallel group. Scribe is light work (file ops only), so the blocking is tolerable. +- **Launch table:** Skip it. Results arrive with the response, not separately. By the time the coordinator speaks, the work is already done. +- **`read_agent`:** Skip entirely. Results return automatically when subagents complete. +- **`agent_type`:** Drop it. All VS Code subagents have full tool access by default. Subagents inherit the parent's tools. +- **`description`:** Drop it. The agent name is already in the prompt. +- **Prompt content:** Keep ALL prompt structure — charter, identity, task, hygiene, response order blocks are surface-independent. + +#### Feature Degradation Table + +| Feature | CLI | VS Code | Degradation | +|---------|-----|---------|-------------| +| Parallel fan-out | `mode: "background"` + `read_agent` | Multiple subagents in one turn | None — equivalent concurrency | +| Model selection | Per-spawn `model` param (4-layer hierarchy) | Session model only (Phase 1) | Accept session model, log intent | +| Scribe fire-and-forget | Background, never read | Sync, must wait | Batch with last parallel group | +| Launch table UX | Show table → results later | Skip table → results with response | UX only — results are correct | +| SQL tool | Available | Not available | Avoid SQL in cross-platform code paths | +| Response order bug | Critical workaround | Possibly necessary (unverified) | Keep the block — harmless if unnecessary | + +#### SQL Tool Caveat + +The `sql` tool is **CLI-only**. It does not exist on VS Code, JetBrains, or GitHub.com. Any coordinator logic or agent workflow that depends on SQL (todo tracking, batch processing, session state) will silently fail on non-CLI surfaces. Cross-platform code paths must not depend on SQL. Use filesystem-based state (`.squad/` files) for anything that must work everywhere. ### MCP Integration @@ -302,7 +492,6 @@ MCP (Model Context Protocol) servers extend Squad with tools for external servic At task start, scan your available tools list for known MCP prefixes: - `github-mcp-server-*` → GitHub API (issues, PRs, code search, actions) -- `azure-devops-*` → Azure DevOps API (work items, repos, PRs, pipelines, wiki) - `trello_*` → Trello boards, cards, lists - `aspire_*` → Aspire dashboard (metrics, logs, health) - `azure_*` → Azure resource management @@ -447,6 +636,39 @@ Squad and all spawned agents may be running inside a **git worktree** rather tha - **Not safe for concurrent sessions.** If two worktrees run sessions simultaneously, Scribe merge-and-commit steps will race on `decisions.md` and git index. Use only when a single session is active at a time. - Best suited for solo use when you want a single source of truth without waiting for branch merges. +### Worktree Lifecycle Management + +When worktree mode is enabled, the coordinator creates dedicated worktrees for issue-based work. This gives each issue its own isolated branch checkout without disrupting the main repo. + +**Worktree mode activation:** +- Explicit: `worktrees: true` in project config (squad.config.ts or package.json `squad` section) +- Environment: `SQUAD_WORKTREES=1` set in environment variables +- Default: `false` (backward compatibility — agents work in the main repo) + +**Creating worktrees:** +- One worktree per issue number +- Multiple agents on the same issue share a worktree +- Path convention: `{repo-parent}/{repo-name}-{issue-number}` + - Example: Working on issue #42 in `C:\src\squad` → worktree at `C:\src\squad-42` +- Branch: `squad/{issue-number}-{kebab-case-slug}` (created from base branch, typically `main`) + +**Dependency management:** +- After creating a worktree, link `node_modules` from the main repo to avoid reinstalling +- Windows: `cmd /c "mklink /J {worktree}\node_modules {main-repo}\node_modules"` +- Unix: `ln -s {main-repo}/node_modules {worktree}/node_modules` +- If linking fails (permissions, cross-device), fall back to `npm install` in the worktree + +**Reusing worktrees:** +- Before creating a new worktree, check if one exists for the same issue +- `git worktree list` shows all active worktrees +- If found, reuse it (cd to the path, verify branch is correct, `git pull` to sync) +- Multiple agents can work in the same worktree concurrently if they modify different files + +**Cleanup:** +- After a PR is merged, the worktree should be removed +- `git worktree remove {path}` + `git branch -d {branch}` +- Ralph heartbeat can trigger cleanup checks for merged branches + ### Orchestration Logging Orchestration log entries are written by **Scribe**, not the coordinator. This keeps the coordinator's post-work turn lean and avoids context window pressure after collecting multi-agent results. @@ -455,6 +677,53 @@ The coordinator passes a **spawn manifest** (who ran, why, what mode, outcome) t Each entry records: agent routed, why chosen, mode (background/sync), files authorized to read, files produced, and outcome. See `.squad/templates/orchestration-log.md` for the field format. +### Pre-Spawn: Worktree Setup + +When spawning an agent for issue-based work (user request references an issue number, or agent is working on a GitHub issue): + +**1. Check worktree mode:** +- Is `SQUAD_WORKTREES=1` set in the environment? +- Or does the project config have `worktrees: true`? +- If neither: skip worktree setup → agent works in the main repo (existing behavior) + +**2. If worktrees enabled:** + +a. **Determine the worktree path:** + - Parse issue number from context (e.g., `#42`, `issue 42`, GitHub issue assignment) + - Calculate path: `{repo-parent}/{repo-name}-{issue-number}` + - Example: Main repo at `C:\src\squad`, issue #42 → `C:\src\squad-42` + +b. **Check if worktree already exists:** + - Run `git worktree list` to see all active worktrees + - If the worktree path already exists → **reuse it**: + - Verify the branch is correct (should be `squad/{issue-number}-*`) + - `cd` to the worktree path + - `git pull` to sync latest changes + - Skip to step (e) + +c. **Create the worktree:** + - Determine branch name: `squad/{issue-number}-{kebab-case-slug}` (derive slug from issue title if available) + - Determine base branch (typically `main`, check default branch if needed) + - Run: `git worktree add {path} -b {branch} {baseBranch}` + - Example: `git worktree add C:\src\squad-42 -b squad/42-fix-login main` + +d. **Set up dependencies:** + - Link `node_modules` from main repo to avoid reinstalling: + - Windows: `cmd /c "mklink /J {worktree}\node_modules {main-repo}\node_modules"` + - Unix: `ln -s {main-repo}/node_modules {worktree}/node_modules` + - If linking fails (error), fall back: `cd {worktree} && npm install` + - Verify the worktree is ready: check build tools are accessible + +e. **Include worktree context in spawn:** + - Set `WORKTREE_PATH` to the resolved worktree path + - Set `WORKTREE_MODE` to `true` + - Add worktree instructions to the spawn prompt (see template below) + +**3. If worktrees disabled:** +- Set `WORKTREE_PATH` to `"n/a"` +- Set `WORKTREE_MODE` to `false` +- Use existing `git checkout -b` flow (no changes to current behavior) + ### How to Spawn an Agent **You MUST call the `task` tool** with these parameters for every agent spawn: @@ -488,6 +757,29 @@ prompt: | TEAM ROOT: {team_root} All `.squad/` paths are relative to this root. + PERSONAL_AGENT: {true|false} # Whether this is a personal agent + GHOST_PROTOCOL: {true|false} # Whether ghost protocol applies + + {If PERSONAL_AGENT is true, append Ghost Protocol rules:} + ## Ghost Protocol + You are a personal agent operating in a project context. You MUST follow these rules: + - Read-only project state: Do NOT write to project's .squad/ directory + - No project ownership: You advise; project agents execute + - Transparent origin: Tag all logs with [personal:{name}] + - Consult mode: Provide recommendations, not direct changes + {end Ghost Protocol block} + + WORKTREE_PATH: {worktree_path} + WORKTREE_MODE: {true|false} + + {% if WORKTREE_MODE %} + **WORKTREE:** You are working in a dedicated worktree at `{WORKTREE_PATH}`. + - All file operations should be relative to this path + - Do NOT switch branches — the worktree IS your branch (`{branch_name}`) + - Build and test in the worktree, not the main repo + - Commit and push from the worktree + {% endif %} + Read .squad/agents/{name}/history.md (your project knowledge). Read .squad/decisions.md (team decisions to respect). If .squad/identity/wisdom.md exists, read it before starting work. @@ -510,9 +802,7 @@ prompt: | AFTER work: 1. APPEND to .squad/agents/{name}/history.md under "## Learnings": - architecture decisions, reusable patterns, key file paths, API behaviors, team conventions. - ⚠️ DO NOT record: requester names, branch names, session metadata, or one-time task context. - History is for knowledge that will be useful in FUTURE sessions, not session attribution. + architecture decisions, patterns, user preferences, key file paths. 2. If you made a team-relevant decision, write to: .squad/decisions/inbox/{name}-{brief-slug}.md 3. SKILL EXTRACTION: If you found a reusable pattern, write/update @@ -568,12 +858,12 @@ prompt: | SPAWN MANIFEST: {spawn_manifest} Tasks (in order): - 1. ORCHESTRATION LOG: Write .squad/orchestration-log/{timestamp}-{agent}.md per agent. Use filename-safe ISO 8601 UTC timestamp (replace colons with hyphens, e.g., `2026-02-23T20-16-27Z` not `2026-02-23T20:16:27Z`). - 2. SESSION LOG: Write .squad/log/{timestamp}-{topic}.md. Brief. Use filename-safe ISO 8601 UTC timestamp (replace colons with hyphens, e.g., `2026-02-23T20-16-27Z`). + 1. ORCHESTRATION LOG: Write .squad/orchestration-log/{timestamp}-{agent}.md per agent. Use ISO 8601 UTC timestamp. + 2. SESSION LOG: Write .squad/log/{timestamp}-{topic}.md. Brief. Use ISO 8601 UTC timestamp. 3. DECISION INBOX: Merge .squad/decisions/inbox/ → decisions.md, delete inbox files. Deduplicate. 4. CROSS-AGENT: Append team updates to affected agents' history.md. 5. DECISIONS ARCHIVE: If decisions.md exceeds ~20KB, archive entries older than 30 days to decisions-archive.md. - 6. GIT COMMIT: Stage with `git add .squad/`, then unstage runtime state that must not reach protected branches: `git reset HEAD -- .squad/orchestration-log/ .squad/log/ .squad/decisions/inbox/ .squad/sessions/ 2>/dev/null`. Commit remaining staged changes (write msg to temp file, use -F). Skip if nothing staged after reset. + 6. GIT COMMIT: git add .squad/ && commit (write msg to temp file, use -F). Skip if nothing staged. 7. HISTORY SUMMARIZATION: If any history.md >12KB, summarize old entries to ## Core Context. Never speak to user. ⚠️ End with plain text summary after all tool calls. @@ -667,7 +957,7 @@ Agent names are drawn from a single fictional universe per assignment. Names are **Rules (always loaded):** - ONE UNIVERSE PER ASSIGNMENT. NEVER MIX. -- 31 universes available (capacity 6–25). See reference file for full list. +- 15 universes available (capacity 6–25). See reference file for full list. - Selection is deterministic: score by size_fit + shape_fit + resonance_fit + LRU. - Same inputs → same choice (unless LRU changes). @@ -726,15 +1016,26 @@ When `.squad/team.md` exists but `.squad/casting/` does not: ## Reviewer Rejection Protocol -**Skill:** Read `.squad/skills/reviewer-protocol/SKILL.md` when a Reviewer rejects work. +When a team member has a **Reviewer** role (e.g., Tester, Code Reviewer, Lead): -**Core rules (always loaded):** -- On rejection: original author is **locked out** — may NOT self-revise, no exceptions -- A different agent MUST own the revision (Reviewer chooses: reassign or escalate) -- Coordinator verifies mechanically: if Reviewer names original author, refuse and ask for a different agent -- Lockout scope: per-artifact only (author can work on other artifacts) -- Lockout duration: persists through revision cycle -- Deadlock: if all eligible agents locked out, escalate to user (never re-admit) +- Reviewers may **approve** or **reject** work from other agents. +- On **rejection**, the Reviewer may choose ONE of: + 1. **Reassign:** Require a *different* agent to do the revision (not the original author). + 2. **Escalate:** Require a *new* agent be spawned with specific expertise. +- The Coordinator MUST enforce this. If the Reviewer says "someone else should fix this," the original agent does NOT get to self-revise. +- If the Reviewer approves, work proceeds normally. + +### Reviewer Rejection Lockout Semantics — Strict Lockout + +When an artifact is **rejected** by a Reviewer: + +1. **The original author is locked out.** They may NOT produce the next version of that artifact. No exceptions. +2. **A different agent MUST own the revision.** The Coordinator selects the revision author based on the Reviewer's recommendation (reassign or escalate). +3. **The Coordinator enforces this mechanically.** Before spawning a revision agent, the Coordinator MUST verify that the selected agent is NOT the original author. If the Reviewer names the original author as the fix agent, the Coordinator MUST refuse and ask the Reviewer to name a different agent. +4. **The locked-out author may NOT contribute to the revision** in any form — not as a co-author, advisor, or pair. The revision must be independently produced. +5. **Lockout scope:** The lockout applies to the specific artifact that was rejected. The original author may still work on other unrelated artifacts. +6. **Lockout duration:** The lockout persists for that revision cycle. If the revision is also rejected, the same rule applies again — the revision author is now also locked out, and a third agent must revise. +7. **Deadlock handling:** If all eligible agents have been locked out of an artifact, the Coordinator MUST escalate to the user rather than re-admitting a locked-out author. --- @@ -785,65 +1086,6 @@ Before connecting to a GitHub repository, verify that the `gh` CLI is available --- -## Platform Detection - -On session start, detect the platform from git remote: -- `github.com` → Use GitHub commands (`gh` CLI) -- `dev.azure.com` or `*.visualstudio.com` → Use Azure DevOps commands (`az` CLI) - -If `squad.config.ts` specifies `workItems: 'planner'`, use Microsoft Planner for work items regardless of where the repo lives. - -### Azure DevOps Mode - -If the git remote points to Azure DevOps: - -| GitHub concept | Azure DevOps equivalent | Command change | -|---|---|---| -| `gh issue list` | WIQL query via `az boards query` | `az boards query --wiql "SELECT ... FROM WorkItems WHERE ..."` | -| `gh pr list` | `az repos pr list` | `az repos pr list --status active` | -| `gh pr create` | `az repos pr create` | `az repos pr create --source-branch ... --target-branch ...` | -| `gh pr merge` | `az repos pr update --status completed` | Set PR status to completed | -| Issue labels | Work Item tags | `az boards work-item update --fields "System.Tags=..."` | -| `squad:{member}` label | `squad:{member}` tag on work items | Tags use `;` separator | - -**Prerequisites for Azure DevOps:** -1. Run `az --version`. If missing: *"Azure DevOps mode requires the Azure CLI. Install from https://aka.ms/install-az-cli"* -2. Run `az extension show --name azure-devops`. If missing: *"Run `az extension add --name azure-devops`"* -3. Run `az account show`. If not logged in: *"Run `az login` to authenticate"* -4. Verify defaults: `az devops configure --list` — org and project must be set - -**ADO Work Item Config (`.squad/config.json`):** - -Read the `ado` section from `.squad/config.json` to resolve org, project, work item type, area/iteration paths: - -```json -{ - "platform": "azure-devops", - "ado": { - "org": "my-org", - "project": "work-items-project", - "defaultWorkItemType": "Scenario", - "areaPath": "MyProject\\Team Alpha", - "iterationPath": "MyProject\\Sprint 5" - } -} -``` - -- If `ado.org`/`ado.project` are set, use them for ALL work item operations (they may differ from the repo's org/project) -- If not set, parse org/project from `git remote get-url origin` -- Pass `--org https://dev.azure.com/{org} --project {project}` on every `az boards` command -- Use `ado.defaultWorkItemType` when creating work items (default: "User Story") - -**Ralph on Azure DevOps:** -- **Read `.squad/config.json`** first — the `ado` section tells you which org/project to query for work items -- Replace `gh issue list --label "squad:untriaged"` with WIQL: `az boards query --wiql "SELECT ... WHERE [System.Tags] Contains 'squad:untriaged' AND [System.TeamProject] = '{project}'" --org ... --project ...` -- Replace `gh issue list --label "squad:{member}"` with WIQL: `az boards query --wiql "SELECT ... WHERE [System.Tags] Contains 'squad:{member}'" --org ... --project ...` -- Replace `gh pr list` with `az repos pr list` (uses repo org/project, not work item org/project) -- When creating work items, use `ado.defaultWorkItemType`, include `ado.areaPath` and `ado.iterationPath` if configured -- Branch naming stays the same: `squad/{issue-number}-{slug}` - ---- - ## Ralph — Work Monitor Ralph is a built-in squad member whose job is keeping tabs on work. **Ralph tracks and drives the work queue.** Always on the roster, one job: make sure the team never sits idle. @@ -868,7 +1110,7 @@ Ralph always appears in `team.md`: `| Ralph | Work Monitor | — | 🔄 Monitor | "Ralph, idle" / "Take a break" / "Stop monitoring" | Fully deactivate (stop loop + idle-watch) | | "Ralph, scope: just issues" / "Ralph, skip CI" | Adjust what Ralph monitors this session | | References PR feedback or changes requested | Spawn agent to address PR review feedback | -| "merge PR #N" / "merge it" (recent context) | Merge via `gh pr merge` (GitHub) or `az repos pr update --status completed` (ADO) | +| "merge PR #N" / "merge it" (recent context) | Merge via `gh pr merge` | These are intent signals, not exact strings — match meaning, not words. @@ -876,9 +1118,6 @@ When Ralph is active, run this check cycle after every batch of agent work compl **Step 1 — Scan for work** (run these in parallel): -> **Platform-aware:** Detect the platform from git remote. If Azure DevOps, read `.squad/config.json` for the `ado` section FIRST — it tells you which org/project to query for work items (may differ from the repo). Use `az boards query` / `az repos pr list` instead of `gh`. If Planner, use Graph API. Do NOT guess the ADO project from the repo name — read the config. - -**GitHub:** ```bash # Untriaged issues (labeled squad but no squad:{member} sub-label) gh issue list --label "squad" --state open --json number,title,labels,assignees --limit 20 @@ -893,24 +1132,6 @@ gh pr list --state open --json number,title,author,labels,isDraft,reviewDecision gh pr list --state open --draft --json number,title,author,labels,checks --limit 20 ``` -**Azure DevOps:** -```bash -# Read org/project from .squad/config.json → ado.org, ado.project -# Fall back to git remote URL parsing if not configured - -# Untriaged work items -az boards query --wiql "SELECT [System.Id],[System.Title],[System.State],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:untriaged' AND [System.TeamProject] = '{project}' ORDER BY [System.CreatedDate] DESC" --org "https://dev.azure.com/{org}" --project "{project}" --output table - -# Member-assigned work items -az boards query --wiql "SELECT [System.Id],[System.Title],[System.State],[System.Tags] FROM WorkItems WHERE [System.Tags] Contains 'squad:{member}' AND [System.State] <> 'Closed' AND [System.TeamProject] = '{project}' ORDER BY [System.CreatedDate] DESC" --org "https://dev.azure.com/{org}" --project "{project}" --output table - -# Open PRs (uses repo org/project, NOT work item org/project) -az repos pr list --status active --output table - -# Create a work item (uses configured type, area path, iteration path) -az boards work-item create --type "{ado.defaultWorkItemType}" --title "{title}" --fields "System.Tags=squad; squad:untriaged" --org "https://dev.azure.com/{org}" --project "{project}" -``` - **Step 2 — Categorize findings:** | Category | Signal | Action | diff --git a/.github/workflows/ci-rerun.yml b/.github/workflows/ci-rerun.yml new file mode 100644 index 000000000..9dcf9850a --- /dev/null +++ b/.github/workflows/ci-rerun.yml @@ -0,0 +1,119 @@ +name: CI Rerun (Manual) + +on: + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to test' + required: true + type: string + +permissions: + contents: read + statuses: write + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Fetch PR metadata + id: pr + env: + GH_TOKEN: ${{ github.token }} + run: | + PR_DATA=$(gh api repos/${{ github.repository }}/pulls/${{ inputs.pr_number }}) + HEAD_SHA=$(echo "$PR_DATA" | jq -r '.head.sha') + HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref') + HEAD_REPO=$(echo "$PR_DATA" | jq -r '.head.repo.full_name') + BASE_REF=$(echo "$PR_DATA" | jq -r '.base.ref') + echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT" + echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT" + echo "head_repo=$HEAD_REPO" >> "$GITHUB_OUTPUT" + echo "base_ref=$BASE_REF" >> "$GITHUB_OUTPUT" + echo "Testing PR #${{ inputs.pr_number }}: $HEAD_REPO/$HEAD_REF → $BASE_REF (SHA: $HEAD_SHA)" + + - name: Set pending status + env: + GH_TOKEN: ${{ github.token }} + run: | + gh api repos/${{ github.repository }}/statuses/${{ steps.pr.outputs.head_sha }} \ + --method POST \ + --field state=pending \ + --field context="Squad CI / rerun" \ + --field description="Running CI rerun..." \ + --field target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + + - uses: actions/checkout@v4 + with: + ref: refs/pull/${{ inputs.pr_number }}/merge + continue-on-error: true + id: checkout_merge + + - name: Fallback — checkout PR head directly + if: steps.checkout_merge.outcome == 'failure' + uses: actions/checkout@v4 + with: + repository: ${{ steps.pr.outputs.head_repo }} + ref: ${{ steps.pr.outputs.head_ref }} + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Fix stale lockfile entries + run: | + node -e " + const fs = require('fs'); + const lock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8')); + const pkgs = lock.packages || {}; + const stale = Object.keys(pkgs).filter(k => + k.includes('/node_modules/@bradygaster/squad-') && + pkgs[k].resolved && pkgs[k].resolved.startsWith('https://') + ); + if (stale.length) { + stale.forEach(k => { console.log('Removing: ' + k); delete pkgs[k]; }); + fs.writeFileSync('package-lock.json', JSON.stringify(lock, null, 2) + '\n'); + } else { + console.log('Lockfile clean'); + } + " + + - name: Install dependencies + run: npm install + + - name: Install docs dependencies + run: npm ci + working-directory: docs + + - name: Install Playwright browsers + run: npx playwright install chromium --with-deps + + - name: Build + run: npm run build + + - name: Run tests + run: npm test + + - name: Set success status + if: success() + env: + GH_TOKEN: ${{ github.token }} + run: | + gh api repos/${{ github.repository }}/statuses/${{ steps.pr.outputs.head_sha }} \ + --method POST \ + --field state=success \ + --field context="Squad CI / rerun" \ + --field description="All checks passed" \ + --field target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + + - name: Set failure status + if: failure() + env: + GH_TOKEN: ${{ github.token }} + run: | + gh api repos/${{ github.repository }}/statuses/${{ steps.pr.outputs.head_sha }} \ + --method POST \ + --field state=failure \ + --field context="Squad CI / rerun" \ + --field description="CI rerun failed — check logs" \ + --field target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 67a7299d0..f3c7d4884 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -3,7 +3,7 @@ name: Squad CI on: pull_request: branches: [dev, preview, main, insider] - types: [opened, synchronize, reopened] + types: [opened, synchronize, reopened, edited] push: branches: [dev, insider] @@ -11,6 +11,24 @@ permissions: contents: read jobs: + docs-quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install docs tools + run: npm install --no-save markdownlint-cli2 cspell + + - name: Lint docs markdown + run: npx markdownlint-cli2 + + - name: Spell check docs + run: npx cspell --no-progress --dot "docs/src/content/**/*.md" "README.md" + test: runs-on: ubuntu-latest steps: @@ -20,8 +38,26 @@ jobs: with: node-version: 22 + - name: Fix stale lockfile entries + run: | + node -e " + const fs = require('fs'); + const lock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8')); + const pkgs = lock.packages || {}; + const stale = Object.keys(pkgs).filter(k => + k.includes('/node_modules/@bradygaster/squad-') && + pkgs[k].resolved && pkgs[k].resolved.startsWith('https://') + ); + if (stale.length) { + stale.forEach(k => { console.log('Removing: ' + k); delete pkgs[k]; }); + fs.writeFileSync('package-lock.json', JSON.stringify(lock, null, 2) + '\n'); + } else { + console.log('Lockfile clean'); + } + " + - name: Install dependencies - run: npm ci + run: npm install - name: Install docs dependencies run: npm ci diff --git a/.github/workflows/squad-docs-links.yml b/.github/workflows/squad-docs-links.yml new file mode 100644 index 000000000..f665903fd --- /dev/null +++ b/.github/workflows/squad-docs-links.yml @@ -0,0 +1,37 @@ +name: Docs — Weekly Link Check + +on: + schedule: + - cron: '0 9 * * 1' # Monday 9am UTC + workflow_dispatch: + +jobs: + linkcheck: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - uses: actions/checkout@v4 + + - name: Check external links + id: lychee + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --verbose + --no-progress + --exclude-mail + --timeout 30 + --max-retries 3 + --accept 200..=299,403,429 + 'docs/src/content/**/*.md' + 'README.md' + fail: false + + - name: Create issue on broken links + if: steps.lychee.outputs.exit_code != 0 + uses: peter-evans/create-issue-from-file@v5 + with: + title: '🔗 Broken external links detected' + content-filepath: ./lychee/out.md + labels: docs, automated diff --git a/.github/workflows/squad-heartbeat.yml b/.github/workflows/squad-heartbeat.yml index 658bef3c7..520c019a2 100644 --- a/.github/workflows/squad-heartbeat.yml +++ b/.github/workflows/squad-heartbeat.yml @@ -7,10 +7,9 @@ name: Squad Heartbeat (Ralph) # Run 'squad upgrade' to sync installed copies from source templates. on: - # DISABLED: Cron heartbeat commented out pre-migration — re-enable when ready - # schedule: - # # Every 30 minutes — adjust or remove if not needed - # - cron: '*/30 * * * *' + schedule: + # Every 30 minutes — adjust via cron expression as needed + - cron: '*/30 * * * *' # React to completed work or new squad work issues: @@ -32,6 +31,38 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Ralph — Repair orphaned squad labels + uses: actions/github-script@v7 + with: + script: | + // Find issues with squad:{member} labels but missing parent "squad" label + const { data: openIssues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100 + }); + + let repaired = 0; + for (const issue of openIssues) { + const labels = issue.labels.map(l => l.name); + const hasSquadMember = labels.some(l => l.startsWith('squad:')); + const hasSquadParent = labels.includes('squad'); + if (hasSquadMember && !hasSquadParent) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['squad'] + }); + core.info(`Repaired orphaned label on #${issue.number} — added parent "squad" label`); + repaired++; + } + } + if (repaired > 0) { + core.info(`🔧 Ralph repaired ${repaired} orphaned squad label(s)`); + } + - name: Check triage script id: check-script run: | diff --git a/.github/workflows/squad-issue-assign.yml b/.github/workflows/squad-issue-assign.yml index ad140f42d..9aef424df 100644 --- a/.github/workflows/squad-issue-assign.yml +++ b/.github/workflows/squad-issue-assign.yml @@ -77,6 +77,18 @@ jobs: return; } + // Ensure parent "squad" label exists (prevents orphaned squad:{member} labels) + const issueLabels = issue.labels.map(l => l.name); + if (!issueLabels.includes('squad')) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['squad'] + }); + core.info(`Added parent "squad" label to #${issue.number}`); + } + // Post assignment acknowledgment let comment; if (isCopilotAssignment) { diff --git a/.lycheeignore b/.lycheeignore new file mode 100644 index 000000000..397cd60fb --- /dev/null +++ b/.lycheeignore @@ -0,0 +1,12 @@ +# Rate-limited or auth-gated URLs +https://github.com/.*/edit/.* +https://dev.azure.com/.* +https://.*\.visualstudio\.com/.* +# Localhost references in examples +localhost +127\.0\.0\.1 +# Template/placeholder URLs +https://example\.com +https://your-.* +# npm registry (rate limits) +https://www.npmjs.com/package/.* diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 000000000..70b6815c7 --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,28 @@ +{ + "config": { + "default": true, + "MD013": false, // Line length — docs are prose, not code + "MD033": false, // Inline HTML — Astro components use HTML in markdown + "MD041": false, // First line heading — some docs don't start with heading + "MD024": false, // Duplicate headings — OK in long docs + "MD025": { "front_matter_title": "" }, // Single H1 + "MD009": false, // Trailing spaces — can conflict with intentional formatting + "MD012": false, // Multiple blank lines — common in docs for readability + "MD028": false, // Blank line inside blockquote — blog frontmatter + "MD060": false, // Table column style — existing blog tables + "MD049": false, // Emphasis style — existing blog content uses mixed styles + "MD032": false, // Lists surrounded by blank lines — existing docs + "MD031": false, // Fenced code blocks surrounded by blank lines + "MD040": false, // Fenced code language — not all code blocks need lang + "MD022": false, // Headings surrounded by blank lines — blog posts + "MD029": false, // Ordered list item prefix — intentional restarts + "MD036": false, // Emphasis as heading — blog/guide formatting + "MD014": false, // Dollar signs before commands — code examples + "MD034": false, // Bare URLs — many existing bare URLs in docs + "MD004": false, // Unordered list style — mixed styles in docs + "MD026": false, // Trailing punctuation in heading — existing style + "MD051": false // Link fragments — will be caught by link validation test + }, + "globs": ["docs/src/content/**/*.md", "README.md"], + "ignores": ["node_modules", "docs/dist", "docs/node_modules", ".squad"] +} diff --git a/.squad-templates/casting-policy.json b/.squad-templates/casting-policy.json index b3858c78d..12a57cca8 100644 --- a/.squad-templates/casting-policy.json +++ b/.squad-templates/casting-policy.json @@ -14,7 +14,8 @@ "Breaking Bad", "Lost", "Marvel Cinematic Universe", - "DC Universe" + "DC Universe", + "Futurama" ], "universe_capacity": { "The Usual Suspects": 6, @@ -30,6 +31,7 @@ "Breaking Bad": 12, "Lost": 18, "Marvel Cinematic Universe": 25, - "DC Universe": 18 + "DC Universe": 18, + "Futurama": 12 } } diff --git a/.squad-templates/casting-reference.md b/.squad-templates/casting-reference.md new file mode 100644 index 000000000..f0a72e094 --- /dev/null +++ b/.squad-templates/casting-reference.md @@ -0,0 +1,104 @@ +# Casting Reference + +On-demand reference for Squad's casting system. Loaded during Init Mode or when adding team members. + +## Universe Table + +| Universe | Capacity | Shape Tags | Resonance Signals | +|---|---|---|---| +| The Usual Suspects | 6 | small, noir, ensemble | crime, heist, mystery, deception | +| Reservoir Dogs | 8 | small, noir, ensemble | crime, heist, tension, loyalty | +| Alien | 8 | small, sci-fi, survival | space, isolation, threat, engineering | +| Ocean's Eleven | 14 | medium, heist, ensemble | planning, coordination, roles, charm | +| Arrested Development | 15 | medium, comedy, ensemble | dysfunction, business, family, satire | +| Star Wars | 12 | medium, sci-fi, epic | conflict, mentorship, legacy, rebellion | +| The Matrix | 10 | medium, sci-fi, cyberpunk | systems, reality, hacking, philosophy | +| Firefly | 10 | medium, sci-fi, western | frontier, crew, independence, smuggling | +| The Goonies | 8 | small, adventure, ensemble | exploration, treasure, kids, teamwork | +| The Simpsons | 20 | large, comedy, ensemble | satire, community, family, absurdity | +| Breaking Bad | 12 | medium, drama, tension | chemistry, transformation, consequence, power | +| Lost | 18 | large, mystery, ensemble | survival, mystery, groups, leadership | +| Marvel Cinematic Universe | 25 | large, action, ensemble | heroism, teamwork, powers, scale | +| DC Universe | 18 | large, action, ensemble | justice, duality, powers, mythology | +| Futurama | 12 | medium, sci-fi, comedy | future, robots, space, absurdity | + +**Total: 15 universes** — capacity range 6–25. + +## Selection Algorithm + +Universe selection is deterministic. Score each universe and pick the highest: + +``` +score = size_fit + shape_fit + resonance_fit + LRU +``` + +| Factor | Description | +|---|---| +| `size_fit` | How well the universe capacity matches the team size. Prefer universes where capacity ≥ agent_count with minimal waste. | +| `shape_fit` | Match universe shape tags against the assignment shape derived from the project description. | +| `resonance_fit` | Match universe resonance signals against session and repo context signals. | +| `LRU` | Least-recently-used bonus — prefer universes not used in recent assignments (from `history.json`). | + +Same inputs → same choice (unless LRU changes between assignments). + +## Casting State File Schemas + +### policy.json + +Source template: `.squad/templates/casting-policy.json` +Runtime location: `.squad/casting/policy.json` + +```json +{ + "casting_policy_version": "1.1", + "allowlist_universes": ["Universe Name", "..."], + "universe_capacity": { + "Universe Name": 10 + } +} +``` + +### registry.json + +Source template: `.squad/templates/casting-registry.json` +Runtime location: `.squad/casting/registry.json` + +```json +{ + "agents": { + "agent-role-id": { + "persistent_name": "CharacterName", + "universe": "Universe Name", + "created_at": "ISO-8601", + "legacy_named": false, + "status": "active" + } + } +} +``` + +### history.json + +Source template: `.squad/templates/casting-history.json` +Runtime location: `.squad/casting/history.json` + +```json +{ + "universe_usage_history": [ + { + "universe": "Universe Name", + "assignment_id": "unique-id", + "used_at": "ISO-8601" + } + ], + "assignment_cast_snapshots": { + "assignment-id": { + "universe": "Universe Name", + "agents": { + "role-id": "CharacterName" + }, + "created_at": "ISO-8601" + } + } +} +``` diff --git a/.squad-templates/casting/Futurama.json b/.squad-templates/casting/Futurama.json new file mode 100644 index 000000000..2cf36b193 --- /dev/null +++ b/.squad-templates/casting/Futurama.json @@ -0,0 +1,10 @@ +[ + "Fry", + "Leela", + "Bender", + "Farnsworth", + "Zoidberg", + "Amy", + "Zapp", + "Kif" +] \ No newline at end of file diff --git a/.squad-templates/cooperative-rate-limiting.md b/.squad-templates/cooperative-rate-limiting.md new file mode 100644 index 000000000..bf56ef122 --- /dev/null +++ b/.squad-templates/cooperative-rate-limiting.md @@ -0,0 +1,229 @@ +# Cooperative Rate Limiting for Multi-Agent Deployments + +> Coordinate API quota across multiple Ralph instances to prevent cascading failures. + +## Problem + +The [circuit breaker template](ralph-circuit-breaker.md) handles single-instance rate limiting well. But when multiple Ralphs run across machines (or pods on K8s), each instance independently hits API limits: + +- **No coordination** — 5 Ralphs each think they have full API quota +- **Thundering herd** — All Ralphs retry simultaneously after rate limit resets +- **Priority inversion** — Low-priority work exhausts quota before critical work runs +- **Reactive only** — Circuit opens AFTER 429, wasting the failed request + +## Solution: 6-Pattern Architecture + +These patterns layer on top of the existing circuit breaker. Each is independent — adopt one or all. + +### Pattern 1: Traffic Light (RAAS — Rate-Aware Agent Scheduling) + +Map GitHub API `X-RateLimit-Remaining` to traffic light states: + +| State | Remaining % | Behavior | +|-------|------------|----------| +| 🟢 GREEN | >20% | Normal operation | +| 🟡 AMBER | 5–20% | Only P0 agents proceed | +| 🔴 RED | <5% | Block all except emergency P0 | + +```typescript +type TrafficLight = 'green' | 'amber' | 'red'; + +function getTrafficLight(remaining: number, limit: number): TrafficLight { + const pct = remaining / limit; + if (pct > 0.20) return 'green'; + if (pct > 0.05) return 'amber'; + return 'red'; +} + +function shouldProceed(light: TrafficLight, agentPriority: number): boolean { + if (light === 'green') return true; + if (light === 'amber') return agentPriority === 0; // P0 only + return false; // RED — block all +} +``` + +### Pattern 2: Cooperative Token Pool (CMARP) + +A shared JSON file (`~/.squad/rate-pool.json`) distributes API quota: + +```json +{ + "totalLimit": 5000, + "resetAt": "2026-03-22T20:00:00Z", + "allocations": { + "picard": { "priority": 0, "allocated": 2000, "used": 450, "leaseExpiry": "2026-03-22T19:55:00Z" }, + "data": { "priority": 1, "allocated": 1750, "used": 200, "leaseExpiry": "2026-03-22T19:55:00Z" }, + "ralph": { "priority": 2, "allocated": 1250, "used": 100, "leaseExpiry": "2026-03-22T19:55:00Z" } + } +} +``` + +**Rules:** +- P0 agents (Lead) get 40% of quota +- P1 agents (specialists) get 35% +- P2 agents (Ralph, Scribe) get 25% +- Stale leases (>5 minutes without heartbeat) are auto-recovered +- Each agent checks their remaining allocation before making API calls + +```typescript +interface RatePoolAllocation { + priority: number; + allocated: number; + used: number; + leaseExpiry: string; +} + +interface RatePool { + totalLimit: number; + resetAt: string; + allocations: Record; +} + +function canUseQuota(pool: RatePool, agentName: string): boolean { + const alloc = pool.allocations[agentName]; + if (!alloc) return true; // Unknown agent — allow (graceful) + + // Reclaim stale leases from crashed agents + const now = new Date(); + for (const [name, a] of Object.entries(pool.allocations)) { + if (new Date(a.leaseExpiry) < now && name !== agentName) { + a.allocated = 0; // Reclaim + } + } + + return alloc.used < alloc.allocated; +} +``` + +### Pattern 3: Predictive Circuit Breaker (PCB) + +Opens the circuit BEFORE getting a 429 by predicting when quota will run out: + +```typescript +interface RateSample { + timestamp: number; // Date.now() + remaining: number; // from X-RateLimit-Remaining header +} + +class PredictiveCircuitBreaker { + private samples: RateSample[] = []; + private readonly maxSamples = 10; + private readonly warningThresholdSeconds = 120; + + addSample(remaining: number): void { + this.samples.push({ timestamp: Date.now(), remaining }); + if (this.samples.length > this.maxSamples) { + this.samples.shift(); + } + } + + /** Predict seconds until quota exhaustion using linear regression */ + predictExhaustion(): number | null { + if (this.samples.length < 3) return null; + + const n = this.samples.length; + const first = this.samples[0]; + const last = this.samples[n - 1]; + + const elapsedMs = last.timestamp - first.timestamp; + if (elapsedMs === 0) return null; + + const consumedPerMs = (first.remaining - last.remaining) / elapsedMs; + if (consumedPerMs <= 0) return null; // Not consuming — safe + + const msUntilExhausted = last.remaining / consumedPerMs; + return msUntilExhausted / 1000; + } + + shouldOpen(): boolean { + const eta = this.predictExhaustion(); + if (eta === null) return false; + return eta < this.warningThresholdSeconds; + } +} +``` + +### Pattern 4: Priority Retry Windows (PWJG) + +Non-overlapping jitter windows prevent thundering herd: + +| Priority | Retry Window | Description | +|----------|-------------|-------------| +| P0 (Lead) | 500ms–5s | Recovers first | +| P1 (Specialists) | 2s–30s | Moderate delay | +| P2 (Ralph/Scribe) | 5s–60s | Most patient | + +```typescript +function getRetryDelay(priority: number, attempt: number): number { + const windows: Record = { + 0: [500, 5000], // P0: 500ms–5s + 1: [2000, 30000], // P1: 2s–30s + 2: [5000, 60000], // P2: 5s–60s + }; + + const [min, max] = windows[priority] ?? windows[2]; + const base = Math.min(min * Math.pow(2, attempt), max); + const jitter = Math.random() * base * 0.5; + return base + jitter; +} +``` + +### Pattern 5: Resource Epoch Tracker (RET) + +Heartbeat-based lease system for multi-machine deployments: + +```typescript +interface ResourceLease { + agent: string; + machine: string; + leaseStart: string; + leaseExpiry: string; // Typically 5 minutes from now + allocated: number; +} + +// Each agent renews its lease every 2 minutes +// If lease expires (agent crashed), allocation is reclaimed +``` + +### Pattern 6: Cascade Dependency Detector (CDD) + +Track downstream failures and apply backpressure: + +``` +Agent A (rate limited) → Agent B (waiting for A) → Agent C (waiting for B) + ↑ Backpressure signal: "don't start new work" +``` + +When a dependency is rate-limited, upstream agents should pause new work rather than queuing requests that will fail. + +## Kubernetes Integration + +On K8s, cooperative rate limiting can use KEDA to scale pods based on API quota: + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +spec: + scaleTargetRef: + name: ralph-deployment + triggers: + - type: external + metadata: + scalerAddress: keda-copilot-scaler:6000 + # Scaler returns 0 when rate limited → pods scale to zero +``` + +See [keda-copilot-scaler](https://github.com/tamirdresher/keda-copilot-scaler) for a complete implementation. + +## Quick Start + +1. **Minimum viable:** Adopt Pattern 1 (Traffic Light) — read `X-RateLimit-Remaining` from API responses +2. **Multi-machine:** Add Pattern 2 (Cooperative Pool) — shared `rate-pool.json` +3. **Production:** Add Pattern 3 (Predictive CB) — prevent 429s entirely +4. **Kubernetes:** Add KEDA scaler for automatic pod scaling + +## References + +- [Circuit Breaker Template](ralph-circuit-breaker.md) — Foundation patterns +- [Squad on AKS](https://github.com/tamirdresher/squad-on-aks) — Production K8s deployment +- [KEDA Copilot Scaler](https://github.com/tamirdresher/keda-copilot-scaler) — Custom KEDA external scaler diff --git a/.squad-templates/issue-lifecycle.md b/.squad-templates/issue-lifecycle.md new file mode 100644 index 000000000..574c205a1 --- /dev/null +++ b/.squad-templates/issue-lifecycle.md @@ -0,0 +1,412 @@ +# Issue Lifecycle — Repo Connection & PR Flow + +Reference for connecting Squad to a repository and managing the issue→branch→PR→merge lifecycle. + +## Repo Connection Format + +When connecting Squad to an issue tracker, store the connection in `.squad/team.md`: + +```markdown +## Issue Source + +**Repository:** {owner}/{repo} +**Connected:** {date} +**Platform:** {GitHub | Azure DevOps | Planner} +**Filters:** +- Labels: `{label-filter}` +- Project: `{project-name}` (ADO/Planner only) +- Plan: `{plan-id}` (Planner only) +``` + +**Detection triggers:** +- User says "connect to {repo}" +- User says "monitor {repo} for issues" +- Ralph is activated without an issue source + +## Platform-Specific Issue States + +Each platform tracks issue lifecycle differently. Squad normalizes these into a common board state. + +### GitHub + +| GitHub State | GitHub API Fields | Squad Board State | +|--------------|-------------------|-------------------| +| Open, no assignee | `state: open`, `assignee: null` | `untriaged` | +| Open, assigned, no branch | `state: open`, `assignee: @user`, no linked PR | `assigned` | +| Open, branch exists | `state: open`, linked branch exists | `inProgress` | +| Open, PR opened | `state: open`, PR exists, `reviewDecision: null` | `needsReview` | +| Open, PR approved | `state: open`, PR `reviewDecision: APPROVED` | `readyToMerge` | +| Open, changes requested | `state: open`, PR `reviewDecision: CHANGES_REQUESTED` | `changesRequested` | +| Open, CI failure | `state: open`, PR `statusCheckRollup: FAILURE` | `ciFailure` | +| Closed | `state: closed` | `done` | + +**Issue labels used by Squad:** +- `squad` — Issue is in Squad backlog +- `squad:{member}` — Assigned to specific agent +- `squad:untriaged` — Needs triage +- `go:needs-research` — Needs investigation before implementation +- `priority:p{N}` — Priority level (0=critical, 1=high, 2=medium, 3=low) +- `next-up` — Queued for next agent pickup + +**Branch naming convention:** +``` +squad/{issue-number}-{kebab-case-slug} +``` +Example: `squad/42-fix-login-validation` + +### Azure DevOps + +| ADO State | Squad Board State | +|-----------|-------------------| +| New | `untriaged` | +| Active, no branch | `assigned` | +| Active, branch exists | `inProgress` | +| Active, PR opened | `needsReview` | +| Active, PR approved | `readyToMerge` | +| Resolved | `done` | +| Closed | `done` | + +**Work item tags used by Squad:** +- `squad` — Work item is in Squad backlog +- `squad:{member}` — Assigned to specific agent + +**Branch naming convention:** +``` +squad/{work-item-id}-{kebab-case-slug} +``` +Example: `squad/1234-add-auth-module` + +### Microsoft Planner + +Planner does not have native Git integration. Squad uses Planner for task tracking and GitHub/ADO for code management. + +| Planner Status | Squad Board State | +|----------------|-------------------| +| Not Started | `untriaged` | +| In Progress, no PR | `inProgress` | +| In Progress, PR opened | `needsReview` | +| Completed | `done` | + +**Planner→Git workflow:** +1. Task created in Planner bucket +2. Agent reads task from Planner +3. Agent creates branch in GitHub/ADO repo +4. Agent opens PR referencing Planner task ID in description +5. Agent marks task as "Completed" when PR merges + +## Issue → Branch → PR → Merge Lifecycle + +### 1. Issue Assignment (Triage) + +**Trigger:** Ralph detects an untriaged issue or user manually assigns work. + +**Actions:** +1. Read `.squad/routing.md` to determine which agent should handle the issue +2. Apply `squad:{member}` label (GitHub) or tag (ADO) +3. Transition issue to `assigned` state +4. Optionally spawn agent immediately if issue is high-priority + +**Issue read command:** +```bash +# GitHub +gh issue view {number} --json number,title,body,labels,assignees + +# Azure DevOps +az boards work-item show --id {id} --output json +``` + +### 2. Branch Creation (Start Work) + +**Trigger:** Agent accepts issue assignment and begins work. + +**Actions:** +1. Ensure working on latest base branch (usually `main` or `dev`) +2. Create feature branch using Squad naming convention +3. Transition issue to `inProgress` state + +**Branch creation commands:** + +**Standard (single-agent, no parallelism):** +```bash +git checkout main && git pull && git checkout -b squad/{issue-number}-{slug} +``` + +**Worktree (parallel multi-agent):** +```bash +git worktree add ../worktrees/{issue-number} -b squad/{issue-number}-{slug} +cd ../worktrees/{issue-number} +``` + +> **Note:** Worktree support is in progress (#525). Current implementation uses standard checkout. + +### 3. Implementation & Commit + +**Actions:** +1. Agent makes code changes +2. Commits reference the issue number +3. Pushes branch to remote + +**Commit message format:** +``` +{type}({scope}): {description} (#{issue-number}) + +{detailed explanation if needed} + +{breaking change notice if applicable} + +Closes #{issue-number} + +Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> +``` + +**Commit types:** `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `perf`, `style`, `build`, `ci` + +**Push command:** +```bash +git push -u origin squad/{issue-number}-{slug} +``` + +### 4. PR Creation + +**Trigger:** Agent completes implementation and is ready for review. + +**Actions:** +1. Open PR from feature branch to base branch +2. Reference issue in PR description +3. Apply labels if needed +4. Transition issue to `needsReview` state + +**PR creation commands:** + +**GitHub:** +```bash +gh pr create --title "{title}" \ + --body "Closes #{issue-number}\n\n{description}" \ + --head squad/{issue-number}-{slug} \ + --base main +``` + +**Azure DevOps:** +```bash +az repos pr create --title "{title}" \ + --description "Closes #{work-item-id}\n\n{description}" \ + --source-branch squad/{work-item-id}-{slug} \ + --target-branch main +``` + +**PR description template:** +```markdown +Closes #{issue-number} + +## Summary +{what changed} + +## Changes +- {change 1} +- {change 2} + +## Testing +{how this was tested} + +{If working as a squad member:} +Working as {member} ({role}) + +{If needs human review:} +⚠️ This task was flagged as "needs review" — please have a squad member review before merging. +``` + +### 5. PR Review & Updates + +**Review states:** +- **Approved** → `readyToMerge` +- **Changes requested** → `changesRequested` +- **CI failure** → `ciFailure` + +**When changes are requested:** +1. Agent addresses feedback +2. Commits fixes to the same branch +3. Pushes updates +4. Requests re-review + +**Update workflow:** +```bash +# Make changes +git add . +git commit -m "fix: address review feedback" +git push +``` + +**Re-request review (GitHub):** +```bash +gh pr ready {pr-number} +``` + +### 6. PR Merge + +**Trigger:** PR is approved and CI passes. + +**Merge strategies:** + +**GitHub (merge commit):** +```bash +gh pr merge {pr-number} --merge --delete-branch +``` + +**GitHub (squash):** +```bash +gh pr merge {pr-number} --squash --delete-branch +``` + +**Azure DevOps:** +```bash +az repos pr update --id {pr-id} --status completed --delete-source-branch true +``` + +**Post-merge actions:** +1. Issue automatically closes (if "Closes #{number}" is in PR description) +2. Feature branch is deleted +3. Squad board state transitions to `done` +4. Worktree cleanup (if worktree was used — #525) + +### 7. Cleanup + +**Standard workflow cleanup:** +```bash +git checkout main +git pull +git branch -d squad/{issue-number}-{slug} +``` + +**Worktree cleanup (future, #525):** +```bash +cd {original-cwd} +git worktree remove ../worktrees/{issue-number} +``` + +## Spawn Prompt Additions for Issue Work + +When spawning an agent to work on an issue, include this context block: + +```markdown +## ISSUE CONTEXT + +**Issue:** #{number} — {title} +**Platform:** {GitHub | Azure DevOps | Planner} +**Repository:** {owner}/{repo} +**Assigned to:** {member} + +**Description:** +{issue body} + +**Labels/Tags:** +{labels} + +**Acceptance Criteria:** +{criteria if present in issue} + +**Branch:** `squad/{issue-number}-{slug}` + +**Your task:** +{specific directive to the agent} + +**After completing work:** +1. Commit with message referencing issue number +2. Push branch +3. Open PR using: + ``` + gh pr create --title "{title}" --body "Closes #{number}\n\n{description}" --head squad/{issue-number}-{slug} --base {base-branch} + ``` +4. Report PR URL to coordinator +``` + +## Ralph's Role in Issue Lifecycle + +Ralph (the work monitor) continuously checks issue and PR state: + +1. **Triage:** Detects untriaged issues, assigns `squad:{member}` labels +2. **Spawn:** Launches agents for assigned issues +3. **Monitor:** Tracks PR state transitions (needsReview → changesRequested → readyToMerge) +4. **Merge:** Automatically merges approved PRs +5. **Cleanup:** Marks issues as done when PRs merge + +**Ralph's work-check cycle:** +``` +Scan → Categorize → Dispatch → Watch → Report → Loop +``` + +See `.squad/templates/ralph-reference.md` for Ralph's full lifecycle. + +## PR Review Handling + +### Automated Approval (CI-only projects) + +If the project has no human reviewers configured: +1. PR opens +2. CI runs +3. If CI passes, Ralph auto-merges +4. Issue closes + +### Human Review Required + +If the project requires human approval: +1. PR opens +2. Human reviewer is notified (GitHub/ADO notifications) +3. Reviewer approves or requests changes +4. If approved + CI passes, Ralph merges +5. If changes requested, agent addresses feedback + +### Squad Member Review + +If the issue was assigned to a squad member and they authored the PR: +1. Another squad member reviews (conflict of interest avoidance) +2. Original author is locked out from re-working rejected code (rejection lockout) +3. Reviewer can approve edits or reject outright + +## Common Issue Lifecycle Patterns + +### Pattern 1: Quick Fix (Single Agent, No Review) +``` +Issue created → Assigned to agent → Branch created → Code fixed → +PR opened → CI passes → Auto-merged → Issue closed +``` + +### Pattern 2: Feature Development (Human Review) +``` +Issue created → Assigned to agent → Branch created → Feature implemented → +PR opened → Human reviews → Changes requested → Agent fixes → +Re-reviewed → Approved → Merged → Issue closed +``` + +### Pattern 3: Research-Then-Implement +``` +Issue created → Labeled `go:needs-research` → Research agent spawned → +Research documented → Research PR merged → Implementation issue created → +Implementation agent spawned → Feature built → PR merged +``` + +### Pattern 4: Parallel Multi-Agent (Future, #525) +``` +Epic issue created → Decomposed into sub-issues → Each sub-issue assigned → +Multiple agents work in parallel worktrees → PRs opened concurrently → +All PRs reviewed → All PRs merged → Epic closed +``` + +## Anti-Patterns + +- ❌ Creating branches without linking to an issue +- ❌ Committing without issue reference in message +- ❌ Opening PRs without "Closes #{number}" in description +- ❌ Merging PRs before CI passes +- ❌ Leaving feature branches undeleted after merge +- ❌ Using `checkout -b` when parallel agents are active (causes working directory conflicts) +- ❌ Manually transitioning issue states — let the platform and Squad automation handle it +- ❌ Skipping the branch naming convention — breaks Ralph's tracking logic + +## Migration Notes + +**v0.8.x → v0.9.x (Worktree Support):** +- `checkout -b` → `git worktree add` for parallel agents +- Worktree cleanup added to post-merge flow +- `TEAM_ROOT` passing to agents to support worktree-aware state resolution + +This template will be updated as worktree lifecycle support lands in #525. diff --git a/.squad-templates/keda-scaler.md b/.squad-templates/keda-scaler.md new file mode 100644 index 000000000..ba1646c5f --- /dev/null +++ b/.squad-templates/keda-scaler.md @@ -0,0 +1,164 @@ +# KEDA External Scaler for GitHub Issue-Driven Agent Autoscaling + +> Scale agent pods to zero when idle, up when work arrives — driven by GitHub Issues. + +## Overview + +When running Squad on Kubernetes, agent pods sit idle when no work exists. [KEDA](https://keda.sh) (Kubernetes Event-Driven Autoscaler) solves this for queue-based workloads, but GitHub Issues isn't a native KEDA trigger. + +The `keda-copilot-scaler` is a KEDA External Scaler (gRPC) that bridges this gap: +1. Polls GitHub API for issues matching specific labels (e.g., `squad:copilot`) +2. Reports queue depth as a KEDA metric +3. Handles rate limits gracefully (Retry-After, exponential backoff) +4. Supports composite scaling decisions + +## Quick Start + +### Prerequisites +- Kubernetes cluster with KEDA v2.x installed +- GitHub personal access token (PAT) with `repo` scope +- Helm 3.x + +### 1. Install the Scaler + +```bash +helm install keda-copilot-scaler oci://ghcr.io/tamirdresher/keda-copilot-scaler \ + --namespace squad-scaler --create-namespace \ + --set github.owner=YOUR_ORG \ + --set github.repo=YOUR_REPO \ + --set github.token=YOUR_TOKEN +``` + +Or with Kustomize: +```bash +kubectl apply -k https://github.com/tamirdresher/keda-copilot-scaler/deploy/kustomize +``` + +### 2. Create a ScaledObject + +```yaml +apiVersion: keda.sh/v1alpha1 +kind: ScaledObject +metadata: + name: picard-scaler + namespace: squad +spec: + scaleTargetRef: + name: picard-deployment + minReplicaCount: 0 # Scale to zero when idle + maxReplicaCount: 3 + pollingInterval: 30 # Check every 30 seconds + cooldownPeriod: 300 # Wait 5 minutes before scaling down + triggers: + - type: external + metadata: + scalerAddress: keda-copilot-scaler.squad-scaler.svc.cluster.local:6000 + owner: your-org + repo: your-repo + labels: squad:copilot # Only count issues with this label + threshold: "1" # Scale up when >= 1 issue exists +``` + +### 3. Verify + +```bash +# Check the scaler is running +kubectl get pods -n squad-scaler + +# Check ScaledObject status +kubectl get scaledobject picard-scaler -n squad + +# Watch scaling events +kubectl get events -n squad --watch +``` + +## Scaling Behavior + +| Open Issues | Target Replicas | Behavior | +|------------|----------------|----------| +| 0 | 0 | Scale to zero — save resources | +| 1–3 | 1 | Single agent handles work | +| 4–10 | 2 | Scale up for parallel processing | +| 10+ | 3 (max) | Maximum parallelism | + +The threshold and max replicas are configurable per ScaledObject. + +## Rate Limit Awareness + +The scaler tracks GitHub API rate limits: +- Reads `X-RateLimit-Remaining` from API responses +- Backs off when quota is low (< 100 remaining) +- Reports rate limit metrics as secondary KEDA triggers +- Never exhausts API quota from polling + +## Integration with Squad + +### Machine Capabilities (#514) + +Combine with machine capability labels for intelligent scheduling: + +```yaml +# Only scale pods on GPU-capable nodes +spec: + template: + spec: + nodeSelector: + node.squad.dev/gpu: "true" + triggers: + - type: external + metadata: + labels: squad:copilot,needs:gpu +``` + +### Cooperative Rate Limiting (#515) + +The scaler exposes rate limit metrics that feed into the cooperative rate limiting system: +- Current `X-RateLimit-Remaining` value +- Predicted time to exhaustion (from predictive circuit breaker) +- Can return 0 target replicas when rate limited → pods scale to zero + +## Architecture + +``` +GitHub API KEDA Kubernetes +┌──────────┐ ┌──────────┐ ┌──────────────┐ +│ Issues │◄── poll ──►│ Scaler │──metrics─►│ HPA / KEDA │ +│ (REST) │ │ (gRPC) │ │ Controller │ +└──────────┘ └──────────┘ └──────┬───────┘ + │ + scale up/down + │ + ┌──────▼───────┐ + │ Agent Pods │ + │ (0–N replicas)│ + └──────────────┘ +``` + +## Configuration Reference + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `github.owner` | — | Repository owner | +| `github.repo` | — | Repository name | +| `github.token` | — | GitHub PAT with `repo` scope | +| `github.labels` | `squad:copilot` | Comma-separated label filter | +| `scaler.port` | `6000` | gRPC server port | +| `scaler.pollInterval` | `30s` | GitHub API polling interval | +| `scaler.rateLimitThreshold` | `100` | Stop polling below this remaining | + +## Source & Contributing + +- **Repository:** [tamirdresher/keda-copilot-scaler](https://github.com/tamirdresher/keda-copilot-scaler) +- **License:** MIT +- **Language:** Go +- **Tests:** 51 passing (unit + integration) +- **CI:** GitHub Actions + +The scaler is maintained as a standalone project. PRs and issues welcome. + +## References + +- [KEDA External Scalers](https://keda.sh/docs/latest/concepts/external-scalers/) — KEDA documentation +- [Squad on AKS](https://github.com/tamirdresher/squad-on-aks) — Full Kubernetes deployment example +- [Machine Capabilities](machine-capabilities.md) — Capability-based routing (#514) +- [Cooperative Rate Limiting](cooperative-rate-limiting.md) — Multi-agent rate management (#515) diff --git a/.squad-templates/machine-capabilities.md b/.squad-templates/machine-capabilities.md new file mode 100644 index 000000000..b770fd04b --- /dev/null +++ b/.squad-templates/machine-capabilities.md @@ -0,0 +1,75 @@ +# Machine Capability Discovery & Label-Based Routing + +> Enable Ralph to skip issues requiring capabilities the current machine lacks. + +## Overview + +When running Squad across multiple machines (laptops, DevBoxes, GPU servers, Kubernetes nodes), each machine has different tooling. The capability system lets you declare what each machine can do, and Ralph automatically routes work accordingly. + +## Setup + +### 1. Create a Capabilities Manifest + +Create `~/.squad/machine-capabilities.json` (user-wide) or `.squad/machine-capabilities.json` (project-local): + +```json +{ + "machine": "MY-LAPTOP", + "capabilities": ["browser", "personal-gh", "onedrive"], + "missing": ["gpu", "docker", "azure-speech"], + "lastUpdated": "2026-03-22T00:00:00Z" +} +``` + +### 2. Label Issues with Requirements + +Add `needs:*` labels to issues that require specific capabilities: + +| Label | Meaning | +|-------|---------| +| `needs:browser` | Requires Playwright / browser automation | +| `needs:gpu` | Requires NVIDIA GPU | +| `needs:personal-gh` | Requires personal GitHub account | +| `needs:emu-gh` | Requires Enterprise Managed User account | +| `needs:azure-cli` | Requires authenticated Azure CLI | +| `needs:docker` | Requires Docker daemon | +| `needs:onedrive` | Requires OneDrive sync | +| `needs:teams-mcp` | Requires Teams MCP tools | + +Custom capabilities are supported — any `needs:X` label works if `X` is in the machine's `capabilities` array. + +### 3. Run Ralph + +```bash +squad watch --interval 5 +``` + +Ralph will log skipped issues: +``` +⏭️ Skipping #42 "Train ML model" — missing: gpu +✓ Triaged #43 "Fix CSS layout" → Picard (routing-rule) +``` + +## How It Works + +1. Ralph loads `machine-capabilities.json` at startup +2. For each open issue, Ralph extracts `needs:*` labels +3. If any required capability is missing, the issue is skipped +4. Issues without `needs:*` labels are always processed (opt-in system) + +## Kubernetes Integration + +On Kubernetes, machine capabilities map to node labels: + +```yaml +# Node labels (set by capability DaemonSet or manually) +node.squad.dev/gpu: "true" +node.squad.dev/browser: "true" + +# Pod spec uses nodeSelector +spec: + nodeSelector: + node.squad.dev/gpu: "true" +``` + +A DaemonSet can run capability discovery on each node and maintain labels automatically. See the [squad-on-aks](https://github.com/tamirdresher/squad-on-aks) project for a complete Kubernetes deployment example. \ No newline at end of file diff --git a/.squad-templates/ralph-circuit-breaker.md b/.squad-templates/ralph-circuit-breaker.md new file mode 100644 index 000000000..87be26015 --- /dev/null +++ b/.squad-templates/ralph-circuit-breaker.md @@ -0,0 +1,313 @@ +# Ralph Circuit Breaker — Model Rate Limit Fallback + +> Classic circuit breaker pattern (Hystrix / Polly / Resilience4j) applied to Copilot model selection. +> When the preferred model hits rate limits, Ralph automatically degrades to free-tier models, then self-heals. + +## Problem + +When running multiple Ralph instances across repos, Copilot model rate limits cause cascading failures. +All Ralphs fail simultaneously when the preferred model (e.g., `claude-sonnet-4.6`) hits quota. + +Premium models burn quota fast: +| Model | Multiplier | Risk | +|-------|-----------|------| +| `claude-sonnet-4.6` | 1x | Moderate with many Ralphs | +| `claude-opus-4.6` | 10x | High | +| `gpt-5.4` | 50x | Very high | +| `gpt-5.4-mini` | **0x** | **Free — unlimited** | +| `gpt-5-mini` | **0x** | **Free — unlimited** | +| `gpt-4.1` | **0x** | **Free — unlimited** | + +## Circuit Breaker States + +``` +┌─────────┐ rate limit error ┌────────┐ +│ CLOSED │ ───────────────────► │ OPEN │ +│ (normal)│ │(fallback)│ +└────┬────┘ ◄──────────────── └────┬────┘ + │ 2 consecutive │ + │ successes │ cooldown expires + │ ▼ + │ ┌──────────┐ + └───── success ◄──────── │HALF-OPEN │ + (close) │ (testing) │ + └──────────┘ +``` + +### CLOSED (normal operation) +- Use preferred model from config +- Every successful response confirms circuit stays closed +- On rate limit error → transition to OPEN + +### OPEN (rate limited — fallback active) +- Fall back through the free-tier model chain: + 1. `gpt-5.4-mini` + 2. `gpt-5-mini` + 3. `gpt-4.1` +- Start cooldown timer (default: 10 minutes) +- When cooldown expires → transition to HALF-OPEN + +### HALF-OPEN (testing recovery) +- Try preferred model again +- If 2 consecutive successes → transition to CLOSED +- If rate limit error → back to OPEN, reset cooldown + +## State File: `.squad/ralph-circuit-breaker.json` + +```json +{ + "state": "closed", + "preferredModel": "claude-sonnet-4.6", + "fallbackChain": ["gpt-5.4-mini", "gpt-5-mini", "gpt-4.1"], + "currentFallbackIndex": 0, + "cooldownMinutes": 10, + "openedAt": null, + "halfOpenSuccesses": 0, + "consecutiveFailures": 0, + "metrics": { + "totalFallbacks": 0, + "totalRecoveries": 0, + "lastFallbackAt": null, + "lastRecoveryAt": null + } +} +``` + +## PowerShell Functions + +Paste these into your `ralph-watch.ps1` or source them from a shared module. + +### `Get-CircuitBreakerState` + +```powershell +function Get-CircuitBreakerState { + param([string]$StateFile = ".squad/ralph-circuit-breaker.json") + + if (-not (Test-Path $StateFile)) { + $default = @{ + state = "closed" + preferredModel = "claude-sonnet-4.6" + fallbackChain = @("gpt-5.4-mini", "gpt-5-mini", "gpt-4.1") + currentFallbackIndex = 0 + cooldownMinutes = 10 + openedAt = $null + halfOpenSuccesses = 0 + consecutiveFailures = 0 + metrics = @{ + totalFallbacks = 0 + totalRecoveries = 0 + lastFallbackAt = $null + lastRecoveryAt = $null + } + } + $default | ConvertTo-Json -Depth 3 | Set-Content $StateFile + return $default + } + + return (Get-Content $StateFile -Raw | ConvertFrom-Json) +} +``` + +### `Save-CircuitBreakerState` + +```powershell +function Save-CircuitBreakerState { + param( + [object]$State, + [string]$StateFile = ".squad/ralph-circuit-breaker.json" + ) + + $State | ConvertTo-Json -Depth 3 | Set-Content $StateFile +} +``` + +### `Get-CurrentModel` + +Returns the model Ralph should use right now, based on circuit state. + +```powershell +function Get-CurrentModel { + param([string]$StateFile = ".squad/ralph-circuit-breaker.json") + + $cb = Get-CircuitBreakerState -StateFile $StateFile + + switch ($cb.state) { + "closed" { + return $cb.preferredModel + } + "open" { + # Check if cooldown has expired + if ($cb.openedAt) { + $opened = [DateTime]::Parse($cb.openedAt) + $elapsed = (Get-Date) - $opened + if ($elapsed.TotalMinutes -ge $cb.cooldownMinutes) { + # Transition to half-open + $cb.state = "half-open" + $cb.halfOpenSuccesses = 0 + Save-CircuitBreakerState -State $cb -StateFile $StateFile + Write-Host " [circuit-breaker] Cooldown expired. Testing preferred model..." -ForegroundColor Yellow + return $cb.preferredModel + } + } + # Still in cooldown — use fallback + $idx = [Math]::Min($cb.currentFallbackIndex, $cb.fallbackChain.Count - 1) + return $cb.fallbackChain[$idx] + } + "half-open" { + return $cb.preferredModel + } + default { + return $cb.preferredModel + } + } +} +``` + +### `Update-CircuitBreakerOnSuccess` + +Call after every successful model response. + +```powershell +function Update-CircuitBreakerOnSuccess { + param([string]$StateFile = ".squad/ralph-circuit-breaker.json") + + $cb = Get-CircuitBreakerState -StateFile $StateFile + $cb.consecutiveFailures = 0 + + if ($cb.state -eq "half-open") { + $cb.halfOpenSuccesses++ + if ($cb.halfOpenSuccesses -ge 2) { + # Recovery! Close the circuit + $cb.state = "closed" + $cb.openedAt = $null + $cb.halfOpenSuccesses = 0 + $cb.currentFallbackIndex = 0 + $cb.metrics.totalRecoveries++ + $cb.metrics.lastRecoveryAt = (Get-Date).ToString("o") + Save-CircuitBreakerState -State $cb -StateFile $StateFile + Write-Host " [circuit-breaker] RECOVERED — back to preferred model ($($cb.preferredModel))" -ForegroundColor Green + return + } + Save-CircuitBreakerState -State $cb -StateFile $StateFile + Write-Host " [circuit-breaker] Half-open success $($cb.halfOpenSuccesses)/2" -ForegroundColor Yellow + return + } + + # closed state — nothing to do +} +``` + +### `Update-CircuitBreakerOnRateLimit` + +Call when a model response indicates rate limiting (HTTP 429 or error message containing "rate limit"). + +```powershell +function Update-CircuitBreakerOnRateLimit { + param([string]$StateFile = ".squad/ralph-circuit-breaker.json") + + $cb = Get-CircuitBreakerState -StateFile $StateFile + $cb.consecutiveFailures++ + + if ($cb.state -eq "closed" -or $cb.state -eq "half-open") { + # Open the circuit + $cb.state = "open" + $cb.openedAt = (Get-Date).ToString("o") + $cb.halfOpenSuccesses = 0 + $cb.currentFallbackIndex = 0 + $cb.metrics.totalFallbacks++ + $cb.metrics.lastFallbackAt = (Get-Date).ToString("o") + Save-CircuitBreakerState -State $cb -StateFile $StateFile + + $fallbackModel = $cb.fallbackChain[0] + Write-Host " [circuit-breaker] RATE LIMITED — falling back to $fallbackModel (cooldown: $($cb.cooldownMinutes)m)" -ForegroundColor Red + return + } + + if ($cb.state -eq "open") { + # Already open — try next fallback in chain if current one also fails + if ($cb.currentFallbackIndex -lt ($cb.fallbackChain.Count - 1)) { + $cb.currentFallbackIndex++ + $nextModel = $cb.fallbackChain[$cb.currentFallbackIndex] + Write-Host " [circuit-breaker] Fallback also limited — trying $nextModel" -ForegroundColor Red + } + # Reset cooldown timer + $cb.openedAt = (Get-Date).ToString("o") + Save-CircuitBreakerState -State $cb -StateFile $StateFile + } +} +``` + +## Integration with ralph-watch.ps1 + +In your Ralph polling loop, wrap the model selection: + +```powershell +# At the top of your polling loop +$model = Get-CurrentModel + +# When invoking copilot CLI +$result = copilot-cli --model $model ... + +# After the call +if ($result -match "rate.?limit" -or $LASTEXITCODE -eq 429) { + Update-CircuitBreakerOnRateLimit +} else { + Update-CircuitBreakerOnSuccess +} +``` + +### Full integration example + +```powershell +# Source the circuit breaker functions +. .squad-templates/ralph-circuit-breaker-functions.ps1 + +while ($true) { + $model = Get-CurrentModel + Write-Host "Polling with model: $model" + + try { + # Your existing Ralph logic here, but pass $model + $response = Invoke-RalphCycle -Model $model + + # Success path + Update-CircuitBreakerOnSuccess + } + catch { + if ($_.Exception.Message -match "rate.?limit|429|quota|Too Many Requests") { + Update-CircuitBreakerOnRateLimit + # Retry immediately with fallback model + continue + } + # Other errors — handle normally + throw + } + + Start-Sleep -Seconds $pollInterval +} +``` + +## Configuration + +Override defaults by editing `.squad/ralph-circuit-breaker.json`: + +| Field | Default | Description | +|-------|---------|-------------| +| `preferredModel` | `claude-sonnet-4.6` | Model to use when circuit is closed | +| `fallbackChain` | `["gpt-5.4-mini", "gpt-5-mini", "gpt-4.1"]` | Ordered fallback models (all free-tier) | +| `cooldownMinutes` | `10` | How long to wait before testing recovery | + +## Metrics + +The state file tracks operational metrics: + +- **totalFallbacks** — How many times the circuit opened +- **totalRecoveries** — How many times it recovered to preferred model +- **lastFallbackAt** — ISO timestamp of last rate limit event +- **lastRecoveryAt** — ISO timestamp of last successful recovery + +Query metrics with: +```powershell +$cb = Get-Content .squad/ralph-circuit-breaker.json | ConvertFrom-Json +Write-Host "Fallbacks: $($cb.metrics.totalFallbacks) | Recoveries: $($cb.metrics.totalRecoveries)" +``` diff --git a/.squad-templates/routing.md b/.squad-templates/routing.md index 490b128e1..65e0e9f45 100644 --- a/.squad-templates/routing.md +++ b/.squad-templates/routing.md @@ -12,35 +12,21 @@ How to decide who handles what. | Code review | {Name} | Review PRs, check quality, suggest improvements | | Testing | {Name} | Write tests, find edge cases, verify fixes | | Scope & priorities | {Name} | What to build next, trade-offs, decisions | -| Async issue work (bugs, tests, small features) | @copilot 🤖 | Well-defined tasks matching capability profile | | Session logging | Scribe | Automatic — never needs routing | ## Issue Routing | Label | Action | Who | |-------|--------|-----| -| `squad` | Triage: analyze issue, evaluate @copilot fit, assign `squad:{member}` label | Lead | +| `squad` | Triage: analyze issue, assign `squad:{member}` label | Lead | | `squad:{name}` | Pick up issue and complete the work | Named member | -| `squad:copilot` | Assign to @copilot for autonomous work (if enabled) | @copilot 🤖 | ### How Issue Assignment Works -1. When a GitHub issue gets the `squad` label, the **Lead** triages it — analyzing content, evaluating @copilot's capability profile, assigning the right `squad:{member}` label, and commenting with triage notes. -2. **@copilot evaluation:** The Lead checks if the issue matches @copilot's capability profile (🟢 good fit / 🟡 needs review / 🔴 not suitable). If it's a good fit, the Lead may route to `squad:copilot` instead of a squad member. -3. When a `squad:{member}` label is applied, that member picks up the issue in their next session. -4. When `squad:copilot` is applied and auto-assign is enabled, `@copilot` is assigned on the issue and picks it up autonomously. -5. Members can reassign by removing their label and adding another member's label. -6. The `squad` label is the "inbox" — untriaged issues waiting for Lead review. - -### Lead Triage Guidance for @copilot - -When triaging, the Lead should ask: - -1. **Is this well-defined?** Clear title, reproduction steps or acceptance criteria, bounded scope → likely 🟢 -2. **Does it follow existing patterns?** Adding a test, fixing a known bug, updating a dependency → likely 🟢 -3. **Does it need design judgment?** Architecture, API design, UX decisions → likely 🔴 -4. **Is it security-sensitive?** Auth, encryption, access control → always 🔴 -5. **Is it medium complexity with specs?** Feature with clear requirements, refactoring with tests → likely 🟡 +1. When a GitHub issue gets the `squad` label, the **Lead** triages it — analyzing content, assigning the right `squad:{member}` label, and commenting with triage notes. +2. When a `squad:{member}` label is applied, that member picks up the issue in their next session. +3. Members can reassign by removing their label and adding another member's label. +4. The `squad` label is the "inbox" — untriaged issues waiting for Lead review. ## Rules @@ -51,4 +37,3 @@ When triaging, the Lead should ask: 5. **"Team, ..." → fan-out.** Spawn all relevant agents in parallel as `mode: "background"`. 6. **Anticipate downstream work.** If a feature is being built, spawn the tester to write test cases from requirements simultaneously. 7. **Issue-labeled work** — when a `squad:{member}` label is applied to an issue, route to that member. The Lead handles all `squad` (base label) triage. -8. **@copilot routing** — when evaluating issues, check @copilot's capability profile in `team.md`. Route 🟢 good-fit tasks to `squad:copilot`. Flag 🟡 needs-review tasks for PR review. Keep 🔴 not-suitable tasks with squad members. diff --git a/.squad-templates/squad.agent.md b/.squad-templates/squad.agent.md index fff5de0e3..12f47139c 100644 --- a/.squad-templates/squad.agent.md +++ b/.squad-templates/squad.agent.md @@ -112,6 +112,22 @@ When triggered: **Casting migration check:** If `.squad/team.md` exists but `.squad/casting/` does not, perform the migration described in "Casting & Persistent Naming → Migration — Already-Squadified Repos" before proceeding. +### Personal Squad (Ambient Discovery) + +Before assembling the session cast, check for personal agents: + +1. **Kill switch check:** If `SQUAD_NO_PERSONAL` is set, skip personal agent discovery entirely. +2. **Resolve personal dir:** Call `resolvePersonalSquadDir()` — returns the user's personal squad path or null. +3. **Discover personal agents:** If personal dir exists, scan `{personalDir}/agents/` for charter.md files. +4. **Merge into cast:** Personal agents are additive — they don't replace project agents. On name conflict, project agent wins. +5. **Apply Ghost Protocol:** All personal agents operate under Ghost Protocol (read-only project state, no direct file edits, transparent origin tagging). + +**Spawn personal agents with:** +- Charter from personal dir (not project) +- Ghost Protocol rules appended to system prompt +- `origin: 'personal'` tag in all log entries +- Consult mode: personal agents advise, project agents execute + ### Issue Awareness **On every session start (after resolving team root):** Check for open GitHub issues assigned to squad members via labels. Use the GitHub CLI or API to list issues with `squad:*` labels: @@ -216,6 +232,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | Signal | Action | |--------|--------| | Names someone ("Ripley, fix the button") | Spawn that agent | +| Personal agent by name (user addresses a personal agent) | Route to personal agent in consult mode — they advise, project agent executes changes | | "Team" or multi-domain question | Spawn 2-3+ relevant agents in parallel, synthesize | | Human member management ("add Brady as PM", routes to human) | Follow Human Team Members (see that section) | | Issue suitable for @copilot (when @copilot is on the roster) | Check capability profile in team.md, suggest routing to @copilot if it's a good fit | @@ -231,6 +248,14 @@ The routing table determines **WHO** handles work. After routing, use Response M **Skill-aware routing:** Before spawning, check `.squad/skills/` for skills relevant to the task domain. If a matching skill exists, add to the spawn prompt: `Relevant skill: .squad/skills/{name}/SKILL.md — read before starting.` This makes earned knowledge an input to routing, not passive documentation. +### Consult Mode Detection + +When a user addresses a personal agent by name: +1. Route the request to the personal agent +2. Tag the interaction as consult mode +3. If the personal agent recommends changes, hand off execution to the appropriate project agent +4. Log: `[consult] {personal-agent} → {project-agent}: {handoff summary}` + ### Skill Confidence Lifecycle Skills use a three-level confidence model. Confidence only goes up, never down. @@ -293,7 +318,13 @@ description: "{emoji} {Name}: {brief task summary}" prompt: | You are {Name}, the {Role} on this project. TEAM ROOT: {team_root} + WORKTREE_PATH: {worktree_path} + WORKTREE_MODE: {true|false} **Requested by:** {current user name} + + {% if WORKTREE_MODE %} + **WORKTREE:** Working in `{WORKTREE_PATH}`. All operations relative to this path. Do NOT switch branches. + {% endif %} TASK: {specific task description} TARGET FILE(S): {exact file path(s)} @@ -311,7 +342,13 @@ For read-only queries, use the explore agent: `agent_type: "explore"` with `"You Before spawning an agent, determine which model to use. Check these layers in order — first match wins: -**Layer 1 — User Override:** Did the user specify a model? ("use opus", "save costs", "use gpt-5.2-codex for this"). If yes, use that model. Session-wide directives ("always use haiku") persist until contradicted. +**Layer 0 — Persistent Config (`.squad/config.json`):** On session start, read `.squad/config.json`. If `agentModelOverrides.{agentName}` exists, use that model for this specific agent. Otherwise, if `defaultModel` exists, use it for ALL agents. This layer survives across sessions — the user set it once and it sticks. + +- **When user says "always use X" / "use X for everything" / "default to X":** Write `defaultModel` to `.squad/config.json`. Acknowledge: `✅ Model preference saved: {model} — all future sessions will use this until changed.` +- **When user says "use X for {agent}":** Write to `agentModelOverrides.{agent}` in `.squad/config.json`. Acknowledge: `✅ {Agent} will always use {model} — saved to config.` +- **When user says "switch back to automatic" / "clear model preference":** Remove `defaultModel` (and optionally `agentModelOverrides`) from `.squad/config.json`. Acknowledge: `✅ Model preference cleared — returning to automatic selection.` + +**Layer 1 — Session Directive:** Did the user specify a model for this session? ("use opus for this session", "save costs"). If yes, use that model. Session-wide directives persist until the session ends or contradicted. **Layer 2 — Charter Preference:** Does the agent's charter have a `## Model` section with `Preferred` set to a specific model (not `auto`)? If yes, use that model. @@ -599,6 +636,39 @@ Squad and all spawned agents may be running inside a **git worktree** rather tha - **Not safe for concurrent sessions.** If two worktrees run sessions simultaneously, Scribe merge-and-commit steps will race on `decisions.md` and git index. Use only when a single session is active at a time. - Best suited for solo use when you want a single source of truth without waiting for branch merges. +### Worktree Lifecycle Management + +When worktree mode is enabled, the coordinator creates dedicated worktrees for issue-based work. This gives each issue its own isolated branch checkout without disrupting the main repo. + +**Worktree mode activation:** +- Explicit: `worktrees: true` in project config (squad.config.ts or package.json `squad` section) +- Environment: `SQUAD_WORKTREES=1` set in environment variables +- Default: `false` (backward compatibility — agents work in the main repo) + +**Creating worktrees:** +- One worktree per issue number +- Multiple agents on the same issue share a worktree +- Path convention: `{repo-parent}/{repo-name}-{issue-number}` + - Example: Working on issue #42 in `C:\src\squad` → worktree at `C:\src\squad-42` +- Branch: `squad/{issue-number}-{kebab-case-slug}` (created from base branch, typically `main`) + +**Dependency management:** +- After creating a worktree, link `node_modules` from the main repo to avoid reinstalling +- Windows: `cmd /c "mklink /J {worktree}\node_modules {main-repo}\node_modules"` +- Unix: `ln -s {main-repo}/node_modules {worktree}/node_modules` +- If linking fails (permissions, cross-device), fall back to `npm install` in the worktree + +**Reusing worktrees:** +- Before creating a new worktree, check if one exists for the same issue +- `git worktree list` shows all active worktrees +- If found, reuse it (cd to the path, verify branch is correct, `git pull` to sync) +- Multiple agents can work in the same worktree concurrently if they modify different files + +**Cleanup:** +- After a PR is merged, the worktree should be removed +- `git worktree remove {path}` + `git branch -d {branch}` +- Ralph heartbeat can trigger cleanup checks for merged branches + ### Orchestration Logging Orchestration log entries are written by **Scribe**, not the coordinator. This keeps the coordinator's post-work turn lean and avoids context window pressure after collecting multi-agent results. @@ -607,6 +677,53 @@ The coordinator passes a **spawn manifest** (who ran, why, what mode, outcome) t Each entry records: agent routed, why chosen, mode (background/sync), files authorized to read, files produced, and outcome. See `.squad/templates/orchestration-log.md` for the field format. +### Pre-Spawn: Worktree Setup + +When spawning an agent for issue-based work (user request references an issue number, or agent is working on a GitHub issue): + +**1. Check worktree mode:** +- Is `SQUAD_WORKTREES=1` set in the environment? +- Or does the project config have `worktrees: true`? +- If neither: skip worktree setup → agent works in the main repo (existing behavior) + +**2. If worktrees enabled:** + +a. **Determine the worktree path:** + - Parse issue number from context (e.g., `#42`, `issue 42`, GitHub issue assignment) + - Calculate path: `{repo-parent}/{repo-name}-{issue-number}` + - Example: Main repo at `C:\src\squad`, issue #42 → `C:\src\squad-42` + +b. **Check if worktree already exists:** + - Run `git worktree list` to see all active worktrees + - If the worktree path already exists → **reuse it**: + - Verify the branch is correct (should be `squad/{issue-number}-*`) + - `cd` to the worktree path + - `git pull` to sync latest changes + - Skip to step (e) + +c. **Create the worktree:** + - Determine branch name: `squad/{issue-number}-{kebab-case-slug}` (derive slug from issue title if available) + - Determine base branch (typically `main`, check default branch if needed) + - Run: `git worktree add {path} -b {branch} {baseBranch}` + - Example: `git worktree add C:\src\squad-42 -b squad/42-fix-login main` + +d. **Set up dependencies:** + - Link `node_modules` from main repo to avoid reinstalling: + - Windows: `cmd /c "mklink /J {worktree}\node_modules {main-repo}\node_modules"` + - Unix: `ln -s {main-repo}/node_modules {worktree}/node_modules` + - If linking fails (error), fall back: `cd {worktree} && npm install` + - Verify the worktree is ready: check build tools are accessible + +e. **Include worktree context in spawn:** + - Set `WORKTREE_PATH` to the resolved worktree path + - Set `WORKTREE_MODE` to `true` + - Add worktree instructions to the spawn prompt (see template below) + +**3. If worktrees disabled:** +- Set `WORKTREE_PATH` to `"n/a"` +- Set `WORKTREE_MODE` to `false` +- Use existing `git checkout -b` flow (no changes to current behavior) + ### How to Spawn an Agent **You MUST call the `task` tool** with these parameters for every agent spawn: @@ -640,6 +757,29 @@ prompt: | TEAM ROOT: {team_root} All `.squad/` paths are relative to this root. + PERSONAL_AGENT: {true|false} # Whether this is a personal agent + GHOST_PROTOCOL: {true|false} # Whether ghost protocol applies + + {If PERSONAL_AGENT is true, append Ghost Protocol rules:} + ## Ghost Protocol + You are a personal agent operating in a project context. You MUST follow these rules: + - Read-only project state: Do NOT write to project's .squad/ directory + - No project ownership: You advise; project agents execute + - Transparent origin: Tag all logs with [personal:{name}] + - Consult mode: Provide recommendations, not direct changes + {end Ghost Protocol block} + + WORKTREE_PATH: {worktree_path} + WORKTREE_MODE: {true|false} + + {% if WORKTREE_MODE %} + **WORKTREE:** You are working in a dedicated worktree at `{WORKTREE_PATH}`. + - All file operations should be relative to this path + - Do NOT switch branches — the worktree IS your branch (`{branch_name}`) + - Build and test in the worktree, not the main repo + - Commit and push from the worktree + {% endif %} + Read .squad/agents/{name}/history.md (your project knowledge). Read .squad/decisions.md (team decisions to respect). If .squad/identity/wisdom.md exists, read it before starting work. @@ -817,7 +957,7 @@ Agent names are drawn from a single fictional universe per assignment. Names are **Rules (always loaded):** - ONE UNIVERSE PER ASSIGNMENT. NEVER MIX. -- 31 universes available (capacity 6–25). See reference file for full list. +- 15 universes available (capacity 6–25). See reference file for full list. - Selection is deterministic: score by size_fit + shape_fit + resonance_fit + LRU. - Same inputs → same choice (unless LRU changes). diff --git a/.squad-templates/workflows/squad-heartbeat.yml b/.squad-templates/workflows/squad-heartbeat.yml index 50556fb2c..70a14cbc7 100644 --- a/.squad-templates/workflows/squad-heartbeat.yml +++ b/.squad-templates/workflows/squad-heartbeat.yml @@ -7,10 +7,9 @@ name: Squad Heartbeat (Ralph) # Run 'squad upgrade' to sync installed copies from source templates. on: - # DISABLED: Cron heartbeat commented out pre-migration — re-enable when ready - # schedule: - # # Every 30 minutes — adjust or remove if not needed - # - cron: '*/30 * * * *' + schedule: + # Every 30 minutes — adjust via cron expression as needed + - cron: '*/30 * * * *' # React to completed work or new squad work issues: diff --git a/.squad/agents/_alumni/baer/charter.md b/.squad/agents/_alumni/baer/charter.md index 90846bfdb..c0ff32045 100644 --- a/.squad/agents/_alumni/baer/charter.md +++ b/.squad/agents/_alumni/baer/charter.md @@ -29,24 +29,5 @@ **I don't handle:** Feature implementation, docs, distribution, visual design. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model - -- **Preferred:** auto -- **Rationale:** Security review uses sonnet for thoroughness. Planning uses haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/baer-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Thorough but pragmatic. Doesn't cry wolf. When Baer raises a risk, it's a real one that needs addressing. Believes security is infrastructure, not a checklist. Hook-based governance is the hill to die on. +Preferred: auto diff --git a/.squad/agents/_alumni/drucker/charter.md b/.squad/agents/_alumni/drucker/charter.md index 28d7d0c09..82e73ed45 100644 --- a/.squad/agents/_alumni/drucker/charter.md +++ b/.squad/agents/_alumni/drucker/charter.md @@ -24,6 +24,8 @@ **Defense in depth:** Every workflow has validation gates. Humans make mistakes. CI catches them before they ship. +**Known failure modes:** Read `.squad/skills/ci-validation-gates/SKILL.md` for defensive CI patterns and known failure modes. + **Automated validation gates:** - **Semver validation:** Every publish workflow MUST validate version format before `npm publish` (no 4-part versions) - **Token verification:** Check NPM_TOKEN type before first publish (Automation tokens only, no User tokens with 2FA) @@ -121,8 +123,6 @@ These failures are inherited from the v0.8.22 disaster and inform Drucker's defe - Manual release orchestration (tagging, GitHub Release creation) — that's Trejo's domain - Feature implementation or bug fixes -**When I'm unsure:** I say so and suggest who might know. If release scope or version numbering is unclear, I bring in Trejo. If workflow needs architectural changes, I bring in Keaton. - **Delegation:** - **Trejo owns release decisions** — version numbers, when to release, what goes in a release, rollback decisions. - **I own CI/CD automation** — workflow code, validation gates, retry logic, publish pipeline, CI health. diff --git a/.squad/agents/_alumni/edie/charter.md b/.squad/agents/_alumni/edie/charter.md index 0e102deff..6184a5c04 100644 --- a/.squad/agents/_alumni/edie/charter.md +++ b/.squad/agents/_alumni/edie/charter.md @@ -32,22 +32,5 @@ **I don't handle:** Runtime implementation details, prompts, docs, security hooks, distribution mechanics. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/edie-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Precise and type-obsessed. Types are contracts — if it compiles, it works. Pushes back hard on any `any`, `@ts-ignore`, or loose typing. Believes the type system is documentation that the compiler enforces. +Preferred: auto diff --git a/.squad/agents/_alumni/fenster/charter.md b/.squad/agents/_alumni/fenster/charter.md index 1b99198f1..136519119 100644 --- a/.squad/agents/_alumni/fenster/charter.md +++ b/.squad/agents/_alumni/fenster/charter.md @@ -32,22 +32,5 @@ **I don't handle:** Prompt architecture, type system design, docs, security policy, visual design. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/fenster-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Practical and thorough. Doesn't over-engineer but doesn't cut corners. Finds the straightforward path through complexity. If the casting algorithm needs three steps, it gets three steps — not five for elegance or one for speed. +Preferred: auto diff --git a/.squad/agents/_alumni/fortier/charter.md b/.squad/agents/_alumni/fortier/charter.md index 6ea761dc8..cf8968788 100644 --- a/.squad/agents/_alumni/fortier/charter.md +++ b/.squad/agents/_alumni/fortier/charter.md @@ -32,22 +32,5 @@ **I don't handle:** Type system design, prompt architecture, docs, distribution, security policy. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/fortier-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Performance-aware and event-driven. Thinks in terms of event loops, backpressure, and async boundaries. If it blocks the event loop, it's wrong. If it buffers when it could stream, it's wasteful. +Preferred: auto diff --git a/.squad/agents/_alumni/hockney/charter.md b/.squad/agents/_alumni/hockney/charter.md index 0aba444b3..61c3fd7ec 100644 --- a/.squad/agents/_alumni/hockney/charter.md +++ b/.squad/agents/_alumni/hockney/charter.md @@ -30,24 +30,5 @@ **I don't handle:** Feature implementation, docs, architecture decisions, distribution. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes test code — uses sonnet for quality. Simple scaffolding can use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/hockney-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Skeptical and relentless. Assumes every feature has a bug until proven otherwise. Pushes back on skipped tests. Prefers integration tests over mocks. Thinks 80% coverage is the floor, not the ceiling. +Preferred: auto diff --git a/.squad/agents/_alumni/keaton/charter.md b/.squad/agents/_alumni/keaton/charter.md index 2a5c5ff60..227bcbcdb 100644 --- a/.squad/agents/_alumni/keaton/charter.md +++ b/.squad/agents/_alumni/keaton/charter.md @@ -29,24 +29,9 @@ **I don't handle:** Implementation details, test writing, docs, distribution, security audits. -**When I'm unsure:** I say so and suggest who might know. -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. ## Model +Preferred: auto -- **Preferred:** auto -- **Rationale:** Coordinator selects — planning uses haiku, code review uses sonnet, architecture proposals may bump to premium -- **Fallback:** Standard chain -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/keaton-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Decisive and opinionated when it matters. Sees the whole picture before anyone else does. Pushes back on scope creep. Respects the team's time by making clear calls, not committees. diff --git a/.squad/agents/_alumni/kobayashi/history.md b/.squad/agents/_alumni/kobayashi/history.md index 9056d5c8a..05db85c8c 100644 --- a/.squad/agents/_alumni/kobayashi/history.md +++ b/.squad/agents/_alumni/kobayashi/history.md @@ -1,3 +1,5 @@ +📌 Team update (2026-03-07T20-04-20Z): GitHub Actions npm publishing automation established. New publish.yml workflow triggers on GitHub Release creation. NPM_TOKEN secret required in repo settings. CI/CD publishing is now authoritative method; local npm publish deprecated. — coordinated by Scribe + 📌 Team update (2026-03-07T16:25:00Z): Actions → CLI migration strategy finalized. 4-agent consensus: migrate 5 squad-specific workflows (12 min/mo) to CLI commands. Keep 9 CI/release workflows (215 min/mo, load-bearing). Zero-risk migration. v0.8.22 quick wins identified: squad labels sync + squad labels enforce. Phased rollout: v0.8.22 (deprecation + CLI) → v0.9.0 (remove workflows) → v0.9.x (opt-in automation). Brady's portability insight captured: CLI-first means Squad runs anywhere (containers, Codespaces). Customer communication strategy: "Zero surprise automation" as competitive differentiator. Decisions merged. — coordinated by Scribe # Project Context @@ -87,6 +89,38 @@ npm error This operation requires a one-time password from your authenticator. ⏸️ NPM publish: BLOCKED (awaiting automation token configuration) ✅ Post-publish dev bump: 0.8.22-preview.1 +### Release v0.8.21 — Dev → Main Merge & NPM Publish Trigger (Initial Log) + +**RELEASE GATE MERGE EXECUTED.** Dev branch merged to main, publish workflow triggered successfully. + +#### Execution Summary +- **Merge strategy:** Local merge (git checkout main && git merge origin/dev) attempted with --no-edit +- **Conflicts encountered:** 5 files with conflicts during merge (cli-entry.ts, package.json files, test files) +- **Resolution:** Used `git checkout --theirs` strategy to accept dev branch state for all conflicts +- **Push success:** Main branch updated successfully (commit 59b0c7a) +- **Workflow trigger:** `gh workflow run publish.yml --ref main -f version=0.8.21` executed successfully +- **Post-publish:** Version bumped on dev to 0.8.22-preview.1 across all 3 package.json files (commit 9473fa1) + +#### Technical Execution Details +- **Initial blocker:** Stash required due to uncommitted changes (.squad/agents/rabin/history.md) +- **Protected branch:** Main branch has force-push protection; rebase strategy aborted after conflicts +- **Conflict resolution pattern:** Theirs strategy (--theirs) ensured dev state landed cleanly on main +- **Workflow input requirement:** publish.yml requires `version` input for manual dispatch (not auto-detected) +- **Workflow verification:** `gh run list --workflow=publish.yml` confirmed workflow started successfully + +#### Key Learnings +1. **Conflict resolution for release merges:** When merging dev → main for release, use `git checkout --theirs` on all conflicts to ensure dev state is authoritative +2. **Workflow dispatch inputs:** Always check workflow file for required inputs; publish.yml needs explicit version string +3. **Protected branch constraints:** Rebase strategies fail on force-push-protected branches; use merge + conflict resolution +4. **Post-release discipline:** Immediately bump dev to next preview version after triggering publish (prevents version collisions) +5. **Stash management:** Always check for uncommitted changes before release operations; stash + restore after + +#### Release Sequence Validation +✅ Pre-release version: 0.8.21-preview.X +✅ Publish version: 0.8.21 (tagged, released) +✅ Post-publish dev bump: 0.8.22-preview.1 +Release versioning sequence followed correctly. + --- ### 2026-03-05: v0.8.21 Release PR Merge — 3 of 4 Successfully Merged (COMPLETE) diff --git a/.squad/agents/_alumni/kovash/charter.md b/.squad/agents/_alumni/kovash/charter.md index 25b41056b..fd220b63a 100644 --- a/.squad/agents/_alumni/kovash/charter.md +++ b/.squad/agents/_alumni/kovash/charter.md @@ -34,22 +34,5 @@ **I don't handle:** SDK adapter internals (Kujan), prompt architecture (Verbal), docs (McManus), type system (Edie). -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/kovash-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Methodical and thorough. Traces problems from user input to screen output. Every REPL interaction should feel instant and responsive — if it doesn't, something's wrong and I'll find it. +Preferred: auto diff --git a/.squad/agents/_alumni/kujan/charter.md b/.squad/agents/_alumni/kujan/charter.md index c25845086..8ce0500aa 100644 --- a/.squad/agents/_alumni/kujan/charter.md +++ b/.squad/agents/_alumni/kujan/charter.md @@ -29,22 +29,5 @@ **I don't handle:** Prompt design, test writing, docs, distribution, security policy. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Technical analysis that often touches code — uses sonnet. Pure research uses haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/kujan-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Pragmatic and platform-savvy. Knows exactly where the SDK boundaries are and won't let the team accidentally cross them. Speaks from direct experience with the Copilot platform. +Preferred: auto diff --git a/.squad/agents/_alumni/mcmanus/charter.md b/.squad/agents/_alumni/mcmanus/charter.md index a99510e9c..9caebe9ec 100644 --- a/.squad/agents/_alumni/mcmanus/charter.md +++ b/.squad/agents/_alumni/mcmanus/charter.md @@ -16,6 +16,9 @@ - Demos and examples - Tone review and messaging - i18n patterns +- External community responses (draft-only, human review gate) +- Tone enforcement via humanizer skill +- Community signal aggregation (unanswered issues → product signals) ## How I Work @@ -23,30 +26,17 @@ - Celebration blog structure: wave:null, parallel narrative - docs/proposals/ pattern: proposals before execution - Every public-facing statement must be substantiated -- **DOCS-TEST SYNC (hard rule):** When I add new docs pages (blog posts, guide pages, etc.), I MUST update the corresponding test assertions in test/docs-build.test.ts — specifically EXPECTED_GUIDES, EXPECTED_BLOG, and similar arrays. New files that aren't reflected in test assertions break CI for all contributors. Check the test file before committing any new docs page. +- - **DOCS-TEST SYNC (hard rule):** When I add new docs pages (blog posts, guide pages, etc.), I MUST update the corresponding test assertions in test/docs-build.test.ts — specifically EXPECTED_GUIDES, EXPECTED_BLOG, and similar arrays. New files that aren't reflected in test assertions break CI for all contributors. Check the test file before committing any new docs page. +- - **EXTERNAL COMMS (hard rule):** NEVER post community responses autonomously. All responses are drafted, presented in a review table with confidence flags, and require explicit human approval before posting. +- **HUMANIZER (hard rule):** All external-facing content must pass tone validation — warm, helpful, human-sounding. No corporate speak, no marketing hype, no empty acknowledgments. +- **AUDIT TRAIL (hard rule):** Every draft-review-post action is logged to `.squad/comms/audit/`. The audit log is append-only. + ## Boundaries -**I handle:** Documentation, demos, messaging, tone review, developer experience, i18n. +**I handle:** README, API docs, demos, examples, tone review, community messaging, contributor recognition, external community response drafting (with human review gate). **I don't handle:** Runtime implementation, architecture decisions, security, distribution mechanics. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** claude-haiku-4.5 -- **Rationale:** Docs and writing — not code. Cost-first. -- **Fallback:** Fast chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/mcmanus-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Clear and engaging. Makes complex things feel simple without dumbing them down. Amplifies the team's work. Enforces the tone ceiling — if it sounds like marketing, it gets rewritten. +Preferred: claude-haiku-4.5 diff --git a/.squad/agents/_alumni/rabin/charter.md b/.squad/agents/_alumni/rabin/charter.md index 188220a8a..542eabc98 100644 --- a/.squad/agents/_alumni/rabin/charter.md +++ b/.squad/agents/_alumni/rabin/charter.md @@ -30,22 +30,5 @@ **I don't handle:** Runtime implementation, architecture decisions, security hooks, visual design. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code for build config — uses sonnet -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/rabin-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -User-first, always. Thinks from the install command backward. If the user has to read docs to install, the install experience is broken. Vigilant about bundle size and dependency count. +Preferred: auto diff --git a/.squad/agents/_alumni/redfoot/charter.md b/.squad/agents/_alumni/redfoot/charter.md index 32342e3dd..cbe0504f3 100644 --- a/.squad/agents/_alumni/redfoot/charter.md +++ b/.squad/agents/_alumni/redfoot/charter.md @@ -30,22 +30,5 @@ **I don't handle:** Code implementation, architecture, tests, security, distribution. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** claude-opus-4.5 -- **Rationale:** Vision-capable model required for design work -- **Fallback:** Premium chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/redfoot-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Visual-first. Every design choice has a rationale. Hates decoration for its own sake. Obsessed with consistency — if two things look different, they better be different. SVG over raster, always. +Preferred: claude-opus-4.5 diff --git a/.squad/agents/_alumni/saul/charter.md b/.squad/agents/_alumni/saul/charter.md index 1ebd7ad32..aef3a1f01 100644 --- a/.squad/agents/_alumni/saul/charter.md +++ b/.squad/agents/_alumni/saul/charter.md @@ -31,22 +31,5 @@ **I don't handle:** Runtime implementation, prompt architecture, type system, docs (beyond observability). -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes test code and infrastructure — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/saul-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Infrastructure-aware and telemetry-native. Thinks in pipelines, exporters, and dashboards. If you can't observe it in Aspire, it doesn't count as instrumented. +Preferred: auto diff --git a/.squad/agents/_alumni/strausz/charter.md b/.squad/agents/_alumni/strausz/charter.md index f4d9f564f..d3b781e22 100644 --- a/.squad/agents/_alumni/strausz/charter.md +++ b/.squad/agents/_alumni/strausz/charter.md @@ -29,22 +29,5 @@ **I don't handle:** Core runtime, architecture decisions, docs, security, distribution. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Writes code — uses sonnet for quality -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/strausz-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Hands-on and detail-oriented. Lives in the gap between what Squad does and what VS Code allows. Bridges the two runtimes. If something works on CLI but breaks in VS Code, Strausz finds out why. +Preferred: auto diff --git a/.squad/agents/_alumni/trejo/charter.md b/.squad/agents/_alumni/trejo/charter.md index 3fa096f79..a42730d1e 100644 --- a/.squad/agents/_alumni/trejo/charter.md +++ b/.squad/agents/_alumni/trejo/charter.md @@ -25,6 +25,8 @@ **Checklist-first:** I follow `.squad/skills/release-process/SKILL.md` step-by-step. No shortcuts. No improvisation. Every release follows the same validated process. +**Known pitfalls:** Read `.squad/skills/ci-validation-gates/SKILL.md` for known release pitfalls. + **Pre-flight validation:** 1. Validate semver format with `node -p "require('semver').valid('X.Y.Z')"` 2. Verify NPM_TOKEN type (must be Automation token, not User token with 2FA) @@ -139,8 +141,6 @@ These failures are inherited from Kobayashi's release disasters. Learn from them - Feature implementation or bug fixes - Documentation content (I coordinate with McManus for release notes) -**When I'm unsure:** I say so and suggest who might know. If CI workflow fails, I bring in Drucker. If release notes need polish, I bring in McManus. - **Delegation:** - **Drucker owns CI/CD workflows** — if publish.yml needs changes (retry logic, validation gates, token checks), that's Drucker's work. - **I own release decisions** — version numbers, when to release, what goes in a release, rollback decisions. diff --git a/.squad/agents/_alumni/verbal/charter.md b/.squad/agents/_alumni/verbal/charter.md index 26d75669f..0b0930a9b 100644 --- a/.squad/agents/_alumni/verbal/charter.md +++ b/.squad/agents/_alumni/verbal/charter.md @@ -30,22 +30,5 @@ **I don't handle:** Runtime implementation, test writing, distribution, security hooks, visual design. -**When I'm unsure:** I say so and suggest who might know. - ## Model - -- **Preferred:** auto -- **Rationale:** Prompt design is like code — uses sonnet. Research/analysis uses haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/verbal-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Forward-thinking and edgy. Thinks three moves ahead of the current feature request. Predicts what developers will need before they ask. Opinionated about prompt structure — treats prompts like executable code with the same rigor. +Preferred: auto diff --git a/.squad/agents/booster/charter.md b/.squad/agents/booster/charter.md index 54e535319..31fe0b661 100644 --- a/.squad/agents/booster/charter.md +++ b/.squad/agents/booster/charter.md @@ -19,24 +19,9 @@ ## How I Work -### NEVER: -- Publish without semver validation -- Run npm publish without NPM_TOKEN type check -- Create verify steps without retry logic -- Allow workflows to commit to main/dev -- Skip branch verification in workflows +**NEVER:** Publish without semver validation; npm publish without NPM_TOKEN type check; verify steps without retry logic; workflows committing to main/dev; skip branch verification. -### ALWAYS: -- Add semver validation before npm publish -- Verify NPM_TOKEN type (must be Automation, not user) -- Implement retry logic for external services (npm registry has propagation delay) -- Log structured output for debugging -- Include remediation steps in error messages -- Add branch-name validation to workflows -- Require PRs for protected branches -- Verify PRs reference issues -- Scan for secrets in CI output -- Add CI check for stale test assertions (prevents the Fenster/Hockney problem of changing APIs without updating tests) +**ALWAYS:** Semver validation before publish; NPM_TOKEN type = Automation; retry logic for external services; structured logging; remediation steps in errors; branch validation; require PRs for protected branches; verify PR→issue references; scan for secrets; CI check for stale assertions. ## Boundaries @@ -44,24 +29,6 @@ **I don't handle:** Feature implementation, docs, architecture decisions, visual design, release orchestration (that's Surgeon). -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Workflow design uses sonnet. Config changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/booster-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Defensive and proactive. CI is the safety net that catches what code review misses. Every workflow is a launch sequence — staging, validation, ignition, verify. If the gates say stop, we stop. No exceptions. +Preferred: auto diff --git a/.squad/agents/booster/history.md b/.squad/agents/booster/history.md index 6b20b29c3..e16d167ad 100644 --- a/.squad/agents/booster/history.md +++ b/.squad/agents/booster/history.md @@ -18,3 +18,53 @@ SKIP_BUILD_BUMP=1 environment variable intended to prevent version mutation duri ### Smoke Test Gating in Publish Pipeline Smoke tests now run as a dedicated `smoke-test` job in publish.yml before any npm publish operations. Both publish-sdk and publish-cli jobs depend on smoke-test passing. Prevents publishing broken CLI packages to npm. Smoke test runs `npx vitest run test/cli-packaging-smoke.test.ts` after a full build. Test takes ~30-60s for pack+install validation. + +### CI Pipeline Hardening — March 20, 2026 + +**Changes shipped in commit 6cbabb5 (dev branch):** + +1. **`edited` trigger added** — `pull_request` event types now include `edited`. Previously, retargeting a PR from `main→dev` would not refire CI because the base branch change uses the `edited` event type. Six PRs (#470, #469, #468, #467, #454, #451) were manually close/reopened to compensate. + +2. **Lockfile lint step added** — New step `Lint lockfile for stale workspace entries` runs before `npm ci` in the `test` job. Uses Node inline script to detect any `packages/*/node_modules/@bradygaster/squad-*` entries in `package-lock.json` that have an `https://` resolved URL (indicating a stale nested registry copy shadowing the workspace symlink). Exits with error code + remediation instructions if found. This catches the TypeScript type-mismatch class of failures at the lockfile level, not at build time. + +3. **Default branch changed to `dev`** — Repo default branch switched from `main` to `dev` via GitHub API. Community PRs now naturally target `dev`. + +**Pattern confirmed:** The `edited` event gap was the exact reason retargeted PRs were not getting CI runs. Any future PR base-branch change will now trigger a fresh CI run automatically. + +### CI Failure Pattern Analysis — March 15, 2026 +Analyzed 20 CI runs from March 15. Identified 3 distinct failure categories: + +**1. TypeScript Build Failures — SDK/CLI Type Mismatches (Most Critical)** +- 7+ consecutive failures on `squad/fix-ci-build` branch (14:00-14:11 UTC) +- Root cause: Stale nested SDK entry in package-lock.json causing TypeScript module resolution errors +- Error: "Module '@bradygaster/squad-sdk' has no exported member 'listRoles'" (and 6 other missing exports) +- Impact: Build failures blocked all PRs attempting to fix roles/cast features +- Fix: Removing stale lockfile entry resolved TypeScript resolution +- Pattern: Workspace dependency mismatches not caught until CI build phase + +**2. Documentation Quality Gate Failures — New Validation Rules** +- 3 failures on `squad/docs-quality-ci` branch (14:32, 15:26, 15:51 UTC) +- Issue 1: Broken anchor link `../guide.md#troubleshooting` (anchor doesn't exist) +- Issue 2: Spell check failure for username "benleane" in notifications.md (not in cspell dictionary) +- Impact: New docs-quality job blocked merges when introducing new validation gates +- Pattern: Adding stricter CI gates without pre-validation of existing content creates immediate failures + +**3. Test Failures — ES Module Migration Side Effects (Legacy)** +- 1 failure on main branch (13:59 UTC) — "deleted images" commit +- Root cause: 8 test files using `require()` in ES module context +- Error: "require is not defined in ES module scope" (node:test imports) +- Impact: Old test files incompatible with `"type": "module"` in package.json +- Pattern: Incomplete ESM migration left test files in CommonJS syntax + +**Key Observations:** +- **Failure clusters**: Multiple consecutive failures trying to fix same root issue (TypeScript build: 7 attempts, docs-quality: 3 attempts) +- **Validation timing**: New validation gates (docs-quality CI) introduced without pre-testing against current codebase state +- **Workspace complexity**: Monorepo TypeScript workspace dependencies prone to lockfile staleness +- **Branch health**: dev branch had 2 failures (last failure: spell check), currently yellow/orange status + +**Recommended CI Improvements:** +1. Pre-merge lockfile validation check (detect stale nested dependencies) +2. Docs validation dry-run before adding new quality gates +3. TypeScript workspace reference health check (catch SDK/CLI type mismatches early) +4. Better failure grouping/attribution in CI UI (distinguish "new gate" vs "regression") +5. Spell check dictionary maintenance workflow (easier to add known-good usernames/terms) diff --git a/.squad/agents/capcom/charter.md b/.squad/agents/capcom/charter.md index a83f2e02f..dde8f533f 100644 --- a/.squad/agents/capcom/charter.md +++ b/.squad/agents/capcom/charter.md @@ -29,24 +29,6 @@ **I don't handle:** Feature implementation, docs, distribution, visual design, security hooks. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** SDK integration review uses sonnet. Quick lookups use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/capcom-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Pragmatic and platform-savvy. Knows where the SDK boundaries are and doesn't waste time fighting them. The only person who talks to the crew — and makes sure the signal is clean. +Preferred: auto diff --git a/.squad/agents/capcom/history.md b/.squad/agents/capcom/history.md new file mode 100644 index 000000000..295dd1af9 --- /dev/null +++ b/.squad/agents/capcom/history.md @@ -0,0 +1,32 @@ +# CAPCOM — History + +> Knowledge base for the SDK Expert. Append-only, union-merged across branches. + +## Learnings + +### 2026-03-14: WSL Transient API Error Investigation (Issue #363) + +**Context:** User reported "Request failed due to a transient API error" on Ubuntu WSL with Copilot CLI v1.0.4, eventually hitting rate limits. + +**Investigation findings:** +- Squad SDK already implements robust retry logic with exponential backoff (1s → 2s → 4s) +- Retry logic in `adapter/client.ts:820-880` handles transient connection errors (ECONNREFUSED, ECONNRESET, EPIPE) +- Rate limit detection in `adapter/errors.ts:229-245` with retry-after awareness +- Error originates **upstream** from Copilot CLI/API platform, not Squad +- Copilot CLI v1.0.4 internal retry behavior triggers the rate limiting before Squad is invoked +- Squad only interacts with CLI via `@github/copilot-sdk` adapter after CLI is already running + +**Key insight:** Squad SDK does NOT contribute to transient API errors or rate limiting issues. Our retry logic follows platform patterns and only applies to SDK connection errors, not upstream API instability. + +**Outcome:** +- Confirmed this is an upstream platform issue (not a Squad bug) +- Recommended user check network connectivity, WSL configuration, and GitHub auth +- Created decision in `.squad/decisions/inbox/capcom-wsl-transient.md` +- Suggested documentation improvement: add WSL troubleshooting guide + +**Pattern learned:** When investigating API errors, distinguish between: +1. **SDK adapter layer** (our retry logic) — handles connection errors only +2. **Copilot CLI layer** (upstream) — handles API communication and its own retries +3. **Copilot API platform** (upstream) — source of transient errors and rate limits + +Squad operates at layer #1, so issues at layers #2-3 are outside our control. diff --git a/.squad/agents/control/charter.md b/.squad/agents/control/charter.md index e7b029c7c..38c7273ba 100644 --- a/.squad/agents/control/charter.md +++ b/.squad/agents/control/charter.md @@ -31,24 +31,6 @@ **I don't handle:** Runtime implementation, docs, distribution, security, visual design. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Type system design uses sonnet. Build config changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/control-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Precise and type-obsessed. Types are contracts. If it compiles, it works. No @ts-ignore, no any-casts, no escape hatches. The type system is the first line of defense. +Preferred: auto diff --git a/.squad/agents/control/history.md b/.squad/agents/control/history.md new file mode 100644 index 000000000..35a9de4f3 --- /dev/null +++ b/.squad/agents/control/history.md @@ -0,0 +1,30 @@ +# Control — History + +## Learnings + +### Model Registry Architecture +- `MODELS` constant in `packages/squad-sdk/src/runtime/constants.ts` is the single source of truth for default model names and fallback chains. `DEFAULT_CONFIG` in `runtime/config.ts` derives `defaultModel` from `MODELS.DEFAULT`. +- `MODEL_CATALOG` in `packages/squad-sdk/src/config/models.ts` is the authoritative model list used by `ModelRegistry`. `DEFAULT_FALLBACK_CHAINS` in the same file mirrors `MODELS.FALLBACK_CHAINS` — both must stay in sync. +- `model-selector.ts` hardcodes task-to-model mappings for `code`, `prompt`, `visual`, `docs`, `planning`, `mechanical` task types. These must be updated alongside `MODELS.FALLBACK_CHAINS` when defaults change. + +### Skill Templates Are Auto-Synced +- `npm run build` calls `scripts/sync-skill-templates.mjs` which copies `.squad/skills/*/SKILL.md` files into both `packages/squad-sdk/templates/skills/` and `packages/squad-cli/templates/skills/`. Editing `.squad/skills/model-selection/SKILL.md` is sufficient — the sync propagates it. + +### Model Default Update Pattern +When updating default models, touch these files in order: +1. `.squad/skills/model-selection/SKILL.md` — tables, fallback chains, valid models list, examples +2. `.github/agents/squad.agent.md` — core rules section (~line 295), spawn example (~line 297) +3. `packages/squad-sdk/src/runtime/constants.ts` — `MODELS.DEFAULT`, `MODELS.FALLBACK_CHAINS` +4. `packages/squad-sdk/src/agents/model-selector.ts` — `selectModelForTask` switch cases +5. `packages/squad-sdk/src/config/models.ts` — `MODEL_CATALOG` entries, `DEFAULT_FALLBACK_CHAINS` +6. `packages/squad-sdk/src/runtime/benchmarks.ts` — fixture data +7. Tests: `test/agents.test.ts`, `test/config.test.ts`, `test/models.test.ts`, `test/compat-v041.test.ts`, `test/init.test.ts` + +### Claude Haiku Stays at 4.5 +There is no `claude-haiku-4.6`. The latest haiku is `claude-haiku-4.5`. Never bump haiku beyond 4.5 until the platform explicitly lists a newer haiku variant. + +### Standard Tier Fallback Chain (current) +`claude-sonnet-4.6 → gpt-5.4 → claude-sonnet-4.5 → gpt-5.3-codex → claude-sonnet-4 → gpt-5.2` + +### ModelId Type +`ModelId = string` in `runtime/config.ts` — not a discriminated union. New model IDs can be added to the catalog without TypeScript changes beyond the catalog and chain arrays. diff --git a/.squad/agents/dsky/charter.md b/.squad/agents/dsky/charter.md index 68d646907..af7e5a6b0 100644 --- a/.squad/agents/dsky/charter.md +++ b/.squad/agents/dsky/charter.md @@ -31,24 +31,6 @@ **I don't handle:** Feature design, docs, distribution, security, SDK integration. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Rendering architecture uses sonnet. Component tweaks use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/dsky-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Precision-focused. The DSKY was the Apollo spacecraft's display and keyboard — the interface between human and machine. Every pixel, every frame, every keystroke. Terminal rendering is not decoration — it's mission-critical communication. +Preferred: auto diff --git a/.squad/agents/eecom/charter.md b/.squad/agents/eecom/charter.md index b4c454b7a..744f2140f 100644 --- a/.squad/agents/eecom/charter.md +++ b/.squad/agents/eecom/charter.md @@ -29,24 +29,6 @@ **I don't handle:** Docs, distribution, visual design, security hooks, prompt architecture. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Core implementation uses sonnet. Scaffolding and simple changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/eecom-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Practical and thorough. Makes it work, then makes it right, then makes it fast. Doesn't over-engineer. Respects the runtime's simplicity. If a change touches a public API, the tests get updated in the same commit — no exceptions. +Preferred: auto diff --git a/.squad/agents/eecom/history.md b/.squad/agents/eecom/history.md index 6c1c3da08..22a13095a 100644 --- a/.squad/agents/eecom/history.md +++ b/.squad/agents/eecom/history.md @@ -4,6 +4,37 @@ ## Learnings +### Privacy scrub messaging + EPERM + gitignore parent coverage (#549) (2026-07-14) + +**Context:** Upgrade footer message always said "Preserves user state" even when the email privacy scrub had run — a direct contradiction of what just happened. Two related issues in the same function: EPERM on read-only `.gitattributes` would crash the upgrade, and `.gitignore` would add redundant entries already covered by parent paths (e.g. `.squad/log/` when `.squad/` was already present). + +**Fix:** +1. `upgrade.ts` — `ensureGitattributes` catches EPERM/EACCES and returns `[]` with a console.warn, graceful degradation. +2. `upgrade.ts` — `ensureGitignore` skips an entry when any existing line is a parent prefix of it. +3. `upgrade.ts` — Footer logic checks whether the email scrub actually ran; shows "Privacy scrub applied" or "Preserves user state" accordingly. +4. `test/cli/upgrade.test.ts` — Added EPERM test using `chmodSync` (fix: `chmodSync` was missing from the `fs` import — added it). + +**Pattern:** When adding a new fs function to a test, always verify the named import list at the top of the test file. Missing named imports from `'fs'` produce `ReferenceError` at runtime, not at type-check time (if the test file isn't part of the main tsconfig). + +📌 **Team update (2026-03-22T09-35Z — Wave 1):** Economy mode fully implemented: ECONOMY_MODEL_MAP + resolveModel() integration in SDK, `squad economy on|off` CLI command, `--economy` flag, 34 tests passing. PR #504 open for review. Soft dependency: #464 rate limit UX should offer economy mode as recovery. Next: Phase 1 of ambient personal squad (T1–T5, T19) — ready to start immediately after merging current work. Procedures wrote governance proposals for squad.agent.md — awaiting Flight review. +### Rate Limit UX (#464) (2026-03-20) + +**Context:** Users hitting Copilot rate limits saw generic "Something went wrong processing your message." Squad hid the actual error. `squad doctor` reported nothing — useless to diagnose. + +**Root cause:** The catch block in `shell/index.ts` line ~1119 always emitted `genericGuidance()` unless `SQUAD_DEBUG=1`. Rate limit errors never got special treatment despite `RateLimitError` existing in `adapter/errors.ts`. + +**Fix:** +1. `error-messages.ts` — Added `rateLimitGuidance({ retryAfter?, model? })` and `extractRetryAfter(message)` utilities. Rate limit guidance shows clear message + recovery options (retry time, `squad economy on`, config.json model override). +2. `shell/index.ts` — Catch block now detects rate limits via `instanceof RateLimitError` OR regex on the raw message. Writes `.squad/rate-limit-status.json` on detection. +3. `doctor.ts` — Added `checkRateLimitStatus()` check. Reads status file and warns if rate limit was recent. +4. `test/error-messages.test.ts` — Added 11 new tests covering `rateLimitGuidance` and `extractRetryAfter`. + +**Pattern:** Rate limit status written to `.squad/rate-limit-status.json` as `{ timestamp, retryAfter, model, message }`. Doctor reads it on next run. File is never deleted automatically — doctor marks it `pass` when > 4h stale. + +**Import path for `RateLimitError`:** `@bradygaster/squad-sdk/adapter/errors` (subpath export, not in main barrel). + +**PR:** #464 fix — squad/464-rate-limit-ux + ### CLI Entry Point Architecture cli-entry.ts is the central router for ~30+ CLI commands using dynamic imports (lazy-loading). Commands are routed via if-else blocks. Has a recurring "unwired command" bug class — implementations exist in cli/commands/ but aren't routed in cli-entry.ts. The cli-command-wiring.test.ts regression test catches this by verifying every .ts file in cli/commands/ is imported. @@ -24,3 +55,133 @@ CLI completeness audit (2026-03-08) confirmed: 26 primary commands routed in cli 📌 **Team update (2026-03-08T21:18:00Z):** FIDO + EECOM released unanimous GO verdict for v0.8.24. Smoke test approved as release gate. FIDO confirmed 32/32 pass + publish.yml wired correctly. EECOM confirmed 26/26 commands + packaging complete (minor gap: "streams" alias untested, non-blocking). +### Cross-Platform Filename and Config Fixes (#348, #356) (2026-03-15T05:30:00Z) + +**Context:** Two cross-platform bugs broke Squad on Windows: (1) log filenames contained colons in ISO 8601 timestamps (illegal on Windows), (2) `.squad/config.json` contained absolute machine-specific `teamRoot` path. + +**Investigation:** +- Searched SDK for all timestamp usage in filenames — found `safeTimestamp()` utility already existed but wasn't consistently used +- `comms-file-log.ts` (line 32) used inline `toISOString().replace(/:/g, '-')` instead of utility +- `init.ts` (line 612) wrote absolute `teamRoot` to config.json on every init +- Session-store already used `safeTimestamp()` correctly (line 71) + +**Fixes:** +1. **Bug #348:** Updated `comms-file-log.ts` to import and use `safeTimestamp()` utility instead of inline timestamp formatting +2. **Bug #356:** Removed `teamRoot` field from config.json (can be computed at runtime via `git rev-parse --show-toplevel`) +3. Updated live `.squad/config.json` in repo to remove machine-specific path + +**Pattern:** Centralized timestamp formatting in `safeTimestamp()` utility (replaces colons + truncates milliseconds). Windows-safe format: `2026-03-15T05-30-00Z` instead of `2026-03-15T05:30:00.123Z`. + +**Test Impact:** All 150 tests pass. Communication adapter test doesn't validate specific filename format (structural test, not behavioral). + +**PR:** #404 opened targeting dev. + +### CastingEngine CLI Integration (#342) (2026-03-15T11:20:00Z) + +**Context:** CastingEngine class (Issue #138, M3-2) existed in SDK with curated universe templates (The Usual Suspects, Ocean's Eleven) but was completely bypassed during `squad init`. LLM picked arbitrary names, and charter generation used regex-based `personalityForRole()` instead of template backstories. + +**Investigation:** +- CastingEngine.castTeam() was never called in CLI flow +- coordinator.ts buildInitModePrompt() let LLM pick any universe without guidance +- cast.ts generateCharter() used fallback personality logic instead of engine data +- SDK exports two AgentRole types: broad one in casting-engine.ts, restrictive one in runtime/constants.ts + +**Integration Strategy (Augment, Not Replace):** +- LLM still proposes roles and team composition (the beloved casting experience) +- CastingEngine augments with curated names when universe is recognized +- Mapping: "The Usual Suspects" → 'usual-suspects', "Ocean's Eleven" → 'oceans-eleven' +- Unrecognized universes (Matrix, Alien, etc.) preserve LLM's arbitrary names + +**Implementation:** +1. Added `augmentWithCastingEngine()` in cast.ts to replace LLM names with engine characters +2. Updated coordinator prompt to suggest preferred universes (Usual Suspects, Ocean's Eleven) +3. Extended `generateCharter()` to use engine personalities/backstories when available +4. Attached `_personality` and `_backstory` to CastMember objects for charter generation +5. Role mapping: CLI role strings → engine AgentRole enum (lead, developer, tester, etc.) + +**Type Import Pattern:** +- Import CastingEngine from `@bradygaster/squad-sdk/casting` (not main barrel export) +- Use casting-engine.ts AgentRole type (9 roles) not runtime/constants.ts (6 roles) +- Partial mapping: unmapped roles log warning and skip engine casting + +**Tests:** +- Created test/casting-engine-integration.test.ts (5 tests, all pass) +- Validates augmentation for both universes, case-insensitive matching, fallback behavior +- All 45 existing cast-parser/casting tests still pass + +**PR:** #417 opened targeting dev. + + +### PR #427 Cross-Fork Rebase (2026-03-15T21:00:00Z) + +**Context:** PR #427 (PAO external communications Phase 1) conflicted with upstream/dev after team recast (#423 Usual Suspects → Apollo 13) and model updates. Cross-repo PR (diberry/squad → bradygaster/squad). Initial rebase attempts failed due to git worktree confusion — main worktree was checked out to a different branch, causing git checkout commands to silently switch to wrong branches. + +**Problem:** Git commands (checkout, rebase) kept switching to unrelated branches (squad/agent-on-disk-concept, squad/320-fix-migration-guide-version-local) mid-rebase. Root cause: main worktree at C:\Users\diberry\repos\project-squad\squad was checked out to squad/agent-on-disk-concept. Git was treating checkout commands as worktree operations and switching the main worktree's HEAD, aborting the rebase. + +**Solution:** Created dedicated worktree (.worktrees/pao-rebase) for the rebase operation. This isolated the rebase from main worktree state and prevented branch switching. + +**Conflict Resolution (3 files, 7 commits rebased):** +1. **.squad/agents/_alumni/mcmanus/charter.md** - Merged both rule sets: DOCS-TEST SYNC (from upstream reskill) and EXTERNAL COMMS, HUMANIZER, AUDIT TRAIL (from PR #427). Used PowerShell regex to extract and combine both sides. +2. **.squad/routing.md** - Accepted Apollo 13 team names (EECOM, PAO, FIDO) from upstream via `git checkout --ours` (in rebase context, "ours" = upstream, "theirs" = our branch). PAO external comms infrastructure is team-agnostic. +3. **.squad/agents/keaton/history.md** - Accepted deletion via `git rm` (file moved to _alumni in upstream recast). + +**Rebase Commits:** 7 commits from squad/426-pao-external-comms rebased onto upstream/dev (f87a7a5), covering #423 team reskill, #424 SDK switch, #425/#428 test parity, #429 model updates. + +**Force Push:** `git push origin squad/426-pao-external-comms --force-with-lease` succeeded. PR #427 comment posted via gh CLI. + +**Pattern:** When working with git worktrees, always create a dedicated worktree for complex operations (rebase, cherry-pick) to avoid main worktree state interference. Use `git worktree list` to diagnose unexpected branch switching. +### Adoption Tracking Tier 1 Implementation (2026-03-10) +Implemented Flight's privacy-first adoption monitoring strategy on PR #326 branch. Moved `.squad/adoption/` → `.github/adoption/` for better GitHub integration. Stripped tracking.md to aggregate-only metrics (removed all individual repo names/URLs). Updated GitHub Action workflow (adoption-report.yml) and monitoring script (scripts/adoption-monitor.mjs) to write reports to `.github/adoption/reports/`. Removed "Built with Squad" showcase link from README.md (deferred to Tier 2 opt-in feature). This honors the principle: collect aggregate metrics via public APIs, but never publish individual repo lists without explicit consent. Test discipline: verified npm run build passes; docs-build.test.ts passed structure tests (Astro build failure unrelated to changes). Committed with clear message explaining privacy rationale. + +📌 **Team update (2026-03-10T12-55-49Z):** Adoption tracking Tier 1 complete and merged to decisions.md. Privacy-first architecture confirmed: aggregate metrics only, opt-in for individual repos, public showcase only when 5+ projects opt in. Append-only file governance enforced (no deletions in history.md or decisions.md). Microsoft ampersand style guide adopted for documentation. + +### Economy Mode Implementation (#500) (2026-03-20) + +**Context:** Issue #500 requested economy mode — a session-level and persistent modifier that shifts model selection to cheaper alternatives. + +**Architecture decision:** Economy mode is a Layer 3/4 modifier only. Layers 0–2 (explicit user preferences: config.json, session directive, charter) are never downgraded. This preserves user intent while enabling cost savings on auto-selected tasks. + +**Implementation:** +1. `ECONOMY_MODEL_MAP` + `applyEconomyMode()` in `config/models.ts` — pure mapping function for premium→standard and standard→fast downgrades +2. `readEconomyMode()` + `writeEconomyMode()` — config.json read/write functions (same merge-without-clobber pattern as `writeModelPreference()`) +3. `resolveModel()` in `config/models.ts` updated with `economyMode?: boolean` option; falls back to reading from `squadDir` if not provided +4. `resolveModel()` in `agents/model-selector.ts` updated with `economyMode?: boolean` — both SDK resolvers are economy-aware +5. `squad economy [on|off]` command in CLI for persistent toggle +6. `--economy` global flag in `cli-entry.ts` sets `SQUAD_ECONOMY_MODE=1` env var for session scope +7. 34 new tests in `test/economy-mode.test.ts` — all pass + +**Key pattern:** Both resolveModel implementations follow identical principle: explicit overrides (user choice) are sacred; economy only affects computed auto-selection. + +**PR:** #500 branch `squad/500-economy-mode` + +### node:sqlite Hard-Fail Fix (#502) (2026-03-21) + +**Context:** Workshop participants (reported by Doron Ben Elazar) were blocked by `ERR_UNKNOWN_BUILTIN_MODULE` crashes. `node:sqlite` (used by Copilot SDK for session storage) requires Node 22.5.0+. The existing soft-warn-and-continue approach let users limp into a cryptic crash. + +**Root cause:** `engines.node` said `>=20` but `node:sqlite` needs `>=22.5.0`. The pre-flight check warned but didn't exit, so users saw confusing failures deep in SDK code. + +**Fix:** +1. **cli-entry.ts:** Replaced `try { await import('node:sqlite') } catch { warn }` with a synchronous version check that calls `process.exit(1)` immediately with a clear upgrade message. Removed the now-dead `checkNodeSqlite()` function and its call site. +2. **doctor.ts:** Added `checkNodeVersion()` to `squad doctor` — exported with optional version param for testability. +3. **package.json (×3):** Corrected `engines.node` to `>=22.5.0` so npm/npx warn at install time. +4. **Tests:** 5 new tests for `checkNodeVersion()` (Node 20.x fail, 22.4.x fail, 22.5.0 pass, 24.x pass, current env pass). Updated check-count assertion. + +**Pattern:** git branch confusion — `git checkout -b` switches HEAD but edits to files on wrong branch are lost when switching. Always confirm `git branch` before making file edits. File edits don't follow you to a new branch if you forgot to switch first. + +**PR:** #506 branch `squad/502-node-sqlite-dependency` + +### Rate Limit Recovery UX (#464) (2026-03-22) + +**Context:** Rate limit errors showed generic message with no actionable recovery. Brady directive: offer model switching + economy mode as recovery options. + +**Implementation:** +1. `error-messages.ts` — `rateLimitGuidance()` shows actual reason + 3 recovery options (retry time, `squad economy on`, config.json model override) +2. `shell/index.ts` — Detects rate limits via `instanceof RateLimitError` or regex; writes `.squad/rate-limit-status.json` +3. `doctor.ts` — `checkRateLimitStatus()` reads status file and warns if recent +4. 36 new tests — all pass + +**PR:** #505 `squad/464-rate-limit-ux` — merged (rebased after #504) + +### Session 2 Summary (2026-03-22) + +Executed 3 tasks across 2 waves: economy mode (#500, PR #504), node:sqlite fix (#502, PR #506), rate limit UX (#464, PR #505). All PRs merged to dev. diff --git a/.squad/agents/fido/charter.md b/.squad/agents/fido/charter.md index 141ea0876..0227cefae 100644 --- a/.squad/agents/fido/charter.md +++ b/.squad/agents/fido/charter.md @@ -20,14 +20,12 @@ ## How I Work -- 80% coverage is the floor, not the ceiling. 100% on critical paths. -- Multi-agent concurrency tests are essential — spawning is the heart of the system -- Casting overflow edge cases: universe exhaustion, diegetic expansion, thematic promotion -- GitHub Actions CI/CD: tests must pass before merge, always -- Adversarial testing: think like an attacker — nasty inputs, race conditions, resource exhaustion -- **TEST ASSERTION DISCIPLINE (hard rule):** When I add test count assertions (e.g., EXPECTED_GUIDES, EXPECTED_BLOG arrays in docs-build.test.ts), I MUST keep them in sync with the actual files on disk. When reviewing other agents' work, I verify that any new files they added are reflected in test assertions. Stale assertions that block CI for other contributors are MY responsibility to prevent. -- **PR BLOCKING AUTHORITY (hard rule):** I can block any PR that reduces test coverage, introduces untested code paths, or breaks existing test assertions. This is a go/no-go gate. -- **CROSS-CHECK DUTY (hard rule):** When any agent changes an API or public interface, I verify their tests were updated in the same commit. If not, I block the PR and require test updates before merge. +- 80% floor, 100% on critical paths. Multi-agent concurrency tests essential. +- Casting edge cases: universe exhaustion, diegetic expansion, thematic promotion +- Adversarial testing: nasty inputs, race conditions, resource exhaustion +- EXPECTED_* arrays (docs-build.test.ts) must sync with disk — my responsibility +- PR blocking authority: can block PRs reducing coverage or breaking assertions +- Cross-check: verify tests updated when APIs change ## Boundaries @@ -35,24 +33,6 @@ **I don't handle:** Feature implementation, docs, architecture decisions, distribution. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Writes test code — uses sonnet for quality. Simple scaffolding can use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/fido-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Skeptical and relentless. Assumes every feature has a bug until proven otherwise. Pushes back on skipped tests. Prefers integration tests over mocks. Thinks 80% coverage is the floor, not the ceiling. If it can break, FIDO will find how — and write the test to prove it. +Preferred: auto diff --git a/.squad/agents/fido/history.md b/.squad/agents/fido/history.md index 774259727..a2130102c 100644 --- a/.squad/agents/fido/history.md +++ b/.squad/agents/fido/history.md @@ -2,22 +2,75 @@ > Flight Dynamics Officer +## Core Context + +Quality gate authority for all PRs. Test assertion arrays (EXPECTED_GUIDES, EXPECTED_FEATURES, EXPECTED_SCENARIOS, etc.) MUST stay in sync with files on disk. When reviewing PRs with CI failures, always check if dev branch has the same failures — don't block PRs for pre-existing issues. 3,931 tests passing, 149 test files, ~89s runtime. + ## Learnings -### Name-Agnostic Testing Pattern -Tests reading live .squad/ files (team.md, routing.md) must assert structure/behavior, not specific agent names. Names change during team rebirths. Two classes of tests: (1) live-file tests — must survive rebirths, use property checks, (2) inline-fixture tests — self-contained, can hardcode names. See ralph-triage.test.ts for the canonical pattern. +### Test Assertion Sync Discipline +EXPECTED_* arrays in docs-build.test.ts must match filesystem reality. When PRs add new content files, verify the corresponding test arrays are updated. Consider dynamic discovery pattern (used for blog posts) for resilience against content additions. Stale assertions that block CI are FIDO's responsibility. -### Dynamic Content Discovery -Blog tests in docs-build.test.ts use filesystem discovery (readdirSync) instead of hardcoded arrays. Adding/removing blog posts no longer requires updating the test. Pattern: discover from disk, sort, validate build output exists. +### PR Quality Gate Pattern +Verdict scale: GO (merge), FAIL (block until fixed), NO-GO (reject). Always verify: test discipline (assertions synced), CI status (distinguish pre-existing vs new failures), content accuracy, cross-reference validity. When detecting CI failures, run baseline comparison (dev branch vs PR branch) to isolate regressions. -### Test Baseline (Post-v0.8.24) -3,931 tests passing, 46 todo, 5 skipped, 149 test files (~89s). Only failure: aspire-integration.test.ts (needs Docker daemon). Speed gates in speed-gates.test.ts enforce UX budgets (help output <100 lines, init <10s, etc.). +### Name-Agnostic Testing +Tests reading live .squad/ files must assert structure/behavior, not specific agent names. Names change during team rebirths. Two test classes: live-file tests (survive rebirths, property checks) and inline-fixture tests (self-contained, can hardcode). + +### Dynamic Content Discovery +Blog tests use filesystem discovery (readdirSync) instead of hardcoded arrays. Pattern: discover from disk, sort, validate build output exists. ### Command Wiring Regression Test -cli-command-wiring.test.ts prevents the "unwired command" bug: verifies every .ts file in packages/squad-cli/src/cli/commands/ is imported in cli-entry.ts. Bidirectional validation — also checks that every import points to an existing file. +cli-command-wiring.test.ts prevents "unwired command" bug: verifies every .ts file in commands/ is imported in cli-entry.ts. Bidirectional validation. + +### CLI Packaging Smoke Test +cli-packaging-smoke.test.ts validates packaged CLI artifact (npm pack → install → execute). Tests 27 commands + 3 aliases. Catches: missing imports, broken exports, bin misconfiguration, ESM resolution failures. Complements source-level wiring test. + +### CastingEngine Integration Review +CastingEngine augments LLM casting with curated names for recognized universes. Unrecognized universes preserve LLM names. Import from `@bradygaster/squad-sdk/casting`, use casting-engine.ts AgentRole type (9 roles). Partial mapping: unmapped roles skip engine casting. + +### PR #331 Quality Gate Review — NO-GO (Blocking Issues Found) (2026-03-10T14:13:00Z) + +**CRITICAL VIOLATIONS DETECTED:** + +1. **Stale Test Assertions (Hard Rule Violation)** — EXPECTED_SCENARIOS array in test/docs-build.test.ts contains only 7 values ['issue-driven-dev', 'existing-repo', 'ci-cd-integration', 'solo-dev', 'monorepo', 'team-of-humans', 'cross-org-auth'], but 25 scenario files exist on disk (aspire-dashboard, client-compatibility, disaster-recovery, keep-my-squad, large-codebase, mid-project, multi-codespace, multiple-squads, new-project, open-source, private-repos, release-process, scaling-workstreams, switching-models, team-portability, team-state-storage, troubleshooting, upgrading, + 7 in array). My charter: "When I add test count assertions, I MUST keep them in sync with the actual files on disk. Stale assertions that block CI are MY responsibility to prevent." This is MY responsibility to catch. + +2. **Missing EXPECTED_FEATURES Array** — PR adds 'features' to the sections list in test/docs-build.test.ts (line 46), but NO EXPECTED_FEATURES array exists. Test line 171 "all expected doc pages produce HTML in dist/" will skip features entirely. 32 feature files exist (.md files in docs/src/content/docs/features/). + +📌 **Team update (2026-03-11T01:27:57Z):** PR #331 quality gate resolved. FIDO fixed test assertion sync in docs-build.test.ts: EXPECTED_SCENARIOS updated to 25 entries, EXPECTED_FEATURES array created with 32 entries, test assertions updated for features validation. Tests: 6/6 passing. Commit: 6599db6. Blocking NO-GO converted to approval gate cleared. Lesson reinforced: test assertions must be synced to filesystem state; CI passing ≠ coverage. + +3. **Incomplete Test Coverage Sync** — PAO's history (line 41) states "Updated EXPECTED_SCENARIOS in docs-build.test.ts to match remaining files" after deleting ralph-operations.md and proactive-communication.md. But the diff shows ONLY a single-line change (adding 'features' to sections array). The full test update was not committed. + +**POSITIVE FINDINGS:** +- ✅ CI passed (test run completed successfully on GitHub) +- ✅ Markdown structure tests pass (6/6 syntax checks) +- ✅ Docs are well-written: sentence-case headings, active voice, present tense, second person +- ✅ Cross-references valid (labels.md link verified) +- ✅ No duplicate "How It Works" heading in reviewer-protocol.md +- ✅ Content intact (no accidental loss) +- ✅ Microsoft Style Guide compliance confirmed + +**ROOT CAUSE:** PAO staged the boundary review changes but the test update commit was incomplete. The assertion arrays must be synchronized before merge. + +**REQUIRED FIX:** Update test/docs-build.test.ts: +1. EXPECTED_SCENARIOS = [ all 25 actual scenario files, sorted ] +2. EXPECTED_FEATURES = [ all 32 actual feature files, sorted ] +3. Regenerate to match disk reality (use filesystem discovery if the project wants test-resilience) + +**VERDICT:** 🔴 **NO-GO** — Merge blocked until test assertions sync with disk state. This is a quality gate violation. + +### Test Assertion Sync Fix (2026-03-10T14:20:00Z) + +**Issue resolved:** Fixed stale test assertions in test/docs-build.test.ts identified during PR #331 review. + +**Changes made:** +1. Expanded EXPECTED_SCENARIOS from 7 to 25 entries (matched all .md files in docs/src/content/docs/scenarios/) +2. Added EXPECTED_FEATURES array with 32 entries (matched all .md files in docs/src/content/docs/features/) +3. Updated test logic to include features section in HTML build validation + +**Validation:** All structure validation tests passing (6/6). Build tests skipped as expected (Astro not installed). Arrays now accurately reflect disk state. -### CLI Packaging Smoke Test (v0.8.24 Release Assessment) -cli-packaging-smoke.test.ts validates the PACKAGED CLI artifact (npm pack → install → execute). Tests 27 commands + 3 aliases by invoking them through the installed tarball. Catches: missing imports (MODULE_NOT_FOUND), broken package.json exports, bin script misconfiguration, and ESM resolution failures. Gate runs before both SDK and CLI publish jobs. Complements cli-command-wiring.test.ts (source-level import verification) by testing the artifact users actually download. All 32 tests passing (37s runtime). Approved for v0.8.24 release gate. +**Commit:** 6599db6 on branch squad/289-squad-dir-explainer -📌 **Team update (2026-03-08T21:18:00Z):** FIDO + EECOM released unanimous GO verdict for v0.8.24. Smoke test approved as release gate. FIDO confirmed 32/32 pass + publish.yml wired correctly. EECOM confirmed 26/26 commands + packaging complete (minor gap: "streams" alias untested, non-blocking). +**Learning:** When test assertions reference file counts, they MUST be kept in sync with disk reality. The principle applies to ALL assertion arrays (EXPECTED_SCENARIOS, EXPECTED_FEATURES, EXPECTED_GUIDES, EXPECTED_REFERENCE, etc.). Consider dynamic discovery pattern (used in EXPECTED_BLOG) for resilience against content additions. diff --git a/.squad/agents/flight/charter.md b/.squad/agents/flight/charter.md index 609afd702..60fb93f1f 100644 --- a/.squad/agents/flight/charter.md +++ b/.squad/agents/flight/charter.md @@ -29,24 +29,6 @@ **I don't handle:** Implementation details, test writing, docs, distribution, security audits. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Coordinator selects — planning uses haiku, code review uses sonnet, architecture proposals may bump to premium -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/flight-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Decisive and opinionated when it matters. Sees the whole picture before anyone else does. Pushes back on scope creep. Respects the team's time by making clear calls, not committees. +Preferred: auto diff --git a/.squad/agents/flight/history.md b/.squad/agents/flight/history.md index 3756a8af3..cc20cc420 100644 --- a/.squad/agents/flight/history.md +++ b/.squad/agents/flight/history.md @@ -4,8 +4,87 @@ --- +📌 **Team update (2026-03-22T09-35Z — Wave 1):** Ambient personal squad design validated and 19-task implementation plan authored across 4 PRs (Phase 1 SDK, Phase 2 CLI, Phase 3 governance, Phase 4 tests). MVP = PR #1 + PR #3. EECOM executing Phase 1–2 (SDK + CLI), Procedures executing Phase 3 (governance) concurrently. All design gaps resolved; dependency graph established. Procedures wrote governance proposals for personal squad + economy mode — awaiting your review. Sims to execute Phase 4 after Phase 1+2 merge. Directive captured: bug #502 (node:sqlite, P1) to be picked up after Wave 1. No blocking issues — ready for execution. + +## Core Context + +Three-branch model (main/dev/insiders). Apollo 13 team, 3931 tests. Boundary review heuristic: "Squad Ships It" — if Squad doesn't ship the code, it's IRL content. Proposal-first: meaningful changes need docs/proposals/ before code. Two-error lockout policy: agent locked out after 2 errors in a session. Test name-agnosticism: framework tests must never depend on dev team's agent names. + ## Learnings -**Updated now.md to reflect post-v0.8.24 state:** Apollo 13 team, 3931 tests, Tamir's active branches across 5 feature streams (remote-control, hierarchical-squad-inheritance, ralph-watch, project-type-detection, prevent-git-checkout-data-loss). +### Adoption Tracking Architecture +Three-tier opt-in system: Tier 1 (aggregate-only, `.github/adoption/`) ships first; Tier 2 (opt-in registry) designed next; Tier 3 (public showcase) launches when ≥5 projects opt in. `.squad/` is for team state only, not adoption data. Never list individual repos without owner consent. + +### Remote Squad Access +Three-phase rollout: Phase 1 — GitHub Discussions bot with `/squad` command (1 day, zero hosting). Phase 2 — GitHub Copilot Extension via Contents API (1 week). Phase 3 — Slack/Teams bot (2 weeks). Constraint: any remote solution must solve `.squad/` context access. + +### Content Triage Skill +"Squad Ships It" litmus test codified into reusable workflow. Triggered by `content-triage` label. Output: boundary analysis, sub-issues for PAO (doc extraction), IRL reference for Scribe. Content labels: `content:blog`, `content:sample`, `content:video`, `content:talk`. + +### Distributed Mesh Integration +Zero code changes. Skill files in templates/skills/, scripts in scripts/mesh/, docs in features/. mesh.json stays separate from squad.config.ts. Convention-first additive layer — invisible if unused. 125:1 ratio (30 lines of script vs 3,756 lines of deleted federation code). + +### Sprint Prioritization Pattern +Rank by: (1) bugs with active user impact, (2) quality/test gaps blocking GA, (3) high-ROI features unblocking downstream work. Interleave stability (bugs/quality) with velocity (features) across sprint capacity. **Updated wisdom.md with 4 patterns + 2 anti-patterns from recent work:** Test name-agnosticism for team rebirths, dynamic filesystem discovery for evolving content, cli-entry.ts unwired command bug pattern, bump-build.mjs version mutation timing, invalid semver formats, git reset data loss. + +📌 **Team update (2026-03-10T12-55-49Z):** Adoption tracking architecture finalized. Three-tier system approved: Tier 1 (aggregate-only, `.github/adoption/`) shipping with PR #326; Tier 2 (opt-in registry) designed for next PR; Tier 3 (public showcase) launches when ≥5 projects opt in. Append-only file governance rule enforced to prevent data loss. Microsoft ampersand style guide adopted for all user-facing documentation. + +### PR #331 Review — Boundary Review Pattern Reinforced (2026-03-10) +Approved PR #331 ("docs: scenario and feature guides from blog analysis") for merge. PAO's boundary review (remove external infrastructure docs, reframe platform features to clarify scope, keep Squad behavior/config docs) was executed correctly. Key decisions: (1) ralph-operations.md and proactive-communication.md deleted — both document infrastructure around Squad, not Squad itself; (2) issue-templates.md reframed to clarify "GitHub feature configured for Squad" not "Squad feature"; (3) reviewer-protocol.md Trust Levels section kept — documents user choice spectrum within Squad's existing review system. Litmus test pattern: if Squad doesn't ship the code/config, it's IRL content. Docs-test sync maintained. Pattern reinforced as reusable boundary review heuristic for future doc PRs. + +**Adoption tracking architecture — three-tier opt-in system:** `.squad/` is for team state only, not adoption data (boundary pattern). Move tracking to `.github/adoption/`. Never list individual repos without owner consent — aggregate metrics only until opt-in exists. Tier 1 (ship now) = aggregate monitoring. Tier 2 (design next) = opt-in registry in `.github/adoption/registry.json`. Tier 3 (launch later) = public showcase once ≥5 projects opt in. Monitoring infra (GitHub Action + script) is solid — keep it. Privacy-first architecture: code search results are public data, but individual listings require consent. + +**Remote Squad access — three-phase rollout:** Phase 1 (ship first): GitHub Discussions bot with `/squad` command. Workflow checks out repo → has full `.squad/` context → answers questions → posts reply. 1 day build, zero hosting, respects repo privacy automatically. Phase 2 (high value): GitHub Copilot Extension — fetches `.squad/` files via GitHub API, answers inline in any Copilot client (VS Code, CLI, mobile). Works truly remote, instant, no cold start. 1 week build. Phase 3 (enterprise): Slack/Teams bot for companies. Webhook + GitHub API fetch. 2 weeks build. Constraint: Squad needs `.squad/` state (team.md, decisions.md, histories, routing) to answer intelligently. Any remote solution must solve context access. GitHub Actions workflows solve this for free (checkout gives full state). Copilot Extension uses Contents API. Discussions wins for MVP because it's async (perfect for knowledge queries), persistent (answers are searchable), and zero infra. Proposal-first: write `docs/proposals/remote-squad-access.md` before building. + +### Content Triage Skill Codified (2026-03-10) +Created `.squad/skills/content-triage/SKILL.md` to codify the boundary heuristic from PR #331. Defines repeatable workflow for triaging external content (blog posts, sample repos, videos, talks) to determine what belongs in Squad's public docs vs IRL tracking. Key components: (1) "Squad Ships It" litmus test — if Squad doesn't ship the code/config, it's IRL content; (2) triage workflow triggered by `content-triage` label or external content reference in issue body; (3) output format with boundary analysis, sub-issues for PAO (doc extraction), and IRL reference entry for Scribe; (4) label convention (`content:blog`, `content:sample`, `content:video`, `content:talk`); (5) Ralph integration for routing to Flight, creating sub-issues, and notifying Scribe. Examples include Tamir blog analysis (PR #331), sample repo with ops patterns, and conference talk. Pattern prevents infrastructure docs from polluting Squad's public docs while ensuring community content accelerates adoption through proper extraction and referencing. + +📌 **Team update (2026-03-11T01:27:57Z):** Content triage skill finalized; "Squad Ships It" boundary heuristic codified into shared team decision (decisions.md). Remote Squad access phased rollout approved (Discussions bot → Copilot Extension → Chat bot). PR #331 boundary review pattern established as standard for all doc PRs. Triage workflow enables Flight to scale as community content accelerates. + +### Ambient Personal Squad Architecture Review (#329 + #344) + +**Design validated:** The `flight-ambient-personal-squad.md` proposal is structurally sound. Key finding: `multi-squad.ts` already stores personal squad paths as direct dirs (`squads/{name}/`) with no nested `.squad/` subfolder — the "each team IS the squad root" convention is already the implementation, not a change needed. + +**Five gaps found in the design doc:** +1. No `resolvePersonalAgents()` function signature — added in implementation plan (T2). +2. Scenario 9 contradiction: personal agents wrote to project orchestration log, violating ghost protocol. Resolution: coordinator writes audit trail (project state), not the personal agent. +3. `--team-root` scope was undefined. Decision: additive CLI flag on `squad init`, backward compat with existing `config.json` teamRoot. +4. `squad personal init` was missing — bootstrapping path for first-time users. Added as T6 subcommand. +5. `SQUAD_NO_PERSONAL` env var was in Open Questions but absent from phases. Added to T1. + +**Architecture decision:** Need `ensureSquadPathTriple` in `resolution.ts` (T4) — personal agents write to a third root (personal squad dir). Without it, ghost protocol is advisory-only and not enforced by path guards in SDK. + +**Phasing:** Four PRs. MVP = PR #1 (SDK Foundation) + PR #3 (Governance). Users see ambient cast immediately; `squad personal` commands are quality-of-life on top. + +**Implementation plan written to:** `.squad/decisions/inbox/flight-329-344-implementation-plan.md` + +📌 **Team update (2026-03-24):** Ambient personal squad design reviewed and approved with 5 gaps identified and resolved. Implementation plan broken into 4 PRs across EECOM (SDK + CLI), Procedures (governance), and Sims (tests). MVP path = SDK foundation + governance updates. Phased to avoid one giant PR. + +### Session 2 Summary (2026-03-22) + +Wave 1 architecture work on #329/#344: validated 20KB personal squad design doc, identified and patched 5 gaps, authored 19-task implementation plan spanning 4 future PRs. Implementation not yet started — deferred to future session. EECOM assigned Phase 1–2 (SDK + CLI), Procedures assigned Phase 3 (governance), Sims assigned Phase 4 (tests). + +### Community PR Batch Review — July 2026 + +Five open community PRs reviewed: + +- **#524 (diberry)** — Astro docs improvements (sitemap, RSS, schema fields, ToC component, robots.txt). ✅ Merge-ready. Flag: `robots.txt` Sitemap URL points to `squad.dev` while `astro.config.mjs` still uses `bradygaster.github.io` — minor URL inconsistency to address. +- **#523 (diberry)** — Worktree-aware `detectSquadDir` + `resolveWorktreeMainCheckout` + init guard. ✅ Merge-ready. Directly addresses the worktree gap flagged in #525. Clean implementation; interactive TTY prompt with sensible default. +- **#522 (tamirdresher)** — Rate limiting/circuit breaker watch integration. 🔄 Still a full rewrite of watch.ts. Brady's CHANGES_REQUESTED (additive patch, not full file replacement) has NOT been addressed. Same structural concern remains. +- **#513 (tamirdresher)** — Cross-machine-coordination SKILL.md. 🔄 Wrong directory (`.squad/skills/` is team-state; generic library content belongs in `templates/skills/`). Personal use case examples (voice cloning, DevBox) should be generalized. Needs `docs/proposals/` entry per proposal-first policy. +- **#507 (JasonYeYuhe)** — Chinese README translation. 🔄 Needs a community-maintained freshness disclaimer before merging. Translation quality looks solid; the maintenance burden concern is the only gate. + +**Patterns noted:** +- Diberry (MSFT) is delivering consistent, architecturally-sound contributions — both PRs are merge-ready. +- Tamir's contributions are technically strong but need delivery discipline (full-rewrite vs. surgical patch, proposal-first for new primitives). +- Community translations are welcome but need a sustainability framing before merge. + +### Worktree Gap Triage — #525 (2025-07-18) + +Community contributor joniba filed #525 identifying that Squad has full worktree *detection* but zero worktree *creation* in the coordinator/spawn flow. Validated all 10 claims — analysis is accurate. The reading infrastructure (resolveSquad() worktree detection, .gitattributes merge=union, boundary tests) is ~95% complete. The gap: ralph-commands.ts hardcodes `git checkout -b` in all 3 platform adapters (lines 50/71/92), coordinator never creates worktrees before spawn, no WORKTREE_PATH in prompts, and issue-lifecycle.md is referenced in squad.agent.md but doesn't exist. + +**Decision:** P2 — important but not v1-blocking. Broke into 5 sub-issues: (1) doc fix for missing issue-lifecycle.md (quick win → Procedures), (2) worktree variant in ralph-commands.ts (EECOM), (3) coordinator pre-spawn logic (Procedures + EECOM), (4) post-merge cleanup (EECOM), (5) architecture decision on heuristic (Flight). Sub-issue #1 ships immediately; #2–5 queue post-Wave-1 alongside SubSquads work where parallel execution becomes a hard requirement. + +**Backlog priority recommendation:** Top 5 for v1 = #508 (Ambient Personal Squad), #498 (remove .squad/ from VCS), #485 (Agent Spec & Validation), #481 (Typed StorageProvider), #347 (shore up init --sdk). Quick wins: #525 doc fix, #347. Deprioritize: manual verification debt (#418–421), long-term exploratory. A2A (#332–336) stays shelved per existing decision. diff --git a/.squad/agents/gnc/charter.md b/.squad/agents/gnc/charter.md index aeac8c6f4..5b45c8ead 100644 --- a/.squad/agents/gnc/charter.md +++ b/.squad/agents/gnc/charter.md @@ -31,24 +31,6 @@ **I don't handle:** Feature design, docs, distribution, visual design, security hooks. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Performance analysis uses sonnet. Simple changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/gnc-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Performance-aware and event-driven. The event loop is truth. If it blocks, it's broken. If it leaks, it's broken. Keeps the runtime flying straight — guidance, navigation, control. +Preferred: auto diff --git a/.squad/agents/gnc/history.md b/.squad/agents/gnc/history.md index cbd545bef..af2c4a257 100644 --- a/.squad/agents/gnc/history.md +++ b/.squad/agents/gnc/history.md @@ -9,3 +9,6 @@ ### Node Version Requirements Node.js ≥20 required. Node 24+ enforces strict ESM resolution (no extensionless imports). cli-entry.ts has runtime check that warns about node:sqlite availability (≥22.5.0). + +### Dual-Layer ESM Fix (Issue #449) +Upgraded from single-layer session.js patch to dual-layer approach: (1) Inject `exports` field into vscode-jsonrpc@8.2.1 package.json at postinstall — this is the canonical fix that resolves ALL subpath imports at once, matching vscode-jsonrpc v9.x. (2) Keep session.js `.js` extension patch as defense-in-depth. Added `squad doctor` detection for both layers (checks vscode-jsonrpc exports field and copilot-sdk session.js import syntax). Runtime Module._resolveFilename patch in cli-entry.ts remains as Layer 3 for npx cache hits where postinstall never runs. diff --git a/.squad/agents/guido/charter.md b/.squad/agents/guido/charter.md index c0f452292..fd4c656f2 100644 --- a/.squad/agents/guido/charter.md +++ b/.squad/agents/guido/charter.md @@ -29,24 +29,6 @@ **I don't handle:** Core runtime, docs, distribution, visual brand, security hooks. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Extension API work uses sonnet. Config changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/guido-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Hands-on and detail-oriented. Bridges Squad and VS Code runtime. Guidance navigation — making sure Squad works wherever the developer is, whether in the terminal or the editor. +Preferred: auto diff --git a/.squad/agents/handbook/charter.md b/.squad/agents/handbook/charter.md index f2bda5049..bf1b2df56 100644 --- a/.squad/agents/handbook/charter.md +++ b/.squad/agents/handbook/charter.md @@ -21,13 +21,11 @@ ## How I Work -- The SDK should be an agent framework designed to make it easy for itself to build apps with itself -- Every public function gets a JSDoc comment that an LLM can parse and act on -- Structured exports over barrel files — discoverability matters -- Type annotations are documentation — make them descriptive -- Code examples in comments are worth more than paragraphs of prose -- **LLM-FIRST DOCS (hard rule):** Every public API surface must have JSDoc comments structured enough that an LLM reading the .d.ts files can correctly use the SDK without additional context. Function signatures, parameter descriptions, return types, and usage examples are mandatory. -- **LEGACY CLEANUP (hard rule):** Track and remove beta-era artifacts that confuse new users or AI consumers. The .ai-team/ folder is the first target. +- SDK should be self-building: easy for agents to build with it +- Every public function: JSDoc that LLMs can parse and act on +- Structured exports > barrel files; type annotations = documentation +- Code examples in comments > prose +- Track and remove legacy artifacts (e.g., .ai-team/ folder) ## Boundaries @@ -35,24 +33,6 @@ **I don't handle:** SDK architecture (that's CAPCOM), SDK implementation (that's EECOM), runtime performance (that's GNC), security (that's RETRO). -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** Reviews SDK PRs for documentation completeness and API usability. On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Documentation writing needs sonnet-level quality. Quick edits use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/handbook-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Empathetic and precise. The flight handbook is the difference between a crew that knows what to do and a crew that's guessing. If someone — human or AI — can't figure out how to use the SDK from the docs alone, the docs are wrong. Writes the manual so both astronauts and mission control can fly the ship. +Preferred: auto diff --git a/.squad/agents/inco/charter.md b/.squad/agents/inco/charter.md index f66859fdc..91b5b06d2 100644 --- a/.squad/agents/inco/charter.md +++ b/.squad/agents/inco/charter.md @@ -32,24 +32,6 @@ **I don't handle:** Runtime implementation, test writing, architecture decisions, security, SDK integration. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Design decisions use sonnet. Quick copy edits use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/inco-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Visual-first and interaction-obsessed. Every pixel in the terminal has purpose. Copy is UI — words matter as much as layout. The console display is the crew's window into mission status — INCO makes sure it's clear, beautiful, and useful. +Preferred: auto diff --git a/.squad/agents/inco/history.md b/.squad/agents/inco/history.md new file mode 100644 index 000000000..a13ff5127 --- /dev/null +++ b/.squad/agents/inco/history.md @@ -0,0 +1,6 @@ +# INCO + +## Core Context + +Terminal flicker fix cherry-picked from main to dev — PR #405 merged (March 2026). + diff --git a/.squad/agents/network/charter.md b/.squad/agents/network/charter.md index 6af6f0d6d..0f31e96ff 100644 --- a/.squad/agents/network/charter.md +++ b/.squad/agents/network/charter.md @@ -30,24 +30,6 @@ **I don't handle:** Feature implementation, docs content, architecture decisions, security hooks. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Bundling decisions use sonnet. Config tweaks use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/network-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -User-first, always. If users have to think about installation, install is broken. Every byte in the bundle is justified. Ground station coverage is global — npm, esbuild, every platform. +Preferred: auto diff --git a/.squad/agents/network/history.md b/.squad/agents/network/history.md new file mode 100644 index 000000000..f979f9859 --- /dev/null +++ b/.squad/agents/network/history.md @@ -0,0 +1,22 @@ +# Network — History + +> Distribution specialist. Installation should be invisible. + +## Learnings + +### Template Placement Pattern (2026-03-15) + +Template placement: canonical skill source is `.squad/skills/`, copies to `packages/*/templates/skills/` for npm distribution. Root `templates/` is NOT used by SDK/CLI init code. The build process now auto-syncs from canonical to packages via `scripts/sync-skill-templates.mjs`, preventing divergence. Old locations (`templates/skills/distributed-mesh/`, `templates/mesh/`) removed — they were never referenced and contributed to maintenance burden. + +### Distributed Mesh Template Placement (2026-03-08) + +Placed the distributed-mesh skill and scaffolding files in the template structure. Three parallel template locations (root, SDK, CLI) receive the SKILL.md. The mesh/ directory holds the sync scripts and config example. This follows the existing pattern where product-shipped skills go in all three template dirs so both init paths (`squad-sdk` and `squad-cli`) can scaffold them into new projects. + +The sync scripts (~40 lines each, bash and PowerShell) materialize remote squad state locally using git/curl. No daemons, no running processes. This is Phase 1 distributed coordination — git pull/push with write partitioning. + +### Mesh State Repo Init Mode (2026-03-08) + +Added `--init` flag to sync scripts for scaffolding mesh state repositories. When users run `sync-mesh.sh --init` or `sync-mesh.ps1 -Init`, the scripts read mesh.json and generate the directory structure: squad folders with placeholder SUMMARY.md files, plus a root README listing participants. Idempotent — skips existing files. This removes the manual setup step when creating a new mesh state repo. The init path adds ~40 lines but keeps sync logic unchanged. + +📌 Team update (2026-03-14T22-01-14Z): Distributed mesh integrated with deterministic skill pattern — decided by Procedures, PAO, Flight, Network + diff --git a/.squad/agents/pao/charter.md b/.squad/agents/pao/charter.md index aa4d55841..0073c0dfa 100644 --- a/.squad/agents/pao/charter.md +++ b/.squad/agents/pao/charter.md @@ -26,6 +26,14 @@ - **DOCS-TEST SYNC (hard rule):** When adding new docs pages (guides, blog posts), update the corresponding test assertions in test/docs-build.test.ts in the SAME commit. Stale test assertions that block CI are a docs team failure. - **CONTRIBUTOR RECOGNITION (hard rule):** Each release includes an update to the Contributors Guide page. No contribution goes unappreciated. - **DOC-IMPACT REVIEW (hard rule):** Review every PR for documentation impact. If a change affects user-facing behavior, ensure corresponding docs are updated or flag the gap. +- **CONTENT DISCIPLINE:** One canonical page per concept. Link, don't duplicate. +- **DEEP LINKING:** Use most specific anchor available when linking between docs pages. +- **SCANNABILITY REVIEW (hard rule):** All content must use the format that best serves scannability. Apply this framework during review: + - **Paragraphs:** Use for narrative flow, conceptual explanations, "why" context, and transitions. Limit to 3-4 sentences. If longer, consider breaking into sections or converting structured parts to lists/tables. + - **Bullet lists:** Use for features, options, steps (non-sequential), any items users scan for one thing. Start with strong verbs or nouns. Keep items parallel in structure. + - **Tables:** Use for comparisons (feature A vs B), structured reference data (config options, API parameters), or any grid of related attributes. Include headers that describe the relationship. + - **Quotes/indents:** Use for warnings, important callouts, citations, or examples. Reserve for content that needs visual separation. + - **Decision test:** If a reader is hunting for one specific item in a paragraph, convert to bullets or table. If explaining relationships between concepts, keep paragraph. If comparing options, use table. ## Boundaries @@ -33,24 +41,6 @@ **I don't handle:** Feature implementation, test writing, architecture decisions, distribution, security. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Docs writing needs sonnet-level quality. Quick edits use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/pao-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Clear, engaging, amplifying. Makes complex things feel simple. Believes that if you can't explain a feature in one sentence, it's not ready to ship. Amplifies the team's work to the community. +Preferred: auto diff --git a/.squad/agents/pao/history.md b/.squad/agents/pao/history.md index 85b620eb5..ef78e54c7 100644 --- a/.squad/agents/pao/history.md +++ b/.squad/agents/pao/history.md @@ -2,19 +2,64 @@ > Public Affairs Officer +## Core Context + +Docs live in docs/ with blog/, concepts/, cookbook/, getting-started/, guide/, features/, scenarios/ sections. Blog tests use filesystem discovery (dynamic); other sections use hardcoded expected arrays. Microsoft Style Guide enforced: sentence-case headings, active voice, second person, present tense. Docs format: plain markdown, H1 title, experimental warning, "Try this" code blocks, overview, HR, H2 content sections. Scannability framework: paragraphs for narrative, bullets for scannable items, tables for comparisons. + ## Learnings -### Docs Build Architecture -docs/ directory contains blog/, concepts/, cookbook/, getting-started/, guide/ sections. Build script produces HTML output for all sections. Blog posts follow numbered naming convention (001-xxx.md through 026-xxx.md). +### Blog Post Format +YAML frontmatter: title, date, author, wave, tags, status, hero. Body: experimental warning, What Shipped, Why This Matters, Quick Stats, What's Next. 200-400 words for infrastructure releases. No hype — explain value. -### Dynamic Blog Test Pattern -docs-build.test.ts discovers blog posts from filesystem instead of hardcoded list. Adding/removing blog posts no longer requires test updates. Other sections (getting-started, guides) still use hardcoded expected lists since they change rarely. +### Boundary Review Heuristic +"Squad Ships It" litmus test: if Squad doesn't ship the code/config, it's IRL content. Platform features used alongside Squad: clarify whose feature it is. Squad behavior/config docs stay. External infrastructure docs (ralph-operations, proactive-communication) → IRL. + +### DOCS-TEST SYNC +When adding docs pages, update test assertions in docs-build.test.ts in the SAME commit. When rebasing doc PRs, main branch (already merged) takes priority. ### Contributor Recognition -CONTRIBUTING.md and CONTRIBUTORS.md exist at repo root. Contributors Guide page added in v0.8.24. Each release should include contributor recognition updates. +CONTRIBUTORS.md tracks team roster and community contributors. Each release includes recognition updates. Append PR counts, don't replace. + +### Skill Scope Documentation Pattern +Explicitly state what a skill produces and does NOT produce. Deterministic skills prevent agents from generating unnecessary code when templates exist. -### Blog Post Format (v0.8.25) -Release blog posts use YAML frontmatter with: title, date, author, wave, tags, status, hero. Hero is one-sentence summary. Body includes experimental warning, What Shipped section with tables/code blocks, Why This Matters section, Quick Stats, What's Next. Keep practical and developer-focused, 200-400 words for infrastructure releases. Tone ceiling enforced: no hype, explain value. +### Teams MCP Audit +External tool integrations require explicit "where to get it" guidance. Placeholder paths need clarification that users must provide actual MCP server implementations. + +### Cross-Org Authentication Docs +Problem/solution structure for multi-account auth: gh auth switch, Copilot instructions, Squad skill pattern. Cover credential helpers, EMU variations, common error messages. Cross-reference in troubleshooting and enterprise-platforms pages. ### Roster & Contributor Recognition (v0.8.25) Squad moved to Apollo 13/NASA Mission Control naming scheme (Flight, Procedures, EECOM, FIDO, PAO, CAPCOM, CONTROL, Surgeon, Booster, GNC, Network, RETRO, INCO, GUIDO, Telemetry, VOX, DSKY, Sims, Handbook). CONTRIBUTORS.md tracks both team roster and community contributors; contributor table entries grow with PRs (append PR counts rather than replace, maintaining attribution history). + +### Git Rebase for Doc Merges +When rebasing doc PRs with conflicts from other merged doc PRs, the main branch version (already merged) should generally take priority. For Node.js version references, maintain LTS terminology when present (e.g., `nvm install --lts` over specific version numbers like `nvm install 20`). Conflict resolution pattern: preserve new content from PR branch only where it doesn't duplicate or contradict already-merged changes. Use `git -c core.editor=true rebase --continue` to bypass interactive editor issues on Windows. + +### Astro Docs Format (v0.8.26) +Squad docs use plain markdown without Astro frontmatter. Structure: title (H1), experimental warning callout, "Try this" code blocks at top, overview paragraph, horizontal rule, then content sections with H2 headings. Microsoft Style Guide enforced: sentence-case headings, active voice, second person ("you"), present tense, no ampersands except in code/brand names. Features and scenarios directories added to test coverage in docs-build.test.ts. Reference implementations linked where available (e.g., ralph-watch.ps1 for operational patterns). + +### Proactive Communication Patterns (v0.8.26) +Two-way communication layer between Squad and work environment. Outbound: Teams webhook notifications (breaking, briefings, recaps, flashes) sent via Adaptive Cards — only when newsworthy. Inbound: WorkIQ/Playwright scanning of Teams channels and email → auto-create GitHub issues with teams-bridge label, anti-duplicate logic enforced. Loop: inbound creates issues → Ralph dispatches → agents work → outbound notifies results. Human stays informed on mobile. Prerequisites are enhancements, not requirements. + +📌 **Team update (2026-03-11T01:27:57Z):** Proactive communication patterns and PR trust levels (full/selective/self-managing spectrum) documented in decisions.md. Pattern rationale reinforced: Ralph 24/7 autonomous deployment requires awareness loop (Teams webhooks for outbound) and external work integration (WorkIQ scanning for inbound). Trust levels enable context-appropriate oversight without bottlenecking teams. + +### PR Trust Model Documentation (v0.8.26) +Three trust levels for PR management: (1) Full review (default, team repos) — human gate on every merge; (2) Selective review (personal projects with patterns) — human reviews only critical paths; (3) Self-managing (solo personal repos only) — Squad merges own PRs, human reviews retroactively. Added to reviewer-protocol.md as new section. Important: self-managing ≠ unmonitored; use Ralph work monitoring and Teams notifications for awareness. Decision matrix included for when to use each level. + +### Final Docs Review Pattern (v0.8.26) +Pre-PR quality reviews check: (1) Microsoft Style Guide compliance (sentence-case headings, active voice, no ampersands, present tense, second person); (2) Tone consistency (practical, developer-focused, no hype); (3) Technical accuracy (code examples, file paths, commands); (4) Cross-reference integrity (valid links between pages); (5) DOCS-TEST SYNC (test assertions match new pages); (6) Privacy directive compliance (no individual repos without consent). Fixed duplicate section heading in reviewer-protocol.md (merge artifact). All staged docs passed review and are ready to commit. + +### Squad vs IRL Boundary Review (v0.8.26) +Evaluated four docs pages from PR #331 (Tamir's blog analysis) against Squad-specificity criterion: does content document Squad features/patterns (belongs in Squad docs) or community implementation examples (belongs in Squad IRL)? Key distinction: Squad docs = "how the feature works + universal best practices" vs IRL = "how one person built an amazing setup." Results: ralph-operations.md borderline (deployment wrappers are external infrastructure, not Squad features — trim "outer loop" framing), issue-templates.md borderline (GitHub feature documented for Squad context, not Squad code — clarify scope), proactive-communication.md does not belong (community extension pattern using WorkIQ/Playwright, not built into Squad), reviewer-protocol.md trust levels section belongs (documents user choice spectrum within Squad's existing review system). Pattern: if Squad doesn't ship the code, it's IRL content; if it's a GitHub platform feature used alongside Squad, clarify that distinction; if it documents actual Squad behavior/configuration, it belongs. + +### Boundary Review Execution (v0.8.26) +Executed boundary review findings from PR #331: (1) Deleted ralph-operations.md (infrastructure around Squad, not Squad itself — moved to IRL); (2) Deleted proactive-communication.md (external tools/webhooks — moved to IRL); (3) Reframed issue-templates.md intro to clarify "GitHub feature configured for Squad" not "Squad feature"; (4) Updated EXPECTED_SCENARIOS in docs-build.test.ts to match remaining files. Pattern reinforced: boundary review = remove external infrastructure docs, reframe platform integration docs to clarify whose feature it is, keep Squad behavior/config docs. Changes staged for commit. + +### Cross-Org Authentication Docs (v0.8.26) +Created docs/src/content/docs/scenarios/cross-org-auth.md covering GitHub personal + Enterprise Managed Users (EMU) multi-account auth. Three solutions documented: (1) gh auth switch for manual account toggling; (2) Copilot instructions (.github/copilot-instructions.md) for account mapping documentation; (3) Squad skill pattern for auth error detection and recovery. Covered git credential helpers (per-host and per-org), EMU hostname variations (github.com vs dedicated instances), and common error messages (HTTP 401, authentication required). Added cross-references in troubleshooting.md (new section), enterprise-platforms.md (authentication section), and navigation.ts. Updated test/docs-build.test.ts with 'cross-org-auth' in EXPECTED_SCENARIOS. Pattern: Microsoft Style Guide (sentence-case), "Try this" prompts at top, problem/solution structure, practical examples over abstractions, links to related pages at bottom. + +### Scannability Framework (v0.8.25) +Format selection is a scannability decision, not style preference. Paragraphs for narrative/concepts (3-4 sentences max). Bullets for scannable items (features, options, non-sequential steps). Tables for comparisons or structured reference data (config, API params). Quotes/indents for callouts/warnings. Decision test: if reader hunts for one item in a paragraph, convert to bullets/table. This framework is now a hard rule in charter under SCANNABILITY REVIEW. + +### npx Purge + Agency Audit +Brady's distribution directive: `npm install -g @bradygaster/squad-cli` is the only supported install path. Remove ALL user-facing `npx @bradygaster/squad-cli` and `npx github:bradygaster/squad` references from docs. Replace with either `npm install -g` (for install steps) or `squad ` (for usage steps). Keep `npx` only for dev tools (changeset, vitest, astro, pagefind). Keep historical blog posts as-is. Migration.md "Before" column and CI/CD "OLD" examples are valid historical context — keep them. Insider program: `npm install -g @bradygaster/squad-cli@insider` and `squad upgrade` replace the old `npx github:bradygaster/squad#insider`. Agency audit: all "agency-agents" references in source files and docs are MIT attribution for the upstream open-source project — legally required, never touch them. The `agency copilot` example in cli-entry.ts help text was a competing-product reference — changed to `gh copilot`. diff --git a/.squad/agents/procedures/charter.md b/.squad/agents/procedures/charter.md index 3b5949dc7..5eb0e9266 100644 --- a/.squad/agents/procedures/charter.md +++ b/.squad/agents/procedures/charter.md @@ -29,24 +29,6 @@ **I don't handle:** Runtime implementation, test writing, docs, distribution, security. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Prompt design needs sonnet-level reasoning. Charter scaffolding can use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/procedures-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Forward-thinking and edgy. Thinks three moves ahead. Predicts what developers will need before they know they need it. Treats prompt architecture with the same rigor as system design. +Preferred: auto diff --git a/.squad/agents/procedures/history.md b/.squad/agents/procedures/history.md new file mode 100644 index 000000000..d844851aa --- /dev/null +++ b/.squad/agents/procedures/history.md @@ -0,0 +1,110 @@ +# Procedures — Project History + +> Learnings, patterns, and context for the Prompt Engineer. + +## Learnings + +📌 **Team update (2026-03-22T09-35Z — Wave 1):** Economy mode governance proposal and personal squad consult-mode governance proposal authored for squad.agent.md — both DRAFT, awaiting Flight review before merging. Economy mode adds Layer 3 table + spawn convention (`💰 economy`) + model catalog audit. Personal squad adds consult mode detection, path reference table, spawn guidance. Persistent model preference (Layer 0) documented. Proposed new skill: `.squad/skills/consult-mode/SKILL.md` (post-approval). Deterministic skill pattern proven effective. PR #503 open with skills module. Next: Flight review → merge governance to squad.agent.md. No blocking issues. + +### 2026-03-10: Deterministic skill pattern + +**Problem:** Skills were too loose. The distributed-mesh skill was tested in a real project (mesh-demo), and agents generated 76 lines of validator code, 5 test files with 43 tests, regenerated sync scripts that should have been copied from templates, and left decision files empty. The skill document let agents interpret intent instead of following explicit steps. + +**Solution:** Rewrite skills to be fully deterministic: + +1. **SCOPE section** (right after frontmatter, before Context) + - ✅ THIS SKILL PRODUCES — exact list of files/artifacts + - ❌ THIS SKILL DOES NOT PRODUCE — explicit negative list to prevent scope creep + +2. **AGENT WORKFLOW section** — Step-by-step deterministic instructions + - ASK: exact questions to ask the user + - GENERATE: exactly which files to create, with schemas + - WRITE: exactly which decision entry to write, with template + - TELL: exact message to output to user + - STOP: explicit stopping condition, with negative list of what NOT to do + +3. **Fix ambiguous language:** + - "do the task" → clarify this means "the agent's normal work" not "build something for the skill" + - "Agent adds the field" → clarify this describes what a consuming agent does with data it READ + - Phase descriptions → note that phases are project-level decisions, not auto-advanced + +4. **Decision template** — inline markdown showing exactly what to write + +5. **Anti-patterns for code generation** — explicit list of things NOT to build + +**Pattern for other skills:** All skills should have SCOPE (what it produces, what it doesn't) and AGENT WORKFLOW (deterministic steps with STOP condition). Same input → same output, every time. Zero ambiguity. + +📌 Team update (2026-03-14T22-01-14Z): Distributed mesh integrated with deterministic skill pattern — decided by Procedures, PAO, Flight, Network + +### 2026-03-15: Self-contained skills pattern (agent-skills spec) + +**Problem:** The distributed-mesh skill had a manual gap — Step 4 told the user to copy sync scripts from templates/mesh/ manually. This violated the GitHub agent-skills spec, which says: "add scripts, examples or other resources to your skill's directory. The skill instructions should tell Copilot when, and how, to use these resources." + +**Solution:** Skills are self-contained bundles. Resources live WITH the skill, not in separate template directories: + +1. **Bundle resources IN the skill directory:** Copy `sync-mesh.sh`, `sync-mesh.ps1`, and `mesh.json.example` into `.squad/skills/distributed-mesh/` +2. **Update SKILL.md workflow:** + - Step 2: Reference `mesh.json.example` from THIS skill's directory + - Step 3: COPY sync scripts from THIS skill's directory to project root (agent does it, not user) + - Step 4: RUN `--init` if Zone 2 state repo specified (agent does it, not user) +3. **Update SCOPE section:** Clarify the skill PRODUCES the copied scripts (bundled resources ≠ generated code) +4. **Replicate to templates:** Copy entire skill directory to `templates/skills/`, `packages/squad-cli/templates/skills/`, `packages/squad-sdk/templates/skills/` + +**Pattern for all skills:** Skills are self-contained. Scripts, examples, configs, and resources travel WITH the skill. The agent reads SKILL.md, sees "copy X from this directory," and does it. Zero manual steps. + +### 2026-03-15: Three new governance policies added to agent system + +**Task:** Brady directive — implement three new policies across the agent system: + +1. **Agent Error Lockout** — Added to squad.agent.md. After 2 cumulative errors (build/test failures or reviewer rejection) on the same task, agent is locked out for that task only. Different agent takes over. Coordinator tracks and enforces; Scribe logs lockout events. + +2. **Product Isolation Rule** — Added to every charter and squad.agent.md Constraints. Tests, CI, and product code must NEVER depend on specific agent names from any squad. "Our squad" must not impact "the squad." Use generic/parameterized values (e.g., "test-agent-1") instead of real agent names (Flight, EECOM, FIDO). + +3. **Peer Quality Check** — Added to every charter. Before finishing work, agents must verify their changes don't break existing tests. Run test suite for files touched. Update history.md when learning from mistakes. + +**Implementation:** Updated `.github/agents/squad.agent.md` (new section + constraint) and all 19 active agent charters in `.squad/agents/*/charter.md`. + +**Pattern:** Policies added as subsections under "How I Work" in charters to ensure they're loaded with agent context. Coordinator-level policies live in squad.agent.md with explicit enforcement instructions. + +### 2026-03-16: Team-wide reskill — 17.4% reduction + +**Context:** Routine maintenance reskill, one day after previous reskill (2026-03-15). Last reskill brought the system from 117.4KB to 51.7KB. This pass focused on remaining oversized charters. + +**Work done:** +- **Scribe (2143→1557):** Compressed workflow steps, kept essential commit instructions +- **Handbook (1807→1529):** Removed repetitive LLM-FIRST DOCS emphasis +- **FIDO (1715→1370):** Consolidated verbose NEVER/ALWAYS sections +- **Booster (1583→1368):** Same NEVER/ALWAYS compression pattern + +**Results:** 26,721→17,088 bytes (charters), 28,602→28,602 bytes (histories), total 55,323→45,690 bytes. 9,633 bytes saved (17.4% reduction). All charters now ≤1.5KB. + +**Skill extraction:** No new patterns extracted. CastingEngine integration work (from EECOM March 15) is still evolving — not yet mature enough for skill template. Histories all <12KB, no compression needed. + +**Pattern:** NEVER/ALWAYS sections in charters compress well — fold bullet lists into single-paragraph summaries. Essential workflow details (Scribe's commit steps) should stay verbose. + +### 2026-03-22: Economy mode skill and personal squad governance (#500, #344) + +**Task:** Two governance tasks — economy mode skill design and personal squad coordinator awareness. + +**Economy mode (SKILL.md):** +- Created `.squad/skills/economy-mode/SKILL.md` as a Layer 3 modifier, not a new resolution layer +- Key design decision: economy mode ONLY affects Layer 3 auto-selection — Layer 0/1/2 (user intent) always wins +- `💰` indicator in spawn acknowledgments keeps it transparent +- Activation via session phrase, persistent config (`economyMode: true` in config.json), or CLI flag +- Architecture trips shift from opus → sonnet; code tasks shift from sonnet → gpt-4.1/gpt-5-mini +- Confidence: `low` — first implementation, not yet validated + +**Personal squad governance (proposals):** +- Gap analysis: coordinator has no consult mode awareness despite full SDK implementation +- Five gaps identified: Init Mode missing personal squad resolution, no consult mode detection, TEAM_ROOT has no personal-squad semantics, charter templates lack consult-mode patterns, no consult-mode skill +- Proposed `CONSULT_MODE: true` as spawn prompt signal, `🧳 consult` in acknowledgments +- Proposed new consult-mode skill (after governance approval — skill after governance, not before) + +**Governance workflow pattern:** When proposals touch squad.agent.md (governance territory), write to `decisions/inbox/` for Flight review. Don't directly edit squad.agent.md — Flight reviews governance changes. + +**Catalog audit finding:** `claude-sonnet-4.6`, `gpt-5.4`, `gpt-5.3-codex` appear in model-selection SKILL.md fallback chains but are absent from squad.agent.md's "Valid models" catalog. Documented in economy-mode governance proposal for Flight to address. + +### Session 2 Summary (2026-03-22) + +Wave 1 governance work on #500 and #344: authored economy-mode skill (`SKILL.md`), economy-mode governance proposal, and personal-squad governance proposal. Caught `claude-sonnet-4.6` missing from valid models catalog. PR #503 (`squad/500-344-governance`) merged to dev. + diff --git a/.squad/agents/ralph/charter.md b/.squad/agents/ralph/charter.md new file mode 100644 index 000000000..c509d0c7e --- /dev/null +++ b/.squad/agents/ralph/charter.md @@ -0,0 +1,19 @@ +# Ralph — Ralph + +Persistent memory agent that maintains context across sessions. + +## Project Context + +**Project:** squad + +## Responsibilities + +- Collaborate with team members on assigned work +- Maintain code quality and project standards +- Document decisions and progress in history + +## Work Style + +- Read project context and team decisions before starting work +- Communicate clearly with team members +- Follow established patterns and conventions diff --git a/.squad/agents/ralph/history.md b/.squad/agents/ralph/history.md new file mode 100644 index 000000000..050d7a70c --- /dev/null +++ b/.squad/agents/ralph/history.md @@ -0,0 +1,16 @@ +# Project Context + +- **Project:** squad +- **Created:** 2026-03-15 + +## Core Context + +Agent Ralph initialized and ready for work. + +## Recent Updates + +📌 Team initialized on 2026-03-15 + +## Learnings + +Initial setup complete. diff --git a/.squad/agents/retro/charter.md b/.squad/agents/retro/charter.md index 6beb659aa..f20745624 100644 --- a/.squad/agents/retro/charter.md +++ b/.squad/agents/retro/charter.md @@ -23,8 +23,8 @@ - PII audit protocols: email addresses and credentials never committed to repo files - File-write guard hooks: prevent agents from writing to unauthorized paths - Raises real risks, not hypothetical ones — pragmatic security -- **SECRET HANDLING (hard rule):** Agents must NEVER write secrets, API keys, tokens, or credentials into conversational history, commit messages, logs, or any file that could be persisted. When users provide secrets, acknowledge receipt without echoing the value. Secrets belong in environment variables and secure vaults, never in text. -- **LOG HYGIENE (hard rule):** Periodically audit .squad/log/, orchestration-log/, and agent histories for accidentally leaked credentials. Clean immediately if found. +- **SECRET HANDLING (hard rule):** Never write secrets into any persisted file. See secret-handling skill. +- **LOG HYGIENE (hard rule):** Audit .squad/log/ and agent histories for leaked credentials. Clean immediately. ## Boundaries @@ -32,24 +32,6 @@ **I don't handle:** Feature implementation, docs, distribution, visual design. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Security review uses sonnet for thoroughness. Planning uses haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/retro-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Thorough but pragmatic. Doesn't cry wolf. When RETRO raises a risk, it's a real one that needs addressing. Believes security is infrastructure, not a checklist. Hook-based governance is the hill to die on. When things go wrong, RETRO calculates the safe return trajectory. +Preferred: auto diff --git a/.squad/agents/scribe/charter.md b/.squad/agents/scribe/charter.md index 9082faa45..0e45c24a6 100644 --- a/.squad/agents/scribe/charter.md +++ b/.squad/agents/scribe/charter.md @@ -18,97 +18,15 @@ ## How I Work -**Worktree awareness:** Use the `TEAM ROOT` provided in the spawn prompt to resolve all `.squad/` paths. If no TEAM ROOT is given, run `git rev-parse --show-toplevel` as fallback. Do not assume CWD is the repo root (the session may be running in a worktree or subdirectory). - -After every substantial work session: - -1. **Log the session** to `.squad/log/{timestamp}-{topic}.md`: - - Who worked - - What was done - - Decisions made - - Key outcomes - - Brief. Facts only. - -2. **Merge the decision inbox:** - - Read all files in `.squad/decisions/inbox/` - - APPEND each decision's contents to `.squad/decisions.md` - - Delete each inbox file after merging - -3. **Deduplicate and consolidate decisions.md:** - - Parse the file into decision blocks (each block starts with `### `). - - **Exact duplicates:** If two blocks share the same heading, keep the first and remove the rest. - - **Overlapping decisions:** Compare block content across all remaining blocks. If two or more blocks cover the same area (same topic, same architectural concern, same component) but were written independently (different dates, different authors), consolidate them: - a. Synthesize a single merged block that combines the intent and rationale from all overlapping blocks. - b. Use today's date and a new heading: `### {today}: {consolidated topic} (consolidated)` - c. Credit all original authors: `**By:** {Name1}, {Name2}` - d. Under **What:**, combine the decisions. Note any differences or evolution. - e. Under **Why:**, merge the rationale, preserving unique reasoning from each. - f. Remove the original overlapping blocks. - - Write the updated file back. This handles duplicates and convergent decisions introduced by `merge=union` across branches. - -4. **Propagate cross-agent updates:** - For any newly merged decision that affects other agents, append to their `history.md`: - ``` - 📌 Team update ({timestamp}): {summary} — decided by {Name} - ``` - -5. **Commit `.squad/` changes:** - **IMPORTANT — Windows compatibility:** Do NOT use `git -C {path}` (unreliable with Windows paths). - Do NOT embed newlines in `git commit -m` (backtick-n fails silently in PowerShell). - Instead: - - `cd` into the team root first. - - Stage all `.squad/` files: `git add .squad/` - - Check for staged changes: `git diff --cached --quiet` - If exit code is 0, no changes — skip silently. - - Write the commit message to a temp file, then commit with `-F`: - ``` - $msg = @" - docs(ai-team): {brief summary} - - Session: {timestamp}-{topic} - Requested by: {user name} - - Changes: - - {what was logged} - - {what decisions were merged} - - {what decisions were deduplicated} - - {what cross-agent updates were propagated} - "@ - $msgFile = [System.IO.Path]::GetTempFileName() - Set-Content -Path $msgFile -Value $msg -Encoding utf8 - git commit -F $msgFile - Remove-Item $msgFile - ``` - - **Verify the commit landed:** Run `git log --oneline -1` and confirm the - output matches the expected message. If it doesn't, report the error. - -6. **Never speak to the user.** Never appear in responses. Work silently. - -## The Memory Architecture - -``` -.squad/ -├── decisions.md # Shared brain — all agents read this (merged by Scribe) -├── decisions/ -│ └── inbox/ # Drop-box — agents write decisions here in parallel -│ ├── river-jwt-auth.md -│ └── kai-component-lib.md -├── orchestration-log/ # Per-spawn log entries -│ ├── 2025-07-01T10-00-river.md -│ └── 2025-07-01T10-00-kai.md -├── log/ # Session history — searchable record -│ ├── 2025-07-01-setup.md -│ └── 2025-07-02-api.md -└── agents/ - ├── kai/history.md # Kai's personal knowledge - ├── river/history.md # River's personal knowledge - └── ... -``` - -- **decisions.md** = what the team agreed on (shared, merged by Scribe) -- **decisions/inbox/** = where agents drop decisions during parallel work -- **history.md** = what each agent learned (personal) -- **log/** = what happened (archive) +**Worktree awareness:** Use `TEAM ROOT` from spawn prompt; fallback: `git rev-parse --show-toplevel`. + +After substantial work: +1. Log session to `.squad/log/{timestamp}-{topic}.md` (who, what, outcomes) +2. Merge `.squad/decisions/inbox/` → `.squad/decisions.md`, delete inbox files +3. Deduplicate decisions.md by `### ` blocks (exact duplicates, overlapping topics) +4. Propagate: append `📌 Team update` to affected agents' history.md +5. Commit: cd to team root, `git add .squad/`, temp file, `git commit -F` (Windows: no `-C`, no `-m` newlines) +6. Never speak to user. Silent background operation. ## Boundaries diff --git a/.squad/agents/sims/charter.md b/.squad/agents/sims/charter.md index dc42b4606..e3aa74300 100644 --- a/.squad/agents/sims/charter.md +++ b/.squad/agents/sims/charter.md @@ -31,24 +31,6 @@ **I don't handle:** Unit tests (that's FIDO), feature implementation, docs, distribution, security. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Test scenario design uses sonnet. Snapshot updates use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/sims-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Thorough and scenario-driven. The Simulations officer runs mission rehearsals — if the sim fails, the mission doesn't fly. Every test is a dress rehearsal. Every failure in simulation is a victory for the mission. +Preferred: auto diff --git a/.squad/agents/surgeon/charter.md b/.squad/agents/surgeon/charter.md index aab4eb78a..cbe7d2db2 100644 --- a/.squad/agents/surgeon/charter.md +++ b/.squad/agents/surgeon/charter.md @@ -29,40 +29,12 @@ - 4-part versions (0.8.21.4) are NOT valid semver — never use them - Set versions with `node -e` script and commit IMMEDIATELY before building -## Release Guardrails - -1. Branch from dev, never from main -2. Validate semver before npm publish -3. Verify NPM_TOKEN type before publish -4. Never create draft releases -5. Set SKIP_BUILD_BUMP=1 for CI -6. Verify npm propagation with retry logic (5 attempts, 15s sleep) -7. Tag must match package.json version exactly - ## Boundaries **I handle:** Release orchestration, versioning, GitHub Releases, changelogs, release gating. **I don't handle:** Feature implementation, test writing, docs content, architecture decisions. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Release decisions use sonnet. Version bumps use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/surgeon-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Methodical and checklist-driven. Zero improvisation. Every release follows the same process, every time. If the checklist says stop, we stop. Release health is patient health — Surgeon checks vitals before clearing for launch. +Preferred: auto diff --git a/.squad/agents/telemetry/charter.md b/.squad/agents/telemetry/charter.md index 91945bb8c..c79de114f 100644 --- a/.squad/agents/telemetry/charter.md +++ b/.squad/agents/telemetry/charter.md @@ -30,24 +30,6 @@ **I don't handle:** Feature implementation, docs, distribution, visual brand, security. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Infrastructure design uses sonnet. Config changes use haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/telemetry-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Infrastructure-aware and telemetry-native. If you can't see it, it didn't happen. Every span tells a story. The dashboard is the mission control display — it must be clear, accurate, and real-time. +Preferred: auto diff --git a/.squad/agents/vox/charter.md b/.squad/agents/vox/charter.md index 9e5303ed8..311b6658f 100644 --- a/.squad/agents/vox/charter.md +++ b/.squad/agents/vox/charter.md @@ -31,24 +31,6 @@ **I don't handle:** Feature design, docs, distribution, visual brand, security hooks. -**When I'm unsure:** I say so and suggest who might know. - -**If I review others' work:** On rejection, I may require a different agent to revise (not the original author) or request a new specialist be spawned. The Coordinator enforces this. - ## Model -- **Preferred:** auto -- **Rationale:** Shell architecture uses sonnet. Event wiring uses haiku. -- **Fallback:** Standard chain - -## Collaboration - -Before starting work, run `git rev-parse --show-toplevel` to find the repo root, or use the `TEAM ROOT` provided in the spawn prompt. All `.squad/` paths must be resolved relative to this root. - -Before starting work, read `.squad/decisions.md` for team decisions that affect me. -After making a decision others should know, write it to `.squad/decisions/inbox/vox-{brief-slug}.md`. -If I need another team member's input, say so — the coordinator will bring them in. - -## Voice - -Methodical and responsive. If the user typed it and nothing happened, that's on VOX. The voice loop — real-time interactive communications. Every keystroke gets a response. Every session is a conversation. +Preferred: auto diff --git a/.squad/comms/.gitignore b/.squad/comms/.gitignore new file mode 100644 index 000000000..1313383b1 --- /dev/null +++ b/.squad/comms/.gitignore @@ -0,0 +1,7 @@ +# Runtime state (not committed) +review-state.db +review-state.db-journal +review-state.db-wal +review-state.db-shm +audit/ +!audit/.gitkeep diff --git a/.squad/comms/README.md b/.squad/comms/README.md new file mode 100644 index 000000000..8359c476a --- /dev/null +++ b/.squad/comms/README.md @@ -0,0 +1,27 @@ +# PAO External Communications + +> Phase 1: Manual-trigger, draft-only mode with human review gate. + +## Directory Structure + +- `audit/` — Runtime-only audit trail for every draft-review-post action (not committed to git; keep `audit/.gitkeep`) +- `review-state.db` — SQLite-based single-reviewer lease and draft state (created at runtime) +- `templates/` — Response templates for common scenarios +- `tests/` — Comms workflow and review-state coverage + +## Workflow + +1. Human manually triggers PAO to scan issues and discussions for unanswered items +2. PAO drafts responses using humanizer skill +3. PAO presents review table with confidence flags +4. Human reviews, approves/edits/skips each draft +5. Human posts approved responses +6. Every action is logged to runtime-only `audit/` + +## Safety + +- `banana` — freezes all pending drafts (safe word) +- Phase 1 is manual-trigger only +- All responses require explicit human approval +- Audit trail is append-only and runtime-only +- SQLite lease prevents concurrent review race conditions diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md new file mode 100644 index 000000000..2bec18bff --- /dev/null +++ b/.squad/comms/templates/audit-entry.md @@ -0,0 +1,41 @@ +--- +timestamp: "{ISO-8601}" +action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expire" +--- + +> All other fields are conditional on the action type. See **Conditional Fields** table below. +> Frontmatter includes `timestamp` and `action` universally, plus any action-specific required fields from the table. +> Include only the body sections relevant to your action type. + +## Context (draft, approve, edit, skip, post, delete actions) +- Thread depth: {comment count} +- Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty|empathetic-disagreement|information-request} +- Confidence: {🟢|🟡|🔴} +- Long thread flag: {true|false} + +## Draft Content (draft, edit, post actions) +{full draft text} + +## Reviewer Notes (approve, edit, skip actions) +{any edits or comments from reviewer, or "—" if none} + +## Post Result (post, delete actions) +{link to posted comment, or original URL if deleted} + +## Conditional Fields + +Not all fields apply to every action. The `outcome` value is contextual per action: + +| Action | Required Fields | Outcome Value | Optional Fields | +|--------|----------------|---------------|-----------------| +| scan | timestamp, action | item count found (e.g., "5 candidates") | — | +| draft | timestamp, action, item_type, item_number, draft_id, confidence, draft_content | — (no outcome for draft) | thread_depth | +| approve | timestamp, action, draft_id, reviewer | "approved" | reviewer_notes | +| edit | timestamp, action, draft_id, reviewer, draft_content | "edited" | reviewer_notes | +| skip | timestamp, action, draft_id, reviewer | "skipped" | reviewer_notes | +| post | timestamp, action, item_number, draft_id, reviewer | "posted" + post_result link | — | +| halt | timestamp, action, reviewer (halter) | "halted" | reason | +| resume | timestamp, action, reviewer (resumer) | "resumed" | — | +| delete | timestamp, action, item_number | "deleted" + original URL | reason | +| lint_failure | timestamp, action, draft_id | violation details (free text) | — | +| expire | timestamp, action, draft_id | "expired" | — | diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql new file mode 100644 index 000000000..d49de8d11 --- /dev/null +++ b/.squad/comms/templates/review-state-schema.sql @@ -0,0 +1,72 @@ +-- Runtime reminder: PRAGMA foreign_keys = ON; +-- PAO External Communications: Review State Database +-- Created at runtime in .squad/comms/review-state.db +-- Zero new dependencies (Copilot CLI already uses SQLite) + +-- Single global review lease — only ONE reviewer at a time +CREATE TABLE IF NOT EXISTS review_lease ( + id INTEGER PRIMARY KEY CHECK (id = 1), + status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'held')), + reviewer TEXT, + hostname TEXT, + pid INTEGER, + acquired_at TEXT, + expires_at TEXT +); + +-- Initialize the single lease row +INSERT OR IGNORE INTO review_lease (id, status) VALUES (1, 'available'); + +-- Acquire: UPDATE review_lease +-- SET status = 'held', reviewer = ?, hostname = ?, pid = ?, acquired_at = datetime('now'), expires_at = datetime('now', '+1 hour') +-- WHERE id = 1 AND (status = 'available' OR expires_at < datetime('now')); +-- Release: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1; +-- Check: SELECT * FROM review_lease WHERE id = 1; +-- Cleanup expired lease before work: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1 AND status = 'held' AND expires_at < datetime('now'); + +-- Draft tracking table +CREATE TABLE IF NOT EXISTS draft_queue ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + reviewer TEXT, + item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion')), + item_number INTEGER NOT NULL, + item_url TEXT, + response_type TEXT NOT NULL, + confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')), + draft_content TEXT NOT NULL, + thread_depth INTEGER DEFAULT 0, + long_thread_flag INTEGER DEFAULT 0, + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'edited', 'skipped', 'posted', 'halted', 'deleted')), + reviewed_at TEXT, + posted_url TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')) +); + +-- Halt state (safe word "banana" mechanism) +CREATE TABLE IF NOT EXISTS halt_state ( + id INTEGER PRIMARY KEY CHECK (id = 1), + halted INTEGER NOT NULL DEFAULT 0, + halted_by TEXT, + halted_at TEXT, + reason TEXT +); + +-- Initialize halt state (not halted by default) +INSERT OR IGNORE INTO halt_state (id, halted) VALUES (1, 0); + +-- Audit log (append-only, mirrors runtime audit files) +CREATE TABLE IF NOT EXISTS audit_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL DEFAULT (datetime('now')), + action TEXT NOT NULL, + item_type TEXT, + item_number INTEGER, + draft_id INTEGER, + reviewer TEXT, + outcome TEXT, + details TEXT +); diff --git a/.squad/comms/templates/tone-validation.json b/.squad/comms/templates/tone-validation.json new file mode 100644 index 000000000..c66625fc3 --- /dev/null +++ b/.squad/comms/templates/tone-validation.json @@ -0,0 +1,88 @@ +{ + "version": 1, + "description": "Tone validation patterns for PAO external communications", + "reject_patterns": [ + { + "id": "corporate-speak", + "pattern": "(?:[Ww]e appreciate your patience|[Pp]lease be advised|[Pp]er our discussion|[Aa]s per|[Kk]indly note|[Pp]lease do not hesitate)", + "message": "Corporate speak detected. Use conversational tone instead." + }, + { + "id": "passive-voice-formal", + "pattern": "(?:[Ii]t has been determined|[Ii]t was decided|[Hh]as been escalated|[Ii]s being investigated|[Hh]as been noted)", + "message": "Formal passive voice detected. Use active voice: 'We determined...' or 'We're looking into...'" + }, + { + "id": "marketing-hype", + "pattern": "(?:[Bb]est[- ]in[- ]class|[Cc]utting[- ]edge|[Rr]evolutionary|[Gg]ame[- ]changing|[Ii]ndustry[- ]leading|[Nn]ext[- ]generation|[Aa]mazing feature)", + "message": "Marketing hype detected. Be specific about what the feature does, not how great it is." + }, + { + "id": "empty-acknowledgment", + "pattern": "^\\s*(?:[Tt]hanks for your feedback\\.?|[Tt]hank you for reaching out\\.?)\\s*$", + "message": "Empty acknowledgment without substance. Add specific context or next steps." + }, + { + "id": "robot-signature", + "pattern": "(?:[Bb]est regards|[Ss]incerely|[Kk]ind regards|[Rr]espectfully|[Ww]arm regards)\\s*[,.]?\\s*(?:[Pp][Aa][Oo]|[Tt]he [Ss]quad [Tt]eam|[Ss]quad [Bb]ot)", + "message": "Robot signature detected. Responses should end naturally, not with formal sign-offs." + }, + { + "id": "over-promising", + "pattern": "(?:[Ww]e will ship|[Ww]e'll release|[Cc]oming soon|[Ii]n the next release|[Dd]efinitely fix|[Gg]uaranteed)", + "message": "Over-promising detected. Only commit to what the team has explicitly agreed to." + }, + { + "id": "dismissive", + "pattern": "(?:[Ww]orks as designed|[Nn]ot a bug|[Ww]on't fix|[Tt]hat's expected|[Uu]ser error)", + "message": "Dismissive language detected. Acknowledge the experience before explaining the design." + }, + { + "id": "profanity", + "pattern": "\\b(?:[Dd]amn|[Hh]ell|[Cc]rap|[Ss]hit|[Ff]uck|[Aa]ss|[Bb]astard|[Bb]itch)\\b", + "message": "Profanity detected. Never include profanity, even when quoting." + } + ], + "require_patterns": [ + { + "id": "acknowledgment", + "pattern": "(?:[Tt]hanks|[Tt]hank you|[Gg]ood catch|[Gg]reat question|[Ii]nteresting|[Aa]ppreciate|[Ww]elcome)", + "message": "Response should include acknowledgment of the author's contribution.", + "applies_to": ["welcome", "troubleshooting", "acknowledgment"] + }, + { + "id": "action-oriented", + "pattern": "(?:[Ll]et us know|[Ff]eel free|[Hh]appy to help|[Ww]e'll update|[Rr]each out|[Ww]e'll dig|[Kk]eep us posted)", + "message": "Response should end with an action-oriented close.", + "applies_to": ["troubleshooting", "feature-guidance", "technical-uncertainty"] + }, + { + "id": "context-provided", + "pattern": "(?:[Cc]urrently|[Rr]ight now|[Aa]t the moment|[Aa]s of|[Tt]he way it works)", + "message": "Feature guidance should provide context on current state.", + "applies_to": ["feature-guidance"] + }, + { + "id": "uncertainty-honest", + "pattern": "(?:[Nn]ot sure|[Nn]ot 100%|[Dd]on't know yet|[Ss]till investigating|[Uu]nclear|[Hh]aven't determined)", + "message": "Technical uncertainty should be honest about unknowns.", + "applies_to": ["technical-uncertainty"] + } + ], + "confidence_thresholds": { + "high": { + "description": "Answered before, clear docs, community consensus", + "min_similarity": 0.8, + "baseline_blocking": true + }, + "medium": { + "description": "Technically sound but minor uncertainty or tone-dependent", + "min_similarity": 0.6 + }, + "low": { + "description": "Technical uncertainty, policy decision, reputational risk", + "min_similarity": 0.0, + "requires_review": true + } + } +} diff --git a/.squad/comms/tests/ci-gate.md b/.squad/comms/tests/ci-gate.md new file mode 100644 index 000000000..ba9f658e3 --- /dev/null +++ b/.squad/comms/tests/ci-gate.md @@ -0,0 +1,54 @@ +# CI Tone Lint Gate + +> Automated quality checks for PAO community response drafts. + +## When This Runs + +- Before any draft enters the review table +- As part of PR review when modifying humanizer or external-comms skills +- Weekly tone analytics (manual trigger via `pao analytics`) + +## Checks + +### Mandatory (blocks draft) + +1. **Anti-pattern scan** — Run all `reject_patterns` from `tone-validation.json` against draft +2. **Profanity filter** — Zero tolerance, even in quotes +3. **Minimum substance** — Draft must be >50 characters (no empty acknowledgments) +4. **Thread read verification** — Confirm all comments in thread were read before drafting + +### Mandatory for High-Confidence Drafts (🟢 only) + +5. **Baseline similarity** — Block if tone similarity to gold standard <80% for high-confidence (🟢) drafts. Aligns with `baseline_blocking: true` in `tone-validation.json`. + +### Warning (flags but doesn't block) + +1. **Positive pattern check** — Warn if response type should contain patterns from `require_patterns` +2. **Length check** — Warn if draft >500 words (may be too verbose for a GitHub comment) +3. **Emoji count** — Warn if >2 emoji in draft +4. **Similarity check** — Warn if tone similarity to gold standard <80% for medium/low-confidence drafts + +### Informational + +1. **Response type classification** — Log which template was used +2. **Confidence level** — Log confidence flag and rationale +3. **Thread depth** — Log comment count for analytics + +## Output Format + +``` +✅ PASS: Anti-pattern scan (0 violations) +✅ PASS: Profanity filter (clean) +✅ PASS: Minimum substance (127 chars) +⚠️ WARN: Positive pattern — missing action-oriented close +⚠️ WARN: Similarity to GS-2: 72% (threshold: 80%) +ℹ️ INFO: Response type: troubleshooting | Confidence: 🟡 | Thread: 4 comments +``` + +## Failure Mode + +If ANY mandatory check fails: +1. Draft is NOT added to review table +2. Error message shown to PAO with specific violation +3. PAO must redraft before presenting to reviewer +4. Failure logged to audit trail (action: "lint_failure") diff --git a/.squad/comms/tests/tone-validation-spec.md b/.squad/comms/tests/tone-validation-spec.md new file mode 100644 index 000000000..4e8edd5d9 --- /dev/null +++ b/.squad/comms/tests/tone-validation-spec.md @@ -0,0 +1,154 @@ +# Tone Validation Test Specification + +> Quality gates for PAO's external communications. All tests must pass before a draft enters the review table. + +## Test Categories + +### T1: Reject Anti-Patterns + +Drafts containing these patterns MUST be rejected: + +| Test ID | Pattern | Example (should FAIL) | +|---------|---------|----------------------| +| T1.1 | Corporate speak | "We appreciate your patience as we investigate this matter" | +| T1.2 | Formal passive voice | "It has been determined that this is a known issue" | +| T1.3 | Marketing hype | "Squad is the best-in-class solution for this" | +| T1.4 | Empty acknowledgment | "Thanks for your feedback." (with nothing else) | +| T1.5 | Robot signature | "Best regards, PAO" | +| T1.6 | Over-promising | "We'll definitely ship this in the next release" | +| T1.7 | Dismissive language | "Works as designed" (without empathy) | +| T1.8 | Profanity | Any profanity, even quoted from the original issue | + +### T2: Require Positive Patterns + +Drafts of specific types MUST contain these patterns: + +| Test ID | Response Type | Required Pattern | Example (should PASS) | +|---------|---------------|-----------------|----------------------| +| T2.1 | Welcome | Author acknowledgment | "Hey @user! Welcome to Squad 👋" | +| T2.2 | Troubleshooting | Action-oriented close | "Let us know if that helps!" | +| T2.3 | Feature guidance | Context on current state | "Currently, Squad handles this by..." | +| T2.4 | Technical uncertainty | Honesty about unknowns | "We're not 100% sure yet..." | + +### T3: Confidence Flag Accuracy + +| Test ID | Scenario | Expected Confidence | +|---------|----------|-------------------| +| T3.1 | Issue matches existing FAQ | 🟢 High | +| T3.2 | Technical question with partial docs | 🟡 Medium | +| T3.3 | Architecture question requiring Flight | 🔴 Needs review | +| T3.4 | Question about unreleased feature | 🔴 Needs review | +| T3.5 | Simple "how to install" question | 🟢 High | + +### T4: Thread Safety + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T4.1 | Thread with >10 comments | ⚠️ Long thread flag set | +| T4.2 | Thread with deleted comments | Validation warning | +| T4.3 | Thread where squad member already responded | Skip (no draft) | +| T4.4 | Thread in different language | Flag for review | + +### T5: Review Gate Enforcement + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T5.1 | Draft without human review | BLOCKED — cannot post | +| T5.2 | `pao approve` command without draft ID | Error message | +| T5.3 | Concurrent review sessions | SQLite lock prevents race | +| T5.4 | Stale lock (>1 hour) | Auto-cleanup, new session allowed | +| T5.5 | `banana` issued (safe word) | All pending drafts frozen | +| T5.6 | `pao resume` after banana | Drafts unfrozen | + +### T6: Audit Trail Completeness + +| Test ID | Action | Expected Audit Entry | +|---------|--------|---------------------| +| T6.1 | Scan completed | scan action with item count | +| T6.2 | Draft created | draft action with content | +| T6.3 | Draft approved | approve action with reviewer | +| T6.4 | Draft skipped | skip action with reviewer | +| T6.5 | Response posted | post action with URL | +| T6.6 | `banana` issued (safe word) | halt action with issuer | +| T6.7 | Draft deleted (rollback) | delete action with reason | + +### T7: Baseline Comparison (Weekly) + +| Test ID | Metric | Threshold | Frequency | +|---------|--------|-----------|-----------| +| T7.1 | Tone similarity to gold standard | >80% | Per draft | +| T7.2 | Response type distribution | No single type >60% | Weekly | +| T7.3 | Confidence flag distribution | 🔴 items <20% | Weekly | +| T7.4 | Average thread read depth | >95% of comments read | Per draft | + +## Gold Standard Responses + +The following 7 gold standard responses serve as the tone baseline. New drafts should align with this tone: + +### GS-1: Welcome (High confidence) +> Hey @newuser! Welcome to Squad 👋 Thanks for opening this — great first issue! +> +> To answer your question: Squad uses `.squad/team.md` to define your team roster. You can add members by editing that file directly or running `squad init`. +> +> Let us know if you hit any snags — happy to help! + +### GS-2: Troubleshooting (High confidence) +> Thanks for the detailed report, @reporter! +> +> This looks like it might be related to the casting registry not finding the universe file. Here's what we'd suggest: +> 1. Check that `.squad/casting/registry.json` exists and is valid JSON +> 2. Run `squad build` to regenerate from source +> 3. If that doesn't work, try deleting `.squad/casting/` and re-running `squad init` +> +> Let us know if that helps, or if you're seeing something different. + +### GS-3: Feature Guidance (Medium confidence) +> Great question! Right now, Squad handles cross-repo orchestration through the hub-and-spoke model — you'd have a central `.squad/` in one repo and reference it from others. +> +> We know this isn't ideal for every setup. There's been some discussion about making this more seamless (see #316 for the RFC). +> +> For now, the workaround is to use `squad export` to share config across repos. Hope that helps! + +### GS-4: Acknowledgment (High confidence) +> Good catch, @finder. We've confirmed this is a real issue with the session pool cleanup. +> +> It looks like sessions aren't being released when the adapter disconnects unexpectedly. We're tracking it and will update this thread when we have a fix. +> +> Thanks for flagging it — this one would have been hard to find without your repro steps! + +### GS-5: Technical Uncertainty (Low confidence) +> Interesting find, @explorer. We're not 100% sure what's causing this yet. +> +> Here's what we've ruled out: +> - It's not a casting issue (registry looks fine) +> - It's not a config issue (your squad.config.ts parses correctly) +> +> Could you share the output of `squad build --verbose`? That would help us narrow it down. We'll dig deeper and update this thread. + +### GS-6: Redirect (High confidence) +> Thanks for reaching out, @asker! This one is actually better suited for the Squad-IRL repo, which covers deployment patterns and infrastructure around Squad. +> +> You can open it here: https://github.com/bradygaster/Squad-IRL — they'll be able to help with the Terraform setup specifically. +> +> Feel free to link back to this thread for context! + +### GS-7: Closing (High confidence) +> This should be resolved in v0.8.22! 🎉 +> +> The fix was in PR #389 — the casting registry now handles universe overflow correctly when you have more than 15 agents. +> +> Thanks for reporting this, @reporter — your repro steps made this one easy to track down. Closing this out! + +## Phase 1 Readiness Criteria + +Before launch, ALL of the following must be true: +- [ ] All T1 tests have corresponding patterns in `tone-validation.json` +- [ ] All T2 tests verified against humanizer skill templates +- [ ] All 7 gold standard responses reviewed and approved by Brady or Dina +- [ ] All 9 response types have corresponding templates (7 original + empathetic disagreement + information request) +- [ ] Thread-read verification tested with threads of 1, 5, 10, and 20+ comments +- [ ] Rollback workflow (delete-and-repost) tested end-to-end +- [ ] Review gate SQLite schema tested with concurrent access +- [ ] Audit trail format validated against template +- [ ] `banana` / `pao resume` flow tested end-to-end +- [ ] At least one full scan→draft→review→post cycle completed successfully diff --git a/.squad/config.json b/.squad/config.json index 39e5c2974..8066cc05c 100644 --- a/.squad/config.json +++ b/.squad/config.json @@ -1,4 +1,4 @@ { "version": 1, - "teamRoot": "C:\\src\\squad-pr" + "defaultModel": "claude-sonnet-4.6" } \ No newline at end of file diff --git a/.squad/decisions-archive.md b/.squad/decisions-archive.md index a02605d0e..3d75e459f 100644 --- a/.squad/decisions-archive.md +++ b/.squad/decisions-archive.md @@ -4244,3 +4244,47 @@ Created two deliverables: **By:** Brady (via Copilot) **What:** DO NOT merge PR #547 (Squad Remote Control). Do not touch #547 at all. **Why:** User request — captured for team memory + +# Decision: CLI sessions use approve-all permission handler + +**Date:** 2025-07-14 +**Author:** Fenster (Core Dev) +**Issue:** #651 + +## Context + +The Copilot SDK requires an onPermissionRequest handler when creating sessions. This handler was defined in our adapter types (SquadSessionConfig) but was never wired in the CLI shell's 4 createSession() calls. External users hit a raw SDK error with no guidance. + +## Decision + +All CLI shell session creation calls now pass onPermissionRequest: approveAllPermissions, a handler that returns { kind: 'approved' } for every request. The CLI runs locally with user trust — there is no interactive permission prompt. + +SDK consumers (programmatic API users) still control their own handler. The SDK's createSession in dapter/client.ts now catches the raw permission error and wraps it with a clear message explaining how to fix it. + +## Impact + +- **CLI users:** Error is gone. All permissions auto-approved (matches existing CLI trust model). +- **SDK consumers:** Better error message if they forget to pass onPermissionRequest. +- **Types:** SquadPermissionHandler, SquadPermissionRequest, SquadPermissionRequestResult are now exported from @bradygaster/squad-sdk/client for reuse. +### 2025-07-24: Multi-Squad Global Config Layout +**By:** Fenster (Core Dev) +**Issue:** #652 +**PR:** #691 + +## What + +Squad now supports a global squads.json registry at the platform config root (%APPDATA%/squad/ on Windows, ~/.config/squad/ on Linux/macOS). Each named squad is registered with a name, path, and creation timestamp. Resolution follows a 5-step chain: explicit name → SQUAD_NAME env var → active in squads.json → "default" → legacy ~/.squad fallback. + +## Why + +Users need to manage multiple squads (personal, work, experiments) without conflicts. A global registry decouples squad identity from the current working directory and enables future CLI commands (squad list, squad switch, etc.) in Phase 2. + +## Migration Strategy + +Migration is **non-destructive and registration-only**. When esolveSquadPath() detects a legacy ~/.squad layout without an existing squads.json, it registers that path as the "default" squad. No files are moved, copied, or renamed. This eliminates data loss risk on first upgrade. + +## Impact + +- All future squad path resolution should go through esolveSquadPath() from multi-squad.ts +- Existing esolveSquad() and esolveSquadPaths() in esolution.ts remain unchanged (project-local .squad/ walk-up) +- Phase 2 CLI commands will consume these SDK functions directly diff --git a/.squad/decisions.md b/.squad/decisions.md index 3f4bd4bd9..566929433 100644 --- a/.squad/decisions.md +++ b/.squad/decisions.md @@ -2,6 +2,7 @@ > Team decisions that all agents must respect. Managed by Scribe. + --- ## Foundational Directives (carried from beta, updated for Mission Control) @@ -51,10 +52,606 @@ **What:** Squad becomes its own interactive CLI shell. `squad` with no args enters a REPL. **Why:** Squad needs to own the full interactive experience. -### No temp/memory files in repo root -**By:** Brady -**What:** No plan files, memory files, or tracking artifacts in the repository root. -**Why:** Keep the repo clean. +### 2026-02-21: User directive — no temp/memory files in repo root +**By:** Brady (via Copilot) +**What:** NEVER write temp files, issue files, or memory files to the repo root. All squad state/scratch files belong in .squad/ and ONLY .squad/. Root tree of a user's repo is sacred. +**Why:** User request — hard rule. Captured for all agents. + +### 2026-02-21: npm workspace protocol for monorepo +**By:** Edie (TypeScript Engineer) +**What:** Use npm-native workspace resolution (version-string references) instead of `workspace:*` protocol for cross-package dependencies. +**Why:** The `workspace:*` protocol is pnpm/Yarn-specific. npm workspaces resolve workspace packages automatically. +**Impact:** All inter-package dependencies in `packages/*/package.json` should use the actual version string, not `workspace:*`. + +### 2026-02-21: Distribution is npm-only (GitHub-native removed) +**By:** Rabin (Distribution) + Fenster (Core Dev) +**What:** Squad packages (`@bradygaster/squad-sdk` and `@bradygaster/squad-cli`) are distributed exclusively via npmjs.com. The GitHub-native `npx github:bradygaster/squad` path has been removed. +**Why:** npm is the standard distribution channel. One distribution path reduces confusion and maintenance burden. Root `cli.js` prints deprecation warning if anyone still hits the old path. + +### 2026-02-21: Coordinator prompt structure — three routing modes +**By:** Verbal (Prompt Engineer) +**What:** Coordinator uses structured response format: `DIRECT:` (answer inline), `ROUTE:` + `TASK:` + `CONTEXT:` (single agent), `MULTI:` (fan-out). Unrecognized formats fall back to `DIRECT`. +**Why:** Keyword prefixes are cheap to parse and reliable. Fallback-to-direct prevents silent failures. +### `.squad/` Directory Scope — Owner Directive +**By:** Brady (project owner, PR #326 review) +**Date:** 2026-03-10 + +**Directive:** The `.squad/` directory is **reserved for team state only** — roster, routing, decisions, agent histories, casting, and orchestration logs. Non-team data (adoption tracking, community metrics, reports) must NOT live in `.squad/`. Use `.github/` for GitHub platform integration or `docs/` for documentation artifacts. + +**Source:** [PR #326 comment](https://github.com/bradygaster/squad/pull/326#issuecomment-4029193833) + + +--- + +### No Individual Repo Listing Without Consent — Owner Directive +**By:** Brady (project owner, PR #326 review) +**Date:** 2026-03-10 + +**Directive:** Growth metrics must report **aggregate numbers only** (e.g., "78+ repositories found via GitHub code search") — never name or link to individual community repos without explicit opt-in consent. The monitoring script and GitHub Action concepts are approved, but any public showcase or tracking list that identifies specific repos is blocked until a community consent plan exists. + +**Source:** [PR #326 comment](https://github.com/bradygaster/squad/pull/326#issuecomment-4029222967) + + +--- + +### Adoption Tracking — Opt-In Architecture +**By:** Flight (implementing Brady's directives above) +**Date:** 2026-03-09 + +### 2026-02-21: CLI entry point split — src/index.ts is a pure barrel +**By:** Edie (TypeScript Engineer) +**What:** `src/index.ts` is a pure re-export barrel with ZERO side effects. `src/cli-entry.ts` contains `main()` and all CLI routing. +**Why:** Library consumers importing `@bradygaster/squad` were triggering CLI argument parsing and `process.exit()` on import. + +### 2026-02-21: Process.exit() refactor — library-safe CLI functions +**By:** Kujan (SDK Expert) +**What:** `fatal()` throws `SquadError` instead of `process.exit(1)`. Only `cli-entry.ts` may call `process.exit()`. +**Pattern:** Library functions throw `SquadError`. CLI entry catches and exits. Library consumers catch for structured error handling. + +### 2026-02-21: User directive — docs as you go +**By:** bradygaster (via Copilot) +**What:** Doc and blog as you go during SquadUI integration work. Doesn't have to be perfect — keep docs updated incrementally. + +### 2026-02-22: Runtime EventBus as canonical bus +**By:** Fortier +**What:** `runtime/event-bus.ts` (colon-notation: `session:created`, `subscribe()` API) is the canonical EventBus for all orchestration classes. The `client/event-bus.ts` (dot-notation) remains for backward-compat but should not be used in new code. +**Why:** Runtime EventBus has proper error isolation — one handler failure doesn't crash others. + +### 2026-02-22: Subpath exports in @bradygaster/squad-sdk +**By:** Edie (TypeScript Engineer) +**What:** SDK declares subpath exports (`.`, `./parsers`, `./types`, and module paths). Each uses types-first condition ordering. +**Constraints:** Every subpath needs a source barrel. `"types"` before `"import"`. ESM-only: no `"require"` condition. + +### 2026-02-22: User directive — Aspire testing requirements +**By:** Brady (via Copilot) +**What:** Integration tests must launch the Aspire dashboard and validate OTel telemetry shows up. Use Playwright. Use latest Aspire bits. Reference aspire.dev (NOT learn.microsoft.com). It's "Aspire" not ".NET Aspire". + +### 2026-02-23: User directive — code fences +**By:** Brady (via Copilot) +**What:** Never use / or \ as code fences in GitHub issues, PRs, or comments. Only use backticks to format code. + +### 2026-02-23: User Directive — Docs Overhaul & Publication Pause +**By:** Brady (via Copilot) +**What:** Pause docs publication until Brady explicitly gives go-ahead. Tone: lighthearted, welcoming, fun (NOT stuffy). First doc should be "first experience" with squad CLI. All docs: brief, prompt-first, action-oriented, fun. Human tone throughout. + +### 2026-02-23: Use sendAndWait for streaming dispatch +**By:** Kovash (REPL Expert) +**What:** `dispatchToAgent()` and `dispatchToCoordinator()` use `sendAndWait()` instead of `sendMessage()`. Fallback listens for `turn_end`/`idle` if unavailable. +**Why:** `sendMessage()` is fire-and-forget — resolves before streaming deltas arrive. +**Impact:** Never parse `accumulated` after a bare `sendMessage()`. Always use `awaitStreamedResponse`. + +### 2026-02-23: extractDelta field priority — deltaContent first +**By:** Kovash (REPL Expert) +**What:** `extractDelta` priority: `deltaContent` > `delta` > `content`. Matches SDK actual format. +**Impact:** Use `deltaContent` as the canonical field name for streamed text chunks. + +### 2026-02-24: Per-command --help/-h: intercept-before-dispatch pattern +**By:** Fenster (Core Dev) +**What:** All CLI subcommands support `--help` and `-h`. Help intercepted before command routing prevents destructive commands from executing. +**Convention:** New CLI commands MUST have a `getCommandHelp()` entry with usage, description, options, and 2+ examples. + +### 2026-02-25: REPL cancellation and configurable timeout +**By:** Kovash (REPL Expert) +**What:** Ctrl+C immediately resets `processing` state. Timeout: `SQUAD_REPL_TIMEOUT` (seconds) > `SQUAD_SESSION_TIMEOUT_MS` (ms) > 600000ms default. CLI `--timeout` flag sets env var. + +### 2026-02-24: Shell Observability Metrics +**By:** Saul (Aspire & Observability) +**What:** Four metrics under `squad.shell.*` namespace, gated behind `SQUAD_TELEMETRY=1`. +**Convention:** Shell metrics require explicit consent via `SQUAD_TELEMETRY=1`, separate from OTLP endpoint activation. + +### 2026-02-23: Telemetry in both CLI and agent modes +**By:** Brady (via Copilot) +**What:** Squad should pump telemetry during BOTH modes: (1) standalone Squad CLI, and (2) running as an agent inside GitHub Copilot CLI. + +### 2026-02-27: ASCII-only separators and NO_COLOR +**By:** Cheritto (TUI Engineer) +**What:** All separators use ASCII hyphens. Text-over-emoji principle: text status is primary, emoji is supplementary. +**Convention:** Use ASCII hyphens for separators. Keep emoji out of status/system messages. + +### 2026-02-24: Version format — bare semver canonical +**By:** Fenster +**What:** Bare semver (e.g., `0.8.5.1`) for version commands. Display contexts use `squad v{VERSION}`. + +### 2026-02-25: Help text — progressive disclosure +**By:** Fenster +**What:** Default `/help` shows 4 essential lines. `/help full` shows complete reference. + +### 2026-02-24: Unified status vocabulary +**By:** Marquez (CLI UX Designer) +**What:** Use `[WORK]` / `[STREAM]` / `[ERR]` / `[IDLE]` across ALL status surfaces. +**Why:** Most granular, NO_COLOR compatible, text-over-emoji, consistent across contexts. + +### 2026-02-24: Pick one tagline +**By:** Marquez (CLI UX Designer) +**What:** Use "Team of AI agents at your fingertips" everywhere. + +### 2026-02-24: User directive — experimental messaging +**By:** Brady (via Copilot) +**What:** CLI docs should note the project is experimental and ask users to file issues. + +### 2026-02-28: User directive — DO NOT merge PR #547 +**By:** Brady (via Copilot) +**What:** DO NOT merge PR #547 (Squad Remote Control). Do not touch #547 at all. +**Why:** User request — captured for team memory + +### 2026-02-28: CLI Critical Gap Issues Filed +**By:** Keaton (Lead) +**What:** 4 critical CLI gaps filed as GitHub issues #554–#557 for explicit team tracking: +- #554: `--preview` flag undocumented and untested +- #556: `--timeout` flag undocumented and untested +- #557: `upgrade --self` is dead code +- #555: `run` subcommand is a stub (non-functional) + +**Why:** Orchestration logs captured gaps but they lacked actionable GitHub tracking and ownership. Filed issues now have explicit assignment to Fenster, clear acceptance criteria, and visibility in Wave E planning. + +### 2026-02-28: Test Gap Issues Filed (10 items) +**By:** Hockney (Tester) +**What:** 10 moderate CLI/test gaps filed as issues #558–#567: +- #558: Exit code consistency untested +- #559: Timeout edge cases untested +- #560: Missing per-command help +- #561: Shell-specific flag behavior untested +- #562: Env var fallback paths untested +- #563: REPL mode transitions untested +- #564: Config file precedence untested +- #565: Agent spawn flags undocumented +- #566: Untested flag aliases +- #567: Flag parsing error handling untested + +**Why:** Each gap identified in coverage analysis but lacked explicit GitHub tracking for prioritization and team visibility. + +### 2026-02-28: Documentation Audit Results (10 issues) +**By:** McManus (DevRel) +**What:** Docs audit filed 10 GitHub issues (#568–#575, #577–#578) spanning: +- Feature documentation lag (#568 `squad run`, #570 consult mode, #572 Ralph smart triage) +- Terminology inconsistency (#569 triage/watch/loop naming) +- Brand compliance (#571 experimental banner on 40+ docs) +- Clarity/UX gaps (#573 response modes, #575 dual-root, #577 VS Code, #578 session examples) +- Reference issue (#574 README command count) + +**Why:** Features shipped faster than documentation. PR #552, #553 merged without doc updates. No automation to enforce experimental banner. Users discover advanced features accidentally. + +**Root cause:** Feature-docs lag, decision-doc drift, no brand enforcement in CI. + +### 2026-02-28: Dogfood UX Issues Filed (4 items) +**By:** Waingro (Dogfooder) +**What:** Dogfood testing against 8 realistic scenarios surfaced 4 UX issues (filed as #576, #579–#581): +- #576 (P1): Shell launch fails in non-TTY piped mode (Blocks CI) +- #580 (P1): Help text overwhelms new users (44 lines, no tiering) +- #579 (P2): Status shows parent `.squad/` as local (confusing in multi-project workspaces) +- #581 (P2): Error messages show debug output always (noisy production logs) + +**Why:** CLI is solid for happy path but first-time user experience and CI/CD integration have friction points. All 4 block either new user onboarding or automation workflows. + +**Priority:** #576 > #580 > #581 > #579. All should be fixed before next public release. + +### 2026-02-28: decisions.md Aggressive Cleanup +**By:** Keaton (Lead) +**What:** Trimmed `decisions.md` from 226KB (223 entries) to 10.3KB (35 entries) — 95% reduction. +- Kept: Core architectural decisions, active process rules, active user directives, current UX conventions, runtime patterns +- Archived: Implementation details, one-time setup, PR reviews, audit reports, wave planning, superseded decisions, duplicates +- Created: `decisions-archive.md` with full original content preserved + +**Why:** Context window bloat during release push. Every agent loads 95% less decisions context. Full history preserved append-only. + +**Impact:** File size reduced, agent context efficiency improved, all decisions preserved in archive. + +### 2026-02-28: Backlog Gap Issues Filed (8 items) +**By:** Keaton (Lead) +**Approval:** Brady (via directive in issue request) +**What:** Filed 8 missing backlog items from `.squad/identity/now.md` as GitHub issues. These items were identified as "should-fix" polish or "post-M1" improvements but lacked explicit GitHub tracking until now. + +**Why:** Brady requested: "Cross-reference the known backlog against filed issues and file anything missing." The team had filed 28 issues this session (#554–#581), but 8 known items from `now.md` remained unfiled. Without GitHub issues, these lack ownership assignment, visibility for Wave E planning, trackability in automated workflows, and routing to squad members. + +**Issues Filed:** +- #583 (squad:rabin): Add `homepage` and `bugs` fields to package.json +- #584 (squad:mcmanus): Document alpha→v1.0 breaking change policy in README +- #585 (squad:edie): Add `noUncheckedIndexedAccess` to tsconfig +- #586 (squad:edie): Tighten ~26 `any` types in SDK +- #587 (squad:mcmanus): Add architecture overview doc +- #588 (squad:kujan): Implement SQUAD_DEBUG env var test +- #589 (squad:kujan): One real Copilot SDK integration test +- #590 (squad:baer): `npm audit fix` for dev-dependency ReDoS warnings +- #591 (squad:hockney, type:bug): Aspire dashboard test fails — docker pull in test suite +- #592 (squad:rabin): Replace workspace:* protocol with version string + +**Impact:** Full backlog now visible with explicit issues. No unmapped items. Each issue routed to the squad member domain expert. Issues are independent; can be executed in any order. + +### 2026-02-28: Codebase Scan — Unfiled Issues Audit +**By:** Fenster (Core Dev) +**Requested by:** Brady +**Date:** 2026-02-28T22:05:00Z +**Status:** Complete — 2 new issues filed + +**What:** Systematic scan of the codebase to identify known issues that haven't been filed as GitHub issues. Checked: +1. TODO/FIXME/HACK/XXX comments in code +2. TypeScript strict mode violations (@ts-ignore/@ts-expect-error) +3. Skipped/todo tests (.skip() or .todo()) +4. Errant console.log statements +5. Missing package.json metadata fields + +**Findings:** +- Type safety violations: ✅ CLEAN — Zero @ts-ignore/@ts-expect-error found. Strict mode compliance excellent. +- Workspace protocol: ❌ VIOLATION — 1 issue filed (#592): `workspace:*` in squad-cli violates npm workspace convention +- Skipped tests: ❌ GAP — 1 issue filed (#588): SQUAD_DEBUG test is .todo() placeholder +- Console.log: ✅ INTENTIONAL — All are user-facing output (status, errors) +- TODO comments: ✅ TEMPLATES — TODOs in generated workflow templates, not code +- Package.json: ✅ TRACKED — Missing homepage/bugs already filed as #583 + +**Code Quality Assessment:** +- Type Safety (Excellent): Zero violations of strict mode or type suppression. Team decision being followed faithfully. +- TODO/FIXME Comments (Clean): All TODOs in upgrade.ts and workflows.ts are template strings for generated GitHub Actions YAML, intentionally scoped. +- Console Output (Intentional): All are user-facing (dashboard startup, OTLP endpoint, issue labeling, shell loading) — no debug debris. +- Dead Code (None Found): No unreachable code, orphaned functions, or unused exports detected. + +**Recommendations:** +1. Immediate: Fix workspace protocol violation (#592) — violates established team convention +2. Soon: Implement SQUAD_DEBUG test (#588) — fills observable test gap +3. Going forward: Maintain type discipline; review package.json metadata during SDK/CLI version bumps + +**Conclusion:** Codebase in good health. Type safety discipline strong. No hidden technical debt. Conventions mostly followed (one npm workspace exception). Test coverage has minor gaps in observability. + +### 2026-02-28: Auto-link detection for preview builds +**By:** Fenster (Core Dev) +**Date:** 2026-02-28 +**What:** When running from source (`VERSION` contains `-preview`), the CLI checks if `@bradygaster/squad-cli` is globally npm-linked. If not, it prompts the developer to link it. Declining creates `~/.squad/.no-auto-link` to suppress future prompts. +**Why:** Dev convenience — saves contributors from forgetting `npm link` after cloning. Non-interactive commands (help, version, export, import, doctor, scrub-emails) skip the check. Everything is wrapped in try/catch so failures are silent. +**Impact:** Only affects `-preview` builds in interactive TTY sessions. No effect on published releases or CI. + +### 2026-03-01T00:34Z: User directive — Full scrollback support in REPL shell +**By:** Brady (via Copilot) +**What:** The REPL shell must support full scrollback — users should be able to scroll up and down to see all text (paste, run output, rendered content, logs) over time, like GitHub Copilot CLI does. The current Ink-based rendering loses/hides content and that's unacceptable. +**Why:** User request — captured for team memory. This is a P0 UX requirement for the shell. +**Status:** P0 blocking issue. Requires rendering architecture review (Cheritto, Kovash, Marquez). + +### 2026-03-01T04:47Z: User directive — Auto-incrementing build numbers +**By:** Brady (via Copilot) +**What:** Add auto-incrementing build numbers to versions. Format: `0.8.6.{N}-preview` where N increments each local build. Tracks build-to-release cadence. +**Why:** User request — captured for team memory. + +### 2026-03-01: Nap engine — dual sync/async export pattern +**By:** Fenster (Core Dev) +**What:** The nap engine (`cli/core/nap.ts`) exports both `runNap` (async, for CLI entry) and `runNapSync` (sync, for REPL). All internal operations use sync fs calls. The async wrapper exists for CLI convention consistency. +**Why:** REPL `executeCommand` is synchronous and cannot await. ESM forbids `require()`. Exporting a sync variant keeps the REPL integration clean without changing the shell architecture. +**Impact:** Future commands that need both CLI and REPL support should follow this pattern if they only do sync fs work. + +### 2026-03-01: First-run gating test strategy +**By:** Hockney (Tester) +**Date:** 2026-03-01 +**Issue:** #607 +**What:** Created `test/first-run-gating.test.ts` with 25 tests covering 6 categories of Init Mode gating. Tests use logic-level extraction from App.tsx conditionals, filesystem marker lifecycle via `loadWelcomeData`, and source-code structural assertions for render ordering. No full App component rendering — SDK dependencies make that impractical for unit tests. +**Why:** 3059 tests existed with zero enforcement of first-run gating behavior. The `.first-run` marker, banner uniqueness, assembled-message gating, warning suppression, session-scoped keys, and terminal clear ordering were all untested paths that could regress silently. +**Impact:** All squad members: if you modify `loadWelcomeData`, the `firstRunElement` conditional in App.tsx, or the terminal clear sequence in `runShell`, these tests will catch regressions. The warning suppression tests replicate the `cli-entry.ts` pattern — if that pattern changes, update both locations. + +### Verbal's Analysis: "nap" Skill — Context Window Optimization +**By:** Verbal (Prompt Engineer) +**Requested by:** Brady +**Date:** 2026-03-01 +**Scope:** Approved. Build it. Current context budget analysis: +- Agent spawn loads charter (~500t) + history + decisions.md (4,852t) + team.md (972t) +- Hockney: 25,940t history (worst offender) +- Fenster: 22,574t (history + CLI inventory) +- Coherence cliff: 40-50K tokens on non-task context + +**Key Recommendations:** +1. **Decision distillation:** Keep decisions.md as single source of truth (don't embed in charters — creates staleness/duplication) +2. **History compression — 12KB rule insufficient:** Six agents blow past threshold. Target **4KB ceiling per history** (~1,000t) with assertions not stories. +3. **Nap should optimize:** Deduplication (strip decisions.md content echoed in histories), staleness (flag closed PRs, merged work), charter bloat (stay <600t), skill pruning (archive high-confidence, no-recent-invocation skills), demand-loading for extra files (CLI inventory, UX catalog, fragility catalog). +4. **Enforcement:** Nap runs periodically or on-demand, enforces hard ceilings without silent quality degradation. + +### ShellApi.clearMessages() for terminal state reset +**By:** Kovash (REPL Expert) +**Date:** 2026-03-01 +**What:** `ShellApi` now exposes `clearMessages()` which resets both `messages` and `archivedMessages` React state. Used in session restore and `/clear` command. +**Why:** Without clearing archived messages, old content bleeds through when restoring sessions or clearing the shell. The `/clear` command previously only reset `messages`, leaving `archivedMessages` in the Static render list. +**Impact:** Any code calling `shellApi` to reset shell state should use `clearMessages()` rather than manually manipulating message arrays. + +### 2026-03-01: Prompt placeholder hints must not duplicate header banner +**By:** Kovash (REPL Expert) +**Date:** 2026-03-01 +**Issue:** #606 +**What:** The InputPrompt placeholder text must provide *complementary* guidance, never repeat what the header banner already shows. The header banner is the single source of truth for @agent routing and /help discovery. Placeholder hints should surface lesser-known features (tab completion, history navigation, utility commands). +**Why:** Two elements showing "Type @agent or /help" simultaneously creates visual noise and a confusing UX. One consistent prompt style throughout the session. +**Impact:** `getHintText()` in InputPrompt.tsx now has two tiers instead of three. Any future prompt hints should check the header banner first to avoid duplication. + +### 2026-03-02: Paste detection via debounce in InputPrompt +**By:** Kovash (REPL Expert) +**Date:** 2026-03-02 +**What:** InputPrompt uses a 10ms debounce on `key.return` to distinguish paste from intentional Enter. If more input arrives within 10ms → paste detected → newline preserved. If timer fires without input → real Enter → submit. A `valueRef` (React ref) mirrors mutations synchronously since closure-captured `value` is stale during rapid `useInput` calls. In disabled state, `key.return` appends `\n` to buffer instead of being ignored. +**Why:** Multi-line paste was garbled because `useInput` fires per-character and `key.return` triggered immediate submission. +**Impact:** 10ms delay on single-line submit is imperceptible. UX: multi-line paste preserved. Testing: Hockney should verify paste scenarios use `jest.useFakeTimers()` or equivalent. Future: if Ink adds native bracketed-paste support, debounce can be replaced. + +### 2026-03-01: First-run init messaging — single source of truth +**By:** Kovash (REPL & Interactive Shell) +**Date:** 2026-03-01 +**Issue:** #625 +**What:** When no roster exists, only the header banner tells the user about `squad init` / `/init`. The `firstRunElement` block returns `null` for the empty-roster case instead of showing a duplicate message. `firstRunElement` is reserved for the "Your squad is assembled" onboarding when a roster already exists. +**Why:** Two competing UI elements both said "run squad init" — visual noise that confuses the information hierarchy. Banner is persistent and visible; it owns the no-roster guidance. `firstRunElement` owns the roster-present first-run experience. +**Impact:** App.tsx only. No API or prop changes. Banner text reworded to prioritize `/init` (in-shell path) over exit-and-run. + +### 2026-03-01: NODE_NO_WARNINGS for subprocess warning suppression +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-01 +**Issue:** #624 +**What:** `process.env.NODE_NO_WARNINGS = '1'` is set as the first executable line in `cli-entry.ts` (line 2, after shebang). This supplements the existing `process.emitWarning` override. +**Why:** The Copilot SDK spawns child processes that inherit environment variables but NOT in-process monkey-patches like `process.emitWarning` overrides. `NODE_NO_WARNINGS=1` is the Node.js-native mechanism for suppressing warnings across an entire process tree. Without it, `ExperimentalWarning` messages (e.g., SQLite) leak into the terminal via the SDK's subprocess stderr forwarding. +**Pattern:** When suppressing Node.js warnings, use BOTH: (1) `process.env.NODE_NO_WARNINGS = '1'` — covers child processes (env var inheritance); (2) `process.emitWarning` override — covers main process (belt-and-suspenders). +**Impact:** Eliminates `ExperimentalWarning` noise in terminal for all Squad CLI users, including when the Copilot SDK spawns subprocesses. + +### 2026-03-01: No content suppression based on terminal width +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-01 +**What:** Terminal width tiers (compact ≤60, standard, wide ≥100) may adjust *layout* (e.g., wrapping, column arrangement) but must NOT suppress or truncate *content*. Every piece of information shown at 120 columns must also be shown at 40 columns. +**Why:** Users can scroll. Hiding roster names, spacing, help text, or routing hints on narrow terminals removes information the user needs. Layout adapts to width; content does not. +**Convention:** `compact` variable may be used for layout decisions (flex direction, column vs. row) but must NOT gate visibility of text, spacing, or UI sections. `wide` may add supplementary content but narrow must not remove it. + +### 2026-03-01: Multi-line user message rendering pattern +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-01 +**What:** Multi-line user messages in the Static scrollback use `split('\n')` with a column layout: first line gets the `❯` prefix, subsequent lines get `paddingLeft={2}` for alignment. +**Why:** Ink's horizontal `` layout doesn't handle embedded `\n` in `` children predictably when siblings exist. Explicit line splitting with column flex direction gives deterministic multi-line rendering. +**Impact:** Any future changes to user message prefix width must update the `paddingLeft={2}` on continuation lines to match. + +### 2026-03-01: Elapsed time display — inline after message content +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-01 +**Issue:** #605 +**What:** Elapsed time annotations on completed agent messages are always rendered inline after the message content as `(X.Xs)` in dimColor. This applies to the Static scrollback block in App.tsx, which is the canonical render path for all completed messages. +**Why:** After the Static scrollback refactor, MessageStream receives `messages=[]` and only renders live streaming content. The duration code in MessageStream was dead. Moving duration display into the Static block ensures it always appears consistently. +**Convention:** `formatDuration()` from MessageStream.tsx is the shared formatter. Format is `Xms` for <1s, `X.Xs` for ≥1s. Always inline, always dimColor, always after content text. + +### 2026-03-01: Banner usage line separator convention +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-01 +**What:** Banner hint/usage lines use middle dot `·` as inline separator. Init messages use single CTA (no dual-path instructions). +**Why:** Consistent visual rhythm. Middle dot is lighter than em-dash or hyphen for inline command lists. Single CTA reduces cognitive load for new users. +**Impact:** App.tsx headerElement. Future banner copy should follow same separator and single-CTA pattern. + +### 2026-03-02: REPL casting engine design +**By:** Fenster (Core Dev) +**Date:** 2026-03-02 +**Status:** Implemented +**Issue:** #638 +**What:** Created `packages/squad-cli/src/cli/core/cast.ts` as a self-contained casting engine with four exports: +1. `parseCastResponse()` — parses the `INIT_TEAM:` format from coordinator output +2. `createTeam()` — scaffolds all `.squad/agents/` directories, writes charters, updates team.md and routing.md, writes casting state JSON +3. `roleToEmoji()` — maps role strings to emoji, reusable across the CLI +4. `formatCastSummary()` — renders a padded roster summary for terminal display + +Scribe and Ralph are always injected if missing from the proposal. Casting state is written to `.squad/casting/` (registry.json, history.json, policy.json). +**Why:** Enables coordinator to propose and create teams from within the REPL session after `squad init`. +**Implications:** + +### 2026-03-02: Beta → Origin Migration: Version Path (v0.5.4 → v0.8.17) + +**By:** Kobayashi (Git & Release) +**Date:** 2026-03-02 +**Context:** Analyzed migration from beta repo (`bradygaster/squad`, v0.5.4) to origin repo (`bradygaster/squad-pr`, v0.8.18-preview). Version gap spans 0.6.x, 0.7.x, 0.8.0–0.8.16 (internal origin development only). + +**What:** Beta will jump directly from v0.5.4 to v0.8.17 (skip all intermediate versions). Rationale: +1. **Semantic versioning allows gaps** — version numbers are labels, not counters +2. **Users care about features, not numbers** — comprehensive changelog is more valuable than version sequence +3. **Simplicity reduces risk** — single migration release is easier to execute and communicate +4. **Precedent exists** — major refactors/rewrites commonly skip versions (Angular 2→4, etc) + +**Risks & Mitigations:** +- Risk: Version jump confuses users. Mitigation: Clear release notes explaining the gap + comprehensive changelog +- Risk: Intermediate versions were never public (no user expectations). Mitigation: This is actually a benefit — no backfill needed + +**Impact:** After merge, beta repo version jumps from v0.5.4 to v0.8.17. All intermediate work is included in the 0.8.17 release. Next release after v0.8.17 may be v0.8.18 or v0.9.0 (team decision post-merge). + +**Why:** Avoids maintenance burden of backfilling 12+ fake versions. Users get complete feature set in one migration release. + +### 2026-03-02: Beta → Origin Migration: Package Naming + +**By:** Kobayashi (Git & Release) +**Date:** 2026-03-02 + +**What:** Deprecate `@bradygaster/create-squad` (beta's package name). All future releases use: +- `@bradygaster/squad-cli` (user-facing CLI) +- `@bradygaster/squad-sdk` (programmatic SDK for integrations) + +**Why:** Origin's naming is more accurate and supports independent versioning if needed. Monorepo structure benefits from clear package separation. + +**Action:** When v0.8.17 is ready to publish, release a final version of `@bradygaster/create-squad` with deprecation notice: "This package has been renamed to @bradygaster/squad-cli. Install with: npm install -g @bradygaster/squad-cli" + +**Impact:** Package ecosystem clarity. No breaking change for users upgrading (CLI handles detection and warnings). + +### 2026-03-02: Beta → Origin Migration: Retroactive v0.8.17 Tag + +**By:** Kobayashi (Git & Release) +**Date:** 2026-03-02 + +**What:** Retroactively tag commit `5b57476` ("chore(release): prep v0.8.16 for npm publish") as v0.8.17. This commit and v0.8.16 have identical code. + +**Rationale:** +- Commit `6fdf9d5` jumped directly to v0.8.17-preview (no v0.8.17 release tag exists) +- Commit `87e4f1c` bumps to v0.8.18-preview "after 0.8.17 release" (implying v0.8.17 was released) +- Retroactive tagging is less disruptive than creating a new prep commit and rebasing + +**Action:** When banana gate clears, tag origin commit `5b57476` as v0.8.17. + +**Why:** Completes the missing link in origin's tag history. Indicates to users which commit was released as v0.8.17. + +### 2026-03-02: npx Distribution Migration: Error-Only Shim Strategy + +**By:** Rabin (Distribution) +**Date:** 2026-03-02 +**Context:** Beta repo currently uses GitHub-native distribution (`npx github:bradygaster/squad`). Origin uses npm distribution (`npm install -g @bradygaster/squad-cli`). After merge, old path will break. + +**Problem:** After migration, `npx github:bradygaster/squad` fails (root `package.json` has no `bin` entry). Users hitting the old path get cryptic npm error. + +**Solution — Option 5 (Error-only shim):** +1. Add root `bin` entry pointing to `cli.js` +2. `cli.js` detects GitHub-native invocation and prints **bold, clear error** with migration instructions +3. Exit with code 1 (fail fast, no hidden redirection) + +**Implementation:** +```json +{ + "bin": { + "squad": "./cli.js" + } +} +``` + +Update `cli.js` to print error message with new install instructions: +``` +npm install -g @bradygaster/squad-cli +``` + +**Pros:** +- ✅ Clear, actionable error message (not cryptic npm error) +- ✅ Aligns with npm-only team decision (no perpetuation of GitHub-native path) +- ✅ Low maintenance burden (simple error script, no complex shim) +- ✅ Can be removed in v1.0.0 when beta users have migrated + +**Cons:** +- Immediate breakage (no grace period) — but users get clear guidance + +**Why This Over Others:** +- Option 1 (keep working) contradicts npm-only decision +- Option 2 (exit early) same as this, but explicit error format needed +- Option 3 (time-limited) best UX but maintenance burden +- Option 4 (just break) user-hostile without error message +- **Option 5 balances user experience + team decision** + +**Related Decision:** See 2026-02-21 decision "Distribution is npm-only (GitHub-native removed)" + +**User Impact:** +- Users running `npx github:bradygaster/squad` see bold error with `npm install -g @bradygaster/squad-cli` instruction +- Existing projects running `squad upgrade` work seamlessly (upgrade logic built-in) +- No data loss or silent breakage + +**Upgrade Path (existing beta users):** +```bash +npm install -g @bradygaster/squad-cli +cd /path/to/project +squad upgrade +squad upgrade --migrate-directory # Optional: .ai-team/ → .squad/ +``` + +**Why:** Rabin's principle: "If users have to think about installation, install is broken." A clear error message respects users better than a cryptic npm error. + +### 2026-02-28: Init flow reliability — proposal-first before code + +**By:** Keaton (Lead) +**Date:** 2026-02-28 +**What:** Init/onboarding fixes require a proposal review before implementation. Proposal at `docs/proposals/reliable-init-flow.md`. Two confirmed bugs (race condition in auto-cast, Ctrl+C doesn't abort init session) plus UX gaps (empty-roster messaging, `/init` no-op). P0 bugs are surgical — don't expand scope. +**Why:** Four PRs (#637–#640) patched init iteratively without a unified design. Before writing more patches, the team needs to agree on the golden path. Proposal-first (per team decision 2026-02-21). +**Impact:** Blocks init-related code changes until Brady reviews the proposal. +- Kovash (REPL): Can call `parseCastResponse` + `createTeam` to wire up casting flow in shell dispatcher +- Verbal (Prompts): INIT_TEAM format is now the contract — coordinator prompt should emit this +- Hockney (Tests): cast.ts needs unit tests for parser edge cases, emoji mapping, file creation + +### 2026-03-02: REPL empty-roster gate — dual check pattern +**By:** Fenster (Core Dev) +**Date:** 2026-03-02 +**What:** REPL dispatch is now gated on *populated* roster, not just team.md existence. `hasRosterEntries()` in `coordinator.ts` checks for table data rows in the `## Members` section. Two layers: `handleDispatch` blocks with user guidance, `buildCoordinatorPrompt` injects refusal prompt. +**Why:** After `squad init`, team.md exists but is empty. Coordinator received a "route to agents" prompt with no agents listed, causing silent generic AI behavior. Users never got told to cast their team. +**Convention:** Post-init message references "Copilot session" (works in VS Code, github.com, and Copilot CLI). The `/init` slash command provides same guidance inside REPL. +**Impact:** All agents — if you modify the `## Members` table format in team.md templates, update `hasRosterEntries()` to match. + +### 2026-03-02: Connection promise dedup in SquadClient +**By:** Fenster (Core Dev) +**Date:** 2026-03-02 +**What:** `SquadClient.connect()` now uses a promise dedup pattern — concurrent callers share the same in-flight `connectPromise` instead of throwing "Connection already in progress". +**Why:** Eager warm-up and auto-cast both call `createSession()` → `connect()` at REPL startup, racing on the connection. The throw crashed auto-cast every time. +**Impact:** `packages/squad-sdk/src/adapter/client.ts` only. No API surface change. + +### 2026-03-01: CLI UI Polish PRD — Alpha Shipment Over Perfection +**By:** Keaton (Lead) +**Date:** 2026-03-01 +**Context:** Team image review identified 20+ UX issues ranging from P0 blockers to P3 future polish + +**What:** CLI UI polish follows pragmatic alpha shipment strategy: fix P0 blockers + P1 quick wins, defer grand redesign to post-alpha. 20 discrete issues created with clear priority tiers (P0/P1/P2/P3). + +**Why:** Brady confirmed "alpha-level shipment acceptable — no grand redesign today." Team converged on 3 P0 blockers (blank screens, static spinner, missing alpha banner) that would embarrass us vs. 15+ polish items that can iterate post-ship. + +**Trade-off:** Shipping with known layout quirks (input positioning, responsive tables) rather than blocking on 1-2 week TUI refactor. Users expect alpha rough edges IF we warn them upfront. + +**Priority Rationale:** +- **P0 (must fix):** User-facing broken states — blank screens, no feedback, looks crashed +- **P1 (quick wins):** Accessibility (contrast), usability (copy clarity), visual hierarchy — high ROI, low effort +- **P2 (next sprint):** Layout architecture, responsive design — important but alpha-acceptable if missing +- **P3 (future):** Fixed bottom input, alt screen buffer, creative spinner — delightful but not blockers + +**Architectural Implications:** +1. **Quick win discovered:** App.tsx overrides ThinkingIndicator's native rotation with static hints (~5 line fix) +2. **Debt acknowledged:** 3 separate separator implementations need consolidation (P2 work) +3. **Layout strategy:** Ink's layout model fights bottom-anchored input. Alt screen buffer is the real solution (P3 deferred). +4. **Issue granularity:** 20 discrete issues vs. 1 monolithic "fix UI" epic — enables parallel work by Cheritto (11 issues), Kovash (4), Redfoot (2), Fenster (1), Marquez (1 review) + +**Success Gate:** "Brady says it doesn't embarrass us" — qualitative gate appropriate for alpha software. Quantitative gates: zero blank screens >500ms, contrast ≥4.5:1, spinner rotates every 3s. + +**Impact:** +- **Team routing:** Clear ownership — Cheritto (TUI), Kovash (shell), Redfoot (design), Marquez (UX review) +- **Timeline transparency:** P0 (1-2 days) → P1 (2-3 days) → P2 (1 week) — alpha ship when P0+P1 done +- **Expectation management:** Out of Scope section explicitly lists grand redesign, advanced features, WCAG audit — prevents scope creep + +### 2026-03-01: Cast confirmation required for freeform REPL casts +**By:** Fenster (Core Dev) +**Date:** 2026-03-01 +**Context:** P2 from Keaton's reliable-init-flow proposal + +**What:** When a user types a freeform message in the REPL and the roster is empty, the cast proposal is shown and the user must confirm (y/yes) before team files are created. Auto-cast from .init-prompt and /init "prompt" skip confirmation since the user explicitly provided the prompt. + +**Why:** Prevents garbage casts from vague or accidental first messages (e.g., "hello", "what can you do?"). Matches the squad.agent.md Init Mode pattern where confirmation is required before creating team files. + +**Pattern:** pendingCastConfirmation state in shell/index.ts. handleDispatch intercepts y/n at the top before normal routing. inalizeCast() is the shared helper for both auto-confirmed and user-confirmed paths. + +### 2026-03-01: Expose setProcessing on ShellApi +**By:** Kovash (REPL Expert) +**Date:** 2026-03-01 +**Context:** Init auto-cast path bypassed App.tsx handleSubmit, so processing state was never set — spinner invisible during team casting. + +**What:** ShellApi now exposes setProcessing(processing: boolean) so that any code path in index.ts that triggers async work outside of handleSubmit can properly bracket it with processing state. This enables ThinkingIndicator and InputPrompt spinner without duplicating React state management. + +**Rule:** Any new async dispatch path in index.ts that bypasses handleSubmit **must** call shellApi.setProcessing(true) before the async work and shellApi.setProcessing(false) in a inally block covering all exit paths. + +**Files Changed:** +- packages/squad-cli/src/cli/shell/components/App.tsx — added setProcessing to ShellApi interface + wired in onReady +- packages/squad-cli/src/cli/shell/index.ts — added setProcessing calls in handleInitCast (entry, pendingCastConfirmation return, finally block) + +### 2026-03-01T20:13:16Z: User directives — UI polish and shipping priorities +**By:** Brady (via Copilot) +**Date:** 2026-03-01 +Ampersands (&) are prohibited in user-facing documentation headings and body text, per Microsoft Style Guide. + +**Rule:** Use "and" instead. + +**Why:** Microsoft Style Guide prioritizes clarity and professionalism. Ampersands feel informal and reduce accessibility. + +**Exceptions:** +- Brand names (AT&T, Barnes & Noble) +- UI element names matching exact product text +- Code samples and technical syntax +- Established product naming conventions + +**Scope:** Applies to docs pages, README files, blog posts, community-facing content. Internal files (.squad/** memory files, decision docs, agent history) have flexibility. + +**Reference:** https://learn.microsoft.com/en-us/style-guide/punctuation/ampersands + --- @@ -65,6 +662,151 @@ **What:** Agents must NEVER write secrets, API keys, tokens, or credentials into conversational history, commit messages, logs, or any persisted file. Acknowledge receipt without echoing values. **Why:** Secrets in logs or history are a security incident waiting to happen. + +--- + +## Squad Ecosystem Boundaries & Content Governance + +### Squad Docs vs Squad IRL Boundary (consolidated) +**By:** PAO (via Copilot), Flight +**Date:** 2026-03-10 +**Status:** Active pattern for all documentation PRs + +**Litmus test:** If Squad doesn't ship the code or configuration, the documentation belongs in Squad IRL, not the Squad framework docs. + +**Categories:** + +1. **Squad docs** — Features Squad ships (routing, charters, reviewer protocol, config, behavior) +2. **Squad IRL** — Infrastructure around Squad (webhooks, deployment patterns, logging, external tools, operational patterns) +3. **Gray area:** Platform features (GitHub Issue Templates) → Squad docs if framed as "how to configure X for Squad" + +**Examples applied (PR #331):** + +| Document | Decision | Reason | +|----------|----------|--------| +| ralph-operations.md | DELETE → IRL | Infrastructure (deployment, logging) around Squad, not Squad itself | +| proactive-communication.md | DELETE → IRL | External tools (Teams, WorkIQ) configured by community, not built into Squad | +| issue-templates.md | KEEP, reframe | GitHub platform feature; clarify scope: "a GitHub feature configured for Squad" | +| reviewer-protocol.md (Trust Levels) | KEEP | Documents user choice spectrum within Squad's existing review system | + +**Enforcement:** Code review + reframe pattern ("GitHub provides X. Here's how to configure it for Squad's needs."). Mark suspicious deletions for restore (append-only governance). + +**Future use:** Apply this pattern to all documentation PRs to maintain clean boundaries. + + +--- + +### Content Triage Skill — External Content Integration +**By:** Flight +**Date:** 2026-03-10 +**Status:** Skill created at `.squad/skills/content-triage/SKILL.md` + +**Pattern:** External content (blog posts, sample repos, videos, conference talks) that helps Squad adoption must be triaged using the "Squad Ships It" boundary heuristic before incorporation. + +**Workflow:** +1. Triggered by `content-triage` label or external content reference in issue +2. Flight performs boundary analysis +3. Sub-issues generated for Squad-ownable content extraction (PAO responsibility) +4. FIDO verifies docs-test sync on extracted content +5. Scribe manages IRL references in `.github/irl/references.yml` (YAML schema) + +**Label convention:** `content:blog`, `content:sample`, `content:video`, `content:talk` + +**Why:** Pattern from PR #331 (Tamir Dresher blog) shows parallel extraction of Squad-ownable patterns (scenario guides, reviewer protocol) and infrastructure patterns (Ralph ops, proactive comms). Without clear boundary, teams pollute Squad docs with operational content or miss valuable patterns that should be generalized. + +**Impact:** Enables community content to accelerate Squad adoption without polluting core docs. Flight's boundary analysis becomes reusable decision framework. Prevents scope creep as adoption grows. + + +--- + +### PR #331 Quality Gate — Test Assertion Sync +**By:** FIDO (Quality Owner) +**Date:** 2026-03-10 +**Status:** 🟢 CLEARED (test fix applied, commit 6599db6) + +**What was blocked:** Merge blocked on stale test assertions in `test/docs-build.test.ts`. + +**Critical violations resolved:** +1. `EXPECTED_SCENARIOS` array stale (7 vs 25 disk files) — ✅ Updated to 25 entries +2. `EXPECTED_FEATURES` constant undefined (32 feature files) — ✅ Created array with 32 entries +3. Test assertion incomplete — ✅ Updated to validate features section + +**Why this matters:** Stale assertions that don't reflect filesystem state cause silent test skips. Regression: If someone deletes a scenario file, the test won't catch it. CI passing doesn't guarantee test coverage — only that the test didn't crash. + +**Lessons:** +- Test arrays must be refreshed when filesystem content changes +- Incomplete commits break the test-reality sync contract +- FIDO's charter: When adding test count assertions, must keep in sync with disk state + +**Outcome:** Test suite: 6/6 passing. Assertions synced to filesystem. No regression risk from stale assertions. + + +--- + +### Communication Patterns and PR Trust Models +**By:** PAO +**Date:** 2026-03-10 +**Status:** Documented in features/reviewer-protocol.md (trust levels section) and scenarios/proactive-communication.md (infrastructure pattern) + +**Decision:** Document emerging patterns in real Squad usage: proactive communication loops and PR review trust spectrum. + +**Components:** + +1. **Proactive communication patterns** — Outbound notifications (Teams webhooks), inbound scanning (Teams/email for work items), two-way feedback loop connecting external sources to Squad workflow + +2. **PR trust levels spectrum:** + - **Full review** (default for team repos) — All PRs require human review + - **Selective review** (personal projects with patterns) — Domain-expert or routine PRs can auto-merge + - **Self-managing** (solo personal repos only) — PRs auto-merge; Ralph's work monitoring provides retroactive visibility + +**Why:** Ralph 24/7 autonomous deployment creates an awareness gap — how does the human stay informed? Outbound notifications solve visibility. Inbound scanning solves "work lives in multiple places." Trust levels let users tune oversight to their context (full review for team repos, selective for personal projects, self-managing for solo work only). + +**Important caveat:** Self-managing ≠ unmonitored; Ralph's work monitoring and notifications provide retroactive visibility. + +**Anti-spam expectations:** Don't spam yourself outbound (notification fatigue), don't spam GitHub inbound (volume controls). + + +--- + +### Remote Squad Access — Phased Rollout (Proposed) +**By:** Flight +**Date:** 2026-03-10 +**Status:** Proposed — awaits proposal document in `docs/proposals/remote-squad-access.md` + +**Context:** Squad currently requires a local clone to answer questions. Users want remote access from mobile, browser, or different machine without checking out repo. + +**Phases:** + +**Phase 1: GitHub Discussions Bot (Ship First)** +- Surface: GitHub Discussions +- Trigger: `/squad` command or `@squad` mention +- Context: GitHub Actions workflow checks out repo → full `.squad/` state +- Response: Bot replies to thread +- Feasibility: 1 day +- Why first: Easy to build, zero hosting, respects repo privacy, async Q&A, immediately useful + +**Phase 2: GitHub Copilot Extension (High Value)** +- Surface: GitHub Copilot chat (VS Code, CLI, web, mobile) +- Trigger: `/squad ask {question}` in any Copilot client +- Context: Extension fetches `.squad/` files via GitHub API (no clone) +- Response: Answer inline in Copilot +- Feasibility: 1 week +- Why second: Works everywhere Copilot exists, instant response, natural UX + +**Phase 3: Slack/Teams Bot (Enterprise Value)** +- Surface: Slack or Teams channel +- Trigger: `@squad` mention in channel +- Context: Webhook fetches `.squad/` via GitHub API +- Response: Bot replies in thread +- Feasibility: 2 weeks +- Why third: Enterprise teams live in chat; high value for companies using Squad + +**Constraint:** Squad's intelligence lives in `.squad/` (roster, routing, decisions, histories). Any remote solution must solve context access. GitHub Actions workflows provide checkout for free. Copilot Extension and chat bots use GitHub API to fetch files. + +**Implementation:** Before Phase 1 execution, write proposal document. New CLI command: `squad answer --context discussions --question "..."`. New workflow: `.github/workflows/squad-answer.yml`. + +**Privacy:** All approaches respect repo visibility or require authentication. Most teams want private by default. + ### Test assertion discipline — mandatory **By:** FIDO (formerly Hockney), v0.8.24 **What:** All code agents must update tests when changing APIs. FIDO has PR blocking authority on quality grounds. @@ -90,6 +832,7 @@ **What:** Every PR must be evaluated for documentation impact. PAO reviews PRs for missing or outdated docs. **Why:** Code changes without doc updates lead to stale guides and confused users. + --- ## Release v0.8.24 @@ -101,40 +844,5896 @@ The CLI packaging smoke test is APPROVED as the quality gate for npm releases. **What:** -- npm pack → creates tarball of both squad-sdk and squad-cli -- npm install → installs in clean temp directory (simulates user install) -- node {cli-entry.js} → invokes 27 commands + 3 aliases through installed package -- Coverage: All 26 primary commands + 3 of 4 aliases (watch, workstreams, remote-control) +1. Text box preference: bottom-aligned, squared off (like Copilot CLI / Claude CLI) — future work, not today +2. Alpha-level shipment acceptable for now — no grand UI redesign today +3. CLI must show "experimental, please file issues" banner +4. Spinner/wait messages should rotate every ~3 seconds — use codebase facts, project trivia, vulnerability info, or creative "-ing" words. Never just spin silently. +5. Use wait time to inform or entertain users -**Why:** Catches broken package.json exports, MODULE_NOT_FOUND errors, ESM resolution failures, command routing regressions — the exact failure modes we've shipped before. +**Why:** User request — captured for team memory and crash recovery -**Gaps (acceptable):** -- Semantic validation not covered (only routing tested) -- Cross-platform gaps (test runs on ubuntu-latest only) -- Optional dependencies allowed to fail (node-pty) +### 2026-03-01T20:16:00Z: User directive — CLI timeout too low +**By:** Brady (via Copilot) +**Date:** 2026-03-01 -**Result:** ✅ GO — v0.8.24 release approved. 32/32 tests pass. +**What:** The CLI timeout is set too low — Brady tried using Squad CLI in this repo and it didn't work well. Timeout needs to be increased. Not urgent but should be captured as a CLI improvement opportunity. ---- +**Why:** User request — captured for team memory and PRD inclusion -### CLI Release Readiness Audit — v0.8.24 -**By:** EECOM -**Date:** 2026-03-08 +### 2026-03-01: Multi-Squad Storage & Resolution Design +**By:** Keaton (Lead) +**What:** +- New directory structure: ~/.config/squad/squads/{name}/.squad/ with ~/.config/squad/config.json for registry +- Keep +esolveGlobalSquadPath() unchanged; add +esolveNamedSquadPath(name?: string) and listPersonalSquads() on top +- Auto-migration: existing single personal squad moves to squads/default/ on first run +- Resolution priority: explicit (CLI flag) > project config > env var > git remote mapping > path mapping > default +- Global config.json schema: { version, defaultSquad, squads, mappings } -Definitive CLI completeness audit confirms all commands work post-publish. +**Why:** +- squads/ container avoids collisions with existing files at global root +- Backward-compatible: legacy layout detected and auto-migrated; existing code continues to work +- Clean separation: global config lives alongside squads, not inside any one squad +- Resolution chain enables flexible mapping without breaking existing workflows +### 2026-03-01: Multi-Squad SDK Functions +**By:** Kujan (SDK Expert) **What:** -- 26 primary commands routed, all tested ✅ -- 4 aliases routed (watch, workstreams, remote-control, streams) — 3 tested, 1 untested -- Tarball: 318 files, bin entry correct, postinstall script functional -- ESM runtime patch verified for Node 24+ compatibility -- All tests pass: 32/32 (36s runtime) +- New SDK exports: +esolveNamedSquadPath(), listSquads(), createSquad(), deleteSquad(), switchSquad(), +esolveSquadForProject() +- New type: SquadEntry { name, path, isDefault, createdAt } +- squads.json registry (separate file, not config.json) with squad metadata and mappings +- SquadDirConfig v2 addition: optional personalSquad?: string field (v1 configs unaffected) +- Consult mode updated: setupConsultMode(options?: { squad?: string }) with explicit selection or auto-resolution -**Gaps (non-blocking):** -- `streams` alias routed but not smoke-tested (same code path as tested `subsquads` — low risk) +**Why:** +- Lazy migration with fallback chain ensures zero breaking changes to existing users +- Separate squads.json is single source of truth for routing; keeps project config focused +- Version handling allows incremental adoption; v1 configs work unchanged +- SDK resolution functions can be called from CLI and library code without duplication -**Result:** ✅ SHIP IT — 95% confidence. CLI production-ready for v0.8.24. +### 2026-03-01: Multi-Squad CLI Commands & REPL +**By:** Kovash (REPL) +**What:** +- New commands: squad list, squad create , squad switch , squad delete +- Modified commands: squad consult --squad=, squad extract --squad=, squad init --global --name= +- Interactive picker for squad selection: arrow keys (↑/↓), Enter to confirm, Ctrl+C to cancel +- REPL integration: /squad and /squads slash commands with riggerSquadReload signal +- .active file stores current active squad name (plain text) +- Status command enhanced to show active squad and squad list ---- +**Why:** +- Picker only shows when needed (multiple squads) and TTY available; non-TTY gracefully uses active squad +- Slash commands follow existing pattern (/init, /agents, etc.); seamless REPL integration +- .active file is simple and atomic; suitable for concurrent CLI access +- Squad deletion safety: cannot delete active squad; requires confirmation + +### 2026-03-01: Multi-Squad UX & Interaction Design +**By:** Marquez (UX Designer) +**What:** +- Visual indicator: current squad marked with ●, others with ○; non-default squads tagged [switched] +- Squad name always visible in REPL header and prompt: ◆ Squad (client-acme) +- Picker interactions: ↑/↓ navigate, Enter select, Esc/Ctrl+C cancel; 5-7 squads displayed, wrap around +- Error states: clear copy with next actions (e.g., "Squad not found. Try @squad:personal." or "Run /squads to list.") +- Copy style: active verbs (Create, Switch, List), human-readable nouns (no jargon), 3-5 words per line +- Onboarding: fresh install defaults to "personal"; existing single-squad users see migration notice + +**Why:** +- Persistent context (squad name in header/prompt) prevents "Which squad am I in?" confusion +- Interactive picker is discoverable and non-blocking; minimal cognitive load +- Error messages with next actions reduce support friction +- Onboarding defaults and migration notices ensure smooth upgrade path for existing users + +# Decision: Separator component is canonical for horizontal rules + +**By:** Cheritto (TUI Engineer) +**Date:** 2026-03-02 +**Issues:** #655, #670, #671, #677 + +## What + +- All horizontal separator lines in shell components must use the shared `Separator` component (`components/Separator.tsx`), not inline `box.h.repeat()` calls. +- The `Separator` component handles terminal capability detection, box-drawing character degradation, and width computation internally. +- Information hierarchy convention: **bold** for primary CTAs (commands, actions) > normal for content > **dim** for metadata (timestamps, status, hints). +- `flexGrow` should not be used on containers that may be empty — it creates dead space in Ink layouts. + +## Why + +Duplicated separator logic was found in 3 files (App.tsx, AgentPanel.tsx, MessageStream.tsx). Consolidation to a single component prevents drift and makes it trivial to change separator style globally. The info hierarchy and whitespace conventions ensure visual consistency as new components are added. +### 2026-03-01: PR #547 Remote Control Feature — Architectural Review +**By:** Fenster +**Date:** 2026-03-01 +**PR:** #547 "Squad Remote Control - PTY mirror + devtunnel for phone access" by tamirdresher (external) + +## Context + +External contributor Tamir Dresher submitted a PR adding `squad start --tunnel` command to run Copilot in a PTY and mirror terminal output to phone/browser via WebSocket + Microsoft Dev Tunnels. + +## Architectural Question + +Is remote terminal access via devtunnel + PTY mirroring in scope for Squad v1 core? + +## Technical Assessment + +**What works:** +- RemoteBridge WebSocket server architecture is sound +- PTY mirroring approach is technically correct +- Session management dashboard is useful +- Security headers and CSP are present +- Test coverage exists (18 tests, though failing due to build issues) + +**Critical blockers:** +1. **Build broken** — TypeScript errors in `start.ts`, all tests failing +2. **Command injection vulnerability** — `execFileSync` with string interpolation in `rc-tunnel.ts` +3. **Native dependency** — `node-pty` requires C++ compiler (install friction) +4. **Windows-only effectively** — hardcoded paths, devtunnel CLI Windows-centric +5. **No cross-platform strategy** — macOS/Linux support unclear + +**Architectural concerns:** + +### 2026-03-02T23:36:00Z: Version target — v0.6.0 for public migration **[SUPERSEDED — see line 1046]** +**By:** Brady (via Copilot) +**What:** The public migration from squad-pr to squad should target v0.6.0, not v0.8.17. This overrides Kobayashi's Phase 5 Option A recommendation. The public repo (bradygaster/squad) goes from v0.5.4 → v0.6.0 — a clean minor bump. +**Why:** User directive. v0.6.0 is the logical next public version from v0.5.4. Internal version numbers (0.6.x–0.8.x) were private development milestones. +**[CORRECTION — 2026-03-03]:** This decision was REVERSED by Brady. Brady explicitly stated: "0.6.0 should NOT appear as the goal for ANY destination. I want the beta to become 0.8.17." The actual migration target is v0.8.17. See the superseding "Versioning Model: npm packages vs Public Repo Tags" decision at line 1046 which clarifies that v0.6.0 is a public repo tag only, while npm packages remain at 0.8.17. Current migration documentation correctly references v0.8.17 throughout. +1. **Not integrated with Squad runtime** — doesn't use EventBus, Coordinator, or agent orchestration. Isolated feature. +2. **Two separate modes** — PTY mode (`start.ts`) vs. ACP passthrough mode (`rc.ts`). Why both? +3. **New CLI paradigm** — "start" implies daemon/server, not interactive mirroring. Command naming collision risk. +4. **External dependency** — requires `devtunnel` CLI installed + authenticated. Not bundled, not auto-installed. +5. **Audit logs** — go to `~/.cli-tunnel/audit/` instead of `.squad/log/` (inconsistent with Squad state location). + +## Recommendation + +**Request Changes** — Do not merge until: +1. TypeScript build errors fixed +2. Command injection vulnerability patched (use array args, no interpolation) +3. Tests passing (currently 18/18 failing) +4. Cross-platform support documented or Windows-only label added +5. Architectural decision on scope: Is this core or plugin? + +**If approved as core feature:** +- Extract to plugin first, prove value, then consider core integration +- Unify PTY vs. ACP modes (pick one) +- Integrate with EventBus/Coordinator (or explain why isolated is correct) +- Rename command to `squad remote` or `squad tunnel` (avoid `start` collision) +- Move audit logs to `.squad/log/` + +**If approved as plugin:** +- This is the right path — keeps core small, proves value independently +- Still fix security issues before merge to plugin repo + +## For Brady + +You requested a runtime review. Here's the verdict: + +- **Concept is cool** — phone access to Copilot is a real use case. +- **Implementation needs work** — build broken, security issues, Windows-only. +- **Architectural fit unclear** — not in any Squad v1 PRD. No integration with agent orchestration. +- **Native dependency risk** — `node-pty` adds install friction (C++ compiler required). + +**My take:** This belongs in a plugin, not core. External contributor did solid work on the WebSocket bridge, but Squad v1 needs to ship agent orchestration first. Remote access is a nice-to-have, not a v1 must-have. + +If you want this in v1, we need a proposal (docs/proposals/) first. + +### 2026-03-02: Multi-squad test contract — squads.json schema +**By:** Hockney (Tester) +**Date:** 2026-03-02 +**Issue:** #652 + +## What + +Tests for multi-squad (PR #690) encode a specific squads.json contract: + +```typescript +interface SquadsJson { + version: 1; + defaultSquad: string; + squads: Record; +} +``` + +Squad name validation regex: `^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$` (kebab-case, 1-40 chars). + +## Why + +Fenster's implementation should match this schema. If the schema changes, tests need updating. Recording so the team knows the contract is encoded in tests. + +## Impact + +Fenster: Align `multi-squad.ts` types with this schema, or flag if different — Hockney will adjust tests. + +### 2026-03-02: PR #582 Review — Consult Mode Implementation +**By:** Keaton (Lead) +**Date:** 2026-03-01 +**Context:** External contributor PR from James Sturtevant (jsturtevant) + +## Decision + +**Do not merge PR #582 in its current form.** + +This is a planning document (PRD) masquerading as implementation. The PR contains: +- An excellent 854-line PRD for consult mode +- Test stubs for non-existent functions +- Zero actual implementation code +- A history entry claiming work is done (aspirational, not factual) + +## Required Actions + +1. **Extract PRD to proper location:** + - Move `.squad/identity/prd-consult-mode.md` → `docs/proposals/consult-mode.md` + - PRDs belong in proposals/, not identity/ + +2. **Close this PR with conversion label:** + - Label: "converted-to-proposal" + - Comment: Acknowledge excellent design work, explain missing implementation + +3. **Create implementation issues from PRD phases:** + - Phase 1: SDK changes (SquadDirConfig, resolution helpers) + - Phase 2: CLI command implementation + - Phase 3: Extraction workflow + - Each phase: discrete PR with actual code + tests + +4. **Architecture discussion needed before implementation:** + - How does consult mode integrate with existing sharing/ module? + - Session learnings vs agent history — conceptual model mismatch + - Remote mode (teamRoot pointer) vs copy approach — PRD contradicts itself + +## Architectural Guidance + +**What's right:** +- `consult: true` flag in config.json ✅ +- `.git/info/exclude` for git invisibility ✅ +- `git rev-parse --git-path info/exclude` for worktree compatibility ✅ +- Separate extraction command (`squad extract`) ✅ +- License risk detection (copyleft) ✅ + +**What needs rethinking:** +- Reusing `sharing/` module (history split vs learnings extraction — different domains) +- PRD flip-flops between "copy squad" and "remote mode teamRoot pointer" +- No design for how learnings are structured or extracted +- Tests before code (cart before horse) + +## Pattern Observed + +James Sturtevant is a thoughtful contributor who understands the product vision. The PRD is coherent and well-structured. This connects to his #652 issue (Multiple Personal Squads) — consult mode is a stepping stone to multi-squad workflows. + +**Recommendation:** Engage James in architecture discussion before he writes code. This feature has implications for the broader personal squad vision. Get alignment on: +1. Sharing module fit (or new consult module?) +2. Learnings structure and extraction strategy +3. Phase boundaries and deliverables + +## Why This Matters + +External contributors are engaging with Squad's architecture. We need to guide them toward shippable PRs, not just accept aspirational work. Setting clear expectations now builds trust and avoids wasted effort. + +## Files Referenced + +- `.squad/identity/prd-consult-mode.md` (PRD, should move) +- `test/consult.test.ts` (tests for non-existent code) +- `.squad/agents/fenster/history.md` (claims work done) +- `packages/squad-sdk/src/resolution.ts` (needs `consult` field, unchanged in PR) + + +### cli.js is now a thin ESM shim + +**By:** Fenster +**Date:** 2025-07 +**What:** `cli.js` at repo root is a 14-line shim that imports `./packages/squad-cli/dist/cli-entry.js`. It no longer contains bundled CLI code. The deprecation notice only displays when invoked via npm/npx. +**Why:** The old bundled cli.js was stale and missing commands added after the monorepo migration (e.g., `aspire`). A shim ensures `node cli.js` always runs the latest built CLI. +**Impact:** `node cli.js` now requires `npm run build` to have been run first (so `packages/squad-cli/dist/cli-entry.js` exists). This was already the case for any development workflow. + + +### 2026-03-02T01-09-49Z: User directive +**By:** Brady (via Copilot) +**What:** Stop distributing the package via NPX and GitHub. Only distribute via NPM from now on. Go from the public version to whatever version we're in now in the private repo. Adopt the versioning scheme from issue #692. +**Why:** User request — captured for team memory + +# Release Plan Update — npm-only Distribution & Semver Fix (#692) + +**Status:** DECIDED +**Decided by:** Kobayashi (Git & Release) +**Date:** 2026-03-01T14:22Z +**Context:** Brady's two strategic decisions on distribution and versioning + +## Decisions + +### 1. NPM-Only Distribution +- **What:** End GitHub-native distribution (`npx github:bradygaster/squad`). Install exclusively via npm registry. +- **How:** Users install via `npm install -g @bradygaster/squad-cli` (global) or `npx @bradygaster/squad-cli` (per-project). +- **Why:** Simplified distribution, centralized source of truth, standard npm tooling conventions. +- **Scope:** Affects all future releases, all external documentation, and CI/CD publish workflows. +- **Owners:** Rabin (docs), Fenster (scripts), all team members (update docs/sample references). + +### 2. Semantic Versioning Fix (#692) +- **Problem:** Versions were `X.Y.Z.N-preview` (four-part with prerelease after), which violates semver spec. +- **Solution:** Correct format is `X.Y.Z-preview.N` (prerelease identifier comes after patch, before any build metadata). +- **Examples:** + - ❌ Invalid: `0.8.6.1-preview`, `0.8.6.16-preview` + - ✅ Valid: `0.8.6-preview.1`, `0.8.6-preview.16` +- **Impact:** Affects all version strings going forward (package.json, CLI version constant, release tags). +- **Release sequence:** + 1. Pre-release: `X.Y.Z-preview.1`, `X.Y.Z-preview.2`, ... + 2. At publish: Bump to `X.Y.Z` + 3. Post-publish: Bump to `{next}-preview.1` (reset counter) + +### 3. Version Continuity +- **Transition:** Public repo ended at `0.8.5.1`. Private repo continues at `0.8.6-preview` (following semver format). +- **Rationale:** Clear break between public (stable) and private (dev) codebases while maintaining version history continuity. + +## Implementation + +- ✅ **CHANGELOG.md:** Added "Changed" section documenting distribution channel and semver fix. +- ✅ **Charter (Kobayashi):** Updated Release Versioning Sequence with corrected pattern and phase description. +- ✅ **History (Kobayashi):** Logged decision with rationale and scope. + +## Dependent Work + +- **Fenster:** Ensure `bump-build.mjs` implements X.Y.Z-preview.N pattern (not X.Y.Z.N-preview). +- **Rabin:** Update README, docs, and all install instructions to reflect npm-only distribution. +- **All:** Use corrected version format in release commits, tags, and announcements. + +## Notes + +- Zero impact on functionality — this is purely distribution and versioning cleanup. +- Merge drivers on `.squad/agents/kobayashi/history.md` ensure this decision appends safely across parallel branches. +- If questions arise about versioning during releases, refer back to Charter § Release Versioning Sequence. + +# Decision: npm-only distribution (GitHub-native removed) + +**By:** Rabin (Distribution) +**Date:** 2026-03-01 +**Requested by:** Brady + +## What Changed + +All distribution now goes through npm. The `npx github:bradygaster/squad` path has been fully removed from: +- Source code (github-dist.ts default template, install-migration.ts, init.ts) +- All 4 copies of squad.agent.md (Ralph Watch Mode commands) +- All 4 copies of squad-insider-release.yml (release notes) +- README.md, migration guides, blog posts, cookbook, installation docs +- Test assertions (bundle.test.ts) +- Rabin's own charter (flipped from "never npmjs.com" to "always npmjs.com") + +## Install Paths (the only paths) + +```bash +# Global install +npm install -g @bradygaster/squad-cli + +# Per-use (no install) +npx @bradygaster/squad-cli + +# SDK for programmatic use +npm install @bradygaster/squad-sdk +``` + +## Why + +One distribution channel means less confusion, fewer edge cases, and zero SSH-agent hang bugs. npm caching makes installs faster. Semantic versioning works properly. The root `cli.js` still exists with a deprecation notice for anyone who somehow hits the old path. + +## Impact + +- **All team members:** When writing docs or examples, use `npm install -g @bradygaster/squad-cli` or `npx @bradygaster/squad-cli`. Never reference `npx github:`. +- **CI/CD:** Insider release workflow now shows npm install commands in release notes. +- **Tests:** bundle.test.ts assertions updated to match new default template. + + +# Decision: Versioning Model — npm Packages vs Public Repo + +**Date:** 2026-03-03T02:45:00Z +**Decided by:** Kobayashi (Git & Release specialist) +**Related issues:** Migration prep, clarifying confusion between npm and public repo versions +**Status:** Active — team should reference this in all future releases + +## The Problem + +The migration process had introduced confusion about which version number applies where: +- Coordinator incorrectly bumped npm package versions to 0.6.0, creating version mismatch +- Migration checklist had npm packages publishing as 0.6.0 +- CHANGELOG treated 0.6.0 as an npm package version +- No clear distinction between "npm packages version" vs "public repo GitHub release tag" +- Risk of future mistakes during releases + +## The Model (CORRECT) + +Two distinct version numbers serve two distinct purposes: + +### 1. npm Packages: `@bradygaster/squad-cli` and `@bradygaster/squad-sdk` + +- **Follow semver cadence from current version:** Currently at 0.8.17 (published to npm) +- **Next publish after 0.8.17:** 0.8.18 (NOT 0.6.0) +- **Development versions:** Use `X.Y.Z-preview.N` format (e.g., 0.8.18-preview.1, 0.8.18-preview.2) +- **Release sequence per Kobayashi charter:** + 1. Pre-release: `X.Y.Z-preview.N` (development) + 2. At publish: Bump to `X.Y.Z` (e.g., 0.8.18), publish to npm, create GitHub release + 3. Post-publish: Immediately bump to next-preview (e.g., 0.8.19-preview.1) + +**MUST NEVER:** +- Bump npm packages down (e.g., 0.8.17 → 0.6.0) +- Confuse npm package version with public repo tag + +### 2. Public Repo (bradygaster/squad): GitHub Release Tag `v0.8.17` **[CORRECTED from v0.6.0]** + +- **Purpose:** Marks the migration release point for the public repository +- **Public repo version history:** v0.5.4 (final pre-migration) → v0.8.17 (migration release) **[CORRECTED: Originally written as v0.6.0, corrected to v0.8.17 per Brady's directive]** +- **Applied to:** The migration merge commit on beta/main +- **Same as npm versions:** v0.8.17 is BOTH the npm package version AND the public repo tag **[CORRECTED: Originally described as "separate from npm versions"]** +- **No package.json changes:** The tag is applied after the merge commit, but the version in package.json matches the tag + +## Why Two Version Numbers? **[CORRECTED: Actually ONE version number — v0.8.17 for both]** + +1. **npm packages evolve on their own cadence:** Independent development, independent release cycles (via @changesets/cli) +2. **Public repo is a release marker:** The v0.8.17 tag signals "here's the migration point" to users who clone the public repo **[CORRECTED: Same version as npm, not different]** +3. **They target different audiences:** + - npm: Users who install via `npm install -g @bradygaster/squad-cli` + - Public repo: Users who clone `bradygaster/squad` or interact with GitHub releases + **[CORRECTED: Both use v0.8.17 — the version numbers are aligned, not separate]** + +## Impact on Migration Checklist & CHANGELOG + +- **migration-checklist.md:** All references correctly use v0.8.17 for both npm packages AND public repo tag. **[CORRECTED: Line originally said "publish as 0.8.18, not 0.6.0" but actual target is 0.8.17]** +- **CHANGELOG.md:** Tracks npm package versions at 0.8.x cadence +- **Future releases:** npm packages and public repo tags use the SAME version number **[CORRECTED: Original text implied they were different]** + +## Known Issue: `scripts/bump-build.mjs` + +The auto-increment build number script (`npm run build`) can produce invalid semver for non-prerelease versions: +- `0.6.0` + auto-increment → `0.6.0.1` (invalid) +- `0.8.18-preview.1` + auto-increment → `0.8.18-preview.2` (valid) + +Since npm packages stay at 0.8.x cadence, this is not a blocker for migration. But worth noting for future patch releases. + +## Directive Merged + +Brady's directive (2026-03-03T02:16:00Z): "squad-cli and squad-sdk must NOT be bumped down to 0.6.0. They are already shipped to npm at 0.8.17." + +✅ **Incorporated:** All fixes ensure npm packages stay at 0.8.x. The v0.8.17 is used for BOTH npm packages AND public repo tag. **[CORRECTED: Original text said "v0.6.0 is public repo only" which was incorrect]** + +## Action Items for Team + +- Reference this decision when asked "what version should we release?" +- Use this model for all future releases (main project and public repo) +- Update team onboarding docs to include this versioning distinction +### No temp/memory files in repo root +**By:** Brady +**What:** No plan files, memory files, or tracking artifacts in the repository root. +**Why:** Keep the repo clean. + + +--- + +## Adoption & Community + +### `.squad/` Directory Scope — Owner Directive +**By:** Brady (project owner, PR #326 review) +**Date:** 2026-03-10 + +**Directive:** The `.squad/` directory is **reserved for team state only** — roster, routing, decisions, agent histories, casting, and orchestration logs. Non-team data (adoption tracking, community metrics, reports) must NOT live in `.squad/`. Use `.github/` for GitHub platform integration or `docs/` for documentation artifacts. + +**Source:** [PR #326 comment](https://github.com/bradygaster/squad/pull/326#issuecomment-4029193833) + +--- + +### No Individual Repo Listing Without Consent — Owner Directive +**By:** Brady (project owner, PR #326 review) +**Date:** 2026-03-10 + +**Directive:** Growth metrics must report **aggregate numbers only** (e.g., "78+ repositories found via GitHub code search") — never name or link to individual community repos without explicit opt-in consent. The monitoring script and GitHub Action concepts are approved, but any public showcase or tracking list that identifies specific repos is blocked until a community consent plan exists. + +**Source:** [PR #326 comment](https://github.com/bradygaster/squad/pull/326#issuecomment-4029222967) + +--- + +### Adoption Tracking — Opt-In Architecture +**By:** Flight (implementing Brady's directives above) +**Date:** 2026-03-09 + +Privacy-first adoption monitoring using a three-tier system: + +**Tier 1: Aggregate monitoring (SHIPPED)** +- GitHub Action + monitoring script collect metrics +- Reports moved to `.github/adoption/reports/{YYYY-MM-DD}.md` +- Reports show ONLY aggregate numbers (no individual repo names): + - "78+ repositories found via code search" + - Total stars/forks across all discovered repos + - npm weekly downloads + +**Tier 2: Opt-in registry (DESIGN NEXT)** +- Create `SHOWCASE.md` in repo root with submission instructions +- Opted-in projects listed in `.github/adoption/registry.json` +- Monitoring script reads registry, reports only on opted-in repos + +**Tier 3: Public showcase (LAUNCH LATER)** +- `docs/community/built-with-squad.md` shows opted-in projects only +- README link added when ≥5 opted-in projects exist + +**Rationale:** +- Aggregate metrics safe (public code search results) +- Individual projects only listed with explicit owner consent +- Prevents surprise listings, respects privacy +- Incremental rollout maintains team capacity + +**Implementation (PR #326):** +- ✅ Moved `.squad/adoption/` → `.github/adoption/` +- ✅ Stripped tracking.md to aggregate-only metrics +- ✅ Removed individual repo names, URLs, metadata +- ✅ Updated adoption-report.yml and scripts/adoption-monitor.mjs +- ✅ Removed "Built with Squad" showcase link from README (Tier 2 feature) + +--- + +### Adoption Tracking Location & Privacy +**By:** EECOM +**Date:** 2026-03-10 + +Implementation decision confirming Tier 1 adoption tracking changes. + +**What:** Move adoption tracking from `.squad/adoption/` to `.github/adoption/` + +**Why:** +1. **GitHub integration:** `.github/adoption/` aligns with GitHub convention (workflows, CODEOWNERS, issue templates) +2. **Privacy-first:** Aggregate metrics only; defer individual repo showcase to Tier 2 (opt-in) +3. **Clear separation:** `.squad/` = team internal; `.github/` = GitHub platform integration +4. **Future-proof:** When Tier 2 opt-in launches, `.github/adoption/` is the natural home + +**Impact:** +- GitHub Action reports write to `.github/adoption/reports/{YYYY-MM-DD}.md` +- No individual repo information published until Tier 2 +- Monitoring continues collecting aggregate metrics via public APIs +- Team sees trends without publishing sensitive adoption data + +--- + +### Append-Only File Governance +**By:** Flight +**Date:** 2026-03-09 + +Feature branches must never modify append-only team state files except to append new content. + +**What:** If a PR diff shows deletions in `.squad/agents/*/history.md` or `.squad/decisions.md`, the PR is blocked until deletions are reverted. + +**Why:** Session state drift causes agents to reset append-only files to stale branch state, destroying team knowledge. PR #326 deleted entire history files and trimmed ~75 lines of decisions, causing data loss. + +**Enforcement:** Code review + future CI check candidate. + +--- + +### Documentation Style: No Ampersands +**By:** PAO +**Date:** 2026-03-09 + +Ampersands (&) are prohibited in user-facing documentation headings and body text, per Microsoft Style Guide. + +**Rule:** Use "and" instead. + +**Why:** Microsoft Style Guide prioritizes clarity and professionalism. Ampersands feel informal and reduce accessibility. + +**Exceptions:** +- Brand names (AT&T, Barnes & Noble) +- UI element names matching exact product text +- Code samples and technical syntax +- Established product naming conventions + +**Scope:** Applies to docs pages, README files, blog posts, community-facing content. Internal files (.squad/** memory files, decision docs, agent history) have flexibility. + +**Reference:** https://learn.microsoft.com/en-us/style-guide/punctuation/ampersands + +--- + +## Sprint Directives + +### Secret handling — agents must never persist secrets +**By:** RETRO (formerly Baer), v0.8.24 +**What:** Agents must NEVER write secrets, API keys, tokens, or credentials into conversational history, commit messages, logs, or any persisted file. Acknowledge receipt without echoing values. +**Why:** Secrets in logs or history are a security incident waiting to happen. + +--- + +## Squad Ecosystem Boundaries & Content Governance + +### Squad Docs vs Squad IRL Boundary (consolidated) +**By:** PAO (via Copilot), Flight +**Date:** 2026-03-10 +**Status:** Active pattern for all documentation PRs + +**Litmus test:** If Squad doesn't ship the code or configuration, the documentation belongs in Squad IRL, not the Squad framework docs. + +**Categories:** + +1. **Squad docs** — Features Squad ships (routing, charters, reviewer protocol, config, behavior) +2. **Squad IRL** — Infrastructure around Squad (webhooks, deployment patterns, logging, external tools, operational patterns) +3. **Gray area:** Platform features (GitHub Issue Templates) → Squad docs if framed as "how to configure X for Squad" + +**Examples applied (PR #331):** + +| Document | Decision | Reason | +|----------|----------|--------| +| ralph-operations.md | DELETE → IRL | Infrastructure (deployment, logging) around Squad, not Squad itself | +| proactive-communication.md | DELETE → IRL | External tools (Teams, WorkIQ) configured by community, not built into Squad | +| issue-templates.md | KEEP, reframe | GitHub platform feature; clarify scope: "a GitHub feature configured for Squad" | +| reviewer-protocol.md (Trust Levels) | KEEP | Documents user choice spectrum within Squad's existing review system | + +**Enforcement:** Code review + reframe pattern ("GitHub provides X. Here's how to configure it for Squad's needs."). Mark suspicious deletions for restore (append-only governance). + +**Future use:** Apply this pattern to all documentation PRs to maintain clean boundaries. + +--- + +### Content Triage Skill — External Content Integration +**By:** Flight +**Date:** 2026-03-10 +**Status:** Skill created at `.squad/skills/content-triage/SKILL.md` + +**Pattern:** External content (blog posts, sample repos, videos, conference talks) that helps Squad adoption must be triaged using the "Squad Ships It" boundary heuristic before incorporation. + +**Workflow:** +1. Triggered by `content-triage` label or external content reference in issue +2. Flight performs boundary analysis +3. Sub-issues generated for Squad-ownable content extraction (PAO responsibility) +4. FIDO verifies docs-test sync on extracted content +5. Scribe manages IRL references in `.github/irl/references.yml` (YAML schema) + +**Label convention:** `content:blog`, `content:sample`, `content:video`, `content:talk` + +**Why:** Pattern from PR #331 (Tamir Dresher blog) shows parallel extraction of Squad-ownable patterns (scenario guides, reviewer protocol) and infrastructure patterns (Ralph ops, proactive comms). Without clear boundary, teams pollute Squad docs with operational content or miss valuable patterns that should be generalized. + +**Impact:** Enables community content to accelerate Squad adoption without polluting core docs. Flight's boundary analysis becomes reusable decision framework. Prevents scope creep as adoption grows. + +--- + +### PR #331 Quality Gate — Test Assertion Sync +**By:** FIDO (Quality Owner) +**Date:** 2026-03-10 +**Status:** 🟢 CLEARED (test fix applied, commit 6599db6) + +**What was blocked:** Merge blocked on stale test assertions in `test/docs-build.test.ts`. + +**Critical violations resolved:** +1. `EXPECTED_SCENARIOS` array stale (7 vs 25 disk files) — ✅ Updated to 25 entries +2. `EXPECTED_FEATURES` constant undefined (32 feature files) — ✅ Created array with 32 entries +3. Test assertion incomplete — ✅ Updated to validate features section + +**Why this matters:** Stale assertions that don't reflect filesystem state cause silent test skips. Regression: If someone deletes a scenario file, the test won't catch it. CI passing doesn't guarantee test coverage — only that the test didn't crash. + +**Lessons:** +- Test arrays must be refreshed when filesystem content changes +- Incomplete commits break the test-reality sync contract +- FIDO's charter: When adding test count assertions, must keep in sync with disk state + +**Outcome:** Test suite: 6/6 passing. Assertions synced to filesystem. No regression risk from stale assertions. + +--- + +### Communication Patterns and PR Trust Models +**By:** PAO +**Date:** 2026-03-10 +**Status:** Documented in features/reviewer-protocol.md (trust levels section) and scenarios/proactive-communication.md (infrastructure pattern) + +**Decision:** Document emerging patterns in real Squad usage: proactive communication loops and PR review trust spectrum. + +**Components:** + +1. **Proactive communication patterns** — Outbound notifications (Teams webhooks), inbound scanning (Teams/email for work items), two-way feedback loop connecting external sources to Squad workflow + +2. **PR trust levels spectrum:** + - **Full review** (default for team repos) — All PRs require human review + - **Selective review** (personal projects with patterns) — Domain-expert or routine PRs can auto-merge + - **Self-managing** (solo personal repos only) — PRs auto-merge; Ralph's work monitoring provides retroactive visibility + +**Why:** Ralph 24/7 autonomous deployment creates an awareness gap — how does the human stay informed? Outbound notifications solve visibility. Inbound scanning solves "work lives in multiple places." Trust levels let users tune oversight to their context (full review for team repos, selective for personal projects, self-managing for solo work only). + +**Important caveat:** Self-managing ≠ unmonitored; Ralph's work monitoring and notifications provide retroactive visibility. + +**Anti-spam expectations:** Don't spam yourself outbound (notification fatigue), don't spam GitHub inbound (volume controls). + +--- + +### Remote Squad Access — Phased Rollout (Proposed) +**By:** Flight +**Date:** 2026-03-10 +**Status:** Proposed — awaits proposal document in `docs/proposals/remote-squad-access.md` + +**Context:** Squad currently requires a local clone to answer questions. Users want remote access from mobile, browser, or different machine without checking out repo. + +**Phases:** + +**Phase 1: GitHub Discussions Bot (Ship First)** +- Surface: GitHub Discussions +- Trigger: `/squad` command or `@squad` mention +- Context: GitHub Actions workflow checks out repo → full `.squad/` state +- Response: Bot replies to thread +- Feasibility: 1 day +- Why first: Easy to build, zero hosting, respects repo privacy, async Q&A, immediately useful + +**Phase 2: GitHub Copilot Extension (High Value)** +- Surface: GitHub Copilot chat (VS Code, CLI, web, mobile) +- Trigger: `/squad ask {question}` in any Copilot client +- Context: Extension fetches `.squad/` files via GitHub API (no clone) +- Response: Answer inline in Copilot +- Feasibility: 1 week +- Why second: Works everywhere Copilot exists, instant response, natural UX + +**Phase 3: Slack/Teams Bot (Enterprise Value)** +- Surface: Slack or Teams channel +- Trigger: `@squad` mention in channel +- Context: Webhook fetches `.squad/` via GitHub API +- Response: Bot replies in thread +- Feasibility: 2 weeks +- Why third: Enterprise teams live in chat; high value for companies using Squad + +**Constraint:** Squad's intelligence lives in `.squad/` (roster, routing, decisions, histories). Any remote solution must solve context access. GitHub Actions workflows provide checkout for free. Copilot Extension and chat bots use GitHub API to fetch files. + +**Implementation:** Before Phase 1 execution, write proposal document. New CLI command: `squad answer --context discussions --question "..."`. New workflow: `.github/workflows/squad-answer.yml`. + +**Privacy:** All approaches respect repo visibility or require authentication. Most teams want private by default. + +### Test assertion discipline — mandatory +**By:** FIDO (formerly Hockney), v0.8.24 +**What:** All code agents must update tests when changing APIs. FIDO has PR blocking authority on quality grounds. +**Why:** APIs changed without test updates caused CI failures and blocked external contributors. + +### Docs-test sync — mandatory +**By:** PAO (formerly McManus), v0.8.24 +**What:** New docs pages require corresponding test assertion updates in the same commit. +**Why:** Stale test assertions block CI and frustrate contributors. + +### Contributor recognition — every release +**By:** PAO, v0.8.24 +**What:** Each release includes an update to the Contributors Guide page. +**Why:** No contribution goes unappreciated. + +### API-test sync cross-check +**By:** FIDO + Booster, v0.8.24 +**What:** Booster adds CI check for stale test assertions. FIDO enforces via PR review. +**Why:** Prevents the pattern of APIs changing without test updates. + +### Doc-impact review — every PR +**By:** PAO, v0.8.25 +**What:** Every PR must be evaluated for documentation impact. PAO reviews PRs for missing or outdated docs. +**Why:** Code changes without doc updates lead to stale guides and confused users. + + +--- + +## Release v0.8.24 + +### CLI Packaging Smoke Test: Release Gate Decision +**By:** FIDO, v0.8.24 +**Date:** 2026-03-08 + +The CLI packaging smoke test is APPROVED as the quality gate for npm releases. + +**What:** +- npm pack → creates tarball of both squad-sdk and squad-cli +- npm install → installs in clean temp directory (simulates user install) +- node {cli-entry.js} → invokes 27 commands + 3 aliases through installed package +- Coverage: All 26 primary commands + 3 of 4 aliases (watch, workstreams, remote-control) + +**Why:** Catches broken package.json exports, MODULE_NOT_FOUND errors, ESM resolution failures, command routing regressions — the exact failure modes we've shipped before. + +**Gaps (acceptable):** +- Semantic validation not covered (only routing tested) +- Cross-platform gaps (test runs on ubuntu-latest only) +- Optional dependencies allowed to fail (node-pty) + +## Impact + +- All agents: charter generation now reliably round-trips model preferences. +- Verbal/Keaton: the 4-layer model selection hierarchy documented in squad.agent.md is now supported at the SDK config level. +- Anyone adding new config fields: use the `assertModelPreference()` pattern (accept string-or-object, normalize internally) for fields that need simple and rich config shapes. + +# Decision: Runtime ExperimentalWarning suppression via process.emit hook + +**Date:** 2026-03-07 +**Author:** Fenster (Core Dev) +**Context:** PR #233 CI failure — 4 tests failed + +## Problem + +PR #233 (CLI wiring fixes for #226, #229, #201, #202) passed all 74 tests locally but failed 4 tests in CI: + +- `test/cli-p0-regressions.test.ts` — bare semver test (expected 1 line, got 3) +- `test/speed-gates.test.ts` — version outputs one line (expected 1, got 3) +- `test/ux-gates.test.ts` — no overflow beyond 80 chars (ExperimentalWarning line >80) +- `test/ux-gates.test.ts` — version bare semver (expected 1 line, got 3) + +Root cause: `node:sqlite` import triggers Node.js `ExperimentalWarning` that leaks to stderr. The existing `process.env.NODE_NO_WARNINGS = '1'` in cli-entry.ts was ineffective because Node only reads that env var at process startup, not when set at runtime. + +The warning likely didn't appear locally because the local Node.js version may have already suppressed it or the env var was set in the shell. + +## Decision + +Added a `process.emit` override in cli-entry.ts that intercepts `warning` events with `name === 'ExperimentalWarning'` and swallows them. This is placed: +- After `process.env.NODE_NO_WARNINGS = '1'` (which still helps child processes) +- Before the `await import('node:sqlite')` pre-flight check + +This is the standard Node.js pattern for runtime warning suppression when you can't control the process launch flags. + +## Impact + +- **cli-entry.ts**: 12 lines added (comment + override function) +- **Tests**: All 4 previously failing tests now pass; no regressions in structural tests (#624) +- **Behavior**: ExperimentalWarning messages no longer appear in CLI output; other warnings (DeprecationWarning, etc.) are unaffected + +### 2026-03-07T14:22:00Z: User directive - Quality cross-review +**By:** Brady (via Copilot) +**What:** All team members must double-and-triple check one another's work. Recent PRs have had weird test failures and inconsistencies. KEEN focus on quality - nothing can slip. +**Why:** User request - quality gate enforcement after speed gate, EBUSY, and cross-contamination issues across PRs #244, #245, #246. + + +# Decision: Optional dependencies must use lazy loading (#247) + +**Date:** 2026-03-09 +**Author:** Fenster +**Status:** Active + +## Context + +Issue #247 — two community reports of installation failure caused by top-level imports of `@opentelemetry/api` crashing when the package wasn't properly installed in `npx` temp environments. + +## Decision + +1. **All optional/telemetry dependencies must be loaded lazily** — never at module top-level. Use `createRequire(import.meta.url)` inside a `try/catch` for synchronous lazy loading. + +2. **Centralized wrapper pattern** — when multiple source files import from the same optional package, create a single wrapper module (e.g., `otel-api.ts`) that provides the fallback logic. Consumers import from the wrapper. + +3. **`@opentelemetry/api` is now an optionalDependency** — it was a hard dependency but is functionally optional. The SDK operates with no-op telemetry when absent. + +4. **`vscode-jsonrpc` added as direct dep** — improves hoisting for npx installs. The ESM subpath import issue (`vscode-jsonrpc/node` without `.js`) is upstream in `@github/copilot-sdk`. + +## Implications + +- Any new OTel integration must import from `runtime/otel-api.js`, never directly from `@opentelemetry/api`. +- Test files may continue importing `@opentelemetry/api` directly (it's installed in dev). +- If adding new optional dependencies in the future, follow the same lazy-load + wrapper pattern. + + +# Release Readiness Check — v0.8.21 + +**By:** Keaton (Lead) +**Date:** 2026-03-07 +**Status:** 🟡 SHIP WITH CAVEATS + + +--- + +## Executive Summary + +v0.8.21 is technically ready to release. All three packages carry the same version string (`0.8.21-preview.7`). Linting passes, 3718 tests pass (19 flaky UI tests pre-existing), CI green on commits. However, **#247 (Installation Failure) must be fixed before shipping**. This is a P0 blocker that breaks the primary installation path. Fenster is actively fixing it. + + +--- + +## Version State ✅ + +All packages aligned at **0.8.21-preview.7:** + +- Root `package.json` — v0.8.21-preview.7 +- `packages/squad-sdk/package.json` — v0.8.21-preview.7 +- `packages/squad-cli/package.json` — v0.8.21-preview.7 + +**Release Tag:** Should be `v0.8.21-preview.7` (already live as -preview, ready to promote to stable or next -preview if #247 requires a patch). + + +--- + +## Git State ✅ + +**Current Branch:** `dev` +**Commits since main:** 23 commits (main..dev) + +Recent activity (last 10 commits): +- 3f924d0 — fix: remove idle blankspace below agent panel (#239) +- 6a9af95 — docs(ai-team): Merge quality directive into team decisions +- 8d4490b — fix: harden flaky tests (EBUSY retry + init speed gate headroom) +- 363a0a8 — feat: Structured model preference & squad-level defaults (#245) +- a488eb8 — fix: wire missing CLI commands into cli-entry.ts (#244) +- b562ef1 — docs: update fenster history & add model-config decision + +**Uncommitted Changes:** 10 files (all acceptable): +- 4 deleted `.squad/decisions/inbox/` files (cleanup, merged to decisions.md) +- 6 untracked images (pilotswarm-*.png — documentation assets) +- 1 untracked `docs/proposals/repl-replacement-prd.md` (draft proposal) + +**Status:** Clean. No staged changes that would block release. + + +--- + +## Open Blockers ⚠️ P0 + +### #247 — Squad Installation Fails 🔴 **CRITICAL BLOCKER** + +**Impact:** Users cannot install via `npm install -g @bradygaster/squad-cli`. +**Assignee:** Fenster (actively fixing) +**Status:** In progress +**Release Impact:** **SHIP CANNOT PROCEED** until resolved. + +**Other Open Issues:** +- #248 — CLI command wiring: `squad triage` does not trigger team assignment loop (minor) +- #242 — Future: Tiered Squad Deployment (deferred, not blocking) +- #241 — New Squad Member for Docs (deferred) +- #240 — ADO configurable work item types (deferred) +- #236 — feat: persistent Ralph (deferred) +- #211 — Squad management paradigms (deferred, release:defer label) + +**Release Blockers:** Only #247 prevents shipping. + + +--- + +## CHANGELOG Review 📝 + +**Current `Unreleased` section covers:** + +### Added — SDK-First Mode (Phase 1) +- Builder functions (defineTeam, defineAgent, defineRouting, defineCeremony, defineHooks, defineCasting, defineTelemetry, defineSquad) +- `squad build` command with --check, --dry-run, --watch flags +- SDK Mode Detection in Coordinator prompt +- Documentation (SDK-First Mode guide, updated SDK Reference, README quick reference) + +### Added — Remote Squad Mode (ported from @spboyer PR #131) +- `resolveSquadPaths()` dual-root resolver +- `squad doctor` command (9-check setup validation) +- `squad link ` command +- `squad init --mode remote` +- `ensureSquadPathDual()` / `ensureSquadPathResolved()` + +### Changed — Distribution & Versioning +- npm-only distribution (no more GitHub-native `npx github:bradygaster/squad`) +- Semantic Versioning fix (X.Y.Z-preview.N format, compliant with semver spec) +- Version transition from public repo (0.8.5.1) to private repo (0.8.x cadence) + +### Fixed +- CLI entry point moved from dist/index.js → dist/cli-entry.js +- CRLF normalization for Windows users +- process.exit() removed from library functions (VS Code extension safe) +- Removed .squad branch protection guard + + +--- + +## Test Status 🟡 + +``` +Test Files: 9 failed | 134 passed (143) +Tests: 19 failed | 3718 passed | 3 todo (3740) +Duration: 80.06s +``` + +**Failures:** All 19 failures are pre-existing UI test timeouts (TerminalHarness spawn issues, not regressions): +- speed-gates.test.ts — 1 timeout +- ux-gates.test.ts — 3 timeouts +- acceptance.test.ts — 8 timeouts +- acceptance/hostile.test.ts — 3 timeouts +- cli/consult.test.ts — 1 timeout + +**Assessment:** Passing rate is strong (99.5% pass rate). Timeouts are environmental (not code regressions). Safe to ship with this test state. + + +--- + +## CI State ✅ + +- **Linting:** ✅ PASS (tsc --noEmit clean on both packages) +- **Build:** ✅ PASS (npm run build succeeds) +- **Tests:** 🟡 PASS (99.5% passing, pre-existing flakes) + + +--- + +## Release Prep Checklist + +- [x] Version strings aligned (0.8.21-preview.7) +- [x] Git state clean (no staged changes) +- [x] Linting passes +- [x] Tests mostly passing (pre-existing flakes only) +- [x] CHANGELOG updated (Unreleased section comprehensive) +- [ ] **#247 resolved (BLOCKER)** +- [ ] Branch merge strategy decided (dev → insiders? or dev → main?) +- [ ] npm publish command prepared + + +--- + +## Merge Strategy + +**Current branches:** +- `main` — stable baseline +- `dev` — integration branch (23 commits ahead of main) +- `insiders` — exists (used for pre-release channel?) + +**Recommendation:** +1. Hold on npm publish until #247 fixed +2. Merge dev → insiders for pre-release testing +3. After QA pass, merge dev → main +4. Tag main as `v0.8.21-preview.7` on npm +5. Consider promoting to `v0.8.21` stable if no further issues + + +--- + +## Draft CHANGELOG Entry for v0.8.21 + +When releasing, move "Unreleased" to versioned section: + +```markdown +## [0.8.21-preview.7] - 2026-03-07 + +### Added — SDK-First Mode (Phase 1) +- [builder functions list] +- [squad build command] +- [SDK Mode Detection] +- [Documentation updates] + +### Added — Remote Squad Mode +- [resolver + commands] + +### Changed — Distribution & Versioning +- [npm-only, semver fix, version transition] + +### Fixed +- [CLI entry point, CRLF, process.exit, branch guard] +``` + + +--- + +## Decision + +**VERDICT: 🟡 RELEASE v0.8.21-preview.7 AFTER #247 FIXED** + +- **GO:** Linting, tests, version alignment all sound. +- **HOLD:** #247 installation failure must be resolved. This is a P0 blocker. +- **ACTION:** Fenster owns #247 fix. Once merged to dev, rerun tests and ship. +- **TIMELINE:** 1–2 hours (estimate: Fenster's ETA on #247). + +**Owner:** Brady (approves final npm publish) +**Fallback:** If #247 unresolvable today, defer to v0.8.22 and open a retro ticket. + + +--- + +## Notes + +- **Community PRs:** 3 community PRs merged cleanly to dev (PR #217, #219, #230). Fork-first contributor workflow is working. +- **Wave planning:** 11 issues targeted for v0.8.22 (5 fix-now + 6 next-wave). 11 deferred to v0.8.23+. +- **Architecture:** SDK/CLI split is clean. Distribution to npm is working. Type safety (strict: true) enforced across both packages. +- **Proposal workflow:** Working as designed. No surprises. + + + +# Decision: Optionalize OpenTelemetry Dependency + +## Context +Telemetry is valuable but should not be a hard requirement for running the SDK. Users in air-gapped environments or minimal setups experienced crashes when `@opentelemetry/api` was missing or incompatible. + +## Decision +We have wrapped `@opentelemetry/api` in a resilient shim (`packages/squad-sdk/src/runtime/otel-api.ts`) and moved the package to `optionalDependencies`. + +### Mechanics +- **Runtime detection:** The wrapper attempts to load `@opentelemetry/api`. +- **Graceful fallback:** If loading fails, it exports no-op implementations of `trace`, `metrics`, and `diag` that match the API surface used by Squad. +- **Developer experience:** Internal code imports from `./runtime/otel-api.ts` instead of the package directly. + +## Consequences +- **Positive:** SDK is robust against missing telemetry dependencies. Installation size is smaller for users who opt out. +- **Negative:** We must maintain the wrapper's type compatibility with the real API. +- **Risk:** If we use new OTel features, we must update the no-op implementation. + +## Status +Accepted and implemented in v0.8.21. + + +# Decision: v0.8.21 Blog Post Scope — SDK-First + Full Release Wave + +**Date:** 2026-03-11 +**Author:** McManus (DevRel) +**Impact:** External communication, developer discovery, release narrative + +## Problem + +v0.8.21 is a major release with TWO significant storylines: +1. **SDK-First Mode** — TypeScript-first authoring, type safety, `squad build` command +2. **Stability Wave** — 26 issues closed, 16 PRs merged, critical crash fix (#247), 3,724 passing tests + +Risk: If blog only emphasizes SDK-First, users miss critical stability improvements (crash fix, Windows hardening, test reliability). If blog buries SDK-First, flagship feature loses visibility. + +## Decision + +Create TWO complementary blog posts with clear ownership: + +1. **`024-v0821-sdk-first-release.md`** (existing) — SDK-First deep dive + - Target: TypeScript-focused teams, SDK adopters + - Scope: Builders, quick start, Azure Function sample, Phase 2/3 roadmap + - Tone: Educational, patterns-focused + +2. **`025-v0821-comprehensive-release.md`** (new) — Full release wave summary + - Target: General audience, release notes consumers + - Scope: All 7 feature areas (SDK-First + Remote Squad + 5 critical fixes), metrics, community credits + - Tone: Reassuring (crash fixed!), factual (26 issues, 0 logic failures) + +**Cross-linking strategy:** +- Comprehensive post links to SDK-First deep dive: "For detailed SDK patterns, see [v0.8.21: SDK-First Mode post](./024-v0821-sdk-first-release.md)" +- SDK-First post references comprehensive post: "For the full release notes, see [v0.8.21: The Complete Release post](./025-v0821-comprehensive-release.md)" + +**CHANGELOG updated once** at `[0.8.21]` section with full scope (all 7 areas) — serves as single source of truth for condensed release info. + +## Rationale + +- **SDK value**: Highlights TypeScript-first workflow, type safety, Azure serverless patterns +- **Stability value**: Installation crash fix alone justifies a major release (user pain elimination) +- **Audience segmentation**: Developers interested in SDK config patterns → read post #024; DevOps/team leads reading release notes → read post #025 +- **SEO/discovery**: Two articles = more surface area for search + internal linking +- **Archive preservation**: Both posts preserved in `docs/blog/` for historical record + +## Alternative Rejected + +**Single mega-post:** Would be 25+ KB, overwhelming, diffuses message (SDK patterns + crash fix + CI stability = scattered narrative). Two posts with clear focus are easier to scan and share. + +## Enforcement + +- CHANGELOG.md single `[0.8.21]` section (source of truth) +- Blog post #025 designated "comprehensive" (headline for external comms) +- Blog post #024 designated "technical deep dive" (for SDK adopters) +- Release announcement on GitHub uses post #025 as primary link + + +--- + +**Decided by:** McManus (DevRel) on behalf of tone ceiling + messaging coherence +**Reviewed by:** Internal tone ceiling check (substantiated claims, no hype, clear value messaging) + + +### 2026-03-07 07:51 UTC: SDK-First init/migrate deferred to v0.8.22 +**By:** Keaton (Coordinator), Brady absent - autonomous decision +**What:** SDK-First mode gaps (init --sdk flag, standalone migrate command, comprehensive docs) deferred to v0.8.22. +**Why:** v0.8.21 has all P0 blockers resolved. Adding features now risks regression. Filed #249, #250, #251. +**Issues filed:** +- #249: squad init --sdk flag for SDK-First mode opt-in +- #250: standalone squad migrate command (subsumes #231) +- #251: comprehensive SDK-First mode documentation + + +### 2026-03-07T08-14-43Z: User directive +**By:** Brady (via Copilot) +**What:** Issues #249, #250, and #251 (SDK-First init --sdk flag, standalone migrate command, comprehensive SDK-First docs) are committed to v0.8.22 - not backlog, not optional. +**Why:** User request - captured for team memory + + +### 2026-03-07T16-19-00Z: Pre-release triage — v0.8.21 release ready pending #248 fix +**By:** Keaton (Lead) +**What:** Analyzed all 23 open issues. Result: v0.8.21 releases cleanly pending fix for #248 (triage team dispatch). v0.8.22 roadmap is well-scoped (9 issues, 3 parallel streams). Close #194 (completed) and #231 (duplicate). +**Why:** Final release gate. Coordinator override: #248 deferred to v0.8.22 (standalone CLI feature, not core to interactive experience). Keeps release unblocked. +**Details:** 2 closeable, 1 P0 override, 9 for v0.8.22, 5 for v0.8.23+, 1 for v0.9+, 4 backlog. See .squad/orchestration-log/2026-03-07T16-19-00Z-keaton.md for full triage table. + +### 2026-03-07T16-19-00Z: PR hold decision — #189 (workstreams) and #191 (ADO) rebase to dev for v0.8.22 +**By:** Hockney (Tester) +**What:** Both PRs are held for v0.8.22 and must rebase from main to dev. Neither ships for v0.8.21. +**Why:** PR #189: merge conflicts, no CI, process.exit() violation, missing CLI tests, 6 unresolved review threads. PR #191: merge conflicts, no CI, untested security fixes, incomplete Planner adapter. Both have solid architecture but insufficient readiness for v0.8.21. +**Details:** See .squad/orchestration-log/2026-03-07T16-19-00Z-hockney.md for detailed code assessment. + +### 2026-03-07T16-19-00Z: Docs ready for v0.8.21 — no release blockers +**By:** McManus (DevRel) +**What:** v0.8.21 documentation is ship-ready. SDK-First mode guide (705 lines), What's New blog, CHANGELOG, and contributors section all complete. No blocking gaps. +**Why:** Release readiness gate. Docs are complete for Phase 1. Minor gaps are non-blocking and addressed in v0.8.22 roadmap. +**Details:** 2 docs issues queued for v0.8.22 (#251 restructure, #210 contributors workflow). See .squad/orchestration-log/2026-03-07T16-19-00Z-mcmanus.md for full triage. + +### 2026-03-07T16:20: User directive — Shift from Actions to CLI +**By:** Brady (via Copilot) +**What:** "I'm seriously concerned about our continued abuse of actions and think the more we can stop relying on actions to do things and start relying on the cli to do things, it puts more emphasis and control in the user's hand and less automation with actions. I think we're maybe going to surprise customers with some of the usage in actions and I would really hate for that to be a deterrent from using squad." +**Why:** User directive — strategic direction for the product. Actions usage can surprise customers with unexpected billing and loss of control. CLI-first puts the user in the driver's seat. + +### Current Actions Inventory (15 workflows) + +**Squad-specific (customer concern):** +1. `sync-squad-labels.yml` — Auto-syncs labels from team.md on push +2. `squad-triage.yml` — Auto-triages issues when labeled "squad" +3. `squad-issue-assign.yml` — Auto-assigns issues when squad:{member} labeled +4. `squad-heartbeat.yml` — Ralph heartbeat/auto-triage (cron currently disabled) +5. `squad-label-enforce.yml` — Label mutual exclusivity on label events + +**Standard CI/Release (expected):** +6. `squad-ci.yml` — Standard PR/push CI +7. `squad-release.yml` — Tag + release on push to main +8. `squad-promote.yml` — Branch promotion (workflow_dispatch) +9. `squad-main-guard.yml` — Forbidden file guard +10. `squad-preview.yml` — Preview validation +11. `squad-docs.yml` — Docs build/deploy +12-15. Publish/insider workflows + +**Directive:** Move squad-specific automation (1-5) into CLI commands. Keep standard CI/release workflows. + +### 2026-03-07T16:20: User directive — Shift from Actions to CLI +**By:** Brady (via Copilot) +**What:** "I'm seriously concerned about our continued abuse of actions and think the more we can stop relying on actions to do things and start relying on the cli to do things, it puts more emphasis and control in the user's hand and less automation with actions. I think we're maybe going to surprise customers with some of the usage in actions and I would really hate for that to be a deterrent from using squad." +**Why:** User directive — strategic direction for the product. Actions usage can surprise customers with unexpected billing and loss of control. CLI-first puts the user in the driver's seat. + +### Current Actions Inventory (15 workflows) + +**Squad-specific (customer concern):** +1. `sync-squad-labels.yml` — Auto-syncs labels from team.md on push +2. `squad-triage.yml` — Auto-triages issues when labeled "squad" +3. `squad-issue-assign.yml` — Auto-assigns issues when squad:{member} labeled +4. `squad-heartbeat.yml` — Ralph heartbeat/auto-triage (cron currently disabled) +5. `squad-label-enforce.yml` — Label mutual exclusivity on label events + +**Standard CI/Release (expected):** +6. `squad-ci.yml` — Standard PR/push CI +7. `squad-release.yml` — Tag + release on push to main +8. `squad-promote.yml` — Branch promotion (workflow_dispatch) +9. `squad-main-guard.yml` — Forbidden file guard +10. `squad-preview.yml` — Preview validation +11. `squad-docs.yml` — Docs build/deploy +12-15. Publish/insider workflows + +**Directive:** Move squad-specific automation (1-5) into CLI commands. Keep standard CI/release workflows. + +### Follow-up (Brady, same session): +> "seems like the more we can offload to ourselves, the more we could control, say, in a container. if actions are doing the work the loop is outside of our control a bit" + +**Key insight:** CLI-first makes Squad **portable**. If the work lives in CLI commands instead of Actions, Squad can run anywhere — Codespaces, devcontainers, local terminals, persistent ACA containers. Actions lock the control loop to GitHub's event system. CLI-first means the user (or their infrastructure) owns the execution loop, not GitHub Actions. + + +# CLI Feasibility Assessment — GitHub Actions → CLI Commands +**Author:** Fenster (Core Dev) +**Date:** 2026-03-07 +**Context:** Brady's request to migrate squad-specific workflows to CLI commands + + +--- + +## Executive Summary + +**Quick wins:** Label sync + label enforce can ship in v0.8.22 (reuses existing parsers, zero new deps). +**Medium effort:** Triage command is 70% done (CLI watch already exists), needs GitHub comment posting. +**Heavy lift:** Issue assign + heartbeat need copilot-swe-agent[bot] API (PAT + agent_assignment field) — no `gh` CLI equivalent exists. Watch mode already implements heartbeat's core logic locally. + +**Key insight:** We already have `squad watch` — it's the local equivalent of `squad-heartbeat.yml`. The workflow runs in GitHub Actions with PAT; watch runs locally with `gh` CLI. They share the same triage logic (`@bradygaster/squad-sdk/ralph/triage`). + + +--- + +## 1. Current CLI Command Inventory + +**Existing commands** (`packages/squad-cli/src/cli/commands/`): + +| Command | Function | Overlap with Workflows | +|---------|----------|------------------------| +| **watch** | Ralph's local polling — triages issues, monitors PRs, assigns labels. Uses `gh` CLI. | ✅ 80% overlap with `squad-heartbeat.yml` + `squad-triage.yml` | +| plugin | Marketplace add/remove. Uses `gh` CLI for repo access. | ❌ No workflow overlap | +| export | Export squad state to JSON. | ❌ No workflow overlap | +| import | Import squad state from JSON. | ❌ No workflow overlap | +| build | SDK config generation. | ❌ No workflow overlap | +| doctor | Health checks (local/remote/hub). | ❌ No workflow overlap | +| aspire | Launch Aspire dashboard for OTel. | ❌ No workflow overlap | +| start | Interactive shell (Coordinator mode). | ❌ No workflow overlap | +| consult | Spawn agent for consultation. | ❌ No workflow overlap | +| rc/rc-tunnel | Remote control server + devtunnel. | ❌ No workflow overlap | +| copilot/copilot-bridge | Copilot SDK adapter. | ❌ No workflow overlap | +| link/init-remote | Link to remote squad repo. | ❌ No workflow overlap | +| streams | Workstream commands (stub). | ❌ No workflow overlap | + +**Key reusable infrastructure:** +- **`gh-cli.ts`** — Thin wrapper around `gh` CLI: `ghIssueList`, `ghIssueEdit`, `ghPrList`, `ghAvailable`, `ghAuthenticated` +- **`@bradygaster/squad-sdk/ralph/triage`** — Shared triage logic (routing rules, module ownership, keyword matching) +- **`watch.ts`** — Already implements triage cycle + PR monitoring + + +--- + +## 2. Per-Workflow Migration Plan + +### 2.1. sync-squad-labels.yml → `squad labels sync` + +**Current workflow:** 170 lines. Parses `team.md`, syncs `squad`, `squad:{member}`, `go:*`, `release:*`, `type:*`, `priority:*`, `bug`, `feedback` labels. Uses Octokit. + +**Proposed CLI command:** +```bash +squad labels sync [--squad-dir .squad] [--dry-run] +``` + +**Implementation:** +- **Size:** S (2-3 hours) +- **Dependencies:** + - ✅ `gh` CLI (already used in plugin.ts, watch.ts) + - ✅ `parseRoster()` from `@bradygaster/squad-sdk/parsers` (already exists) + - ✅ Thin wrapper — reuse roster parser, call `gh label create/edit` +- **Offline:** ❌ Needs GitHub API access via `gh` +- **Reuse:** Roster parsing (team.md → member list) already exists. Just needs label creation loop with `gh`. +- **Complexity:** Low. No auth complexity (uses `gh auth` flow). No copilot-swe-agent API. + +**Why quick win:** Zero new parsers needed. Label sync is idempotent (create-or-update pattern). Can run manually after `team.md` changes. + + +--- + +### 2.2. squad-triage.yml → `squad triage` (or extend `squad watch`) + +**Current workflow:** 260 lines. On `squad` label, parses `team.md` + `routing.md`, keyword-matches, applies `squad:{member}` label, posts comment. + +**Proposed CLI command:** +```bash +squad triage [--issue ] [--squad-dir .squad] +``` +Or: enhance `squad watch` to post comments (currently it only adds labels). + +**Implementation:** +- **Size:** M (4-6 hours) +- **Dependencies:** + - ✅ `gh` CLI (already used) + - ✅ `triageIssue()` from `@bradygaster/squad-sdk/ralph/triage` (already used in watch.ts) + - ❌ **Missing:** `gh issue comment` wrapper in `gh-cli.ts` (5 lines to add) +- **Offline:** ❌ Needs GitHub API +- **Reuse:** + - **watch.ts already does this** (line 189-209). Just missing comment posting. + - Triage logic, routing rules, module ownership — all implemented. +- **Complexity:** Low. The logic exists; just needs `gh issue comment --body ` wrapper. + +**Why medium effort:** Code exists. Just needs comment posting feature added to `gh-cli.ts` and called from `watch.ts`. + + +--- + +### 2.3. squad-issue-assign.yml → ??? + +**Current workflow:** 160 lines. On `squad:{member}` label, posts assignment comment, calls **copilot-swe-agent[bot] assignment API with PAT** (lines 116-161). + +**Problem:** The workflow uses a special POST endpoint: +```js +POST /repos/{owner}/{repo}/issues/{issue_number}/assignees +{ + assignees: ['copilot-swe-agent[bot]'], + agent_assignment: { + target_repo: `${owner}/${repo}`, + base_branch: baseBranch, + custom_instructions: '', + custom_agent: '', + model: '' + } +} +``` +**This endpoint does NOT exist in `gh` CLI.** It requires: +- Personal Access Token (PAT) with `issues:write` scope +- Direct Octokit call (cannot use `gh` as thin wrapper) + +**Migration options:** +1. **Add Octokit dependency** — heavyweight (35+ deps), violates zero-dependency CLI goal +2. **Add raw HTTPS module** — 50-100 lines to make authenticated POST with PAT, parse JSON response +3. **Document manual workflow** — "To auto-assign @copilot, use the GitHub Actions workflow (requires PAT)" + +**Proposed approach:** +- **Do NOT migrate.** Keep as workflow-only feature. +- **Reasoning:** The copilot-swe-agent assignment API is GitHub-specific and requires secrets (PAT). CLI commands should not manage secrets. Workflows already have secure secret storage. +- **Alternative:** Document `squad watch` as the local equivalent (it can label + post comments, but not trigger bot assignment). + +**Implementation:** +- **Size:** XL (8-12 hours if full migration) +- **Dependencies:** + - ❌ PAT management (needs secret storage or prompting) + - ❌ Octokit or raw HTTPS POST wrapper (50-100 lines) + - ❌ Not available in `gh` CLI +- **Offline:** ❌ Never (GitHub-specific API) +- **Complexity:** High. Requires secret handling, bot assignment API, error handling, fallback. + +**Recommendation:** **Do not migrate.** Keep as workflow. Document that copilot auto-assign requires Actions + PAT. + + +--- + +### 2.4. squad-heartbeat.yml → Already exists as `squad watch` + +**Current workflow:** 170 lines. Runs on cron (disabled), issues closed/labeled, PRs closed. Triages untriaged issues, assigns @copilot to `squad:copilot` issues. + +**CLI equivalent:** **Already shipped as `squad watch`** (`packages/squad-cli/src/cli/commands/watch.ts`, 356 lines). + +**What `squad watch` does:** +- Polls open issues with `squad` label +- Triages untriaged issues (adds `squad:{member}` label) +- Monitors PRs (draft/needs-review/changes-requested/CI failures/ready-to-merge) +- Runs on interval (default: 30 minutes) +- Uses `gh` CLI for auth + API access +- Uses shared `@bradygaster/squad-sdk/ralph/triage` logic + +**What `squad watch` does NOT do (that heartbeat.yml does):** +- ❌ Post triage comments (workflow posts "Ralph — Auto-Triage" comments) +- ❌ Auto-assign copilot-swe-agent[bot] (requires PAT + bot API, same issue as #2.3) + +**Implementation gap:** +- **Comment posting:** M (4-6 hours) — add `gh issue comment` wrapper to `gh-cli.ts`, call it from `runCheck()` in watch.ts +- **Copilot auto-assign:** Do not migrate (same as #2.3) + +**Migration plan:** +- ✅ **Already done.** `squad watch` is the local heartbeat. +- **Add comment posting** to match workflow behavior (quick win, 4-6 hours). +- **Document copilot auto-assign** as workflow-only (requires PAT). + +**Recommendation:** Enhance `squad watch` with comment posting. Keep copilot auto-assign in workflow. + + +--- + +### 2.5. squad-label-enforce.yml → `squad labels enforce` + +**Current workflow:** 180 lines. On label applied, removes conflicting labels from mutual-exclusivity namespaces (`go:`, `release:`, `type:`, `priority:`). Posts update comment. + +**Proposed CLI command:** +```bash +squad labels enforce [--issue ] [--squad-dir .squad] +``` + +**Implementation:** +- **Size:** S (2-4 hours) +- **Dependencies:** + - ✅ `gh` CLI (already used) + - ❌ `gh issue edit --remove-label