@bradygaster/squad-cli 0.9.1 → 0.9.2-insider.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +329 -329
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +10 -10
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/config.d.ts +12 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +157 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/consult.d.ts.map +1 -1
- package/dist/cli/commands/consult.js +9 -4
- package/dist/cli/commands/consult.js.map +1 -1
- package/dist/cli/commands/copilot.d.ts.map +1 -1
- package/dist/cli/commands/copilot.js +8 -7
- package/dist/cli/commands/copilot.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +50 -17
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/economy.d.ts.map +1 -1
- package/dist/cli/commands/economy.js +3 -2
- package/dist/cli/commands/economy.js.map +1 -1
- package/dist/cli/commands/export.d.ts.map +1 -1
- package/dist/cli/commands/export.js +22 -16
- package/dist/cli/commands/export.js.map +1 -1
- package/dist/cli/commands/extract.d.ts.map +1 -1
- package/dist/cli/commands/extract.js +14 -10
- package/dist/cli/commands/extract.js.map +1 -1
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +21 -18
- package/dist/cli/commands/import.js.map +1 -1
- package/dist/cli/commands/init-remote.d.ts.map +1 -1
- package/dist/cli/commands/init-remote.js +7 -6
- package/dist/cli/commands/init-remote.js.map +1 -1
- package/dist/cli/commands/link.d.ts.map +1 -1
- package/dist/cli/commands/link.js +11 -10
- package/dist/cli/commands/link.js.map +1 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +19 -18
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/cli/commands/personal.d.ts.map +1 -1
- package/dist/cli/commands/personal.js +57 -65
- package/dist/cli/commands/personal.js.map +1 -1
- package/dist/cli/commands/plugin.d.ts.map +1 -1
- package/dist/cli/commands/plugin.js +8 -7
- package/dist/cli/commands/plugin.js.map +1 -1
- package/dist/cli/commands/rc.d.ts.map +1 -1
- package/dist/cli/commands/rc.js +19 -12
- package/dist/cli/commands/rc.js.map +1 -1
- package/dist/cli/commands/schedule.d.ts.map +1 -1
- package/dist/cli/commands/schedule.js +6 -5
- package/dist/cli/commands/schedule.js.map +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +18 -11
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/streams.d.ts.map +1 -1
- package/dist/cli/commands/streams.js +3 -2
- package/dist/cli/commands/streams.js.map +1 -1
- package/dist/cli/commands/upstream.d.ts.map +1 -1
- package/dist/cli/commands/upstream.js +23 -19
- package/dist/cli/commands/upstream.js.map +1 -1
- package/dist/cli/commands/watch/capabilities/board.d.ts +22 -0
- package/dist/cli/commands/watch/capabilities/board.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/board.js +121 -0
- package/dist/cli/commands/watch/capabilities/board.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/decision-hygiene.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/decision-hygiene.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/decision-hygiene.js +72 -0
- package/dist/cli/commands/watch/capabilities/decision-hygiene.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/execute.d.ts +33 -0
- package/dist/cli/commands/watch/capabilities/execute.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/execute.js +119 -0
- package/dist/cli/commands/watch/capabilities/execute.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/index.d.ts +7 -0
- package/dist/cli/commands/watch/capabilities/index.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/index.js +28 -0
- package/dist/cli/commands/watch/capabilities/index.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/monitor-email.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/monitor-email.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/monitor-email.js +54 -0
- package/dist/cli/commands/watch/capabilities/monitor-email.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/monitor-teams.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/monitor-teams.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/monitor-teams.js +55 -0
- package/dist/cli/commands/watch/capabilities/monitor-teams.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/retro.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/retro.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/retro.js +81 -0
- package/dist/cli/commands/watch/capabilities/retro.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/self-pull.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/self-pull.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/self-pull.js +33 -0
- package/dist/cli/commands/watch/capabilities/self-pull.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/two-pass.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/two-pass.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/two-pass.js +66 -0
- package/dist/cli/commands/watch/capabilities/two-pass.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/wave-dispatch.d.ts +14 -0
- package/dist/cli/commands/watch/capabilities/wave-dispatch.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/wave-dispatch.js +117 -0
- package/dist/cli/commands/watch/capabilities/wave-dispatch.js.map +1 -0
- package/dist/cli/commands/watch/config.d.ts +25 -0
- package/dist/cli/commands/watch/config.d.ts.map +1 -0
- package/dist/cli/commands/watch/config.js +82 -0
- package/dist/cli/commands/watch/config.js.map +1 -0
- package/dist/cli/commands/watch/index.d.ts +95 -0
- package/dist/cli/commands/watch/index.d.ts.map +1 -0
- package/dist/cli/commands/watch/index.js +704 -0
- package/dist/cli/commands/watch/index.js.map +1 -0
- package/dist/cli/commands/watch/registry.d.ts +19 -0
- package/dist/cli/commands/watch/registry.d.ts.map +1 -0
- package/dist/cli/commands/watch/registry.js +28 -0
- package/dist/cli/commands/watch/registry.js.map +1 -0
- package/dist/cli/commands/watch/types.d.ts +57 -0
- package/dist/cli/commands/watch/types.d.ts.map +1 -0
- package/dist/cli/commands/watch/types.js +8 -0
- package/dist/cli/commands/watch/types.js.map +1 -0
- package/dist/cli/core/cast.d.ts.map +1 -1
- package/dist/cli/core/cast.js +15 -19
- package/dist/cli/core/cast.js.map +1 -1
- package/dist/cli/core/detect-squad-dir.d.ts.map +1 -1
- package/dist/cli/core/detect-squad-dir.js +12 -10
- package/dist/cli/core/detect-squad-dir.js.map +1 -1
- package/dist/cli/core/email-scrub.d.ts.map +1 -1
- package/dist/cli/core/email-scrub.js +12 -11
- package/dist/cli/core/email-scrub.js.map +1 -1
- package/dist/cli/core/gh-cli.d.ts +13 -0
- package/dist/cli/core/gh-cli.d.ts.map +1 -1
- package/dist/cli/core/gh-cli.js +24 -0
- package/dist/cli/core/gh-cli.js.map +1 -1
- package/dist/cli/core/init.d.ts +2 -0
- package/dist/cli/core/init.d.ts.map +1 -1
- package/dist/cli/core/init.js +22 -5
- package/dist/cli/core/init.js.map +1 -1
- package/dist/cli/core/migrate-directory.d.ts.map +1 -1
- package/dist/cli/core/migrate-directory.js +14 -13
- package/dist/cli/core/migrate-directory.js.map +1 -1
- package/dist/cli/core/migrations.d.ts.map +1 -1
- package/dist/cli/core/migrations.js +22 -8
- package/dist/cli/core/migrations.js.map +1 -1
- package/dist/cli/core/nap.d.ts.map +1 -1
- package/dist/cli/core/nap.js +111 -49
- package/dist/cli/core/nap.js.map +1 -1
- package/dist/cli/core/project-type.d.ts.map +1 -1
- package/dist/cli/core/project-type.js +11 -10
- package/dist/cli/core/project-type.js.map +1 -1
- package/dist/cli/core/team-md.d.ts.map +1 -1
- package/dist/cli/core/team-md.js +43 -38
- package/dist/cli/core/team-md.js.map +1 -1
- package/dist/cli/core/templates.d.ts.map +1 -1
- package/dist/cli/core/templates.js +4 -3
- package/dist/cli/core/templates.js.map +1 -1
- package/dist/cli/core/upgrade.d.ts.map +1 -1
- package/dist/cli/core/upgrade.js +68 -55
- package/dist/cli/core/upgrade.js.map +1 -1
- package/dist/cli/core/version.d.ts.map +1 -1
- package/dist/cli/core/version.js +8 -7
- package/dist/cli/core/version.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/self-update.d.ts.map +1 -1
- package/dist/cli/self-update.js +7 -4
- package/dist/cli/self-update.js.map +1 -1
- package/dist/cli/shell/agent-name-parser.d.ts +16 -0
- package/dist/cli/shell/agent-name-parser.d.ts.map +1 -0
- package/dist/cli/shell/agent-name-parser.js +54 -0
- package/dist/cli/shell/agent-name-parser.js.map +1 -0
- package/dist/cli/shell/commands.d.ts.map +1 -1
- package/dist/cli/shell/commands.js +4 -3
- package/dist/cli/shell/commands.js.map +1 -1
- package/dist/cli/shell/coordinator.d.ts +4 -1
- package/dist/cli/shell/coordinator.d.ts.map +1 -1
- package/dist/cli/shell/coordinator.js +29 -26
- package/dist/cli/shell/coordinator.js.map +1 -1
- package/dist/cli/shell/index.d.ts.map +1 -1
- package/dist/cli/shell/index.js +33 -35
- package/dist/cli/shell/index.js.map +1 -1
- package/dist/cli/shell/lifecycle.d.ts +13 -2
- package/dist/cli/shell/lifecycle.d.ts.map +1 -1
- package/dist/cli/shell/lifecycle.js +26 -13
- package/dist/cli/shell/lifecycle.js.map +1 -1
- package/dist/cli/shell/session-store.d.ts.map +1 -1
- package/dist/cli/shell/session-store.js +16 -12
- package/dist/cli/shell/session-store.js.map +1 -1
- package/dist/cli/shell/spawn.d.ts +4 -1
- package/dist/cli/shell/spawn.d.ts.map +1 -1
- package/dist/cli/shell/spawn.js +28 -10
- package/dist/cli/shell/spawn.js.map +1 -1
- package/dist/cli-entry.js +83 -12
- package/dist/cli-entry.js.map +1 -1
- package/package.json +8 -4
- package/scripts/patch-esm-imports.mjs +105 -105
- package/scripts/patch-ink-rendering.mjs +115 -115
- package/templates/casting/Futurama.json +9 -9
- package/templates/casting-history.json +4 -4
- package/templates/casting-policy.json +37 -37
- package/templates/casting-reference.md +104 -104
- package/templates/casting-registry.json +3 -3
- package/templates/ceremonies.md +41 -41
- package/templates/charter.md +53 -53
- package/templates/constraint-tracking.md +38 -38
- package/templates/cooperative-rate-limiting.md +229 -229
- package/templates/copilot-instructions.md +46 -46
- package/templates/history.md +10 -10
- package/templates/identity/now.md +9 -9
- package/templates/identity/wisdom.md +15 -15
- package/templates/issue-lifecycle.md +412 -412
- package/templates/keda-scaler.md +164 -164
- package/templates/machine-capabilities.md +74 -74
- package/templates/mcp-config.md +90 -90
- package/templates/multi-agent-format.md +28 -28
- package/templates/orchestration-log.md +27 -27
- package/templates/plugin-marketplace.md +49 -49
- package/templates/ralph-circuit-breaker.md +313 -313
- package/templates/raw-agent-output.md +37 -37
- package/templates/roster.md +60 -60
- package/templates/routing.md +39 -39
- package/templates/run-output.md +50 -50
- package/templates/scribe-charter.md +123 -119
- package/templates/skill.md +24 -24
- package/templates/skills/agent-collaboration/SKILL.md +42 -42
- package/templates/skills/agent-conduct/SKILL.md +24 -24
- package/templates/skills/architectural-proposals/SKILL.md +151 -151
- package/templates/skills/ci-validation-gates/SKILL.md +84 -84
- package/templates/skills/cli-wiring/SKILL.md +47 -47
- package/templates/skills/client-compatibility/SKILL.md +89 -89
- package/templates/skills/cross-machine-coordination/SKILL.md +434 -0
- package/templates/skills/cross-squad/SKILL.md +114 -114
- package/templates/skills/distributed-mesh/SKILL.md +287 -287
- package/templates/skills/distributed-mesh/mesh.json.example +30 -30
- package/templates/skills/distributed-mesh/sync-mesh.ps1 +111 -111
- package/templates/skills/distributed-mesh/sync-mesh.sh +104 -104
- package/templates/skills/docs-standards/SKILL.md +71 -71
- package/templates/skills/economy-mode/SKILL.md +114 -114
- package/templates/skills/error-recovery/SKILL.md +99 -0
- package/templates/skills/external-comms/SKILL.md +329 -329
- package/templates/skills/gh-auth-isolation/SKILL.md +183 -183
- package/templates/skills/git-workflow/SKILL.md +204 -204
- package/templates/skills/github-multi-account/SKILL.md +95 -95
- package/templates/skills/history-hygiene/SKILL.md +36 -36
- package/templates/skills/humanizer/SKILL.md +105 -105
- package/templates/skills/init-mode/SKILL.md +102 -102
- package/templates/skills/iterative-retrieval/SKILL.md +165 -0
- package/templates/skills/model-selection/SKILL.md +117 -117
- package/templates/skills/nap/SKILL.md +24 -24
- package/templates/skills/notification-routing/SKILL.md +105 -0
- package/templates/skills/personal-squad/SKILL.md +57 -57
- package/templates/skills/pr-screenshots/SKILL.md +149 -0
- package/templates/skills/ralph-two-pass-scan/SKILL.md +35 -0
- package/templates/skills/reflect/SKILL.md +229 -0
- package/templates/skills/release-process/SKILL.md +131 -423
- package/templates/skills/reskill/SKILL.md +92 -92
- package/templates/skills/retro-enforcement/SKILL.md +148 -0
- package/templates/skills/reviewer-protocol/SKILL.md +79 -79
- package/templates/skills/secret-handling/SKILL.md +200 -200
- package/templates/skills/session-recovery/SKILL.md +155 -155
- package/templates/skills/squad-conventions/SKILL.md +69 -69
- package/templates/skills/test-discipline/SKILL.md +37 -37
- package/templates/skills/tiered-memory/SKILL.md +234 -0
- package/templates/skills/windows-compatibility/SKILL.md +98 -74
- package/templates/{squad.agent.md → squad.agent.md.template} +1316 -1287
- package/templates/workflows/squad-ci.yml +24 -24
- package/templates/workflows/squad-docs.yml +54 -54
- package/templates/workflows/squad-heartbeat.yml +0 -4
- package/templates/workflows/squad-insider-release.yml +61 -61
- package/templates/workflows/squad-issue-assign.yml +161 -161
- package/templates/workflows/squad-label-enforce.yml +181 -181
- package/templates/workflows/squad-preview.yml +55 -55
- package/templates/workflows/squad-promote.yml +120 -120
- package/templates/workflows/squad-release.yml +77 -77
- package/templates/workflows/squad-triage.yml +260 -260
- package/templates/workflows/sync-squad-labels.yml +169 -169
- package/dist/cli/commands/watch.d.ts +0 -18
- package/dist/cli/commands/watch.d.ts.map +0 -1
- package/dist/cli/commands/watch.js +0 -306
- package/dist/cli/commands/watch.js.map +0 -1
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
# Model Selection
|
|
2
|
-
|
|
3
|
-
> Determines which LLM model to use for each agent spawn.
|
|
4
|
-
|
|
5
|
-
## SCOPE
|
|
6
|
-
|
|
7
|
-
✅ THIS SKILL PRODUCES:
|
|
8
|
-
- A resolved `model` parameter for every `task` tool call
|
|
9
|
-
- Persistent model preferences in `.squad/config.json`
|
|
10
|
-
- Spawn acknowledgments that include the resolved model
|
|
11
|
-
|
|
12
|
-
❌ THIS SKILL DOES NOT PRODUCE:
|
|
13
|
-
- Code, tests, or documentation
|
|
14
|
-
- Model performance benchmarks
|
|
15
|
-
- Cost reports or billing artifacts
|
|
16
|
-
|
|
17
|
-
## Context
|
|
18
|
-
|
|
19
|
-
Squad supports 18+ models across three tiers (premium, standard, fast). The coordinator must select the right model for each agent spawn. Users can set persistent preferences that survive across sessions.
|
|
20
|
-
|
|
21
|
-
## 5-Layer Model Resolution Hierarchy
|
|
22
|
-
|
|
23
|
-
Resolution is **first-match-wins** — the highest layer with a value wins.
|
|
24
|
-
|
|
25
|
-
| Layer | Name | Source | Persistence |
|
|
26
|
-
|-------|------|--------|-------------|
|
|
27
|
-
| **0a** | Per-Agent Config | `.squad/config.json` → `agentModelOverrides.{name}` | Persistent (survives sessions) |
|
|
28
|
-
| **0b** | Global Config | `.squad/config.json` → `defaultModel` | Persistent (survives sessions) |
|
|
29
|
-
| **1** | Session Directive | User said "use X" in current session | Session-only |
|
|
30
|
-
| **2** | Charter Preference | Agent's `charter.md` → `## Model` section | Persistent (in charter) |
|
|
31
|
-
| **3** | Task-Aware Auto | Code → sonnet, docs → haiku, visual → opus | Computed per-spawn |
|
|
32
|
-
| **4** | Default | `claude-haiku-4.5` | Hardcoded fallback |
|
|
33
|
-
|
|
34
|
-
**Key principle:** Layer 0 (persistent config) beats everything. If the user said "always use opus" and it was saved to config.json, every agent gets opus regardless of role or task type. This is intentional — the user explicitly chose quality over cost.
|
|
35
|
-
|
|
36
|
-
## AGENT WORKFLOW
|
|
37
|
-
|
|
38
|
-
### On Session Start
|
|
39
|
-
|
|
40
|
-
1. READ `.squad/config.json`
|
|
41
|
-
2. CHECK for `defaultModel` field — if present, this is the Layer 0 override for all spawns
|
|
42
|
-
3. CHECK for `agentModelOverrides` field — if present, these are per-agent Layer 0a overrides
|
|
43
|
-
4. STORE both values in session context for the duration
|
|
44
|
-
|
|
45
|
-
### On Every Agent Spawn
|
|
46
|
-
|
|
47
|
-
1. CHECK Layer 0a: Is there an `agentModelOverrides.{agentName}` in config.json? → Use it.
|
|
48
|
-
2. CHECK Layer 0b: Is there a `defaultModel` in config.json? → Use it.
|
|
49
|
-
3. CHECK Layer 1: Did the user give a session directive? → Use it.
|
|
50
|
-
4. CHECK Layer 2: Does the agent's charter have a `## Model` section? → Use it.
|
|
51
|
-
5. CHECK Layer 3: Determine task type:
|
|
52
|
-
- Code (implementation, tests, refactoring, bug fixes) → `claude-sonnet-4.6`
|
|
53
|
-
- Prompts, agent designs → `claude-sonnet-4.6`
|
|
54
|
-
- Visual/design with image analysis → `claude-opus-4.6`
|
|
55
|
-
- Non-code (docs, planning, triage, changelogs) → `claude-haiku-4.5`
|
|
56
|
-
6. FALLBACK Layer 4: `claude-haiku-4.5`
|
|
57
|
-
7. INCLUDE model in spawn acknowledgment: `🔧 {Name} ({resolved_model}) — {task}`
|
|
58
|
-
|
|
59
|
-
### When User Sets a Preference
|
|
60
|
-
|
|
61
|
-
**Trigger phrases:** "always use X", "use X for everything", "switch to X", "default to X"
|
|
62
|
-
|
|
63
|
-
1. VALIDATE the model ID against the catalog (18+ models)
|
|
64
|
-
2. WRITE `defaultModel` to `.squad/config.json` (merge, don't overwrite)
|
|
65
|
-
3. ACKNOWLEDGE: `✅ Model preference saved: {model} — all future sessions will use this until changed.`
|
|
66
|
-
|
|
67
|
-
**Per-agent trigger:** "use X for {agent}"
|
|
68
|
-
|
|
69
|
-
1. VALIDATE model ID
|
|
70
|
-
2. WRITE to `agentModelOverrides.{agent}` in `.squad/config.json`
|
|
71
|
-
3. ACKNOWLEDGE: `✅ {Agent} will always use {model} — saved to config.`
|
|
72
|
-
|
|
73
|
-
### When User Clears a Preference
|
|
74
|
-
|
|
75
|
-
**Trigger phrases:** "switch back to automatic", "clear model preference", "use default models"
|
|
76
|
-
|
|
77
|
-
1. REMOVE `defaultModel` from `.squad/config.json`
|
|
78
|
-
2. ACKNOWLEDGE: `✅ Model preference cleared — returning to automatic selection.`
|
|
79
|
-
|
|
80
|
-
### STOP
|
|
81
|
-
|
|
82
|
-
After resolving the model and including it in the spawn template, this skill is done. Do NOT:
|
|
83
|
-
- Generate model comparison reports
|
|
84
|
-
- Run benchmarks or speed tests
|
|
85
|
-
- Create new config files (only modify existing `.squad/config.json`)
|
|
86
|
-
- Change the model after spawn (fallback chains handle runtime failures)
|
|
87
|
-
|
|
88
|
-
## Config Schema
|
|
89
|
-
|
|
90
|
-
`.squad/config.json` model-related fields:
|
|
91
|
-
|
|
92
|
-
```json
|
|
93
|
-
{
|
|
94
|
-
"version": 1,
|
|
95
|
-
"defaultModel": "claude-opus-4.6",
|
|
96
|
-
"agentModelOverrides": {
|
|
97
|
-
"fenster": "claude-sonnet-4.6",
|
|
98
|
-
"mcmanus": "claude-haiku-4.5"
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
- `defaultModel` — applies to ALL agents unless overridden by `agentModelOverrides`
|
|
104
|
-
- `agentModelOverrides` — per-agent overrides that take priority over `defaultModel`
|
|
105
|
-
- Both fields are optional. When absent, Layers 1-4 apply normally.
|
|
106
|
-
|
|
107
|
-
## Fallback Chains
|
|
108
|
-
|
|
109
|
-
If a model is unavailable (rate limit, plan restriction), retry within the same tier:
|
|
110
|
-
|
|
111
|
-
```
|
|
112
|
-
Premium: claude-opus-4.6 → claude-opus-4.6-fast → claude-opus-4.5 → claude-sonnet-4.6
|
|
113
|
-
Standard: claude-sonnet-4.6 → gpt-5.4 → claude-sonnet-4.5 → gpt-5.3-codex → claude-sonnet-4
|
|
114
|
-
Fast: claude-haiku-4.5 → gpt-5.1-codex-mini → gpt-4.1 → gpt-5-mini
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Never fall UP in tier.** A fast task won't land on a premium model via fallback.
|
|
1
|
+
# Model Selection
|
|
2
|
+
|
|
3
|
+
> Determines which LLM model to use for each agent spawn.
|
|
4
|
+
|
|
5
|
+
## SCOPE
|
|
6
|
+
|
|
7
|
+
✅ THIS SKILL PRODUCES:
|
|
8
|
+
- A resolved `model` parameter for every `task` tool call
|
|
9
|
+
- Persistent model preferences in `.squad/config.json`
|
|
10
|
+
- Spawn acknowledgments that include the resolved model
|
|
11
|
+
|
|
12
|
+
❌ THIS SKILL DOES NOT PRODUCE:
|
|
13
|
+
- Code, tests, or documentation
|
|
14
|
+
- Model performance benchmarks
|
|
15
|
+
- Cost reports or billing artifacts
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Squad supports 18+ models across three tiers (premium, standard, fast). The coordinator must select the right model for each agent spawn. Users can set persistent preferences that survive across sessions.
|
|
20
|
+
|
|
21
|
+
## 5-Layer Model Resolution Hierarchy
|
|
22
|
+
|
|
23
|
+
Resolution is **first-match-wins** — the highest layer with a value wins.
|
|
24
|
+
|
|
25
|
+
| Layer | Name | Source | Persistence |
|
|
26
|
+
|-------|------|--------|-------------|
|
|
27
|
+
| **0a** | Per-Agent Config | `.squad/config.json` → `agentModelOverrides.{name}` | Persistent (survives sessions) |
|
|
28
|
+
| **0b** | Global Config | `.squad/config.json` → `defaultModel` | Persistent (survives sessions) |
|
|
29
|
+
| **1** | Session Directive | User said "use X" in current session | Session-only |
|
|
30
|
+
| **2** | Charter Preference | Agent's `charter.md` → `## Model` section | Persistent (in charter) |
|
|
31
|
+
| **3** | Task-Aware Auto | Code → sonnet, docs → haiku, visual → opus | Computed per-spawn |
|
|
32
|
+
| **4** | Default | `claude-haiku-4.5` | Hardcoded fallback |
|
|
33
|
+
|
|
34
|
+
**Key principle:** Layer 0 (persistent config) beats everything. If the user said "always use opus" and it was saved to config.json, every agent gets opus regardless of role or task type. This is intentional — the user explicitly chose quality over cost.
|
|
35
|
+
|
|
36
|
+
## AGENT WORKFLOW
|
|
37
|
+
|
|
38
|
+
### On Session Start
|
|
39
|
+
|
|
40
|
+
1. READ `.squad/config.json`
|
|
41
|
+
2. CHECK for `defaultModel` field — if present, this is the Layer 0 override for all spawns
|
|
42
|
+
3. CHECK for `agentModelOverrides` field — if present, these are per-agent Layer 0a overrides
|
|
43
|
+
4. STORE both values in session context for the duration
|
|
44
|
+
|
|
45
|
+
### On Every Agent Spawn
|
|
46
|
+
|
|
47
|
+
1. CHECK Layer 0a: Is there an `agentModelOverrides.{agentName}` in config.json? → Use it.
|
|
48
|
+
2. CHECK Layer 0b: Is there a `defaultModel` in config.json? → Use it.
|
|
49
|
+
3. CHECK Layer 1: Did the user give a session directive? → Use it.
|
|
50
|
+
4. CHECK Layer 2: Does the agent's charter have a `## Model` section? → Use it.
|
|
51
|
+
5. CHECK Layer 3: Determine task type:
|
|
52
|
+
- Code (implementation, tests, refactoring, bug fixes) → `claude-sonnet-4.6`
|
|
53
|
+
- Prompts, agent designs → `claude-sonnet-4.6`
|
|
54
|
+
- Visual/design with image analysis → `claude-opus-4.6`
|
|
55
|
+
- Non-code (docs, planning, triage, changelogs) → `claude-haiku-4.5`
|
|
56
|
+
6. FALLBACK Layer 4: `claude-haiku-4.5`
|
|
57
|
+
7. INCLUDE model in spawn acknowledgment: `🔧 {Name} ({resolved_model}) — {task}`
|
|
58
|
+
|
|
59
|
+
### When User Sets a Preference
|
|
60
|
+
|
|
61
|
+
**Trigger phrases:** "always use X", "use X for everything", "switch to X", "default to X"
|
|
62
|
+
|
|
63
|
+
1. VALIDATE the model ID against the catalog (18+ models)
|
|
64
|
+
2. WRITE `defaultModel` to `.squad/config.json` (merge, don't overwrite)
|
|
65
|
+
3. ACKNOWLEDGE: `✅ Model preference saved: {model} — all future sessions will use this until changed.`
|
|
66
|
+
|
|
67
|
+
**Per-agent trigger:** "use X for {agent}"
|
|
68
|
+
|
|
69
|
+
1. VALIDATE model ID
|
|
70
|
+
2. WRITE to `agentModelOverrides.{agent}` in `.squad/config.json`
|
|
71
|
+
3. ACKNOWLEDGE: `✅ {Agent} will always use {model} — saved to config.`
|
|
72
|
+
|
|
73
|
+
### When User Clears a Preference
|
|
74
|
+
|
|
75
|
+
**Trigger phrases:** "switch back to automatic", "clear model preference", "use default models"
|
|
76
|
+
|
|
77
|
+
1. REMOVE `defaultModel` from `.squad/config.json`
|
|
78
|
+
2. ACKNOWLEDGE: `✅ Model preference cleared — returning to automatic selection.`
|
|
79
|
+
|
|
80
|
+
### STOP
|
|
81
|
+
|
|
82
|
+
After resolving the model and including it in the spawn template, this skill is done. Do NOT:
|
|
83
|
+
- Generate model comparison reports
|
|
84
|
+
- Run benchmarks or speed tests
|
|
85
|
+
- Create new config files (only modify existing `.squad/config.json`)
|
|
86
|
+
- Change the model after spawn (fallback chains handle runtime failures)
|
|
87
|
+
|
|
88
|
+
## Config Schema
|
|
89
|
+
|
|
90
|
+
`.squad/config.json` model-related fields:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"version": 1,
|
|
95
|
+
"defaultModel": "claude-opus-4.6",
|
|
96
|
+
"agentModelOverrides": {
|
|
97
|
+
"fenster": "claude-sonnet-4.6",
|
|
98
|
+
"mcmanus": "claude-haiku-4.5"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- `defaultModel` — applies to ALL agents unless overridden by `agentModelOverrides`
|
|
104
|
+
- `agentModelOverrides` — per-agent overrides that take priority over `defaultModel`
|
|
105
|
+
- Both fields are optional. When absent, Layers 1-4 apply normally.
|
|
106
|
+
|
|
107
|
+
## Fallback Chains
|
|
108
|
+
|
|
109
|
+
If a model is unavailable (rate limit, plan restriction), retry within the same tier:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
Premium: claude-opus-4.6 → claude-opus-4.6-fast → claude-opus-4.5 → claude-sonnet-4.6
|
|
113
|
+
Standard: claude-sonnet-4.6 → gpt-5.4 → claude-sonnet-4.5 → gpt-5.3-codex → claude-sonnet-4
|
|
114
|
+
Fast: claude-haiku-4.5 → gpt-5.1-codex-mini → gpt-4.1 → gpt-5-mini
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Never fall UP in tier.** A fast task won't land on a premium model via fallback.
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
# Skill: nap
|
|
2
|
-
|
|
3
|
-
> Context hygiene — compress, prune, archive .squad/ state
|
|
4
|
-
|
|
5
|
-
## What It Does
|
|
6
|
-
|
|
7
|
-
Reclaims context window budget by compressing agent histories, pruning old logs,
|
|
8
|
-
archiving stale decisions, and cleaning orphaned inbox files.
|
|
9
|
-
|
|
10
|
-
## When To Use
|
|
11
|
-
|
|
12
|
-
- Before heavy fan-out work (many agents will spawn)
|
|
13
|
-
- When history.md files exceed 15KB
|
|
14
|
-
- When .squad/ total size exceeds 1MB
|
|
15
|
-
- After long-running sessions or sprints
|
|
16
|
-
|
|
17
|
-
## Invocation
|
|
18
|
-
|
|
19
|
-
- CLI: `squad nap` / `squad nap --deep` / `squad nap --dry-run`
|
|
20
|
-
- REPL: `/nap` / `/nap --dry-run` / `/nap --deep`
|
|
21
|
-
|
|
22
|
-
## Confidence
|
|
23
|
-
|
|
24
|
-
medium — Confirmed by team vote (4-1) and initial implementation
|
|
1
|
+
# Skill: nap
|
|
2
|
+
|
|
3
|
+
> Context hygiene — compress, prune, archive .squad/ state
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
Reclaims context window budget by compressing agent histories, pruning old logs,
|
|
8
|
+
archiving stale decisions, and cleaning orphaned inbox files.
|
|
9
|
+
|
|
10
|
+
## When To Use
|
|
11
|
+
|
|
12
|
+
- Before heavy fan-out work (many agents will spawn)
|
|
13
|
+
- When history.md files exceed 15KB
|
|
14
|
+
- When .squad/ total size exceeds 1MB
|
|
15
|
+
- After long-running sessions or sprints
|
|
16
|
+
|
|
17
|
+
## Invocation
|
|
18
|
+
|
|
19
|
+
- CLI: `squad nap` / `squad nap --deep` / `squad nap --dry-run`
|
|
20
|
+
- REPL: `/nap` / `/nap --dry-run` / `/nap --deep`
|
|
21
|
+
|
|
22
|
+
## Confidence
|
|
23
|
+
|
|
24
|
+
medium — Confirmed by team vote (4-1) and initial implementation
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "notification-routing"
|
|
3
|
+
description: "Route agent notifications to specific channels by type — prevent alert fatigue from single-channel flooding"
|
|
4
|
+
domain: "communication"
|
|
5
|
+
confidence: "high"
|
|
6
|
+
source: "earned"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
When a Squad grows beyond a few agents, notifications flood a single channel — failure alerts drown in daily
|
|
12
|
+
briefings, tech news buries security findings, and everything gets ignored. This is the pub-sub problem:
|
|
13
|
+
a single message queue for everything is a recipe for missed alerts.
|
|
14
|
+
|
|
15
|
+
The fix is **topic-based routing**: agents tag notifications with a channel type, and a routing function
|
|
16
|
+
sends them to the appropriate destination.
|
|
17
|
+
|
|
18
|
+
**Trigger symptoms:**
|
|
19
|
+
- Important alerts missed because they're buried in routine notifications
|
|
20
|
+
- Team members turning off notifications entirely (signal overwhelm)
|
|
21
|
+
- Onboarding friction: "where do I look for X?"
|
|
22
|
+
|
|
23
|
+
## Patterns
|
|
24
|
+
|
|
25
|
+
### Channel Config Schema
|
|
26
|
+
|
|
27
|
+
Define a `.squad/teams-channels.json` (or equivalent) mapping notification types to channel identifiers:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"teamId": "your-team-id",
|
|
32
|
+
"channels": {
|
|
33
|
+
"notifications": "squad-alerts",
|
|
34
|
+
"tech-news": "tech-news",
|
|
35
|
+
"security": "security-findings",
|
|
36
|
+
"releases": "release-announcements",
|
|
37
|
+
"daily-digest": "daily-digest"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Place this in `.squad/` (git-tracked, shared across the team). For platforms that use channel IDs instead of
|
|
43
|
+
names (Teams, Slack), store the resolved ID alongside the name to avoid name-collision bugs:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"channels": {
|
|
48
|
+
"notifications": { "name": "squad-alerts", "id": "channel-id-opaque-string" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### CHANNEL: Tag Convention
|
|
54
|
+
|
|
55
|
+
Agents prefix their output with `CHANNEL:<type>` to signal where the notification should go:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
CHANNEL:security
|
|
59
|
+
Worf found 3 new CVEs in dependency scan: lodash@4.17.15, minimist@1.2.5
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Routing Dispatcher (shell pseudocode)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
dispatch_notification() {
|
|
66
|
+
local raw_output="$1"
|
|
67
|
+
local channel="notifications" # default
|
|
68
|
+
|
|
69
|
+
if echo "$raw_output" | grep -qE '^CHANNEL:[a-z][a-z0-9-]*'; then
|
|
70
|
+
channel=$(echo "$raw_output" | head -1 | cut -d: -f2)
|
|
71
|
+
raw_output=$(echo "$raw_output" | tail -n +2)
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
send_notification --channel "$channel" --message "$raw_output"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Provider-Agnostic Adapter
|
|
79
|
+
|
|
80
|
+
The routing layer is provider-agnostic. Plug in your platform adapter:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
.squad/notify-adapter.sh # Teams / Slack / Discord / webhook -- swappable
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The routing config and CHANNEL: tags never change. Only the adapter changes per deployment.
|
|
87
|
+
|
|
88
|
+
## Anti-Patterns
|
|
89
|
+
|
|
90
|
+
**Never send all notification types to one channel:**
|
|
91
|
+
```
|
|
92
|
+
send_notification --channel "general" --message "$anything"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Never use display names as identifiers (name collision risk):**
|
|
96
|
+
```
|
|
97
|
+
send_to_team --name "Squad" --channel "notifications"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Resolve channel IDs once at setup. Use IDs at runtime.
|
|
101
|
+
|
|
102
|
+
## Distributed Systems Pattern
|
|
103
|
+
|
|
104
|
+
This is **pub-sub with topic routing** -- the same principle as Kafka topics, RabbitMQ routing keys, and
|
|
105
|
+
AWS SNS topic filtering. Route by type. Each consumer subscribes to the topics it cares about.
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
# Personal Squad — Skill Document
|
|
2
|
-
|
|
3
|
-
## What is a Personal Squad?
|
|
4
|
-
|
|
5
|
-
A personal squad is a user-level collection of AI agents that travel with you across projects. Unlike project agents (defined in a project's `.squad/` directory), personal agents live in your global config directory and are automatically discovered when you start a squad session.
|
|
6
|
-
|
|
7
|
-
## Directory Structure
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
~/.config/squad/personal-squad/ # Linux/macOS
|
|
11
|
-
%APPDATA%/squad/personal-squad/ # Windows
|
|
12
|
-
├── agents/
|
|
13
|
-
│ ├── {agent-name}/
|
|
14
|
-
│ │ ├── charter.md
|
|
15
|
-
│ │ └── history.md
|
|
16
|
-
│ └── ...
|
|
17
|
-
└── config.json # Optional: personal squad config
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## How It Works
|
|
21
|
-
|
|
22
|
-
1. **Ambient Discovery:** When Squad starts a session, it checks for a personal squad directory
|
|
23
|
-
2. **Merge:** Personal agents are merged into the session cast alongside project agents
|
|
24
|
-
3. **Ghost Protocol:** Personal agents can read project state but not write to it
|
|
25
|
-
4. **Kill Switch:** Set `SQUAD_NO_PERSONAL=1` to disable ambient discovery
|
|
26
|
-
|
|
27
|
-
## Commands
|
|
28
|
-
|
|
29
|
-
- `squad personal init` — Bootstrap a personal squad directory
|
|
30
|
-
- `squad personal list` — List your personal agents
|
|
31
|
-
- `squad personal add {name} --role {role}` — Add a personal agent
|
|
32
|
-
- `squad personal remove {name}` — Remove a personal agent
|
|
33
|
-
- `squad cast` — Show the current session cast (project + personal)
|
|
34
|
-
|
|
35
|
-
## Ghost Protocol
|
|
36
|
-
|
|
37
|
-
See `templates/ghost-protocol.md` for the full rules. Key points:
|
|
38
|
-
- Personal agents advise; project agents execute
|
|
39
|
-
- No writes to project `.squad/` state
|
|
40
|
-
- Transparent origin tagging in logs
|
|
41
|
-
- Project agents take precedence on conflicts
|
|
42
|
-
|
|
43
|
-
## Configuration
|
|
44
|
-
|
|
45
|
-
Optional `config.json` in the personal squad directory:
|
|
46
|
-
```json
|
|
47
|
-
{
|
|
48
|
-
"defaultModel": "auto",
|
|
49
|
-
"ghostProtocol": true,
|
|
50
|
-
"agents": {}
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Environment Variables
|
|
55
|
-
|
|
56
|
-
- `SQUAD_NO_PERSONAL` — Set to any value to disable personal squad discovery
|
|
57
|
-
- `SQUAD_PERSONAL_DIR` — Override the default personal squad directory path
|
|
1
|
+
# Personal Squad — Skill Document
|
|
2
|
+
|
|
3
|
+
## What is a Personal Squad?
|
|
4
|
+
|
|
5
|
+
A personal squad is a user-level collection of AI agents that travel with you across projects. Unlike project agents (defined in a project's `.squad/` directory), personal agents live in your global config directory and are automatically discovered when you start a squad session.
|
|
6
|
+
|
|
7
|
+
## Directory Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
~/.config/squad/personal-squad/ # Linux/macOS
|
|
11
|
+
%APPDATA%/squad/personal-squad/ # Windows
|
|
12
|
+
├── agents/
|
|
13
|
+
│ ├── {agent-name}/
|
|
14
|
+
│ │ ├── charter.md
|
|
15
|
+
│ │ └── history.md
|
|
16
|
+
│ └── ...
|
|
17
|
+
└── config.json # Optional: personal squad config
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
1. **Ambient Discovery:** When Squad starts a session, it checks for a personal squad directory
|
|
23
|
+
2. **Merge:** Personal agents are merged into the session cast alongside project agents
|
|
24
|
+
3. **Ghost Protocol:** Personal agents can read project state but not write to it
|
|
25
|
+
4. **Kill Switch:** Set `SQUAD_NO_PERSONAL=1` to disable ambient discovery
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
- `squad personal init` — Bootstrap a personal squad directory
|
|
30
|
+
- `squad personal list` — List your personal agents
|
|
31
|
+
- `squad personal add {name} --role {role}` — Add a personal agent
|
|
32
|
+
- `squad personal remove {name}` — Remove a personal agent
|
|
33
|
+
- `squad cast` — Show the current session cast (project + personal)
|
|
34
|
+
|
|
35
|
+
## Ghost Protocol
|
|
36
|
+
|
|
37
|
+
See `templates/ghost-protocol.md` for the full rules. Key points:
|
|
38
|
+
- Personal agents advise; project agents execute
|
|
39
|
+
- No writes to project `.squad/` state
|
|
40
|
+
- Transparent origin tagging in logs
|
|
41
|
+
- Project agents take precedence on conflicts
|
|
42
|
+
|
|
43
|
+
## Configuration
|
|
44
|
+
|
|
45
|
+
Optional `config.json` in the personal squad directory:
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"defaultModel": "auto",
|
|
49
|
+
"ghostProtocol": true,
|
|
50
|
+
"agents": {}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Environment Variables
|
|
55
|
+
|
|
56
|
+
- `SQUAD_NO_PERSONAL` — Set to any value to disable personal squad discovery
|
|
57
|
+
- `SQUAD_PERSONAL_DIR` — Override the default personal squad directory path
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "pr-screenshots"
|
|
3
|
+
description: "Capture Playwright screenshots and embed them in GitHub PR descriptions"
|
|
4
|
+
domain: "pull-requests, visual-review, docs, testing"
|
|
5
|
+
confidence: "high"
|
|
6
|
+
source: "earned (multiple sessions establishing the pattern for PR #11 TypeDoc API reference)"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
When a PR includes visual changes (docs sites, UI components, generated pages), reviewers
|
|
12
|
+
need to see what the PR delivers without checking out the branch. Screenshots belong in
|
|
13
|
+
the **PR description body**, not as committed files and not as text descriptions.
|
|
14
|
+
|
|
15
|
+
Use this skill whenever:
|
|
16
|
+
- A PR touches docs site pages (Astro, Starlight, etc.)
|
|
17
|
+
- A PR adds or changes UI components
|
|
18
|
+
- A PR generates visual artifacts (TypeDoc, Storybook, diagrams)
|
|
19
|
+
- Playwright tests already capture screenshots as part of testing
|
|
20
|
+
|
|
21
|
+
## Patterns
|
|
22
|
+
|
|
23
|
+
### 1. Capture screenshots with Playwright
|
|
24
|
+
|
|
25
|
+
If Playwright tests already exist and produce screenshots, reuse those. Otherwise,
|
|
26
|
+
write a minimal capture script:
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// scripts/capture-pr-screenshots.mjs
|
|
30
|
+
import { chromium } from 'playwright';
|
|
31
|
+
|
|
32
|
+
const browser = await chromium.launch();
|
|
33
|
+
const page = await browser.newPage({ viewport: { width: 1280, height: 720 } });
|
|
34
|
+
|
|
35
|
+
const screenshots = [
|
|
36
|
+
{ url: 'http://localhost:4321/path/to/page', name: 'feature-landing' },
|
|
37
|
+
{ url: 'http://localhost:4321/path/to/detail', name: 'feature-detail' },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
for (const { url, name } of screenshots) {
|
|
41
|
+
await page.goto(url, { waitUntil: 'networkidle' });
|
|
42
|
+
await page.screenshot({ path: `screenshots/${name}.png`, fullPage: false });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await browser.close();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Host screenshots on a temporary branch
|
|
49
|
+
|
|
50
|
+
GitHub PR descriptions render images via URLs. The `gh` CLI cannot upload binary
|
|
51
|
+
images directly. Use a temporary orphan branch to host the images:
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
# Save current branch
|
|
55
|
+
$currentBranch = git branch --show-current
|
|
56
|
+
|
|
57
|
+
# Create orphan branch with only screenshot files
|
|
58
|
+
git checkout --orphan screenshots-temp
|
|
59
|
+
git reset
|
|
60
|
+
git add screenshots/*.png
|
|
61
|
+
git commit -m "screenshots for PR review"
|
|
62
|
+
git push origin screenshots-temp --force
|
|
63
|
+
|
|
64
|
+
# Build raw URLs
|
|
65
|
+
$base = "https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots"
|
|
66
|
+
# Each image: $base/{name}.png
|
|
67
|
+
|
|
68
|
+
# Return to working branch
|
|
69
|
+
git checkout -f $currentBranch
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Embed in PR description
|
|
73
|
+
|
|
74
|
+
Use `gh pr edit` with the raw URLs embedded as markdown images:
|
|
75
|
+
|
|
76
|
+
```powershell
|
|
77
|
+
$base = "https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots"
|
|
78
|
+
|
|
79
|
+
gh pr edit {PR_NUMBER} --repo {owner}/{repo} --body @"
|
|
80
|
+
## {PR Title}
|
|
81
|
+
|
|
82
|
+
### What this PR delivers
|
|
83
|
+
- {bullet points of changes}
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### Screenshots
|
|
88
|
+
|
|
89
|
+
#### {Page/Feature Name}
|
|
90
|
+

|
|
91
|
+
|
|
92
|
+
#### {Another Page}
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### To verify locally
|
|
98
|
+
```bash
|
|
99
|
+
{commands to run locally}
|
|
100
|
+
```
|
|
101
|
+
"@
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 4. Cleanup after merge
|
|
105
|
+
|
|
106
|
+
After the PR is merged, delete the temporary branch:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git push origin --delete screenshots-temp
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 5. Gitignore screenshots locally
|
|
113
|
+
|
|
114
|
+
Screenshots are build artifacts — never commit them to feature branches:
|
|
115
|
+
|
|
116
|
+
```gitignore
|
|
117
|
+
# PR screenshots (hosted on temp branch, not committed to features)
|
|
118
|
+
screenshots/
|
|
119
|
+
docs/tests/screenshots/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Examples
|
|
123
|
+
|
|
124
|
+
### Example: Docs site PR with 3 pages
|
|
125
|
+
|
|
126
|
+
1. Start dev server: `cd docs && npm run dev`
|
|
127
|
+
2. Run Playwright tests (they capture screenshots as a side effect)
|
|
128
|
+
3. Push screenshots to `screenshots-temp` branch
|
|
129
|
+
4. Update PR body with embedded `![...]()` image references
|
|
130
|
+
5. Reviewer sees the pages inline without checking out the branch
|
|
131
|
+
|
|
132
|
+
### Example: Reusing existing Playwright test screenshots
|
|
133
|
+
|
|
134
|
+
If tests at `docs/tests/*.spec.mjs` already save to `docs/tests/screenshots/`:
|
|
135
|
+
|
|
136
|
+
```powershell
|
|
137
|
+
cd docs && npx playwright test tests/api-reference.spec.mjs
|
|
138
|
+
# Screenshots now at docs/tests/screenshots/*.png
|
|
139
|
+
# Push those to screenshots-temp and embed in PR
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Anti-Patterns
|
|
143
|
+
|
|
144
|
+
- ❌ **Committing screenshots to feature branches** — they bloat the repo and go stale
|
|
145
|
+
- ❌ **Posting text descriptions instead of actual images** — reviewers can't see what they're getting
|
|
146
|
+
- ❌ **Using `gh` CLI to "upload" images** — `gh issue comment` and `gh pr edit` don't support binary uploads
|
|
147
|
+
- ❌ **Asking the user to manually drag-drop images** — automate it with the temp branch pattern
|
|
148
|
+
- ❌ **Skipping screenshots for visual PRs** — if the PR changes what users see, show what users see
|
|
149
|
+
- ❌ **Leaving the screenshots-temp branch around forever** — clean up after merge
|