Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ logs/
*.pem
*.key
secrets.yaml

# Ralph watch state (auto-generated, user-specific)
.squad/identity/.ralph-watch-state.json

azure-functions-eval/
transcript.json
azure-validate-eval/
Expand Down
24 changes: 24 additions & 0 deletions .squad/agents/linus/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,30 @@ All code roles now use `claude-opus-4.6`. Docs/Scribe/diversity use `gemini-3-pr
- **What:** Added `waza suggest <skill-path>` for LLM-driven eval generation. Command supports `--model`, `--dry-run` (default), `--apply`, `--output-dir`, and `--format yaml|json`. New `internal/suggest` package builds prompt context from SKILL.md + grader types + eval schema summary + example eval, parses structured YAML responses, validates generated `eval_yaml`, and writes `eval.yaml`/task/fixture files when applying.
- **Key learning:** A robust parser needs to handle both structured wrapper YAML (`eval_yaml` + files) and fenced YAML blocks from models. Validating generated `eval_yaml` against `models.BenchmarkSpec.Validate()` catches malformed model output early before writing files.

### Teams Notification Scripts
- **Date:** 2026-03-12
- **Files:** `.squad/scripts/teams-notify.sh`, `.squad/scripts/teams-test.sh`
- **What:** Created Teams notification script using `az rest` + Microsoft Graph API. Reads config from `.squad/identity/teams-config.json`. Supports 5 event types with per-event enable/disable. HTML-formatted messages with emoji headers. Graceful error handling (never exits non-zero). jq preferred, grep/sed fallback. Companion test script for verification.
- **Key learning:** `az rest` handles auth token injection automatically when hitting `graph.microsoft.com` — no manual token management needed. Using `jq -n --arg` for JSON body construction is essential to handle HTML content with special chars safely.

## Learnings
- Windows local test runs can fail in `cmd/waza/tokens/internal/git` when temporary repos inherit strict CRLF behavior; setting `core.autocrlf=false` and `core.safecrlf=false` inside test repo setup makes these tests cross-platform stable.
- PR conflict resolution for `copilot/migrate-copilot-client-usage` in `internal/execution/copilot_test.go` should keep the `TestCopilotExecute_InitializePropagatesStartError` variant from main to preserve startup error propagation coverage.
- Teams Graph API channel messages POST to `/v1.0/teams/{groupId}/channels/{channelId}/messages` with body `{body:{contentType:"html",content:"..."}}`. `az rest` auto-injects bearer tokens for graph.microsoft.com endpoints.
- Squad notification scripts live in `.squad/scripts/` and config in `.squad/identity/teams-config.json`. The notify script always exits 0 to be safe for caller pipelines.
- `gh api repos/:owner/:repo/compare/{base}...{head}` gives `ahead_by` count and per-commit author info — ideal for summarizing new commits without cloning or fetching refs locally.
- State-file-based deduplication (tracking known PR/issue numbers) is more reliable than timestamp-based filtering when GitHub API results may be paginated or delayed.

## 2026-03-12: Teams Notification System

Created `.squad/scripts/teams-notify.sh` and `.squad/scripts/teams-test.sh` for Microsoft Teams notifications via Graph API. System sends milestone updates (work batches, PRs, issues, decisions) to the "Waza Squad" Teams channel.

**Key decisions:** Always exit 0 (failures never block automation), jq with grep/sed fallback for JSON, HTML content escaping for security, config-driven event filtering, TEAM_ROOT auto-detection.

**Outcome:** Test notification verified in Teams channel. System ready for production use by Scribe and all agents.

### Ralph Watch — Local Watchdog (PR pending on squad/teams-notifications)
- **Date:** 2026-03-12
- **Files:** `.squad/scripts/ralph-watch.sh`, `.squad/skills/teams-notify/SKILL.md`
- **What:** Created local watchdog script that polls GitHub every N minutes (default 10) via `gh` CLI. Detects merged PRs, closed issues, and new commits on main. Calls `teams-notify.sh` for each new event. State tracked in `.squad/identity/.ralph-watch-state.json` to avoid duplicate notifications. First run seeds state from current repo activity. Graceful Ctrl+C shutdown with summary. Updated SKILL.md with watchdog documentation.
- **Key learning:** Using `gh api repos/:owner/:repo/compare` for commit diffs avoids needing local git state. State-file dedup by PR/issue number is more robust than timestamp filtering.
45 changes: 45 additions & 0 deletions .squad/agents/livingston/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,48 @@ All code roles now use `claude-opus-4.6`. Docs/Scribe/diversity use `gemini-3-pr
**Site build verified:** All 14 pages built successfully, ci-cd page included

