~/.config/graph/plans/) against a Linear workspace; the lessons transfer to any MCP source.
project_status — solver report, resilient references
A status report for a Linear project: metadata → milestones → 14 days of issues → latest human status updates → synthesized report.
- Later steps pass the project by name (
{{E0.projects.0.name}}) — one canonical deep reference instead of chained ids. A bad project name produces exactly one cleanEmptyDataoutcome. - The solver template conditionally includes a Milestones section only when milestones exist:
- Real-world constraint encoded as a comment in the plan: Linear’s API rejects
includeMilestoneson project listing (query complexity), so milestones are their own step.
sprint_analysis — strict output via a grammar
Ported from graph’s predecessor. Its solver template pins the report structure with a context-free grammar, which buys week-over-week consistency:
- A grammar (or any rigid spec) in
query_to_answeris the tool for reports that get diffed or posted on a schedule — prose specs drift more. - The plan handles “team has no active cycle” honestly via an inverted section that switches the instructions:
- Aggregation (ticket counts, story points) is done by the solver from raw data — no computation in templates, by design.
Recipe: scheduled report to Slack
A solver plan on cron — stdout is the deliverable, so delivery is a pipe:slack pack enabled, delivery can live in the plan instead of the pipe: a final builtin__slack_post_message step posts the report and returns the message ts, so a follow-up step can thread details under it. Prefer the tool when the plan owns delivery and a failed post should fail the run; prefer the webhook pipe when stdout is the deliverable and the shell owns delivery (a webhook needs no app scopes or channel invite).
Run it with GRAPH_STORAGE=memory in the cron environment when it should leave no state behind (scripting contract).