Skip to main content

Recurring Automations

Single source of truth for every SecurityV0 automation that fires on a schedule or recurring trigger. If it runs without a human in the loop, it is listed here with its ownership, failure surface, and pause instructions.

Registry

#RoutineCadenceHostOwnerStatus
1Daily AI Security ScanDaily 08:00 owner-local TZclaude.ai RoutineIvan FofanovActive
2Weekly Incident ResearcherMonday 08:00 UTCGitHub Actions (sv0-intelligence)Ivan FofanovActive (legacy fallback)
3Project Management CleanupTBDTBDIvan FofanovPlanned

Daily AI Security Scan

Purpose. Scan public AI-security signal sources each morning; research the top candidate; cross-review with an Opus critic and a Sonnet fact-checker; raise a PR on sv0-website when both agree; notify Slack either way. Human PR review is the only merge gate — the routine never merges on its own.

Schedule. Daily at 08:00 in the routine owner's configured local timezone. Routines are owner-TZ, not UTC; wall-clock UTC therefore varies by DST. Anthropic-applied stagger may delay the actual fire by a few minutes.

Host. claude.ai Routine, executing as the owner's claude.ai user against Anthropic's cloud infrastructure.

Skill. SecurityV0/sv0-skillsdaily-ai-security-scan/SKILL.md (9-step playbook). Skill directory contents:

  • SKILL.md — the orchestration playbook
  • queries.yaml — WebSearch query catalog (4 categories, 13 queries), RSS fallback sources, NVD keyword list
  • prompts/researcher.md — Opus; produces the structured research brief (incident summary, authority-path analysis, SV0 taxonomy mapping, claim inventory, novelty assessment, disqualifiers)
  • prompts/critic.md — Opus; publishability rubric (ai_relevance, authority_failure_fit, sv0_finding_fit, newsworthiness)
  • prompts/fact-check.md — Sonnet; independent claim verification using sources different from those cited in the brief
  • prompts/post-template.md — the house 4-section post template with taxonomy, hard rules, and frontmatter schema

Output surface. PR on SecurityV0/sv0-website against main, branch claude/daily-scan-YYYY-MM-DD-<slug>, file at src/content/blog/YYYY-MM-DD-<slug>.md. Published at securityv0.com/intelligence/<slug>/ after human merge and the staging → production approval gate.

Notification surface. Slack, via a workflow_dispatch bridge on SecurityV0/sv0-website/.github/workflows/notify-slack.yml. The routine calls the REST dispatch endpoint; the workflow reads SLACK_WEBHOOK and posts formatted Block Kit to the configured channel. Three kinds: published, skipped, error. Rationale for the dispatch bridge rather than a native Slack connector: the incoming-webhook credential is scoped to one channel and post-only, whereas a native Slack connector would grant full workspace read/write to autonomous routine code — a blast-radius mismatch for a notification-only use case.

Secrets.

SecretLocationScopeUsed by
GITHUB_TOKENRoutine env var (claude.ai Routines config)Fine-grained PAT on SecurityV0/sv0-website only — actions:write, metadata:read. 90-day expiry.Routine, for calling the notify-slack.yml REST dispatch endpoint
SLACK_WEBHOOKRepo secret: SecurityV0/sv0-website → Settings → Secrets → ActionsSlack Incoming Webhook URL, channel-scoped, post-onlynotify-slack.yml workflow only

The routine never sees SLACK_WEBHOOK; the workflow never sees GITHUB_TOKEN. Credential isolation is the reason the bridge exists.

Failure modes.

  • Setup failure (gh + GITHUB_TOKEN both unavailable, or skill file missing): kind=error Slack post, exit non-zero, no PR.
  • Zero candidates after dedup: kind=skipped Slack post with reason, exit success, no PR.
  • Researcher / critic / fact-check returns SKIP: kind=skipped Slack post with the verdict summary, exit success, no PR.
  • PR creation fails: kind=error Slack post, exit non-zero.
  • Slack dispatch itself fails: logged to stderr; no recovery (Slack is best-effort). If the PR was already created it remains visible.

Manual trigger. Click "Run now" on the routine's page in claude.ai Routines UI. Equivalent to waiting for the next cron fire; useful for smoke-testing changes to the skill.

Pause / disable. Toggle the routine off in claude.ai Routines UI. The skill files, workflow, and secrets remain intact and the routine can be re-enabled with one click.

