Two problems:
1. Schedule was every 20 min but review_all cycles take 35 min,
causing overlapping triggers that fill both slots
2. Trigger server only deduped by issue number, not by reason,
so two review_all runs could stack up
Fixes:
- Change schedule from */20 to 0,45 (every 45 min)
- Add reason-based dedup in trigger-server.ts: reject 409 if a
non-issue run with the same reason is already in progress
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The two scheduled modes (review_all every 15 min, scan every 30 min)
competed for MAX_CONCURRENT=1 on the trigger server, causing 429 drops
and 30-55+ min gaps. Merge both into a single cycle that runs every
20 min, prioritizing PR review but also performing lightweight repo
scanning when capacity allows (≤5 open PRs).
Also prevents refactor agents from closing issues manually — issues
now auto-close via `Fixes #N` in the PR body when merged.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: security triage now applies full label taxonomy
Triage mode now applies:
- Safety label (safe-to-work / malicious / needs-human-review)
- Content-type label (bug, enhancement, security, question, etc.)
- Lifecycle label (Pending Review) so downstream teams can pick up
Team-building mode now transitions lifecycle labels:
- Adds "In Progress" at start, removes it on close
Added a "Available Labels Reference" section to the triage prompt
documenting all label categories for the agent.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: all security-filed issues get safe-to-work + Pending Review
Issues filed by the security team (scan findings, drift/anomaly
reports, follow-up issues from closed PRs) now automatically get
`safe-to-work` and `Pending Review` labels so downstream teams
can immediately pick them up without waiting for another triage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove Pending Review from safe-to-work issues
safe-to-work already means triage is complete — adding Pending Review
is redundant and confusing. Now only UNCLEAR issues get Pending Review
(they still need human attention). SAFE issues and security-filed
issues skip straight to actionable with just safe-to-work.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: normalize all labels to kebab-case
Renamed on GitHub:
- "In Progress" → "in-progress"
- "Pending Review" → "pending-review"
- "Under Review" → "under-review"
- "good first issue" → "good-first-issue"
- "help wanted" → "help-wanted"
Updated all references in security.sh and refactor.sh to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: align issue templates and workflows with actual repo labels
Created missing labels: cloud-request, agent-request, cli.
Replaced nonexistent needs-triage with pending-review in all templates.
Templates updated:
- bug_report: bug + pending-review
- cli_feature_request: cli + enhancement + pending-review
- cloud_request: cloud-request + enhancement + pending-review
- agent_request: agent-request + enhancement + pending-review
Workflows updated:
- refactor.yml: trigger on safe-to-work AND (bug|cli|enhancement|maintenance)
- discovery.yml: already correct (safe-to-work AND cloud-request|agent-request)
- security.yml: already correct (team-building label check)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Simplify from 6 modes (Hexa-Mode) to 4 modes (Quad-Mode) by folding
single-PR review and hygiene into a unified review_all mode that runs
every 15 minutes. This removes the pull_request trigger entirely since
review_all catches all open PRs on schedule, and absorbs staleness
checks + branch cleanup into the same cycle.
Remaining modes: team_building, triage, review_all, scan.
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New issues are triaged by the security team before other workflows can
act on them. The triage agent checks for prompt injection, social
engineering, spam, and unsafe payloads — marking safe issues with
`safe-to-work`, closing malicious ones, or flagging unclear ones for
human review. Discovery and refactor workflows now require the
`safe-to-work` label in addition to their existing label requirements.
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New issue template: Team Building (team-building label) — 2 fields:
which agent team to improve + what to change
- Security team gets a new team_building mode: reads the issue, spawns
implementer + reviewer (both Opus), creates PR, reviews, merges, closes issue
- Discovery workflow: only triggers on cloud-request / agent-request issues
- Refactor workflow: only triggers on bug / cli issues
- Security workflow: only triggers on team-building issues (+ PR/schedule)
- All workflows still run on schedule and workflow_dispatch as before
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add security review team for PR review (#543)
Adds a security team that automatically reviews every PR for security
issues (injection, credential leaks, unsafe patterns, macOS compat)
and sends Slack notifications to #spawn when concerns are found.
- security.sh: dual-mode cycle script (PR review + scheduled scan)
- security.yml: GitHub Actions workflow on pull_request events
- start-security.sh: gitignored wrapper with secrets (deployed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: expand security team with hygiene, scan modes + auto-merge clean PRs
- PR mode: 2-agent team (code-reviewer + test-verifier) reviews PRs.
If zero findings, auto-approves AND merges. If concerns, requests
changes and sends Slack notification to #spawn.
- Hygiene mode (every 6h): pr-triager + branch-cleaner close stale PRs,
file follow-up issues, delete orphan branches.
- Scan mode (daily): shell-auditor + code-auditor + drift-detector
perform full repo security audit, file GitHub issues for findings.
- All modes use Claude Code agent teams (TeamCreate, parallel teammates
via Task tool, SendMessage coordination, TaskList monitoring).
- Workflow updated with schedule triggers and workflow_dispatch inputs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: upgrade all security auditor agents to Opus model
All security-critical roles (code-reviewer, pr-triager, shell-auditor,
code-auditor) now use Opus. Helper roles (test-verifier, branch-cleaner,
drift-detector) remain on Haiku.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: auto-merge PRs with MEDIUM/LOW or no findings
Only CRITICAL/HIGH findings block a PR. MEDIUM/LOW are informational
notes included in the approving review — PR still gets merged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: bun install creates empty directories in proot (Termux)
because proot can't intercept bun's symlink/hardlink/copy_file_range
syscalls. This breaks both local build and source-mode fallback.
Fix: when `bun run build` fails, download the pre-built cli.js from
the `cli-latest` GitHub release. The bundled binary is self-contained
(80KB, all deps inlined) and only needs the bun runtime.
- Add CI workflow (.github/workflows/cli-release.yml) that builds and
uploads cli.js to a rolling `cli-latest` release on every push to main
- Replace broken source-mode fallback with GitHub release download
- Bump CLI version to 0.2.63
Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Agent request: remove redundant name field (already in title),
broaden traction criteria to include fork activity and venture funding.
Cloud request: remove redundant name field (already in title),
consolidate API docs and billing into Additional Context.
New: CLI feature request template for spawn CLI improvements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HTTP/2 has strict stream lifecycle management that doesn't play well
with long-lived chunked responses — curl exits with error 92
(stream not closed cleanly: INTERNAL_ERROR). HTTP/1.1 handles
persistent streaming connections natively.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the broken keep-alive ping loop with a fundamentally better
approach: the trigger server now streams the script's stdout/stderr
back as the HTTP response body in chunks. The GH Action holds the
curl connection open for the entire cycle duration (~90 min timeout).
This works because Sprite keeps VMs alive while "actively servicing
HTTP requests." A single long-lived streaming response satisfies
this naturally — no synthetic pings needed.
Key changes:
trigger-server.ts:
- /trigger now returns a streaming text/plain Response
- stdout/stderr piped through ReadableStream with chunked output
- 30s heartbeat lines injected during silent periods
- Client disconnect handled gracefully (process keeps running)
- X-Accel-Buffering: no header to prevent proxy buffering
discovery.yml / refactor.yml:
- curl -sSN --fail-with-body streams output in real-time
- timeout-minutes: 90 to hold the connection for full cycles
- Error responses (429/409/401) still print body and exit cleanly
discovery.sh / refactor.sh:
- Removed all keep-alive logic (start_keepalive/stop_keepalive)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the GitHub workflow, scripts, and service from "improve" to
"discovery" to better reflect what the automation does. Remove the
`spawn improve` CLI command entirely — the discovery/refactor loops
are internal automation, not user-facing CLI features.
File renames:
- .github/workflows/improve.yml → discovery.yml
- .claude/skills/.../improve.sh → discovery.sh
- .claude/skills/.../start-improve.sh → start-discovery.sh
- Service: improve-trigger → discovery-trigger
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Issue triggers now spawn lightweight 2-agent runs (15-min timeout) in
isolated worktrees, while refactor cycles continue independently with
the full 6-agent team (30-min timeout). Duplicate issue runs are
rejected with 409.
- trigger-server.ts: pass SPAWN_ISSUE/SPAWN_REASON env vars to script,
add issue dedup (409), include issue in health/trigger responses
- refactor.sh: dual-mode (issue vs refactor) with isolated worktrees,
mode-specific prompts and timeouts, scoped cleanup
- start-refactor.sh: set MAX_CONCURRENT=3 (gitignored, local only)
- refactor.yml: handle 409 alongside existing 429
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When MAX_CONCURRENT=1 and a cycle is in progress, the trigger server
returns 429. This is expected behavior, not an error — the previous
curl -f treated it as failure (exit code 22).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Change trigger-server MAX_CONCURRENT default from 3 to 1 to prevent
overlapping cycles that duplicate GitHub issue comments
- Add SIGTERM/SIGINT handling to trigger-server so running scripts finish
gracefully on service restart instead of being killed mid-flight
- Add cleanup trap to refactor.sh for worktree/tempfile cleanup on exit
- Add pre-cycle cleanup of stale worktrees, merged branches, and
abandoned PRs from previously interrupted cycles
- Add mandatory Lifecycle Management section to team lead prompt requiring
shutdown_request to all teammates before exiting
- Add dedup checks to community-coordinator: check existing comments
before posting to prevent duplicate acknowledgments/resolutions
- Pass issue number in workflow trigger reason for better logging
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Sprite start service API (/services/{name}/start) returns
"service name required" for all service names — appears to be an API
bug. Switched to hitting the sprite's public URL directly with
TRIGGER_SECRET bearer auth instead.
- Re-added TRIGGER_SECRET auth to trigger-server.ts
- Set sprite url_settings.auth to "public"
- Updated both workflows to use SPRITE_URL + TRIGGER_SECRET pattern
- Aligned workflow structure (both use same env vars and curl format)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use env vars from secrets instead of hardcoded names
- Add issues trigger (opened, reopened)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sprite API rejects service names with hyphens. Renamed from
improve-trigger to improve_trigger.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SERVICE_NAME env var may conflict with GitHub Actions internals.
Inline the secrets directly in the URL template instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Sprite start service API returns streaming NDJSON, causing curl -f
to fail with exit code 22. Use duration=0s to return immediately and
drop -f flag since the response is streaming.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sprite may take time to wake from pause, causing --max-time 30 to fail
with exit code 22.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace SPRITE_URL/SPRITE_SECRET pattern with SPRITE_NAME/SERVICE_NAME
- Use Sprite start service API endpoint (api.sprites.dev)
- Share SPRITE_TOKEN across all services
- Update skill documentation to reflect new approach
- Delete deprecated URL/SECRET based secrets
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add max 3 concurrent run limits:
- GitHub Actions: concurrency groups prevent workflow queue buildup
- trigger-server: tracks concurrent runs, rejects with 429 if at max
- Configurable via MAX_CONCURRENT env var (defaults to 3)
- Returns running count and max in trigger response
This prevents resource exhaustion when workflows trigger frequently.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add refactor.sh: Continuous service that spawns Claude Code agent teams
- Team roles: security-auditor, ux-engineer, complexity-hunter, test-engineer, issue-triager
- Focus on security, UX, complexity reduction, testing, and GitHub issue response
- Add GitHub issue template for bug reports (focused on error logs)
- Auto-triages and responds to issues within 1 hour
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added shellcheck to catch bash anti-patterns across 115 scripts:
- Created .shellcheckrc configuration
- Added GitHub Actions workflow (.github/workflows/lint.yml)
- Documented shellcheck usage in README
Currently found 3,598 warnings (expected for unlinted codebase).
Using || true temporarily to not block PRs - warnings will be fixed
incrementally in follow-up tasks.
Common issues: SC2250 (missing braces), SC2162 (read without -r),
SC2312 (command substitution masking), SC1091 (sourcing pattern).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>