diff --git a/.squad/agents/_alumni/mcmanus/charter.md b/.squad/agents/_alumni/mcmanus/charter.md index b6a722845..9caebe9ec 100644 --- a/.squad/agents/_alumni/mcmanus/charter.md +++ b/.squad/agents/_alumni/mcmanus/charter.md @@ -16,6 +16,9 @@ - Demos and examples - Tone review and messaging - i18n patterns +- External community responses (draft-only, human review gate) +- Tone enforcement via humanizer skill +- Community signal aggregation (unanswered issues → product signals) ## How I Work @@ -23,11 +26,15 @@ - Celebration blog structure: wave:null, parallel narrative - docs/proposals/ pattern: proposals before execution - Every public-facing statement must be substantiated -- **DOCS-TEST SYNC (hard rule):** When I add new docs pages (blog posts, guide pages, etc.), I MUST update the corresponding test assertions in test/docs-build.test.ts — specifically EXPECTED_GUIDES, EXPECTED_BLOG, and similar arrays. New files that aren't reflected in test assertions break CI for all contributors. Check the test file before committing any new docs page. +- - **DOCS-TEST SYNC (hard rule):** When I add new docs pages (blog posts, guide pages, etc.), I MUST update the corresponding test assertions in test/docs-build.test.ts — specifically EXPECTED_GUIDES, EXPECTED_BLOG, and similar arrays. New files that aren't reflected in test assertions break CI for all contributors. Check the test file before committing any new docs page. +- - **EXTERNAL COMMS (hard rule):** NEVER post community responses autonomously. All responses are drafted, presented in a review table with confidence flags, and require explicit human approval before posting. +- **HUMANIZER (hard rule):** All external-facing content must pass tone validation — warm, helpful, human-sounding. No corporate speak, no marketing hype, no empty acknowledgments. +- **AUDIT TRAIL (hard rule):** Every draft-review-post action is logged to `.squad/comms/audit/`. The audit log is append-only. + ## Boundaries -**I handle:** Documentation, demos, messaging, tone review, developer experience, i18n. +**I handle:** README, API docs, demos, examples, tone review, community messaging, contributor recognition, external community response drafting (with human review gate). **I don't handle:** Runtime implementation, architecture decisions, security, distribution mechanics. diff --git a/.squad/agents/eecom/history.md b/.squad/agents/eecom/history.md index 87425dcc0..b4007c402 100644 --- a/.squad/agents/eecom/history.md +++ b/.squad/agents/eecom/history.md @@ -80,6 +80,25 @@ CLI completeness audit (2026-03-08) confirmed: 26 primary commands routed in cli **PR:** #417 opened targeting dev. + +### PR #427 Cross-Fork Rebase (2026-03-15T21:00:00Z) + +**Context:** PR #427 (PAO external communications Phase 1) conflicted with upstream/dev after team recast (#423 Usual Suspects → Apollo 13) and model updates. Cross-repo PR (diberry/squad → bradygaster/squad). Initial rebase attempts failed due to git worktree confusion — main worktree was checked out to a different branch, causing git checkout commands to silently switch to wrong branches. + +**Problem:** Git commands (checkout, rebase) kept switching to unrelated branches (squad/agent-on-disk-concept, squad/320-fix-migration-guide-version-local) mid-rebase. Root cause: main worktree at C:\Users\diberry\repos\project-squad\squad was checked out to squad/agent-on-disk-concept. Git was treating checkout commands as worktree operations and switching the main worktree's HEAD, aborting the rebase. + +**Solution:** Created dedicated worktree (.worktrees/pao-rebase) for the rebase operation. This isolated the rebase from main worktree state and prevented branch switching. + +**Conflict Resolution (3 files, 7 commits rebased):** +1. **.squad/agents/_alumni/mcmanus/charter.md** - Merged both rule sets: DOCS-TEST SYNC (from upstream reskill) and EXTERNAL COMMS, HUMANIZER, AUDIT TRAIL (from PR #427). Used PowerShell regex to extract and combine both sides. +2. **.squad/routing.md** - Accepted Apollo 13 team names (EECOM, PAO, FIDO) from upstream via `git checkout --ours` (in rebase context, "ours" = upstream, "theirs" = our branch). PAO external comms infrastructure is team-agnostic. +3. **.squad/agents/keaton/history.md** - Accepted deletion via `git rm` (file moved to _alumni in upstream recast). + +**Rebase Commits:** 7 commits from squad/426-pao-external-comms rebased onto upstream/dev (f87a7a5), covering #423 team reskill, #424 SDK switch, #425/#428 test parity, #429 model updates. + +**Force Push:** `git push origin squad/426-pao-external-comms --force-with-lease` succeeded. PR #427 comment posted via gh CLI. + +**Pattern:** When working with git worktrees, always create a dedicated worktree for complex operations (rebase, cherry-pick) to avoid main worktree state interference. Use `git worktree list` to diagnose unexpected branch switching. ### Adoption Tracking Tier 1 Implementation (2026-03-10) Implemented Flight's privacy-first adoption monitoring strategy on PR #326 branch. Moved `.squad/adoption/` → `.github/adoption/` for better GitHub integration. Stripped tracking.md to aggregate-only metrics (removed all individual repo names/URLs). Updated GitHub Action workflow (adoption-report.yml) and monitoring script (scripts/adoption-monitor.mjs) to write reports to `.github/adoption/reports/`. Removed "Built with Squad" showcase link from README.md (deferred to Tier 2 opt-in feature). This honors the principle: collect aggregate metrics via public APIs, but never publish individual repo lists without explicit consent. Test discipline: verified npm run build passes; docs-build.test.ts passed structure tests (Astro build failure unrelated to changes). Committed with clear message explaining privacy rationale. diff --git a/.squad/comms/.gitignore b/.squad/comms/.gitignore new file mode 100644 index 000000000..1313383b1 --- /dev/null +++ b/.squad/comms/.gitignore @@ -0,0 +1,7 @@ +# Runtime state (not committed) +review-state.db +review-state.db-journal +review-state.db-wal +review-state.db-shm +audit/ +!audit/.gitkeep diff --git a/.squad/comms/README.md b/.squad/comms/README.md new file mode 100644 index 000000000..8359c476a --- /dev/null +++ b/.squad/comms/README.md @@ -0,0 +1,27 @@ +# PAO External Communications + +> Phase 1: Manual-trigger, draft-only mode with human review gate. + +## Directory Structure + +- `audit/` — Runtime-only audit trail for every draft-review-post action (not committed to git; keep `audit/.gitkeep`) +- `review-state.db` — SQLite-based single-reviewer lease and draft state (created at runtime) +- `templates/` — Response templates for common scenarios +- `tests/` — Comms workflow and review-state coverage + +## Workflow + +1. Human manually triggers PAO to scan issues and discussions for unanswered items +2. PAO drafts responses using humanizer skill +3. PAO presents review table with confidence flags +4. Human reviews, approves/edits/skips each draft +5. Human posts approved responses +6. Every action is logged to runtime-only `audit/` + +## Safety + +- `banana` — freezes all pending drafts (safe word) +- Phase 1 is manual-trigger only +- All responses require explicit human approval +- Audit trail is append-only and runtime-only +- SQLite lease prevents concurrent review race conditions diff --git a/.squad/comms/templates/audit-entry.md b/.squad/comms/templates/audit-entry.md new file mode 100644 index 000000000..2bec18bff --- /dev/null +++ b/.squad/comms/templates/audit-entry.md @@ -0,0 +1,41 @@ +--- +timestamp: "{ISO-8601}" +action: "scan|draft|approve|edit|skip|post|halt|resume|delete|lint_failure|expire" +--- + +> All other fields are conditional on the action type. See **Conditional Fields** table below. +> Frontmatter includes `timestamp` and `action` universally, plus any action-specific required fields from the table. +> Include only the body sections relevant to your action type. + +## Context (draft, approve, edit, skip, post, delete actions) +- Thread depth: {comment count} +- Response type: {welcome|troubleshooting|feature-guidance|redirect|acknowledgment|closing|technical-uncertainty|empathetic-disagreement|information-request} +- Confidence: {🟢|🟡|🔴} +- Long thread flag: {true|false} + +## Draft Content (draft, edit, post actions) +{full draft text} + +## Reviewer Notes (approve, edit, skip actions) +{any edits or comments from reviewer, or "—" if none} + +## Post Result (post, delete actions) +{link to posted comment, or original URL if deleted} + +## Conditional Fields + +Not all fields apply to every action. The `outcome` value is contextual per action: + +| Action | Required Fields | Outcome Value | Optional Fields | +|--------|----------------|---------------|-----------------| +| scan | timestamp, action | item count found (e.g., "5 candidates") | — | +| draft | timestamp, action, item_type, item_number, draft_id, confidence, draft_content | — (no outcome for draft) | thread_depth | +| approve | timestamp, action, draft_id, reviewer | "approved" | reviewer_notes | +| edit | timestamp, action, draft_id, reviewer, draft_content | "edited" | reviewer_notes | +| skip | timestamp, action, draft_id, reviewer | "skipped" | reviewer_notes | +| post | timestamp, action, item_number, draft_id, reviewer | "posted" + post_result link | — | +| halt | timestamp, action, reviewer (halter) | "halted" | reason | +| resume | timestamp, action, reviewer (resumer) | "resumed" | — | +| delete | timestamp, action, item_number | "deleted" + original URL | reason | +| lint_failure | timestamp, action, draft_id | violation details (free text) | — | +| expire | timestamp, action, draft_id | "expired" | — | diff --git a/.squad/comms/templates/review-state-schema.sql b/.squad/comms/templates/review-state-schema.sql new file mode 100644 index 000000000..d49de8d11 --- /dev/null +++ b/.squad/comms/templates/review-state-schema.sql @@ -0,0 +1,72 @@ +-- Runtime reminder: PRAGMA foreign_keys = ON; +-- PAO External Communications: Review State Database +-- Created at runtime in .squad/comms/review-state.db +-- Zero new dependencies (Copilot CLI already uses SQLite) + +-- Single global review lease — only ONE reviewer at a time +CREATE TABLE IF NOT EXISTS review_lease ( + id INTEGER PRIMARY KEY CHECK (id = 1), + status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'held')), + reviewer TEXT, + hostname TEXT, + pid INTEGER, + acquired_at TEXT, + expires_at TEXT +); + +-- Initialize the single lease row +INSERT OR IGNORE INTO review_lease (id, status) VALUES (1, 'available'); + +-- Acquire: UPDATE review_lease +-- SET status = 'held', reviewer = ?, hostname = ?, pid = ?, acquired_at = datetime('now'), expires_at = datetime('now', '+1 hour') +-- WHERE id = 1 AND (status = 'available' OR expires_at < datetime('now')); +-- Release: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1; +-- Check: SELECT * FROM review_lease WHERE id = 1; +-- Cleanup expired lease before work: UPDATE review_lease +-- SET status = 'available', reviewer = NULL, hostname = NULL, pid = NULL, acquired_at = NULL, expires_at = NULL +-- WHERE id = 1 AND status = 'held' AND expires_at < datetime('now'); + +-- Draft tracking table +CREATE TABLE IF NOT EXISTS draft_queue ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + reviewer TEXT, + item_type TEXT NOT NULL CHECK (item_type IN ('issue', 'discussion')), + item_number INTEGER NOT NULL, + item_url TEXT, + response_type TEXT NOT NULL, + confidence TEXT NOT NULL CHECK (confidence IN ('high', 'medium', 'low')), + draft_content TEXT NOT NULL, + thread_depth INTEGER DEFAULT 0, + long_thread_flag INTEGER DEFAULT 0, + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'edited', 'skipped', 'posted', 'halted', 'deleted')), + reviewed_at TEXT, + posted_url TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')) +); + +-- Halt state (safe word "banana" mechanism) +CREATE TABLE IF NOT EXISTS halt_state ( + id INTEGER PRIMARY KEY CHECK (id = 1), + halted INTEGER NOT NULL DEFAULT 0, + halted_by TEXT, + halted_at TEXT, + reason TEXT +); + +-- Initialize halt state (not halted by default) +INSERT OR IGNORE INTO halt_state (id, halted) VALUES (1, 0); + +-- Audit log (append-only, mirrors runtime audit files) +CREATE TABLE IF NOT EXISTS audit_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL DEFAULT (datetime('now')), + action TEXT NOT NULL, + item_type TEXT, + item_number INTEGER, + draft_id INTEGER, + reviewer TEXT, + outcome TEXT, + details TEXT +); diff --git a/.squad/comms/templates/tone-validation.json b/.squad/comms/templates/tone-validation.json new file mode 100644 index 000000000..c66625fc3 --- /dev/null +++ b/.squad/comms/templates/tone-validation.json @@ -0,0 +1,88 @@ +{ + "version": 1, + "description": "Tone validation patterns for PAO external communications", + "reject_patterns": [ + { + "id": "corporate-speak", + "pattern": "(?:[Ww]e appreciate your patience|[Pp]lease be advised|[Pp]er our discussion|[Aa]s per|[Kk]indly note|[Pp]lease do not hesitate)", + "message": "Corporate speak detected. Use conversational tone instead." + }, + { + "id": "passive-voice-formal", + "pattern": "(?:[Ii]t has been determined|[Ii]t was decided|[Hh]as been escalated|[Ii]s being investigated|[Hh]as been noted)", + "message": "Formal passive voice detected. Use active voice: 'We determined...' or 'We're looking into...'" + }, + { + "id": "marketing-hype", + "pattern": "(?:[Bb]est[- ]in[- ]class|[Cc]utting[- ]edge|[Rr]evolutionary|[Gg]ame[- ]changing|[Ii]ndustry[- ]leading|[Nn]ext[- ]generation|[Aa]mazing feature)", + "message": "Marketing hype detected. Be specific about what the feature does, not how great it is." + }, + { + "id": "empty-acknowledgment", + "pattern": "^\\s*(?:[Tt]hanks for your feedback\\.?|[Tt]hank you for reaching out\\.?)\\s*$", + "message": "Empty acknowledgment without substance. Add specific context or next steps." + }, + { + "id": "robot-signature", + "pattern": "(?:[Bb]est regards|[Ss]incerely|[Kk]ind regards|[Rr]espectfully|[Ww]arm regards)\\s*[,.]?\\s*(?:[Pp][Aa][Oo]|[Tt]he [Ss]quad [Tt]eam|[Ss]quad [Bb]ot)", + "message": "Robot signature detected. Responses should end naturally, not with formal sign-offs." + }, + { + "id": "over-promising", + "pattern": "(?:[Ww]e will ship|[Ww]e'll release|[Cc]oming soon|[Ii]n the next release|[Dd]efinitely fix|[Gg]uaranteed)", + "message": "Over-promising detected. Only commit to what the team has explicitly agreed to." + }, + { + "id": "dismissive", + "pattern": "(?:[Ww]orks as designed|[Nn]ot a bug|[Ww]on't fix|[Tt]hat's expected|[Uu]ser error)", + "message": "Dismissive language detected. Acknowledge the experience before explaining the design." + }, + { + "id": "profanity", + "pattern": "\\b(?:[Dd]amn|[Hh]ell|[Cc]rap|[Ss]hit|[Ff]uck|[Aa]ss|[Bb]astard|[Bb]itch)\\b", + "message": "Profanity detected. Never include profanity, even when quoting." + } + ], + "require_patterns": [ + { + "id": "acknowledgment", + "pattern": "(?:[Tt]hanks|[Tt]hank you|[Gg]ood catch|[Gg]reat question|[Ii]nteresting|[Aa]ppreciate|[Ww]elcome)", + "message": "Response should include acknowledgment of the author's contribution.", + "applies_to": ["welcome", "troubleshooting", "acknowledgment"] + }, + { + "id": "action-oriented", + "pattern": "(?:[Ll]et us know|[Ff]eel free|[Hh]appy to help|[Ww]e'll update|[Rr]each out|[Ww]e'll dig|[Kk]eep us posted)", + "message": "Response should end with an action-oriented close.", + "applies_to": ["troubleshooting", "feature-guidance", "technical-uncertainty"] + }, + { + "id": "context-provided", + "pattern": "(?:[Cc]urrently|[Rr]ight now|[Aa]t the moment|[Aa]s of|[Tt]he way it works)", + "message": "Feature guidance should provide context on current state.", + "applies_to": ["feature-guidance"] + }, + { + "id": "uncertainty-honest", + "pattern": "(?:[Nn]ot sure|[Nn]ot 100%|[Dd]on't know yet|[Ss]till investigating|[Uu]nclear|[Hh]aven't determined)", + "message": "Technical uncertainty should be honest about unknowns.", + "applies_to": ["technical-uncertainty"] + } + ], + "confidence_thresholds": { + "high": { + "description": "Answered before, clear docs, community consensus", + "min_similarity": 0.8, + "baseline_blocking": true + }, + "medium": { + "description": "Technically sound but minor uncertainty or tone-dependent", + "min_similarity": 0.6 + }, + "low": { + "description": "Technical uncertainty, policy decision, reputational risk", + "min_similarity": 0.0, + "requires_review": true + } + } +} diff --git a/.squad/comms/tests/ci-gate.md b/.squad/comms/tests/ci-gate.md new file mode 100644 index 000000000..ba9f658e3 --- /dev/null +++ b/.squad/comms/tests/ci-gate.md @@ -0,0 +1,54 @@ +# CI Tone Lint Gate + +> Automated quality checks for PAO community response drafts. + +## When This Runs + +- Before any draft enters the review table +- As part of PR review when modifying humanizer or external-comms skills +- Weekly tone analytics (manual trigger via `pao analytics`) + +## Checks + +### Mandatory (blocks draft) + +1. **Anti-pattern scan** — Run all `reject_patterns` from `tone-validation.json` against draft +2. **Profanity filter** — Zero tolerance, even in quotes +3. **Minimum substance** — Draft must be >50 characters (no empty acknowledgments) +4. **Thread read verification** — Confirm all comments in thread were read before drafting + +### Mandatory for High-Confidence Drafts (🟢 only) + +5. **Baseline similarity** — Block if tone similarity to gold standard <80% for high-confidence (🟢) drafts. Aligns with `baseline_blocking: true` in `tone-validation.json`. + +### Warning (flags but doesn't block) + +1. **Positive pattern check** — Warn if response type should contain patterns from `require_patterns` +2. **Length check** — Warn if draft >500 words (may be too verbose for a GitHub comment) +3. **Emoji count** — Warn if >2 emoji in draft +4. **Similarity check** — Warn if tone similarity to gold standard <80% for medium/low-confidence drafts + +### Informational + +1. **Response type classification** — Log which template was used +2. **Confidence level** — Log confidence flag and rationale +3. **Thread depth** — Log comment count for analytics + +## Output Format + +``` +✅ PASS: Anti-pattern scan (0 violations) +✅ PASS: Profanity filter (clean) +✅ PASS: Minimum substance (127 chars) +⚠️ WARN: Positive pattern — missing action-oriented close +⚠️ WARN: Similarity to GS-2: 72% (threshold: 80%) +ℹ️ INFO: Response type: troubleshooting | Confidence: 🟡 | Thread: 4 comments +``` + +## Failure Mode + +If ANY mandatory check fails: +1. Draft is NOT added to review table +2. Error message shown to PAO with specific violation +3. PAO must redraft before presenting to reviewer +4. Failure logged to audit trail (action: "lint_failure") diff --git a/.squad/comms/tests/tone-validation-spec.md b/.squad/comms/tests/tone-validation-spec.md new file mode 100644 index 000000000..4e8edd5d9 --- /dev/null +++ b/.squad/comms/tests/tone-validation-spec.md @@ -0,0 +1,154 @@ +# Tone Validation Test Specification + +> Quality gates for PAO's external communications. All tests must pass before a draft enters the review table. + +## Test Categories + +### T1: Reject Anti-Patterns + +Drafts containing these patterns MUST be rejected: + +| Test ID | Pattern | Example (should FAIL) | +|---------|---------|----------------------| +| T1.1 | Corporate speak | "We appreciate your patience as we investigate this matter" | +| T1.2 | Formal passive voice | "It has been determined that this is a known issue" | +| T1.3 | Marketing hype | "Squad is the best-in-class solution for this" | +| T1.4 | Empty acknowledgment | "Thanks for your feedback." (with nothing else) | +| T1.5 | Robot signature | "Best regards, PAO" | +| T1.6 | Over-promising | "We'll definitely ship this in the next release" | +| T1.7 | Dismissive language | "Works as designed" (without empathy) | +| T1.8 | Profanity | Any profanity, even quoted from the original issue | + +### T2: Require Positive Patterns + +Drafts of specific types MUST contain these patterns: + +| Test ID | Response Type | Required Pattern | Example (should PASS) | +|---------|---------------|-----------------|----------------------| +| T2.1 | Welcome | Author acknowledgment | "Hey @user! Welcome to Squad 👋" | +| T2.2 | Troubleshooting | Action-oriented close | "Let us know if that helps!" | +| T2.3 | Feature guidance | Context on current state | "Currently, Squad handles this by..." | +| T2.4 | Technical uncertainty | Honesty about unknowns | "We're not 100% sure yet..." | + +### T3: Confidence Flag Accuracy + +| Test ID | Scenario | Expected Confidence | +|---------|----------|-------------------| +| T3.1 | Issue matches existing FAQ | 🟢 High | +| T3.2 | Technical question with partial docs | 🟡 Medium | +| T3.3 | Architecture question requiring Flight | 🔴 Needs review | +| T3.4 | Question about unreleased feature | 🔴 Needs review | +| T3.5 | Simple "how to install" question | 🟢 High | + +### T4: Thread Safety + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T4.1 | Thread with >10 comments | ⚠️ Long thread flag set | +| T4.2 | Thread with deleted comments | Validation warning | +| T4.3 | Thread where squad member already responded | Skip (no draft) | +| T4.4 | Thread in different language | Flag for review | + +### T5: Review Gate Enforcement + +| Test ID | Scenario | Expected Behavior | +|---------|----------|------------------| +| T5.1 | Draft without human review | BLOCKED — cannot post | +| T5.2 | `pao approve` command without draft ID | Error message | +| T5.3 | Concurrent review sessions | SQLite lock prevents race | +| T5.4 | Stale lock (>1 hour) | Auto-cleanup, new session allowed | +| T5.5 | `banana` issued (safe word) | All pending drafts frozen | +| T5.6 | `pao resume` after banana | Drafts unfrozen | + +### T6: Audit Trail Completeness + +| Test ID | Action | Expected Audit Entry | +|---------|--------|---------------------| +| T6.1 | Scan completed | scan action with item count | +| T6.2 | Draft created | draft action with content | +| T6.3 | Draft approved | approve action with reviewer | +| T6.4 | Draft skipped | skip action with reviewer | +| T6.5 | Response posted | post action with URL | +| T6.6 | `banana` issued (safe word) | halt action with issuer | +| T6.7 | Draft deleted (rollback) | delete action with reason | + +### T7: Baseline Comparison (Weekly) + +| Test ID | Metric | Threshold | Frequency | +|---------|--------|-----------|-----------| +| T7.1 | Tone similarity to gold standard | >80% | Per draft | +| T7.2 | Response type distribution | No single type >60% | Weekly | +| T7.3 | Confidence flag distribution | 🔴 items <20% | Weekly | +| T7.4 | Average thread read depth | >95% of comments read | Per draft | + +## Gold Standard Responses + +The following 7 gold standard responses serve as the tone baseline. New drafts should align with this tone: + +### GS-1: Welcome (High confidence) +> Hey @newuser! Welcome to Squad 👋 Thanks for opening this — great first issue! +> +> To answer your question: Squad uses `.squad/team.md` to define your team roster. You can add members by editing that file directly or running `squad init`. +> +> Let us know if you hit any snags — happy to help! + +### GS-2: Troubleshooting (High confidence) +> Thanks for the detailed report, @reporter! +> +> This looks like it might be related to the casting registry not finding the universe file. Here's what we'd suggest: +> 1. Check that `.squad/casting/registry.json` exists and is valid JSON +> 2. Run `squad build` to regenerate from source +> 3. If that doesn't work, try deleting `.squad/casting/` and re-running `squad init` +> +> Let us know if that helps, or if you're seeing something different. + +### GS-3: Feature Guidance (Medium confidence) +> Great question! Right now, Squad handles cross-repo orchestration through the hub-and-spoke model — you'd have a central `.squad/` in one repo and reference it from others. +> +> We know this isn't ideal for every setup. There's been some discussion about making this more seamless (see #316 for the RFC). +> +> For now, the workaround is to use `squad export` to share config across repos. Hope that helps! + +### GS-4: Acknowledgment (High confidence) +> Good catch, @finder. We've confirmed this is a real issue with the session pool cleanup. +> +> It looks like sessions aren't being released when the adapter disconnects unexpectedly. We're tracking it and will update this thread when we have a fix. +> +> Thanks for flagging it — this one would have been hard to find without your repro steps! + +### GS-5: Technical Uncertainty (Low confidence) +> Interesting find, @explorer. We're not 100% sure what's causing this yet. +> +> Here's what we've ruled out: +> - It's not a casting issue (registry looks fine) +> - It's not a config issue (your squad.config.ts parses correctly) +> +> Could you share the output of `squad build --verbose`? That would help us narrow it down. We'll dig deeper and update this thread. + +### GS-6: Redirect (High confidence) +> Thanks for reaching out, @asker! This one is actually better suited for the Squad-IRL repo, which covers deployment patterns and infrastructure around Squad. +> +> You can open it here: https://github.com/bradygaster/Squad-IRL — they'll be able to help with the Terraform setup specifically. +> +> Feel free to link back to this thread for context! + +### GS-7: Closing (High confidence) +> This should be resolved in v0.8.22! 🎉 +> +> The fix was in PR #389 — the casting registry now handles universe overflow correctly when you have more than 15 agents. +> +> Thanks for reporting this, @reporter — your repro steps made this one easy to track down. Closing this out! + +## Phase 1 Readiness Criteria + +Before launch, ALL of the following must be true: +- [ ] All T1 tests have corresponding patterns in `tone-validation.json` +- [ ] All T2 tests verified against humanizer skill templates +- [ ] All 7 gold standard responses reviewed and approved by Brady or Dina +- [ ] All 9 response types have corresponding templates (7 original + empathetic disagreement + information request) +- [ ] Thread-read verification tested with threads of 1, 5, 10, and 20+ comments +- [ ] Rollback workflow (delete-and-repost) tested end-to-end +- [ ] Review gate SQLite schema tested with concurrent access +- [ ] Audit trail format validated against template +- [ ] `banana` / `pao resume` flow tested end-to-end +- [ ] At least one full scan→draft→review→post cycle completed successfully diff --git a/.squad/skills/external-comms/SKILL.md b/.squad/skills/external-comms/SKILL.md new file mode 100644 index 000000000..9ac372dca --- /dev/null +++ b/.squad/skills/external-comms/SKILL.md @@ -0,0 +1,329 @@ +--- +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 only ("PAO, check community") — no automated or Ralph-triggered activation in Phase 1. + +## 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. +- 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 + +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) +- 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. +- 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: + +```text +📝 PAO — Community Response Drafts +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +| # | 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. + +- `pao approve 1 3` — approve drafts 1 and 3 +- `pao edit 2` — edit draft 2 +- `pao skip` — skip all +- `banana` — 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:** + - 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 + +**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 + +### 6. Post + +After approval: + +- 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. + +### 7. Audit + +Log every action. + +- Location: `.squad/comms/audit/{timestamp}.md` +- 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 + +These are reusable templates. Keep the structure, replace placeholders, and adjust only where the thread requires it. + +### 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 | 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 + +Full drafts below ▼ +``` + +### Example audit entry (post action) + +```markdown +--- +timestamp: "2026-03-16T21:30:00Z" +action: "post" +item_number: 426 +draft_id: 1 +reviewer: "@bradygaster" +--- + +## Context (draft, approve, edit, skip, post, delete actions) +- Thread depth: 3 +- Response type: welcome +- Confidence: 🟢 +- Long thread flag: false + +## 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. + +## Post Result (post, delete actions) +https://github.com/bradygaster/squad/issues/426#issuecomment-123456 +``` + +### 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) +- ❌ 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) +- ❌ 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 new file mode 100644 index 000000000..4dbb854df --- /dev/null +++ b/.squad/skills/humanizer/SKILL.md @@ -0,0 +1,105 @@ +--- +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 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 in Phase 1 issues/discussions workflows. + +## 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) +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 + +### 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 +- ❌ Link-dumping: Pasting URLs without context ("See: https://...") +- ❌ Open-ended info requests: "Can you provide more information?" without specifying what information