Dedup state. None persisted. Dedup checks the src/content/blog/ directory and gh search prs --state all on sv0-website at runtime. A "considered but skipped" candidate may resurface tomorrow; v1 relies on natural newsworthiness decay rather than a persistent skip log. Reconsider if this produces retry churn; candidate storage pattern sketched in the spec (deferred item).

Design spec. sv0-intelligence/docs/specs/2026-04-20-daily-ai-security-scan-design.md (design branch design/daily-ai-security-scan). Implementation plan: sv0-intelligence/docs/plans/2026-04-20-daily-ai-security-scan.md.

Key PRs.

  • sv0-website #39 — notify-slack.yml dispatch workflow (merged 2026-04-21)
  • sv0-skills #23 — initial skill + symlink (merged 2026-04-22)
  • sv0-skills #24 — curl fallback for Routine sandbox (merged 2026-04-22)
  • sv0-skills #25 — executive Slack fields extraction (pending)
  • sv0-website #45 — executive Block Kit layout (pending)

Live output to date. Intelligence Monitor posts published from the daily scan:

  • 2026-04-22-anthropic-mcp-stdio-design-flaw-rce (sv0-website PR #43)
  • 2026-04-22-anthropic-action-comment-and-control (sv0-website PR #44)
  • 2026-04-23-automagik-npm-canisterworm (latest)

Weekly Incident Researcher

Purpose. Original weekly AI-incident pipeline. Gathers public signals (RSS + NVD + AI Incident DB), scores with Claude, generates blog post + LinkedIn draft, opens PR on sv0-website. Kept active as a fallback while the daily scan stabilizes.

Schedule. Monday 08:00 UTC (GitHub Actions cron: 0 8 * * 1).

Host. GitHub Actions on SecurityV0/sv0-intelligence, workflow .github/workflows/weekly-incident.yml.

Implementation. Python pipeline under sv0-intelligence/researchers/weekly_incident/ (gather → score → generate → publish). Dual-mode: Anthropic SDK when ANTHROPIC_API_KEY is set (in CI), claude -p CLI otherwise (local/Claude Max).

Output surface. PR on SecurityV0/sv0-website. LinkedIn copy attached to the PR body.

Notification surface. None (pre-Slack-integration era). Surfaces via GitHub Actions run status and the PR itself.

Secrets.

SecretLocationScope
ANTHROPIC_API_KEYGitHub Actions secret on sv0-intelligenceClaude API access
GH_TOKENGitHub Actions secret on sv0-intelligenceWrite access to both sv0-intelligence and sv0-website

Failure modes. Non-zero exit from the pipeline surfaces as a failed run in GitHub Actions. No Slack notification; operator checks gh run list periodically.

Manual trigger. workflow_dispatch via GitHub UI or gh workflow run weekly-incident.yml --repo SecurityV0/sv0-intelligence. Dry-run supported via workflow input.

Pause / disable. Remove the schedule block from weekly-incident.yml, or disable the workflow in the Actions tab.

Deprecation plan. Delete the weekly cron once the daily scan has produced two merged PRs from live routine runs. This bar has been met (three merged as of 2026-04-23). Deprecation is low-priority; the weekly pipeline is cheap insurance. Revisit after one more week of stable daily operation.

Project Management Cleanup (planned)

Placeholder. Scope and host to be specified before implementation. Expected shape: recurring check on open issues and PRs across the SV0 repo set, flagging stale items and suggesting triage. Whether it lives as a claude.ai Routine, a GitHub Actions cron, or a Mac Mini scheduler task is undecided.

Adding a New Routine

When adding a new recurring automation, do these six things before merging the implementation:

  1. Decide host. claude.ai Routine (user-owned, usage-capped, cloud-hosted), GitHub Actions cron (repo-owned, CI quota, GitHub-hosted), or local (Mac Mini scheduler). Each has different ownership, SPOF, and secret-management properties; pick deliberately.
  2. Author the artifact. Skill (sv0-skills or .claude/skills/ in the target repo), GitHub Actions workflow, or script. Follow the existing examples.
  3. Configure secrets explicitly. Decide where each secret lives and what its minimum scope is. Document it in the per-routine section here, not just in the code.
  4. Set up the notification surface. Decide how the operator learns about success, skip, and error. Slack via the existing notify-slack.yml dispatch bridge is the default pattern — reuse it unless there is a specific reason to diverge.
  5. Register the routine here. Add a row to the Registry table and a detail section below, using the same shape as the existing entries.
  6. Update mkdocs nav if the page hierarchy changes. For a single new routine added to this page, no nav change needed.

See Also