**Branch:** squad/89-ci-integration-guide → PR to microsoft/waza main

## 📌 Skill Documentation: Teams Notifications (2026-03-12)

**Created:** `.squad/skills/teams-notify/SKILL.md`

**What the skill documents:**
The Teams notification system that the squad uses to communicate milestones to the "Waza Squad" Teams channel. Uses Microsoft Graph API via `az rest` (Azure CLI) — no Power Automate, no webhooks, no app registration.

**Key components documented:**
1. **Architecture** — Azure CLI (`az rest`) posts to Graph API, Scribe-driven
2. **Configuration** — teams-config.json with group ID, channel ID, per-event toggles
3. **Event types** — work_complete, pr_opened, pr_merged, issue_closed, decisions, ralph_status
4. **Usage** — Manual notifications via `.squad/scripts/teams-notify.sh <event_type> "<message>"`
5. **Troubleshooting** — Login issues, 403 permissions, channel ID extraction, script not found
6. **Graceful degradation** — Full functionality without Teams configured, no impact on dev workflow
7. **Configuration checklist** — Prerequisites and test procedure

**Key design patterns established:**
- Master `enabled` toggle gates all notifications
- Per-event toggles allow selective notification (e.g., decisions=true, ralph_status=false)
- Script pattern: read config → check enabled and event type → format → post → exit silently on disable
- Teams channel ID extracted from Teams UI (right-click → copy link) or Azure CLI
- No retry logic — fire-and-forget HTTP POST to Graph API

**File paths:**
- Skill document: `.squad/skills/teams-notify/SKILL.md`
- Configuration: `.squad/identity/teams-config.json`
- Script: `.squad/scripts/teams-notify.sh`
- Graph API endpoint: `/v1.0/teams/{groupId}/channels/{channelId}/messages`

**Clarity improvements over requirements:**
- Added mermaid-like flow diagram to show architecture
- Included step-by-step channel ID extraction procedure (Teams UI + CLI)
- Provided schema table with field descriptions
- Added troubleshooting decision tree with specific `az` commands to test
- Clarified graceful degradation (no errors, no noise when disabled)
- Included configuration checklist with pre-flight items

## 2026-03-12: Teams Notification Skill Documentation

Created `.squad/skills/teams-notify/SKILL.md` for the Teams notification system. Documented purpose, all event types, usage patterns, configuration, examples, and troubleshooting.

**Integration points:** Scribe calls this for work batch notifications. Coordinator can use for orchestration milestones. All agents can trigger for their work.

**Outcome:** Comprehensive documentation complete and integrated.
19 changes: 19 additions & 0 deletions .squad/agents/scribe/charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ Never start work unprompted. Scribe is always spawned after substantial work by

Always run in `mode: "background"` — non-blocking, async logging.

## Teams Notifications

After completing logging and decision merging tasks, check if Teams notifications are enabled:

1. Read `.squad/identity/teams-config.json`
2. If `enabled` is `true`, call `.squad/scripts/teams-notify.sh` with the appropriate event type and a brief summary
3. Event type mapping:
- After a work batch → `work_complete` with agent names and what they did
- After PR creation → `pr_opened` with PR number, title, and branch
- After PR merge → `pr_merged` with PR number and title
- After issue close → `issue_closed` with issue number and title
- After decision merge → `decisions` with the decision summary
4. If the script fails or Teams is not configured, continue normally — notifications never block logging

The script handles all formatting and auth. Scribe just calls it with the event type and message string:
```bash
.squad/scripts/teams-notify.sh work_complete "🔧 Linus refactored auth module. 🧪 Basher added 12 test cases."
```

