Weekly planning
Every Monday last week's GTM work is ranked against active initiatives, declared infra, and live runs, as one reviewable pull request per initiative — or one workspace pull request when there are none.
Set up the weekly-planning cookbook in this project.
1. If the Cargo CLI is not installed yet, follow every step in https://api.getcargo.io/INSTALL.md
2. From the Cargo project, run: cargo-ai cdk add cookbook/weekly-planning
3. Then follow .claude/skills/weekly-planning/SKILL.md. Stop for my approval before any paid call, and stop at "cargo-ai project plan" before deploying anything.$cargo-ai cdk add cookbook/weekly-planningSay this to your agent
Every Monday morning, check last week's runs against our initiatives and open one pull request per initiative saying what to do next.
Illustrative output #
Fictional records, to show the shape of what comes back.
[cadence] eu-outbound 2026-W41 -> cadence/plan/2026-W41-eu-outbound.md
---
title: 2026-W41 EU outbound
description: Blocked. The sourcing play is declared but did not run once this week.
week: 2026-W41
target: eu-outbound
---
## What you will be asked
| Input | | Why |
| --- | --- | --- |
| `PLANNING_TIMEZONE` (`infra/agents/planner.ts`) | Looked up | The previous ISO week is computed in this timezone. A timezone the collector does not share with the prompt splits the dump and the plan files across two weeks. |
## Done when
- `--dry-run` printed the dump for the previous ISO week, and the run without it wrote `cadence/log/raw/planning/<YYYY-Www>.md`; running it twice that Monday overwrote the same file
- `node --import tsx evals/contract.mjs` passes: harness is `claudeCode` bound to an Anthropic connector and a model, no capability is wired on the agent, there is no Slack action, and no tool wraps git or the CLI
- `cargo-ai cdk plan` reports the agent, the GitHub and Anthropic connectors and the folder, and does **not** run git or `gh` while planning
- with **zero** active initiatives, the first scheduled run opened exactly one unmerged pull request titled `[cadence] workspace <YYYY-Www>` whose diff contains the dump and `cadence/plan/<YYYY-Www>.md` with `## Recommendations`
- with **N** active initiatives, it opened exactly N unmerged pull requests, one per slug, each diff containing the dump and exactly one `cadence/plan/<YYYY-Www>-<slug>.md` — never a second initiative in the same diff — plus one `[cadence] unplanned <YYYY-Www>` pull request only when work no initiative claims met the bar in the prompt
- every plan file's `description` and PR body open with the same verdict (On track, Behind, At risk, Blocked, Unplanned, or No active initiatives), and every recommendation names an action and a day
- a re-run the same Monday opened no additional pull request for a target whose `## Recommendations` section was already on disk
- no number in a plan file is absent from the raw dump, a metrics file dated that week, or a `cargo-ai` read the agent actually ran. A CLI read that errors is a note on the PR, not a made-up count
## What it costs
The collector talks to git and, when `gh` is installed, to GitHub from the harness environment.
Those calls are not Cargo connector actions.
The recurring cost is the harness run itself, once a week, billed as LLM tokens through the bound
Anthropic connector, and it scales with how much the agent reads — the dump, the week's cadence
files, the active initiative files, declared infra, and the read-only `cargo-ai` calls in §1b
(whoami, what is deployed, run counts, usage). Those reads are API calls, not connector actions, so
they bill nothing. There is no per-record fan-out, and the recap never runs a command that spends.
Turn last week’s GTM work into recommendation files a reviewer can merge: ranked against active initiatives, declared infra, and live runs. Collected by a committed script, judged by a Claude Code harness agent, delivered as one pull request per initiative — or one workspace pull request when there are none.
What it does #
- Collects.
scripts/collect/week.tsdumps the previous ISO week’s git commits, pull requests, initiative inventory, declared infra, and cadence files dated in that week intocadence/log/raw/planning/. Deterministic, no LLM anywhere near it. - Reads the workspace. The agent runs read-only
cargo-aicommands (what is deployed, runs, usage). No capability is wired on it. Ifcargo-ai whoamifails, it notes that on every pull request and continues from the dump. - Recommends. Zero active initiatives: one file,
cadence/plan/<week>.md. N active: one file per initiative,cadence/plan/<week>-<slug>.md. - Stops. One unmerged pull request per file. Never a deploy. Never a Slack post — standup already owns the daily channel.
How it works #
- The cron trigger fires at 15:00 UTC Monday (8am PT during PDT), after Sunday’s standup has landed.
- The agent clones the repository — the project’s own, resolved from the checkout’s git origin at deploy rather than written down.
- It runs the collector —
npx tsx scripts/weekly-planning/collect/week.ts— which readsPLANNING_TIMEZONEfrom the harness environment. The agent is told not to fetch the week itself. - It reads the workspace with Cargo’s own CLI, which the checkout already
has:
whoami, what is deployed, last week’s run counts and failures, usage. - It writes the plan file(s) and opens the pull requests from step 2 of the prompt: one per active initiative, or one workspace pull request.
- A human merges. The agent never does.
Adds 4 resources plus a script bundle.
| File | Resource | Role |
|---|---|---|
infra/agents/planner.ts | defineAgent (claudeCode) | schedule, repository binding, env |
infra/agents/planner.prompt.ts | (not a resource) | the recap contract: window, one-PR-per-initiative rule, limits |
infra/connectors/git.ts | defineConnector (github) | the clone, branch, push and PR path, resolved by binding |
infra/connectors/anthropic.ts | defineConnector (anthropic) | the model the harness runs on, billed and metered |
infra/folders/index.ts | defineFolder | the workspace folder this pipeline’s resources are filed in |
scripts/collect/week.ts | (not a resource) | the entrypoint: dump git / gh / initiatives / infra for the week |
The two halves, and where they land #
This pipeline has one directory per layer it touches, and the install mirrors each into its namesake in the project:
weekly-planning/infra/ -> infra/weekly-planning/ what is declared and deployed
weekly-planning/scripts/ -> scripts/weekly-planning/ what the agent runs
Those are the layers cargo-ai cdk init already scaffolds — infra/ is the CDK
project, scripts/ is “imperative glue for runtime surfaces the CDK cannot
declare yet” — so a pipeline that needs both contributes to both under its own
name rather than inventing a third place.
scripts/package.json is belt and braces. In a Manifest repo the CDK project
root is infra/, so nothing under scripts/ is ever imported as a resource.
In a project whose CDK root is the repo root, the loader imports every .ts it
finds except directories carrying a package.json — without that file,
cargo-ai cdk plan would import the collector and run git/gh on every plan.
Why the split #
The collection and the judgement are different jobs, and the failure modes for mixing them are not symmetric.
A fetch loop an agent re-derives every Monday is a fetch loop that silently
changes shape: a window that drifts, a gh flag that quietly widens. Nothing
downstream can tell, because the dump is what everything downstream is diffed
against. So the fetch is a committed script and the agent is told not to
improvise it.
The recommendation is the opposite. It is judgement — which initiative is idle,
whether a declared play ran, who owns the next step — and it produces one diff
per bet. That is what harness: "claudeCode" buys: a working tree, the git
history to read before writing, and a pull request. It does not buy its own
model: the harness runs against Cargo’s LLM proxy, so connector and
languageModel are required here exactly as they are on a streamText agent,
and they are what the run is billed and metered against.
Why one pull request per initiative #
A single weekly diff with five initiatives in it is how the loud bet gets merged and the overdue one rides along unread. Split them, and a reviewer can merge one and send another back.
Zero active initiatives is the empty-queue case that still has something to say: the workspace, the infra, the runs. That is one pull request, not zero, because a quiet repo with plays that ran (or did not) is still a finding.
Unclaimed runs — a play no active initiative names — stay in the dump. They are not a sixth pull request. Mention them in an initiative file only when they compete with that initiative.
Placeholders (edit before deploy) #
PLANNING_TIMEZONE—infra/agents/planner.ts: IANA timezone the previous ISO week is computed in. Change it together withcron.languageModel— same file: any Anthropic model the workspace’s connector can reach.claudeCodepairs with theanthropicintegration and nothing else.
What it does not do #
It does not contact customers, write to a CRM, merge its own pull request, run
a CLI command that spends or deploys, edit or delete a raw dump or an
existing recommendation file, promote first-occurrence claims into context/,
or touch plan/ and infra/. It recommends the week; it does not change the
strategy or the deployed engine. It does not post to Slack — that is standup.