feat: add 'squad watch' — Ralph local watchdog for persistent polling#57
feat: add 'squad watch' — Ralph local watchdog for persistent polling#57bradygaster merged 6 commits intobradygaster:devfrom
Conversation
…radygaster#53) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * chore: trim npm package — exclude docs and contributor files (bradygaster#48) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * chore: trim npm package — exclude docs, CONTRIBUTING.md, .gitignore - Removed docs/ from package.json files allowlist (read on GitHub, not runtime) - Added CONTRIBUTING.md, .gitignore, docs/ to .npmignore (belt-and-suspenders) - Package: 82 files / 205.7kB -> 30 files / 75.1kB (63% smaller) --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> * feat: blog migration, team-docs guard, docs site generator (bradygaster#49, bradygaster#50, bradygaster#51) (bradygaster#52) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * feat: blog migration, team-docs guard, docs site generator (bradygaster#49, bradygaster#50, bradygaster#51) --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> * fix: add --base path support to docs build for GitHub Pages Nav links, search index, and logo all used root-relative paths (/index.html) which 404 on GitHub Pages where the site is served under /squad/. Added --base CLI flag to build.js and updated workflows to pass --base /squad. Also added workflow_dispatch trigger for manual re-deploys. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: extract docs template, CSS, and JS into static files Moved inline HTML template, CSS, and JS from build.js into separate files under docs/assets/ (template.html, style.css, script.js). Build script now reads template and does placeholder replacement. CSS and JS are linked externally via the existing assets copy step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ter#54) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * chore: trim npm package — exclude docs and contributor files (bradygaster#48) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * chore: trim npm package — exclude docs, CONTRIBUTING.md, .gitignore - Removed docs/ from package.json files allowlist (read on GitHub, not runtime) - Added CONTRIBUTING.md, .gitignore, docs/ to .npmignore (belt-and-suspenders) - Package: 82 files / 205.7kB -> 30 files / 75.1kB (63% smaller) --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> * feat: blog migration, team-docs guard, docs site generator (bradygaster#49, bradygaster#50, bradygaster#51) (bradygaster#52) * chore: unignore .ai-team/ for dev branches, update contributing guide - Removed .ai-team/ from .gitignore so team files can be committed on dev/feature branches - Updated CONTRIBUTING.md to reflect guard workflow as enforcement (not .gitignore) - Updated guard workflow error message in both live and template copies - .npmignore still excludes .ai-team/ from the published package * feat: blog migration, team-docs guard, docs site generator (bradygaster#49, bradygaster#50, bradygaster#51) --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> * fix: add --base path support to docs build for GitHub Pages Nav links, search index, and logo all used root-relative paths (/index.html) which 404 on GitHub Pages where the site is served under /squad/. Added --base CLI flag to build.js and updated workflows to pass --base /squad. Also added workflow_dispatch trigger for manual re-deploys. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: extract docs template, CSS, and JS into static files Moved inline HTML template, CSS, and JS from build.js into separate files under docs/assets/ (template.html, style.css, script.js). Build script now reads template and does placeholder replacement. CSS and JS are linked externally via the existing assets copy step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: remove stale team-docs/blog from tracking Blogs already migrated to docs/blog/ — these stale copies predated the guard workflow update and leaked to main/preview. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: guard workflow should allow removal of forbidden files The guard was blocking PRs that *delete* team-docs/ or .ai-team/ files from protected branches. Deletions are exactly what we want — filter out files with status 'removed' before checking paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: bradygaster <bradygaster@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace aspirational in-session idle-watch (agent can't self-schedule) with a mechanically sound approach: 'npx squad watch' runs as a standalone local process that polls GitHub every N minutes for new squad work. Three layers of Ralph: - In-session: 'Ralph, go' active loop while work exists - Local watchdog: 'npx squad watch --interval N' for persistent polling - Cloud heartbeat: squad-heartbeat.yml for fully unattended Changes: - index.js: Add 'watch' subcommand with --interval flag (default: 10min) - squad.agent.md: Replace idle-watch self-scheduling with squad watch ref - docs/features/ralph.md: Document three-layer architecture
The package is published as @bradygaster/create-squad with bin name 'create-squad', so the correct invocation is: npx github:bradygaster/squad watch --interval 10 NOT 'npx squad watch' which would fail to resolve. Updated all references in squad.agent.md and docs/features/ralph.md to use the correct 'npx github:bradygaster/squad watch' path, matching the existing convention used throughout the project (e.g., help text in index.js line 34).
Caught one more instance of the bare 'npx squad' shorthand that doesn't resolve. The package bin is 'create-squad' under the @bradygaster scope, so all npx invocations must use the full 'npx github:bradygaster/squad' path. This was a pre-existing bug in index.js (upgrade hint message) spotted while fixing the watch command references.
|
Moving to v0.5.0 — this is a feature, and 0.4.1 is focused on QOL/polish. The npx path fix from this PR has been cherry-picked into dev separately. The Ralph watch feature will land in 0.5.0 after the .ai-team → .squad rename (#69). |
Cherry-picked from #57. The upgrade message was showing 'npx squad copilot' instead of 'npx github:bradygaster/squad copilot'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Which honestly? Could be like in half an hour. Or we could do a 0.4.2 and add this. I'm easy here. |
Keaton's Architectural Review — PR #57VERDICT: APPROVE with defer to post-v0.5.0 + REQUEST CHANGES (scope) 1. Architectural Assessment ✅The three-layer Ralph design is architecturally sound: In-session ("Ralph, go"): Active loop processes work → self-chains → idles when clear This correctly addresses the fundamental constraint: agents are request-response and cannot self-schedule. The aspirational idle-watch spec claimed Ralph could poll on a timer inside a Copilot session, but that's impossible — agents can't The separation of concerns is clean:
This architecture enables new features rather than closing doors — the local watchdog can evolve independently (adding Slack notifications, metric tracking, etc.) without touching Ralph's core coordination logic. 2. Code Quality ✅ (with minor notes)index.js watch implementation (lines 74-238):
docs/features/ralph.md:
squad.agent.md changes:
3. Scope Assessment
|
Merged origin/dev (v0.5.0 changes) into squad/ralph-watch branch. Key integrations: - Updated watch command to use detectSquadDir() for .squad/ migration support - Preserved all v0.5.0 infrastructure: email scrubbing, project type detection, identity layer - Merged Ralph watch references into squad.agent.md alongside .squad/ path updates - All 64 tests passing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
❌ NEEDS REVISIONIssue: PR #57 bundles TWO separate docs when it should only contain the notification routing guide. The \�uilding-resilient-agents.md\ file belongs in PR #58 (circuit breaker guide). Notification Routing Doc ✅
Building Resilient Agents Doc
|
Summary
Replaces the aspirational in-session idle-watch polling (which can't actually work — a Copilot agent can't
setTimeoutto wake itself) with a mechanically sound approach:npx squad watchruns as a standalone local process that polls GitHub every N minutes for new squad work.Problem
The previous idle-watch spec claimed Ralph could auto-poll on a timer inside a Copilot CLI session. This isn't possible — the agent is request-response. When it ""idles"", it's simply not running. There's no timer mechanism. Users had to manually say ""Ralph, go"" again when new work arrived.
Solution: Three Layers of Ralph
Instead of pretending the agent can schedule itself, we now have three honest, mechanically sound layers:
npx squad watch --interval 10— standalone process polls GitHubsquad-heartbeat.yml— GitHub Actions cron every 30 minnpx squad watchA new CLI subcommand that runs as a persistent local process:
Each cycle it:
squad-labeled issues@copilottosquad:copilotissues (if auto-assign is enabled)Ctrl+C to stop. Requires
ghCLI authenticated with a PAT.Changes
index.js(+165 lines)watchsubcommand with--interval NflagwatchcommandghCLI for GitHub API access (same as heartbeat workflow).ai-team/team.mdfor triage routingsquad-heartbeat.yml).github/agents/squad.agent.mdsquad watchand three-layer architectureactive/idle(removedwatching)docs/features/ralph.mdnpx squad watch) documentationTesting
ghCLI + GitHub repo context for integration testing)