## Voice

Quiet. Observant. The institutional memory of the team. Doesn't have opinions, just facts. Makes sure decisions don't get lost.
126 changes: 126 additions & 0 deletions .squad/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,129 @@ All issues routed to qualified squad members:
| #89 | CI/CD integration guide (P1) | squad:livingston + squad:saul | Documentation with doc-review gate |

**Why:** Batch review + triage ensures all green PRs merge cleanly and new work is routed to the right specialist without manual coordination. Parallel work begins immediately once triage is complete.

## 2026-03-10: PR Feedback Pass 2 — Design Decision Rationale

**By:** Linus (Backend Developer)
**Date:** 2026-03-10

**What:** Resolved all 49 unresolved review threads across PRs #79–#96. Key design decisions documented:

1. **Trigger grader empty prompt handling** (PR #90): Empty prompts now fail immediately. Previously score=0 in negative mode would pass (0 < threshold), a false positive.

2. **Snapshot path resolution** (PR #95): `resolvePathWithSymlinks` now recursively walks up the path tree, enabling snapshot writes to non-existent intermediate directories. This was blocking the parent-dir-creation use case.

3. **Coverage threshold** (PR #92): ≥2 grader types for "Full" coverage is intentional — a single grader validates one dimension; multi-angle coverage requires multiple grader types. Documented in code.

4. **Base ref fallback chain** (PR #93): Changed from origin/main → main to origin/main → main → HEAD per chlowell's review. Enables diff command in repos without remotes.

**Why:** Clearing the review feedback backlog to unblock merge queue. All human reviewer feedback (wbreza, chlowell) addressed with code or rationale. Copilot automated comments assessed individually — genuine bugs fixed, design choices documented and resolved.

**Impact:** All 8 authored PRs now have 0 unresolved threads and are ready for merge.

## 2026-03-10: Fork PR Branch Fix Protocol

**By:** Linus (Backend Developer)
**Date:** 2026-03-10

**What:** When squad feedback sweep commits land on the wrong remote (origin/microsoft instead of fork/spboyer), the fix protocol is:

1. Fetch both remotes
2. Compare `origin/<branch>` vs `fork/<branch>` — identify unique origin commits by deduplicating on commit message
3. Create detached worktrees from fork branch tips
4. Cherry-pick only unique, architecturally-compatible commits (skip commits targeting superseded code)
5. Push to fork remote
6. Verify PR head SHA advanced on GitHub

**Key rule for #93 (tokens diff):** When a fork branch was independently reworked (diff→compare consolidation), do NOT cherry-pick old fix commits that target removed code. Only cherry-pick architecture-neutral commits (docs, CHANGELOG).

**Why:** Fork-backed PRs only advance when the fork branch moves. Pushing to origin branches (same name) has no effect on the PR. This protocol avoids introducing conflicts from stale commits while ensuring all review feedback reaches the actual PR.

**Impact:** All future feedback sweeps must verify they're pushing to the correct remote (`fork` for fork-backed PRs, `origin` for origin-backed PRs) before pushing. Check `gh pr view <N> --json headRepository` to confirm.

## 2026-03-10: hasConfiguredTokenLimits: non-nil pointer = authoritative

**By:** Linus (Backend Developer)
**PR:** #96
**Date:** 2026-03-10

**What:** `hasConfiguredTokenLimits` now returns `true` for any non-nil `*TokenLimitsConfig` pointer, not just when Defaults or Overrides maps are populated. This means `tokens.limits: {}` in `.waza.yaml` is treated as authoritative and suppresses the deprecated `.token-limits.json` fallback.

**Why:** A non-nil pointer from YAML unmarshaling means the user explicitly declared the section. Requiring populated child maps created a semantic gap where `limits: {}` silently fell back to legacy JSON — surprising behavior during migration.

**Impact:** Users migrating from `.token-limits.json` to `.waza.yaml` can now safely write an empty `tokens.limits:` section to disable the legacy fallback before populating their limits.

## 2026-03-12: Teams Notification Script Design

**By:** Linus (Backend Developer)
**Date:** 2026-03-12

### Context

Created `.squad/scripts/teams-notify.sh` for sending squad notifications to the Waza Squad Teams channel via Microsoft Graph API.

### Decisions

1. **Always exit 0** — The notification script never returns a non-zero exit code. If az isn't installed, not logged in, config is missing, or the API call fails, it logs a warning to stderr and exits cleanly. This prevents notification failures from breaking CI/CD pipelines or squad automation.

2. **jq with grep/sed fallback** — Uses jq for JSON parsing when available, falls back to grep/sed for environments without jq. The jq path is preferred because it properly handles JSON escaping in the request body.

3. **HTML content escaping** — Message content is escaped (`&`, `<`, `>`, `"`) before embedding in HTML to prevent injection in Teams messages.

4. **Config-driven event filtering** — Each event type can be independently enabled/disabled in `teams-config.json` via the `notify_on` object. The script checks this before making any API call.

5. **TEAM_ROOT resolution** — Script auto-detects the team root by walking up from its own location (`../../` from `.squad/scripts/`). Can be overridden via `TEAM_ROOT` env var.

### Files

- `.squad/scripts/teams-notify.sh` — Main notification script
- `.squad/scripts/teams-test.sh` — Test/verification companion
- `.squad/identity/teams-config.json` — Channel config (introduced in this PR)

Comment on lines +475 to +480
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says .squad/identity/teams-config.json is “pre-existing”, but it’s introduced in this PR. Please correct the wording so the decision log matches the actual change history (and avoid implying the repo previously contained these IDs).

Copilot uses AI. Check for mistakes.

## 2026-03-12: Microsoft Teams Notifications via Graph API

**By:** Coordinator (in consultation with Linus and Shayne Boyer)
**Date:** 2026-03-12T13:45Z
**Related:** User directive (2026-03-12)

**What:** Implemented Teams notifications for squad milestone updates via Microsoft Graph API. System sends notifications to "Waza Squad" Teams channel on work batches, PR lifecycle, issue closure, and decision merges.

**Components:**
- **Script:** `.squad/scripts/teams-notify.sh` — Main notification sender
- **Test:** `.squad/scripts/teams-test.sh` — Verification tool
- **Config:** `.squad/identity/teams-config.json` — Channel config (introduced in this PR)
- **Skill:** `.squad/skills/teams-notify/SKILL.md` — Usage documentation

**Design Decisions:**

1. **Always exit 0** — Notification failures never block automation. Graceful degradation: if az isn't installed, not logged in, config missing, or API fails, the script logs a warning to stderr and exits cleanly.

2. **jq with grep/sed fallback** — JSON parsing prefers jq (proper HTML/JSON escaping) but falls back to grep/sed for minimal environments without jq installed.

3. **HTML content escaping** — Message content escaped for `&`, `<`, `>`, `"` before embedding in Teams HTML to prevent injection vulnerabilities.

4. **Config-driven event filtering** — Each event type (`work_complete`, `pr_opened`, `pr_merged`, `issue_closed`, `decisions`) independently controllable via `notify_on` object in teams-config.json. Allows disabling noisy events while keeping critical ones.

5. **TEAM_ROOT auto-detection** — Script walks up from its location (`../../` from `.squad/scripts/`) to find repo root. Can be overridden via `TEAM_ROOT` environment variable for CI/CD flexibility.

**Event Types:**
- `work_complete` — Agent work batch summaries (names + what they did)
- `pr_opened` — New PR (number, title, branch)
- `pr_merged` — Merged PR (number, title)
- `issue_closed` — Closed issue (number, title)
- `decisions` — Decision merges (summary)

**Integration:**
- Scribe calls notification system after completing logging tasks
- All agents can manually trigger notifications for their work
- Coordinator uses for orchestration milestones
- Failures never block automation — entirely optional enhancement

**Testing:**
- `.squad/scripts/teams-test.sh` verified notification delivery to Teams
- Message successfully appeared in "Waza Squad" channel
- No blocking errors observed

**Why:**
User request (Shayne Boyer) to send squad milestone updates to Teams channel. System enables real-time team awareness of work completion, PRs, and decisions without requiring polling or manual updates. Designed to never interfere with CI/CD or squad automation — a pure enhancement to team communication.
28 changes: 28 additions & 0 deletions .squad/decisions/inbox/linus-ralph-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Decision: Ralph Watch — Local Watchdog for Teams Notifications

**Date:** 2026-03-12
**Author:** Linus (Backend Developer)
**Status:** Implemented

## Context

Shayne requested a local process (Option 1 from heartbeat discussion) to monitor GitHub activity and post to Teams. Explicitly not GitHub Actions — "do not update the gh actions heartbeat, it does nothing for us."

## Decision

Created `ralph-watch.sh` as a local daemon that:
- Polls GitHub every N minutes (default 10) using `gh` CLI
- Tracks state in `.squad/identity/.ralph-watch-state.json` to avoid duplicate notifications
- Calls existing `teams-notify.sh` for each new event (pr_merged, issue_closed, work_complete)
- Seeds state on first run so existing activity doesn't flood Teams

## Design Choices

1. **State-file deduplication over timestamps:** Tracking known PR/issue numbers is more reliable than timestamp filtering when API results are paginated or delayed.
2. **`gh api` compare endpoint for commits:** Avoids needing local git state; the API gives commit count and authors directly.
3. **Delegates to `teams-notify.sh`:** Watchdog only detects events; formatting and posting is the notify script's job. Single responsibility.
4. **No background daemon management:** Runs in foreground with Ctrl+C shutdown. Shayne can wrap in `nohup` or `tmux` if needed.

## Impact

All squad members benefit from real-time Teams notifications about repo activity. No CI/CD changes required.
14 changes: 14 additions & 0 deletions .squad/identity/teams-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"enabled": false,
"group_id": "your-group-id-here",
"channel_id": "19:your-channel-id-here@thread.tacv2",
"channel_name": "Waza Squad",
"notify_on": {
Comment on lines +1 to +6
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repo-default teams-config.json ships with enabled: true and concrete group/channel IDs. That means anyone running teams-test.sh, teams-notify.sh, or ralph-watch.sh from a fresh checkout will post into the real channel by default (potential noise/spam). Consider defaulting enabled to false (and/or shipping an example config) so notifications are opt-in per user/environment.

Copilot uses AI. Check for mistakes.
"work_complete": true,
"pr_opened": true,
"pr_merged": true,
"issue_closed": true,
"decisions": true,
"ralph_status": false
Comment on lines +3 to +12
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo commits a real teams-config.json alongside the .example. Even with placeholders, it’s easy for someone to paste real group_id/channel_id and accidentally commit internal IDs. Consider gitignoring .squad/identity/teams-config.json and keeping only the .example in-repo (update docs/scripts to reference copying the example), or add a strong warning comment + CI guard to prevent committing non-placeholder values.

Suggested change
"group_id": "your-group-id-here",
"channel_id": "19:your-channel-id-here@thread.tacv2",
"channel_name": "Waza Squad",
"notify_on": {
"work_complete": true,
"pr_opened": true,
"pr_merged": true,
"issue_closed": true,
"decisions": true,
"ralph_status": false
"group_id": "__DO_NOT_PUT_REAL_GROUP_ID_HERE__",
"channel_id": "__DO_NOT_PUT_REAL_CHANNEL_ID_HERE__",
"channel_name": "DEMO CHANNEL - REPLACE IN LOCAL UNTRACKED COPY ONLY",
"notify_on": {
"work_complete": true,
"pr_opened": true,
"pr_merged": true,
"issue_closed": true,
"decisions": true,
"ralph_status": false

Copilot uses AI. Check for mistakes.
}
}
14 changes: 14 additions & 0 deletions .squad/identity/teams-config.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"enabled": false,
"group_id": "your-group-id-here",
"channel_id": "19:your-channel-id-here@thread.tacv2",
"channel_name": "Your Channel Name",
"notify_on": {
"work_complete": true,
"pr_opened": true,
"pr_merged": true,
"issue_closed": true,
"decisions": true,
"ralph_status": false
}
}
Loading
Loading