Validates that all cloud provider lib/common.sh files follow security
conventions from the security audit. Tests cover SSH key encoding
(json_escape or python json.dumps), config file permissions, Python
code injection prevention, API body JSON safety, heredoc injection
prevention, shared/common.sh sourcing, and credential handling patterns.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two UX improvements:
1. `spawn <agent> <cloud> --dry-run` now shows a Credentials section that
checks which env vars (OPENROUTER_API_KEY, cloud auth vars) are set vs
missing, so users can verify readiness before a real run.
2. Script failure guidance (exit code 1 and default) now checks which
specific env vars are unset instead of showing a generic "need X + Y"
message, making it immediately clear what's missing.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These helpers were extracted from _cloud_api_retry_loop in PR #821 to
reduce cyclomatic complexity but had zero test coverage. They are
invoked on every cloud API call across all providers:
- _classify_api_result: Classifies curl/HTTP results into retry reasons
(network error, rate limit 429, service unavailable 503) or empty
(success/non-retryable error). Tests cover all branches including
curl exit codes 1/6/7/28, HTTP 429/503, success codes 200/201/204,
non-retryable errors 400-502, and edge cases.
- _report_api_failure: Generates user-facing error messages after
retries are exhausted. Differentiates network vs HTTP errors,
outputs API response body only for HTTP errors. Tests cover
retry count display, response body handling, and special chars.
Also includes integration tests verifying the classify-then-report
pipeline and realistic cloud provider scenarios (Hetzner, DigitalOcean,
DNS failures, auth errors, validation errors).
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Validates the critical contract that every implemented agent script
correctly injects the environment variables from manifest.json.
Catches silent breakage where an agent starts but cannot reach the
LLM API due to missing OPENROUTER_API_KEY or provider-specific vars.
Tests cover:
- OPENROUTER_API_KEY presence in all scripts
- Provider-specific env vars (ANTHROPIC_BASE_URL, OPENAI_BASE_URL, etc.)
- OpenRouter API key acquisition patterns (env check, OAuth, manual)
- Agent install and launch command references
- Cloud lib env injection infrastructure
- Base URL values pointing to openrouter.ai
- No hardcoded API keys (security)
- Full coverage statistics across all agents and clouds
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Long sleeps block message delivery — teammate messages arrive as
user turns between the lead's responses. sleeping 30s means 30s
of queued messages. Use sleep 5 to yield quickly, process messages
immediately, and do useful work between polls.
Updated all 3 service scripts: security.sh, refactor.sh, discovery.sh.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- latitude/lib/common.sh: Replace custom 38-line wait_for_server_ready
polling loop with generic_wait_for_instance from shared/common.sh.
Consolidate extract_latitude_server_ip (36 lines of inline Python) into
a single readonly expression constant. Net -59 lines.
- ovh/lib/common.sh: Replace shell variable interpolation in Python
strings ('${var}') with sys.argv[] in _ovh_find_flavor_id,
_ovh_get_ssh_key_id, _ovh_build_instance_body, and ovh_register_ssh_key.
This eliminates injection surface and follows the established pattern
used by other cloud providers.
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
For non-Sprite environments (standard Linux VMs, sandboxes), systemd
is the recommended way to run the trigger server. Added full unit
file template, management commands, and troubleshooting entries.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add worktree requirement to security team prompts
PR reviewers must check out PRs in sub-worktrees before running
bash -n or bun test. Scan mode agents must also work inside a
worktree. This prevents concurrent agents from conflicting in
the main repo checkout.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: enforce worktrees everywhere, refactor pr-maintainer role
- SKILL.md: expand worktree convention to cover all agent work
(PR review, testing, audits) not just branch creation
- refactor.sh pr-maintainer: strip review/approve/merge
responsibilities — that's the security team's job. pr-maintainer
now focuses on rebasing conflicting PRs, addressing review
comments, and fixing failing checks
- Remove stale PR auto-merge from pre-cycle cleanup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove self-review from refactor team, clarify separation of concerns
Refactor team focuses on research, deep-dives, and solving problems.
Security team owns the entire PR review/approve/merge lifecycle.
- Replace "No Self-Merge Rule" with "Separation of Concerns" section
- Remove all self-review steps from issue and refactor mode workflows
- Remove needs-team-review labeling from agent instructions
- Simplify monitoring loop (no more review verification)
- Simplify lifecycle checks (verify PRs exist, not reviewed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove stale needs-team-review label from security triage reference
The refactor team no longer applies this label, so remove it
from the available labels documentation in triage mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The LOG_FILE paths in security.sh and refactor.sh were hardcoded to
/home/sprite/spawn, causing permission errors on non-Sprite environments.
Use $REPO_ROOT (already computed dynamically) instead. Also update
SKILL.md examples to use dynamic path resolution.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The quick-start sections in `spawn <cloud>` and `spawn <agent>` now show
whether required env vars are already set (green with "set" indicator)
or still need to be configured (cyan "export" instruction). This helps
users immediately see what credentials are missing before launching.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce cyclomatic complexity in the two highest-scoring functions:
- cli/src/commands.ts: Extract `handleUserInterrupt` and `runWithRetries`
from `execScript` (complexity score 6 -> 2 for execScript, retry logic
now independently testable)
- shared/common.sh: Extract `_classify_api_result` and `_report_api_failure`
from `_cloud_api_retry_loop` (complexity score 9 -> 4, removes duplicated
error-classification logic from loop body)
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously, `spawn --prompt="Fix bugs" claude sprite` or
`spawn list --agent=claude` would fail with "Unknown flag" because
the CLI only recognized `--flag value` (space-separated) syntax.
Now `--flag=value` is expanded to `--flag value` early in the
arg parsing pipeline, supporting the common GNU-style convention.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
When a CLI auto-update triggers mid-command (e.g. `spawn claude sprite`),
the updated binary now automatically re-runs with the original arguments
instead of asking the user to manually re-run. Sets SPAWN_NO_UPDATE_CHECK=1
on re-exec to prevent infinite update loops. Falls back to the old "run
again" message when no arguments were provided (bare `spawn`).
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 5 per-cloud live recording functions (_live_hetzner, _live_digitalocean,
_live_vultr, _live_linode, _live_civo) each duplicated 50-65 lines of
identical create->save->extract-id->delete->save logic. Extract a generic
_live_create_delete_cycle helper that handles the shared flow, with per-cloud
body builder functions providing only the cloud-specific parts.
Reduces test/record.sh by 112 lines (1016 -> 904) while preserving all
behavior including cloud-specific delete delays and empty-response fallbacks.
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This function parses JSON error responses from cloud provider APIs (used
by Hetzner, DigitalOcean, Vultr, and Contabo) and had zero test coverage.
Tests cover: field priority order, fallback behavior, realistic cloud
provider responses, and edge cases (non-object JSON, null/empty fields).
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover ensure_ssh_key_with_provider (zero prior coverage), plus edge cases
for generate_ssh_key_if_missing, get_ssh_fingerprint, extract_ssh_key_ids,
and check_ssh_key_by_fingerprint. Tests validate the callback-based SSH
key registration flow used by all cloud providers.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract _hetzner_find_candidates helper to eliminate duplicated jq
candidate-search logic (same-family and any-family searches were
nearly identical 15-line blocks)
- Consolidate 3 separate jq calls for wanted_cpu/cores/memory into
a single jq invocation
- Replace duplicated replacement-picking code with a loop over
family strategies
Function reduced from 106 to ~72 lines (plus 17-line reusable helper).
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "Rerun last" hint in `spawn list` was truncating prompts at 30
characters and appending "...", producing broken copy-paste commands.
Now delegates to the existing buildRetryCommand helper which properly
handles long prompts by suggesting --prompt-file instead of truncating.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover critical infrastructure functions that had zero dedicated test coverage:
- ssh_run_server, ssh_upload_file, ssh_interactive_session (SSH command construction)
- ssh_verify_connectivity (ConnectTimeout, max_attempts, test command)
- generic_ssh_wait (exponential backoff, success/failure, elapsed time logging)
- wait_for_cloud_init (argument delegation, cloud-init file check)
- generic_wait_for_instance (API polling, status matching, IP export, timeout)
- extract_api_error_message (all 5 error field patterns + fallbacks)
- SSH_USER default behavior (root fallback across all helpers)
Uses mock SSH/SCP/sleep commands via PATH override to test argument
construction and behavior without requiring network connectivity.
Agent: test-engineer
-- refactor/test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Standalone, sourceable script that installs the gh CLI and runs
interactive gh auth login. Any agent script on any cloud can source
it and call ensure_github_auth to get authenticated with GitHub.
- ensure_gh_cli: installs via brew/apt/dnf/binary fallback
- ensure_gh_auth: uses GITHUB_TOKEN or interactive OAuth flow
- ensure_github_auth: combined convenience wrapper
- Idempotent, macOS bash 3.x compatible, curl|bash compatible
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All spawn environments are disposable cloud VMs. Setting IS_SANDBOX=1
helps agents like Claude Code recognize the environment as a sandbox,
avoiding unnecessary safety prompts for root-level operations.
Added in two places for full coverage:
- generate_env_config(): included automatically in every env injection
- get_cloud_init_userdata(): set in .bashrc/.zshrc during cloud-init
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hetzner lib: replace all Python JSON parsing with jq. Uses the
/datacenters API as the authoritative source for server type
availability (server_types.available), cross-referenced with
/server_types for specs and pricing. jq is auto-installed if missing.
URLs: update openrouter.ai/lab/spawn → openrouter.ai/labs/spawn
across all READMEs and CLI source.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When HETZNER_SERVER_TYPE and HETZNER_LOCATION are both pre-set (e.g. by
automated scripts), there was no validation that the type is actually
available at that location. ARM types like cax11 are only available in
EU datacenters, causing "unsupported location for server type" errors
when paired with US locations like ash.
Now create_server validates the type against the Hetzner /datacenters
API (server_types.available) before attempting creation. If incompatible,
it auto-selects the cheapest compatible alternative (same CPU family,
>= specs) and warns the user.
Uses jq for JSON parsing (auto-installed if missing) and the Hetzner
/datacenters + /server_types APIs for authoritative availability data.
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>
* docs: add Contributing section to README
Adds guidance for testing cloud providers, reporting issues,
requesting new clouds/agents, and reporting auth problems.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use correct issue template URLs for cloud, agent, and CLI requests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Many gh commands in agent team prompts were missing the mandatory
`-- team/agent-name` sign-off footer, causing dedup checks to fail
and making it impossible to identify which agent posted a comment.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- buildRetryCommand: suggest --prompt-file for long prompts instead of
truncating into a non-functional command (threshold raised to 80 chars)
- showUnknownCommandError: change "Unknown command" to "Unknown agent or cloud"
since users are passing agent/cloud names, not commands
- Bump CLI version to 0.2.66
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: add comment dedup checks to all community-facing agent prompts
- security.sh triage: check for existing triage labels/comments before
re-triaging (prevents duplicate "Security triage: SAFE" comments)
- security.sh issue-checker: check for prior nudge comments before
re-posting "Re-flagging for attention" on stale issues
- discovery.sh Issue Responder: added DEDUP CHECK section (was missing
entirely — could post duplicate acknowledgments/PR links)
- Fixed stale Pending Review/Under Review/In Progress references to
kebab-case in issue-checker prompt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: standardize team/agent sign-off on all comments for dedup
Every agent comment now ends with `— team/agent-name` sign-off:
- security/triage, security/pr-reviewer, security/issue-checker,
security/scan, security/shell-auditor, etc.
- refactor/community-coordinator, refactor/pr-maintainer, etc.
- discovery/issue-responder, discovery/cloud-scout, etc.
- qa/cycle
Dedup checks now look for the sign-off string instead of author
login, making it reliable across bot account changes. Each agent
can identify its own prior comments by grepping for its sign-off.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use double-hyphen sign-off and document convention in SKILL.md
Replace emdash (—) with double-hyphen (--) in all agent sign-offs
to avoid encoding issues in shell strings. Format: `-- team/agent`.
Added section 5 "Comment sign-off for dedup" to SKILL.md documenting
the convention, format rules, and how agents use it for dedup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 10 inline `python3 -c "import json,sys; d=json.loads(...)..."` one-liners
across vultr, hetzner, digitalocean, and contabo with calls to a new shared
`extract_api_error_message` helper in shared/common.sh. The helper tries common
JSON error field patterns (message, error, error.message, error.error_message,
reason) and falls back to a caller-specified default.
This pattern appears 35+ times across cloud libs; this PR converts the first 4
clouds as a proof of concept. Remaining clouds can adopt incrementally.
Net reduction: 10 lines per converted cloud (~3 lines saved per call site).
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use sys.argv to pass shell values to inline Python instead of direct
string interpolation, preventing single-quote injection attacks across
cloud lib common.sh files and test/record.sh.
Also fix eval injection in test/record.sh try_load_config() by replacing
eval of Python-generated export statements with safe tab-separated
parsing and direct variable assignment.
Fixes#759Fixes#760
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In-progress actions (installing, starting, connecting...) should use
log_step (cyan) to visually distinguish them from completion messages
which use log_info (green). This makes it easier for users to see at a
glance what is happening vs what has finished.
Changes:
- cli/install.sh: add log_step function, use it for install progress
- shared/common.sh: OAuth flow and non-interactive exec messages
- Cloud libs: interactive_session, auth, and cleanup messages
- Agent scripts: gateway startup and session opening messages
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
((var++)) returns exit code 1 when the variable is 0 (falsy), which
causes set -e to terminate the script. Replace all instances with
the safe var=$((var + 1)) pattern in sprite/lib/common.sh and
test/run.sh.
Fixes#762
Agent: community-coordinator
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove `1n` (accidental zsh error output from automated process)
- Remove `runpod/` and `vastai/` directories — GPU clouds are explicitly
prohibited per CLAUDE.md and these were orphaned stubs with no
lib/common.sh, no README, and no manifest entries
Fixes#764
Agent: community-coordinator
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
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>
Tests cover parseAuthEnvVars, hasCloudCredentials, cloud sorting by
detected credentials, mapToSelectOptions with hintOverrides, getAuthHint,
getImplementedClouds, and the full interactive picker prioritization flow.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* feat: implement netcup/kilocode integration
Add Kilo Code support on Netcup VPS provider. This fills a missing matrix entry by combining Netcup cloud primitives with Kilo Code agent setup.
Changes:
- netcup/kilocode.sh: New script using Netcup API provisioning + Kilo Code CLI
- netcup/README.md: Added Kilo Code to available agents list
- manifest.json: Updated netcup/kilocode from "missing" to "implemented"
Agent: gap-filler-1
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: address review findings in netcup/kilocode.sh
- Add missing upload_file/run_server args to inject_env_vars_ssh (HIGH -
prevented credential leak where API key was passed as upload_func)
- Add wait_for_cloud_init call after verify_server_connectivity (MEDIUM)
- Add shellcheck source directive and SC2154 disable
- Add server info to completion message
Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Cover _parse_api_response, _update_retry_interval, _api_should_retry_on_error,
calculate_retry_backoff, _cloud_api_retry_loop, generic_cloud_api,
generic_cloud_api_custom_auth, _make_api_request, _make_api_request_custom_auth,
and _curl_api -- all recently refactored with zero prior test coverage.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consistently use log_step for progress/status messages ("Waiting for...",
"Fetching...", "Creating...") and reserve log_info for success/completion
messages. This gives users a clear visual distinction between operations
that are still running (cyan) vs operations that have completed (green).
Also adds periodic progress updates to silent polling loops in ramnode,
cherry, and netcup IP wait functions so users see activity during long waits.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Created missing repo labels: malicious, needs-human-review,
maintenance, team-building
- PR reviewers now label PRs after review:
- security-review-required for CRITICAL/HIGH findings
- security-approved for clean/MEDIUM/LOW PRs
- Added issue-checker agent to review_all mode that monitors stale
issues (no activity >1 hour) and re-triggers review:
- Re-flags safe-to-work issues with no activity
- Re-notifies needs-human-review issues via Slack
- Ensures all open issues have a status label
- Adds Pending Review to un-triaged issues
Co-authored-by: Sprite <noreply@sprites.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When running `spawn` interactively, clouds where the user already has
auth env vars set (e.g. HCLOUD_TOKEN, DO_API_TOKEN) now appear first
in the cloud selection list with a "credentials detected" hint. This
reduces friction by surfacing the most likely-to-succeed options.
Fixes#685
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Replace direct string comparison (!==) with crypto.timingSafeEqual() for
Bearer token authentication, preventing timing side-channel attacks on
TRIGGER_SECRET. Pattern matches existing key-server.ts implementation.
Also validate the `reason` query parameter against an allowlist of known
values to prevent injection of arbitrary strings into the SPAWN_REASON
env var passed to spawned scripts.
Fixes#745
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>