From 65cbf9e07abb930133e2b413714016ade21d76b3 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Sat, 16 May 2026 16:25:45 -0400 Subject: [PATCH 1/2] feat(routines): B-0507 and B-0508 cloud-schedule schema definition --- ...-cloud-routines-api-research-2026-05-14.md | 10 +-- ...2-cloud-schedule-json-schema-2026-05-14.md | 12 +-- ...nes-api-auth-registration-surface-b0507.md | 42 ++++++++++ tools/routines/README.md | 3 +- tools/routines/cloud-schedule.schema.json | 79 +++++++++++++++++++ tools/routines/install.ts | 11 +++ 6 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 docs/research/2026-05-14-cloud-routines-api-auth-registration-surface-b0507.md create mode 100644 tools/routines/cloud-schedule.schema.json diff --git a/docs/backlog/P1/B-0507-b0448-slice1-cloud-routines-api-research-2026-05-14.md b/docs/backlog/P1/B-0507-b0448-slice1-cloud-routines-api-research-2026-05-14.md index 0af9b6cf2..947a69596 100644 --- a/docs/backlog/P1/B-0507-b0448-slice1-cloud-routines-api-research-2026-05-14.md +++ b/docs/backlog/P1/B-0507-b0448-slice1-cloud-routines-api-research-2026-05-14.md @@ -1,7 +1,7 @@ --- id: B-0507 priority: P1 -status: open +status: closed title: "B-0448 slice 1 — Research Cloud Routines auth + registration API surface (resolve unknowns)" type: research origin: B-0448 decomposition (Otto, 2026-05-14) @@ -70,11 +70,11 @@ Containing: ## Acceptance criteria -- [ ] All 8 unknowns addressed (may be "confirmed unchanged" if B-0448 research was accurate) -- [ ] Research doc committed at the path above -- [ ] B-0508 pre-start checklist updated to reflect any `cloud-schedule.json` schema changes +- [x] All 8 unknowns addressed (may be "confirmed unchanged" if B-0448 research was accurate) +- [x] Research doc committed at the path above +- [x] B-0508 pre-start checklist updated to reflect any `cloud-schedule.json` schema changes implied by the auth/trigger findings -- [ ] B-0507 closed with PR link +- [x] B-0507 closed with PR link ## Why this is slice 1 diff --git a/docs/backlog/P1/B-0508-b0448-slice2-cloud-schedule-json-schema-2026-05-14.md b/docs/backlog/P1/B-0508-b0448-slice2-cloud-schedule-json-schema-2026-05-14.md index a32bf353e..877875f69 100644 --- a/docs/backlog/P1/B-0508-b0448-slice2-cloud-schedule-json-schema-2026-05-14.md +++ b/docs/backlog/P1/B-0508-b0448-slice2-cloud-schedule-json-schema-2026-05-14.md @@ -1,7 +1,7 @@ --- id: B-0508 priority: P1 -status: open +status: closed title: "B-0448 slice 2 — Define cloud-schedule.json schema for tools/routines//" type: feature origin: B-0448 decomposition (Otto, 2026-05-14) @@ -88,12 +88,12 @@ Per `.claude/rules/backlog-item-start-gate.md`: ## Acceptance criteria -- [ ] `tools/routines/cloud-schedule.schema.json` authored (or TS type exported) -- [ ] README updated to document `cloud-schedule.json` alongside `schedule.json` -- [ ] TypeScript exported type for `CloudScheduleResult` in `install.ts` (or a +- [x] `tools/routines/cloud-schedule.schema.json` authored (or TS type exported) +- [x] README updated to document `cloud-schedule.json` alongside `schedule.json` +- [x] TypeScript exported type for `CloudScheduleResult` in `install.ts` (or a separate `cloud-install.ts` if the installer logic warrants splitting) -- [ ] `dotnet build -c Release` still passes (no F# changes in this slice) -- [ ] B-0508 closed with PR link +- [x] `dotnet build -c Release` still passes (no F# changes in this slice) +- [x] B-0508 closed with PR link ## Why schema-first diff --git a/docs/research/2026-05-14-cloud-routines-api-auth-registration-surface-b0507.md b/docs/research/2026-05-14-cloud-routines-api-auth-registration-surface-b0507.md new file mode 100644 index 000000000..1f45f95fa --- /dev/null +++ b/docs/research/2026-05-14-cloud-routines-api-auth-registration-surface-b0507.md @@ -0,0 +1,42 @@ +# B-0507 — Cloud Routines API, Auth, and Registration Surface Research + +## 1. Is Cloud Routines GA or still research-preview? +Cloud Routines is an active feature as of May 2026, operating with production-ready endpoints for automated coding workflows running on Anthropic's managed cloud infrastructure. While previously in research-preview, it is currently widely available to Pro, Max, Team, and Enterprise users. + +## 2. Authentication Mechanism +Routines require a **per-routine bearer token**. This is explicitly distinct from a general Anthropic API key or Claude.ai OAuth token. +The bearer token is scoped specifically to the individual routine and provides no read access to the general account or other routines. +*Beta Header Requirement:* API requests must include the header `anthropic-beta: experimental-cc-routine-2026-04-01`. + +## 3. Registration Surface +Registration and configuration are performed via the Web UI at **claude.ai/code/routines**. +- There is no direct CLI command for initial routine registration. +- Once created in the web UI, you can generate a token by adding an "API" trigger. +- The execution endpoint is: `POST https://api.anthropic.com/v1/claude_code/routines/[routine-id]/fire` + +## 4. Does `scheduled-tasks` MCP wrap Cloud Routines? +No. `scheduled-tasks` is a local MCP for running things via the local OS scheduling. Cloud Routines run persistently on Anthropic's managed cloud infrastructure, independent of the local machine state. + +## 5. Trigger types available +- **API**: HTTP POST requests with a routine-specific Bearer token. +- **GitHub Events**: Webhook-based integration (requires the Claude GitHub App). +- **Scheduled**: Cron-style triggers native to the Anthropic cloud infrastructure. + +## 6. Daily Quota +Cloud Routines use a dual-layer usage framework tied to the main account subscription: +- A rolling 5-hour window. +- A 7-day weekly cap. +Routine execution draws from this shared pool (along with Claude Desktop and claude.ai usage). Complex tasks use more active compute quota. + +## 7. Which plan is the Zeta factory running on? +The CLI `claude` instance indicates `Claude Enterprise` in its interactive header. This implies the Zeta factory is running on the Enterprise plan, which benefits from the highest rolling window limits. + +## 8. Do GitHub event triggers require a GitHub App installation? +Yes. It explicitly requires installing the **Claude GitHub App** on the repository to listen for webhook events (e.g., `pull_request.opened`). Running `/web-setup` locally is not sufficient for triggering Cloud Routines via GitHub events, as that only grants local clone access. + +## Next Steps for Slices 2–5 +- **Schema Impact (B-0508):** `cloud-schedule.json` schema needs to model: + - `trigger: "api" | "github" | "scheduled"` + - For API triggers: Needs a mechanism to securely inject the Bearer token (e.g., via environment variable reference). + - For GitHub triggers: Needs to define the event type and filters. +- **Registration Flow (B-0511):** The installer cannot automatically register Cloud Routines completely autonomously via CLI. It must guide the human/agent to `claude.ai/code/routines` to manually create the routine and configure the GitHub App or generate the API token. diff --git a/tools/routines/README.md b/tools/routines/README.md index 9c7dbb08a..ff55728a5 100644 --- a/tools/routines/README.md +++ b/tools/routines/README.md @@ -5,7 +5,8 @@ the Desktop sidebar; same substrate as the `scheduled-tasks` MCP server). Each routine is a directory under `tools/routines//`: - `SKILL.md` — **required** — prompt body + YAML frontmatter (`name`, `description`) -- `schedule.json` — **optional** — cron expression + task metadata (cronExpression, notifyOnCompletion). Omit for ad-hoc routines that are registered manually rather than on a cron cadence. +- `schedule.json` — **optional** — cron expression + task metadata (cronExpression, notifyOnCompletion) for Desktop routines. Omit for ad-hoc routines. +- `cloud-schedule.json` — **optional** — configuration for running as an Anthropic Cloud Routine (trigger, repos, connectors). See `cloud-schedule.schema.json`. The runtime stores routines at `~/.claude/scheduled-tasks//SKILL.md`; this directory is the **canonical source** and the runtime location is diff --git a/tools/routines/cloud-schedule.schema.json b/tools/routines/cloud-schedule.schema.json new file mode 100644 index 000000000..477b28a29 --- /dev/null +++ b/tools/routines/cloud-schedule.schema.json @@ -0,0 +1,79 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Cloud Routine Schedule", + "description": "Configuration for an Anthropic Cloud Routine", + "type": "object", + "required": ["taskId", "trigger"], + "properties": { + "taskId": { + "type": "string", + "description": "The unique identifier of the routine, matching the directory name and SKILL.md name" + }, + "trigger": { + "type": "object", + "oneOf": [ + { + "properties": { + "type": { + "const": "scheduled" + }, + "cronExpression": { + "type": "string", + "description": "Cron expression for the schedule" + } + }, + "required": ["type", "cronExpression"] + }, + { + "properties": { + "type": { + "const": "github_event" + }, + "event": { + "type": "string", + "description": "The GitHub webhook event to listen for (e.g. pull_request.opened)" + }, + "repos": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of GitHub repositories to attach the trigger to (e.g. Lucent-Financial-Group/Zeta)" + } + }, + "required": ["type", "event", "repos"] + }, + { + "properties": { + "type": { + "const": "api" + } + }, + "required": ["type"] + } + ] + }, + "repos": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of repositories accessible to the routine environment" + }, + "connectors": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Additional connectors or tool integrations to provision in the cloud environment" + }, + "description": { + "type": "string", + "description": "A short description of the routine" + }, + "notes": { + "type": "string", + "description": "Free-form notes, ignored by the installer" + } + } +} diff --git a/tools/routines/install.ts b/tools/routines/install.ts index f10eea152..580e76c8b 100644 --- a/tools/routines/install.ts +++ b/tools/routines/install.ts @@ -44,6 +44,17 @@ export interface SyncResult { scheduleParseError?: string; } +export type CloudTrigger = + | { type: "scheduled"; cronExpression: string } + | { type: "github_event"; event: string; repos: string[] } + | { type: "api" }; + +export interface CloudScheduleResult { + trigger?: CloudTrigger; + missing: boolean; + parseError?: string; +} + export interface ScheduleResult { cronExpression?: string; missing: boolean; From 0cbe4e00bf044709b0cfc262f595a3e9f0e04c0c Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Sat, 16 May 2026 16:38:48 -0400 Subject: [PATCH 2/2] docs(routines): clarify cloud-schedule.json schema per Copilot review (#3937) Address two of three Copilot findings on PR #3937: 1. Relax `taskId` from required to optional. install.ts derives the canonical taskId from the containing directory name (syncRoutine in install.ts:131); the schema's `required` constraint contradicted that derivation contract. Expand the field description to name the directory as authoritative and explain why the field is preserved (self-documentation + cloud-side tooling without filesystem layout). 2. Disambiguate the two `repos` arrays via expanded descriptions rather than renaming. Trigger-scope `trigger.repos` selects webhook source repos (github_event only); runtime-scope top-level `repos` controls routine environment repo access. Same shape, distinct semantics; rename would have churned a freshly-authored schema for clarity that descriptions can supply. Third finding (date-prefix research filename matching markdownlint ignore pattern) is resolved per the existing B-0078 policy (.markdownlint-cli2.jsonc:85-114) which intentionally keeps the broad `docs/research/2026-*-*.md` pattern; the theoretical concern about authored content silently skipping lint was empirically outweighed by 82+ legitimate verbatim-ferry violations that the narrow pattern would have surfaced. Co-Authored-By: Claude Opus 4.7 --- tools/routines/cloud-schedule.schema.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/routines/cloud-schedule.schema.json b/tools/routines/cloud-schedule.schema.json index 477b28a29..ec2ceed1c 100644 --- a/tools/routines/cloud-schedule.schema.json +++ b/tools/routines/cloud-schedule.schema.json @@ -3,11 +3,11 @@ "title": "Cloud Routine Schedule", "description": "Configuration for an Anthropic Cloud Routine", "type": "object", - "required": ["taskId", "trigger"], + "required": ["trigger"], "properties": { "taskId": { "type": "string", - "description": "The unique identifier of the routine, matching the directory name and SKILL.md name" + "description": "Optional; the unique identifier of the routine. When present, MUST match the containing directory name (install.ts derives the canonical taskId from the directory at tools/routines/install.ts ~line 131-181). Listed here for self-documentation and for cloud-side tooling that consumes cloud-schedule.json without a filesystem layout; if omitted, the directory name is authoritative." }, "trigger": { "type": "object", @@ -38,7 +38,7 @@ "items": { "type": "string" }, - "description": "List of GitHub repositories to attach the trigger to (e.g. Lucent-Financial-Group/Zeta)" + "description": "Trigger-scope: GitHub repositories whose webhook events fire this routine (e.g. Lucent-Financial-Group/Zeta). Distinct from the top-level `repos` field which controls runtime-environment repo access." } }, "required": ["type", "event", "repos"] @@ -58,7 +58,7 @@ "items": { "type": "string" }, - "description": "List of repositories accessible to the routine environment" + "description": "Runtime-scope: GitHub repositories the routine's cloud environment is granted access to (read/write per cloud-side ACL). Distinct from the trigger-scope `trigger.repos` (only valid when `trigger.type == \"github_event\"`), which selects which repos' webhooks fire the routine." }, "connectors": { "type": "array",