From 50380e826c3362f0de2d3285b1f05e03d78c3d10 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 20:56:36 -0700 Subject: [PATCH 1/8] feat(.squad): PAO external communications - Phase 1 infrastructure Implements the Phase 1 foundation for RFC #426: PAO External Communications with human review gate. New skills: - humanizer: Tone enforcement patterns for community responses - external-comms: Full scan-draft-review-post workflow with confidence flags Infrastructure: - .squad/comms/ directory with audit logging, SQLite locking schema, tone validation patterns, and review state templates - Tone validation test spec (7 test categories, 5 gold standard responses) - CI gate definition (mandatory and warning checks) Charter and routing updates: - PAO (McManus) charter: external comms ownership, 3 hard rules - Routing: community response work type added Closes #426 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/agents/keaton/history.md | 3 + .squad/agents/mcmanus/charter.md | 8 +- .squad/comms/.gitignore | 5 + .squad/comms/README.md | 25 +++ .squad/comms/audit/.gitkeep | 0 .squad/comms/templates/audit-entry.md | 25 +++ .../comms/templates/review-state-schema.sql | 69 ++++++++ .squad/comms/templates/tone-validation.json | 75 +++++++++ .squad/comms/tests/ci-gate.md | 50 ++++++ .squad/comms/tests/tone-validation-spec.md | 137 ++++++++++++++++ .squad/routing.md | 1 + .squad/skills/external-comms/SKILL.md | 155 ++++++++++++++++++ .squad/skills/humanizer/SKILL.md | 100 +++++++++++ 13 files changed, 652 insertions(+), 1 deletion(-) create mode 100644 .squad/comms/.gitignore create mode 100644 .squad/comms/README.md create mode 100644 .squad/comms/audit/.gitkeep create mode 100644 .squad/comms/templates/audit-entry.md create mode 100644 .squad/comms/templates/review-state-schema.sql create mode 100644 .squad/comms/templates/tone-validation.json create mode 100644 .squad/comms/tests/ci-gate.md create mode 100644 .squad/comms/tests/tone-validation-spec.md create mode 100644 .squad/skills/external-comms/SKILL.md create mode 100644 .squad/skills/humanizer/SKILL.md diff --git a/.squad/agents/keaton/history.md b/.squad/agents/keaton/history.md index 423026c27..20e4400a0 100644 --- a/.squad/agents/keaton/history.md +++ b/.squad/agents/keaton/history.md @@ -49,6 +49,9 @@ ## Learnings +- PAO external comms architecture decision: Phase 1 uses a scanβ†’draftβ†’reviewβ†’post pipeline with humanizer tone enforcement, SQLite review state, append-only audit logs, and a `pao halt` freeze switch. +- Phase 1 scope and constraints: manual-trigger only, never autonomous, every draft requires explicit human approval before posting, and scheduled scans stay blocked pending Brady approval. + ## πŸ“Œ v0.8.22 Release Disaster β€” 2026-03-07T20:50:00Z **THE WORST RELEASE IN SQUAD HISTORY.** Brady was rightfully upset. This was a catastrophe. Full retrospective written with brutal honesty. diff --git a/.squad/agents/mcmanus/charter.md b/.squad/agents/mcmanus/charter.md index 56406a947..7c417551c 100644 --- a/.squad/agents/mcmanus/charter.md +++ b/.squad/agents/mcmanus/charter.md @@ -16,6 +16,9 @@ - Demos and examples - Tone review and messaging - i18n patterns +- External community responses (draft-only, human review gate) +- Tone enforcement via humanizer skill +- Community signal aggregation (unanswered issues β†’ product signals) ## How I Work @@ -23,10 +26,13 @@ - Celebration blog structure: wave:null, parallel narrative - docs/proposals/ pattern: proposals before execution - Every public-facing statement must be substantiated +- **EXTERNAL COMMS (hard rule):** NEVER post community responses autonomously. All responses are drafted, presented in a review table with confidence flags, and require explicit human approval before posting. +- **HUMANIZER (hard rule):** All external-facing content must pass tone validation β€” warm, helpful, human-sounding. No corporate speak, no marketing hype, no empty acknowledgments. +- **AUDIT TRAIL (hard rule):** Every draft-review-post action is logged to `.squad/comms/audit/`. The audit log is append-only. ## Boundaries -**I handle:** Documentation, demos, messaging, tone review, developer experience, i18n. +**I handle:** README, API docs, demos, examples, tone review, community messaging, contributor recognition, external community response drafting (with human review gate). **I don't handle:** Runtime implementation, architecture decisions, security, distribution mechanics. diff --git a/.squad/comms/.gitignore b/.squad/comms/.gitignore new file mode 100644 index 000000000..71d241b62 --- /dev/null +++ b/.squad/comms/.gitignore @@ -0,0 +1,5 @@ +# Runtime state (not committed) +review-state.db +review-state.db-journal +review-state.db-wal +review-state.db-shm diff --git a/.squad/comms/README.md b/.squad/comms/README.md new file mode 100644 index 000000000..a739bd8c3 --- /dev/null +++ b/.squad/comms/README.md @@ -0,0 +1,25 @@ +# PAO External Communications + +> Phase 1: Draft-only mode with human review gate. + +## Directory Structure + +- `audit/` β€” Audit trail for every draft-review-post action +- `review-state.db` β€” SQLite-based atomic locking for concurrent review sessions (created at runtime) +- `templates/` β€” Response templates for common scenarios + +## Workflow + +1. PAO scans issues and discussions for unanswered items +2. PAO drafts responses using humanizer skill +3. PAO presents review table with confidence flags +4. Human reviews, approves/edits/skips each draft +5. Human posts approved responses +6. Every action logged to `audit/` + +## Safety + +- `pao halt` β€” freezes all pending drafts +- All responses require explicit human approval +- Audit trail is append-only +- SQLite locking prevents concurrent review race conditions diff --git a/.squad/comms/audit/.gitkeep b/.squad/comms/audit/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md new file mode 100644 index 000000000..1bc655671 --- /dev/null +++ b/.squad/comms/templates/audit-entry.md @@ -0,0 +1,25 @@ +--- +timestamp: "{ISO-8601}" +action: "scan|draft|approve|edit|skip|post|halt|resume|delete" +item_type: "issue|discussion|pr" +item_number: {number} +item_url: "{url}" +draft_id: "{N from review table}" +reviewer: "{github-username}" +outcome: "approved|edited|skipped|posted|halted|deleted" +--- + +## Context +- Thread depth: {comment count} +- Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty} +- Confidence: {🟒|🟑|πŸ”΄} +- Long thread flag: {true|false} + +## Draft Content +{full draft text} + +## Reviewer Notes +{any edits or comments from reviewer, or "β€”" if none} + +## Post Result +{link to posted comment if posted, or "not posted" if skipped/halted} diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql new file mode 100644 index 000000000..c852a2acd --- /dev/null +++ b/.squad/comms/templates/review-state-schema.sql @@ -0,0 +1,69 @@ +-- PAO External Communications: Review State Database +-- Created at runtime in .squad/comms/review-state.db +-- Zero new dependencies (Copilot CLI already uses SQLite) + +CREATE TABLE IF NOT EXISTS review_locks ( + session_id TEXT PRIMARY KEY, + reviewer TEXT NOT NULL, + hostname TEXT NOT NULL, + pid INTEGER NOT NULL, + acquired_at TEXT NOT NULL DEFAULT (datetime('now')), + expires_at TEXT NOT NULL DEFAULT (datetime('now', '+1 hour')), + status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'released', 'expired')) +); + +-- Atomic lock acquisition using INSERT ... ON CONFLICT +-- If a lock exists and is expired, it gets replaced +-- If a lock exists and is active, the INSERT fails (lock held) +CREATE TRIGGER IF NOT EXISTS cleanup_expired_locks +BEFORE INSERT ON review_locks +BEGIN + DELETE FROM review_locks + WHERE expires_at < datetime('now') + AND status = 'active'; +END; + +-- Draft tracking table +CREATE TABLE IF NOT EXISTS draft_queue ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + session_id TEXT NOT NULL, + item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion', 'pr')), + item_number INTEGER NOT NULL, + item_url TEXT, + response_type TEXT NOT NULL, + confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')), + draft_content TEXT NOT NULL, + thread_depth INTEGER DEFAULT 0, + long_thread_flag INTEGER DEFAULT 0, + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'edited', 'skipped', 'posted', 'halted', 'deleted')), + reviewer TEXT, + reviewed_at TEXT, + posted_url TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')), + FOREIGN KEY (session_id) REFERENCES review_locks(session_id) +); + +-- Halt state (safe word mechanism) +CREATE TABLE IF NOT EXISTS halt_state ( + id INTEGER PRIMARY KEY CHECK (id = 1), + halted INTEGER NOT NULL DEFAULT 0, + halted_by TEXT, + halted_at TEXT, + reason TEXT +); + +-- Initialize halt state (not halted by default) +INSERT OR IGNORE INTO halt_state (id, halted) VALUES (1, 0); + +-- Audit log (append-only, mirrors markdown audit files) +CREATE TABLE IF NOT EXISTS audit_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL DEFAULT (datetime('now')), + action TEXT NOT NULL, + item_type TEXT, + item_number INTEGER, + draft_id INTEGER, + reviewer TEXT, + outcome TEXT, + details TEXT +); diff --git a/.squad/comms/templates/tone-validation.json b/.squad/comms/templates/tone-validation.json new file mode 100644 index 000000000..525afa3fd --- /dev/null +++ b/.squad/comms/templates/tone-validation.json @@ -0,0 +1,75 @@ +{ + "version": 1, + "description": "Tone validation patterns for PAO external communications", + "reject_patterns": [ + { + "id": "corporate-speak", + "pattern": "(?i)(we appreciate your patience|please be advised|per our discussion|as per|kindly note|please do not hesitate)", + "message": "Corporate speak detected. Use conversational tone instead." + }, + { + "id": "passive-voice-formal", + "pattern": "(?i)(it has been determined|it was decided|has been escalated|is being investigated|has been noted)", + "message": "Formal passive voice detected. Use active voice: 'We determined...' or 'We're looking into...'" + }, + { + "id": "marketing-hype", + "pattern": "(?i)(best in class|cutting.edge|revolutionary|game.changing|industry.leading|next.generation|amazing feature)", + "message": "Marketing hype detected. Be specific about what the feature does, not how great it is." + }, + { + "id": "empty-acknowledgment", + "pattern": "(?i)^(thanks for your feedback\\.?|thank you for reaching out\\.?)$", + "message": "Empty acknowledgment without substance. Add specific context or next steps." + }, + { + "id": "robot-signature", + "pattern": "(?i)(best regards|sincerely|kind regards|respectfully|warm regards)\\s*[,.]?\\s*(pao|the squad team|squad bot)", + "message": "Robot signature detected. Responses should end naturally, not with formal sign-offs." + }, + { + "id": "over-promising", + "pattern": "(?i)(we will ship|we'll release|coming soon|in the next release|definitely fix|guaranteed)", + "message": "Over-promising detected. Only commit to what the team has explicitly agreed to." + }, + { + "id": "dismissive", + "pattern": "(?i)(works as designed|not a bug|won't fix|that's expected|user error)", + "message": "Dismissive language detected. Acknowledge the experience before explaining the design." + }, + { + "id": "profanity", + "pattern": "(?i)(damn|hell|crap|crap|shit|fuck|ass|bastard|bitch)", + "message": "Profanity detected. Never include profanity, even when quoting." + } + ], + "require_patterns": [ + { + "id": "acknowledgment", + "pattern": "(?i)(thanks|thank you|good catch|great question|interesting|appreciate|welcome)", + "message": "Response should include acknowledgment of the author's contribution.", + "applies_to": ["welcome", "troubleshooting", "acknowledgment"] + }, + { + "id": "action-oriented", + "pattern": "(?i)(let us know|feel free|happy to help|we'll update|reach out|we'll dig|keep us posted)", + "message": "Response should end with an action-oriented close.", + "applies_to": ["troubleshooting", "feature-guidance", "technical-uncertainty"] + } + ], + "confidence_thresholds": { + "high": { + "description": "Answered before, clear docs, community consensus", + "min_similarity": 0.8 + }, + "medium": { + "description": "Technically sound but minor uncertainty or tone-dependent", + "min_similarity": 0.6 + }, + "low": { + "description": "Technical uncertainty, policy decision, reputational risk", + "min_similarity": 0.0, + "requires_review": true + } + } +} diff --git a/.squad/comms/tests/ci-gate.md b/.squad/comms/tests/ci-gate.md new file mode 100644 index 000000000..a4e0cf0a7 --- /dev/null +++ b/.squad/comms/tests/ci-gate.md @@ -0,0 +1,50 @@ +# CI Tone Lint Gate + +> Automated quality checks for PAO community response drafts. + +## When This Runs + +- Before any draft enters the review table +- As part of PR review when modifying humanizer or external-comms skills +- Weekly tone analytics (manual trigger via `pao analytics`) + +## Checks + +### Mandatory (blocks draft) + +1. **Anti-pattern scan** β€” Run all `reject_patterns` from `tone-validation.json` against draft +2. **Profanity filter** β€” Zero tolerance, even in quotes +3. **Minimum substance** β€” Draft must be >50 characters (no empty acknowledgments) +4. **Thread read verification** β€” Confirm all comments in thread were read before drafting + +### Warning (flags but doesn't block) + +1. **Positive pattern check** β€” Warn if response type should contain patterns from `require_patterns` +2. **Length check** β€” Warn if draft >500 words (may be too verbose for a GitHub comment) +3. **Emoji count** β€” Warn if >2 emoji in draft +4. **Similarity check** β€” Warn if tone similarity to gold standard <80% + +### Informational + +1. **Response type classification** β€” Log which template was used +2. **Confidence level** β€” Log confidence flag and rationale +3. **Thread depth** β€” Log comment count for analytics + +## Output Format + +``` +βœ… PASS: Anti-pattern scan (0 violations) +βœ… PASS: Profanity filter (clean) +βœ… PASS: Minimum substance (127 chars) +⚠️ WARN: Positive pattern β€” missing action-oriented close +⚠️ WARN: Similarity to GS-2: 72% (threshold: 80%) +ℹ️ INFO: Response type: troubleshooting | Confidence: 🟑 | Thread: 4 comments +``` + +## Failure Mode + +If ANY mandatory check fails: +1. Draft is NOT added to review table +2. Error message shown to PAO with specific violation +3. PAO must redraft before presenting to reviewer +4. Failure logged to audit trail (action: "lint_failure") diff --git a/.squad/comms/tests/tone-validation-spec.md b/.squad/comms/tests/tone-validation-spec.md new file mode 100644 index 000000000..277bf4092 --- /dev/null +++ b/.squad/comms/tests/tone-validation-spec.md @@ -0,0 +1,137 @@ +# Tone Validation Test Specification + +> Quality gates for PAO's external communications. All tests must pass before a draft enters the review table. + +## Test Categories + +### T1: Reject Anti-Patterns + +Drafts containing these patterns MUST be rejected: + +| Test ID | Pattern | Example (should FAIL) | +|---------|---------|----------------------| +| T1.1 | Corporate speak | "We appreciate your patience as we investigate this matter" | +| T1.2 | Formal passive voice | "It has been determined that this is a known issue" | +| T1.3 | Marketing hype | "Squad is the best-in-class solution for this" | +| T1.4 | Empty acknowledgment | "Thanks for your feedback." (with nothing else) | +| T1.5 | Robot signature | "Best regards, PAO" | +| T1.6 | Over-promising | "We'll definitely ship this in the next release" | +| T1.7 | Dismissive language | "Works as designed" (without empathy) | +| T1.8 | Profanity | Any profanity, even quoted from the original issue | + +### T2: Require Positive Patterns + +Drafts of specific types MUST contain these patterns: + +| Test ID | Response Type | Required Pattern | Example (should PASS) | +|---------|---------------|-----------------|----------------------| +| T2.1 | Welcome | Author acknowledgment | "Hey @user! Welcome to Squad πŸ‘‹" | +| T2.2 | Troubleshooting | Action-oriented close | "Let us know if that helps!" | +| T2.3 | Feature guidance | Context on current state | "Currently, Squad handles this by..." | +| T2.4 | Technical uncertainty | Honesty about unknowns | "We're not 100% sure yet..." | + +### T3: Confidence Flag Accuracy + +| Test ID | Scenario | Expected Confidence | +|---------|----------|-------------------| +| T3.1 | Issue matches existing FAQ | 🟒 High | +| T3.2 | Technical question with partial docs | 🟑 Medium | +| T3.3 | Architecture question requiring Flight | πŸ”΄ Needs review | +| T3.4 | Question about unreleased feature | πŸ”΄ Needs review | +| T3.5 | Simple "how to install" question | 🟒 High | + +### T4: Thread Safety + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T4.1 | Thread with >10 comments | ⚠️ Long thread flag set | +| T4.2 | Thread with deleted comments | Validation warning | +| T4.3 | Thread where squad member already responded | Skip (no draft) | +| T4.4 | Thread in different language | Flag for review | + +### T5: Review Gate Enforcement + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T5.1 | Draft without human review | BLOCKED β€” cannot post | +| T5.2 | `pao approve` command without draft ID | Error message | +| T5.3 | Concurrent review sessions | SQLite lock prevents race | +| T5.4 | Stale lock (>1 hour) | Auto-cleanup, new session allowed | +| T5.5 | `pao halt` issued | All pending drafts frozen | +| T5.6 | `pao resume` after halt | Drafts unfrozen | + +### T6: Audit Trail Completeness + +| Test ID | Action | Expected Audit Entry | +|---------|--------|---------------------| +| T6.1 | Scan completed | scan action with item count | +| T6.2 | Draft created | draft action with content | +| T6.3 | Draft approved | approve action with reviewer | +| T6.4 | Draft skipped | skip action with reviewer | +| T6.5 | Response posted | post action with URL | +| T6.6 | `pao halt` issued | halt action with issuer | +| T6.7 | Draft deleted (rollback) | delete action with reason | + +### T7: Baseline Comparison (Weekly) + +| Test ID | Metric | Threshold | Frequency | +|---------|--------|-----------|-----------| +| T7.1 | Tone similarity to gold standard | >80% | Per draft | +| T7.2 | Response type distribution | No single type >60% | Weekly | +| T7.3 | Confidence flag distribution | πŸ”΄ items <20% | Weekly | +| T7.4 | Average thread read depth | >95% of comments read | Per draft | + +## Gold Standard Responses + +The following 5 responses serve as the tone baseline. New drafts should align with this tone: + +### GS-1: Welcome (High confidence) +> Hey @newuser! Welcome to Squad πŸ‘‹ Thanks for opening this β€” great first issue! +> +> To answer your question: Squad uses `.squad/team.md` to define your team roster. You can add members by editing that file directly or running `squad init`. +> +> Let us know if you hit any snags β€” happy to help! + +### GS-2: Troubleshooting (High confidence) +> Thanks for the detailed report, @reporter! +> +> This looks like it might be related to the casting registry not finding the universe file. Here's what we'd suggest: +> 1. Check that `.squad/casting/registry.json` exists and is valid JSON +> 2. Run `squad build` to regenerate from source +> 3. If that doesn't work, try deleting `.squad/casting/` and re-running `squad init` +> +> Let us know if that helps, or if you're seeing something different. + +### GS-3: Feature Guidance (Medium confidence) +> Great question! Right now, Squad handles cross-repo orchestration through the hub-and-spoke model β€” you'd have a central `.squad/` in one repo and reference it from others. +> +> We know this isn't ideal for every setup. There's been some discussion about making this more seamless (see #316 for the RFC). +> +> For now, the workaround is to use `squad export` to share config across repos. Hope that helps! + +### GS-4: Acknowledgment (High confidence) +> Good catch, @finder. We've confirmed this is a real issue with the session pool cleanup. +> +> It looks like sessions aren't being released when the adapter disconnects unexpectedly. We're tracking it and will update this thread when we have a fix. +> +> Thanks for flagging it β€” this one would have been hard to find without your repro steps! + +### GS-5: Technical Uncertainty (Low confidence) +> Interesting find, @explorer. We're not 100% sure what's causing this yet. +> +> Here's what we've ruled out: +> - It's not a casting issue (registry looks fine) +> - It's not a config issue (your squad.config.ts parses correctly) +> +> Could you share the output of `squad build --verbose`? That would help us narrow it down. We'll dig deeper and update this thread. + +## Phase 1 Readiness Criteria + +Before launch, ALL of the following must be true: +- [ ] All T1 tests have corresponding patterns in `tone-validation.json` +- [ ] All T2 tests verified against humanizer skill templates +- [ ] Gold standard responses reviewed and approved by Brady or Dina +- [ ] Review gate SQLite schema tested with concurrent access +- [ ] Audit trail format validated against template +- [ ] `pao halt` / `pao resume` flow tested end-to-end +- [ ] At least one full scanβ†’draftβ†’reviewβ†’post cycle completed successfully diff --git a/.squad/routing.md b/.squad/routing.md index 7c1108849..95b6d5586 100644 --- a/.squad/routing.md +++ b/.squad/routing.md @@ -11,6 +11,7 @@ | Runtime performance | Fortier ⚑ | Streaming, event loop health, session management, async iterators, memory profiling | | Tests & quality | Hockney πŸ§ͺ | Test coverage, Vitest, edge cases, CI/CD, quality gates | | Docs & messaging | McManus πŸ“£ | README, API docs, getting-started, demos, tone review | +| Community response | McManus πŸ“£ | Scan unanswered issues/discussions, draft responses, present review table | | Architecture & review | Keaton πŸ—οΈ | Product direction, architectural decisions, code review, scope/trade-offs | | Distribution | Rabin πŸ“¦ | npm packaging, esbuild config, global install, marketplace prep | | Release management | Trejo 🚒 | Semantic versioning, GitHub Releases, changelogs, devβ†’main merges, release gating | diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md new file mode 100644 index 000000000..2eddaf441 --- /dev/null +++ b/.squad/skills/external-comms/SKILL.md @@ -0,0 +1,155 @@ +--- +name: "external-comms" +description: "PAO workflow for scanning, drafting, and presenting community responses with human review gate" +domain: "community, communication, workflow" +confidence: "low" +source: "manual (RFC #426 β€” PAO External Communications)" +tools: + - name: "github-mcp-server-list_issues" + description: "List open issues for scan candidates and lightweight triage" + when: "Use for recent open issue scans before thread-level review" + - name: "github-mcp-server-issue_read" + description: "Read the full issue, comments, and labels before drafting" + when: "Use after selecting a candidate so PAO has complete thread context" + - name: "github-mcp-server-search_issues" + description: "Search for candidate issues or prior squad responses" + when: "Use when filtering by keywords, labels, or duplicate response checks" + - name: "gh CLI" + description: "Fallback for GitHub issue comments and discussions workflows" + when: "Use gh issue list/comment and gh api or gh api graphql when MCP coverage is incomplete" +--- + +## Context + +Phase 1 is **draft-only mode**. + +- PAO scans issues and discussions, drafts responses with the humanizer skill, and presents a review table for human approval. +- **Human review gate is mandatory** β€” PAO never posts autonomously. +- Every action is logged to `.squad/comms/audit/`. +- This workflow is triggered manually ("PAO, check community") or when Ralph detects the `squad:needs-response` label. + +## Patterns + +### 1. Scan + +Find unanswered community items with GitHub MCP tools first, or `gh issue list` / `gh api` as fallback for issues and discussions. + +- Include **open** issues and discussions only. +- Filter for items with **no squad team response**. +- Limit to items created in the last 7 days. +- Exclude items labeled `squad:internal` or `wontfix`. +- Include discussions **and** issues in the same sweep. + +### 2. Classify + +Determine the response type before drafting. + +- Welcome (new contributor) +- Troubleshooting (bug/help) +- Feature guidance (feature request/how-to) +- Redirect (wrong repo/scope) +- Acknowledgment (confirmed, no fix) +- Closing (resolved) +- Technical uncertainty (unknown cause) + +### 3. Draft + +Use the humanizer skill for every draft. + +- Read the **full thread**, including all comments, before writing. +- Classify the response type. +- Draft with the humanizer patterns and the matching template. +- Validate the draft against the humanizer anti-patterns. +- Flag long threads (`>10` comments) with `⚠️`. + +### 4. Present + +Show drafts for review in this exact format: + +```text +πŸ“ PAO β€” Community Response Drafts +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +| # | Item | Author | Type | Confidence | Preview | +|---|------|--------|------|------------|---------| +| 1 | Issue #N | @user | Type | 🟒/🟑/πŸ”΄ | "First words..." | + +Confidence: 🟒 High | 🟑 Medium | πŸ”΄ Needs review + +Full drafts below β–Ό +``` + +### 5. Human Action + +Wait for explicit human direction before anything is posted. + +- `pao approve 1 3` β€” approve drafts 1 and 3 +- `pao edit 2` β€” edit draft 2 +- `pao skip` β€” skip all +- `pao halt` β€” freeze all pending (safe word) + +### 6. Post + +After approval: + +- Human posts via `gh issue comment` or `gh api`. +- PAO helps by preparing the CLI command. +- Write the audit entry after the posting action. + +### 7. Audit + +Log every action. + +- Location: `.squad/comms/audit/{timestamp}.md` +- Required fields: action, item, draft content, reviewer, outcome, timestamp + +## Examples + +### Example scan command + +```bash +gh issue list --state open --json number,title,author,labels,comments --limit 20 +``` + +### Example review table + +```text +πŸ“ PAO β€” Community Response Drafts +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +| # | Item | Author | Type | Confidence | Preview | +|---|------|--------|------|------------|---------| +| 1 | Issue #426 | @newdev | Welcome | 🟒 | "Hey @newdev! Welcome to Squad..." | +| 2 | Discussion #18 | @builder | Feature guidance | 🟑 | "Great question! Today the CLI..." | +| 3 | Issue #431 ⚠️ | @debugger | Technical uncertainty | πŸ”΄ | "Interesting find, @debugger..." | + +Confidence: 🟒 High | 🟑 Medium | πŸ”΄ Needs review + +Full drafts below β–Ό +``` + +### Example audit entry + +```markdown +# PAO External Comms Audit + +- action: posted +- item: Issue #426 +- draft content: | + Hey @newdev! Welcome to Squad πŸ‘‹ Thanks for opening this. + We reproduced the issue in preview builds and we're checking the regression point now. + Let us know if you can share the command you ran right before the failure. +- reviewer: @bradygaster +- outcome: approved and posted via gh issue comment +- timestamp: 2026-03-16T21:30:00Z +``` + +## Anti-Patterns + +- ❌ Posting without human review (NEVER β€” this is the cardinal rule) +- ❌ Drafting without reading full thread (context is everything) +- ❌ Ignoring confidence flags (πŸ”΄ items need Flight/human review) +- ❌ Scanning closed issues (only open items) +- ❌ Responding to issues labeled `squad:internal` or `wontfix` +- ❌ Skipping audit logging (every action must be recorded) +- ❌ Drafting for issues where a squad member already responded (avoid duplicates) diff --git a/.squad/skills/humanizer/SKILL.md b/.squad/skills/humanizer/SKILL.md new file mode 100644 index 000000000..3fd08630d --- /dev/null +++ b/.squad/skills/humanizer/SKILL.md @@ -0,0 +1,100 @@ +--- +name: "humanizer" +description: "Tone enforcement patterns for external-facing community responses" +domain: "communication, tone, community" +confidence: "low" +source: "manual (RFC #426 β€” PAO External Communications)" +--- + +## Context + +Use this skill whenever PAO drafts external-facing responses for issues, discussions, or pull requests. + +- Tone must be warm, helpful, and human-sounding β€” never robotic or corporate. +- Brady's constraint applies everywhere: **Humanized tone is mandatory**. +- This applies to **all external-facing content** drafted by PAO. + +## Patterns + +1. **Warm opening** β€” Start with acknowledgment ("Thanks for reporting this", "Great question!") +2. **Active voice** β€” "We're looking into this" not "This is being investigated" +3. **Second person** β€” Address the person directly ("you" not "the user") +4. **Conversational connectors** β€” "That said...", "Here's what we found...", "Quick note:" +5. **Specific, not vague** β€” "This affects the casting module in v0.8.x" not "We are aware of issues" +6. **Empathy markers** β€” "I can see how that would be frustrating", "Good catch!" +7. **Action-oriented closes** β€” "Let us know if that helps!" not "Please advise if further assistance is required" +8. **Uncertainty is OK** β€” "We're not 100% sure yet, but here's what we think is happening..." is better than false confidence +9. **Profanity filter** β€” Never include profanity, slurs, or aggressive language, even when quoting +10. **Baseline comparison** β€” Responses should align with tone of 5-10 "gold standard" responses (>80% similarity threshold) + +## Examples + +### 1. Welcome + +```text +Hey {author}! Welcome to Squad πŸ‘‹ Thanks for opening this. +{substantive response} +Let us know if you have questions β€” happy to help! +``` + +### 2. Troubleshooting + +```text +Thanks for the detailed report, {author}! +Here's what we think is happening: {explanation} +{steps or workaround} +Let us know if that helps, or if you're seeing something different. +``` + +### 3. Feature guidance + +```text +Great question! {context on current state} +{guidance or workaround} +We've noted this as a potential improvement β€” {tracking info if applicable}. +``` + +### 4. Redirect + +```text +Thanks for reaching out! This one is actually better suited for {correct location}. +{brief explanation of why} +Feel free to open it there β€” they'll be able to help! +``` + +### 5. Acknowledgment + +```text +Good catch, {author}. We've confirmed this is a real issue. +{what we know so far} +We'll update this thread when we have a fix. Thanks for flagging it! +``` + +### 6. Closing + +```text +This should be resolved in {version/PR}! πŸŽ‰ +{brief summary of what changed} +Thanks for reporting this, {author} β€” it made Squad better. +``` + +### 7. Technical uncertainty + +```text +Interesting find, {author}. We're not 100% sure what's causing this yet. +Here's what we've ruled out: {list} +We'd love more context if you have it β€” {specific ask}. +We'll dig deeper and update this thread. +``` + +## Anti-Patterns + +- ❌ Corporate speak: "We appreciate your patience as we investigate this matter" +- ❌ Marketing hype: "Squad is the BEST way to..." or "This amazing feature..." +- ❌ Passive voice: "It has been determined that..." or "The issue is being tracked" +- ❌ Dismissive: "This works as designed" without empathy +- ❌ Over-promising: "We'll ship this next week" without commitment from the team +- ❌ Empty acknowledgment: "Thanks for your feedback" with no substance +- ❌ Robot signatures: "Best regards, PAO" or "Sincerely, The Squad Team" +- ❌ Excessive emoji: More than 1-2 emoji per response +- ❌ Quoting profanity: Even when the original issue contains it, paraphrase instead From 816bd1360a30620065bf0257ad3257941d8e34fb Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:25:34 -0700 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20address=20team=20review=20round=201?= =?UTF-8?q?=20=E2=80=94=20all=20critical=20blockers=20resolved?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes from Flight (architecture), Procedures (skills), FIDO (validation): SQLite lock: single global lease replacing per-session locks (Flight) Routing: community response now explicit manual-trigger Phase 1 (Flight) Audit lifecycle: runtime artifacts gitignored, README clarified (Flight) External-comms skill: operationalized templates, rollback path, thread-read verification, confidence classification, discussion workflow (Procedures) Humanizer skill: disagreement/info-request/no-link-dumping patterns (Procedures) Gold standards: added GS-6 redirect + GS-7 closing (FIDO) Tone validation: Node-safe regex, removed duplicate, added required patterns, baseline_blocking flag (FIDO) Audit template: expanded action enum, conditional fields matrix (FIDO) Reviewer rejection protocol enforced: original authors locked out per-artifact. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/.gitignore | 12 +- .squad/comms/README.md | 52 ++--- .squad/comms/templates/audit-entry.md | 20 +- .../comms/templates/review-state-schema.sql | 141 +++++++------- .squad/comms/templates/tone-validation.json | 35 ++-- .squad/comms/tests/tone-validation-spec.md | 43 +++-- .squad/routing.md | 2 +- .squad/skills/external-comms/SKILL.md | 181 ++++++++++++++++-- .squad/skills/humanizer/SKILL.md | 9 +- 9 files changed, 357 insertions(+), 138 deletions(-) diff --git a/.squad/comms/.gitignore b/.squad/comms/.gitignore index 71d241b62..1313383b1 100644 --- a/.squad/comms/.gitignore +++ b/.squad/comms/.gitignore @@ -1,5 +1,7 @@ -# Runtime state (not committed) -review-state.db -review-state.db-journal -review-state.db-wal -review-state.db-shm +# Runtime state (not committed) +review-state.db +review-state.db-journal +review-state.db-wal +review-state.db-shm +audit/ +!audit/.gitkeep diff --git a/.squad/comms/README.md b/.squad/comms/README.md index a739bd8c3..8dd52f9e9 100644 --- a/.squad/comms/README.md +++ b/.squad/comms/README.md @@ -1,25 +1,27 @@ -# PAO External Communications - -> Phase 1: Draft-only mode with human review gate. - -## Directory Structure - -- `audit/` β€” Audit trail for every draft-review-post action -- `review-state.db` β€” SQLite-based atomic locking for concurrent review sessions (created at runtime) -- `templates/` β€” Response templates for common scenarios - -## Workflow - -1. PAO scans issues and discussions for unanswered items -2. PAO drafts responses using humanizer skill -3. PAO presents review table with confidence flags -4. Human reviews, approves/edits/skips each draft -5. Human posts approved responses -6. Every action logged to `audit/` - -## Safety - -- `pao halt` β€” freezes all pending drafts -- All responses require explicit human approval -- Audit trail is append-only -- SQLite locking prevents concurrent review race conditions +# PAO External Communications + +> Phase 1: Manual-trigger, draft-only mode with human review gate. + +## Directory Structure + +- `audit/` β€” Runtime-only audit trail for every draft-review-post action (not committed to git; keep `audit/.gitkeep`) +- `review-state.db` β€” SQLite-based single-reviewer lease and draft state (created at runtime) +- `templates/` β€” Response templates for common scenarios +- `tests/` β€” Comms workflow and review-state coverage + +## Workflow + +1. Human manually triggers PAO to scan issues and discussions for unanswered items +2. PAO drafts responses using humanizer skill +3. PAO presents review table with confidence flags +4. Human reviews, approves/edits/skips each draft +5. Human posts approved responses +6. Every action is logged to runtime-only `audit/` + +## Safety + +- `pao halt` β€” freezes all pending drafts +- Phase 1 is manual-trigger only +- All responses require explicit human approval +- Audit trail is append-only and runtime-only +- SQLite lease prevents concurrent review race conditions diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md index 1bc655671..67a0ed600 100644 --- a/.squad/comms/templates/audit-entry.md +++ b/.squad/comms/templates/audit-entry.md @@ -1,6 +1,6 @@ --- timestamp: "{ISO-8601}" -action: "scan|draft|approve|edit|skip|post|halt|resume|delete" +action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expire" item_type: "issue|discussion|pr" item_number: {number} item_url: "{url}" @@ -23,3 +23,21 @@ outcome: "approved|edited|skipped|posted|halted|deleted" ## Post Result {link to posted comment if posted, or "not posted" if skipped/halted} + +## Conditional Fields + +Not all fields apply to every action: + +| Action | Required Fields | Optional Fields | +|--------|----------------|-----------------| +| scan | timestamp, action, outcome (item count) | β€” | +| draft | timestamp, action, item_type, item_number, draft_id, confidence, draft_content | thread_depth | +| approve | timestamp, action, draft_id, reviewer, outcome | reviewer_notes | +| edit | timestamp, action, draft_id, reviewer, outcome, draft_content | reviewer_notes | +| skip | timestamp, action, draft_id, reviewer, outcome | reviewer_notes | +| post | timestamp, action, item_number, draft_id, reviewer, post_result | β€” | +| halt | timestamp, action, reviewer (halter), outcome | reason | +| resume | timestamp, action, reviewer (resumer), outcome | β€” | +| delete | timestamp, action, item_number, post_result (deleted URL), outcome | reason | +| lint_failure | timestamp, action, draft_id, outcome (violation details) | β€” | +| expire | timestamp, action, draft_id, outcome | β€” | diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql index c852a2acd..12e8104b1 100644 --- a/.squad/comms/templates/review-state-schema.sql +++ b/.squad/comms/templates/review-state-schema.sql @@ -1,69 +1,72 @@ --- PAO External Communications: Review State Database --- Created at runtime in .squad/comms/review-state.db --- Zero new dependencies (Copilot CLI already uses SQLite) - -CREATE TABLE IF NOT EXISTS review_locks ( - session_id TEXT PRIMARY KEY, - reviewer TEXT NOT NULL, - hostname TEXT NOT NULL, - pid INTEGER NOT NULL, - acquired_at TEXT NOT NULL DEFAULT (datetime('now')), - expires_at TEXT NOT NULL DEFAULT (datetime('now', '+1 hour')), - status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'released', 'expired')) -); - --- Atomic lock acquisition using INSERT ... ON CONFLICT --- If a lock exists and is expired, it gets replaced --- If a lock exists and is active, the INSERT fails (lock held) -CREATE TRIGGER IF NOT EXISTS cleanup_expired_locks -BEFORE INSERT ON review_locks -BEGIN - DELETE FROM review_locks - WHERE expires_at < datetime('now') - AND status = 'active'; -END; - --- Draft tracking table -CREATE TABLE IF NOT EXISTS draft_queue ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - session_id TEXT NOT NULL, - item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion', 'pr')), - item_number INTEGER NOT NULL, - item_url TEXT, - response_type TEXT NOT NULL, - confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')), - draft_content TEXT NOT NULL, - thread_depth INTEGER DEFAULT 0, - long_thread_flag INTEGER DEFAULT 0, - status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'edited', 'skipped', 'posted', 'halted', 'deleted')), - reviewer TEXT, - reviewed_at TEXT, - posted_url TEXT, - created_at TEXT NOT NULL DEFAULT (datetime('now')), - FOREIGN KEY (session_id) REFERENCES review_locks(session_id) -); - --- Halt state (safe word mechanism) -CREATE TABLE IF NOT EXISTS halt_state ( - id INTEGER PRIMARY KEY CHECK (id = 1), - halted INTEGER NOT NULL DEFAULT 0, - halted_by TEXT, - halted_at TEXT, - reason TEXT -); - --- Initialize halt state (not halted by default) -INSERT OR IGNORE INTO halt_state (id, halted) VALUES (1, 0); - --- Audit log (append-only, mirrors markdown audit files) -CREATE TABLE IF NOT EXISTS audit_log ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - timestamp TEXT NOT NULL DEFAULT (datetime('now')), - action TEXT NOT NULL, - item_type TEXT, - item_number INTEGER, - draft_id INTEGER, - reviewer TEXT, - outcome TEXT, - details TEXT -); +-- Runtime reminder: PRAGMA foreign_keys = ON; +-- PAO External Communications: Review State Database +-- Created at runtime in .squad/comms/review-state.db +-- Zero new dependencies (Copilot CLI already uses SQLite) + +-- Single global review lease β€” only ONE reviewer at a time +CREATE TABLE IF NOT EXISTS review_lease ( + id INTEGER PRIMARY KEY CHECK (id = 1), + status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'held')), + reviewer TEXT, + hostname TEXT, + pid INTEGER, + acquired_at TEXT, + expires_at TEXT +); + +-- Initialize the single lease row +INSERT OR IGNORE INTO review_lease (id, status) VALUES (1, 'available'); + +-- Acquire: UPDATE review_lease +-- SET status = 'held', reviewer = ?, hostname = ?, pid = ?, acquired_at = datetime('now'), expires_at = datetime('now', '+1 hour') +-- WHERE id = 1 AND (status = 'available' OR expires_at < datetime('now')); +-- Release: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1; +-- Check: SELECT * FROM review_lease WHERE id = 1; +-- Cleanup expired lease before work: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1 AND status = 'held' AND expires_at < datetime('now'); + +-- Draft tracking table +CREATE TABLE IF NOT EXISTS draft_queue ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + reviewer TEXT, + item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion', 'pr')), + item_number INTEGER NOT NULL, + item_url TEXT, + response_type TEXT NOT NULL, + confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')), + draft_content TEXT NOT NULL, + thread_depth INTEGER DEFAULT 0, + long_thread_flag INTEGER DEFAULT 0, + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'edited', 'skipped', 'posted', 'halted', 'deleted')), + reviewed_at TEXT, + posted_url TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')) +); + +-- Halt state (safe word mechanism) +CREATE TABLE IF NOT EXISTS halt_state ( + id INTEGER PRIMARY KEY CHECK (id = 1), + halted INTEGER NOT NULL DEFAULT 0, + halted_by TEXT, + halted_at TEXT, + reason TEXT +); + +-- Initialize halt state (not halted by default) +INSERT OR IGNORE INTO halt_state (id, halted) VALUES (1, 0); + +-- Audit log (append-only, mirrors runtime audit files) +CREATE TABLE IF NOT EXISTS audit_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL DEFAULT (datetime('now')), + action TEXT NOT NULL, + item_type TEXT, + item_number INTEGER, + draft_id INTEGER, + reviewer TEXT, + outcome TEXT, + details TEXT +); diff --git a/.squad/comms/templates/tone-validation.json b/.squad/comms/templates/tone-validation.json index 525afa3fd..c66625fc3 100644 --- a/.squad/comms/templates/tone-validation.json +++ b/.squad/comms/templates/tone-validation.json @@ -4,63 +4,76 @@ "reject_patterns": [ { "id": "corporate-speak", - "pattern": "(?i)(we appreciate your patience|please be advised|per our discussion|as per|kindly note|please do not hesitate)", + "pattern": "(?:[Ww]e appreciate your patience|[Pp]lease be advised|[Pp]er our discussion|[Aa]s per|[Kk]indly note|[Pp]lease do not hesitate)", "message": "Corporate speak detected. Use conversational tone instead." }, { "id": "passive-voice-formal", - "pattern": "(?i)(it has been determined|it was decided|has been escalated|is being investigated|has been noted)", + "pattern": "(?:[Ii]t has been determined|[Ii]t was decided|[Hh]as been escalated|[Ii]s being investigated|[Hh]as been noted)", "message": "Formal passive voice detected. Use active voice: 'We determined...' or 'We're looking into...'" }, { "id": "marketing-hype", - "pattern": "(?i)(best in class|cutting.edge|revolutionary|game.changing|industry.leading|next.generation|amazing feature)", + "pattern": "(?:[Bb]est[- ]in[- ]class|[Cc]utting[- ]edge|[Rr]evolutionary|[Gg]ame[- ]changing|[Ii]ndustry[- ]leading|[Nn]ext[- ]generation|[Aa]mazing feature)", "message": "Marketing hype detected. Be specific about what the feature does, not how great it is." }, { "id": "empty-acknowledgment", - "pattern": "(?i)^(thanks for your feedback\\.?|thank you for reaching out\\.?)$", + "pattern": "^\\s*(?:[Tt]hanks for your feedback\\.?|[Tt]hank you for reaching out\\.?)\\s*$", "message": "Empty acknowledgment without substance. Add specific context or next steps." }, { "id": "robot-signature", - "pattern": "(?i)(best regards|sincerely|kind regards|respectfully|warm regards)\\s*[,.]?\\s*(pao|the squad team|squad bot)", + "pattern": "(?:[Bb]est regards|[Ss]incerely|[Kk]ind regards|[Rr]espectfully|[Ww]arm regards)\\s*[,.]?\\s*(?:[Pp][Aa][Oo]|[Tt]he [Ss]quad [Tt]eam|[Ss]quad [Bb]ot)", "message": "Robot signature detected. Responses should end naturally, not with formal sign-offs." }, { "id": "over-promising", - "pattern": "(?i)(we will ship|we'll release|coming soon|in the next release|definitely fix|guaranteed)", + "pattern": "(?:[Ww]e will ship|[Ww]e'll release|[Cc]oming soon|[Ii]n the next release|[Dd]efinitely fix|[Gg]uaranteed)", "message": "Over-promising detected. Only commit to what the team has explicitly agreed to." }, { "id": "dismissive", - "pattern": "(?i)(works as designed|not a bug|won't fix|that's expected|user error)", + "pattern": "(?:[Ww]orks as designed|[Nn]ot a bug|[Ww]on't fix|[Tt]hat's expected|[Uu]ser error)", "message": "Dismissive language detected. Acknowledge the experience before explaining the design." }, { "id": "profanity", - "pattern": "(?i)(damn|hell|crap|crap|shit|fuck|ass|bastard|bitch)", + "pattern": "\\b(?:[Dd]amn|[Hh]ell|[Cc]rap|[Ss]hit|[Ff]uck|[Aa]ss|[Bb]astard|[Bb]itch)\\b", "message": "Profanity detected. Never include profanity, even when quoting." } ], "require_patterns": [ { "id": "acknowledgment", - "pattern": "(?i)(thanks|thank you|good catch|great question|interesting|appreciate|welcome)", + "pattern": "(?:[Tt]hanks|[Tt]hank you|[Gg]ood catch|[Gg]reat question|[Ii]nteresting|[Aa]ppreciate|[Ww]elcome)", "message": "Response should include acknowledgment of the author's contribution.", "applies_to": ["welcome", "troubleshooting", "acknowledgment"] }, { "id": "action-oriented", - "pattern": "(?i)(let us know|feel free|happy to help|we'll update|reach out|we'll dig|keep us posted)", + "pattern": "(?:[Ll]et us know|[Ff]eel free|[Hh]appy to help|[Ww]e'll update|[Rr]each out|[Ww]e'll dig|[Kk]eep us posted)", "message": "Response should end with an action-oriented close.", "applies_to": ["troubleshooting", "feature-guidance", "technical-uncertainty"] + }, + { + "id": "context-provided", + "pattern": "(?:[Cc]urrently|[Rr]ight now|[Aa]t the moment|[Aa]s of|[Tt]he way it works)", + "message": "Feature guidance should provide context on current state.", + "applies_to": ["feature-guidance"] + }, + { + "id": "uncertainty-honest", + "pattern": "(?:[Nn]ot sure|[Nn]ot 100%|[Dd]on't know yet|[Ss]till investigating|[Uu]nclear|[Hh]aven't determined)", + "message": "Technical uncertainty should be honest about unknowns.", + "applies_to": ["technical-uncertainty"] } ], "confidence_thresholds": { "high": { "description": "Answered before, clear docs, community consensus", - "min_similarity": 0.8 + "min_similarity": 0.8, + "baseline_blocking": true }, "medium": { "description": "Technically sound but minor uncertainty or tone-dependent", diff --git a/.squad/comms/tests/tone-validation-spec.md b/.squad/comms/tests/tone-validation-spec.md index 277bf4092..e96c9fbc9 100644 --- a/.squad/comms/tests/tone-validation-spec.md +++ b/.squad/comms/tests/tone-validation-spec.md @@ -83,54 +83,71 @@ Drafts of specific types MUST contain these patterns: ## Gold Standard Responses -The following 5 responses serve as the tone baseline. New drafts should align with this tone: +The following 7 gold standard responses serve as the tone baseline. New drafts should align with this tone: ### GS-1: Welcome (High confidence) > Hey @newuser! Welcome to Squad πŸ‘‹ Thanks for opening this β€” great first issue! -> +> > To answer your question: Squad uses `.squad/team.md` to define your team roster. You can add members by editing that file directly or running `squad init`. -> +> > Let us know if you hit any snags β€” happy to help! ### GS-2: Troubleshooting (High confidence) -> Thanks for the detailed report, @reporter! -> +> Thanks for the detailed report, @reporter! +> > This looks like it might be related to the casting registry not finding the universe file. Here's what we'd suggest: > 1. Check that `.squad/casting/registry.json` exists and is valid JSON > 2. Run `squad build` to regenerate from source > 3. If that doesn't work, try deleting `.squad/casting/` and re-running `squad init` -> +> > Let us know if that helps, or if you're seeing something different. ### GS-3: Feature Guidance (Medium confidence) > Great question! Right now, Squad handles cross-repo orchestration through the hub-and-spoke model β€” you'd have a central `.squad/` in one repo and reference it from others. -> +> > We know this isn't ideal for every setup. There's been some discussion about making this more seamless (see #316 for the RFC). -> +> > For now, the workaround is to use `squad export` to share config across repos. Hope that helps! ### GS-4: Acknowledgment (High confidence) > Good catch, @finder. We've confirmed this is a real issue with the session pool cleanup. -> +> > It looks like sessions aren't being released when the adapter disconnects unexpectedly. We're tracking it and will update this thread when we have a fix. -> +> > Thanks for flagging it β€” this one would have been hard to find without your repro steps! ### GS-5: Technical Uncertainty (Low confidence) > Interesting find, @explorer. We're not 100% sure what's causing this yet. -> +> > Here's what we've ruled out: > - It's not a casting issue (registry looks fine) > - It's not a config issue (your squad.config.ts parses correctly) -> +> > Could you share the output of `squad build --verbose`? That would help us narrow it down. We'll dig deeper and update this thread. +### GS-6: Redirect (High confidence) +> Thanks for reaching out, @asker! This one is actually better suited for the Squad-IRL repo, which covers deployment patterns and infrastructure around Squad. +> +> You can open it here: https://github.com/bradygaster/Squad-IRL β€” they'll be able to help with the Terraform setup specifically. +> +> Feel free to link back to this thread for context! + +### GS-7: Closing (High confidence) +> This should be resolved in v0.8.22! πŸŽ‰ +> +> The fix was in PR #389 β€” the casting registry now handles universe overflow correctly when you have more than 15 agents. +> +> Thanks for reporting this, @reporter β€” your repro steps made this one easy to track down. Closing this out! + ## Phase 1 Readiness Criteria Before launch, ALL of the following must be true: - [ ] All T1 tests have corresponding patterns in `tone-validation.json` - [ ] All T2 tests verified against humanizer skill templates -- [ ] Gold standard responses reviewed and approved by Brady or Dina +- [ ] All 7 gold standard responses reviewed and approved by Brady or Dina +- [ ] All 9 response types have corresponding templates (7 original + empathetic disagreement + information request) +- [ ] Thread-read verification tested with threads of 1, 5, 10, and 20+ comments +- [ ] Rollback workflow (delete-and-repost) tested end-to-end - [ ] Review gate SQLite schema tested with concurrent access - [ ] Audit trail format validated against template - [ ] `pao halt` / `pao resume` flow tested end-to-end diff --git a/.squad/routing.md b/.squad/routing.md index 95b6d5586..28fc98bae 100644 --- a/.squad/routing.md +++ b/.squad/routing.md @@ -11,7 +11,7 @@ | Runtime performance | Fortier ⚑ | Streaming, event loop health, session management, async iterators, memory profiling | | Tests & quality | Hockney πŸ§ͺ | Test coverage, Vitest, edge cases, CI/CD, quality gates | | Docs & messaging | McManus πŸ“£ | README, API docs, getting-started, demos, tone review | -| Community response | McManus πŸ“£ | Scan unanswered issues/discussions, draft responses, present review table | +| Community response | McManus πŸ“£ | Manual-trigger scan of unanswered issues/discussions, draft responses with human review gate | | Architecture & review | Keaton πŸ—οΈ | Product direction, architectural decisions, code review, scope/trade-offs | | Distribution | Rabin πŸ“¦ | npm packaging, esbuild config, global install, marketplace prep | | Release management | Trejo 🚒 | Semantic versioning, GitHub Releases, changelogs, devβ†’main merges, release gating | diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md index 2eddaf441..dca79bd2d 100644 --- a/.squad/skills/external-comms/SKILL.md +++ b/.squad/skills/external-comms/SKILL.md @@ -39,6 +39,16 @@ Find unanswered community items with GitHub MCP tools first, or `gh issue list` - Limit to items created in the last 7 days. - Exclude items labeled `squad:internal` or `wontfix`. - Include discussions **and** issues in the same sweep. +- Phase 1 scope is **issues and discussions only** β€” do not draft PR replies. + +### Discussion Handling (Phase 1) + +Discussions use the GitHub Discussions API, which differs from issues: + +- **Scan:** `gh api /repos/{owner}/{repo}/discussions --jq '.[] | select(.answer_chosen_at == null)'` to find unanswered discussions +- **Categories:** Filter by Q&A and General categories only (skip Announcements, Show and Tell) +- **Answers vs comments:** In Q&A discussions, PAO drafts an "answer" (not a comment). The human marks it as accepted answer after posting. +- **Phase 1 scope:** Issues and Discussions ONLY. No PR comments. ### 2. Classify @@ -51,17 +61,60 @@ Determine the response type before drafting. - Acknowledgment (confirmed, no fix) - Closing (resolved) - Technical uncertainty (unknown cause) +- Empathetic disagreement (pushback on a decision or design) +- Information request (need more reproduction details or context) + +### Template Selection Guide + +| Signal in Issue/Discussion | β†’ Response Type | Template | +|---------------------------|-----------------|----------| +| New contributor (0 prior issues) | Welcome | T1 | +| Error message, stack trace, "doesn't work" | Troubleshooting | T2 | +| "How do I...?", "Can Squad...?", "Is there a way to...?" | Feature Guidance | T3 | +| Wrong repo, out of scope for Squad | Redirect | T4 | +| Confirmed bug, no fix available yet | Acknowledgment | T5 | +| Fix shipped, PR merged that resolves issue | Closing | T6 | +| Unclear cause, needs investigation | Technical Uncertainty | T7 | +| Author disagrees with a decision or design | Empathetic Disagreement | T8 | +| Need more reproduction info or context | Information Request | T9 | + +Use 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. + +### Confidence Classification + +| Confidence | Criteria | Example | +|-----------|----------|---------| +| 🟒 High | Answer exists in Squad docs or FAQ, similar question answered before, no technical ambiguity | "How do I install Squad?" | +| 🟑 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) | +| πŸ”΄ Needs Review | Technical uncertainty, policy/roadmap question, potential reputational risk, author is frustrated/angry, question about unreleased features | "When will Squad support Claude?" | + +**Auto-escalation rules:** +- Any mention of competitors β†’ πŸ”΄ +- Any mention of pricing/licensing β†’ πŸ”΄ +- Author has >3 follow-up comments without resolution β†’ πŸ”΄ +- Question references a closed-wontfix issue β†’ πŸ”΄ ### 3. Draft Use the humanizer skill for every draft. +- Complete **Thread-Read Verification** before writing. - Read the **full thread**, including all comments, before writing. -- Classify the response type. -- Draft with the humanizer patterns and the matching template. +- Select the matching template from the **Template Selection Guide** and record the template ID in the review notes. +- Treat templates as reusable drafting assets: keep the structure, replace placeholders, and only improvise when the thread truly requires it. - Validate the draft against the humanizer anti-patterns. - Flag long threads (`>10` comments) with `⚠️`. +### Thread-Read Verification + +Before drafting, PAO MUST verify complete thread coverage: + +1. **Count verification:** Compare API comment count with actually-read comments. If mismatch, abort draft. +2. **Deleted comment check:** Use `gh api` timeline to detect deleted comments. If found, flag as ⚠️ in review table. +3. **Thread summary:** Include in every draft: "Thread: {N} comments, last activity {date}, {summary of key points}" +4. **Long thread flag:** If >10 comments, add ⚠️ to review table and include condensed thread summary +5. **Evidence line in review table:** Each draft row includes "Read: {N}/{total} comments" column + ### 4. Present Show drafts for review in this exact format: @@ -70,15 +123,18 @@ Show drafts for review in this exact format: πŸ“ PAO β€” Community Response Drafts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -| # | Item | Author | Type | Confidence | Preview | -|---|------|--------|------|------------|---------| -| 1 | Issue #N | @user | Type | 🟒/🟑/πŸ”΄ | "First words..." | +| # | Item | Author | Type | Confidence | Read | Preview | +|---|------|--------|------|------------|------|---------| +| 1 | Issue #N | @user | Type | 🟒/🟑/πŸ”΄ | N/N | "First words..." | Confidence: 🟒 High | 🟑 Medium | πŸ”΄ Needs review Full drafts below β–Ό ``` +Each full draft must begin with the thread summary line: +`Thread: {N} comments, last activity {date}, {summary of key points}` + ### 5. Human Action Wait for explicit human direction before anything is posted. @@ -88,11 +144,25 @@ Wait for explicit human direction before anything is posted. - `pao skip` β€” skip all - `pao halt` β€” freeze all pending (safe word) +### Rollback β€” Bad Post Recovery + +If a posted response turns out to be wrong, inappropriate, or needs correction: + +1. **Delete the comment:** `gh api -X DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}` +2. **Log the deletion:** Write audit entry with action `delete`, include reason and original content +3. **Draft replacement** (if needed): PAO drafts a corrected response, goes through normal review cycle +4. **Postmortem:** If the error reveals a pattern gap, update humanizer anti-patterns or add a new test case + +**Safe word β€” `pao halt`:** +- Immediately freezes all pending drafts in the review queue +- No new scans or drafts until `pao resume` is issued +- Audit entry logged with halter identity and reason + ### 6. Post After approval: -- Human posts via `gh issue comment` or `gh api`. +- Human posts via `gh issue comment` for issues or `gh api` for discussion answers/comments. - PAO helps by preparing the CLI command. - Write the audit entry after the posting action. @@ -105,6 +175,8 @@ Log every action. ## Examples +These are reusable templates. Keep the structure, replace placeholders, and adjust only where the thread requires it. + ### Example scan command ```bash @@ -117,11 +189,11 @@ gh issue list --state open --json number,title,author,labels,comments --limit 20 πŸ“ PAO β€” Community Response Drafts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -| # | Item | Author | Type | Confidence | Preview | -|---|------|--------|------|------------|---------| -| 1 | Issue #426 | @newdev | Welcome | 🟒 | "Hey @newdev! Welcome to Squad..." | -| 2 | Discussion #18 | @builder | Feature guidance | 🟑 | "Great question! Today the CLI..." | -| 3 | Issue #431 ⚠️ | @debugger | Technical uncertainty | πŸ”΄ | "Interesting find, @debugger..." | +| # | Item | Author | Type | Confidence | Read | Preview | +|---|------|--------|------|------------|------|---------| +| 1 | Issue #426 | @newdev | Welcome | 🟒 | 1/1 | "Hey @newdev! Welcome to Squad..." | +| 2 | Discussion #18 | @builder | Feature guidance | 🟑 | 4/4 | "Great question! Today the CLI..." | +| 3 | Issue #431 ⚠️ | @debugger | Technical uncertainty | πŸ”΄ | 12/12 | "Interesting find, @debugger..." | Confidence: 🟒 High | 🟑 Medium | πŸ”΄ Needs review @@ -136,6 +208,7 @@ Full drafts below β–Ό - action: posted - item: Issue #426 - draft content: | + Thread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install. Hey @newdev! Welcome to Squad πŸ‘‹ Thanks for opening this. We reproduced the issue in preview builds and we're checking the regression point now. Let us know if you can share the command you ran right before the failure. @@ -144,6 +217,89 @@ Full drafts below β–Ό - timestamp: 2026-03-16T21:30:00Z ``` +### T1 β€” Welcome + +```text +Hey {author}! Welcome to Squad πŸ‘‹ Thanks for opening this. +{specific acknowledgment or first answer} +Let us know if you have questions β€” happy to help! +``` + +### T2 β€” Troubleshooting + +```text +Thanks for the detailed report, {author}! +Here's what we think is happening: {explanation} +{steps or workaround} +Let us know if that helps, or if you're seeing something different. +``` + +### T3 β€” Feature Guidance + +```text +Great question! {context on current state} +{guidance or workaround} +We've noted this as a potential improvement β€” {tracking info if applicable}. +``` + +### T4 β€” Redirect + +```text +Thanks for reaching out! This one is actually better suited for {correct location}. +{brief explanation of why} +Feel free to open it there β€” they'll be able to help! +``` + +### T5 β€” Acknowledgment + +```text +Good catch, {author}. We've confirmed this is a real issue. +{what we know so far} +We'll update this thread when we have a fix. Thanks for flagging it! +``` + +### T6 β€” Closing + +```text +This should be resolved in {version/PR}! πŸŽ‰ +{brief summary of what changed} +Thanks for reporting this, {author} β€” it made Squad better. +``` + +### T7 β€” Technical Uncertainty + +```text +Interesting find, {author}. We're not 100% sure what's causing this yet. +Here's what we've ruled out: {list} +We'd love more context if you have it β€” {specific ask}. +We'll dig deeper and update this thread. +``` + +### T8 β€” Empathetic Disagreement + +```text +We hear you, {author}. That's a fair concern. + +The current design choice was driven by {reason}. We know it's not ideal for every use case. + +{what alternatives exist or what trade-off was made} + +If 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! +``` + +### T9 β€” Information Request + +```text +Thanks for reporting this, {author}! + +To help us dig into this, could you share: +- {specific ask 1} +- {specific ask 2} +- {specific ask 3, if applicable} + +That context will help us narrow down what's happening. Appreciate it! +``` + ## Anti-Patterns - ❌ Posting without human review (NEVER β€” this is the cardinal rule) @@ -153,3 +309,6 @@ Full drafts below β–Ό - ❌ Responding to issues labeled `squad:internal` or `wontfix` - ❌ Skipping audit logging (every action must be recorded) - ❌ Drafting for issues where a squad member already responded (avoid duplicates) +- ❌ Drafting pull request responses in Phase 1 (issues/discussions only) +- ❌ Treating templates like loose examples instead of reusable drafting assets +- ❌ Asking for more info without specific requests diff --git a/.squad/skills/humanizer/SKILL.md b/.squad/skills/humanizer/SKILL.md index 3fd08630d..4dbb854df 100644 --- a/.squad/skills/humanizer/SKILL.md +++ b/.squad/skills/humanizer/SKILL.md @@ -8,11 +8,11 @@ source: "manual (RFC #426 β€” PAO External Communications)" ## Context -Use this skill whenever PAO drafts external-facing responses for issues, discussions, or pull requests. +Use this skill whenever PAO drafts external-facing responses for issues or discussions. - Tone must be warm, helpful, and human-sounding β€” never robotic or corporate. - Brady's constraint applies everywhere: **Humanized tone is mandatory**. -- This applies to **all external-facing content** drafted by PAO. +- This applies to **all external-facing content** drafted by PAO in Phase 1 issues/discussions workflows. ## Patterns @@ -26,6 +26,9 @@ Use this skill whenever PAO drafts external-facing responses for issues, discuss 8. **Uncertainty is OK** β€” "We're not 100% sure yet, but here's what we think is happening..." is better than false confidence 9. **Profanity filter** β€” Never include profanity, slurs, or aggressive language, even when quoting 10. **Baseline comparison** β€” Responses should align with tone of 5-10 "gold standard" responses (>80% similarity threshold) +11. **Empathetic disagreement** β€” "We hear you. That's a fair concern." before explaining the reasoning +12. **Information request** β€” Ask for specific details, not open-ended "can you provide more info?" +13. **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 ## Examples @@ -98,3 +101,5 @@ We'll dig deeper and update this thread. - ❌ Robot signatures: "Best regards, PAO" or "Sincerely, The Squad Team" - ❌ Excessive emoji: More than 1-2 emoji per response - ❌ Quoting profanity: Even when the original issue contains it, paraphrase instead +- ❌ Link-dumping: Pasting URLs without context ("See: https://...") +- ❌ Open-ended info requests: "Can you provide more information?" without specifying what information From a017694fb6c71d4bd089551b99c9959180bcb013 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:34:14 -0700 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20address=20team=20review=20round=202?= =?UTF-8?q?=20=E2=80=94=20Phase=201=20consistency=20and=20audit=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Remove Ralph-triggered activation (manual-trigger only in Phase 1) 2. Remove 'pr' from item_type (issues/discussions only in Phase 1) 3. Fix audit action taxonomy: 'posted' β†’ 'post' in example 4. Add empathetic-disagreement and information-request to response types 5. Fix outcome field: contextual per-action values with clear table 6. Add Discussion rollback path (GraphQL mutation for discussion comments) 7. Make baseline similarity blocking for high-confidence drafts in ci-gate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/templates/audit-entry.md | 34 +++++++++---------- .../comms/templates/review-state-schema.sql | 2 +- .squad/comms/tests/ci-gate.md | 6 +++- .squad/skills/external-comms/SKILL.md | 8 +++-- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md index 67a0ed600..cd6b9cddb 100644 --- a/.squad/comms/templates/audit-entry.md +++ b/.squad/comms/templates/audit-entry.md @@ -1,17 +1,17 @@ --- timestamp: "{ISO-8601}" action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expire" -item_type: "issue|discussion|pr" +item_type: "issue|discussion" item_number: {number} item_url: "{url}" draft_id: "{N from review table}" reviewer: "{github-username}" -outcome: "approved|edited|skipped|posted|halted|deleted" +outcome: "{contextual β€” see Conditional Fields table for per-action outcome values}" --- ## Context - Thread depth: {comment count} -- Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty} +- Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty|empathetic-disagreement|information-request} - Confidence: {🟒|🟑|πŸ”΄} - Long thread flag: {true|false} @@ -26,18 +26,18 @@ outcome: "approved|edited|skipped|posted|halted|deleted" ## Conditional Fields -Not all fields apply to every action: +Not all fields apply to every action. The `outcome` value is contextual per action: -| Action | Required Fields | Optional Fields | -|--------|----------------|-----------------| -| scan | timestamp, action, outcome (item count) | β€” | -| draft | timestamp, action, item_type, item_number, draft_id, confidence, draft_content | thread_depth | -| approve | timestamp, action, draft_id, reviewer, outcome | reviewer_notes | -| edit | timestamp, action, draft_id, reviewer, outcome, draft_content | reviewer_notes | -| skip | timestamp, action, draft_id, reviewer, outcome | reviewer_notes | -| post | timestamp, action, item_number, draft_id, reviewer, post_result | β€” | -| halt | timestamp, action, reviewer (halter), outcome | reason | -| resume | timestamp, action, reviewer (resumer), outcome | β€” | -| delete | timestamp, action, item_number, post_result (deleted URL), outcome | reason | -| lint_failure | timestamp, action, draft_id, outcome (violation details) | β€” | -| expire | timestamp, action, draft_id, outcome | β€” | +| Action | Required Fields | Outcome Value | Optional Fields | +|--------|----------------|---------------|-----------------| +| scan | timestamp, action | item count found (e.g., "5 candidates") | β€” | +| draft | timestamp, action, item_type, item_number, draft_id, confidence, draft_content | β€” (no outcome for draft) | thread_depth | +| approve | timestamp, action, draft_id, reviewer | "approved" | reviewer_notes | +| edit | timestamp, action, draft_id, reviewer, draft_content | "edited" | reviewer_notes | +| skip | timestamp, action, draft_id, reviewer | "skipped" | reviewer_notes | +| post | timestamp, action, item_number, draft_id, reviewer | "posted" + post_result link | β€” | +| halt | timestamp, action, reviewer (halter) | "halted" | reason | +| resume | timestamp, action, reviewer (resumer) | "resumed" | β€” | +| delete | timestamp, action, item_number | "deleted" + original URL | reason | +| lint_failure | timestamp, action, draft_id | violation details (free text) | β€” | +| expire | timestamp, action, draft_id | "expired" | β€” | diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql index 12e8104b1..952c35f5e 100644 --- a/.squad/comms/templates/review-state-schema.sql +++ b/.squad/comms/templates/review-state-schema.sql @@ -32,7 +32,7 @@ INSERT OR IGNORE INTO review_lease (id, status) VALUES (1, 'available'); CREATE TABLE IF NOT EXISTS draft_queue ( id INTEGER PRIMARY KEY AUTOINCREMENT, reviewer TEXT, - item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion', 'pr')), + item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion')), item_number INTEGER NOT NULL, item_url TEXT, response_type TEXT NOT NULL, diff --git a/.squad/comms/tests/ci-gate.md b/.squad/comms/tests/ci-gate.md index a4e0cf0a7..ba9f658e3 100644 --- a/.squad/comms/tests/ci-gate.md +++ b/.squad/comms/tests/ci-gate.md @@ -17,12 +17,16 @@ 3. **Minimum substance** β€” Draft must be >50 characters (no empty acknowledgments) 4. **Thread read verification** β€” Confirm all comments in thread were read before drafting +### Mandatory for High-Confidence Drafts (🟒 only) + +5. **Baseline similarity** β€” Block if tone similarity to gold standard <80% for high-confidence (🟒) drafts. Aligns with `baseline_blocking: true` in `tone-validation.json`. + ### Warning (flags but doesn't block) 1. **Positive pattern check** β€” Warn if response type should contain patterns from `require_patterns` 2. **Length check** β€” Warn if draft >500 words (may be too verbose for a GitHub comment) 3. **Emoji count** β€” Warn if >2 emoji in draft -4. **Similarity check** β€” Warn if tone similarity to gold standard <80% +4. **Similarity check** β€” Warn if tone similarity to gold standard <80% for medium/low-confidence drafts ### Informational diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md index dca79bd2d..74716714d 100644 --- a/.squad/skills/external-comms/SKILL.md +++ b/.squad/skills/external-comms/SKILL.md @@ -26,7 +26,7 @@ Phase 1 is **draft-only mode**. - PAO scans issues and discussions, drafts responses with the humanizer skill, and presents a review table for human approval. - **Human review gate is mandatory** β€” PAO never posts autonomously. - Every action is logged to `.squad/comms/audit/`. -- This workflow is triggered manually ("PAO, check community") or when Ralph detects the `squad:needs-response` label. +- This workflow is triggered manually only ("PAO, check community") β€” no automated or Ralph-triggered activation in Phase 1. ## Patterns @@ -148,7 +148,9 @@ Wait for explicit human direction before anything is posted. If a posted response turns out to be wrong, inappropriate, or needs correction: -1. **Delete the comment:** `gh api -X DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}` +1. **Delete the comment:** + - Issues: `gh api -X DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}` + - Discussions: `gh api graphql -f query='mutation { deleteDiscussionComment(input: {id: "{node_id}"}) { comment { id } } }'` 2. **Log the deletion:** Write audit entry with action `delete`, include reason and original content 3. **Draft replacement** (if needed): PAO drafts a corrected response, goes through normal review cycle 4. **Postmortem:** If the error reveals a pattern gap, update humanizer anti-patterns or add a new test case @@ -205,7 +207,7 @@ Full drafts below β–Ό ```markdown # PAO External Comms Audit -- action: posted +- action: post - item: Issue #426 - draft content: | Thread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install. From 5fe0b7c412836b0d071c123bc3f6641b751c60cf Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 22:41:29 -0700 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20address=20team=20review=20round=203?= =?UTF-8?q?=20=E2=80=94=20audit=20template=20consistency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Audit entry frontmatter: only universal fields (timestamp, action) 2. Template sections annotated with applicable action types 3. Example audit entry in SKILL.md matches canonical template format 4. SKILL.md audit section references conditional fields table Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/templates/audit-entry.md | 17 +++++------- .squad/skills/external-comms/SKILL.md | 39 ++++++++++++++++++--------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md index cd6b9cddb..3f418b1b8 100644 --- a/.squad/comms/templates/audit-entry.md +++ b/.squad/comms/templates/audit-entry.md @@ -1,27 +1,24 @@ --- timestamp: "{ISO-8601}" action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expire" -item_type: "issue|discussion" -item_number: {number} -item_url: "{url}" -draft_id: "{N from review table}" -reviewer: "{github-username}" -outcome: "{contextual β€” see Conditional Fields table for per-action outcome values}" --- -## Context +> All other fields are conditional on the action type. See **Conditional Fields** table below. +> Include only the sections relevant to your action type. + +## Context (draft, approve, edit, skip, post, delete actions) - Thread depth: {comment count} - Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty|empathetic-disagreement|information-request} - Confidence: {🟒|🟑|πŸ”΄} - Long thread flag: {true|false} -## Draft Content +## Draft Content (draft, edit, post actions) {full draft text} -## Reviewer Notes +## Reviewer Notes (approve, edit, skip actions) {any edits or comments from reviewer, or "β€”" if none} -## Post Result +## Post Result (post, delete actions) {link to posted comment if posted, or "not posted" if skipped/halted} ## Conditional Fields diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md index 74716714d..5203c1c4c 100644 --- a/.squad/skills/external-comms/SKILL.md +++ b/.squad/skills/external-comms/SKILL.md @@ -173,7 +173,9 @@ After approval: Log every action. - Location: `.squad/comms/audit/{timestamp}.md` -- Required fields: action, item, draft content, reviewer, outcome, timestamp +- Required fields vary by action β€” see `.squad/comms/templates/audit-entry.md` Conditional Fields table +- Universal required fields: `timestamp`, `action` +- All other fields are conditional on the action type ## Examples @@ -205,18 +207,29 @@ Full drafts below β–Ό ### Example audit entry ```markdown -# PAO External Comms Audit - -- action: post -- item: Issue #426 -- draft content: | - Thread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install. - Hey @newdev! Welcome to Squad πŸ‘‹ Thanks for opening this. - We reproduced the issue in preview builds and we're checking the regression point now. - Let us know if you can share the command you ran right before the failure. -- reviewer: @bradygaster -- outcome: approved and posted via gh issue comment -- timestamp: 2026-03-16T21:30:00Z +--- +timestamp: "2026-03-16T21:30:00Z" +action: "post" +--- + +## Context +- Thread depth: 3 +- Response type: welcome +- Confidence: 🟒 +- Long thread flag: false + +## Draft Content +Thread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install. + +Hey @newdev! Welcome to Squad πŸ‘‹ Thanks for opening this. +We reproduced the issue in preview builds and we're checking the regression point now. +Let us know if you can share the command you ran right before the failure. + +## Reviewer Notes +β€” + +## Post Result +https://github.com/bradygaster/squad/issues/426#issuecomment-123456 ``` ### T1 β€” Welcome From 3f6bc4584dff96cd5ad11df49ad761b84d02965f Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 05:34:18 -0700 Subject: [PATCH 5/8] =?UTF-8?q?fix:=20address=20team=20review=20round=204?= =?UTF-8?q?=20=E2=80=94=20example=20and=20template=20alignment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Post example includes all required fields (item_number, draft_id, reviewer) 2. Post example excludes Reviewer Notes (scoped to approve/edit/skip only) 3. Post Result placeholder text matches post/delete scoping 4. Template clarifies action-specific fields go in frontmatter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/templates/audit-entry.md | 5 +++-- .squad/skills/external-comms/SKILL.md | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md index 3f418b1b8..2bec18bff 100644 --- a/.squad/comms/templates/audit-entry.md +++ b/.squad/comms/templates/audit-entry.md @@ -4,7 +4,8 @@ action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expir --- > All other fields are conditional on the action type. See **Conditional Fields** table below. -> Include only the sections relevant to your action type. +> Frontmatter includes `timestamp` and `action` universally, plus any action-specific required fields from the table. +> Include only the body sections relevant to your action type. ## Context (draft, approve, edit, skip, post, delete actions) - Thread depth: {comment count} @@ -19,7 +20,7 @@ action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expir {any edits or comments from reviewer, or "β€”" if none} ## Post Result (post, delete actions) -{link to posted comment if posted, or "not posted" if skipped/halted} +{link to posted comment, or original URL if deleted} ## Conditional Fields diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md index 5203c1c4c..3d93db299 100644 --- a/.squad/skills/external-comms/SKILL.md +++ b/.squad/skills/external-comms/SKILL.md @@ -204,31 +204,31 @@ Confidence: 🟒 High | 🟑 Medium | πŸ”΄ Needs review Full drafts below β–Ό ``` -### Example audit entry +### Example audit entry (post action) ```markdown --- timestamp: "2026-03-16T21:30:00Z" action: "post" +item_number: 426 +draft_id: 1 +reviewer: "@bradygaster" --- -## Context +## Context (draft, approve, edit, skip, post, delete actions) - Thread depth: 3 - Response type: welcome - Confidence: 🟒 - Long thread flag: false -## Draft Content +## Draft Content (draft, edit, post actions) Thread: 3 comments, last activity 2026-03-16, reporter hit a preview-build regression after install. Hey @newdev! Welcome to Squad πŸ‘‹ Thanks for opening this. We reproduced the issue in preview builds and we're checking the regression point now. Let us know if you can share the command you ran right before the failure. -## Reviewer Notes -β€” - -## Post Result +## Post Result (post, delete actions) https://github.com/bradygaster/squad/issues/426#issuecomment-123456 ``` From c015ad9147e75a7748cd1af2f9cc9625ca83906f Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 05:56:33 -0700 Subject: [PATCH 6/8] chore: remove empty .gitkeep from PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit directory is runtime-only (gitignored) β€” no need for placeholder. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/audit/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .squad/comms/audit/.gitkeep diff --git a/.squad/comms/audit/.gitkeep b/.squad/comms/audit/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From 6fda725336d16ddb3d41f066697f1bad45b36603 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 06:04:58 -0700 Subject: [PATCH 7/8] chore: change safe word from 'pao halt' to 'banana' per Brady Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/comms/README.md | 2 +- .squad/comms/templates/review-state-schema.sql | 2 +- .squad/comms/tests/tone-validation-spec.md | 8 ++++---- .squad/skills/external-comms/SKILL.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.squad/comms/README.md b/.squad/comms/README.md index 8dd52f9e9..8359c476a 100644 --- a/.squad/comms/README.md +++ b/.squad/comms/README.md @@ -20,7 +20,7 @@ ## Safety -- `pao halt` β€” freezes all pending drafts +- `banana` β€” freezes all pending drafts (safe word) - Phase 1 is manual-trigger only - All responses require explicit human approval - Audit trail is append-only and runtime-only diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql index 952c35f5e..d49de8d11 100644 --- a/.squad/comms/templates/review-state-schema.sql +++ b/.squad/comms/templates/review-state-schema.sql @@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS draft_queue ( created_at TEXT NOT NULL DEFAULT (datetime('now')) ); --- Halt state (safe word mechanism) +-- Halt state (safe word "banana" mechanism) CREATE TABLE IF NOT EXISTS halt_state ( id INTEGER PRIMARY KEY CHECK (id = 1), halted INTEGER NOT NULL DEFAULT 0, diff --git a/.squad/comms/tests/tone-validation-spec.md b/.squad/comms/tests/tone-validation-spec.md index e96c9fbc9..4e8edd5d9 100644 --- a/.squad/comms/tests/tone-validation-spec.md +++ b/.squad/comms/tests/tone-validation-spec.md @@ -57,8 +57,8 @@ Drafts of specific types MUST contain these patterns: | T5.2 | `pao approve` command without draft ID | Error message | | T5.3 | Concurrent review sessions | SQLite lock prevents race | | T5.4 | Stale lock (>1 hour) | Auto-cleanup, new session allowed | -| T5.5 | `pao halt` issued | All pending drafts frozen | -| T5.6 | `pao resume` after halt | Drafts unfrozen | +| T5.5 | `banana` issued (safe word) | All pending drafts frozen | +| T5.6 | `pao resume` after banana | Drafts unfrozen | ### T6: Audit Trail Completeness @@ -69,7 +69,7 @@ Drafts of specific types MUST contain these patterns: | T6.3 | Draft approved | approve action with reviewer | | T6.4 | Draft skipped | skip action with reviewer | | T6.5 | Response posted | post action with URL | -| T6.6 | `pao halt` issued | halt action with issuer | +| T6.6 | `banana` issued (safe word) | halt action with issuer | | T6.7 | Draft deleted (rollback) | delete action with reason | ### T7: Baseline Comparison (Weekly) @@ -150,5 +150,5 @@ Before launch, ALL of the following must be true: - [ ] Rollback workflow (delete-and-repost) tested end-to-end - [ ] Review gate SQLite schema tested with concurrent access - [ ] Audit trail format validated against template -- [ ] `pao halt` / `pao resume` flow tested end-to-end +- [ ] `banana` / `pao resume` flow tested end-to-end - [ ] At least one full scanβ†’draftβ†’reviewβ†’post cycle completed successfully diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md index 3d93db299..9ac372dca 100644 --- a/.squad/skills/external-comms/SKILL.md +++ b/.squad/skills/external-comms/SKILL.md @@ -142,7 +142,7 @@ Wait for explicit human direction before anything is posted. - `pao approve 1 3` β€” approve drafts 1 and 3 - `pao edit 2` β€” edit draft 2 - `pao skip` β€” skip all -- `pao halt` β€” freeze all pending (safe word) +- `banana` β€” freeze all pending (safe word) ### Rollback β€” Bad Post Recovery @@ -155,7 +155,7 @@ If a posted response turns out to be wrong, inappropriate, or needs correction: 3. **Draft replacement** (if needed): PAO drafts a corrected response, goes through normal review cycle 4. **Postmortem:** If the error reveals a pattern gap, update humanizer anti-patterns or add a new test case -**Safe word β€” `pao halt`:** +**Safe word β€” `banana`:** - Immediately freezes all pending drafts in the review queue - No new scans or drafts until `pao resume` is issued - Audit entry logged with halter identity and reason From 22a8c6964dbfdaff68999435a96dd27e9a6bb4b2 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 10:28:41 -0700 Subject: [PATCH 8/8] docs: add agent on-disk anatomy concept doc Developer-oriented guide explaining: - Directory structure (.squad/agents/{name}/) - charter.md format and parsing - history.md append-only learnings - Casting system (registry, policy, history) - Relationship between .squad/ runtime and SDK source - How an agent 'exists' (charter + roster + routing) - Alumni pattern for retired agents - Cross-agent context propagation Requested by Brady via Dina. Addresses the question: 'What does it mean on disk to be a Squad agent?' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/concepts/agent-on-disk.md | 394 +++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 docs/concepts/agent-on-disk.md diff --git a/docs/concepts/agent-on-disk.md b/docs/concepts/agent-on-disk.md new file mode 100644 index 000000000..e3a425c71 --- /dev/null +++ b/docs/concepts/agent-on-disk.md @@ -0,0 +1,394 @@ +# What It Means on Disk to Be a Squad Agent + +> Developer-oriented concept doc: the on-disk anatomy of a Squad agent + +## Overview + +A Squad agent is not a single file or code module. It's a **distributed identity** spanning three layers: + +1. **Runtime state** β€” `.squad/` directory (team-specific, git-committed) +2. **SDK infrastructure** β€” `packages/squad-sdk/src/agents/` (compiled code) +3. **Configuration** β€” `squad.config.ts` or `squad.config.json` (optional overrides) + +This doc explains how these layers work together to create an agent that can be spawned, collaborate, and accumulate knowledge over time. + +## Directory Structure + +Each agent exists in `.squad/agents/{name}/`: + +``` +.squad/ +└── agents/ + β”œβ”€β”€ flight/ + β”‚ β”œβ”€β”€ charter.md # Agent's identity, boundaries, voice + β”‚ └── history.md # Append-only learnings (optional) + β”œβ”€β”€ capcom/ + β”‚ └── charter.md + β”œβ”€β”€ scribe/ + β”‚ └── charter.md + └── _alumni/ + └── verbal/ # Retired agents live here + └── charter.md +``` + +### Key Files + +#### `charter.md` β€” The Agent's DNA + +**Who writes it:** The team (usually via a specialist like Procedures, or manually by the team owner). + +**Who reads it:** The SDK's charter compiler (`charter-compiler.ts`) at agent spawn time. + +**What it contains:** + +```markdown +# {Name} β€” {Role} + +> {One-line personality statement} + +## Identity +- **Name:** Flight +- **Role:** Lead +- **Expertise:** Product vision, architecture, code review +- **Style:** Decisive. Opinionated when it matters. + +## What I Own +- Product direction and architectural decisions +- Code review and quality gates + +## How I Work +- Architecture decisions compound +- Proposal-first: meaningful changes need docs/proposals/ before code + +## Boundaries +**I handle:** Architecture, product direction, code review, scope. +**I don't handle:** Implementation details, test writing, docs, distribution. + +## Model +Preferred: auto +``` + +**Parsed sections:** +- **Identity** β†’ `name`, `role`, `expertise`, `style` +- **What I Own** β†’ `ownership` (plain text) +- **Boundaries** β†’ `boundaries` (plain text) +- **Model** β†’ `modelPreference`, `modelRationale`, `modelFallback` + +The charter is compiled into a `SquadCustomAgentConfig` object that includes: +- The full charter content as the agent's system prompt +- Parsed metadata (name, role, model preference) +- Team context (from `team.md`, `routing.md`, `decisions.md`) + +**Format expectations:** +- Markdown headings (`## `) structure the charter +- The SDK parses specific sections by heading name +- Freeform content is preserved and passed to the LLM +- Personality and voice matter β€” agents have opinions + +#### `history.md` β€” Append-Only Learnings + +**Who writes it:** The agent itself, after completing work. + +**Who reads it:** The agent, before starting new work (via the charter compiler's history shadow feature). + +**What it contains:** + +```markdown +# Flight β€” Project History + +> Knowledge accumulated through leading Squad development. + +## Core Context + +Three-branch model (main/dev/insiders). Apollo 13 team, 3931 tests. +Boundary review heuristic: "Squad Ships It" β€” if Squad doesn't ship +the code, it's IRL content. + +## Learnings + +### Adoption Tracking Architecture +Three-tier opt-in system: Tier 1 (aggregate-only, `.github/adoption/`) +ships first; Tier 2 (opt-in registry) designed next; Tier 3 (public +showcase) launches when β‰₯5 projects opt in. + +### Remote Squad Access +Three-phase rollout: Phase 1 β€” GitHub Discussions bot with `/squad` +command (1 day, zero hosting). Phase 2 β€” GitHub Copilot Extension via +Contents API (1 week). Phase 3 β€” Slack/Teams bot (2 weeks). +``` + +**What goes in:** +- Context that persists across sessions (project patterns, established decisions) +- Learnings that inform future work (what worked, what didn't) +- Domain-specific knowledge accumulated over time + +**What doesn't go in:** +- Transient task state (use the session-scoped SQL database for that) +- Raw command output or logs (use `.squad/log/` for session logs) +- Decisions that affect other agents (those go in `.squad/decisions.md`) + +**Format:** +- Top-level `## Core Context` β€” stable facts +- Top-level `## Learnings` β€” append new `### ` blocks here +- No deletion β€” history is append-only + +### Alumni β€” The Retirement Pattern + +When an agent is no longer needed, it's moved to `.squad/agents/_alumni/{name}/`: + +``` +.squad/agents/_alumni/ +β”œβ”€β”€ verbal/ +β”‚ └── charter.md +β”œβ”€β”€ kobayashi/ +β”‚ └── charter.md +└── mcmanus/ + └── charter.md +``` + +**What happens on retirement:** +1. Agent directory moved from `.squad/agents/{name}/` to `.squad/agents/_alumni/{name}/` +2. Agent removed from `team.md` roster +3. Routing rules updated to remove agent from work assignments +4. Charter preserved for historical reference +5. Casting name returned to the pool (if using the casting system) + +Alumni agents cannot be spawned. Their charters are read-only archives. + +## The Casting System + +Squad uses a **thematic casting model** to assign memorable names from fictional universes. + +### Files + +#### `casting-registry.json` β€” Name Allocation + +```json +{ + "agents": { + "flight": { + "universe": "Apollo 13", + "character": "Flight Director", + "assigned": "2026-02-21T10:00:00Z" + } + } +} +``` + +**Purpose:** Tracks which names are in use, which universe they're from, and when they were assigned. + +**Who manages it:** The casting module (`packages/squad-sdk/src/casting/`). + +**Lifecycle:** +- Name allocated when agent created β†’ entry added +- Agent retired β†’ entry remains (name not reused within same universe) +- Universe exhausted β†’ new universe added to `casting-policy.json` + +#### `casting-policy.json` β€” Universe Rules + +```json +{ + "casting_policy_version": "1.1", + "allowlist_universes": [ + "The Usual Suspects", + "Reservoir Dogs", + "Alien", + "Ocean's Eleven" + ], + "universe_capacity": { + "The Usual Suspects": 6, + "Reservoir Dogs": 8, + "Alien": 8, + "Ocean's Eleven": 14 + } +} +``` + +**Purpose:** Defines which fictional universes are available and how many names each can provide. + +**Who manages it:** The team owner (manually edited when adding new universes). + +**Rules:** +- Each universe has a capacity limit (prevents name dilution) +- Names must be recognizable characters from that universe +- No universe mixing on the same team (maintains thematic coherence) + +#### `casting-history.json` β€” Audit Log + +```json +{ + "universe_usage_history": [ + { + "timestamp": "2026-02-21T10:00:00Z", + "universe": "Apollo 13", + "agent": "flight", + "character": "Flight Director", + "action": "assigned" + } + ], + "assignment_cast_snapshots": {} +} +``` + +**Purpose:** Immutable audit trail of all casting decisions. + +**Who writes it:** The casting module (append-only). + +**Why it matters:** Enables rollback, debugging, and understanding team evolution over time. + +## How an Agent "Exists" + +An agent is **active** when all three conditions are met: + +1. **Charter exists** β€” `.squad/agents/{name}/charter.md` is present +2. **Roster entry** β€” Agent listed in `team.md` with status `βœ… Active` or `πŸ“‹ Silent` +3. **Routing rules** β€” Agent appears in `routing.md` work assignments + +Without all three, the agent cannot be spawned. + +**Spawn flow:** + +``` +User request + ↓ +Coordinator reads routing.md + ↓ +Identifies agent to spawn (e.g., "flight") + ↓ +SDK reads .squad/agents/flight/charter.md + ↓ +SDK reads .squad/agents/flight/history.md (if exists) + ↓ +SDK reads .squad/team.md, routing.md, decisions.md + ↓ +Charter compiler builds SquadCustomAgentConfig + ↓ +SDK spawns agent with compiled prompt + ↓ +Agent runs, writes to history.md after work +``` + +## Relationship to SDK Source Files + +The `.squad/` directory is **runtime state**, not code. The SDK provides the **infrastructure** to load, parse, and execute agents: + +| SDK Module | Purpose | +|------------|---------| +| `packages/squad-sdk/src/agents/charter-compiler.ts` | Parses `charter.md` into `SquadCustomAgentConfig` | +| `packages/squad-sdk/src/agents/history-shadow.ts` | Loads `history.md` and injects into agent context | +| `packages/squad-sdk/src/agents/lifecycle.ts` | Agent spawn, session management, termination | +| `packages/squad-sdk/src/agents/model-selector.ts` | Resolves `## Model` preference to actual model | +| `packages/squad-sdk/src/casting/` | Name allocation, registry management | + +**Key insight:** The SDK never hardcodes agent names or roles. It's a generic **agent runtime**. All specificity lives in `.squad/`. + +This means: +- You can add new agents without changing SDK code +- Multiple projects using the same SDK have different teams +- Agents can be dynamically added, retired, or renamed + +## What About `squad.config.ts`? + +The optional `squad.config.ts` file provides **overrides** for charter-based agents: + +```typescript +export default { + agents: { + flight: { + model: 'gpt-4.1', // Override charter's "Preferred: auto" + tools: ['read', 'write'], // Restrict tool access + extraPrompt: 'Focus on performance trade-offs.' // Append to charter + } + } +} +``` + +**Merge order (config wins on conflict):** +1. Charter parsed β†’ base `SquadCustomAgentConfig` +2. Config overrides applied β†’ merged `SquadCustomAgentConfig` +3. Team context injected β†’ final prompt sent to LLM + +This allows: +- Per-environment tuning (staging vs production) +- Temporary restrictions (disable tools during testing) +- A/B testing different prompts without editing charters + +## Cross-Agent Context Propagation + +Agents don't share memory. Context flows via **explicit artifacts**: + +### `team.md` β€” Shared Roster +All agents read this to know who else exists and what they do. + +### `routing.md` β€” Work Assignment Rules +Defines which agent handles which type of work. Coordinator uses this to route requests. + +### `decisions.md` β€” Canonical Decisions Log +All agents read this before starting work. It's the shared memory. + +### `.squad/decisions/inbox/` β€” Decision Drop-Box +Agents write decisions here. Scribe merges them into `decisions.md`. + +**Flow:** + +``` +Flight makes a decision + ↓ +Flight writes .squad/decisions/inbox/flight-api-versioning.md + ↓ +Scribe (background agent) runs + ↓ +Scribe reads inbox, appends to decisions.md, deletes inbox file + ↓ +CAPCOM starts work, reads decisions.md + ↓ +CAPCOM sees Flight's decision, respects it +``` + +### `.squad/log/` β€” Session Logs +Scribe writes session summaries here. Useful for auditing and debugging. + +**Example log file:** + +``` +.squad/log/2026-03-16T10-00-00-feature-adoption-tracking.md +``` + +Contains: +- Who worked +- What was done +- Decisions made +- Key outcomes + +## Key Takeaways + +1. **An agent is a directory** β€” `.squad/agents/{name}/` with at least `charter.md`. +2. **Charter is the source of truth** β€” defines identity, boundaries, voice. +3. **History is optional** β€” but recommended for agents doing repeated work. +4. **Casting adds personality** β€” thematic names make agents memorable. +5. **SDK is generic infrastructure** β€” no agent-specific code in the runtime. +6. **Context flows via files** β€” `team.md`, `routing.md`, `decisions.md`, `.squad/log/`. +7. **Retirement is move + remove** β€” alumni live in `_alumni/`, can't be spawned. + +## Developer Checklist: Creating a New Agent + +- [ ] Create `.squad/agents/{name}/` directory +- [ ] Write `charter.md` using `.squad/templates/charter.md` as reference +- [ ] Add agent to `team.md` roster with status `βœ… Active` +- [ ] Add agent to `routing.md` with work type assignments +- [ ] (Optional) Allocate name via casting system +- [ ] (Optional) Create `history.md` if agent needs persistent memory +- [ ] Test spawn: `squad spawn {name} "Hello, world"` + +## Further Reading + +- **Charter format reference:** `.squad/templates/charter.md` +- **Roster format reference:** `.squad/templates/roster.md` +- **SDK agent infrastructure:** `packages/squad-sdk/src/agents/` +- **Casting system design:** `packages/squad-sdk/src/casting/` + +--- + +**Author:** Flight +**Requested by:** Dina (via Brady) +**Date:** 2026-03-16