From bd1e1bf740428378e9437b67d086f870f7aab9e1 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/_alumni/mcmanus/charter.md | 11 +- .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/skills/external-comms/SKILL.md | 155 ++++++++++++++++++ .squad/skills/humanizer/SKILL.md | 100 +++++++++++ 11 files changed, 650 insertions(+), 2 deletions(-) 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/_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/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/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 ad50dc402928cfc7b2a9c6729ebb01f49ca49cd6 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/skills/external-comms/SKILL.md | 181 ++++++++++++++++-- .squad/skills/humanizer/SKILL.md | 9 +- 8 files changed, 356 insertions(+), 137 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/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 f06a7d8e351442cd6da926b175e361cf888cc2e5 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 ea6661a3ef3cda7c600ae74ac1fc1f733c5b7821 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 3856b0dc425d617b838fb78e2e7c1ebede90e5fb 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 851da4d34614761423dd7f66944d43631cddf74c 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 9d5102bb70fd13bc1e14588cab8acac40d849d15 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 4e7af70735f705d70e259a5e2b62a60463b852fb Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 10:34:23 -0700 Subject: [PATCH 8/8] chore(eecom): update history with PR #427 rebase learning Documented git worktree conflict resolution pattern for cross-fork rebase operations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .squad/agents/eecom/history.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.squad/agents/eecom/history.md b/.squad/agents/eecom/history.md index 51f9021d5..e52519489 100644 --- a/.squad/agents/eecom/history.md +++ b/.squad/agents/eecom/history.md @@ -80,3 +80,22 @@ 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.