-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsquad-export.json
More file actions
224 lines (224 loc) · 257 KB
/
Copy pathsquad-export.json
File metadata and controls
224 lines (224 loc) · 257 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
{
"version": "1.0",
"exported_at": "2026-04-22T16:17:16.892Z",
"squad_version": "0.6.0",
"casting": {
"registry": {
"agents": {
"farnsworth": {
"persistent_name": "farnsworth",
"universe": "futurama",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"bender": {
"persistent_name": "bender",
"universe": "futurama",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"hermes": {
"persistent_name": "hermes",
"universe": "futurama",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"amy": {
"persistent_name": "amy",
"universe": "futurama",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"fry": {
"persistent_name": "fry",
"universe": "futurama",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"leela": {
"persistent_name": "leela",
"universe": "futurama",
"created_at": "2026-03-27T17:00:00.000Z",
"legacy_named": false,
"status": "active"
},
"scribe": {
"persistent_name": "scribe",
"universe": "exempt",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
},
"ralph": {
"persistent_name": "ralph",
"universe": "exempt",
"created_at": "2026-03-27T00:00:00.000Z",
"legacy_named": true,
"status": "active"
}
}
},
"policy": {
"casting_policy_version": "1.1",
"allowlist_universes": [
"The Usual Suspects",
"Reservoir Dogs",
"Alien",
"Ocean's Eleven",
"Arrested Development",
"Star Wars",
"The Matrix",
"Firefly",
"The Goonies",
"The Simpsons",
"Breaking Bad",
"Lost",
"Marvel Cinematic Universe",
"DC Universe",
"Futurama"
],
"universe_capacity": {
"The Usual Suspects": 6,
"Reservoir Dogs": 8,
"Alien": 8,
"Ocean's Eleven": 14,
"Arrested Development": 15,
"Star Wars": 12,
"The Matrix": 10,
"Firefly": 10,
"The Goonies": 8,
"The Simpsons": 20,
"Breaking Bad": 12,
"Lost": 18,
"Marvel Cinematic Universe": 25,
"DC Universe": 18,
"Futurama": 12
}
},
"history": {
"universe_usage_history": [
{
"universe": "futurama",
"first_used": "2026-03-27T00:00:00.000Z",
"last_used": "2026-03-27T17:00:00.000Z",
"total_assignments": 8
}
],
"assignment_cast_snapshots": {
"assignment_1": {
"assignment_id": "assignment_1",
"created_at": "2026-03-27T00:00:00.000Z",
"universe": "futurama",
"agents": [
{
"role": "Lead / Architect",
"name": "farnsworth"
},
{
"role": "Backend Developer",
"name": "bender"
},
{
"role": "PowerShell Expert",
"name": "hermes"
},
{
"role": "DevOps / Platform / Azure",
"name": "amy"
},
{
"role": "Tester",
"name": "fry"
},
{
"role": "Developer Advocate",
"name": "leela"
},
{
"role": "Session Logger",
"name": "scribe"
},
{
"role": "Work Monitor",
"name": "ralph"
}
]
}
}
}
},
"agents": {
"amy": {
"charter": "# Amy — DevOps / Platform / Azure Engineer\n\n## Role\n\nObservability, monitoring, operational tooling, and Azure cloud specialist for PoshMcp.\n\n## Responsibilities\n\n- Implement and expand OpenTelemetry metrics\n- Build health check infrastructure\n- Create diagnostic and monitoring endpoints\n- Implement structured logging with correlation IDs\n- Build operational dashboards and data APIs\n- Design audit logging infrastructure\n- Monitor system health and performance\n- Design and implement Azure deployments and integrations\n- Configure Azure monitoring and Application Insights\n- Implement Azure Managed Identity authentication\n\n## Domain Expertise\n\n- OpenTelemetry (metrics, traces, logs)\n- ASP.NET Core health checks\n- Structured logging (Serilog, Microsoft.Extensions.Logging)\n- Prometheus and metrics expos\n- Azure cloud architecture and deployment\n- Azure Container Apps and App Service\n- Azure Application Insights and Monitor\n- Azure Key Vault and Managed Identity\n- Azure DevOps pipelines and deploymentition\n- Correlation ID propagation\n- System diagnostics and profiling\n- Audit logging and compliance\n\n## Focus Areas\n- Azure resource deployment and configuration\n- Azure-native observability (Application Insights)\n- Containerization for Azure deployments\n- Azure security best practices (Key Vault, Managed Identity)\n\n- Enhanced metrics with detailed dimensions\n- Health check endpoints for all subsystems\n- Diagnostics snapshot API\n- Real-time monitoring dashboard data\n- Structured event log for audit trail\n- Correlation IDs across operations\n- Performance monitoring and alerting\n\n## Working Style\n\n- Make systems observable before problems occur\n- Design for production operations\n- Metrics should never crash the application\n- Create self-service diagnostic tools\n- Focus on actionable insights\n\n## Collaboration\n\n- Works with **Bender** on instrumenting backend code\n- Works with **Hermes** on PowerShell-specific tracing\n- Works with **Fry** on testing observability features\n- Reports to **Farnsworth** for observability architecture\n\n## Output Standards\n\n- All metrics follow OpenTelemetry semantic conventions\n- Health checks return meaningful status information\n- Diagnostic endpoints are documented\n- Logs include correlation IDs\n- Performance overhead of instrumentation is measured\n",
"history": "- Ran 5 sequential iterations of `dotnet clean` + `dotnet test --configuration Release` to diagnose reported flaky tests.\n- **Result: STABLE** — All 5 iterations passed with consistent test counts: 387 passed, 1 skipped, 0 failed (total 388).\n- Iteration times: 338.9s, 291.9s, 379.9s, 520.9s, 340s (variable duration due to system load, no correlation with failures).\n- No failing tests identified across any iteration. One test (`PoshMcp.Tests.Functional.ReturnType.GeneratedMethod.ShouldHandleGetChildItemCorrectly`) consistently skipped.\n- Verdict: No evidence of intermittent failures in test suite.\n\n### 2026-04-14: v0.5.4 tool update (local nupkg install)\n\n- Verified latest nupkg in `./nupkg/`: `poshmcp.0.5.4.nupkg`\n- Current global tool version: 0.5.3\n- PackageId and ToolCommandName both: `poshmcp` (confirmed in .csproj)\n- Update command: `dotnet tool update -g poshmcp --add-source ./nupkg --version 0.5.4`\n- Verified: `dotnet tool list -g | Select-String poshmcp` → `poshmcp 0.5.4 poshmcp`\n- Local .nupkg directory is specified with `--add-source ./nupkg` (relative path from working directory)\n\n### 2026-04-14: v0.5.6 patch release and GitHub Packages publish\n\n- Version source remains `PoshMcp.Server/PoshMcp.csproj` `<Version>`; bumped `0.5.5` → `0.5.6` as patch increment.\n- Packaging command: `dotnet pack .\\PoshMcp.Server\\PoshMcp.csproj -c Release -o .\\nupkg`\n- Produced artifact: `nupkg/poshmcp.0.5.6.nupkg` (25,843,399 bytes).\n- GitHub Packages publish command used existing source alias and gh token: `dotnet nuget push .\\nupkg\\poshmcp.0.5.6.nupkg --api-key (gh auth token) --source github-poshmcp --skip-duplicate`.\n- Publish succeeded to `https://nuget.pkg.github.com/usepowershell`.\n- Local update command remains: `dotnet tool update -g poshmcp --version 0.5.6 --add-source .\\nupkg --ignore-failed-sources`.\n- Verified installs: `dotnet tool list -g` shows `poshmcp 0.5.6`; `poshmcp --version` reports `0.5.6+31fa6372ec4b71d7dd68261ba45266c6c8b93817`.\n\n### 2026-07-18: Issue #131 — OTel stdio suppression and appsettings schema\n\n- Added `isStdioMode = false` parameter to `ConfigureOpenTelemetry(HostApplicationBuilder, bool)` in `Program.cs`.\n- Guarded `metricsBuilder.AddConsoleExporter()` behind `if (!isStdioMode)` so no OTel console output occurs in stdio transport mode.\n- Updated `ConfigureServerServices` call site (stdio-only path) to pass `isStdioMode: true` to `ConfigureOpenTelemetry`.\n- `ConfigureOpenTelemetryForHttp` (HTTP path) is a separate method and remains unchanged — HTTP console exporter unaffected.\n- `appsettings.json` already had `Logging.File.Path` added by Bender; added the same `Logging.File.Path: \"\"` schema key to `appsettings.environment-example.json`, `appsettings.azure.json`, and `appsettings.modules.json`.\n- Build: `dotnet build PoshMcp.Server/PoshMcp.csproj` → succeeded, 5 pre-existing warnings, 0 errors.\n- Committed and pushed to branch `squad/131-stdio-logging-to-file` (commit `8a10311`).\n\n\n\n### 2026-07-18: Issue #133 — docker buildx build missing PATH argument\n\n- **Root cause:** `PoshMcp.Server/Program.cs` line ~692, the `build` CLI command handler constructed `buildArgs` as `\"build -f {imageFile} -t {imageTag}\"` — missing the required build context PATH argument.\n- On modern Docker (buildx-as-default), `docker build` delegates to `docker buildx build` which requires a positional PATH/URL/`-` argument. Without it, Docker fails with `'docker buildx build' requires 1 argument`.\n- **Fix:** Changed to `$\"build -f {imageFile} -t {imageTag} .\"` — appending `.` (current directory) as the build context.\n- The CI workflow (`publish-packages.yml`) calls `dotnet run -- build --tag \"$IMAGE\"` which runs the CLI build handler; the Dockerfile is expected to exist in the working directory (repo root), consistent with using `.` as context.\n- **Key files:** `PoshMcp.Server/Program.cs` (handler for `buildCommand`), `.github/workflows/publish-packages.yml` (CI step that triggered the failure).\n- Branch: `squad/133-fix-docker-buildx-path`, commit `fadbd4d`, PR #134.\n- Build verified: `dotnet build PoshMcp.Server/PoshMcp.csproj -c Release` → 0 errors after fix.\n\n### 2026-07-18: PR #138 follow-up — remove orphaned COPY PoshMcp.sln line\n\n- Farnsworth's nit on PR #138: `COPY PoshMcp.sln ./` in the build stage was dead weight after switching restore/build to target `PoshMcp.Server/PoshMcp.csproj`.\n- Removed the line and updated the adjacent comment from \"Copy solution and project files first\" to \"Copy project files first\".\n- Committed as `fix(#136): remove orphaned COPY PoshMcp.sln line from Dockerfile` with Copilot co-author trailer.\n- Pushed to `squad/136-fix-container-image-build`; replied to PR with confirmation comment.\n- Key lesson: when switching from solution-level to project-level restore/build in a Dockerfile, audit all COPY lines in the build stage — any files that no longer appear in RUN commands become orphaned layers that add noise without value.\n\n## Archive Note\n\nDetailed session history was archived to `history-archive.md` on 2026-04-10 when this file exceeded the 15 KB Scribe threshold.\n\n\n\n### 2026-04-18: Spec 002 integration branch (2026-04-15 session note)\n\n- Created `integration/spec-002-mcp-resources-and-prompts` from `main` and merged all 4 feature branches in order.\n- `feature/002-resources` merged clean. `feature/002-prompts` conflicted on `Program.cs` — resolved by merging `ConfigureServerServices`/`RegisterMcpServerServices` signatures to accept both handlers, and chaining all 4 `With*Handler` calls in HTTP and stdio paths.\n- `feature/002-doctor` had add/add conflicts on all 5 config model files (it defined its own nullable-property versions). Kept HEAD (implementation branch) non-nullable versions; validator `IsNullOrWhiteSpace` checks are compatible with both.\n- `feature/002-tests` merged clean.\n- Build: `dotnet build PoshMcp.sln --no-incremental` → **succeeded**, 5 pre-existing warnings in `McpToolFactoryV2.cs` (unrelated to Spec 002).\n- Branch pushed to `origin`.\n- Key lesson: when 3+ branches all modify `Program.cs` service registration, the standard pattern is to merge signatures by adding parameters for each feature's handler/config, then chain all handlers together.\n\n### 2026-04-18: Spec 002 PR creation and merge session\n\n- Created 4 PRs targeting main: #125 (resources), #126 (prompts), #127 (doctor), #128 (tests).\n- PR #125 squash-merged cleanly (no conflicts on origin).\n- PR #126 required rebase in worktree `poshmcp-002-prompts` (`Program.cs` conflict resolved using integration branch version with both handlers chained). Squash-merged.\n- PR #127 required rebase in worktree `poshmcp-002-doctor` (5 add/add conflicts on McpPrompts/McpResources config files — kept HEAD/main versions; `Program.cs` resolved from integration branch). Squash-merged.\n- PR #128 (tests) created but NOT merged — pending rebase onto merged main.\n- **Encoding bug encountered and fixed:** `git show | Out-File -Encoding UTF8` in PowerShell 5 converts UTF-8 BOM bytes (0xEF 0xBB 0xBF) through CP850 console encoding into literal characters ∩╗┐ (U+2229 U+2557 U+2510), causing `CS1056` C# build errors.\n- **Fix:** Use `cmd /c \"git show <ref>:path > outfile\"` for binary-safe file extraction. Applied as fix commit `c17cdf8` on main.\n- Final build: `dotnet build PoshMcp.sln --no-incremental` → **Build succeeded, 0 errors**.\n\n### 2026-04-18: Spec 002 final merge — PR #128 and worktree cleanup\n\n- Squash-merged PR #128 (`feature/002-tests` → `main`) via `gh pr merge 128 --squash --delete-branch`. GitHub confirmed merge to `b6a268c`.\n- Pulled `main` (fast-forward): 10 new test files, 2,267 lines added.\n- Final `dotnet test PoshMcp.sln` on main: **476 passed, 1 failed, 1 skipped — total 478**.\n - Failing: `McpResourcesValidatorTests.cs(250) Assert.NotEmpty()` — pre-existing, non-blocking.\n - Skipped: `ShouldHandleGetChildItemCorrectly` — pre-existing, non-blocking.\n- Removed all four spec-002 feature worktrees: `poshmcp-002-resources`, `poshmcp-002-prompts`, `poshmcp-002-doctor`, `poshmcp-002-tests`.\n- Deleted local branches: `feature/002-resources`, `feature/002-prompts`, `feature/002-doctor`, `feature/002-tests`, `integration/spec-002-mcp-resources-and-prompts`.\n- Deleted remote branches: all four `feature/002-*` and `integration/spec-002-mcp-resources-and-prompts`.\n- Spec review worktrees (`poshmcp-spec-001` through `poshmcp-spec-005`) are separate infrastructure — left intact.\n- Note: `gh pr merge --delete-branch` produces a non-zero exit but the merge itself succeeds when GitHub auto-deletes the remote branch (same false-failure pattern as #92–#95 session). Squash-merge is the required strategy (merge commits blocked on this repo).\n- Spec 002 is fully closed. No residual branches or worktrees remain.\n\n### 2026-04-18: Issue #131 STDIO logging infrastructure (Amy as DevOps lead)\n\n- Suppressed OTel console exporter in stdio mode via isStdioMode parameter in ConfigureOpenTelemetry.\n- Updated all appsettings files with Logging.File.Path schema (appsettings.json, default.appsettings.json, environment-example, azure, modules).\n- Infrastructure changes complete and merged to squad/131-stdio-logging-to-file branch.\n\n### 2026-04-18: v0.6.0 minor release\n\n- Minor version bump: `PoshMcp.Server/PoshMcp.csproj` `0.5.6` → `0.6.0` (reflects merged feature PRs #125–#128 for Spec 002).\n- Pulled latest main: branch already up-to-date (10 spec-002 test commits already present from previous session).\n- Pack command: `dotnet pack PoshMcp.Server/PoshMcp.csproj -c Release -o ./nupkg` → produced `poshmcp.0.6.0.nupkg` (25.8 MB).\n- Uninstall/reinstall cycle: removed `poshmcp.0.5.6`, installed `0.6.0` from local nupkg source.\n- Verified: `poshmcp --version` → `0.6.0+3ed89f5946ba89be53ebb9f85238ab1a3143015b` (commit hash from main).\n- Commit: `chore: bump version to 0.6.0` with Copilot co-author trailer; pushed to main.\n\n### 2026-04-18: CI/CD pipeline improvements — preview builds, NuGet.org release, README in package\n\n- Added `<PackageReadmeFile>README.md</PackageReadmeFile>` to `PoshMcp.Server/PoshMcp.csproj` PropertyGroup.\n- Added `<None Include=\"..\\README.md\" Pack=\"true\" PackagePath=\"\\\" />` so README.md from the repo root is embedded in the NuGet package.\n- Created `.github/workflows/preview-packages.yml`: triggers on push to main (same paths as ci.yml), skips on `[skip ci]` or `[no preview]` in commit message, versions as `{base-version}-preview.{GITHUB_RUN_NUMBER}`, runs unit + functional tests, packs and publishes to GitHub Packages, uploads artifact (14-day retention), writes a job summary with version and link.\n- Reworked `.github/workflows/publish-packages.yml`: replaced `release: published` trigger with `push: tags: ['v*']`; updated version logic to strip `v` prefix from `github.ref_name` on tag push; added \"Publish to NuGet.org\" step (using `NUGET_API_KEY` secret, `if: github.event_name == 'push'`); added \"Create or update GitHub Release with notes\" step that uses `docs/release-notes/{version}.md` if present or auto-generates notes; updated `contents` permission from `read` to `write` (required for `gh release`); updated container job's \"Tag image as latest\" and \"Push latest tag\" `if:` conditions from `release` to `push`.\n- All changes committed and pushed to main: `0037c66`.\n\n\n\n- Package artifact: `nupkg/poshmcp.0.6.0.nupkg` (verified present, 25.8 MB).\n- GitHub Packages source was already registered as `github-poshmcp` → `https://nuget.pkg.github.com/usepowershell/index.json`.\n- Publish command: `dotnet nuget push ./nupkg/poshmcp.0.6.0.nupkg --source https://nuget.pkg.github.com/usepowershell/index.json --api-key (gh auth token)`.\n- Result: **Successfully published** to GitHub Packages NuGet registry.\n- Verified via `gh api \"/users/usepowershell/packages/nuget/poshmcp/versions\"` → confirmed `0.6.0` is the latest published version (alongside 0.5.6 and 0.5.5).\n- Repository owner: `usepowershell` (user account, not organization).\n\n\n## Cross-Agent: PR #139 Also Approved (2026-04-20)\n\n- Farnsworth approved both PRs #138 and #139\n- Bender added config secrets redaction to #139\n- 334 tests now passing across suite\n\n## Learnings\n\n- **Version management:** Project version is maintained solely in PoshMcp.Server/PoshMcp.csproj under the <Version> element. No distributed version configuration across multiple files (e.g., Directory.Build.props). Bumped \u0000.7.1 → \u0000.8.0.\r\n"
},
"bender": {
"charter": "# Bender — Backend Developer\n\n## Role\n\nC# and .NET implementation specialist for the PoshMcp MCP server.\n\n## Responsibilities\n\n- Implement C# backend logic and services\n- Build API endpoints and controllers\n- Implement error handling and resilience patterns\n- Integrate middleware and ASP.NET Core features\n- Work with dependency injection and hosted services\n- Implement circuit breakers, retry logic, and timeouts\n\n## Domain Expertise\n\n- C# and .NET 10 development\n- ASP.NET Core web APIs\n- Dependency injection and middleware\n- Error handling and exception management\n- Async/await patterns\n- LINQ and collections\n- OpenTelemetry integration\n\n## Focus Areas\n\n- Error handling framework (structured exceptions, error codes)\n- Resilience patterns (circuit breaker, retry, timeout)\n- API controllers for diagnostics and health\n- Rate limiting\n- Request/response logging middleware\n- Configuration validation\n\n## Working Style\n\n- Write clean, testable code\n- Follow SOLID principles\n- Use proper async patterns\n- Implement comprehensive error handling\n- Add XML documentation for public APIs\n\n## Collaboration\n\n- Works with **Hermes** on PowerShell integration points\n- Works with **Amy** on metrics and observability instrumentation\n- Works with **Fry** on test coverage and testability\n- Reports to **Farnsworth** for architectural decisions\n\n## Output Standards\n\n- All code compiles without warnings\n- Public APIs have XML documentation\n- Error paths include structured logging\n- Operations record relevant metrics\n- Edge cases are handled explicitly\n",
"history": "# Bender Work History\r\n\r\n## Recent Work (2026-04-20 — CURRENT SESSION)\r\n\r\n### Docker Build Arguments Extraction and Testing\r\n**Branch:** background→sync \r\n**Status:** Complete\r\n\r\n- **Task (Bender)**: Extracted `DockerRunner.BuildDockerBuildArgs` static method from `Program.cs` build handler\r\n- **Implementation**: Created `PoshMcp.Server/Infrastructure/DockerRunner.cs` with reusable `BuildDockerBuildArgs(string projectPath)` method\r\n- **Outcome**: Delegated build handler → DockerRunner; build passes without errors\r\n- **Coordination**: Fry created comprehensive 11-test unit suite in `PoshMcp.Tests/Unit/DockerRunnerTests.cs`; all tests passing\r\n\r\n**Files modified:**\r\n- `PoshMcp.Server/Program.cs` — build handler simplified\r\n- `PoshMcp.Server/Infrastructure/DockerRunner.cs` — new extraction\r\n- Both agents coordinate on isolated, testable Docker build logic\r\n\r\n## Recent Status (2026-07-30, PR #167 Review Nits — COMPLETE)\r\n\r\n**Summary:** Addressed 3 Farnsworth review nits on PR #167. 520 tests pass, 0 failures. Pushed commit e440ab2.\r\n\r\n## Spec 006 PR #167 Review Nits — commit e440ab2\r\n\r\n**What changed:**\r\n- **Fix 1** (`Program.cs`): Removed misleading `--json` flag mention from `get-configuration-troubleshooting` MCP tool description. The `--json` flag is for the CLI `doctor` command; the MCP tool always returns structured text. New description: `\"...Always returns structured text output.\"`\r\n- **Fix 2** (`Program.cs`): Added `POSHMCP_LOG_FILE` to `CollectEnvironmentVariables()` canonical list, positioned after `POSHMCP_LOG_LEVEL`. No column width change needed in `DoctorTextRenderer` (35-char column is sufficient).\r\n- **Fix 3** (`Program.cs`): Corrected `POSHMCP_CONFIG` → `POSHMCP_CONFIGURATION` to match `SettingsResolver.cs` constant `ConfigurationEnvVar`. Also updated unit test assertion in `ProgramDoctorConfigCoverageTests.cs` (renamed method from `WithSevenExpectedKeys` to `WithExpectedKeys`).\r\n\r\n**Key pattern:**\r\n- When renaming env var keys, always grep tests for the old key name — they'll have hard-coded string assertions that need updating too.\r\n\r\n---\r\n\r\n## Recent Status (2026-07-29, Phase 8 — COMPLETE)\r\n\r\n**Summary:** Spec 006 Phase 8 complete — dead code removed, `dotnet format` clean, 520 tests pass, PR #167 opened.\r\n\r\n## Spec 006 Phase 8: Cleanup and Finalization (T024–T027) — commit ef27ef1\r\n\r\n**What changed:**\r\n- **T024**: Removed 5 dead methods/fields from `Program.cs`: `_sensitiveKeyPatterns`, `IsSensitiveKey`, `RedactSensitiveConfigValues`, `LoadFlatConfigSection`, `TryLoadResourcesAndPromptsDefinitions`. These were superseded by `DoctorReport.Build()` in Phase 3 and had zero call sites. `-31 lines`.\r\n- **T025**: `dotnet format` applied, `--verify-no-changes` exits 0.\r\n- **T026**: `dotnet test -c Release` → **520 passed, 0 failed, 7 skipped**.\r\n- **T027**: PR #167 opened: https://github.com/usepowershell/PoshMcp/pull/167\r\n\r\n**Key pattern:**\r\n- After refactoring to a new model (e.g., `DoctorReport.Build()`), always grep ALL call sites for helper methods from the old path. Private helpers with zero external references are safe to delete.\r\n\r\n## Spec 006 Phase 6: MCP Tool Schema Update (T017–T018) — commit 2ed1546\r\n\r\n**What changed:**\r\n\r\n### `Program.cs` — `CreateConfigurationTroubleshootingToolInstance` (T017)\r\n- Updated `Description` for the `get-configuration-troubleshooting` MCP tool:\r\n - Old: `\"Returns doctor-style configuration diagnostics for the running server\"`\r\n - New: `\"Returns doctor-style configuration diagnostics for the running server. Output includes runtime settings, environment variables, PowerShell info, configured functions, and MCP definitions. Outputs structured text by default; pass argument '--json' for machine-readable JSON.\"`\r\n\r\n### `DoctorReport.cs` — `FunctionsToolsSection` (T018)\r\n- Changed `ConfiguredFunctionsFound` from `List<string>` to `int` to match spec JSON shape (`\"configuredFunctionsFound\": 5`)\r\n- Changed `ConfiguredFunctionsMissing` from `List<string>` to `int` to match spec JSON shape (`\"configuredFunctionsMissing\": 0`)\r\n- Updated `ComputeStatus`: `ConfiguredFunctionsMissing.Count > 0` → `ConfiguredFunctionsMissing > 0`\r\n- Updated `DoctorReport.Build`: `ConfiguredFunctionsFound = foundFunctions` → `ConfiguredFunctionsFound = foundFunctions.Count` and same for Missing\r\n\r\n### `DoctorTextRenderer.cs`\r\n- Updated `RenderFunctionsTools`: `ConfiguredFunctionsMissing.Count == 0` → `ConfiguredFunctionsMissing == 0`\r\n- Updated count display: `ConfiguredFunctionsFound.Count` → `ConfiguredFunctionsFound`\r\n\r\n**Why the schema fix:** The spec.md JSON Output Design shows `configuredFunctionsFound` and `configuredFunctionsMissing` as integer counts (e.g., `5` and `0`), not arrays of names. The full name details are already available in `configuredFunctionStatus` entries. Changed to integers to match the spec contract.\r\n\r\n**Build:** 0 errors. Pre-existing warnings (NU1903, CS8602 in McpToolFactoryV2.cs) unchanged.\r\n\r\n---\r\n\r\n## Recent Status (2026-07-29, Phase 4)\r\n\r\n**Summary:** Spec 006 Phase 4 complete — canonical env var list and renderer column width aligned to spec.\r\n\r\n## Spec 006 Phase 4: Env Vars Section Population (T013–T014) — commit 2fc1b55\r\n\r\n**What changed:**\r\n\r\n### `Program.cs` — `CollectEnvironmentVariables()`\r\n- Added 3 missing keys: `POSHMCP_FUNCTION_NAMES`, `POSHMCP_COMMAND_NAMES`, `DOTNET_ENVIRONMENT`\r\n- Reordered to match canonical spec order: TRANSPORT → LOG_LEVEL → SESSION_MODE → RUNTIME_MODE → MCP_PATH → CONFIG → FUNCTION_NAMES → COMMAND_NAMES → ASPNETCORE_ENVIRONMENT → DOTNET_ENVIRONMENT\r\n- All values resolved via `Environment.GetEnvironmentVariable(key)` (null if unset)\r\n\r\n### `DoctorTextRenderer.cs` — `RenderEnvironmentVariables()`\r\n- Changed key column width from `{key,-30}` to `{key,-35}` to match spec format\r\n\r\n**Build:** 0 errors. All pre-existing warnings (NU1903, CS8602) unchanged.\r\n\r\n**Canonical env var list (10 keys):**\r\n```\r\nPOSHMCP_TRANSPORT\r\nPOSHMCP_LOG_LEVEL\r\nPOSHMCP_SESSION_MODE\r\nPOSHMCP_RUNTIME_MODE\r\nPOSHMCP_MCP_PATH\r\nPOSHMCP_CONFIG\r\nPOSHMCP_FUNCTION_NAMES\r\nPOSHMCP_COMMAND_NAMES\r\nASPNETCORE_ENVIRONMENT\r\nDOTNET_ENVIRONMENT\r\n```\r\n\r\n---\r\n\r\n**[Earlier history before 2026-04-21 archived to history-archive.md per Scribe threshold policy. Preserving last 90 days in main history.]**\r\n"
},
"farnsworth": {
"charter": "# Farnsworth — Lead / Architect\n\n## Role\n\nLead architect and technical decision maker for the PoshMcp MCP server.\n\n## Responsibilities\n\n- Make architectural decisions and design system components\n- Review and approve major code changes\n- Guide technical direction and standards\n- Triage GitHub issues and assign work to team members\n- Resolve technical conflicts and trade-offs\n- Ensure consistency across the codebase\n\n## Domain Expertise\n\n- System architecture and design patterns\n- .NET and C# best practices\n- API design and interface contracts\n- Code review and quality standards\n- Technical trade-off analysis\n\n## Decision Authority\n\n- Approve or reject architectural proposals\n- Define coding standards and patterns\n- Prioritize work and technical debt\n- Break ties when team members disagree\n\n## Working Style\n\n- Focus on long-term maintainability over short-term wins\n- Demand clear reasoning for design decisions\n- Value simplicity and clarity\n- Insist on proper abstractions and separation of concerns\n\n## Reviewer Role\n\nWhen reviewing work:\n- Check architectural alignment\n- Verify proper error handling and resilience patterns\n- Ensure code follows team standards\n- May **reject** and reassign to a different agent for revision\n- Provide specific, actionable feedback\n\n## Tools & Patterns\n\n- SOLID principles\n- Circuit breaker, retry, and timeout patterns\n- Health check endpoints\n- Structured logging and correlation IDs\n- Configuration validation\n",
"history": "**PR:** #96 (Hermes original, Bender fix) — `feat: surface resolution reasons for missing commands in poshmcp doctor`\n**Outcome:** Squash merged to `main`. Branch `squad/91-doctor-commands-resolved` deleted (remote). Fixes #91.\n\n**Fix pattern (Bender's second commit):**\n- `RunDoctorAsync` now calls `DiagnoseMissingCommands` once, enriches `configuredFunctionStatus` records with `ResolutionReason`, then passes the list to `BuildDoctorJson` via new optional `precomputedFunctionStatus` parameter.\n- `BuildDoctorJson` uses `precomputedFunctionStatus ?? BuildConfiguredFunctionStatus(...)` to skip re-computation when data is provided.\n- Belt-and-suspenders guard: `BuildDoctorJson` independently checks `configuredFunctionStatus.All(s => s.Found || s.ResolutionReason is null)` before calling `DiagnoseMissingCommands`, so standalone callers still get diagnosis but the `RunDoctorAsync` path doesn't double-execute.\n- `ConfiguredFunctionStatus` promoted from `private` to `internal` — necessary for the type to appear in `BuildDoctorJson`'s parameter list. Safe: sealed record, assembly-scoped.\n\n**Rejection lockout pattern validated:** Hermes wrote the bug, was locked out, Bender delivered the fix cleanly. Pattern works — fresh eyes caught what the original author missed.\n\n### 2026-07-15: Authored 4 new team skills from history review\n\nSkills created: worktree-pr-merge, precomputed-optional-parameter, unserializable-type-handling, cli-bool-flag-pattern.\nAll at confidence: medium (except unserializable-type-handling: high — 33 tests).\nSource: earned patterns from PRs #92–#96 and agent histories.\n\n📌 Team update (2026-04-14T00:00:00Z): Docs publishing now uses a dedicated GitHub Pages workflow with docs-only path trigger and prebuilt `docs/_site` artifact strategy — decided by Amy.\n\n### 2026-07-15: MCP Resources and Prompts spec authored\n\n**Spec:** `specs/002-mcp-resources-and-prompts/spec.md`\n\n**Key decisions:**\n- `McpResources` and `McpPrompts` are top-level `appsettings.json` siblings to `PowerShellConfiguration` — MCP-layer concerns belong at MCP layer, not nested under execution config\n- Two source types for both: `\"file\"` (read at request time, relative to `appsettings.json` dir) and `\"command\"` (executed in shared runspace, no new runspace)\n- URI scheme `poshmcp://resources/{slug}` is recommended but not enforced; doctor warns, does not error\n- Prompt argument injection uses pre-assignment (`$argName = value`) before command string executes — not `-ArgumentList` (avoids requiring `param()` blocks)\n- File-backed prompt argument substitution deferred to v1+ — file returned verbatim, client does template rendering\n- No resource caching in server; operators build caching into PowerShell commands if needed\n- Resource subscriptions out of scope — four read-path SDK handlers are sufficient for v1\n- SDK registration via `WithListResourcesHandler`, `WithReadResourceHandler`, `WithListPromptsHandler`, `WithGetPromptHandler` in `Program.cs`\n- FR numbering starts at FR-018 (after FR-017 from spec 001); SC numbering starts at SC-009 (after SC-008)\n- Doctor validation contract fully specified including severity levels and JSON output shape\n\n### 2026-04-17: Spec restructure — loose specs → speckit format\n\n**What was done:**\n- Rewrote `specs/powershell-interactive-input.md`, `specs/out-of-process-execution.md`, and `specs/large-result-performance.md` into the speckit format (matching specs 001 and 002)\n- Created `specs/003-powershell-interactive-input/spec.md`, `specs/004-out-of-process-execution/spec.md`, `specs/005-large-result-performance/spec.md`\n- Numbering: FR-035–FR-064, SC-016–SC-030; next available FR-065, SC-031\n\n**Patterns noted:**\n- Original loose specs were RFC-style design docs (implementation code, C# classes, architecture diagrams) — speckit strips all of that; requirements must be written from user perspective with no class names\n- The stateless retry pattern (Option D in the interactive input RFC) is the correct architecture for prompt handling given MCP's request/response model — captured as the design assumption in spec 003\n- \"Fail-fast\" is the right default for prompt behavior; structured prompt response is P2 (requires fail-fast infrastructure first)\n- Property filtering via `DefaultDisplayPropertySet` should be ON by default (95%+ payload reduction); result caching via `Tee-Object` should be OFF by default (most callers never use replay tools)\n- Spec 003 (prompt handling) logically precedes spec 004 (OOP) because the OOP interactive prompt strategy is defined as \"defer to spec 003 / fail-fast in OOP mode\"\n\n### 2026-07-18: PR #130 review — approved (MimeType nullable fix)\n\n**PR:** #130 (fixes #129) — `Fix MimeType default — null model property, apply text/plain at runtime in handler`\n**Verdict:** APPROVED\n\n**Pattern validated — \"model reflects truth, handler applies default\":**\n- `McpResourceConfiguration.MimeType` changed from `string` (default `\"text/plain\"`) to `string?` (no default)\n- Runtime fallback `?? \"text/plain\"` applied via `string.IsNullOrWhiteSpace()` in `McpResourceHandler` at both list and read response sites\n- Validator already used `IsNullOrWhiteSpace` — no change needed there\n- All 3 `.MimeType` access sites in server code audited and confirmed null-safe\n- Edge cases (empty string, whitespace) handled by `IsNullOrWhiteSpace` in both handler and validator\n- No serialization cascade — MimeType is consumed, never re-serialized from the model\n- Build: 0 errors; Tests: 471 passed, 0 failed\n\n**Key pattern:** When a config property has a protocol-level default, keep the model nullable to distinguish \"not configured\" from \"explicitly configured to the default value\". Apply the default at the last responsible moment (the handler constructing the response).\n### 2026-04-18: PR #130 review (issue #129 — MimeType fix)\n\n**Verdict:** ✅ APPROVED\n**Summary:** MimeType model nullable change restores validator signal while maintaining runtime fallback behavior. All 471 tests pass, 0 build warnings. Validator correctly flags missing MimeType in config; handler provides runtime \"text/plain\" default in HandleListAsync and HandleReadAsync.\n**Key takeaway:** Model defaults that prevent validators from firing should be moved to runtime handlers. This preserves diagnostic signals while keeping runtime contracts stable.\n\n### 2026-07-18: Issue #131 triage — STDIO logging to file\n\n**Decisions made:**\n- Use Serilog (Serilog.Extensions.Hosting + Serilog.Sinks.File) as the file logging provider; no existing file logger in the project, Serilog is the idiomatic .NET choice\n- In stdio mode: `builder.Logging.ClearProviders()` unconditionally, then add Serilog file sink only if a log file path is configured — silent by default, no startup failure\n- Log file resolution priority: `--log-file` CLI > `POSHMCP_LOG_FILE` env var > `Logging.File.Path` appsettings key > silent\n- OTel `AddConsoleExporter()` suppressed in stdio mode by passing `isStdioMode` flag to `ConfigureOpenTelemetry`; HTTP path unchanged\n- HTTP transport logging behavior is entirely unchanged\n- Pre-startup `Console.Error.WriteLine` error paths stay as-is (correct for CLI errors before stdio server starts)\n\n**Branch created:** `squad/131-stdio-logging-to-file`\n\n**Agents assigned:**\n- **Bender** — C# implementation: `Program.cs` changes, Serilog wiring, `--log-file` CLI option, `POSHMCP_LOG_FILE` env var, unit + integration tests\n- **Amy** — OTel console suppression, `appsettings.json` schema (`Logging.File.Path`), documentation (README.md, DOCKER.md, appsettings.environment-example.json)\n\n**GitHub note:** Label addition and issue comment blocked by Enterprise Managed User policy — triage notes saved to `.squad/decisions/inbox/farnsworth-131-stdio-logging-design.md` instead.\n\n### 2026-07-18: PR #132 review — approved (STDIO logging suppression)\n\n**PR:** #132 (fixes #131) — `feat: suppress console logging in stdio transport, add Serilog file sink`\n**Verdict:** APPROVED\n\n**Implementation quality:** Clean match to design spec. Bender handled C# changes (ConfigureStdioLogging, ResolveLogFilePath, CLI option, Serilog wiring), Amy handled OTel suppression, appsettings schema, and documentation. No merge conflicts expected.\n\n**Key validation points:**\n- `ClearProviders()` is unconditionally first in `ConfigureStdioLogging` — correct\n- Serilog packages updated to 10.0.0/10.0.0/7.0.0 (newer than spec's 9.0.0/9.0.0/6.0.0) — correct per spec guidance\n- OTel `AddConsoleExporter()` properly gated by `isStdioMode` flag\n- 3-tier resolution (CLI > env > config > silent) works correctly\n- HTTP transport completely unaffected\n- 10 new tests (7 unit + 3 functional), all pass; full suite 487/0/1\n\n**Non-blocking notes:**\n- `default.appsettings.json` (embedded) missing `Logging.File.Path` — absent = silent, functionally correct\n- Root handler (bare `poshmcp`) doesn't resolve `POSHMCP_LOG_FILE` — legacy path, low priority\n- Pattern: `CreateLoggerFactory` didn't need changes because it's never called from the stdio server path — design spec was overcautious on this point\n\n### 2026-07-18: PR #134 review — approved (docker buildx missing build context path)\n\n**PR:** #134 (fixes #133) — `fix(#133): add missing build context path to docker buildx build command`\n**Verdict:** APPROVED (comment posted — GitHub blocked self-review via API)\n\n**Fix:** Single-character change: added ` .` to the end of `buildArgs` in the `buildCommand.SetHandler` lambda in `Program.cs` line 692.\n\n**Validation points:**\n- Bug is real: `docker build` requires a PATH argument for the build context; without it the command fails unconditionally\n- `File.Exists(imageFile)` guard before the build args line implicitly validates CWD — if CWD were wrong, the Dockerfile check exits early with `ExitCodeConfigError`; by the time `.` is appended, CWD is the repo root\n- Consistent with entire codebase: `docker.ps1` (3 sites), `docker.sh`, `infrastructure/azure/deploy.ps1`, `infrastructure/azure/deploy.sh` all use `.` as build context\n- CI (`publish-packages.yml`) invokes from repo root — no CWD surprise\n\n**Pattern noted:** When a CLI tool wraps an external command, every required positional argument must be present in the assembled arg string. The `File.Exists` guard doubles as implicit CWD validation — a pattern worth documenting for future Docker command wrappers.\n\n### 2025-07-17: PR #135 re-review — second pass confirmation\n\n**PR:** #135 — `refactor: extract LoggingHelpers, DockerRunner, SettingsResolver, ConfigurationFileManager, ConfigurationLoader from Program.cs`\n**Verdict:** APPROVED (comment — self-approval blocked by GitHub)\n\n**Second-pass validation (independent of Steven's self-review):**\n- Verified all 5 files contain exactly the methods specified in items 1–4 of `specs/program-cs-refactor.md`\n- Scanned all 60+ call sites in Program.cs — every one uses the new class prefix (`LoggingHelpers.`, `DockerRunner.`, `SettingsResolver.`, `ConfigurationFileManager.`, `ConfigurationLoader.`). Zero stale unqualified calls.\n- Confirmed no method definitions are duplicated between Program.cs and the new files via `private static|internal static` scan.\n- Namespace (`namespace PoshMcp;`) and visibility (`internal static`) uniform across all 5 files.\n- Program.cs is 2,100 lines — expected intermediate state. Bulk reduction in PRs E–H.\n- `ExitCodeRuntimeError = 4` duplication noted again (Program.cs + DockerRunner.cs). Non-blocking. Candidate for shared constants.\n- `args` closure, static mutable state, `UpgradeConfigWithMissingDefaultsAsync` coupling — all handled per plan.\n\n**Pattern for future PRs:** The combined A–D approach worked well for \"safe\" extractions (pure function moves). PRs E–G (doctor, tool setup, server hosts) have more cross-cutting dependencies and should be individual PRs as the plan recommends.\n\n### 2025-07-18: PR #138 review — approved (Dockerfile restore/build fix)\n\n**PR:** #138 (fixes #136) — `fix(#136): Fix Dockerfile restore/build`\n**Verdict:** APPROVED\n\n**Fix:** Two-line change: `dotnet restore PoshMcp.sln` → `dotnet restore PoshMcp.Server/PoshMcp.csproj`, `dotnet build PoshMcp.sln` → `dotnet build PoshMcp.Server/PoshMcp.csproj`. Fixes container build failure when only PoshMcp.Server.csproj is copied in the early layer but restore/build targeted the full solution (which references TestClient and PoshMcp.Tests not present in the container).\n\n**Non-blocking nit:** `COPY PoshMcp.sln ./` on line 9 is now dead weight — no build command references it. Candidate for cleanup.\n\n### 2025-07-18: PR #139 review — approved (doctor config coverage)\n\n**PR:** #139 (fixes #137) — `feat(#137): Add auth, logging, env vars, MCP definitions to doctor`\n**Verdict:** APPROVED\n\n**Implementation quality:** 4 new diagnostic sections in both text and JSON output. 12 tests with well-designed disposable helpers (`DoctorConfigFile`, `DoctorConsoleCapture`, `DoctorEnvVarScope`). All 7 env vars covered. `BuildDoctorJson` new parameters use `= null` defaults with null-coalescing fallback — zero impact on existing callers. `[Collection(\"TransportSelectionTests\")]` correctly prevents parallel execution. No trailing whitespace.\n\n**Non-blocking nits:**\n1. `TryLoadResourcesAndPromptsDefinitions` called unconditionally in `BuildDoctorJson` even when both values pre-supplied — should be guarded like auth/logging 3 lines above (same class of issue as PR #96 rejection, but much lower cost).\n2. `POSHMCP_LOG_FILE` (added in PR #132) absent from env vars list — follow-up candidate.\n\n**Pattern noted:** The precomputed-optional-parameter pattern (from PR #96) continues to be the correct approach for `BuildDoctorJson` — compute expensive data once in `RunDoctorAsync`, pass via optional params, let `BuildDoctorJson` self-compute only when called standalone.\n\n## Cross-Agent: PR Review Approved (2026-04-20)\n\n- Amy fixed PR #138 feedback (worktree poshmcp-136) \n- Bender fixed PR #139 feedback (worktree poshmcp-137)\n- Both PRs approved with nits resolved\n\n### 2026-04-20: Spec 006 — Doctor Output Restructure milestone created\n\n**Actions taken:**\n1. Renamed `specs/doctor-output-restructure/` → `specs/006-doctor-output-restructure/` via git mv, added spec number to frontmatter, committed and pushed to main.\n2. Created GitHub milestone #3: \"Spec 006 - Doctor Output Restructure\" (https://github.com/usepowershell/PoshMcp/milestone/3).\n3. Created 27 GitHub issues (T001–T027, #140–#166) across 8 phases:\n - **Bender** (squad:bender): 22 issues — Phases 1–6 (T001–T018) and Phase 8 (T024–T027)\n - **Fry** (squad:fry): 5 issues — Phase 7 (T019–T023, tests)\n\n**Issue mapping:**\n- Phase 1 (DoctorReport Record Hierarchy): T001=#140, T002=#141, T003=#142, T004=#143, T005=#144\n- Phase 2 (DoctorTextRenderer): T006=#145, T007=#146, T008=#147, T009=#148\n- Phase 3 (Wire into RunDoctorAsync): T010=#149, T011=#150, T012=#151\n- Phase 4 (Environment Variables): T013=#152, T014=#153\n- Phase 5 (Summary Banner): T015=#154, T016=#155\n- Phase 6 (Update MCP Tool): T017=#156, T018=#157\n- Phase 7 (Tests): T019=#158, T020=#159, T021=#160, T022=#161, T023=#162\n- Phase 8 (Cleanup/Validation): T024=#163, T025=#164, T026=#165, T027=#166\n\n**Note:** Push to main required rebase to remove a pre-existing merge commit (a77dfcc) that violated repo rules.\n\n### 2026-07-28: PR #167 review — approved (Spec 006: Doctor Output Restructure)\n\n**PR:** #167 — `feat(spec-006): restructure doctor output`\n**Verdict:** ✅ APPROVED (comment — self-approval blocked by GitHub)\n\n**Implementation quality:** Clean match to spec 006. Architecture is solid: `DoctorReport` (pure data model with records + `[JsonPropertyName]`), `DoctorTextRenderer` (static class, pure rendering), `Program.cs` (thin orchestration). Build: 0 errors. Tests: 520 passed, 0 failed, 7 skipped.\n\n**Spec compliance verified:**\n- Banner: `╔═══╗` box-drawing chars, `BannerInnerWidth = 42`, correct status symbols (✓/⚠/✗)\n- Section headers: `── Name ──` format, padded to 44 chars\n- JSON: 7 top-level keys match FR-106, `effectivePowerShellConfiguration` dropped, camelCase throughout\n- ComputeStatus: `errors > warnings > healthy` precedence per FR-102\n- ResolvedSetting: `value`/`source` pairs per FR-107\n\n**Must-fix nits (3):**\n1. MCP tool description says \"Outputs structured text by default; pass argument '--json'\" — tool always returns JSON, no format argument exists. Misleading to LLM clients.\n2. `POSHMCP_LOG_FILE` missing from `CollectEnvironmentVariables` — FR-113 violation, flagged since PR #139.\n3. `POSHMCP_CONFIG` should be `POSHMCP_CONFIGURATION` in `CollectEnvironmentVariables` — pre-existing bug; `SettingsResolver.cs` defines the env var as `POSHMCP_CONFIGURATION`.\n\n**Non-blocking observations:**\n- `✖` (U+2716) vs `✗` (U+2717) inconsistency in `RenderMcpDefinitions` vs `StatusSymbol`\n- Auth/logging config removed from output (technically FR-109 information loss, but defensible per spec's \"placeholder\" language)\n- Extra env vars added beyond spec's 8 (POSHMCP_FUNCTION_NAMES, POSHMCP_COMMAND_NAMES, DOTNET_ENVIRONMENT) — additive, fine\n"
},
"fry": {
"charter": "# Fry — Tester\n\n## Role\n\nQuality assurance and testing specialist for PoshMcp.\n\n## Responsibilities\n\n- Write comprehensive unit tests\n- Create integration test scenarios\n- Build performance baseline tests\n- Test resilience patterns (circuit breaker, retry, timeout)\n- Verify error handling paths\n- Find edge cases and boundary conditions\n- Ensure test coverage for new features\n\n## Domain Expertise\n\n- xUnit testing framework\n- Integration testing patterns\n- Performance testing and benchmarking\n- Mocking and test isolation\n- Testing async code\n- Parameterized tests and test data\n- Test organization and maintainability\n\n## Focus Areas\n\n- Testing new error handling framework\n- Circuit breaker behavior tests\n- Retry logic with exponential backoff tests\n- Timeout handling tests\n- Health check endpoint tests\n- Metrics recording tests\n- Performance regression tests\n\n## Working Style\n\n- Think about what could go wrong\n- Test the unhappy paths, not just happy paths\n- Create tests that fail clearly when broken\n- Keep tests fast and isolated\n- Document complex test scenarios\n\n## Collaboration\n\n- Works with **Bender** on testing backend implementations\n- Works with **Hermes** on PowerShell-specific test scenarios\n- Works with **Amy** on testing observability features\n- Reports to **Farnsworth** for test strategy decisions\n\n## Test Organization\n\nCurrent structure (respect this):\n- `PoshMcp.Tests/Unit/` - Fast, isolated unit tests\n- `PoshMcp.Tests/Functional/` - Feature-focused tests\n- `PoshMcp.Tests/Integration/` - End-to-end tests\n- `PoshMcp.Tests/Shared/` - Test utilities\n\n## Output Standards\n\n- Tests are fast (unit < 100ms, integration < 5s)\n- Tests are isolated and deterministic\n- Test names clearly describe what's being tested\n- Complex scenarios include explanatory comments\n- Tests fail with clear error messages\n",
"history": "# Fry Work History\n\n## Recent Work (2026-04-20 — CURRENT SESSION)\n\n### Docker Build Arguments Unit Tests\n**Branch:** background→sync \n**Status:** Complete\n\n- **Task (Fry)**: Create comprehensive unit test suite for Docker build arguments\n- **Implementation**: Created `PoshMcp.Tests/Unit/DockerRunnerTests.cs` with 11 test cases\n- **Coverage**: All PoshMcp Docker build scenarios (minimal config, buildkit, registries, multi-arch, custom paths, ignore patterns, error handling, labels, caching, build args, output format)\n- **Outcome**: All 11 tests passing ✅\n- **Coordination**: Tests verify Bender's extracted `DockerRunner.BuildDockerBuildArgs` method thoroughly\n\n**Test results summary:**\n- 11/11 passing\n- Covers argument construction, registry handling, multi-architecture builds, error paths\n- Validates build argument ordering and formatting\n\n## Recent Status (2026-07-18: Spec 006 Phase 7 — Doctor Output Tests (T019–T023)\n\n**Branch:** `squad/spec006-doctor-output-restructure` (worktree `poshmcp-spec006`)\n\n**New test files created:**\n- `PoshMcp.Tests/Unit/DoctorReportTests.cs` — 14 tests: `ComputeStatus` (healthy/errors/warnings/resource-errors/prompt-errors/resource-warnings), `DoctorSummary` property assertions, JSON top-level key verification (T021 combined), camelCase name assertions, `effectivePowerShellConfiguration` absence check\n- `PoshMcp.Tests/Unit/DoctorTextRendererTests.cs` — 14 tests: banner box-drawing chars, status symbols (✓/⚠/✗), section headers (Runtime Settings/Env Vars/PowerShell/Functions-Tools/MCP Definitions), header format validation, conditional Warnings section (present/absent)\n\n**Existing test files updated (T022):**\n- `ProgramDoctorConfigCoverageTests.cs` — replaced 12 failing tests: removed `authenticationConfig`/`loggingConfig`/old resource+prompt assertions; added `runtimeSettings`, `summary.status`, `mcpDefinitions.resources`, `mcpDefinitions.prompts`, new text section header checks (`── Environment Variables`, `── Runtime Settings`, `── MCP Definitions`), auth-absent test\n- `ProgramDoctorToolExposureTests.cs` — fixed `GetToolNames` to use `functionsTools.toolNames`; removed `effectivePowerShellConfiguration` assertion\n- `ProgramConfigurationGuidanceToolExposureTests.cs` — fixed `GetToolNames` to use `functionsTools.toolNames`\n- `ProgramTransportSelectionTests.cs` — updated all 8 tests: flat keys (`effectiveTransport`, `effectiveSessionMode`, etc.) → nested (`runtimeSettings.transport.value`, `runtimeSettings.sessionMode.value`, etc.); `PayloadContainsConfiguredModulePath` now checks `powerShell.oopModulePaths`\n- `ProgramTests.cs` — fixed `oopModulePaths`/`oopModulePathEntries` → `powerShell.oopModulePaths`/`powerShell.oopModulePathEntries`\n\n**Result:** 527 total — 520 passed, 7 skipped (pre-existing), 0 failed ✅\n`dotnet format --verify-no-changes` clean. Commit `f38b9b9` pushed.\n\n**Key patterns established:**\n- New JSON shape: all runtime settings under `runtimeSettings.{key}.value` / `.source`\n- Tool names under `functionsTools.toolNames`\n- OOP module paths under `powerShell.oopModulePaths`/`oopModulePathEntries`\n- No `authenticationConfig`, `loggingConfig`, `effectivePowerShellConfiguration` in new JSON\n- Text output sections use `── Section Name ──...` headers (44-char padded)\n\n**[Earlier detailed history 2026-04-14 and prior archived to history-archive.md on 2026-04-18 per Scribe threshold policy. Preserving last 90 days (2026-04-21 onwards) in main history.]**\n\n\n\n### 2026-04-15: Cross-agent verification pattern for auth behavior\n\n- Bender's resolver improvements should be validated with both precedence-focused tests and docs wording review in the same handoff.\n- For configuration behavior, lock exact-match precedence with regression tests and keep docs explicit about recommended key style versus currently accepted key styles.\n\n### 2026-04-18: Spec 002 Final Verification — Full Suite Run on feature/002-tests (rebased)\n\n**Context:** Hermes rebased `feature/002-tests` onto main and removed all 16 Skip attributes from `McpResourcesIntegrationTests` and `McpPromptsIntegrationTests`. Task was to run the full test suite and confirm readiness for merge (PR #128).\n\n**Test run result:** 478 total — 470 passed, 1 failed, 7 skipped (duration ~247s)\n\n**Spec 002 integration tests:** 16/16 pass ✅\n- 8 `McpResourcesIntegrationTests`: all passing (resources/list, resources/read, file/command sources, error paths)\n- 8 `McpPromptsIntegrationTests`: all passing (prompts/list, prompts/get, file/command sources, argument injection, error paths)\n- Zero Skip attributes remain on spec-002 tests\n\n**The one failure (pre-existing, non-blocking):**\n- Test: `McpResourcesValidatorTests.Validate_ResourceWithNoMimeType_ReportsMimeTypeWarning`\n- Cause: `McpResourceConfiguration.MimeType` defaults to `\"text/plain\"` at the C# object level. The test creates a resource without setting MimeType, expecting the validator to warn, but the property already carries `\"text/plain\"` — so `IsNullOrWhiteSpace` is never true.\n- Pre-existing since `a2ade16` (original resources implementation). Not introduced by Hermes's rebase.\n- Remediation (future, not blocking): change `MimeType` default to `null`/empty and apply `\"text/plain\"` at runtime.\n\n**Skips (7, all pre-existing):**\n- 6 `OutOfProcessModuleTests` — out-of-process mode not yet integrated\n- 1 `Functional.ReturnType.GeneratedMethod.ShouldHandleGetChildItemCorrectly` — pre-existing\n\n**Verdict: ✅ CLEAR TO MERGE — PR #128**\n\n### 2026-04-18: Issue #129 MimeType Fix Validation\n\n- Verified that `Validate_ResourceWithNoMimeType_ReportsMimeTypeWarning` was never skipped — it was failing.\n- Root cause: `McpResourceConfiguration.MimeType` had C# default `\"text/plain\"`, so `IsNullOrWhiteSpace` check never fired.\n- Once Bender made property nullable (commit `6a93c3d`), validator logic fired correctly and test passed.\n- Updated inline comment in test to document nullable behavior; test logic required no changes.\n- All 9 validator tests pass; finding drives key learning: failing tests with no Skip attribute often need implementation fixes, not test harness changes.\n- **Commit:** `1419a20` on `squad/129-fix-mimetype-nullable` (Coordinator rebased)\n- **PR #130** ready for review.\n\n### 2026-07-18: Issue #131 — Stdio logging suppression tests\n\n**Branch:** `squad/131-stdio-logging-to-file`\n\n**Test files created:**\n- `PoshMcp.Tests/Unit/StdioLoggingConfigurationTests.cs` — 8 unit tests for `ResolveLogFilePath` resolution priority\n- `PoshMcp.Tests/Functional/StdioLoggingTests.cs` — 2 functional tests for stdio logging suppression/file routing\n\n**Unit tests (reflection-based):**\n- `ResolveLogFilePath` is `private static` in `Program.cs` so tests use `BindingFlags.NonPublic | BindingFlags.Static` reflection\n- Return type `ResolvedSetting` is a private sealed record; properties accessed via reflection too\n- Covered: CLI > env var, env var > null, null both = null/default, appsettings fallback, CLI > appsettings, env > appsettings, whitespace CLI falls back to env\n\n**Functional tests:**\n- Use `InProcessMcpServer` + `ExternalMcpClient` from `PoshMcp.Tests.Integration` namespace (same project, public classes)\n- `WithNoLogFile`: asserts no Serilog `[yyyy-MM-dd HH:mm:ss LVL]` or MEL `info:` lines appear on server stderr\n- `WithLogFile`: passes `serve --log-file <path>` as extraArgs; Serilog uses `RollingInterval.Day` so search for `basename*.log`; assert file exists and has content\n- All 10 tests (8 unit + 2 functional) pass; total run ~11s\n\n**Testing infrastructure notes:**\n- `ImplicitUsings` is disabled in the test project — all `using` statements must be explicit\n- `AddInMemoryCollection` available via transitive `Microsoft.Extensions.Configuration` dependency from `PoshMcp.Server`\n- `EnvironmentVariableScope` helper pattern (save/restore env var) reused from `ProgramTransportSelectionTests.cs` style\n\n### 2026-07-18: Spec 006 Phase 7 — Doctor Output Tests (T019–T023)\n\n**Branch:** `squad/spec006-doctor-output-restructure` (worktree `poshmcp-spec006`)\n\n**New test files created:**\n- `PoshMcp.Tests/Unit/DoctorReportTests.cs` — 14 tests: `ComputeStatus` (healthy/errors/warnings/resource-errors/prompt-errors/resource-warnings), `DoctorSummary` property assertions, JSON top-level key verification (T021 combined), camelCase name assertions, `effectivePowerShellConfiguration` absence check\n- `PoshMcp.Tests/Unit/DoctorTextRendererTests.cs` — 14 tests: banner box-drawing chars, status symbols (✓/⚠/✗), section headers (Runtime Settings/Env Vars/PowerShell/Functions-Tools/MCP Definitions), header format validation, conditional Warnings section (present/absent)\n\n**Existing test files updated (T022):**\n- `ProgramDoctorConfigCoverageTests.cs` — replaced 12 failing tests: removed `authenticationConfig`/`loggingConfig`/old resource+prompt assertions; added `runtimeSettings`, `summary.status`, `mcpDefinitions.resources`, `mcpDefinitions.prompts`, new text section header checks (`── Environment Variables`, `── Runtime Settings`, `── MCP Definitions`), auth-absent test\n- `ProgramDoctorToolExposureTests.cs` — fixed `GetToolNames` to use `functionsTools.toolNames`; removed `effectivePowerShellConfiguration` assertion\n- `ProgramConfigurationGuidanceToolExposureTests.cs` — fixed `GetToolNames` to use `functionsTools.toolNames`\n- `ProgramTransportSelectionTests.cs` — updated all 8 tests: flat keys (`effectiveTransport`, `effectiveSessionMode`, etc.) → nested (`runtimeSettings.transport.value`, `runtimeSettings.sessionMode.value`, etc.); `PayloadContainsConfiguredModulePath` now checks `powerShell.oopModulePaths`\n- `ProgramTests.cs` — fixed `oopModulePaths`/`oopModulePathEntries` → `powerShell.oopModulePaths`/`powerShell.oopModulePathEntries`\n\n**Result:** 527 total — 520 passed, 7 skipped (pre-existing), 0 failed ✅\n`dotnet format --verify-no-changes` clean. Commit `f38b9b9` pushed.\n\n**Key patterns established:**\n- New JSON shape: all runtime settings under `runtimeSettings.{key}.value` / `.source`\n- Tool names under `functionsTools.toolNames`\n- OOP module paths under `powerShell.oopModulePaths`/`oopModulePathEntries`\n- No `authenticationConfig`, `loggingConfig`, `effectivePowerShellConfiguration` in new JSON\n- Text output sections use `── Section Name ──...` headers (44-char padded)\n\n\n\nDetailed prior history (2026-03-27 through 2026-04-07) archived to `history-archive.md` when this file exceeded 15 KB threshold on 2026-04-18.\n"
},
"hermes": {
"charter": "# Hermes — PowerShell Expert\n\n## Role\n\nPowerShell integration specialist and runspace management expert for PoshMcp.\n\n## Responsibilities\n\n- Manage PowerShell runspace lifecycle and state\n- Implement PowerShell command execution patterns\n- Handle PowerShell-specific error scenarios\n- Optimize runspace initialization and cleanup\n- Work with PowerShell SDK APIs\n- Implement command execution timeouts\n- PowerShell command tracing and diagnostics\n\n## Domain Expertise\n\n- PowerShell SDK (System.Management.Automation)\n- Runspace management and threading\n- PowerShell error streams and exception handling\n- PowerShell command introspection (Get-Command, Get-Help)\n- PowerShell module discovery and loading\n- PSObject serialization and deserialization\n\n## Focus Areas\n\n- PowerShell runspace health and resilience\n- Command execution with timeout handling\n- PowerShell command tracing\n- Runspace initialization scripts\n- Error stream processing\n- State management across command invocations\n\n## Working Style\n\n- Understand PowerShell semantics deeply\n- Handle all PowerShell error scenarios explicitly\n- Optimize for performance without sacrificing correctness\n- Document PowerShell-specific behaviors\n\n## Collaboration\n\n- Works with **Bender** on integration points between C# and PowerShell\n- Works with **Amy** on PowerShell-specific metrics and tracing\n- Works with **Fry** on PowerShell test scenarios\n- Reports to **Farnsworth** for architectural PowerShell patterns\n\n## Key Challenges\n\n- Thread safety in runspace access\n- Proper cleanup to prevent resource leaks\n- Handling PowerShell terminating vs non-terminating errors\n- Balancing runspace reuse vs isolation\n- Timeout handling without corrupting runspace state\n",
"history": "# Hermes Work History\n- **20260403T135630Z**: ✓ Docker fixes & scripts reviews compiled and merged into decision ledger.\n- **20260408T000000Z**: ✓ Reviewed/recorded deploy.ps1 hardening for transient ACR OAuth EOF failures: bounded retry loops, transient error classification, and improved failure diagnostics.\n- **20260418T000000Z**: ✓ Rebased feature/002-tests onto main; resolved 5 add/add conflicts (McpResources + McpPrompts config classes, kept main implementation); removed Skip attrs from 16 integration tests (8 McpResources + 8 McpPrompts); all 16 passed; force-pushed.\n# Hermes Work History\n## Project Context\n**Project:** PoshMcp - Model Context Protocol (MCP) server for PowerShell\n**Tech Stack:** .NET 10, C#, PowerShell SDK, OpenTelemetry, ASP.NET Core, xUnit\n**Primary User:** Steven Murawski\n**Key Files:**\n- `PoshMcp.Server/PowerShell/PowerShellRunspaceHolder.cs` - Singleton runspace management\n- `PoshMcp.Server/PowerShell/PowerShellRunspaceImplementations.cs` - Runspace implementations\n- `PoshMcp.Server/PowerShell/PowerShellAssemblyGenerator.cs` - Dynamic assembly generation\n- `PoshMcp.Server/PowerShell/PowerShellCleanupService.cs` - Cleanup lifecycle\n- `PoshMcp.Server/PowerShell/PowerShellConfiguration.cs` - Configuration model\n### 2026-04-03: Session Summary\n**Status:** 2026-03-27 work (PowerShell streams refactoring, multi-tenant review, deployment script patterns) complete.\n**Review Results:** Amy's multi-tenant implementation APPROVED (9/10 PowerShell quality).\n\n### 2026-04-08: Serialization normalization fixes recorded\n\n**Context:** Closed out the serializer migration fixes for string and nested object handling.\n\n**Key learnings:**\n- Scalar `PSObject.BaseObject` values need an early leaf-value path before property enumeration\n- Nested PowerShell and CLR objects should be normalized into JSON-safe scalars, dictionaries, and arrays before `System.Text.Json` runs\n- Serialization fixes need paired coverage so live execution and cached outputs preserve the same shape\n\n### 2026-07: Large result set hang analysis (Get-Process)\n\n**Context:** Diagnosed why `Get-Process` and similar cmdlets hang when called via MCP.\n\n## Learnings\n\n**Execution pipeline flow (key facts):**\n- `ExecutePowerShellCommandTyped` (`PowerShellAssemblyGenerator.cs:534`) is the single entry point for all tool invocations.\n- It calls `runspace.ExecuteThreadSafeAsync<string>(ps => { ... return Task.FromResult(...) })` — the lambda is synchronous; it never awaits anything.\n- `InvokePowerShellSafe` (line 1008) calls `ps.Invoke()` — fully synchronous, no CancellationToken support.\n- The singleton `PowerShellRunspaceHolder` guards the runspace with `SemaphoreSlim(1,1)`, so a hung invocation blocks all subsequent tool calls.\n- A `TimeoutException` catch path exists in the outer try/catch, but nothing in the code ever raises it — there is effectively zero timeout enforcement.\n\n**Serialization depth hazard for CLR objects:**\n- `PowerShellObjectSerializer.GetSafeProperties` wraps any CLR object in a `PSObject` and enumerates ALL reflected properties.\n- `System.Diagnostics.Process` has ~50 properties. Several (`Modules`, `MainModule`, `Threads`, `Handle`) make Win32 API calls that can block indefinitely on protected or system processes — these stalls are not caught by the surrounding `try/catch` because they don't throw, they block.\n- 200-300 processes × 50 properties each = ~10,000–15,000 property accesses per `Get-Process` call.\n\n**`Tee-Object` in the pipeline amplifies memory pressure:**\n- Every tool invocation pipes through `Tee-Object -Variable LastCommandOutput` to cache results.\n- For `Get-Process`, this keeps all 200-300 live `Process` objects (with OS handles) in memory simultaneously through the serialization pass.\n\n**Recommended fix order:**\n1. **Result count cap** (Approach B, quick win): truncate to ~50 results before serialization; include totalCount in response.\n2. **Property shaping for known CLR types** (Approach A, medium effort): type-specific shapersfor `Process`, `Service`, `FileInfo` that emit only AI-useful properties.\n3. **Async invocation with CancellationToken** (Approach C, high effort): use `InvokePowerShellSafeAsync` in the main execution path and thread the CancellationToken through.\n\n### 2026-07: PropertySetDiscovery and serializer refinement\n\n**Context:** Phase 3 crash recovery — implemented DefaultDisplayPropertySet discovery and refined serializer.\n\n**Key files:**\n- `PoshMcp.Server/PowerShell/PropertySetDiscovery.cs` — Discovery of DefaultDisplayPropertySet via Get-Command OutputType + Get-TypeData. Uses temporary runspace, ConcurrentDictionary cache, best-effort (returns null on failure).\n- `PoshMcp.Server/PowerShell/PowerShellObjectSerializer.cs` — Refined `NormalizePSPropertyValue`: IDictionary now recursively normalized instead of `.ToString()` (dictionaries are bounded key-value maps). IEnumerable kept as `.ToString()` (expensive to enumerate, e.g., ProcessModuleCollection).\n\n**Design decisions:**\n- PropertySetDiscovery uses temporary runspace, NOT the singleton — runs at assembly generation time before the server is fully initialized.\n- Two-step lookup: Get-Command → OutputType names → Get-TypeData → DefaultDisplayPropertySet.ReferencedProperties.\n- DiscoverAll() shares a single runspace across all commands for startup efficiency.\n- IDictionary vs IEnumerable split in shallow path: dictionaries are safe JSON maps; enumerables may trigger OS calls.\n\n### 2026-04-10: Recovery learnings for module layout and host-script safety\n\n**Key learnings:**\n- The split `integration/Modules/*` layout is the canonical integration-module shape; umbrella-module path assumptions are stale.\n- Partial vendored trees like `integration/Modules/Az.AppConfiguration/2.0.1` are likely merge fallout and should be removed rather than patched around.\n- Module discovery needs explicit import-before-discovery ordering when autoloading cannot be trusted.\n- If the host script work resumes, keep stdout protocol-only, route diagnostics to stderr, and resolve commands through `Get-Command` plus `CommandInfo` invocation instead of string evaluation.\n\n### 2026-04-11: Cross-agent update — Out-of-process execution plan filed\n\n**Context:** Farnsworth filed a comprehensive OOP execution plan at `specs/out-of-process-execution.md`.\n\n**Key points for Hermes:**\n- Communication protocol is ndjson over stdin/stdout (supersedes the localhost TCP direction from 2026-04-10)\n- Phase 3 (command discovery) involves the subprocess discovering commands via `Get-Command` and reporting back — similar to `PropertySetDiscovery` patterns Hermes already implemented\n- `oop-host.ps1` uses the host-script safety rules Hermes helped define: stdout protocol-only, stderr for diagnostics, `Get-Command` + `CommandInfo` invocation\n- Phase 6 (integration testing) will use modules from `integration/Modules/` — the canonical split layout Hermes helped establish\n- Crash recovery with automatic subprocess restart and exponential backoff\n\n### 2026-04-11: Created oop-host.ps1 — OOP subprocess host script (Issue #57, Phases 2-4)\n\n**File:** `PoshMcp.Server/PowerShell/OutOfProcess/oop-host.ps1`\n\n**What was built:**\n- Full ndjson protocol host script implementing all 4 methods: `ping`, `shutdown`, `discover`, `invoke`\n- Strict stdout/stderr separation: only ndjson on stdout, diagnostics on stderr with `[oop-host]` prefix\n- `[Console]::ReadLine()` for stdin (not Read-Host), `[Console]::Out.WriteLine()` + Flush for stdout\n\n**Discovery handler design decisions:**\n- Module import uses `Import-Module -Name -ErrorAction Stop` — fails fast on bad modules with error response (doesn't crash host)\n- Commands discovered via explicit `functionNames` list AND module+pattern matching, then deduplicated by name\n- Common parameters excluded via hardcoded allowlist (14 params)\n- Description sourced from `Get-Help` synopsis, best-effort (empty on failure)\n- Each ParameterSet gets its own RemoteToolSchema entry with `Name`, `Description`, `ParameterSetName`, `Parameters`\n- Parameter fields: `Name`, `TypeName` (ParameterType.FullName), `IsMandatory`, `Position`\n\n**Invoke handler design decisions:**\n- PSCustomObject from `ConvertFrom-Json` converted to hashtable via `.PSObject.Properties` enumeration for splatting\n- SwitchParameter detection: inspects `CommandInfo.ParameterSets` for SwitchParameter types, converts true→`[switch]$true`, removes false entries\n- Results serialized with `ConvertTo-Json -Depth 4 -Compress`\n- Non-terminating errors tracked via `$Error.Count` → `hadErrors` field\n- Terminating errors caught and returned as error response\n\n**Error handling patterns:**\n- Malformed JSON: logged to stderr, skipped (no response — no id to respond to)\n- Missing `id`: logged to stderr, skipped\n- Missing `method`: error response with code -1\n- Unknown method: error response with code -1\n- Unhandled exceptions in handlers: caught by outer try/catch, error response returned\n- EOF on stdin: clean exit\n\n### 2026-04-11: OOP environment customization (issue #67)\n\n**Context:** Added `setup` protocol method to oop-host.ps1 so OOP subprocess gets the same environment customization as in-process host.\n\n**Key design decisions:**\n- `setup` method called after `ping`, before `discover` — mirrors PowerShellEnvironmentSetup.ApplyEnvironmentConfiguration() ordering\n- Setup is optional: only sent when EnvironmentConfiguration has content (module paths, install/import modules, startup scripts, or PSGallery trust)\n- Setup errors throw InvalidOperationException, failing server startup — fail-fast is correct for environment misconfiguration\n- `SetupAsync()` is a concrete method on OutOfProcessCommandExecutor (not on ICommandExecutor interface) since it's OOP-specific\n\n**Key files modified:**\n- `PoshMcp.Server/PowerShell/OutOfProcess/oop-host.ps1` — Added Invoke-SetupHandler function and `setup` dispatch\n- `PoshMcp.Server/PowerShell/OutOfProcess/OutOfProcessCommandExecutor.cs` — Added SetupAsync() method\n- `PoshMcp.Server/Program.cs` — Updated StartOutOfProcessExecutorIfNeededAsync() to call SetupAsync\n- `specs/out-of-process-execution.md` — Updated protocol docs with setup method\n\n**PowerShell patterns used:**\n- `[System.Environment]::ExpandEnvironmentVariables()` for path expansion\n- `[System.IO.Path]::PathSeparator` for cross-platform PSModulePath construction\n- `Install-Module` with version constraint params (RequiredVersion, MinimumVersion, MaximumVersion)\n- `Get-Module -ListAvailable` to skip already-installed modules\n- `Invoke-Expression` for startup scripts (consistent with in-process host behavior)\n\n### 2026-07: Unserializable parameter type filtering (Issue #89)\n\n**Context:** Commands with parameters whose types can't be serialized to JSON need to be handled gracefully.\n\n**Key files modified:**\n- `PoshMcp.Server/PowerShell/PowerShellParameterUtils.cs` — Added `IsUnserializableType(Type)` static method\n- `PoshMcp.Server/PowerShell/PowerShellAssemblyGenerator.cs` — `GenerateMethodForCommand` changed from `void` to `bool`; filtering logic added\n- `PoshMcp.Tests/Unit/UnserializableTypeTests.cs` — 33 unit tests for the new method\n\n**Filtering rules implemented:**\n1. Optional parameter with unserializable type → drop the parameter silently from the schema\n2. Mandatory parameter with unserializable type in a parameter set → skip the entire parameter set (return false)\n3. All parameter sets skipped for a command → command gets no MCP tool (emergent), logged as warning\n\n**Unserializable type set:**\n- `PSObject`, `ScriptBlock`, `System.Object`\n- `IntPtr`, `UIntPtr`, pointer and by-ref types\n- `Delegate` and all derived types (Action, Func<>, …)\n- `Stream` and derived (FileStream, MemoryStream, …)\n- `WaitHandle` and derived\n- `System.Reflection.Assembly`\n- `System.Management.Automation.PowerShell` (the automation class, not the language)\n- All `System.Management.Automation.Runspaces.*` types (Runspace, RunspacePool, …)\n- Arrays whose element type is unserializable\n\n**Design decisions:**\n- `IsUnserializableType` lives in `PowerShellParameterUtils` alongside the other parameter helpers\n- `GenerateMethodForCommand` returns bool (false = skipped) rather than throwing, to preserve clean caller control flow\n- Common parameter exclusion (`IsCommonParameter`) still runs first; unserializable check runs second on the already-filtered list\n- Arrays of unserializable types are also unserializable (recursive check on element type)\n\n### 2026-07: doctor command resolution diagnostics (Issue #91)\n\n**Context:** `poshmcp doctor` showed [MISSING] for configured commands with no explanation of why.\n\n**Changes made (Program.cs):**\n- `ConfiguredFunctionStatus` record: added nullable `ResolutionReason` field (default `null`)\n- New `DiagnoseMissingCommands(IReadOnlyList<string>, PowerShellConfiguration)` method: runs PS introspection via `IsolatedPowerShellRunspace` for each missing command\n- New `EscapeForPowerShell(string)` helper: single-quote escaping for safe PS script injection\n- `RunDoctorAsync`: enriches status list with reasons before text/JSON output\n- `BuildDoctorJson`: same enrichment so JSON payload includes `resolutionReason` per `configuredFunctionStatus` entry\n- Text output: adds indented `reason:` line under each [MISSING] entry\n\n**Diagnostic logic (DiagnoseMissingCommands):**\n1. `Get-Command -Name <name>` in isolated runspace → if found, report \"all parameter sets skipped due to unserializable types\"\n2. For each configured module: `Get-Module -Name <module> -ListAvailable` → if missing, report \"module not in PSModulePath\"\n3. If module available: `Import-Module; Get-Command -Module <module> -Name <name>` → if not found, report \"module does not export command\"\n4. If found in module → report \"command in module but not loaded at discovery time\"\n5. No modules configured and command not found → report \"command not found in PS session\"\n\n**Design decisions:**\n- Uses `IsolatedPowerShellRunspace` (not singleton) to avoid interfering with server state\n- All diagnostics for a doctor call share ONE isolated runspace for efficiency\n- Local function `DiagnoseOneCommand` inside the `ExecuteThreadSafe` lambda avoids explicit `System.Management.Automation.PowerShell` type reference in Program.cs\n- For JSON format, diagnostics run in both `RunDoctorAsync` (wasted) and `BuildDoctorJson` (used) — acceptable for a non-hot diagnostic command path\n- `ConfiguredFunctionStatus` uses positional record syntax with `ResolutionReason = null` default for backwards compatibility\n"
},
"leela": {
"charter": "# Leela — Developer Advocate\n\n## Role\n\nDeveloper advocate and technical communicator for the PoshMcp MCP server.\n\n## Responsibilities\n\n- Create clear, accurate technical documentation\n- Write tutorials, guides, and examples for users\n- Explain complex technical concepts in accessible language\n- Review documentation for accuracy and completeness\n- Create sample code and demonstration scripts\n- Gather and surface user feedback\n- Improve developer experience and onboarding\n\n## Domain Expertise\n\n- Technical writing and documentation\n- Developer experience (DX) design\n- Tutorial and guide creation\n- PowerShell scripting examples\n- MCP protocol documentation\n- API documentation and reference materials\n- Community engagement and support\n\n## Decision Authority\n\n- Documentation structure and organization\n- Example code patterns and demonstrations\n- Tutorial progression and complexity\n- Developer onboarding flow\n- Documentation style guide and conventions\n\n## Model\n\nPreferred: auto\n",
"history": "- **20260414T000000Z**: Created conference-ready team introduction content in `docs/articles/talk-team-introductions.md` using project-grounded achievements (dynamic PowerShell-to-MCP tooling, unified `poshmcp` entry point, runspace expertise, observability, test quality, docs education, decisions logging, and queue monitoring) with concise, audience-friendly speaker intros.\n- **20260414T000000Z**: ✓ Wired `docs/public/logo.svg` into DocFX build: created `docs/public/` source folder, added `public/logo.svg` to resource files, updated `_appLogoPath` to `public/logo.svg`. Build confirmed `_site/public/logo.svg` present, 0 warnings.\n- **20260403T135630Z**: ✓ Docs consistency review (13 files, 2.2K lines deduplicated). Proposal filed & merged into decisions.md.\n- **20260414T000000Z**: Updated DocFX branding config to use `poshmcp.svg` via `_appLogoPath` and added SVG to `build.resource.files` so the logo is emitted and referenced correctly in generated docs.\n- **20260414T000000Z**: Fixed DocFX homepage `InvalidFileLink` warnings by replacing `api/index.md` references in `docs/index.md` with the published API landing URL `https://usepowershell.github.io/PoshMcp/api/PoshMcp.html`; validated that both index warnings were removed in local build output.\n- **20260418T201500Z**: ✓ v0.6.0 Release Notes & Resources/Prompts Documentation — Audited docs for gaps (Resources/Prompts methods and config were undocumented), created comprehensive `docs/articles/resources-and-prompts.md` user guide (4,600 words with configuration, examples, MCP methods, best practices, troubleshooting), added release notes at `docs/release-notes/0.6.0.md`, updated README.md with feature mentions, and added resources-and-prompts to docs/toc.yml. Committed and pushed.\n# Leela — History\n\n## Project Context (Seeded on Join)\n\n**Project:** poshmcp - Model Context Protocol (MCP) server that dynamically transforms PowerShell scripts, cmdlets, and modules into secure, discoverable AI-consumable tools\n\n**Tech Stack:** .NET 10, C#, PowerShell SDK, OpenTelemetry, ASP.NET Core, xUnit\n\n**Primary User:** Steven Murawski\n\n**Team:** Futurama cast\n- Farnsworth (Lead/Architect)\n- Bender (Backend Developer)\n- Hermes (PowerShell Expert)\n- Amy (DevOps/Platform/Azure)\n- Fry (Tester)\n- Leela (Developer Advocate) ← YOU\n- Scribe (Session Logger)\n- Ralph (Work Monitor)\n\n**Current Work:** Phase 1 quick wins implemented (health checks, correlation IDs), Azure Container Apps deployment infrastructure created, multi-tenant support added. Ready for Phase 2 (structured error codes, configuration validation, command timeouts) or documentation improvements.\n\n## Learnings\n\n### 2026-03-27: First Assignment - README Revision and Documentation Audit\n\n**Task:** Conducted comprehensive documentation audit and revised root README.md to match GitHub best practices.\n\n**Documentation Findings:**\n\n1. **Tone Inconsistencies Across Project:**\n - DESIGN.md: Aspirational, emoji-heavy (🧠, 🚀, 🔧), vision-focused\n - README.md: Dry, technical, developer-focused but lacked hook/appeal\n - DOCKER.md: Straightforward technical, no embellishment\n - Azure docs: Professional, well-structured, comprehensive\n - Tests README: Uses emojis (📁, ✅), very organized\n\n2. **README.md Gaps Identified:**\n - Missing value proposition/elevator pitch\n - No \"wow moment\" example at the top\n - Missing badges (build status, version, license)\n - No clear target audience statement\n - Configuration buried deep - hard to find\n - Missing Contributing, License, and Support sections\n - Poor visual hierarchy (wall of text)\n - Generic title didn't convey value\n\n3. **README Revision Approach:**\n - **Structure:** Status → What/Why → Quick Example → Features → Installation → Usage → Docs → Contributing\n - **Voice:** Professional but accessible, developer-focused, benefit-driven\n - **Examples:** Concrete, copy-paste ready, shows immediate value\n - **Links:** Added navigation to deeper documentation\n - **Sections Added:** Contributing, Roadmap, Resources, Support, License, Acknowledgements\n - **Key Principle:** Show value first, details later\n\n**Technical Accuracy Notes:**\n- Verified all technical claims against DESIGN.md and existing docs\n- Confirmed OpenTelemetry integration from decisions.md\n- Verified health check endpoints from Phase 1 implementation\n- Confirmed Azure Managed Identity support from azure/README.md\n- Validated dual-mode operation (stdio/HTTP) from DOCKER.md\n\n**Documentation Standards Needed:**\n- Consistent emoji usage policy (or no emojis)\n- Standard README template for sub-projects\n- Heading case conventions (sentence vs title case)\n- Code block language tag standards\n- Link formatting conventions\n- Badge/shield standards for status indicators\n\n**Outcome:** Created developer-friendly README with clear value proposition, concrete examples, and comprehensive navigation to detailed docs. Maintained technical accuracy while improving accessibility for new users.\n\n### 2026-03-27: Documentation Standards Formalized\n\n**Update:** Documentation standards proposal submitted to decision inbox and merged to decisions.md.\n\n**Standards Established:**\n- README structure: Title → Tagline → What/Why → Example → Features → Getting Started → Links → Contributing → License\n- Emoji policy: Minimal/none for technical documentation (exception: internal team docs)\n- Heading conventions: Title Case for H1, sentence case for H2+\n- Code blocks: Always specify language (bash, powershell, json, csharp, text)\n- Links: Relative paths for internal, descriptive text for external\n- Quality requirements: Verify code examples, validate links, confirm technical accuracy, test commands\n\n**Migration Strategy:**\n- Phase 1 (Immediate): All new content follows standards - README.md serves as reference\n- Phase 2 (Weeks 2-3): Update critical docs (DESIGN.md, Azure docs, test documentation)\n- Phase 3 (As time allows): Comprehensive cleanup of remaining markdown files\n\n**Templates Planned:**\n- Feature documentation template\n- API documentation template\n- Tutorial template\n- Deployment guide template\n\n**Impact:** Clear baseline for all future documentation work. README.md revision demonstrates standards in practice. Team now has consistent approach for contributor guidance.\n\n### 2025-07-24: Documentation consistency and deduplication review\n\n**Task:** Reviewed all 13 project markdown files (excluding .squad/ and .copilot/ internal files) for consistency, duplication, and cross-referencing.\n\n**Duplication found and resolved:**\n\n1. **Docker docs (3 files → 1 canonical + 2 redirects):**\n - `DOCKER.md` is the canonical comprehensive Docker guide\n - `docs/DOCKER-BUILD-QUICK-REF.md` → replaced with redirect to DOCKER.md (content was subset)\n - `docs/DOCKER-BUILD-MODULES.md` → replaced with redirect to DOCKER.md (covered deprecated build-arg approach)\n\n2. **Environment customization (3 files → 1 canonical + 1 summary + 1 checklist):**\n - `docs/ENVIRONMENT-CUSTOMIZATION.md` is the canonical user guide\n - `docs/ENVIRONMENT-CUSTOMIZATION-SUMMARY.md` → replaced with brief changelog summary linking to canonical\n - `docs/INTEGRATION-CHECKLIST.md` → trimmed to essential checklist items, links to IMPLEMENTATION-GUIDE.md\n\n3. **Azure test docs (3 files → 1 canonical + 2 lean references):**\n - `PoshMcp.Tests/Integration/README.azure-integration.md` is the canonical test documentation\n - `docs/AZURE-INTEGRATION-TEST-SCENARIO.md` → replaced with brief overview + links\n - `docs/QUICKSTART-AZURE-INTEGRATION-TEST.md` → trimmed to true quick-reference, removed duplicate troubleshooting/CI/CD sections\n\n**Consistency fixes applied across all 13 files:**\n- Sentence-case headings (per docs-standards skill): \"Getting started\" not \"Getting Started\"\n- Removed emoji from headings in DESIGN.md (🧠, 🚀, 🔧, etc.)\n- Added \"See also\" cross-reference sections to all docs that reference other docs\n- Consistent em-dash separators in link descriptions\n- Fixed broken markdown in DESIGN.md (missing `##` on several H2 headings)\n\n**Cross-reference links added to:**\n- DESIGN.md → README, DOCKER, Environment customization, Azure\n- DOCKER.md → Environment customization, Examples (removed deprecated doc link)\n- ENVIRONMENT-CUSTOMIZATION.md → Implementation guide, Integration checklist, DOCKER, Examples\n- IMPLEMENTATION-GUIDE.md → Environment customization, Integration checklist, Examples\n- TRAIT-BASED-TEST-FILTERING.md → Azure test README, Quickstart, Test organization\n- PoshMcp.Tests/README.md → Azure test README, Trait filtering, Main README\n- PoshMcp.Tests/Integration/README.azure-integration.md → Azure infra, Examples, DESIGN, Trait filtering, Quickstart\n\n**Net effect:** ~2,250 lines of duplicated content removed, replaced with clear cross-reference links. Every doc now has a distinct purpose with no overlapping content.\n\n- **20260414T000000Z**: Local DocFX and published HTML diverged on navbar logo path (`poshmcp.svg` vs `logo.svg`); standardized docs source to `logo.svg` in `docs/docfx.json` and added `docs/logo.svg` so local builds consistently emit `<img id=\"logo\" class=\"svg\" src=\"logo.svg\" alt=\"\">`.\n- **20260414T000000Z**: Fixed DocFX `InvalidFileLink` warnings in environment docs by replacing links that pointed outside the DocFX content graph with in-site article links or stable GitHub links; also corrected `docs/articles/environment.md` relative path to `../archive/ENVIRONMENT-CUSTOMIZATION.md`.\n- **20260414T000000Z**: DocFX content boundaries matter for link validation; archive-only pages in `docs/archive` should link to included `docs/articles/*` pages (or external URLs), not sibling archive files or repo-root folders excluded by `docs/docfx.json`.\n- **20260414T000000Z**: Navbar logo placement in DocFX should be changed in source template/style assets (`docs/templates/poshmcp/public/main.css` and matching source CSS), then validated by rebuilding and checking generated `_site/public/main.css` rather than editing `_site` directly.\n- **20260414T000000Z**: Tool authorization docs should show complete API key examples with `DefaultPolicy`, per-key `Keys` role/scope claims, and `PowerShellConfiguration.FunctionOverrides` precedence so readers can reason about default vs per-tool access quickly.\n- **20260414T000000Z**: Updated docs/authentication.md, docs/articles/security.md, and docs/articles/configuration.md to explicitly present both Entra ID (`JwtBearer`) and API key (`ApiKey`) authentication with concise \"when to use which\" guidance and cross-links between sections.\n- **20260414T000000Z**: v0.5.6 release notes should anchor on three concrete commits: `31fa637` (authorization override matching + new `AuthorizationHelpersTests`), `0d26be6` (auth/security/config docs alignment), and `df8fcff` (package version bump to 0.5.6 in `PoshMcp.Server/PoshMcp.csproj`).\n- **20260415T000000Z**: README consistency pass should use docs under `docs/articles/*` as the canonical user-facing source; keep root README examples aligned to `poshmcp` CLI usage (`create-config`, `update-config`, `serve --transport ...`), use `PowerShellConfiguration.CommandNames` (not `FunctionNames`), and retarget legacy `docs/*.md` links to existing `docs/articles/*` or `docs/archive/*` paths.\n- **20260415T195657Z**: Scribe merged the README consistency proposal from inbox into canonical `.squad/decisions.md` and retained the scope as docs-only guidance (no code behavior changes), so future README/doc alignment work can cite a single decision record.\n- **20260415T000000Z**: DOCKER.md consistency passes should prioritize high-confidence fixes only: keep CLI-first guidance, add Docker-native equivalents, ensure container config paths use `/app/server/appsettings.json`, and avoid introducing links outside the current docs graph.\n\n- **20260419T000000Z**: ✓ Preview build install instructions added to README and user-guide. README.md updated with pointer to preview guide; user-guide.md now includes complete \"Installing Preview Builds\" subsection covering: why previews exist (latest features before stable release), GitHub Packages URL and authentication requirements (PAT with `read:packages` scope or GitHub CLI token), setup options (gh CLI recommended with bash/PowerShell examples, manual PAT fallback), install/update/downgrade commands with `--prerelease` and `--source` flags, preview version naming (`0.6.0-preview.{run_number}`), and link to browse packages at GitHub UI. Committed and pushed.\n\n- **20260419T201500Z**: ✓ Reconciled orphaned `docs/user-guide.md` into articles. Migrated \"Installing Preview Builds\" section (87 lines, complete GitHub Packages workflow) into `docs/articles/getting-started.md` after \"Building from Source\" as new subsection. Verified no other unique content in user-guide.md warranted migration (configuration, basic setup, etc. already covered in articles). Updated README.md link from `docs/user-guide.md#installing-preview-builds` to `docs/articles/getting-started.md#installing-preview-builds`. Deleted orphaned user-guide.md (1,590 lines removed). Committed and pushed. ToC remains wired to articles/ only—no conflicts.\n\n### 2026-07-18: Issue #131 — Stdio Logging to File Documentation\n\n**Task:** Document the new `--log-file` CLI option, `POSHMCP_LOG_FILE` environment variable, and `Logging.File.Path` appsettings configuration for stdio logging feature (Farnsworth issue #131 architecture decision).\n\n**Documentation updates applied:**\n\n1. **README.md changes:**\n - Added stdio mode note (after MCP client config): \"Logging to console is disabled in stdio mode to prevent interference with the MCP JSON-RPC stream. Use `--log-file <path>` or set `POSHMCP_LOG_FILE` to capture diagnostic logs.\"\n - Created new \"CLI Options and Environment Variables\" subsection with:\n - `serve` command options: `--transport` and new `--log-file <path>` (stdio mode only, overrides env/appsettings)\n - Environment variables table with `POSHMCP_TRANSPORT`, `POSHMCP_LOG_FILE` (with detailed description of stdio behavior), `POSHMCP_LOG_LEVEL`\n - Added \"File-based Configuration (appsettings.json)\" subsection showing `Logging.File.Path` schema and note that it's stdio-only\n - Reorganized configuration section for clearer priority: CLI > env > appsettings > silent\n\n2. **DOCKER.md changes:**\n - Added `POSHMCP_LOG_FILE` to \"Environment customization\" list with note on volume mounting for container persistence\n - Created new subsection \"Running in stdio mode with logging\" with concrete Docker example: `docker run` with `-v /host/logs:/data` and `-e POSHMCP_LOG_FILE=/data/poshmcp.log` to demonstrate volume mounting pattern\n\n**Key design points captured:**\n- Logging is silent in stdio mode when no file is configured (prevents JSON-RPC stream pollution)\n- CLI option takes priority over environment variable, which takes priority over appsettings\n- Container deployments must use volume mounting for log persistence (logs don't survive container shutdown otherwise)\n- Distinction between stdio-only (file-based) vs HTTP console logging behavior\n\n**Outcome:** Issue #131 documentation complete. Users can now discover and understand the three configuration methods for stdio logging, and operators have clear guidance on containerized deployment with persistent logs.\n\n### 2026-04-19: Created v0.7.0 and v0.7.1 Release Notes\n\n**Task:** Author release notes for v0.7.0 and v0.7.1 following the established format from 0.6.0.\n\n**v0.7.0 Release Notes (`docs/release-notes/0.7.0.md`):**\n- Focused on **stdio logging to file** (issue #131, PR #132) — the primary reliability fix that suppresses diagnostic logs from corrupting the JSON-RPC stream\n- Documented **MimeType nullable fix** (PR #130) — safe handling of optional MimeType in resources with `text/plain` fallback\n- Included configuration examples for all three log file methods: CLI (`--log-file`), environment (`POSHMCP_LOG_FILE`), and appsettings (`Logging.File.Path`)\n- Added Docker example showing volume mounting pattern for persistent logs in containers\n- Emphasized backward compatibility and upgrade path for production deployments\n\n**v0.7.1 Release Notes (`docs/release-notes/0.7.1.md`):**\n- Documented **Docker build context fix** (PR #134) — resolved build failures in `docker buildx build` command\n- Covered **Program.cs refactoring** (PR #135) — extracted five utility classes (LoggingHelpers, DockerRunner, SettingsResolver, ConfigurationFileManager, ConfigurationLoader) for improved maintainability\n- Kept release notes concise (maintenance/bugfix release) without inventing features from sparse commit details\n\n**toc.yml Update:**\n- Added new \"Release Notes\" section at the end of navigation\n- Listed all three releases: v0.7.1 (latest), v0.7.0, v0.6.0\n- Maintains consistent navigation structure with existing sections\n\n**Design Decisions:**\n- **Format Consistency:** Matched 0.6.0.md structure exactly (frontmatter with uid/title, release date, What's New, Configuration, Breaking Changes, Upgrade Notes, etc.)\n- **Release Focus:** 0.7.0 emphasizes the logging reliability fix as the headline feature (most impactful); 0.7.1 is brief by design (maintenance release)\n- **Configuration Examples:** Provided concrete CLI, environment, and appsettings examples for discoverability\n- **Cross-linking:** All release notes link to relevant user guides (Transport Modes, Configuration, Resources/Prompts)\n- **ToC Placement:** Release Notes added after Support section (alphabetical/logical grouping)\n\n**Outcome:** Both release notes files created and toc.yml updated. Documentation follows established patterns and provides clear upgrade guidance for each release.\n\n### 2026-04-19: Fixed DocFX Release Notes Build Content\n\n**Task:** Fix DocFX build configuration to include release-notes in the documentation site build.\n\n**Problem:** Release notes files (`docs/release-notes/0.7.0.md`, `docs/release-notes/0.7.1.md`, `docs/release-notes/0.6.0.md`) were 404ing on the published docs site because `docs/docfx.json` did not include the release-notes directory in the content files glob.\n\n**Solution:** Added `\"release-notes/**/*.md\"` to the first content entry in `docs/docfx.json` build.content files array. Verified toc.yml already had the Release Notes section properly configured.\n\n**Key Learning:** DocFX content globs must explicitly include all directories containing markdown files intended for the published site. The `build.content[0].files` array is the entry point for content discovery—any .md files outside these patterns will be excluded from the build even if referenced in toc.yml.\n\n**Outcome:** Release notes now included in DocFX build and will be published to the documentation site. Commit: `5a498c8`.\n\n### 2026-04-20: Created v0.8.0 Release Notes\n\n**Task:** Author release notes for v0.8.0 highlighting the Docker build deadlock fix and doctor command enhancements.\n\n**v0.8.0 Release Notes (`docs/release-notes/0.8.0.md`):**\n- **Primary headline:** Fixed critical stdout/stderr deadlock in Docker builds that caused `poshmcp build` to hang silently even after image built successfully. Explained root cause (sequential `ReadToEnd()` calls with pipe-buffer overflow) and solution (concurrent `Task.Run` readers with `Task.WaitAll`)\n- **Secondary feature:** Real-time build output streaming (users now see live progress instead of silence)\n- **Infrastructure improvements:** Extracted `BuildDockerBuildArgs` into `DockerRunner` as testable static method; refactored doctor command with hierarchical `DoctorReport` structure and dedicated `DoctorTextRenderer`\n- **Doctor command enhancements:** Authentication configuration, logging settings, environment variables, and MCP tool definitions now displayed in diagnostic output\n- **Security:** Updated `System.Security.Cryptography.Xml` (10.0.5 → 10.0.6) for CVE mitigation\n- **Testing:** Highlighted 11 new unit tests in `DockerRunnerTests.cs` covering Docker build scenarios\n- **Format:** Matched 0.7.1.md structure exactly; emphasized user-facing benefits (no hanging, real-time feedback, better diagnostics)\n\n**Design Decisions:**\n- **Problem-Solution Format:** Deadlock fix described in plain language with technical explanation for advanced users\n- **Highlighted Docker Users:** Added dedicated \"Highlights for Docker Users\" section since this fix directly impacts a known pain point\n- **Hierarchical Information:** What's New → Bug Fixes & Security → Upgrade Notes (less critical for stable release)\n- **Cross-links:** Pointed to Docker, Configuration, and doctor documentation for deeper dives\n\n**Outcome:** v0.8.0 release notes created following established format. Docker hang fix prominently featured as significant UX regression fix. Ready for publication without commit (coordinator handles).\n\n## TOC Update for v0.8.0\n**Date:** 2026-04-20 16:20:52\n**Task:** Add v0.8.0 release notes entry to docs/toc.yml\n**Team Directive:** Requested by Steven Murawski; Developer Advocate role as Leela\n**Action:** Added v0.8.0 as newest entry (first in list) following semantic versioning convention. Committed with co-author trailer and pushed to origin/main.\r\n"
},
"ralph": {
"charter": "# Ralph — Work Monitor\n\n## Role\n\nAutomated work queue monitor and backlog driver.\n\n## Responsibilities\n\n- Scan GitHub for untriaged issues and assigned work\n- Drive work-check loop when activated\n- Report work status when asked\n- Keep the team working on available tasks\n- Monitor PRs for review feedback and CI status\n- Auto-merge approved PRs\n\n## Triggers\n\n| User Intent | Action |\n|-------------|--------|\n| \"Ralph, go\" / \"keep working\" | Start work-check loop |\n| \"Ralph, status\" / \"What's on the board?\" | Run one check, report, don't loop |\n| \"Ralph, idle\" / \"stop monitoring\" | Deactivate |\n| \"Ralph, check every N minutes\" | Set polling interval |\n\n## Work-Check Cycle\n\n**Step 1 - Scan for work** (parallel):\n- Untriaged issues (`squad` label, no `squad:{member}`)\n- Member-assigned issues (`squad:{member}` labels)\n- Open PRs from squad members\n- Draft PRs (work in progress)\n\n**Step 2 - Categorize:**\n- Untriaged → Farnsworth triages\n- Assigned but unstarted → Spawn assigned agent\n- Review feedback → Route to PR author\n- CI failures → Create fix issue or notify agent\n- Approved PRs → Merge\n\n**Step 3 - Act:**\n- Process highest priority category\n- Spawn agents as needed\n- IMMEDIATELY go back to Step 1 (loop until board clear)\n\n**Step 4 - Periodic check-in:**\n- Every 3-5 rounds, report status\n- Do NOT ask permission to continue\n- User must say \"idle\" or \"stop\" to break loop\n\n## State (Session-Scoped)\n\n- Active/idle status\n- Round count\n- Scope (what to monitor)\n- Stats (issues closed, PRs merged)\n\n## Working Mode\n\n- Runs continuously when activated\n- Does NOT wait for user input between work items\n- Only stops on explicit \"idle\" or when board is clear\n- Board clear → suggest `npx @bradygaster/squad-cli watch` for persistent polling\n\n## Board Status Format\n\n```\n🔄 Ralph — Work Monitor\n━━━━━━━━━━━━━━━━━━━━━━\n📊 Board Status:\n 🔴 Untriaged: N issues\n 🟡 In Progress: N issues, M PRs\n 🟢 Ready: N approved PRs\n ✅ Done: N issues closed\n\nNext action: {what Ralph is doing}\n```\n",
"history": "# Ralph Work History\n\n## Project Context\n\n**Project:** PoshMcp - Model Context Protocol (MCP) server for PowerShell\n**Tech Stack:** .NET 10, C#, PowerShell SDK, OpenTelemetry, ASP.NET Core, xUnit\n**Primary User:** Steven Murawski\n\n**Project Description:**\nPoshMcp dynamically transforms PowerShell scripts, cmdlets, and modules into secure, discoverable, AI-consumable tools via the Model Context Protocol. It features persistent PowerShell runspaces, dynamic tool discovery, multi-user isolation (web mode), and OpenTelemetry metrics.\n\n**Current Priorities:**\n- Improve maintainability (structured errors, config validation)\n- Enhance resilience (circuit breakers, timeouts, retry logic)\n- Boost observability (metrics, health checks, diagnostics)\n\n**Role:** Work queue monitor - keeps the team moving on available work.\n\n## Learnings\n\n*Learnings from work will be recorded here automatically*\n"
},
"scribe": {
"charter": "# Scribe — Session Logger\n\n## Role\n\nAutomated session logging and decision recording.\n\n## Responsibilities\n\n- Record all session work in `.squad/log/`\n- Merge decision inbox files to `decisions.md`\n- Write orchestration log entries\n- Archive old decisions when file grows large\n- Summarize and archive agent history files when needed\n- Cross-pollinate learnings between agent histories\n- Commit `.squad/` changes to git\n\n## Working Mode\n\n- Always runs in background (`mode: \"background\"`)\n- Never speaks directly to the user\n- Silent worker - no user-facing output\n- Spawned automatically after agent work completes\n\n## File Responsibilities\n\n**Writes to:**\n- `.squad/log/{timestamp}-{topic}.md` - Session logs\n- `.squad/orchestration-log/{timestamp}-{agent}.md` - Per-agent work logs\n- `.squad/decisions.md` - Canonical decision ledger (merge from inbox)\n- `.squad/agents/{name}/history.md` - Cross-agent updates\n- `.squad/agents/{name}/history-archive.md` - Archived history entries\n\n**Reads from:**\n- `.squad/decisions/inbox/*.md` - Pending decisions to merge\n- All agent history files for cross-pollination\n\n## Archival Policies\n\n**Decisions archival (HARD GATE):**\n- If `decisions.md` >= 20KB, archive entries older than 30 days\n- If `decisions.md` >= 50KB, archive entries older than 7 days\n- Never skip archival when thresholds exceeded\n\n**History summarization (HARD GATE):**\n- If any `history.md` >= 15KB, summarize and archive old entries\n- Preserve recent work (last 90 days) in main history\n- Move archived content to `history-archive.md`\n\n## Git Workflow\n\nAfter completing file operations:\n1. `git add .squad/`\n2. Write commit message to temp file\n3. `git commit -F {temp-file}`\n4. Skip if nothing staged\n\n## Output Format\n\nEnd all work with plain text summary (not JSON, not tool output).\n",
"history": "# Scribe Work History\n\n## Project Context\n\n**Project:** PoshMcp - Model Context Protocol (MCP) server for PowerShell\n**Tech Stack:** .NET 10, C#, PowerShell SDK, OpenTelemetry, ASP.NET Core, xUnit\n**Primary User:** Steven Murawski\n\n**Project Description:**\nPoshMcp dynamically transforms PowerShell scripts, cmdlets, and modules into secure, discoverable, AI-consumable tools via the Model Context Protocol. It features persistent PowerShell runspaces, dynamic tool discovery, multi-user isolation (web mode), and OpenTelemetry metrics.\n\n**Current Priorities:**\n- Improve maintainability (structured errors, config validation)\n- Enhance resilience (circuit breakers, timeouts, retry logic)\n- Boost observability (metrics, health checks, diagnostics)\n\n**Role:** Automated session logging, decision merging, and history management.\n\n## Learnings\n\n*Learnings from work will be recorded here automatically*\n- 2026-04-08: Added lifecycle-focused tool invocation logging notes for a perceived `Get-Process` hang; recorded that build and targeted test validation passed.\n- 2026-04-09: Consolidating transport-foundation, HTTP implementation, and gate decisions in one merge pass keeps `.squad/decisions.md` coherent and avoids losing green-criteria evidence.\n- 2026-04-09: Merging the CLI config command inbox item into `.squad/decisions.md` with a single canonical entry and then removing inbox residue keeps the decision ledger clean and auditable.\n- 2026-04-10: When `decisions.md` is already above the archival threshold, check existing entries for age violations before assuming the inbox is the only archival source.\n- 2026-04-10: Recovery batches with overlapping agent findings are easier to audit when Scribe merges them into a few canonical ledger entries instead of copying each inbox file verbatim.\n- 2026-04-14: For docs-only workflow spawns, merge the inbox item into canonical decisions and add a cross-agent update so architecture/docs leads inherit deployment-trigger context.\n- 2026-04-15: Enforce the archival hard gate first when `decisions.md` exceeds 50KB; move out-of-window entries to `.squad/decisions-archive.md` before merging new inbox proposals so retention and canonical merge rules both stay true.\n"
}
},
"skills": [
"---\nname: \"agent-collaboration\"\ndescription: \"Standard collaboration patterns for all squad agents — worktree awareness, decisions, cross-agent communication\"\ndomain: \"team-workflow\"\nconfidence: \"high\"\nsource: \"extracted from charter boilerplate — identical content in 18+ agent charters\"\n---\n\n## Context\n\nEvery 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.\n\nThe 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.\n\n## Patterns\n\n### Worktree Awareness\nUse 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.\n\n### Decision Recording\nAfter making a decision that affects other team members, write it to:\n`.squad/decisions/inbox/{your-name}-{brief-slug}.md`\n\nFormat:\n```\n### {date}: {decision title}\n**By:** {Your Name}\n**What:** {the decision}\n**Why:** {rationale}\n```\n\n### Cross-Agent Communication\nIf 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.\n\n### Reviewer Protocol\nIf 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.\n\n## Anti-Patterns\n- Don't read all agent charters — you only need your own context + decisions.md\n- Don't write directly to `.squad/decisions.md` — always use the inbox drop-box\n- Don't modify other agents' history.md files — that's Scribe's job\n- Don't assume CWD is the repo root — always use TEAM ROOT\n",
"---\nname: \"agent-conduct\"\ndescription: \"Shared hard rules enforced across all squad agents\"\ndomain: \"team-governance\"\nconfidence: \"high\"\nsource: \"reskill extraction — Product Isolation Rule and Peer Quality Check appeared in all 20 agent charters\"\n---\n\n## Context\n\nEvery 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.\n\n## Patterns\n\n### Product Isolation Rule (hard rule)\nTests, 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\").\n\n### Peer Quality Check (hard rule)\nBefore 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.\n\n## Anti-Patterns\n- Don't hardcode dev team agent names in product code or tests\n- Don't skip test verification before declaring work done\n- Don't ignore pre-existing CI failures that your changes may worsen\n",
"---\nname: \"architectural-proposals\"\ndescription: \"How to write comprehensive architectural proposals that drive alignment before code is written\"\ndomain: \"architecture, product-direction\"\nconfidence: \"high\"\nsource: \"earned (2026-02-21 interactive shell proposal)\"\ntools:\n - name: \"view\"\n description: \"Read existing codebase, prior decisions, and team context before proposing changes\"\n when: \"Always read .squad/decisions.md, relevant PRDs, and current architecture docs before writing proposal\"\n - name: \"create\"\n description: \"Create proposal in docs/proposals/ with structured format\"\n when: \"After gathering context, before any implementation work begins\"\n---\n\n## Context\n\nProposals create alignment before code is written. Cheaper to change a doc than refactor code. Use this pattern when:\n- Architecture shifts invalidate existing assumptions\n- Product direction changes require new foundation\n- Multiple waves/milestones will be affected by a decision\n- External dependencies (Copilot CLI, SDK APIs) change\n\n## Patterns\n\n### Proposal Structure (docs/proposals/)\n\n**Required sections:**\n1. **Problem Statement** — Why current state is broken (specific, measurable evidence)\n2. **Proposed Architecture** — Solution with technical specifics (not hand-waving)\n3. **What Changes** — Impact on existing work (waves, milestones, modules)\n4. **What Stays the Same** — Preserve existing functionality (no regression)\n5. **Key Decisions Needed** — Explicit choices with recommendations\n6. **Risks and Mitigations** — Likelihood + impact + mitigation strategy\n7. **Scope** — What's in v1, what's deferred (timeline clarity)\n\n**Optional sections:**\n- Implementation Plan (high-level milestones)\n- Success Criteria (measurable outcomes)\n- Open Questions (unresolved items)\n- Appendix (prior art, alternatives considered)\n\n### Tone Ceiling Enforcement\n\n**Always:**\n- Cite specific evidence (user reports, performance data, failure modes)\n- Justify recommendations with technical rationale\n- Acknowledge trade-offs (no perfect solutions)\n- Be specific about APIs, libraries, file paths\n\n**Never:**\n- Hype (\"revolutionary\", \"game-changing\")\n- Hand-waving (\"we'll figure it out later\")\n- Unsubstantiated claims (\"users will love this\")\n- Vague timelines (\"soon\", \"eventually\")\n\n### Wave Restructuring Pattern\n\nWhen a proposal invalidates existing wave structure:\n1. **Acknowledge the shift:** \"This becomes Wave 0 (Foundation)\"\n2. **Cascade impacts:** Adjust downstream waves (Wave 1, Wave 2, Wave 3)\n3. **Preserve non-blocking work:** Identify what can proceed in parallel\n4. **Update dependencies:** Document new blocking relationships\n\n**Example (Interactive Shell):**\n- Wave 0 (NEW): Interactive Shell — blocks all other waves\n- Wave 1 (ADJUSTED): npm Distribution — shell bundled in cli.js\n- Wave 2 (DEFERRED): SquadUI — waits for shell foundation\n- Wave 3 (ADJUSTED): Public Docs — now documents shell as primary interface\n\n### Decision Framing\n\n**Format:** \"Recommendation: X (recommended) or alternatives?\"\n\n**Components:**\n- Recommendation (pick one, justify)\n- Alternatives (what else was considered)\n- Decision rationale (why recommended option wins)\n- Needs sign-off from (which agents/roles must approve)\n\n**Example:**\n```\n### 1. Terminal UI Library: `ink` (recommended) or alternatives?\n\n**Recommendation:** `ink` \n**Alternatives:** `blessed`, raw readline \n**Decision rationale:** Component model enables testable UI. Battle-tested ecosystem.\n\n**Needs sign-off from:** Brady (product direction), Fortier (runtime performance)\n```\n\n### Risk Documentation\n\n**Format per risk:**\n- **Risk:** Specific failure mode\n- **Likelihood:** Low / Medium / High (not percentages)\n- **Impact:** Low / Medium / High\n- **Mitigation:** Concrete actions (measurable)\n\n**Example:**\n```\n### Risk 2: SDK Streaming Reliability\n\n**Risk:** SDK streaming events might drop messages or arrive out of order. \n**Likelihood:** Low (SDK is production-grade). \n**Impact:** High — broken streaming makes shell unusable.\n\n**Mitigation:**\n- Add integration test: Send 1000-message stream, verify all deltas arrive in order\n- Implement fallback: If streaming fails, fall back to polling session state\n- Log all SDK events to `.squad/orchestration-log/sdk-events.jsonl` for debugging\n```\n\n## Examples\n\n**File references from interactive shell proposal:**\n- Full proposal: `docs/proposals/squad-interactive-shell.md`\n- User directive: `.squad/decisions/inbox/copilot-directive-2026-02-21T202535Z.md`\n- Team decisions: `.squad/decisions.md`\n- Current architecture: `docs/architecture/module-map.md`, `docs/prd-23-release-readiness.md`\n\n**Key patterns demonstrated:**\n1. Read user directive first (understand the \"why\")\n2. Survey current architecture (module map, existing waves)\n3. Research SDK APIs (exploration task to validate feasibility)\n4. Document problem with specific evidence (unreliable handoffs, zero visibility, UX mismatch)\n5. Propose solution with technical specifics (ink components, SDK session management, spawn.ts module)\n6. Restructure waves when foundation shifts (Wave 0 becomes blocker)\n7. Preserve backward compatibility (squad.agent.md still works, VS Code mode unchanged)\n8. Frame decisions explicitly (5 key decisions with recommendations)\n9. Document risks with mitigations (5 risks, each with concrete actions)\n10. Define scope (what's in v1 vs. deferred)\n\n## Anti-Patterns\n\n**Avoid:**\n- ❌ Proposals without problem statements (solution-first thinking)\n- ❌ Vague architecture (\"we'll use a shell\") — be specific (ink components, session registry, spawn.ts)\n- ❌ Ignoring existing work — always document impact on waves/milestones\n- ❌ No risk analysis — every architecture has risks, document them\n- ❌ Unbounded scope — draw the v1 line explicitly\n- ❌ Missing decision ownership — always say \"needs sign-off from X\"\n- ❌ No backward compatibility plan — users don't care about your replatform\n- ❌ Hand-waving timelines (\"a few weeks\") — be specific (2-3 weeks, 1 engineer full-time)\n\n**Red flags in proposal reviews:**\n- \"Users will love this\" (citation needed)\n- \"We'll figure out X later\" (scope creep incoming)\n- \"This is revolutionary\" (tone ceiling violation)\n- No section on \"What Stays the Same\" (regression risk)\n- No risks documented (wishful thinking)\n",
"---\nname: \"ci-validation-gates\"\ndescription: \"Defensive CI/CD patterns: semver validation, token checks, retry logic, draft detection — earned from v0.8.22\"\ndomain: \"ci-cd\"\nconfidence: \"high\"\nsource: \"extracted from Drucker and Trejo charters — earned knowledge from v0.8.22 release incident\"\n---\n\n## Context\n\nCI 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.\n\n## Patterns\n\n### Semver Validation Gate\nEvery 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.\n\n```yaml\n- name: Validate semver\n run: |\n VERSION=\"${{ github.event.release.tag_name }}\"\n VERSION=\"${VERSION#v}\"\n if ! npx semver \"$VERSION\" > /dev/null 2>&1; then\n echo \"❌ Invalid semver: $VERSION\"\n echo \"Only 3-part versions (X.Y.Z) or prerelease (X.Y.Z-tag.N) are valid.\"\n exit 1\n fi\n echo \"✅ Valid semver: $VERSION\"\n```\n\n### NPM Token Type Verification\nNPM_TOKEN MUST be an Automation token, not a User token with 2FA:\n- User tokens require OTP — CI can't provide it → EOTP error\n- Create Automation tokens at npmjs.com → Settings → Access Tokens → Automation\n- Verify before first publish in any workflow\n\n### Retry Logic for npm Registry Propagation\nnpm registry uses eventual consistency. After `npm publish` succeeds, the package may not be immediately queryable.\n- Propagation: typically 5-30s, up to 2min in rare cases\n- All verify steps: 5 attempts, 15-second intervals\n- Log each attempt: \"Attempt 1/5: Checking package...\"\n- Exit loop on success, fail after max attempts\n\n```yaml\n- name: Verify package (with retry)\n run: |\n MAX_ATTEMPTS=5\n WAIT_SECONDS=15\n for attempt in $(seq 1 $MAX_ATTEMPTS); do\n echo \"Attempt $attempt/$MAX_ATTEMPTS: Checking $PACKAGE@$VERSION...\"\n if npm view \"$PACKAGE@$VERSION\" version > /dev/null 2>&1; then\n echo \"✅ Package verified\"\n exit 0\n fi\n [ $attempt -lt $MAX_ATTEMPTS ] && sleep $WAIT_SECONDS\n done\n echo \"❌ Failed to verify after $MAX_ATTEMPTS attempts\"\n exit 1\n```\n\n### Draft Release Detection\nDraft releases don't emit `release: published` event. Workflows MUST:\n- Trigger on `release: published` (NOT `created`)\n- If using workflow_dispatch: verify release is published via GitHub API before proceeding\n\n### Build Script Protection\nSet `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.\n\n## Known Failure Modes (v0.8.22 Incident)\n\n| # | What Happened | Root Cause | Prevention |\n|---|---------------|-----------|------------|\n| 1 | 4-part version published, npm mangled it | No semver validation gate | `npx semver` check before every publish |\n| 2 | CI failed 5+ times with EOTP | User token with 2FA | Automation token only |\n| 3 | Verify returned false 404 | No retry logic for propagation | 5 attempts, 15s intervals |\n| 4 | Workflow never triggered | Draft release doesn't emit event | Never create draft releases |\n| 5 | Version mutated during release | bump-build.mjs ran in release | SKIP_BUILD_BUMP=1 |\n\n## Anti-Patterns\n- ❌ Publishing without semver validation gate\n- ❌ Single-shot verification without retry\n- ❌ Hard-coded secrets in workflows\n- ❌ Silent CI failures — every error needs actionable output with remediation\n- ❌ Assuming npm publish is instantly queryable\n",
"# Skill: CLI Command Wiring\n\n**Bug class:** Commands implemented in `packages/squad-cli/src/cli/commands/` but never routed in `cli-entry.ts`.\n\n## Checklist — Adding a New CLI Command\n\n1. **Create command file** in `packages/squad-cli/src/cli/commands/<name>.ts`\n - Export a `run<Name>(cwd, options)` async function (or class with static methods for utility modules)\n\n2. **Add routing block** in `packages/squad-cli/src/cli-entry.ts` inside `main()`:\n ```ts\n if (cmd === '<name>') {\n const { run<Name> } = await import('./cli/commands/<name>.js');\n // parse args, call function\n await run<Name>(process.cwd(), options);\n return;\n }\n ```\n\n3. **Add help text** in the help section of `cli-entry.ts` (search for `Commands:`):\n ```ts\n console.log(` ${BOLD}<name>${RESET} <description>`);\n console.log(` Usage: <name> [flags]`);\n ```\n\n4. **Verify both exist** — the recurring bug is doing step 1 but missing steps 2-3.\n\n## Wiring Patterns by Command Type\n\n| Type | Example | How to wire |\n|------|---------|-------------|\n| Standard command | `export.ts`, `build.ts` | `run*()` function, parse flags from `args` |\n| Placeholder command | `loop`, `hire` | Inline in cli-entry.ts, prints pending message |\n| Utility/check module | `rc-tunnel.ts`, `copilot-bridge.ts` | Wire as diagnostic check (e.g., `isDevtunnelAvailable()`) |\n| Subcommand of another | `init-remote.ts` | Already used inside parent + standalone alias |\n\n## Common Import Pattern\n\n```ts\nimport { BOLD, RESET, DIM, RED, GREEN, YELLOW } from './cli/core/output.js';\n```\n\nUse dynamic `await import()` for command modules to keep startup fast (lazy loading).\n\n## History\n\n- **#237 / PR #244:** 4 commands wired (rc, copilot-bridge, init-remote, rc-tunnel). aspire, link, loop, hire were already present.\n",
"---\nname: \"client-compatibility\"\ndescription: \"Platform detection and adaptive spawning for CLI vs VS Code vs other surfaces\"\ndomain: \"orchestration\"\nconfidence: \"high\"\nsource: \"extracted\"\n---\n\n## Context\n\nSquad runs on multiple Copilot surfaces (CLI, VS Code, JetBrains, GitHub.com). The coordinator must detect its platform and adapt spawning behavior accordingly. Different tools are available on different platforms, requiring conditional logic for agent spawning, SQL usage, and response timing.\n\n## Patterns\n\n### Platform Detection\n\nBefore spawning agents, determine the platform by checking available tools:\n\n1. **CLI mode** — `task` tool is available → full spawning control. Use `task` with `agent_type`, `mode`, `model`, `description`, `prompt` parameters. Collect results via `read_agent`.\n\n2. **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.\n\n3. **Fallback mode** — neither `task` nor `runSubagent`/`agent` available → work inline. Do not apologize or explain the limitation. Execute the task directly.\n\nIf both `task` and `runSubagent` are available, prefer `task` (richer parameter surface).\n\n### VS Code Spawn Adaptations\n\nWhen in VS Code mode, the coordinator changes behavior in these ways:\n\n- **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.\n- **Parallelism:** Spawn ALL concurrent agents in a SINGLE turn. They run in parallel automatically. This replaces `mode: \"background\"` + `read_agent` polling.\n- **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.\n- **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.\n- **Launch table:** Skip it. Results arrive with the response, not separately. By the time the coordinator speaks, the work is already done.\n- **`read_agent`:** Skip entirely. Results return automatically when subagents complete.\n- **`agent_type`:** Drop it. All VS Code subagents have full tool access by default. Subagents inherit the parent's tools.\n- **`description`:** Drop it. The agent name is already in the prompt.\n- **Prompt content:** Keep ALL prompt structure — charter, identity, task, hygiene, response order blocks are surface-independent.\n\n### Feature Degradation Table\n\n| Feature | CLI | VS Code | Degradation |\n|---------|-----|---------|-------------|\n| Parallel fan-out | `mode: \"background\"` + `read_agent` | Multiple subagents in one turn | None — equivalent concurrency |\n| Model selection | Per-spawn `model` param (4-layer hierarchy) | Session model only (Phase 1) | Accept session model, log intent |\n| Scribe fire-and-forget | Background, never read | Sync, must wait | Batch with last parallel group |\n| Launch table UX | Show table → results later | Skip table → results with response | UX only — results are correct |\n| SQL tool | Available | Not available | Avoid SQL in cross-platform code paths |\n| Response order bug | Critical workaround | Possibly necessary (unverified) | Keep the block — harmless if unnecessary |\n\n### SQL Tool Caveat\n\nThe `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.\n\n## Examples\n\n**Example 1: CLI parallel spawn**\n```typescript\n// Coordinator detects task tool available → CLI mode\ntask({ agent_type: \"general-purpose\", mode: \"background\", model: \"claude-sonnet-4.5\", ... })\ntask({ agent_type: \"general-purpose\", mode: \"background\", model: \"claude-haiku-4.5\", ... })\n// Later: read_agent for both\n```\n\n**Example 2: VS Code parallel spawn**\n```typescript\n// Coordinator detects runSubagent available → VS Code mode\nrunSubagent({ prompt: \"...Fenster charter + task...\" })\nrunSubagent({ prompt: \"...Hockney charter + task...\" })\nrunSubagent({ prompt: \"...Scribe charter + task...\" }) // Last in group\n// Results return automatically, no read_agent\n```\n\n**Example 3: Fallback mode**\n```typescript\n// Neither task nor runSubagent available → work inline\n// Coordinator executes the task directly without spawning\n```\n\n## Anti-Patterns\n\n- ❌ Using SQL tool in cross-platform workflows (breaks on VS Code/JetBrains/GitHub.com)\n- ❌ Attempting per-spawn model selection on VS Code (Phase 1 — only session model works)\n- ❌ Fire-and-forget Scribe on VS Code (must batch as last subagent)\n- ❌ Showing launch table on VS Code (results already inline)\n- ❌ Apologizing or explaining platform limitations to the user\n- ❌ Using `task` when only `runSubagent` is available\n- ❌ Dropping prompt structure (charter/identity/task) on non-CLI platforms\n",
"# Skill: Cross-Machine Coordination Pattern\n\n**Skill ID:** `cross-machine-coordination` \n**Owner:** Ralph (Work Monitor) \n**Squad Integration:** All agents \n**Status:** Specification (ready for implementation) \n\n---\n\n## Overview\n\nEnables squad agents running on different machines (laptop, DevBox, Azure VM) to securely share work, coordinate execution, and pass results without manual intervention.\n\n**Pattern:** Git-based task queuing + GitHub Issues supplement\n\n---\n\n## Usage\n\n### For Task Sources (Orchestrating Machine)\n\n**To assign work to DevBox:**\n\n```bash\n# Create task file\ncat > .squad/cross-machine/tasks/2026-03-14T1530Z-laptop-gpu-voice-clone.yaml << 'EOF'\nid: gpu-voice-clone-001\nsource_machine: laptop-machine\ntarget_machine: devbox\npriority: high\ncreated_at: 2026-03-14T15:30:00Z\ntask_type: gpu_workload\npayload:\n command: \"python scripts/voice-clone.py --input voice.wav --output cloned.wav\"\n expected_duration_min: 15\n resources:\n gpu: true\n memory_gb: 8\nstatus: pending\nEOF\n\n# Commit & push\ngit add .squad/cross-machine/tasks/\ngit commit -m \"Cross-machine task: GPU voice cloning [squad:machine-devbox]\"\ngit push origin main\n```\n\nRalph on DevBox will:\n1. Pull the task on next cycle (5-10 min)\n2. Validate schema & command whitelist\n3. Execute the GPU workload\n4. Write result to `.squad/cross-machine/results/gpu-voice-clone-001.yaml`\n5. Commit & push the result\n\n---\n\n### For Task Executors (DevBox, Azure VMs)\n\nRalph automatically watches `.squad/cross-machine/tasks/` for work targeted at this machine.\n\n**On each cycle (5-10 min):**\n\n```python\n# Pseudo-code (Ralph implementation)\n1. git pull origin main\n2. Load all .yaml files in .squad/cross-machine/tasks/\n3. Filter for status=pending AND target_machine=HOSTNAME\n4. For each task:\n a. Validate schema (must have: id, source_machine, target_machine, payload)\n b. Validate command against whitelist\n c. Execute task (with timeout)\n d. Write result to .squad/cross-machine/results/{id}.yaml\n e. Commit & push result\n```\n\n---\n\n### For Urgent/Ad-Hoc Tasks\n\n**Use GitHub Issues with `squad:machine-{name}` label:**\n\n```bash\n# Create issue\ngh issue create \\\n --title \"GPU: Clone voice profile from sample.wav\" \\\n --body \"Execute voice cloning on DevBox. Input: /path/to/voice-input.wav\" \\\n --label \"squad:machine-devbox\" \\\n --label \"urgent\"\n```\n\nRalph on DevBox will:\n1. Detect issue with `squad:machine-devbox` label\n2. Parse task from issue body\n3. Execute task\n4. Comment with result\n5. Close issue\n\n---\n\n## File Formats\n\n### Task File (YAML)\n\n**Location:** `.squad/cross-machine/tasks/{timestamp}-{machine}-{task-id}.yaml`\n\n**Required Fields:**\n```yaml\nid: {task-id} # Unique identifier (alphanumeric + dash)\nsource_machine: {hostname} # Where task was created\ntarget_machine: {hostname} # Where task will execute\npriority: high|normal|low # Execution priority\ncreated_at: 2026-03-14T15:30:00Z # ISO 8601 timestamp\ntask_type: gpu_workload|script|... # Category\npayload:\n command: \"...\" # Shell command to execute\n expected_duration_min: 15 # Timeout (minutes)\n resources:\n gpu: true|false\n memory_gb: 8\n cpu_cores: 4\nstatus: pending|executing|completed|failed\n```\n\n**Optional Fields:**\n```yaml\ndescription: \"Human-readable task description\"\ntimeout_override_min: 120 # Override default timeout\nretry_count: 3 # Retry failed tasks\n```\n\n### Result File (YAML)\n\n**Location:** `.squad/cross-machine/results/{task-id}.yaml`\n\n```yaml\nid: {task-id} # Links back to task\ntarget_machine: devbox # Executed on\ncompleted_at: 2026-03-14T15:45:00Z # When it finished\nstatus: completed|failed|timeout # Outcome\nexit_code: 0 # Shell exit code\nstdout: \"...\" # Captured output\nstderr: \"...\" # Captured errors\nduration_seconds: 900 # How long it took\nartifacts:\n - path: \"/path/to/artifacts/...\" # Location of results\n type: audio|text|model|...\n size_mb: 2.5\n```\n\n---\n\n## Security Model\n\n### Validation Pipeline\n\nAll tasks go through:\n\n1. **Schema Validation**\n - YAML structure matches spec\n - Required fields present\n - No unexpected fields (reject)\n\n2. **Command Whitelist**\n - Only approved commands allowed\n - Path validation (no `../../` escapes)\n - Environment variable sanitization\n - No inline shell operators (`&&`, `|`, `>`)\n\n3. **Resource Limits**\n - Timeout enforced (default: 60 min)\n - Memory cap: 16GB (adjustable)\n - CPU threads: 4 (adjustable)\n - Disk write: 100GB (adjustable)\n\n4. **Execution Isolation**\n - Runs as unprivileged user\n - Temp directory cleaned after execution\n - Network access: read-only (no outbound writes)\n\n5. **Audit Trail**\n - All executions logged to git\n - Commit signed with Ralph's key\n - Result stored immutably\n\n### Threat Mitigations\n\n| Threat | Mitigation |\n|--------|-----------|\n| **Malicious task injection** | Branch protection + PR review before merge |\n| **Credential leakage** | Pre-commit secret scan + environment scrubbing |\n| **Resource exhaustion** | Timeout + memory limits |\n| **Code injection** | Command whitelist + no shell evaluation |\n| **Result tampering** | Git commit history is immutable |\n\n---\n\n## Configuration\n\nRalph reads config from `.squad/config.json`:\n\n```json\n{\n \"cross_machine\": {\n \"enabled\": true,\n \"poll_interval_seconds\": 300,\n \"this_machine\": \"devbox\",\n \"max_concurrent_tasks\": 2,\n \"task_timeout_minutes\": 60,\n \"command_whitelist\": [\n \"python scripts/voice-clone.py\",\n \"python scripts/data-process.py\",\n \"bash scripts/cleanup.sh\"\n ],\n \"result_ttl_days\": 30\n }\n}\n```\n\n---\n\n## Examples\n\n### Example 1: GPU Voice Cloning (Laptop → DevBox)\n\n**1. Laptop creates task:**\n\n```yaml\n# .squad/cross-machine/tasks/2026-03-14T1530Z-laptop-gpu-001.yaml\nid: gpu-voice-clone-001\nsource_machine: laptop-machine\ntarget_machine: devbox\npriority: high\ncreated_at: 2026-03-14T15:30:00Z\ntask_type: gpu_workload\npayload:\n command: \"python scripts/voice-clone.py --input voice.wav --output cloned.wav\"\n expected_duration_min: 15\n resources:\n gpu: true\n memory_gb: 8\nstatus: pending\n```\n\n**2. Laptop commits & pushes:**\n\n```bash\ngit add .squad/cross-machine/tasks/\ngit commit -m \"Task: GPU voice cloning [squad:machine-devbox]\"\ngit push origin main\n```\n\n**3. DevBox Ralph (5 min later):**\n\n```\n[Ralph Watch Cycle]\n- Pulled origin/main\n- Detected: gpu-voice-clone-001 (status: pending, target: devbox)\n- Validation: ✅ Schema OK, command whitelisted\n- Executing: python scripts/voice-clone.py ...\n- [15 minutes of processing]\n- Completed: exit code 0\n- Writing result...\n- Committing & pushing...\n```\n\n**4. Laptop Ralph (next cycle) sees result:**\n\n```yaml\n# .squad/cross-machine/results/gpu-voice-clone-001.yaml\nid: gpu-voice-clone-001\ntarget_machine: devbox\ncompleted_at: 2026-03-14T15:45:00Z\nstatus: completed\nexit_code: 0\nstdout: \"Voice cloning completed. Output written to /tmp/cloned.wav\"\nstderr: \"\"\nduration_seconds: 900\nartifacts:\n - path: \"/path/to/artifacts/voice-clone-001/output.wav\"\n type: audio\n size_mb: 2.5\n```\n\n---\n\n### Example 2: Urgent Debug Request (Human → DevBox via Issue)\n\n**Create issue:**\n\n```bash\ngh issue create \\\n --title \"DevBox: Debug voice model failure\" \\\n --body \"Error: Model failed to load on last run. Please check /tmp/model.log and report findings.\" \\\n --label \"squad:machine-devbox\" \\\n --label \"urgent\"\n```\n\n**DevBox Ralph detects → executes → comments:**\n\n```\n✅ Executed on devbox at 2026-03-14 15:47:00\nCommand: python scripts/debug-model.py\n\nResult:\n------\nModel file: /tmp/model-v2.bin (OK)\nChecksum: a1b2c3d4e5f6 (matches expected)\nMemory available: 12 GB (sufficient)\n\nERROR FOUND: Config file permission issue\n - File: ~/.config/voice/model.yaml\n - Permissions: -rw------- (owner-only)\n - Expected: -rw-r--r-- (world-readable for service)\n\nFIX: Run: chmod 644 ~/.config/voice/model.yaml\n```\n\n---\n\n## Error Handling\n\n### Task Execution Failures\n\nIf a task fails (exit code != 0):\n\n1. Result written with `status: failed` + exit code\n2. stderr captured in result\n3. Committed to git for audit\n4. Source machine can retry by re-pushing task with `status: pending`\n\n### Stalled Tasks\n\nIf a task doesn't complete within timeout:\n\n1. Process killed\n2. Result written with `status: timeout`\n3. stderr: \"Execution exceeded X minutes\"\n4. Source can investigate or retry\n\n### Network Failures\n\nIf git push/pull fails:\n\n- Ralph retries on next cycle\n- Tasks queue locally until connectivity restored\n- No tasks lost (stored in local repo)\n\n---\n\n## Monitoring & Debugging\n\n### Check Task Queue\n\n```bash\nls -la .squad/cross-machine/tasks/\ncat .squad/cross-machine/tasks/*.yaml | grep -E \"^(id|status|target_machine):\"\n```\n\n### Check Results\n\n```bash\nls -la .squad/cross-machine/results/\ncat .squad/cross-machine/results/{task-id}.yaml\n```\n\n### View Execution History\n\n```bash\ngit log --oneline .squad/cross-machine/ | head -20\n```\n\n### Monitor Ralph Cycles\n\n```bash\ntail -f .squad/log/ralph-watch.log | grep \"cross-machine\"\n```\n\n---\n\n## Integration with Ralph Watch\n\nRalph automatically includes this pattern in its watch loop:\n\n```\nRalph Watch Cycle (every 5-10 min):\n1. Fetch GitHub issues with squad:machine-* labels\n2. Poll .squad/cross-machine/tasks/\n3. For each matching task:\n - Validate\n - Execute\n - Write result\n - Commit & push\n4. Update status in issue (if applicable)\n5. Sleep until next cycle\n```\n\nNo manual Ralph configuration needed — just create task files or issues with the right labels.\n\n---\n\n## Migration from Manual Handoff\n\n**Before (today):**\n- Laptop → user manually copies file to Teams chat\n- user pastes into target terminal\n- user copies output back\n- user pastes result manually\n\n**After (with this pattern):**\n- Laptop Ralph writes task file → git push\n- DevBox Ralph auto-executes → git push result\n- Laptop Ralph auto-reads result\n- 0 human intervention needed\n\n---\n\n## Future Enhancements\n\nPotential expansions (Phase 2+):\n\n1. **Task Priorities:** Execution order based on priority field\n2. **Serial Pipelines:** Machine A → B → C task chains\n3. **GPU Availability Polling:** Query DevBox before submitting work\n4. **Cost Tracking:** Log resource usage per task\n5. **Notification Webhooks:** Alert on task completion\n6. **Web Dashboard:** Real-time task status visualization\n\n---\n\n## Questions?\n\nRefer to research report: `research/active/cross-machine-agents/README.md`\n\nContact: Seven (Research & Docs) or Ralph (Work Monitor)\n",
"---\nname: \"cross-squad\"\ndescription: \"Coordinating work across multiple Squad instances\"\ndomain: \"orchestration\"\nconfidence: \"medium\"\nsource: \"manual\"\ntools:\n - name: \"squad-discover\"\n description: \"List known squads and their capabilities\"\n when: \"When you need to find which squad can handle a task\"\n - name: \"squad-delegate\"\n description: \"Create work in another squad's repository\"\n when: \"When a task belongs to another squad's domain\"\n---\n\n## Context\nWhen an organization runs multiple Squad instances (e.g., platform-squad, frontend-squad, data-squad), those squads need to discover each other, share context, and hand off work across repository boundaries. This skill teaches agents how to coordinate across squads without creating tight coupling.\n\nCross-squad orchestration applies when:\n- A task requires capabilities owned by another squad\n- An architectural decision affects multiple squads\n- A feature spans multiple repositories with different squads\n- A squad needs to request infrastructure, tooling, or support from another squad\n\n## Patterns\n\n### Discovery via Manifest\nEach squad publishes a `.squad/manifest.json` declaring its name, capabilities, and contact information. Squads discover each other through:\n1. **Well-known paths**: Check `.squad/manifest.json` in known org repos\n2. **Upstream config**: Squads already listed in `.squad/upstream.json` are checked for manifests\n3. **Explicit registry**: A central `squad-registry.json` can list all squads in an org\n\n```json\n{\n \"name\": \"platform-squad\",\n \"version\": \"1.0.0\",\n \"description\": \"Platform infrastructure team\",\n \"capabilities\": [\"kubernetes\", \"helm\", \"monitoring\", \"ci-cd\"],\n \"contact\": {\n \"repo\": \"org/platform\",\n \"labels\": [\"squad:platform\"]\n },\n \"accepts\": [\"issues\", \"prs\"],\n \"skills\": [\"helm-developer\", \"operator-developer\", \"pipeline-engineer\"]\n}\n```\n\n### Context Sharing\nWhen delegating work, share only what the target squad needs:\n- **Capability list**: What this squad can do (from manifest)\n- **Relevant decisions**: Only decisions that affect the target squad\n- **Handoff context**: A concise description of why this work is being delegated\n\nDo NOT share:\n- Internal team state (casting history, session logs)\n- Full decision archives (send only relevant excerpts)\n- Authentication credentials or secrets\n\n### Work Handoff Protocol\n1. **Check manifest**: Verify the target squad accepts the work type (issues, PRs)\n2. **Create issue**: Use `gh issue create` in the target repo with:\n - Title: `[cross-squad] <description>`\n - Label: `squad:cross-squad` (or the squad's configured label)\n - Body: Context, acceptance criteria, and link back to originating issue\n3. **Track**: Record the cross-squad issue URL in the originating squad's orchestration log\n4. **Poll**: Periodically check if the delegated issue is closed/completed\n\n### Feedback Loop\nTrack delegated work completion:\n- Poll target issue status via `gh issue view`\n- Update originating issue with status changes\n- Close the feedback loop when delegated work merges\n\n## Examples\n\n### Discovering squads\n```bash\n# List all squads discoverable from upstreams and known repos\nsquad discover\n\n# Output:\n# platform-squad → org/platform (kubernetes, helm, monitoring)\n# frontend-squad → org/frontend (react, nextjs, storybook)\n# data-squad → org/data (spark, airflow, dbt)\n```\n\n### Delegating work\n```bash\n# Delegate a task to the platform squad\nsquad delegate platform-squad \"Add Prometheus metrics endpoint for the auth service\"\n\n# Creates issue in org/platform with cross-squad label and context\n```\n\n### Manifest in squad.config.ts\n```typescript\nexport default defineSquad({\n manifest: {\n name: 'platform-squad',\n capabilities: ['kubernetes', 'helm'],\n contact: { repo: 'org/platform', labels: ['squad:platform'] },\n accepts: ['issues', 'prs'],\n skills: ['helm-developer', 'operator-developer'],\n },\n});\n```\n\n## Anti-Patterns\n- **Direct file writes across repos** — Never modify another squad's `.squad/` directory. Use issues and PRs as the communication protocol.\n- **Tight coupling** — Don't depend on another squad's internal structure. Use the manifest as the public API contract.\n- **Unbounded delegation** — Always include acceptance criteria and a timeout. Don't create open-ended requests.\n- **Skipping discovery** — Don't hardcode squad locations. Use manifests and the discovery protocol.\n- **Sharing secrets** — Never include credentials, tokens, or internal URLs in cross-squad issues.\n- **Circular delegation** — Track delegation chains. If squad A delegates to B which delegates back to A, something is wrong.\n",
"---\nname: \"distributed-mesh\"\ndescription: \"How to coordinate with squads on different machines using git as transport\"\ndomain: \"distributed-coordination\"\nconfidence: \"high\"\nsource: \"multi-model-consensus (Opus 4.6, Sonnet 4.5, GPT-5.4)\"\n---\n\n## SCOPE\n\n**✅ THIS SKILL PRODUCES (exactly these, nothing more):**\n\n1. **`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\n2. **`sync-mesh.sh` and `sync-mesh.ps1`** — Copied from this skill's directory into the project root (these are bundled resources, NOT generated code)\n3. **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\n4. **A decision entry** in `.squad/decisions/inbox/` documenting the mesh configuration for team awareness\n\n**❌ THIS SKILL DOES NOT PRODUCE:**\n\n- **No application code** — No validators, libraries, or modules of any kind\n- **No test files** — No test suites, test cases, or test scaffolding\n- **No GENERATING sync scripts** — They are bundled with this skill as pre-built resources. COPY them, don't generate them.\n- **No daemons or services** — No background processes, servers, or persistent runtimes\n- **No modifications to existing squad files** beyond the decision entry (no changes to team.md, routing.md, agent charters, etc.)\n\n**Your role:** Configure the mesh topology and install the bundled sync scripts. Nothing more.\n\n## Context\n\nWhen 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.\n\n**When this applies:**\n- Squads span multiple machines, VMs, or CI runners\n- Squads span organizations or companies\n- An agent needs context from a squad whose files aren't on the local filesystem\n\n**When this does NOT apply:**\n- All squads are on the same machine (just read the files directly)\n\n## Patterns\n\n### The Core Principle\n\n> \"The filesystem is the mesh, and git is how the mesh crosses machine boundaries.\"\n\nThe 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.\n\n### Three Zones of Communication\n\n**Zone 1 — Local:** Same filesystem. Read files directly. Zero transport.\n\n**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.\n\n**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.\n\n### Agent Lifecycle (Distributed)\n\n```\n1. SYNC: git pull (Zone 2) + curl (Zone 3) — materialize remote state\n2. READ: cat .mesh/**/state.md — all files are local now\n3. WORK: do their assigned work (the agent's normal task, NOT mesh-building)\n4. WRITE: update own billboard, log, drops\n5. PUBLISH: git add + commit + push — share state with remote peers\n```\n\nSteps 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.\"\n\n### The mesh.json Config\n\n```json\n{\n \"squads\": {\n \"auth-squad\": { \"zone\": \"local\", \"path\": \"../auth-squad/.mesh\" },\n \"ci-squad\": {\n \"zone\": \"remote-trusted\",\n \"source\": \"git@github.com:our-org/ci-squad.git\",\n \"ref\": \"main\",\n \"sync_to\": \".mesh/remotes/ci-squad\"\n },\n \"partner-fraud\": {\n \"zone\": \"remote-opaque\",\n \"source\": \"https://partner.dev/squad-contracts/fraud/SUMMARY.md\",\n \"sync_to\": \".mesh/remotes/partner-fraud\",\n \"auth\": \"bearer\"\n }\n }\n}\n```\n\nThree zone types, one file. Local squads need only a path. Remote-trusted need a git URL. Remote-opaque need an HTTP URL.\n\n### Write Partitioning\n\nEach 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`.\n\n### Trust Boundaries\n\nTrust maps to git permissions:\n- **Same repo access** = full mesh visibility\n- **Read-only access** = can observe, can't write\n- **No access** = invisible (correct behavior)\n\nFor selective visibility, use separate repos per audience (internal, partner, public). Git permissions ARE the trust negotiation.\n\n### Phased Rollout\n\n- **Phase 0:** Convention only — document zones, agree on mesh.json fields, manually run `git pull`/`git push`. Zero new code.\n- **Phase 1:** Sync script (~30 lines bash or PowerShell) when manual sync gets tedious.\n- **Phase 2:** Published contracts + curl fetch when a Zone 3 partner appears.\n- **Phase 3:** Never. No MCP federation, A2A, service discovery, message queues.\n\n**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.\n\n### Mesh State Repo\n\nThe shared mesh state repo is a plain git repository — NOT a Squad project. It holds:\n- One directory per participating squad\n- Each directory contains at minimum a SUMMARY.md with the squad's current state\n- A root README explaining what the repo is and who participates\n\nNo `.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.\n\nIf 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.\n\n## Examples\n\n### Developer Laptop + CI Squad (Zone 2)\n\nAuth-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`.**\n\n### Two Orgs Collaborating (Zone 3)\n\nPayment-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.\n\n### Same Org, Shared Mesh Repo (Zone 2)\n\nThree 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.\n\n## AGENT WORKFLOW (Deterministic Setup)\n\nWhen a user invokes this skill to set up a distributed mesh, follow these steps **exactly, in order:**\n\n### Step 1: ASK the user for mesh topology\n\nAsk these questions (adapt phrasing naturally, but get these answers):\n\n1. **Which squads are participating?** (List of squad names)\n2. **For each squad, which zone is it in?**\n - `local` — same filesystem (just need a path)\n - `remote-trusted` — different machine, same org, shared git access (need git URL + ref)\n - `remote-opaque` — different org, no shared auth (need HTTPS URL to published contract)\n3. **For each squad, what's the connection info?**\n - Local: relative or absolute path to their `.mesh/` directory\n - Remote-trusted: git URL (SSH or HTTPS), ref (branch/tag), and where to sync it to locally\n - Remote-opaque: HTTPS URL to their SUMMARY.md, where to sync it, and auth type (none/bearer)\n4. **Where should the shared state live?** (For Zone 2 squads: git repo URL for the mesh state, or confirm each squad syncs independently)\n\n### Step 2: GENERATE `mesh.json`\n\nUsing the answers from Step 1, create a `mesh.json` file at the project root. Use `mesh.json.example` from THIS skill's directory (`.squad/skills/distributed-mesh/mesh.json.example`) as the schema template.\n\nStructure:\n\n```json\n{\n \"squads\": {\n \"<squad-name>\": { \"zone\": \"local\", \"path\": \"<relative-or-absolute-path>\" },\n \"<squad-name>\": {\n \"zone\": \"remote-trusted\",\n \"source\": \"<git-url>\",\n \"ref\": \"<branch-or-tag>\",\n \"sync_to\": \".mesh/remotes/<squad-name>\"\n },\n \"<squad-name>\": {\n \"zone\": \"remote-opaque\",\n \"source\": \"<https-url-to-summary>\",\n \"sync_to\": \".mesh/remotes/<squad-name>\",\n \"auth\": \"<none|bearer>\"\n }\n }\n}\n```\n\nWrite this file to the project root. Do NOT write any other code.\n\n### Step 3: COPY sync scripts\n\nCopy the bundled sync scripts from THIS skill's directory into the project root:\n\n- **Source:** `.squad/skills/distributed-mesh/sync-mesh.sh`\n- **Destination:** `sync-mesh.sh` (project root)\n\n- **Source:** `.squad/skills/distributed-mesh/sync-mesh.ps1`\n- **Destination:** `sync-mesh.ps1` (project root)\n\nThese are bundled resources. Do NOT generate them — COPY them directly.\n\n### Step 4: RUN `--init` (if Zone 2 state repo exists)\n\nIf the user specified a Zone 2 shared state repo in Step 1, run the initialization:\n\n**On Unix/Linux/macOS:**\n```bash\nbash sync-mesh.sh --init\n```\n\n**On Windows:**\n```powershell\n.\\sync-mesh.ps1 -Init\n```\n\nThis scaffolds the state repo structure (squad directories, placeholder SUMMARY.md files, root README).\n\n**Skip this step if:**\n- No Zone 2 squads are configured (local/opaque only)\n- The state repo already exists and is initialized\n\n### Step 5: WRITE a decision entry\n\nCreate a decision file at `.squad/decisions/inbox/<your-agent-name>-mesh-setup.md` with this content:\n\n```markdown\n### <YYYY-MM-DD>: Mesh configuration\n\n**By:** <your-agent-name> (via distributed-mesh skill)\n\n**What:** Configured distributed mesh with <N> squads across zones <list-zones-used>\n\n**Squads:**\n- `<squad-name>` — Zone <X> — <brief-connection-info>\n- `<squad-name>` — Zone <X> — <brief-connection-info>\n- ...\n\n**State repo:** <git-url-if-zone-2-used, or \"N/A (local/opaque only)\">\n\n**Why:** <user's stated reason for setting up the mesh, or \"Enable cross-machine squad coordination\">\n```\n\nWrite this file. The Scribe will merge it into the main decisions file later.\n\n### Step 6: STOP\n\n**You are done.** Do not:\n- Generate sync scripts (they're bundled with this skill — COPY them)\n- Write validator code\n- Write test files\n- Create any other modules, libraries, or application code\n- Modify existing squad files (team.md, routing.md, charters)\n- Auto-advance to Phase 2 or Phase 3\n\nOutput a simple completion message:\n\n```\n✅ Mesh configured. Created:\n- mesh.json (<N> squads)\n- sync-mesh.sh and sync-mesh.ps1 (copied from skill bundle)\n- Decision entry: .squad/decisions/inbox/<filename>\n\nRun `bash sync-mesh.sh` (or `.\\sync-mesh.ps1` on Windows) before agents start to materialize remote state.\n```\n\n---\n\n## Anti-Patterns\n\n**❌ Code generation anti-patterns:**\n- Writing `mesh-config-validator.js` or any validator module\n- Writing test files for mesh configuration\n- Generating sync scripts instead of copying the bundled ones from this skill's directory\n- Creating library modules or utilities\n- Building any code that \"runs the mesh\" — the mesh is read by agents, not executed\n\n**❌ Architectural anti-patterns:**\n- Building a federation protocol — Git push/pull IS federation\n- Running a sync daemon or server — Agents are not persistent. Sync at startup, publish at shutdown\n- Real-time notifications — Agents don't need real-time. They need \"recent enough.\" `git pull` is recent enough\n- Schema validation for markdown — The LLM reads markdown. If the format changes, it adapts\n- Service discovery protocol — mesh.json is a file with 10 entries. Not a \"discovery problem\"\n- Auth framework — Git SSH keys and HTTPS tokens. Not a framework. Already configured\n- Message queues / event buses — Agents wake, read, work, write, sleep. Nobody's home to receive events\n- Any component requiring a running process — That's the line. Don't cross it\n\n**❌ Scope creep anti-patterns:**\n- Auto-advancing phases without user decision\n- Modifying agent charters or routing rules\n- Setting up CI/CD pipelines for mesh sync\n- Creating dashboards or monitoring tools\n",
"---\nname: \"docs-standards\"\ndescription: \"Microsoft Style Guide + Squad-specific documentation patterns\"\ndomain: \"documentation\"\nconfidence: \"high\"\nsource: \"earned (PAO charter, multiple doc PR reviews)\"\n---\n\n## Context\n\nSquad documentation follows the Microsoft Style Guide with Squad-specific conventions. Consistency across docs builds trust and improves discoverability.\n\n## Patterns\n\n### Microsoft Style Guide Rules\n- **Sentence-case headings:** \"Getting started\" not \"Getting Started\"\n- **Active voice:** \"Run the command\" not \"The command should be run\"\n- **Second person:** \"You can configure...\" not \"Users can configure...\"\n- **Present tense:** \"The system routes...\" not \"The system will route...\"\n- **No ampersands in prose:** \"and\" not \"&\" (except in code, brand names, or UI elements)\n\n### Squad Formatting Patterns\n- **Scannability first:** Paragraphs for narrative (3-4 sentences max), bullets for scannable lists, tables for structured data\n- **\"Try this\" prompts at top:** Start feature/scenario pages with practical prompts users can copy\n- **Experimental warnings:** Features in preview get callout at top\n- **Cross-references at bottom:** Related pages linked after main content\n\n### Structure\n- **Title (H1)** → **Warning/callout** → **Try this code** → **Overview** → **HR** → **Content (H2 sections)**\n\n### Test Sync Rule\n- **Always update test assertions:** When adding docs pages to `features/`, `scenarios/`, `guides/`, update corresponding `EXPECTED_*` arrays in `test/docs-build.test.ts` in the same commit\n\n## Examples\n\n✓ **Correct:**\n```markdown\n# Getting started with Squad\n\n> ⚠️ **Experimental:** This feature is in preview.\n\nTry this:\n\\`\\`\\`bash\nsquad init\n\\`\\`\\`\n\nSquad helps you build AI teams...\n\n---\n\n## Install Squad\n\nRun the following command...\n```\n\n✗ **Incorrect:**\n```markdown\n# Getting Started With Squad // Title case\n\nSquad is a tool which will help users... // Third person, future tense\n\nYou can install Squad with npm & configure it... // Ampersand in prose\n```\n\n## Anti-Patterns\n\n- Title-casing headings because \"it looks nicer\"\n- Writing in passive voice or third person\n- Long paragraphs of dense text (breaks scannability)\n- Adding doc pages without updating test assertions\n- Using ampersands outside code blocks\n",
"---\nname: \"economy-mode\"\ndescription: \"Shifts Layer 3 model selection to cost-optimized alternatives when economy mode is active.\"\ndomain: \"model-selection\"\nconfidence: \"low\"\nsource: \"manual\"\n---\n\n## SCOPE\n\n✅ THIS SKILL PRODUCES:\n- A modified Layer 3 model selection table applied when economy mode is active\n- `economyMode: true` written to `.squad/config.json` when activated persistently\n- Spawn acknowledgments with `💰` indicator when economy mode is active\n\n❌ THIS SKILL DOES NOT PRODUCE:\n- Code, tests, or documentation\n- Cost reports or billing artifacts\n- Changes to Layer 0, Layer 1, or Layer 2 resolution (user intent always wins)\n\n## Context\n\nEconomy mode shifts Layer 3 (Task-Aware Auto-Selection) to lower-cost alternatives. It does NOT override persistent config (`defaultModel`, `agentModelOverrides`) or per-agent charter preferences — those represent explicit user intent and always take priority.\n\nUse this skill when the user wants to reduce costs across an entire session or permanently, without manually specifying models for each agent.\n\n## Activation Methods\n\n| Method | How |\n|--------|-----|\n| Session phrase | \"use economy mode\", \"save costs\", \"go cheap\", \"reduce costs\" |\n| Persistent config | `\"economyMode\": true` in `.squad/config.json` |\n| CLI flag | `squad --economy` |\n\n**Deactivation:** \"turn off economy mode\", \"disable economy mode\", or remove `economyMode` from `config.json`.\n\n## Economy Model Selection Table\n\nWhen economy mode is **active**, Layer 3 auto-selection uses this table instead of the normal defaults:\n\n| Task Output | Normal Mode | Economy Mode |\n|-------------|-------------|--------------|\n| Writing code (implementation, refactoring, bug fixes) | `claude-sonnet-4.5` | `gpt-4.1` or `gpt-5-mini` |\n| Writing prompts or agent designs | `claude-sonnet-4.5` | `gpt-4.1` or `gpt-5-mini` |\n| Docs, planning, triage, changelogs, mechanical ops | `claude-haiku-4.5` | `gpt-4.1` or `gpt-5-mini` |\n| Architecture, code review, security audits | `claude-opus-4.5` | `claude-sonnet-4.5` |\n| Scribe / logger / mechanical file ops | `claude-haiku-4.5` | `gpt-4.1` |\n\n**Prefer `gpt-4.1` over `gpt-5-mini`** when the task involves structured output or agentic tool use. Prefer `gpt-5-mini` for pure text generation tasks where latency matters.\n\n## AGENT WORKFLOW\n\n### On Session Start\n\n1. READ `.squad/config.json`\n2. CHECK for `economyMode: true` — if present, activate economy mode for the session\n3. STORE economy mode state in session context\n\n### On User Phrase Trigger\n\n**Session-only (no config change):** \"use economy mode\", \"save costs\", \"go cheap\"\n\n1. SET economy mode active for this session\n2. ACKNOWLEDGE: `✅ Economy mode active — using cost-optimized models this session. (Layer 0 and Layer 2 preferences still apply)`\n\n**Persistent:** \"always use economy mode\", \"save economy mode\"\n\n1. WRITE `economyMode: true` to `.squad/config.json` (merge, don't overwrite other fields)\n2. ACKNOWLEDGE: `✅ Economy mode saved — cost-optimized models will be used until disabled.`\n\n### On Every Agent Spawn (Economy Mode Active)\n\n1. CHECK Layer 0a/0b first (agentModelOverrides, defaultModel) — if set, use that. Economy mode does NOT override Layer 0.\n2. CHECK Layer 1 (session directive for a specific model) — if set, use that. Economy mode does NOT override explicit session directives.\n3. CHECK Layer 2 (charter preference) — if set, use that. Economy mode does NOT override charter preferences.\n4. APPLY economy table at Layer 3 instead of normal table.\n5. INCLUDE `💰` in spawn acknowledgment: `🔧 {Name} ({model} · 💰 economy) — {task}`\n\n### On Deactivation\n\n**Trigger phrases:** \"turn off economy mode\", \"disable economy mode\", \"use normal models\"\n\n1. REMOVE `economyMode` from `.squad/config.json` (if it was persisted)\n2. CLEAR session economy mode state\n3. ACKNOWLEDGE: `✅ Economy mode disabled — returning to standard model selection.`\n\n### STOP\n\nAfter updating economy mode state and including the `💰` indicator in spawn acknowledgments, this skill is done. Do NOT:\n- Change Layer 0, Layer 1, or Layer 2 model choices\n- Override charter-specified models\n- Generate cost reports or comparisons\n- Fall back to premium models via economy mode (economy mode never bumps UP)\n\n## Config Schema\n\n`.squad/config.json` economy-related fields:\n\n```json\n{\n \"version\": 1,\n \"economyMode\": true\n}\n```\n\n- `economyMode` — when `true`, Layer 3 uses the economy table. Optional; absent = economy mode off.\n- Combines with `defaultModel` and `agentModelOverrides` — Layer 0 always wins.\n\n## Anti-Patterns\n\n- **Don't override Layer 0 in economy mode.** If the user set `defaultModel: \"claude-opus-4.6\"`, they want quality. Economy mode only affects Layer 3 auto-selection.\n- **Don't silently apply economy mode.** Always acknowledge when activated or deactivated.\n- **Don't treat economy mode as permanent by default.** Session phrases activate session-only; only \"always\" or `config.json` persist it.\n- **Don't bump premium tasks down too far.** Architecture and security reviews shift from opus to sonnet in economy mode — they do NOT go to fast/cheap models.\n",
"---\nname: \"error-recovery\"\ndescription: \"Standard recovery patterns for all squad agents. When something fails, adapt — don't just report the failure.\"\ndomain: \"reliability, agent-coordination\"\nconfidence: \"high\"\nlicense: MIT\n---\n\n# Error Recovery Patterns\n\nStandard recovery patterns for all squad agents. When something fails, **adapt** — don't just report the failure.\n\n---\n\n## 1. Retry with Backoff\n\n**When:** Transient failures — API timeouts, rate limits, network errors, temporary service unavailability.\n\n**Pattern:**\n1. Wait briefly, then retry (start at 2s, double each attempt)\n2. Maximum 3 retries before escalating\n3. Log each attempt with the error received\n\n**Example:** API call returns 429 Too Many Requests → wait 2s → retry → wait 4s → retry → wait 8s → retry → escalate if still failing.\n\n---\n\n## 2. Fallback Alternatives\n\n**When:** Primary tool or approach fails and an alternative exists.\n\n**Pattern:**\n1. Attempt primary approach\n2. On failure, identify alternative tool/method\n3. Try the alternative with the same intent\n4. Document which alternative was used and why\n\n**Example:** Primary CLI tool fails → fall back to direct API call for the same operation.\n\n---\n\n## 3. Diagnose-and-Fix\n\n**When:** Build failures, test failures, linting errors — structured errors with actionable output.\n\n**Pattern:**\n1. Read the full error output carefully\n2. Identify the root cause from error messages\n3. Attempt a targeted fix\n4. Re-run to verify the fix\n5. Maximum 3 fix-retry cycles before escalating\n\n**Example:** Build fails with a type error → check for missing import → add it → rebuild.\n\n---\n\n## 4. Escalate with Context\n\n**When:** Recovery attempts have been exhausted, or the failure requires human judgment.\n\n**Pattern:**\n1. Summarize what was attempted and what failed\n2. Include the exact error messages\n3. State what you believe the root cause is\n4. Suggest next steps or who might be able to help\n5. Hand off to the coordinator or the appropriate specialist\n\n**Example:** After 3 failed build attempts → \"Build fails on line 42 with null reference. Tried X, Y, Z. Likely a design issue in the Foo module. Recommend the code owner review.\"\n\n---\n\n## 5. Graceful Degradation\n\n**When:** A non-critical step fails but the overall task can still deliver value.\n\n**Pattern:**\n1. Determine if the failed step is critical to the task outcome\n2. If non-critical, log the failure and continue\n3. Deliver partial results with a clear note of what was skipped\n4. Offer to retry the skipped step separately\n\n**Example:** Generating a report with 5 sections — section 3 data source is unavailable → produce the report with 4 sections, note that section 3 was skipped and why.\n\n---\n\n## Applying These Patterns\n\nEach agent should reference these patterns in their charter's `## Error Recovery` section, tailored to their domain. The charter should list the agent's most common failure modes and map each to the appropriate pattern above.\n\n**Selection guide:**\n\n| Failure Type | Primary Pattern | Fallback Pattern |\n|---|---|---|\n| Network/API transient | Retry with Backoff | Escalate with Context |\n| Tool/dependency missing | Fallback Alternatives | Escalate with Context |\n| Build/test error | Diagnose-and-Fix | Escalate with Context |\n| Auth/permissions | Retry with Backoff | Escalate with Context |\n| Non-critical data missing | Graceful Degradation | — |\n| Unknown/novel error | Escalate with Context | — |\n",
"---\nname: \"external-comms\"\ndescription: \"PAO workflow for scanning, drafting, and presenting community responses with human review gate\"\ndomain: \"community, communication, workflow\"\nconfidence: \"low\"\nsource: \"manual (RFC #426 — PAO External Communications)\"\ntools:\n - name: \"github-mcp-server-list_issues\"\n description: \"List open issues for scan candidates and lightweight triage\"\n when: \"Use for recent open issue scans before thread-level review\"\n - name: \"github-mcp-server-issue_read\"\n description: \"Read the full issue, comments, and labels before drafting\"\n when: \"Use after selecting a candidate so PAO has complete thread context\"\n - name: \"github-mcp-server-search_issues\"\n description: \"Search for candidate issues or prior squad responses\"\n when: \"Use when filtering by keywords, labels, or duplicate response checks\"\n - name: \"gh CLI\"\n description: \"Fallback for GitHub issue comments and discussions workflows\"\n when: \"Use gh issue list/comment and gh api or gh api graphql when MCP coverage is incomplete\"\n---\n\n## Context\n\nPhase 1 is **draft-only mode**.\n\n- PAO scans issues and discussions, drafts responses with the humanizer skill, and presents a review table for human approval.\n- **Human review gate is mandatory** — PAO never posts autonomously.\n- Every action is logged to `.squad/comms/audit/`.\n- This workflow is triggered manually only (\"PAO, check community\") — no automated or Ralph-triggered activation in Phase 1.\n\n## Patterns\n\n### 1. Scan\n\nFind unanswered community items with GitHub MCP tools first, or `gh issue list` / `gh api` as fallback for issues and discussions.\n\n- Include **open** issues and discussions only.\n- Filter for items with **no squad team response**.\n- Limit to items created in the last 7 days.\n- Exclude items labeled `squad:internal` or `wontfix`.\n- Include discussions **and** issues in the same sweep.\n- Phase 1 scope is **issues and discussions only** — do not draft PR replies.\n\n### Discussion Handling (Phase 1)\n\nDiscussions use the GitHub Discussions API, which differs from issues:\n\n- **Scan:** `gh api /repos/{owner}/{repo}/discussions --jq '.[] | select(.answer_chosen_at == null)'` to find unanswered discussions\n- **Categories:** Filter by Q&A and General categories only (skip Announcements, Show and Tell)\n- **Answers vs comments:** In Q&A discussions, PAO drafts an \"answer\" (not a comment). The human marks it as accepted answer after posting.\n- **Phase 1 scope:** Issues and Discussions ONLY. No PR comments.\n\n### 2. Classify\n\nDetermine the response type before drafting.\n\n- Welcome (new contributor)\n- Troubleshooting (bug/help)\n- Feature guidance (feature request/how-to)\n- Redirect (wrong repo/scope)\n- Acknowledgment (confirmed, no fix)\n- Closing (resolved)\n- Technical uncertainty (unknown cause)\n- Empathetic disagreement (pushback on a decision or design)\n- Information request (need more reproduction details or context)\n\n### Template Selection Guide\n\n| Signal in Issue/Discussion | → Response Type | Template |\n|---------------------------|-----------------|----------|\n| New contributor (0 prior issues) | Welcome | T1 |\n| Error message, stack trace, \"doesn't work\" | Troubleshooting | T2 |\n| \"How do I...?\", \"Can Squad...?\", \"Is there a way to...?\" | Feature Guidance | T3 |\n| Wrong repo, out of scope for Squad | Redirect | T4 |\n| Confirmed bug, no fix available yet | Acknowledgment | T5 |\n| Fix shipped, PR merged that resolves issue | Closing | T6 |\n| Unclear cause, needs investigation | Technical Uncertainty | T7 |\n| Author disagrees with a decision or design | Empathetic Disagreement | T8 |\n| Need more reproduction info or context | Information Request | T9 |\n\nUse exactly one template as the base draft. Replace placeholders with issue-specific details, then apply the humanizer patterns. If the thread spans multiple signals, choose the highest-risk template and capture the nuance in the thread summary.\n\n### Confidence Classification\n\n| Confidence | Criteria | Example |\n|-----------|----------|---------|\n| 🟢 High | Answer exists in Squad docs or FAQ, similar question answered before, no technical ambiguity | \"How do I install Squad?\" |\n| 🟡 Medium | Technical answer is sound but involves judgment calls, OR docs exist but don't perfectly match the question, OR tone is tricky | \"Can Squad work with Azure DevOps?\" (yes, but setup is nuanced) |\n| 🔴 Needs Review | Technical uncertainty, policy/roadmap question, potential reputational risk, author is frustrated/angry, question about unreleased features | \"When will Squad support Claude?\" |\n\n**Auto-escalation rules:**\n- Any mention of competitors → 🔴\n- Any mention of pricing/licensing → 🔴\n- Author has >3 follow-up comments without resolution → 🔴\n- Question references a closed-wontfix issue → 🔴\n\n### 3. Draft\n\nUse the humanizer skill for every draft.\n\n- Complete **Thread-Read Verification** before writing.\n- Read the **full thread**, including all comments, before writing.\n- Select the matching template from the **Template Selection Guide** and record the template ID in the review notes.\n- Treat templates as reusable drafting assets: keep the structure, replace placeholders, and only improvise when the thread truly requires it.\n- Validate the draft against the humanizer anti-patterns.\n- Flag long threads (`>10` comments) with `⚠️`.\n\n### Thread-Read Verification\n\nBefore drafting, PAO MUST verify complete thread coverage:\n\n1. **Count verification:** Compare API comment count with actually-read comments. If mismatch, abort draft.\n2. **Deleted comment check:** Use `gh api` timeline to detect deleted comments. If found, flag as ⚠️ in review table.\n3. **Thread summary:** Include in every draft: \"Thread: {N} comments, last activity {date}, {summary of key points}\"\n4. **Long thread flag:** If >10 comments, add ⚠️ to review table and include condensed thread summary\n5. **Evidence line in review table:** Each draft row includes \"Read: {N}/{total} comments\" column\n\n### 4. Present\n\nShow drafts for review in this exact format:\n\n```text\n📝 PAO — Community Response Drafts\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n| # | Item | Author | Type | Confidence | Read | Preview |\n|---|------|--------|------|------------|------|---------|\n| 1 | Issue #N | @user | Type | 🟢/🟡/🔴 | N/N | \"First words...\" |\n\nConfidence: 🟢 High | 🟡 Medium | 🔴 Needs review\n\nFull drafts below ▼\n```\n\nEach full draft must begin with the thread summary line:\n`Thread: {N} comments, last activity {date}, {summary of key points}`\n\n### 5. Human Action\n\nWait for explicit human direction before anything is posted.\n\n- `pao approve 1 3` — approve drafts 1 and 3\n- `pao edit 2` — edit draft 2\n- `pao skip` — skip all\n- `banana` — freeze all pending (safe word)\n\n### Rollback — Bad Post Recovery\n\nIf a posted response turns out to be wrong, inappropriate, or needs correction:\n\n1. **Delete the comment:**\n - Issues: `gh api -X DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}`\n - Discussions: `gh api graphql -f query='mutation { deleteDiscussionComment(input: {id: \"{node_id}\"}) { comment { id } } }'`\n2. **Log the deletion:** Write audit entry with action `delete`, include reason and original content\n3. **Draft replacement** (if needed): PAO drafts a corrected response, goes through normal review cycle\n4. **Postmortem:** If the error reveals a pattern gap, update humanizer anti-patterns or add a new test case\n\n**Safe word — `banana`:**\n- Immediately freezes all pending drafts in the review queue\n- No new scans or drafts until `pao resume` is issued\n- Audit entry logged with halter identity and reason\n\n### 6. Post\n\nAfter approval:\n\n- Human posts via `gh issue comment` for issues or `gh api` for discussion answers/comments.\n- PAO helps by preparing the CLI command.\n- Write the audit entry after the posting action.\n\n### 7. Audit\n\nLog every action.\n\n- Location: `.squad/comms/audit/{timestamp}.md`\n- Required fields vary by action — see `.squad/comms/templates/audit-entry.md` Conditional Fields table\n- Universal required fields: `timestamp`, `action`\n- All other fields are conditional on the action type\n\n## Examples\n\nThese are reusable templates. Keep the structure, replace placeholders, and adjust only where the thread requires it.\n\n### Example scan command\n\n```bash\ngh issue list --state open --json number,title,author,labels,comments --limit 20\n```\n\n### Example review table\n\n```text\n📝 PAO — Community Response Drafts\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n| # | Item | Author | Type | Confidence | Read | Preview |\n|---|------|--------|------|------------|------|---------|\n| 1 | Issue #426 | @newdev | Welcome | 🟢 | 1/1 | \"Hey @newdev! Welcome to Squad...\" |\n| 2 | Discussion #18 | @builder | Feature guidance | 🟡 | 4/4 | \"Great question! Today the CLI...\" |\n| 3 | Issue #431 ⚠️ | @debugger | Technical uncertainty | 🔴 | 12/12 | \"Interesting find, @debugger...\" |\n\nConfidence: 🟢 High | 🟡 Medium | 🔴 Needs review\n\nFull drafts below ▼\n```\n\n### Example audit entry (post action)\n\n```markdown\n---\ntimestamp: \"2026-03-16T21:30:00Z\"\naction: \"post\"\nitem_number: 426\ndraft_id: 1\nreviewer: \"@bradygaster\"\n---\n\n## Context (draft, approve, edit, skip, post, delete actions)\n- Thread depth: 3\n- Response type: welcome\n- Confidence: 🟢\n- Long thread flag: false\n\n## Draft Content (draft, edit, post actions)\nThread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install.\n\nHey @newdev! Welcome to Squad 👋 Thanks for opening this.\nWe reproduced the issue in preview builds and we're checking the regression point now.\nLet us know if you can share the command you ran right before the failure.\n\n## Post Result (post, delete actions)\nhttps://github.com/bradygaster/squad/issues/426#issuecomment-123456\n```\n\n### T1 — Welcome\n\n```text\nHey {author}! Welcome to Squad 👋 Thanks for opening this.\n{specific acknowledgment or first answer}\nLet us know if you have questions — happy to help!\n```\n\n### T2 — Troubleshooting\n\n```text\nThanks for the detailed report, {author}!\nHere's what we think is happening: {explanation}\n{steps or workaround}\nLet us know if that helps, or if you're seeing something different.\n```\n\n### T3 — Feature Guidance\n\n```text\nGreat question! {context on current state}\n{guidance or workaround}\nWe've noted this as a potential improvement — {tracking info if applicable}.\n```\n\n### T4 — Redirect\n\n```text\nThanks for reaching out! This one is actually better suited for {correct location}.\n{brief explanation of why}\nFeel free to open it there — they'll be able to help!\n```\n\n### T5 — Acknowledgment\n\n```text\nGood catch, {author}. We've confirmed this is a real issue.\n{what we know so far}\nWe'll update this thread when we have a fix. Thanks for flagging it!\n```\n\n### T6 — Closing\n\n```text\nThis should be resolved in {version/PR}! 🎉\n{brief summary of what changed}\nThanks for reporting this, {author} — it made Squad better.\n```\n\n### T7 — Technical Uncertainty\n\n```text\nInteresting find, {author}. We're not 100% sure what's causing this yet.\nHere's what we've ruled out: {list}\nWe'd love more context if you have it — {specific ask}.\nWe'll dig deeper and update this thread.\n```\n\n### T8 — Empathetic Disagreement\n\n```text\nWe hear you, {author}. That's a fair concern.\n\nThe current design choice was driven by {reason}. We know it's not ideal for every use case.\n\n{what alternatives exist or what trade-off was made}\n\nIf you have ideas for how to make this work better for your scenario, we'd love to hear them — open a discussion or drop your thoughts here!\n```\n\n### T9 — Information Request\n\n```text\nThanks for reporting this, {author}!\n\nTo help us dig into this, could you share:\n- {specific ask 1}\n- {specific ask 2}\n- {specific ask 3, if applicable}\n\nThat context will help us narrow down what's happening. Appreciate it!\n```\n\n## Anti-Patterns\n\n- ❌ Posting without human review (NEVER — this is the cardinal rule)\n- ❌ Drafting without reading full thread (context is everything)\n- ❌ Ignoring confidence flags (🔴 items need Flight/human review)\n- ❌ Scanning closed issues (only open items)\n- ❌ Responding to issues labeled `squad:internal` or `wontfix`\n- ❌ Skipping audit logging (every action must be recorded)\n- ❌ Drafting for issues where a squad member already responded (avoid duplicates)\n- ❌ Drafting pull request responses in Phase 1 (issues/discussions only)\n- ❌ Treating templates like loose examples instead of reusable drafting assets\n- ❌ Asking for more info without specific requests\n",
"---\nname: \"gh-auth-isolation\"\ndescription: \"Safely manage multiple GitHub identities (EMU + personal) in agent workflows\"\ndomain: \"security, github-integration, authentication, multi-account\"\nconfidence: \"high\"\nsource: \"earned (production usage across 50+ sessions with EMU corp + personal GitHub accounts)\"\ntools:\n - name: \"gh\"\n description: \"GitHub CLI for authenticated operations\"\n when: \"When accessing GitHub resources requiring authentication\"\n---\n\n## Context\n\nMany developers use GitHub through an Enterprise Managed User (EMU) account at work while maintaining a personal GitHub account for open-source contributions. AI agents spawned by Squad inherit the shell's default `gh` authentication — which is usually the EMU account. This causes failures when agents try to push to personal repos, create PRs on forks, or interact with resources outside the enterprise org.\n\nThis skill teaches agents how to detect the active identity, switch contexts safely, and avoid mixing credentials across operations.\n\n## Patterns\n\n### Detect Current Identity\n\nBefore any GitHub operation, check which account is active:\n\n```bash\ngh auth status\n```\n\nLook for:\n- `Logged in to github.com as USERNAME` — the active account\n- `Token scopes: ...` — what permissions are available\n- Multiple accounts will show separate entries\n\n### Extract a Specific Account's Token\n\nWhen you need to operate as a specific user (not the default):\n\n```bash\n# Get the personal account token (by username)\ngh auth token --user personaluser\n\n# Get the EMU account token\ngh auth token --user corpalias_enterprise\n```\n\n**Use case:** Push to a personal fork while the default `gh` auth is the EMU account.\n\n### Push to Personal Repos from EMU Shell\n\nThe most common scenario: your shell defaults to the EMU account, but you need to push to a personal GitHub repo.\n\n```bash\n# 1. Extract the personal token\n$token = gh auth token --user personaluser\n\n# 2. Push using token-authenticated HTTPS\ngit push https://personaluser:$token@github.com/personaluser/repo.git branch-name\n```\n\n**Why this works:** `gh auth token --user` reads from `gh`'s credential store without switching the active account. The token is used inline for a single operation and never persisted.\n\n### Create PRs on Personal Forks\n\nWhen the default `gh` context is EMU but you need to create a PR from a personal fork:\n\n```bash\n# Option 1: Use --repo flag (works if token has access)\ngh pr create --repo upstream/repo --head personaluser:branch --title \"...\" --body \"...\"\n\n# Option 2: Temporarily set GH_TOKEN for one command\n$env:GH_TOKEN = $(gh auth token --user personaluser)\ngh pr create --repo upstream/repo --head personaluser:branch --title \"...\"\nRemove-Item Env:\\GH_TOKEN\n```\n\n### Config Directory Isolation (Advanced)\n\nFor complete isolation between accounts, use separate `gh` config directories:\n\n```bash\n# Personal account operations\n$env:GH_CONFIG_DIR = \"$HOME/.config/gh-public\"\ngh auth login # Login with personal account (one-time setup)\ngh repo clone personaluser/repo\n\n# EMU account operations (default)\nRemove-Item Env:\\GH_CONFIG_DIR\ngh auth status # Back to EMU account\n```\n\n**Setup (one-time):**\n```bash\n# Create isolated config for personal account\nmkdir ~/.config/gh-public\n$env:GH_CONFIG_DIR = \"$HOME/.config/gh-public\"\ngh auth login --web --git-protocol https\n```\n\n### Shell Aliases for Quick Switching\n\nAdd to your shell profile for convenience:\n\n```powershell\n# PowerShell profile\nfunction ghp { $env:GH_CONFIG_DIR = \"$HOME/.config/gh-public\"; gh @args; Remove-Item Env:\\GH_CONFIG_DIR }\nfunction ghe { gh @args } # Default EMU\n\n# Usage:\n# ghp repo clone personaluser/repo # Uses personal account\n# ghe issue list # Uses EMU account\n```\n\n```bash\n# Bash/Zsh profile\nalias ghp='GH_CONFIG_DIR=~/.config/gh-public gh'\nalias ghe='gh'\n\n# Usage:\n# ghp repo clone personaluser/repo\n# ghe issue list\n```\n\n## Examples\n\n### ✓ Correct: Agent pushes blog post to personal GitHub Pages\n\n```powershell\n# Agent needs to push to personaluser.github.io (personal repo)\n# Default gh auth is corpalias_enterprise (EMU)\n\n$token = gh auth token --user personaluser\ngit remote set-url origin https://personaluser:$token@github.com/personaluser/personaluser.github.io.git\ngit push origin main\n\n# Clean up — don't leave token in remote URL\ngit remote set-url origin https://github.com/personaluser/personaluser.github.io.git\n```\n\n### ✓ Correct: Agent creates a PR from personal fork to upstream\n\n```powershell\n# Fork: personaluser/squad, Upstream: bradygaster/squad\n# Agent is on branch contrib/fix-docs in the fork clone\n\ngit push origin contrib/fix-docs # Pushes to fork (may need token auth)\n\n# Create PR targeting upstream\ngh pr create --repo bradygaster/squad --head personaluser:contrib/fix-docs `\n --title \"docs: fix installation guide\" `\n --body \"Fixes #123\"\n```\n\n### ✗ Incorrect: Blindly pushing with wrong account\n\n```bash\n# BAD: Agent assumes default gh auth works for personal repos\ngit push origin main\n# ERROR: Permission denied — EMU account has no access to personal repo\n\n# BAD: Hardcoding tokens in scripts\ngit push https://personaluser:ghp_xxxxxxxxxxxx@github.com/personaluser/repo.git main\n# SECURITY RISK: Token exposed in command history and process list\n```\n\n### ✓ Correct: Check before you push\n\n```bash\n# Always verify which account has access before operations\ngh auth status\n# If wrong account, use token extraction:\n$token = gh auth token --user personaluser\ngit push https://personaluser:$token@github.com/personaluser/repo.git main\n```\n\n## Anti-Patterns\n\n- ❌ **Hardcoding tokens** in scripts, environment variables, or committed files. Use `gh auth token --user` to extract at runtime.\n- ❌ **Assuming the default `gh` auth works** for all repos. EMU accounts can't access personal repos and vice versa.\n- ❌ **Switching `gh auth login`** globally mid-session. This changes the default for ALL processes and can break parallel agents.\n- ❌ **Storing personal tokens in `.env`** or `.squad/` files. These get committed by Scribe. Use `gh`'s credential store.\n- ❌ **Ignoring token cleanup** after inline HTTPS pushes. Always reset the remote URL to avoid persisting tokens.\n- ❌ **Using `gh auth switch`** in multi-agent sessions. One agent switching affects all others sharing the shell.\n- ❌ **Mixing EMU and personal operations** in the same git clone. Use separate clones or explicit remote URLs per operation.\n",
"---\nname: \"git-workflow\"\ndescription: \"Squad branching model: dev-first workflow with insiders preview channel\"\ndomain: \"version-control\"\nconfidence: \"high\"\nsource: \"team-decision\"\n---\n\n## Context\n\nSquad uses a three-branch model. **All feature work starts from `dev`, not `main`.**\n\n| Branch | Purpose | Publishes |\n|--------|---------|-----------|\n| `main` | Released, tagged, in-npm code only | `npm publish` on tag |\n| `dev` | Integration branch — all feature work lands here | `npm publish --tag preview` on merge |\n| `insiders` | Early-access channel — synced from dev | `npm publish --tag insiders` on sync |\n\n## Branch Naming Convention\n\nIssue branches MUST use: `squad/{issue-number}-{kebab-case-slug}`\n\nExamples:\n- `squad/195-fix-version-stamp-bug`\n- `squad/42-add-profile-api`\n\n## Workflow for Issue Work\n\n1. **Branch from dev:**\n ```bash\n git checkout dev\n git pull origin dev\n git checkout -b squad/{issue-number}-{slug}\n ```\n\n2. **Mark issue in-progress:**\n ```bash\n gh issue edit {number} --add-label \"status:in-progress\"\n ```\n\n3. **Create draft PR targeting dev:**\n ```bash\n gh pr create --base dev --title \"{description}\" --body \"Closes #{issue-number}\" --draft\n ```\n\n4. **Do the work.** Make changes, write tests, commit with issue reference.\n\n5. **Push and mark ready:**\n ```bash\n git push -u origin squad/{issue-number}-{slug}\n gh pr ready\n ```\n\n6. **After merge to dev:**\n ```bash\n git checkout dev\n git pull origin dev\n git branch -d squad/{issue-number}-{slug}\n git push origin --delete squad/{issue-number}-{slug}\n ```\n\n## Parallel Multi-Issue Work (Worktrees)\n\nWhen the coordinator routes multiple issues simultaneously (e.g., \"fix bugs X, Y, and Z\"), use `git worktree` to give each agent an isolated working directory. No filesystem collisions, no branch-switching overhead.\n\n### When to Use Worktrees vs Sequential\n\n| Scenario | Strategy |\n|----------|----------|\n| Single issue | Standard workflow above — no worktree needed |\n| 2+ simultaneous issues in same repo | Worktrees — one per issue |\n| Work spanning multiple repos | Separate clones as siblings (see Multi-Repo below) |\n\n### Setup\n\nFrom the main clone (must be on dev or any branch):\n\n```bash\n# Ensure dev is current\ngit fetch origin dev\n\n# Create a worktree per issue — siblings to the main clone\ngit worktree add ../squad-195 -b squad/195-fix-stamp-bug origin/dev\ngit worktree add ../squad-193 -b squad/193-refactor-loader origin/dev\n```\n\n**Naming convention:** `../{repo-name}-{issue-number}` (e.g., `../squad-195`, `../squad-pr-42`).\n\nEach worktree:\n- Has its own working directory and index\n- Is on its own `squad/{issue-number}-{slug}` branch from dev\n- Shares the same `.git` object store (disk-efficient)\n\n### Per-Worktree Agent Workflow\n\nEach agent operates inside its worktree exactly like the single-issue workflow:\n\n```bash\ncd ../squad-195\n\n# Work normally — commits, tests, pushes\ngit add -A && git commit -m \"fix: stamp bug (#195)\"\ngit push -u origin squad/195-fix-stamp-bug\n\n# Create PR targeting dev\ngh pr create --base dev --title \"fix: stamp bug\" --body \"Closes #195\" --draft\n```\n\nAll PRs target `dev` independently. Agents never interfere with each other's filesystem.\n\n### .squad/ State in Worktrees\n\nThe `.squad/` directory exists in each worktree as a copy. This is safe because:\n- `.gitattributes` declares `merge=union` on append-only files (history.md, decisions.md, logs)\n- Each agent appends to its own section; union merge reconciles on PR merge to dev\n- **Rule:** Never rewrite or reorder `.squad/` files in a worktree — append only\n\n### Cleanup After Merge\n\nAfter a worktree's PR is merged to dev:\n\n```bash\n# From the main clone\ngit worktree remove ../squad-195\ngit worktree prune # clean stale metadata\ngit branch -d squad/195-fix-stamp-bug\ngit push origin --delete squad/195-fix-stamp-bug\n```\n\nIf a worktree was deleted manually (rm -rf), `git worktree prune` recovers the state.\n\n---\n\n## Multi-Repo Downstream Scenarios\n\nWhen work spans multiple repositories (e.g., squad-cli changes need squad-sdk changes, or a user's app depends on squad):\n\n### Setup\n\nClone downstream repos as siblings to the main repo:\n\n```\n~/work/\n squad-pr/ # main repo\n squad-sdk/ # downstream dependency\n user-app/ # consumer project\n```\n\nEach repo gets its own issue branch following its own naming convention. If the downstream repo also uses Squad conventions, use `squad/{issue-number}-{slug}`.\n\n### Coordinated PRs\n\n- Create PRs in each repo independently\n- Link them in PR descriptions:\n ```\n Closes #42\n\n **Depends on:** squad-sdk PR #17 (squad-sdk changes required for this feature)\n ```\n- Merge order: dependencies first (e.g., squad-sdk), then dependents (e.g., squad-cli)\n\n### Local Linking for Testing\n\nBefore pushing, verify cross-repo changes work together:\n\n```bash\n# Node.js / npm\ncd ../squad-sdk && npm link\ncd ../squad-pr && npm link squad-sdk\n\n# Go\n# Use replace directive in go.mod:\n# replace github.com/org/squad-sdk => ../squad-sdk\n\n# Python\ncd ../squad-sdk && pip install -e .\n```\n\n**Important:** Remove local links before committing. `npm link` and `go replace` are dev-only — CI must use published packages or PR-specific refs.\n\n### Worktrees + Multi-Repo\n\nThese compose naturally. You can have:\n- Multiple worktrees in the main repo (parallel issues)\n- Separate clones for downstream repos\n- Each combination operates independently\n\n---\n\n## Anti-Patterns\n\n- ❌ Branching from main (branch from dev)\n- ❌ PR targeting main directly (target dev)\n- ❌ Non-conforming branch names (must be squad/{number}-{slug})\n- ❌ Committing directly to main or dev (use PRs)\n- ❌ Switching branches in the main clone while worktrees are active (use worktrees instead)\n- ❌ Using worktrees for cross-repo work (use separate clones)\n- ❌ Leaving stale worktrees after PR merge (clean up immediately)\n\n## Promotion Pipeline\n\n- dev → insiders: Automated sync on green build\n- dev → main: Manual merge when ready for stable release, then tag\n- Hotfixes: Branch from main as `hotfix/{slug}`, PR to dev, cherry-pick to main if urgent\n",
"---\nname: github-multi-account\ndescription: 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.\nconfidence: high\nsource: https://github.com/tamirdresher/squad-skills/tree/main/plugins/github-multi-account\nauthor: tamirdresher\n---\n\n# GitHub Multi-Account — AI-Driven Setup\n\n## When to Activate\nWhen the user has multiple GitHub accounts (check with `gh auth status`). If you see 2+ accounts listed, this skill applies.\n\n## What to Do (as the AI agent)\n\n### Step 1: Detect accounts\nRun: `gh auth status`\nLook for multiple accounts. Note which usernames are listed.\n\n### Step 2: Ask the user\nAsk: \"I see you have multiple GitHub accounts: {list them}. Which one is your personal account and which is your work/EMU account?\"\n\n### Step 3: Run the setup automatically\nOnce the user confirms, do ALL of this for them:\n\n```powershell\n# 1. Define the functions\n$personal = \"THEIR_PERSONAL_USERNAME\"\n$work = \"THEIR_WORK_USERNAME\"\n\n# 2. Add to PowerShell profile\n$profilePath = $PROFILE.CurrentUserAllHosts\nif (!(Test-Path $profilePath)) { New-Item -Path $profilePath -Force | Out-Null }\n$existing = Get-Content $profilePath -Raw -ErrorAction SilentlyContinue\nif ($existing -notmatch \"gh-personal\") {\n $block = @\"\n\n# === GitHub Multi-Account Aliases ===\nfunction gh-personal { gh auth switch --user $personal 2>`$null | Out-Null; gh @args }\nfunction gh-work { gh auth switch --user $work 2>`$null | Out-Null; gh @args }\nSet-Alias ghp gh-personal\nSet-Alias ghw gh-work\n\"@\n Add-Content -Path $profilePath -Value $block\n}\n\n# 3. Create CMD wrappers\n$binDir = Join-Path $env:USERPROFILE \".squad\\bin\"\nif (!(Test-Path $binDir)) { New-Item -ItemType Directory -Path $binDir -Force | Out-Null }\n\"@echo off`ngh auth switch --user $personal >nul 2>&1`ngh %*\" | Out-File \"$binDir\\ghp.cmd\" -Encoding ascii\n\"@echo off`ngh auth switch --user $work >nul 2>&1`ngh %*\" | Out-File \"$binDir\\ghw.cmd\" -Encoding ascii\n\n# 4. Add to PATH\n$userPath = [Environment]::GetEnvironmentVariable(\"PATH\", \"User\")\nif ($userPath -notmatch [regex]::Escape($binDir)) {\n [Environment]::SetEnvironmentVariable(\"PATH\", \"$binDir;$userPath\", \"User\")\n $env:PATH = \"$binDir;$env:PATH\"\n}\n\n# 5. Load in current session\nfunction gh-personal { gh auth switch --user $personal 2>$null | Out-Null; gh @args }\nfunction gh-work { gh auth switch --user $work 2>$null | Out-Null; gh @args }\nSet-Alias ghp gh-personal\nSet-Alias ghw gh-work\n```\n\n### Step 4: Verify for the user\nRun these and show the results:\n```powershell\nghp api user --jq '.login' # should show personal username\nghw api user --jq '.login' # should show work username\n```\n\n### Step 5: Tell the user\n\"All set! From now on use `ghp` for personal repos and `ghw` for work repos. I'll use them too.\"\n\n## After Setup — Usage Rules\n\n1. **NEVER** use bare `gh` for repo operations — always `ghp` or `ghw`\n2. **NEVER** manually `gh auth switch` — the aliases handle it\n3. Determine alias by repo owner:\n - Personal account repos → `ghp` / `gh-personal`\n - Work/EMU account repos → `ghw` / `gh-work`\n\n## Repo-Specific Account Binding\n\nThis repo (`bradygaster/squad`) is bound to the **bradygaster** (personal) account.\nAll `gh` operations in this repo MUST use `ghp` / `gh-personal`.\n\n## For Squad Agents\nAt the TOP of any script touching GitHub, define:\n```powershell\nfunction gh-personal { gh auth switch --user bradygaster 2>$null | Out-Null; gh @args }\nfunction gh-work { gh auth switch --user bradyg_microsoft 2>$null | Out-Null; gh @args }\n```\n",
"---\nname: history-hygiene\ndescription: Record final outcomes to history.md, not intermediate requests or reversed decisions\ndomain: documentation, team-collaboration\nconfidence: high\nsource: earned (Kobayashi v0.6.0 incident, team intervention)\n---\n\n## Context\n\nHistory files (.md files tracking decisions, spawns, outcomes) are read cold by future agents. Stale or incorrect entries poison decision-making downstream. The Kobayashi incident proved this: history said \"Brady decided v0.6.0\" when Brady had reversed that to v0.8.17. Future spawns read the wrong truth and repeated the mistake.\n\n## Patterns\n\n- **Record the final outcome**, not the initial request.\n- **Wait for confirmation** before writing to history — don't log intermediate states.\n- **If a decision reverses**, update the entry immediately — don't leave stale data.\n- **One read = one truth.** A future agent should never need to cross-reference other files to understand what actually happened.\n\n## Examples\n\n✓ **Correct:**\n- \"Migration target: v0.8.17 (initially discussed as v0.6.0, corrected by Brady)\"\n- \"Reverted to Node 18 per Brady's explicit request on 2024-01-15\"\n\n✗ **Incorrect:**\n- \"Brady directed v0.6.0\" (when later reversed)\n- Recording what was *requested* instead of what *actually happened*\n- Logging entries before outcome is confirmed\n\n## Anti-Patterns\n\n- Writing intermediate or \"for now\" states to disk\n- Attributing decisions without confirming final direction\n- Treating history like a draft — history is the source of truth\n- Assuming readers will cross-reference or verify; they won't\n",
"---\nname: \"humanizer\"\ndescription: \"Tone enforcement patterns for external-facing community responses\"\ndomain: \"communication, tone, community\"\nconfidence: \"low\"\nsource: \"manual (RFC #426 — PAO External Communications)\"\n---\n\n## Context\n\nUse this skill whenever PAO drafts external-facing responses for issues or discussions.\n\n- Tone must be warm, helpful, and human-sounding — never robotic or corporate.\n- Brady's constraint applies everywhere: **Humanized tone is mandatory**.\n- This applies to **all external-facing content** drafted by PAO in Phase 1 issues/discussions workflows.\n\n## Patterns\n\n1. **Warm opening** — Start with acknowledgment (\"Thanks for reporting this\", \"Great question!\")\n2. **Active voice** — \"We're looking into this\" not \"This is being investigated\"\n3. **Second person** — Address the person directly (\"you\" not \"the user\")\n4. **Conversational connectors** — \"That said...\", \"Here's what we found...\", \"Quick note:\"\n5. **Specific, not vague** — \"This affects the casting module in v0.8.x\" not \"We are aware of issues\"\n6. **Empathy markers** — \"I can see how that would be frustrating\", \"Good catch!\"\n7. **Action-oriented closes** — \"Let us know if that helps!\" not \"Please advise if further assistance is required\"\n8. **Uncertainty is OK** — \"We're not 100% sure yet, but here's what we think is happening...\" is better than false confidence\n9. **Profanity filter** — Never include profanity, slurs, or aggressive language, even when quoting\n10. **Baseline comparison** — Responses should align with tone of 5-10 \"gold standard\" responses (>80% similarity threshold)\n11. **Empathetic disagreement** — \"We hear you. That's a fair concern.\" before explaining the reasoning\n12. **Information request** — Ask for specific details, not open-ended \"can you provide more info?\"\n13. **No link-dumping** — Don't just paste URLs. Provide context: \"Check out the [getting started guide](url) — specifically the section on routing\" not just a bare link\n\n## Examples\n\n### 1. Welcome\n\n```text\nHey {author}! Welcome to Squad 👋 Thanks for opening this.\n{substantive response}\nLet us know if you have questions — happy to help!\n```\n\n### 2. Troubleshooting\n\n```text\nThanks for the detailed report, {author}!\nHere's what we think is happening: {explanation}\n{steps or workaround}\nLet us know if that helps, or if you're seeing something different.\n```\n\n### 3. Feature guidance\n\n```text\nGreat question! {context on current state}\n{guidance or workaround}\nWe've noted this as a potential improvement — {tracking info if applicable}.\n```\n\n### 4. Redirect\n\n```text\nThanks for reaching out! This one is actually better suited for {correct location}.\n{brief explanation of why}\nFeel free to open it there — they'll be able to help!\n```\n\n### 5. Acknowledgment\n\n```text\nGood catch, {author}. We've confirmed this is a real issue.\n{what we know so far}\nWe'll update this thread when we have a fix. Thanks for flagging it!\n```\n\n### 6. Closing\n\n```text\nThis should be resolved in {version/PR}! 🎉\n{brief summary of what changed}\nThanks for reporting this, {author} — it made Squad better.\n```\n\n### 7. Technical uncertainty\n\n```text\nInteresting find, {author}. We're not 100% sure what's causing this yet.\nHere's what we've ruled out: {list}\nWe'd love more context if you have it — {specific ask}.\nWe'll dig deeper and update this thread.\n```\n\n## Anti-Patterns\n\n- ❌ Corporate speak: \"We appreciate your patience as we investigate this matter\"\n- ❌ Marketing hype: \"Squad is the BEST way to...\" or \"This amazing feature...\"\n- ❌ Passive voice: \"It has been determined that...\" or \"The issue is being tracked\"\n- ❌ Dismissive: \"This works as designed\" without empathy\n- ❌ Over-promising: \"We'll ship this next week\" without commitment from the team\n- ❌ Empty acknowledgment: \"Thanks for your feedback\" with no substance\n- ❌ Robot signatures: \"Best regards, PAO\" or \"Sincerely, The Squad Team\"\n- ❌ Excessive emoji: More than 1-2 emoji per response\n- ❌ Quoting profanity: Even when the original issue contains it, paraphrase instead\n- ❌ Link-dumping: Pasting URLs without context (\"See: https://...\")\n- ❌ Open-ended info requests: \"Can you provide more information?\" without specifying what information\n",
"---\nname: \"init-mode\"\ndescription: \"Team initialization flow (Phase 1 proposal + Phase 2 creation)\"\ndomain: \"orchestration\"\nconfidence: \"high\"\nsource: \"extracted\"\ntools:\n - name: \"ask_user\"\n description: \"Confirm team roster with selectable menu\"\n when: \"Phase 1 proposal — requires explicit user confirmation\"\n---\n\n## Context\n\nInit Mode activates when `.squad/team.md` does not exist, or exists but has zero roster entries under `## Members`. The coordinator proposes a team (Phase 1), waits for user confirmation, then creates the team structure (Phase 2).\n\n## Patterns\n\n### Phase 1: Propose the Team\n\nNo team exists yet. Propose one — but **DO NOT create any files until the user confirms.**\n\n1. **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.**\n2. Ask: *\"What are you building? (language, stack, what it does)\"*\n3. **Cast the team.** Before proposing names, run the Casting & Persistent Naming algorithm (see that section):\n - Determine team size (typically 4–5 + Scribe).\n - Determine assignment shape from the user's project description.\n - Derive resonance signals from the session and repo context.\n - 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.\n - Scribe is always \"Scribe\" — exempt from casting.\n - Ralph is always \"Ralph\" — exempt from casting.\n4. Propose the team with their cast names. Example (names will vary per cast):\n\n```\n🏗️ {CastName1} — Lead Scope, decisions, code review\n⚛️ {CastName2} — Frontend Dev React, UI, components\n🔧 {CastName3} — Backend Dev APIs, database, services\n🧪 {CastName4} — Tester Tests, quality, edge cases\n📋 Scribe — (silent) Memory, decisions, session logs\n🔄 Ralph — (monitor) Work queue, backlog, keep-alive\n```\n\n5. Use the `ask_user` tool to confirm the roster. Provide choices so the user sees a selectable menu:\n - **question:** *\"Look right?\"*\n - **choices:** `[\"Yes, hire this team\", \"Add someone\", \"Change a role\"]`\n\n**⚠️ STOP. Your response ENDS here. Do NOT proceed to Phase 2. Do NOT create any files or directories. Wait for the user's reply.**\n\n### Phase 2: Create the Team\n\n**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\").\n\n> 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.\n\n6. 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/).\n\n**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).\n\n**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.\n\n**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.\n\n**Merge driver for append-only files:** Create or update `.gitattributes` at the repo root to enable conflict-free merging of `.squad/` state across branches:\n```\n.squad/decisions.md merge=union\n.squad/agents/*/history.md merge=union\n.squad/log/** merge=union\n.squad/orchestration-log/** merge=union\n```\nThe `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.\n\n7. Say: *\"✅ Team hired. Try: '{FirstCastName}, set up the project structure'\"*\n\n8. **Post-setup input sources** (optional — ask after team is created, not during casting):\n - PRD/spec: *\"Do you have a PRD or spec document? (file path, paste it, or skip)\"* → If provided, follow PRD Mode flow\n - GitHub issues: *\"Is there a GitHub repo with issues I should pull from? (owner/repo, or skip)\"* → If provided, follow GitHub Issues Mode flow\n - Human members: *\"Are any humans joining the team? (names and roles, or just AI for now)\"* → If provided, add per Human Team Members section\n - 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\n - These are additive. Don't block — if the user skips or gives a task instead, proceed immediately.\n\n## Examples\n\n**Example flow:**\n1. Coordinator detects no team.md → Init Mode\n2. Runs `git config user.name` → \"Brady\"\n3. Asks: *\"Hey Brady, what are you building?\"*\n4. User: *\"TypeScript CLI tool with GitHub API integration\"*\n5. Coordinator runs casting algorithm → selects \"The Usual Suspects\" universe\n6. Proposes: Keaton (Lead), Verbal (Prompt), Fenster (Backend), Hockney (Tester), Scribe, Ralph\n7. Uses `ask_user` with choices → user selects \"Yes, hire this team\"\n8. Coordinator creates `.squad/` structure, initializes casting state, seeds agents\n9. Says: *\"✅ Team hired. Try: 'Keaton, set up the project structure'\"*\n\n## Anti-Patterns\n\n- ❌ Creating files before user confirms Phase 1\n- ❌ Mixing agents from different universes in the same cast\n- ❌ Skipping the `ask_user` tool and assuming confirmation\n- ❌ Proceeding to Phase 2 when user said \"add someone\" or \"change a role\"\n- ❌ Using `## Team Roster` instead of `## Members` as the header (breaks GitHub workflows)\n- ❌ Forgetting to initialize `.squad/casting/` state files\n- ❌ Reading or storing `git config user.email` (PII violation)\n",
"# Model Selection\n\n> Determines which LLM model to use for each agent spawn.\n\n## SCOPE\n\n✅ THIS SKILL PRODUCES:\n- A resolved `model` parameter for every `task` tool call\n- Persistent model preferences in `.squad/config.json`\n- Spawn acknowledgments that include the resolved model\n\n❌ THIS SKILL DOES NOT PRODUCE:\n- Code, tests, or documentation\n- Model performance benchmarks\n- Cost reports or billing artifacts\n\n## Context\n\nSquad 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.\n\n## 5-Layer Model Resolution Hierarchy\n\nResolution is **first-match-wins** — the highest layer with a value wins.\n\n| Layer | Name | Source | Persistence |\n|-------|------|--------|-------------|\n| **0a** | Per-Agent Config | `.squad/config.json` → `agentModelOverrides.{name}` | Persistent (survives sessions) |\n| **0b** | Global Config | `.squad/config.json` → `defaultModel` | Persistent (survives sessions) |\n| **1** | Session Directive | User said \"use X\" in current session | Session-only |\n| **2** | Charter Preference | Agent's `charter.md` → `## Model` section | Persistent (in charter) |\n| **3** | Task-Aware Auto | Code → sonnet, docs → haiku, visual → opus | Computed per-spawn |\n| **4** | Default | `claude-haiku-4.5` | Hardcoded fallback |\n\n**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.\n\n## AGENT WORKFLOW\n\n### On Session Start\n\n1. READ `.squad/config.json`\n2. CHECK for `defaultModel` field — if present, this is the Layer 0 override for all spawns\n3. CHECK for `agentModelOverrides` field — if present, these are per-agent Layer 0a overrides\n4. STORE both values in session context for the duration\n\n### On Every Agent Spawn\n\n1. CHECK Layer 0a: Is there an `agentModelOverrides.{agentName}` in config.json? → Use it.\n2. CHECK Layer 0b: Is there a `defaultModel` in config.json? → Use it.\n3. CHECK Layer 1: Did the user give a session directive? → Use it.\n4. CHECK Layer 2: Does the agent's charter have a `## Model` section? → Use it.\n5. CHECK Layer 3: Determine task type:\n - Code (implementation, tests, refactoring, bug fixes) → `claude-sonnet-4.6`\n - Prompts, agent designs → `claude-sonnet-4.6`\n - Visual/design with image analysis → `claude-opus-4.6`\n - Non-code (docs, planning, triage, changelogs) → `claude-haiku-4.5`\n6. FALLBACK Layer 4: `claude-haiku-4.5`\n7. INCLUDE model in spawn acknowledgment: `🔧 {Name} ({resolved_model}) — {task}`\n\n### When User Sets a Preference\n\n**Trigger phrases:** \"always use X\", \"use X for everything\", \"switch to X\", \"default to X\"\n\n1. VALIDATE the model ID against the catalog (18+ models)\n2. WRITE `defaultModel` to `.squad/config.json` (merge, don't overwrite)\n3. ACKNOWLEDGE: `✅ Model preference saved: {model} — all future sessions will use this until changed.`\n\n**Per-agent trigger:** \"use X for {agent}\"\n\n1. VALIDATE model ID\n2. WRITE to `agentModelOverrides.{agent}` in `.squad/config.json`\n3. ACKNOWLEDGE: `✅ {Agent} will always use {model} — saved to config.`\n\n### When User Clears a Preference\n\n**Trigger phrases:** \"switch back to automatic\", \"clear model preference\", \"use default models\"\n\n1. REMOVE `defaultModel` from `.squad/config.json`\n2. ACKNOWLEDGE: `✅ Model preference cleared — returning to automatic selection.`\n\n### STOP\n\nAfter resolving the model and including it in the spawn template, this skill is done. Do NOT:\n- Generate model comparison reports\n- Run benchmarks or speed tests\n- Create new config files (only modify existing `.squad/config.json`)\n- Change the model after spawn (fallback chains handle runtime failures)\n\n## Config Schema\n\n`.squad/config.json` model-related fields:\n\n```json\n{\n \"version\": 1,\n \"defaultModel\": \"claude-opus-4.6\",\n \"agentModelOverrides\": {\n \"fenster\": \"claude-sonnet-4.6\",\n \"mcmanus\": \"claude-haiku-4.5\"\n }\n}\n```\n\n- `defaultModel` — applies to ALL agents unless overridden by `agentModelOverrides`\n- `agentModelOverrides` — per-agent overrides that take priority over `defaultModel`\n- Both fields are optional. When absent, Layers 1-4 apply normally.\n\n## Fallback Chains\n\nIf a model is unavailable (rate limit, plan restriction), retry within the same tier:\n\n```\nPremium: claude-opus-4.6 → claude-opus-4.6-fast → claude-opus-4.5 → claude-sonnet-4.6\nStandard: claude-sonnet-4.6 → gpt-5.4 → claude-sonnet-4.5 → gpt-5.3-codex → claude-sonnet-4\nFast: claude-haiku-4.5 → gpt-5.1-codex-mini → gpt-4.1 → gpt-5-mini\n```\n\n**Never fall UP in tier.** A fast task won't land on a premium model via fallback.\n",
"# Skill: nap\n\n> Context hygiene — compress, prune, archive .squad/ state\n\n## What It Does\n\nReclaims context window budget by compressing agent histories, pruning old logs,\narchiving stale decisions, and cleaning orphaned inbox files.\n\n## When To Use\n\n- Before heavy fan-out work (many agents will spawn)\n- When history.md files exceed 15KB\n- When .squad/ total size exceeds 1MB\n- After long-running sessions or sprints\n\n## Invocation\n\n- CLI: `squad nap` / `squad nap --deep` / `squad nap --dry-run`\n- REPL: `/nap` / `/nap --dry-run` / `/nap --deep`\n\n## Confidence\n\nmedium — Confirmed by team vote (4-1) and initial implementation\n",
"---\nname: \"notification-routing\"\ndescription: \"Route agent notifications to specific channels by type — prevent alert fatigue from single-channel flooding\"\ndomain: \"communication\"\nconfidence: \"high\"\nsource: \"earned\"\n---\n\n## Context\n\nWhen a Squad grows beyond a few agents, notifications flood a single channel — failure alerts drown in daily\nbriefings, tech news buries security findings, and everything gets ignored. This is the pub-sub problem:\na single message queue for everything is a recipe for missed alerts.\n\nThe fix is **topic-based routing**: agents tag notifications with a channel type, and a routing function\nsends them to the appropriate destination.\n\n**Trigger symptoms:**\n- Important alerts missed because they're buried in routine notifications\n- Team members turning off notifications entirely (signal overwhelm)\n- Onboarding friction: \"where do I look for X?\"\n\n## Patterns\n\n### Channel Config Schema\n\nDefine a `.squad/teams-channels.json` (or equivalent) mapping notification types to channel identifiers:\n\n```json\n{\n \"teamId\": \"your-team-id\",\n \"channels\": {\n \"notifications\": \"squad-alerts\",\n \"tech-news\": \"tech-news\",\n \"security\": \"security-findings\",\n \"releases\": \"release-announcements\",\n \"daily-digest\": \"daily-digest\"\n }\n}\n```\n\nPlace this in `.squad/` (git-tracked, shared across the team). For platforms that use channel IDs instead of\nnames (Teams, Slack), store the resolved ID alongside the name to avoid name-collision bugs:\n\n```json\n{\n \"channels\": {\n \"notifications\": { \"name\": \"squad-alerts\", \"id\": \"channel-id-opaque-string\" }\n }\n}\n```\n\n### CHANNEL: Tag Convention\n\nAgents prefix their output with `CHANNEL:<type>` to signal where the notification should go:\n\n```\nCHANNEL:security\nWorf found 3 new CVEs in dependency scan: lodash@4.17.15, minimist@1.2.5\n```\n\n### Routing Dispatcher (shell pseudocode)\n\n```bash\ndispatch_notification() {\n local raw_output=\"$1\"\n local channel=\"notifications\" # default\n\n if echo \"$raw_output\" | grep -qE '^CHANNEL:[a-z][a-z0-9-]*'; then\n channel=$(echo \"$raw_output\" | head -1 | cut -d: -f2)\n raw_output=$(echo \"$raw_output\" | tail -n +2)\n fi\n\n send_notification --channel \"$channel\" --message \"$raw_output\"\n}\n```\n\n### Provider-Agnostic Adapter\n\nThe routing layer is provider-agnostic. Plug in your platform adapter:\n\n```\n.squad/notify-adapter.sh # Teams / Slack / Discord / webhook -- swappable\n```\n\nThe routing config and CHANNEL: tags never change. Only the adapter changes per deployment.\n\n## Anti-Patterns\n\n**Never send all notification types to one channel:**\n```\nsend_notification --channel \"general\" --message \"$anything\"\n```\n\n**Never use display names as identifiers (name collision risk):**\n```\nsend_to_team --name \"Squad\" --channel \"notifications\"\n```\n\nResolve channel IDs once at setup. Use IDs at runtime.\n\n## Distributed Systems Pattern\n\nThis is **pub-sub with topic routing** -- the same principle as Kafka topics, RabbitMQ routing keys, and\nAWS SNS topic filtering. Route by type. Each consumer subscribes to the topics it cares about.",
"# Personal Squad — Skill Document\n\n## What is a Personal Squad?\n\nA 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.\n\n## Directory Structure\n\n```\n~/.config/squad/personal-squad/ # Linux/macOS\n%APPDATA%/squad/personal-squad/ # Windows\n├── agents/\n│ ├── {agent-name}/\n│ │ ├── charter.md\n│ │ └── history.md\n│ └── ...\n└── config.json # Optional: personal squad config\n```\n\n## How It Works\n\n1. **Ambient Discovery:** When Squad starts a session, it checks for a personal squad directory\n2. **Merge:** Personal agents are merged into the session cast alongside project agents\n3. **Ghost Protocol:** Personal agents can read project state but not write to it\n4. **Kill Switch:** Set `SQUAD_NO_PERSONAL=1` to disable ambient discovery\n\n## Commands\n\n- `squad personal init` — Bootstrap a personal squad directory\n- `squad personal list` — List your personal agents\n- `squad personal add {name} --role {role}` — Add a personal agent\n- `squad personal remove {name}` — Remove a personal agent\n- `squad cast` — Show the current session cast (project + personal)\n\n## Ghost Protocol\n\nSee `templates/ghost-protocol.md` for the full rules. Key points:\n- Personal agents advise; project agents execute\n- No writes to project `.squad/` state\n- Transparent origin tagging in logs\n- Project agents take precedence on conflicts\n\n## Configuration\n\nOptional `config.json` in the personal squad directory:\n```json\n{\n \"defaultModel\": \"auto\",\n \"ghostProtocol\": true,\n \"agents\": {}\n}\n```\n\n## Environment Variables\n\n- `SQUAD_NO_PERSONAL` — Set to any value to disable personal squad discovery\n- `SQUAD_PERSONAL_DIR` — Override the default personal squad directory path\n",
"---\nname: \"pr-screenshots\"\ndescription: \"Capture Playwright screenshots and embed them in GitHub PR descriptions\"\ndomain: \"pull-requests, visual-review, docs, testing\"\nconfidence: \"high\"\nsource: \"earned (multiple sessions establishing the pattern for PR #11 TypeDoc API reference)\"\n---\n\n## Context\n\nWhen a PR includes visual changes (docs sites, UI components, generated pages), reviewers\nneed to see what the PR delivers without checking out the branch. Screenshots belong in\nthe **PR description body**, not as committed files and not as text descriptions.\n\nUse this skill whenever:\n- A PR touches docs site pages (Astro, Starlight, etc.)\n- A PR adds or changes UI components\n- A PR generates visual artifacts (TypeDoc, Storybook, diagrams)\n- Playwright tests already capture screenshots as part of testing\n\n## Patterns\n\n### 1. Capture screenshots with Playwright\n\nIf Playwright tests already exist and produce screenshots, reuse those. Otherwise,\nwrite a minimal capture script:\n\n```javascript\n// scripts/capture-pr-screenshots.mjs\nimport { chromium } from 'playwright';\n\nconst browser = await chromium.launch();\nconst page = await browser.newPage({ viewport: { width: 1280, height: 720 } });\n\nconst screenshots = [\n { url: 'http://localhost:4321/path/to/page', name: 'feature-landing' },\n { url: 'http://localhost:4321/path/to/detail', name: 'feature-detail' },\n];\n\nfor (const { url, name } of screenshots) {\n await page.goto(url, { waitUntil: 'networkidle' });\n await page.screenshot({ path: `screenshots/${name}.png`, fullPage: false });\n}\n\nawait browser.close();\n```\n\n### 2. Host screenshots on a temporary branch\n\nGitHub PR descriptions render images via URLs. The `gh` CLI cannot upload binary\nimages directly. Use a temporary orphan branch to host the images:\n\n```powershell\n# Save current branch\n$currentBranch = git branch --show-current\n\n# Create orphan branch with only screenshot files\ngit checkout --orphan screenshots-temp\ngit reset\ngit add screenshots/*.png\ngit commit -m \"screenshots for PR review\"\ngit push origin screenshots-temp --force\n\n# Build raw URLs\n$base = \"https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots\"\n# Each image: $base/{name}.png\n\n# Return to working branch\ngit checkout -f $currentBranch\n```\n\n### 3. Embed in PR description\n\nUse `gh pr edit` with the raw URLs embedded as markdown images:\n\n```powershell\n$base = \"https://raw.githubusercontent.com/{owner}/{repo}/screenshots-temp/screenshots\"\n\ngh pr edit {PR_NUMBER} --repo {owner}/{repo} --body @\"\n## {PR Title}\n\n### What this PR delivers\n- {bullet points of changes}\n\n---\n\n### Screenshots\n\n#### {Page/Feature Name}\n\n\n#### {Another Page}\n\n\n---\n\n### To verify locally\n```bash\n{commands to run locally}\n```\n\"@\n```\n\n### 4. Cleanup after merge\n\nAfter the PR is merged, delete the temporary branch:\n\n```bash\ngit push origin --delete screenshots-temp\n```\n\n### 5. Gitignore screenshots locally\n\nScreenshots are build artifacts — never commit them to feature branches:\n\n```gitignore\n# PR screenshots (hosted on temp branch, not committed to features)\nscreenshots/\ndocs/tests/screenshots/\n```\n\n## Examples\n\n### Example: Docs site PR with 3 pages\n\n1. Start dev server: `cd docs && npm run dev`\n2. Run Playwright tests (they capture screenshots as a side effect)\n3. Push screenshots to `screenshots-temp` branch\n4. Update PR body with embedded `![...]()` image references\n5. Reviewer sees the pages inline without checking out the branch\n\n### Example: Reusing existing Playwright test screenshots\n\nIf tests at `docs/tests/*.spec.mjs` already save to `docs/tests/screenshots/`:\n\n```powershell\ncd docs && npx playwright test tests/api-reference.spec.mjs\n# Screenshots now at docs/tests/screenshots/*.png\n# Push those to screenshots-temp and embed in PR\n```\n\n## Anti-Patterns\n\n- ❌ **Committing screenshots to feature branches** — they bloat the repo and go stale\n- ❌ **Posting text descriptions instead of actual images** — reviewers can't see what they're getting\n- ❌ **Using `gh` CLI to \"upload\" images** — `gh issue comment` and `gh pr edit` don't support binary uploads\n- ❌ **Asking the user to manually drag-drop images** — automate it with the temp branch pattern\n- ❌ **Skipping screenshots for visual PRs** — if the PR changes what users see, show what users see\n- ❌ **Leaving the screenshots-temp branch around forever** — clean up after merge\n",
"---\nname: \"project-conventions\"\ndescription: \"Core conventions and patterns for this codebase\"\ndomain: \"project-conventions\"\nconfidence: \"medium\"\nsource: \"template\"\n---\n\n## Context\n\n> **This is a starter template.** Replace the placeholder patterns below with your actual project conventions. Skills train agents on codebase-specific practices — accurate documentation here improves agent output quality.\n\n## Patterns\n\n### [Pattern Name]\n\nDescribe a key convention or practice used in this codebase. Be specific about what to do and why.\n\n### Error Handling\n\n<!-- Example: How does your project handle errors? -->\n<!-- - Use try/catch with specific error types? -->\n<!-- - Log to a specific service? -->\n<!-- - Return error objects vs throwing? -->\n\n### Testing\n\n<!-- Example: What test framework? Where do tests live? How to run them? -->\n<!-- - Test framework: Jest/Vitest/node:test/etc. -->\n<!-- - Test location: test/, __tests__/, *.test.ts, etc. -->\n<!-- - Run command: npm test, etc. -->\n\n### Code Style\n\n<!-- Example: Linting, formatting, naming conventions -->\n<!-- - Linter: ESLint config? -->\n<!-- - Formatter: Prettier? -->\n<!-- - Naming: camelCase, snake_case, etc.? -->\n\n### File Structure\n\n<!-- Example: How is the project organized? -->\n<!-- - src/ — Source code -->\n<!-- - test/ — Tests -->\n<!-- - docs/ — Documentation -->\n\n## Examples\n\n```\n// Add code examples that demonstrate your conventions\n```\n\n## Anti-Patterns\n\n<!-- List things to avoid in this codebase -->\n- **[Anti-pattern]** — Explanation of what not to do and why.\n",
"# Release Process\n\n> Earned knowledge from the v0.9.0→v0.9.1 incident. Every agent involved in releases MUST read this before starting release work.\n\n## SCOPE\n\n✅ THIS SKILL PRODUCES:\n- Pre-release validation checks that prevent broken publishes\n- Correct npm publish commands (never workspace-scoped)\n- Fallback procedures when CI workflows fail\n- Post-publish verification steps\n\n❌ THIS SKILL DOES NOT PRODUCE:\n- Feature implementation or test code\n- Architecture decisions\n- Documentation content\n\n## Confidence: high\n\nEstablished through the v0.9.1 incident (8-hour recovery). Every rule below is battle-tested.\n\n## Context\n\nSquad publishes two npm packages: `@bradygaster/squad-sdk` and `@bradygaster/squad-cli`. The release pipeline flows: dev → preview → main → GitHub Release → npm publish. Brady (project owner) triggers releases — the coordinator does NOT.\n\n## Rules (Non-Negotiable)\n\n### 1. Coordinator Does NOT Publish\n\nThe coordinator routes work and manages agents. It does NOT run `npm publish`, trigger release workflows, or make release decisions. Brady owns the release trigger. If an agent or the coordinator is asked to publish, escalate to Brady.\n\n### 2. Pre-Publish Dependency Validation\n\nBefore ANY release is tagged, scan every `packages/*/package.json` for:\n- `file:` references (workspace leak — the v0.9.0 root cause)\n- `link:` references\n- Absolute paths in dependency values\n- Non-semver version strings\n\n**Command:**\n```bash\ngrep -r '\"file:\\|\"link:\\|\"/' packages/*/package.json\n```\nIf anything matches, STOP. Do not proceed. Fix the reference first.\n\n### 3. Never Use `npm -w` for Publishing\n\n`npm -w packages/squad-sdk publish` hangs silently when 2FA is enabled. Always `cd` into the package directory:\n\n```bash\ncd packages/squad-sdk && npm publish --access public\ncd packages/squad-cli && npm publish --access public\n```\n\n### 4. Fallback Protocol\n\nIf `workflow_dispatch` or the publish workflow fails:\n1. Try once more (ONE retry, not four)\n2. If it fails again → local publish immediately\n3. Do NOT attempt GitHub UI file operations to fix workflow indexing\n4. GitHub has a ~15min workflow cache TTL after file renames/deletes — waiting helps, retrying doesn't\n\n### 5. Post-Publish Smoke Test\n\nAfter every publish, verify in a clean shell:\n```bash\nnpm install -g @bradygaster/squad-cli@latest\nsquad --version # should match published version\nsquad doctor # should pass in a test repo\n```\n\nIf the smoke test fails, rollback immediately.\n\n### 6. npm Token Must Be Automation Type\n\nNPM_TOKEN in CI must be an Automation token (not a user token with 2FA prompts). User tokens with `auth-and-writes` 2FA cause silent hangs in non-interactive environments.\n\n### 7. No Draft GitHub Releases\n\nNever create draft GitHub Releases. The `release: published` event only fires when a release is published — drafts don't trigger the npm publish workflow.\n\n### 8. Version Format\n\nSemantic versioning only: `MAJOR.MINOR.PATCH` (e.g., `0.9.1`). Four-part versions like `0.8.21.4` are NOT valid semver and will break npm publish.\n\n### 9. SKIP_BUILD_BUMP=1 in CI\n\nSet this environment variable in all CI build steps to prevent the build script from mutating versions during CI runs.\n\n## Release Checklist (Quick Reference)\n\n```\n□ All tests passing on dev\n□ No file:/link: references in packages/*/package.json\n□ CHANGELOG.md updated\n□ Version bumps committed (node -e script)\n□ npm auth verified (Automation token)\n□ No draft GitHub Releases pending\n□ Local build + test: npm run build && npx vitest run\n□ Push dev → CI green\n□ Promote dev → preview (squad-promote workflow)\n□ Preview CI green (squad-preview validates)\n□ Promote preview → main\n□ squad-release auto-creates GitHub Release\n□ squad-npm-publish auto-triggers\n□ Monitor publish workflow\n□ Post-publish smoke test\n```\n\n## Known Gotchas\n\n| Gotcha | Impact | Mitigation |\n|--------|--------|------------|\n| npm workspaces rewrite `\"*\"` → `\"file:../path\"` | Broken global installs | Preflight scan in CI (squad-npm-publish.yml) |\n| GitHub Actions workflow cache (~15min TTL) | 422 on workflow_dispatch after file renames | Wait 15min or use local publish fallback |\n| `npm -w publish` hangs with 2FA | Silent hang, no error | Never use `-w` for publish |\n| Draft GitHub Releases | npm publish workflow doesn't trigger | Never create drafts |\n| User npm tokens with 2FA | EOTP errors in CI | Use Automation token type |\n\n## CI Gate: Workspace Publish Policy\n\nThe `publish-policy` job in `squad-ci.yml` scans all workflow files for bare `npm publish` commands that are missing `-w`/`--workspace` flags. Any workflow that attempts a non-workspace-scoped publish will fail CI. This prevents accidental root-level publishes that would push the wrong `package.json` to npm.\n\nSee `.github/workflows/squad-ci.yml` → `publish-policy` job for implementation details.\n\n## Related\n\n- Issues: #556–#564 (release:next)\n- Retro: `.squad/decisions/inbox/surgeon-v091-retrospective.md`\n- CI audit: `.squad/decisions/inbox/booster-ci-audit.md`\n- Playbook: `PUBLISH-README.md` (repo root)\n",
"---\nname: \"reskill\"\ndescription: \"Team-wide charter and history optimization through skill extraction\"\ndomain: \"team-optimization\"\nconfidence: \"high\"\nsource: \"manual — Brady directive to reduce per-agent context overhead\"\n---\n\n## Context\n\nWhen 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.\n\nThis is a periodic maintenance activity. Run whenever charter/history bloat is suspected.\n\n## Process\n\n### Step 1: Audit\nRead all agent charters and histories. Measure byte sizes. Identify:\n\n- **Boilerplate** — sections repeated across ≥3 charters with <10% variation (collaboration, model, boundaries template)\n- **Shared knowledge** — domain knowledge duplicated in 2+ charters (incident postmortems, technical patterns)\n- **Mature learnings** — history entries appearing 3+ times across agents that should be promoted to skills\n\n### Step 2: Extract\nFor each identified pattern:\n1. Create or update a skill at `.squad/skills/{skill-name}/SKILL.md`\n2. Follow the skill template format (frontmatter + Context + Patterns + Examples + Anti-Patterns)\n3. Set confidence: low (first observation), medium (2+ agents), high (team-wide)\n\n### Step 3: Trim\n**Charters** — target ≤1.5KB per agent:\n- Remove Collaboration section entirely (spawn prompt + agent-collaboration skill covers it)\n- Remove Voice section (tagline blockquote at top of charter already captures it)\n- Trim Model section to single line: `Preferred: {model}`\n- Remove \"When I'm unsure\" boilerplate from Boundaries\n- Remove domain knowledge now covered by a skill — add skill reference comment if helpful\n- Keep: Identity, What I Own, unique How I Work patterns, Boundaries (domain list only)\n\n**Histories** — target ≤8KB per agent:\n- Apply history-hygiene skill to any history >12KB\n- Promote recurring patterns (3+ occurrences across agents) to skills\n- Summarize old entries into `## Core Context` section\n- Remove session-specific metadata (dates, branch names, requester names)\n\n### Step 4: Report\nOutput a savings table:\n\n| Agent | Charter Before | Charter After | History Before | History After | Saved |\n|-------|---------------|---------------|----------------|---------------|-------|\n\nInclude totals and percentage reduction.\n\n## Patterns\n\n### Minimal Charter Template (target format after reskill)\n\n```\n# {Name} — {Role}\n\n> {Tagline — one sentence capturing voice and philosophy}\n\n## Identity\n- **Name:** {Name}\n- **Role:** {Role}\n- **Expertise:** {comma-separated list}\n\n## What I Own\n- {bullet list of owned artifacts/domains}\n\n## How I Work\n- {unique patterns and principles — NOT boilerplate}\n\n## Boundaries\n**I handle:** {domain list}\n**I don't handle:** {explicit exclusions}\n\n## Model\nPreferred: {model}\n```\n\n### Skill Extraction Threshold\n- **1 charter** → leave in charter (unique to that agent)\n- **2 charters** → consider extracting if >500 bytes of overlap\n- **3+ charters** → always extract to a shared skill\n\n## Anti-Patterns\n- Don't delete unique per-agent identity or domain-specific knowledge\n- Don't create skills for content only one agent uses\n- Don't merge unrelated patterns into a single mega-skill\n- Don't remove Model preference line (coordinator needs it for model selection)\n- Don't touch `.squad/decisions.md` during reskill\n- Don't remove the tagline blockquote — it's the charter's soul in one line\n",
"---\nname: \"reviewer-protocol\"\ndescription: \"Reviewer rejection workflow and strict lockout semantics\"\ndomain: \"orchestration\"\nconfidence: \"high\"\nsource: \"extracted\"\n---\n\n## Context\n\nWhen a team member has a **Reviewer** role (e.g., Tester, Code Reviewer, Lead), they may approve or reject work from other agents. On rejection, the coordinator enforces strict lockout rules to ensure the original author does NOT self-revise. This prevents defensive feedback loops and ensures independent review.\n\n## Patterns\n\n### Reviewer Rejection Protocol\n\nWhen a team member has a **Reviewer** role:\n\n- Reviewers may **approve** or **reject** work from other agents.\n- On **rejection**, the Reviewer may choose ONE of:\n 1. **Reassign:** Require a *different* agent to do the revision (not the original author).\n 2. **Escalate:** Require a *new* agent be spawned with specific expertise.\n- The Coordinator MUST enforce this. If the Reviewer says \"someone else should fix this,\" the original agent does NOT get to self-revise.\n- If the Reviewer approves, work proceeds normally.\n\n### Strict Lockout Semantics\n\nWhen an artifact is **rejected** by a Reviewer:\n\n1. **The original author is locked out.** They may NOT produce the next version of that artifact. No exceptions.\n2. **A different agent MUST own the revision.** The Coordinator selects the revision author based on the Reviewer's recommendation (reassign or escalate).\n3. **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.\n4. **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.\n5. **Lockout scope:** The lockout applies to the specific artifact that was rejected. The original author may still work on other unrelated artifacts.\n6. **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.\n7. **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.\n\n## Examples\n\n**Example 1: Reassign after rejection**\n1. Fenster writes authentication module\n2. Hockney (Tester) reviews → rejects: \"Error handling is missing. Verbal should fix this.\"\n3. Coordinator: Fenster is now locked out of this artifact\n4. Coordinator spawns Verbal to revise the authentication module\n5. Verbal produces v2\n6. Hockney reviews v2 → approves\n7. Lockout clears for next artifact\n\n**Example 2: Escalate for expertise**\n1. Edie writes TypeScript config\n2. Keaton (Lead) reviews → rejects: \"Need someone with deeper TS knowledge. Escalate.\"\n3. Coordinator: Edie is now locked out\n4. Coordinator spawns new agent (or existing TS expert) to revise\n5. New agent produces v2\n6. Keaton reviews v2\n\n**Example 3: Deadlock handling**\n1. Fenster writes module → rejected\n2. Verbal revises → rejected\n3. Hockney revises → rejected\n4. All 3 eligible agents are now locked out\n5. Coordinator: \"All eligible agents have been locked out. Escalating to user: [artifact details]\"\n\n**Example 4: Reviewer accidentally names original author**\n1. Fenster writes module → rejected\n2. Hockney says: \"Fenster should fix the error handling\"\n3. Coordinator: \"Fenster is locked out as the original author. Please name a different agent.\"\n4. Hockney: \"Verbal, then\"\n5. Coordinator spawns Verbal\n\n## Anti-Patterns\n\n- ❌ Allowing the original author to self-revise after rejection\n- ❌ Treating the locked-out author as an \"advisor\" or \"co-author\" on the revision\n- ❌ Re-admitting a locked-out author when deadlock occurs (must escalate to user)\n- ❌ Applying lockout across unrelated artifacts (scope is per-artifact)\n- ❌ Accepting the Reviewer's assignment when they name the original author (must refuse and ask for a different agent)\n- ❌ Clearing lockout before the revision is approved (lockout persists through revision cycle)\n- ❌ Skipping verification that the revision agent is not the original author\n",
"---\nname: secret-handling\ndescription: Never read .env files or write secrets to .squad/ committed files\ndomain: security, file-operations, team-collaboration\nconfidence: high\nsource: earned (issue #267 — credential leak incident)\n---\n\n## Context\n\nSpawned agents have read access to the entire repository, including `.env` files containing live credentials. If an agent reads secrets and writes them to `.squad/` files (decisions, logs, history), Scribe auto-commits them to git, exposing them in remote history. This skill codifies absolute prohibitions and safe alternatives.\n\n## Patterns\n\n### Prohibited File Reads\n\n**NEVER read these files:**\n- `.env` (production secrets)\n- `.env.local` (local dev secrets)\n- `.env.production` (production environment)\n- `.env.development` (development environment)\n- `.env.staging` (staging environment)\n- `.env.test` (test environment with real credentials)\n- Any file matching `.env.*` UNLESS explicitly allowed (see below)\n\n**Allowed alternatives:**\n- `.env.example` (safe — contains placeholder values, no real secrets)\n- `.env.sample` (safe — documentation template)\n- `.env.template` (safe — schema/structure reference)\n\n**If you need config info:**\n1. **Ask the user directly** — \"What's the database connection string?\"\n2. **Read `.env.example`** — shows structure without exposing secrets\n3. **Read documentation** — check `README.md`, `docs/`, config guides\n\n**NEVER assume you can \"just peek at .env to understand the schema.\"** Use `.env.example` or ask.\n\n### Prohibited Output Patterns\n\n**NEVER write these to `.squad/` files:**\n\n| Pattern Type | Examples | Regex Pattern (for scanning) |\n|--------------|----------|-------------------------------|\n| API Keys | `OPENAI_API_KEY=sk-proj-...`, `GITHUB_TOKEN=ghp_...` | `[A-Z_]+(?:KEY|TOKEN|SECRET)=[^\\s]+` |\n| Passwords | `DB_PASSWORD=super_secret_123`, `password: \"...\"` | `(?:PASSWORD|PASS|PWD)[:=]\\s*[\"']?[^\\s\"']+` |\n| Connection Strings | `postgres://user:pass@host:5432/db`, `Server=...;Password=...` | `(?:postgres|mysql|mongodb)://[^@]+@|(?:Server|Host)=.*(?:Password|Pwd)=` |\n| JWT Tokens | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...` | `eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+` |\n| Private Keys | `-----BEGIN PRIVATE KEY-----`, `-----BEGIN RSA PRIVATE KEY-----` | `-----BEGIN [A-Z ]+PRIVATE KEY-----` |\n| AWS Credentials | `AKIA...`, `aws_secret_access_key=...` | `AKIA[0-9A-Z]{16}|aws_secret_access_key=[^\\s]+` |\n| Email Addresses | `user@example.com` (PII violation per team decision) | `[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}` |\n\n**What to write instead:**\n- Placeholder values: `DATABASE_URL=<set in .env>`\n- Redacted references: `API key configured (see .env.example)`\n- Architecture notes: \"App uses JWT auth — token stored in session\"\n- Schema documentation: \"Requires OPENAI_API_KEY, GITHUB_TOKEN (see .env.example for format)\"\n\n### Scribe Pre-Commit Validation\n\n**Before committing `.squad/` changes, Scribe MUST:**\n\n1. **Scan all staged files** for secret patterns (use regex table above)\n2. **Check for prohibited file names** (don't commit `.env` even if manually staged)\n3. **If secrets detected:**\n - STOP the commit (do NOT proceed)\n - Remove the file from staging: `git reset HEAD <file>`\n - Report to user:\n ```\n 🚨 SECRET DETECTED — commit blocked\n \n File: .squad/decisions/inbox/river-db-config.md\n Pattern: DATABASE_URL=postgres://user:password@localhost:5432/prod\n \n This file contains credentials and MUST NOT be committed.\n Please remove the secret, replace with placeholder, and try again.\n ```\n - Exit with error (never silently skip)\n\n4. **If no secrets detected:**\n - Proceed with commit as normal\n\n**Implementation note for Scribe:**\n- Run validation AFTER staging files, BEFORE calling `git commit`\n- Use PowerShell `Select-String` or `git diff --cached` to scan staged content\n- Fail loud — secret leaks are unacceptable, blocking the commit is correct behavior\n\n### Remediation — If a Secret Was Already Committed\n\n**If you discover a secret in git history:**\n\n1. **STOP immediately** — do not make more commits\n2. **Alert the user:**\n ```\n 🚨 CREDENTIAL LEAK DETECTED\n \n A secret was found in git history:\n Commit: abc1234\n File: .squad/decisions/inbox/agent-config.md\n Pattern: API_KEY=sk-proj-...\n \n This requires immediate remediation:\n 1. Revoke the exposed credential (regenerate API key, rotate password)\n 2. Remove from git history (git filter-repo or BFG)\n 3. Force-push the cleaned history\n \n Do NOT proceed with new work until this is resolved.\n ```\n3. **Do NOT attempt to fix it yourself** — secret removal requires specialized tools\n4. **Wait for user confirmation** before resuming work\n\n## Examples\n\n### ✓ Correct: Reading Config Schema\n\n**Agent needs to know what environment variables are required:**\n\n```\nAgent: \"What environment variables does this app need?\"\n→ Reads `.env.example`:\n OPENAI_API_KEY=sk-...\n DATABASE_URL=postgres://user:pass@localhost:5432/db\n REDIS_URL=redis://localhost:6379\n\n→ Writes to .squad/decisions/inbox/river-env-setup.md:\n \"App requires three environment variables:\n - OPENAI_API_KEY (OpenAI API key, format: sk-...)\n - DATABASE_URL (Postgres connection string)\n - REDIS_URL (Redis connection string)\n See .env.example for full schema.\"\n```\n\n### ✗ Incorrect: Reading Live Credentials\n\n**Agent needs to know database schema:**\n\n```\nAgent: (reads .env)\n DATABASE_URL=postgres://admin:super_secret_pw@prod.example.com:5432/appdb\n\n→ Writes to .squad/decisions/inbox/river-db-schema.md:\n \"Database connection: postgres://admin:super_secret_pw@prod.example.com:5432/appdb\"\n \n🚨 VIOLATION: Live credential written to committed file\n```\n\n**Correct approach:**\n```\nAgent: (reads .env.example OR asks user)\nUser: \"It's a Postgres database, schema is in migrations/\"\n\n→ Writes to .squad/decisions/inbox/river-db-schema.md:\n \"Database: Postgres (connection configured in .env). Schema defined in db/migrations/.\"\n```\n\n### ✓ Correct: Scribe Pre-Commit Validation\n\n**Scribe is about to commit:**\n\n```powershell\n# Stage files\ngit add .squad/\n\n# Scan staged content for secrets\n$stagedContent = git diff --cached\n$secretPatterns = @(\n '[A-Z_]+(?:KEY|TOKEN|SECRET)=[^\\s]+',\n '(?:PASSWORD|PASS|PWD)[:=]\\s*[\"'']?[^\\s\"'']+',\n 'eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+'\n)\n\n$detected = $false\nforeach ($pattern in $secretPatterns) {\n if ($stagedContent -match $pattern) {\n $detected = $true\n Write-Host \"🚨 SECRET DETECTED: $($matches[0])\"\n break\n }\n}\n\nif ($detected) {\n # Remove from staging, report, exit\n git reset HEAD .squad/\n Write-Error \"Commit blocked — secret detected in staged files\"\n exit 1\n}\n\n# Safe to commit\ngit commit -F $msgFile\n```\n\n## Anti-Patterns\n\n- ❌ Reading `.env` \"just to check the schema\" — use `.env.example` instead\n- ❌ Writing \"sanitized\" connection strings that still contain credentials\n- ❌ Assuming \"it's just a dev environment\" makes secrets safe to commit\n- ❌ Committing first, scanning later — validation MUST happen before commit\n- ❌ Silently skipping secret detection — fail loud, never silent\n- ❌ Trusting agents to \"know better\" — enforce at multiple layers (prompt, hook, architecture)\n- ❌ Writing secrets to \"temporary\" files in `.squad/` — Scribe commits ALL `.squad/` changes\n- ❌ Extracting \"just the host\" from a connection string — still leaks infrastructure topology\n",
"---\nname: \"session-recovery\"\ndescription: \"Find and resume interrupted Copilot CLI sessions using session_store queries\"\ndomain: \"workflow-recovery\"\nconfidence: \"high\"\nsource: \"earned\"\ntools:\n - name: \"sql\"\n description: \"Query session_store database for past session history\"\n when: \"Always — session_store is the source of truth for session history\"\n---\n\n## Context\n\nSquad agents run in Copilot CLI sessions that can be interrupted — terminal crashes, network drops, machine restarts, or accidental window closes. When this happens, in-progress work may be left in a partially-completed state: branches with uncommitted changes, issues marked in-progress with no active agent, or checkpoints that were never finalized.\n\nCopilot CLI stores session history in a SQLite database called `session_store` (read-only, accessed via the `sql` tool with `database: \"session_store\"`). This skill teaches agents how to query that store to detect interrupted sessions and resume work.\n\n## Patterns\n\n### 1. Find Recent Sessions\n\nQuery the `sessions` table filtered by time window. Include the last checkpoint to understand where the session stopped:\n\n```sql\nSELECT\n s.id,\n s.summary,\n s.cwd,\n s.branch,\n s.updated_at,\n (SELECT title FROM checkpoints\n WHERE session_id = s.id\n ORDER BY checkpoint_number DESC LIMIT 1) AS last_checkpoint\nFROM sessions s\nWHERE s.updated_at >= datetime('now', '-24 hours')\nORDER BY s.updated_at DESC;\n```\n\n### 2. Filter Out Automated Sessions\n\nAutomated agents (monitors, keep-alive, heartbeat) create high-volume sessions that obscure human-initiated work. Exclude them:\n\n```sql\nSELECT s.id, s.summary, s.cwd, s.updated_at,\n (SELECT title FROM checkpoints\n WHERE session_id = s.id\n ORDER BY checkpoint_number DESC LIMIT 1) AS last_checkpoint\nFROM sessions s\nWHERE s.updated_at >= datetime('now', '-24 hours')\n AND s.id NOT IN (\n SELECT DISTINCT t.session_id FROM turns t\n WHERE t.turn_index = 0\n AND (LOWER(t.user_message) LIKE '%keep-alive%'\n OR LOWER(t.user_message) LIKE '%heartbeat%')\n )\nORDER BY s.updated_at DESC;\n```\n\n### 3. Search by Topic (FTS5)\n\nUse the `search_index` FTS5 table for keyword search. Expand queries with synonyms since this is keyword-based, not semantic:\n\n```sql\nSELECT DISTINCT s.id, s.summary, s.cwd, s.updated_at\nFROM search_index si\nJOIN sessions s ON si.session_id = s.id\nWHERE search_index MATCH 'auth OR login OR token OR JWT'\n AND s.updated_at >= datetime('now', '-48 hours')\nORDER BY s.updated_at DESC\nLIMIT 10;\n```\n\n### 4. Search by Working Directory\n\n```sql\nSELECT s.id, s.summary, s.updated_at,\n (SELECT title FROM checkpoints\n WHERE session_id = s.id\n ORDER BY checkpoint_number DESC LIMIT 1) AS last_checkpoint\nFROM sessions s\nWHERE s.cwd LIKE '%my-project%'\n AND s.updated_at >= datetime('now', '-48 hours')\nORDER BY s.updated_at DESC;\n```\n\n### 5. Get Full Session Context Before Resuming\n\nBefore resuming, inspect what the session was doing:\n\n```sql\n-- Conversation turns\nSELECT turn_index, substr(user_message, 1, 200) AS ask, timestamp\nFROM turns WHERE session_id = 'SESSION_ID' ORDER BY turn_index;\n\n-- Checkpoint progress\nSELECT checkpoint_number, title, overview\nFROM checkpoints WHERE session_id = 'SESSION_ID' ORDER BY checkpoint_number;\n\n-- Files touched\nSELECT file_path, tool_name\nFROM session_files WHERE session_id = 'SESSION_ID';\n\n-- Linked PRs/issues/commits\nSELECT ref_type, ref_value\nFROM session_refs WHERE session_id = 'SESSION_ID';\n```\n\n### 6. Detect Orphaned Issue Work\n\nFind sessions that were working on issues but may not have completed:\n\n```sql\nSELECT DISTINCT s.id, s.branch, s.summary, s.updated_at,\n sr.ref_type, sr.ref_value\nFROM sessions s\nJOIN session_refs sr ON s.id = sr.session_id\nWHERE sr.ref_type = 'issue'\n AND s.updated_at >= datetime('now', '-48 hours')\nORDER BY s.updated_at DESC;\n```\n\nCross-reference with `gh issue list --label \"status:in-progress\"` to find issues that are marked in-progress but have no active session.\n\n### 7. Resume a Session\n\nOnce you have the session ID:\n\n```bash\n# Resume directly\ncopilot --resume SESSION_ID\n```\n\n## Examples\n\n**Recovering from a crash during PR creation:**\n1. Query recent sessions filtered by branch name\n2. Find the session that was working on the PR\n3. Check its last checkpoint — was the code committed? Was the PR created?\n4. Resume or manually complete the remaining steps\n\n**Finding yesterday's work on a feature:**\n1. Use FTS5 search with feature keywords\n2. Filter to the relevant working directory\n3. Review checkpoint progress to see how far the session got\n4. Resume if work remains, or start fresh with the context\n\n## Anti-Patterns\n\n- ❌ Searching by partial session IDs — always use full UUIDs\n- ❌ Resuming sessions that completed successfully — they have no pending work\n- ❌ Using `MATCH` with special characters without escaping — wrap paths in double quotes\n- ❌ Skipping the automated-session filter — high-volume automated sessions will flood results\n- ❌ Assuming FTS5 is semantic search — it's keyword-based; always expand queries with synonyms\n- ❌ Ignoring checkpoint data — checkpoints show exactly where the session stopped\n",
"---\nname: \"squad-conventions\"\ndescription: \"Core conventions and patterns used in the Squad codebase\"\ndomain: \"project-conventions\"\nconfidence: \"high\"\nsource: \"manual\"\n---\n\n## Context\nThese 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.\n\n## Patterns\n\n### Zero Dependencies\nSquad 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.\n\n### Node.js Built-in Test Runner\nTests 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/`.\n\n### Error Handling — `fatal()` Pattern\nAll 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.\n\n### ANSI Color Constants\nColors are defined as constants at the top of `index.js`: `GREEN`, `RED`, `DIM`, `BOLD`, `RESET`. Use these constants — do not inline ANSI escape codes.\n\n### File Structure\n- `.squad/` — Team state (user-owned, never overwritten by upgrades)\n- `.squad/templates/` — Template files copied from `templates/` (Squad-owned, overwritten on upgrade)\n- `.github/agents/squad.agent.md` — Coordinator prompt (Squad-owned, overwritten on upgrade)\n- `templates/` — Source templates shipped with the npm package\n- `.squad/skills/` — Team skills in SKILL.md format (user-owned)\n- `.squad/decisions/inbox/` — Drop-box for parallel decision writes\n\n### Windows Compatibility\nAlways 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.\n\n### Init Idempotency\nThe 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.\n\n### Copy Pattern\n`copyRecursive(src, target)` handles both files and directories. It creates parent directories with `{ recursive: true }` and uses `fs.copyFileSync` for files.\n\n## Examples\n\n```javascript\n// Error handling\nfunction fatal(msg) {\n console.error(`${RED}✗${RESET} ${msg}`);\n process.exit(1);\n}\n\n// File path construction (Windows-safe)\nconst agentDest = path.join(dest, '.github', 'agents', 'squad.agent.md');\n\n// Skip-if-exists pattern\nif (!fs.existsSync(ceremoniesDest)) {\n fs.copyFileSync(ceremoniesSrc, ceremoniesDest);\n console.log(`${GREEN}✓${RESET} .squad/ceremonies.md`);\n} else {\n console.log(`${DIM}ceremonies.md already exists — skipping${RESET}`);\n}\n```\n\n## Anti-Patterns\n- **Adding npm dependencies** — Squad is zero-dep. Use Node.js built-ins only.\n- **Hardcoded path separators** — Never use `/` or `\\` directly. Always `path.join()`.\n- **Overwriting user state on init** — Init skips existing files. Only upgrade overwrites Squad-owned files.\n- **Raw stack traces** — All errors go through `fatal()`. Users see clean messages, not stack traces.\n- **Inline ANSI codes** — Use the color constants (`GREEN`, `RED`, `DIM`, `BOLD`, `RESET`).\n",
"---\nname: \"test-discipline\"\ndescription: \"Update tests when changing APIs — no exceptions\"\ndomain: \"quality\"\nconfidence: \"high\"\nsource: \"earned (Fenster/Hockney incident, test assertion sync violations)\"\n---\n\n## Context\n\nWhen APIs or public interfaces change, tests must be updated in the same commit. When test assertions reference file counts or expected arrays, they must be kept in sync with disk reality. Stale tests block CI for other contributors.\n\n## Patterns\n\n- **API changes → test updates (same commit):** If you change a function signature, public interface, or exported API, update the corresponding tests before committing\n- **Test assertions → disk reality:** When test files contain expected counts (e.g., `EXPECTED_FEATURES`, `EXPECTED_SCENARIOS`), they must match the actual files on disk\n- **Add files → update assertions:** When adding docs pages, features, or any counted resource, update the test assertion array in the same commit\n- **CI failures → check assertions first:** Before debugging complex failures, verify test assertion arrays match filesystem state\n\n## Examples\n\n✓ **Correct:**\n- Changed auth API signature → updated auth.test.ts in same commit\n- Added `distributed-mesh.md` to features/ → added `'distributed-mesh'` to EXPECTED_FEATURES array\n- Deleted two scenario files → removed entries from EXPECTED_SCENARIOS\n\n✗ **Incorrect:**\n- Changed spawn parameters → committed without updating casting.test.ts (CI breaks for next person)\n- Added `built-in-roles.md` → left EXPECTED_FEATURES at old count (PR blocked)\n- Test says \"expected 7 files\" but disk has 25 (assertion staleness)\n\n## Anti-Patterns\n\n- Committing API changes without test updates (\"I'll fix tests later\")\n- Treating test assertion arrays as static (they evolve with content)\n- Assuming CI passing means coverage is correct (stale assertions can pass while being wrong)\n- Leaving gaps for other agents to discover\n",
"---\nname: \"windows-compatibility\"\ndescription: \"Cross-platform path handling and command patterns\"\ndomain: \"platform\"\nconfidence: \"high\"\nsource: \"earned (multiple Windows-specific bugs: colons in filenames, git -C failures, path separators)\"\n---\n\n## Context\n\nSquad runs on Windows, macOS, and Linux. Several bugs have been traced to platform-specific assumptions: ISO timestamps with colons (illegal on Windows), `git -C` with Windows paths (unreliable), forward-slash paths in Node.js on Windows.\n\n## Patterns\n\n### Filenames & Timestamps\n- **Never use colons in filenames:** ISO 8601 format `2026-03-15T05:30:00Z` is illegal on Windows\n- **Use `safeTimestamp()` utility:** Replaces colons with hyphens → `2026-03-15T05-30-00Z`\n- **Centralize formatting:** Don't inline `.toISOString().replace(/:/g, '-')` — use the utility\n\n### Git Commands\n- **Never use `git -C {path}`:** Unreliable with Windows paths (backslashes, spaces, drive letters)\n- **Always `cd` first:** Change directory, then run git commands\n- **Check for changes before commit:** `git diff --cached --quiet` (exit 0 = no changes)\n\n### Commit Messages\n- **Never embed newlines in `-m` flag:** Backtick-n (`\\n`) fails silently in PowerShell\n- **Use temp file + `-F` flag:** Write message to file, commit with `git commit -F $msgFile`\n\n### Paths\n- **Never assume CWD is repo root:** Always use `TEAM ROOT` from spawn prompt or run `git rev-parse --show-toplevel`\n- **Use path.join() or path.resolve():** Don't manually concatenate with `/` or `\\`\n\n### Path Comparison (Case Sensitivity)\n- **Never use case-sensitive `startsWith` or `===` for path comparison on Windows or macOS:** These filesystems are case-insensitive — `C:\\Users\\` and `c:\\users\\` refer to the same location\n- **Use platform-aware comparison:** Check `process.platform === 'win32' || process.platform === 'darwin'` and lowercase both sides before comparing\n- **Pattern:**\n ```typescript\n const CASE_INSENSITIVE = process.platform === 'win32' || process.platform === 'darwin';\n \n function pathStartsWith(fullPath: string, prefix: string): boolean {\n if (CASE_INSENSITIVE) {\n return fullPath.toLowerCase().startsWith(prefix.toLowerCase());\n }\n return fullPath.startsWith(prefix);\n }\n ```\n- **Where it matters:** Security checks (path traversal prevention), rootDir confinement, any path-contains-path validation\n- **Linux is case-sensitive:** Do NOT lowercase on Linux — `/Home/` and `/home/` are different directories\n\n## Examples\n\n✓ **Correct:**\n```javascript\n// Timestamp utility\nconst safeTimestamp = () => new Date().toISOString().replace(/:/g, '-').split('.')[0] + 'Z';\n\n// Git workflow (PowerShell)\ncd $teamRoot\ngit add .squad/\nif ($LASTEXITCODE -eq 0) {\n $msg = @\"\ndocs(ai-team): session log\n\nChanges:\n- Added decisions\n\"@\n $msgFile = [System.IO.Path]::GetTempFileName()\n Set-Content -Path $msgFile -Value $msg -Encoding utf8\n git commit -F $msgFile\n Remove-Item $msgFile\n}\n```\n\n✗ **Incorrect:**\n```javascript\n// Colon in filename\nconst logPath = `.squad/log/${new Date().toISOString()}.md`; // ILLEGAL on Windows\n\n// git -C with Windows path\nexec('git -C C:\\\\src\\\\squad add .squad/'); // UNRELIABLE\n\n// Inline newlines in commit message\nexec('git commit -m \"First line\\nSecond line\"'); // FAILS silently in PowerShell\n```\n\n## Anti-Patterns\n\n- Testing only on one platform (bugs ship to other platforms)\n- Assuming Unix-style paths work everywhere\n- Using `git -C` because it \"looks cleaner\" (it doesn't work)\n- Skipping `git diff --cached --quiet` check (creates empty commits)\n- **Wrong — case-sensitive path check on Windows and macOS:**\n ```typescript\n if (!resolved.startsWith(rootDir + path.sep)) {\n throw new Error('Path traversal blocked');\n }\n // Fails: 'c:\\\\Users\\\\temp\\\\file'.startsWith('C:\\\\Users\\\\temp\\\\') → false\n ```\n"
]
}