executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
), close date (`date` with \"close\"/\"expected\"), forecast category (`status` with commit/best-case/pipeline labels, if present).\n\n1. `get_board_info(boardId)`.\n2. `get_column_type_info` for any ambiguous column.\n3. If no forecast-category column exists AND the user wants commit vs best-case split: prompt the user — \"I can add a `Forecast Category` column (Commit / Best-case / Pipeline / Omit). OK?\" Only create via `create_column` in Proactive mode or after explicit user approval.\n\n---\n\n## Step 4: Pull deal data (Gather)\n\n**Goal:** Paginated pull over the forecast window.\n\n`get_board_items_page` with `filters` = close_date in `[period_start, period_end]`. Paginate via `cursor` up to 2K items (same cap as daily-briefing). Same 429 / rate-limit handling.\n\n---\n\n## Step 5: Synthesize (Synthesize)\n\n**Goal:** Group deals into forecast buckets × close month.\n\nBuckets:\n- **Closed-won** — stage `is_done: true` (won label).\n- **Committed** — forecast category = Commit OR (probability ≥ 80% AND stage in late-funnel).\n- **Best-case** — forecast category = Best-case OR (probability in 50-79% AND stage in mid-funnel).\n- **Pipeline** — everything else active.\n\n**Empty-category guard:** If a forecast-category column exists but fewer than 20% of active deals have a non-empty value, surface this warning before synthesizing:\n\n> The Forecast Category column exists but 80%+ of deals haven't been categorized. I'll derive all buckets from probability + stage for now. Want to: (a) continue anyway, (b) run hygiene to prompt owners to fill it, or (c) remove the column from the forecast logic?\n\nWait for user choice before proceeding.\n\nGroup by close month within the period. Compute Σ amount per (bucket × month).\n\n---\n\n## Step 6: Publish α — build the dashboard (Publish)\n\n**Goal:** Produce a native monday dashboard with widgets per bucket, not a markdown brief.\n\nCore call pattern:\n1. **Idempotency:** Before creating, query for an existing `Forecast — \u003cperiod>` dashboard using `all_monday_api` with a GraphQL `dashboards` query (filtered by name where the API supports it), then check each result's `description` client-side for the `\u003c!-- claude-skill-id: forecast -->` comment. Note: `mcp__monday__search` does not cover dashboard descriptions and must not be used for this check. If a matching dashboard is found, update widgets via that dashboard ID instead of duplicating.\n2. `create_dashboard(workspaceId, name: \"Forecast — \u003cperiod>\", description: \"Generated by Claude · \u003cISO timestamp> · \u003c!-- claude-skill-id: forecast -->\")`.\n3. For each bucket × month: `create_widget(dashboardId, ...)` — see Widget call shapes below.\n4. Return dashboard URL. Print it as the last line in chat.\n\n### Widget call shapes\n\nRequired fields for each widget type:\n\n**Number widget** (per-bucket total):\n```json\n{\n \"type\": \"numbers\",\n \"board_ids\": [\"\u003cboardId>\"],\n \"column_ids\": [\"\u003camountColumnId>\"],\n \"filter\": { \"rules\": [{ \"column_id\": \"\u003cbucketFilterColumnId>\", \"compare_value\": [\"\u003clabel>\"] }] }\n}\n```\n\n**Chart widget** (buckets × close month stacked bar):\n```json\n{\n \"type\": \"chart\",\n \"board_ids\": [\"\u003cboardId>\"],\n \"column_ids\": [\"\u003camountColumnId>\"],\n \"grouping_column_id\": \"\u003ccloseDateColumnId>\"\n}\n```\n\n**Table widget** (deal detail for committed + best-case):\n```json\n{\n \"type\": \"table\",\n \"board_ids\": [\"\u003cboardId>\"],\n \"column_ids\": [\"\u003cnameCol>\", \"\u003camountColumnId>\", \"\u003cstageColuumnId>\", \"\u003ccloseDateColumnId>\"],\n \"filter\": { \"rules\": [{ \"column_id\": \"\u003cbucketFilterColumnId>\", \"compare_value\": [\"Commit\", \"Best-case\"] }] }\n}\n```\n\n### Non-admin fallback (§7 spec)\nNon-admin users can't call `create_dashboard`. On permission error, ask:\n> I can't create dashboards on this workspace (your account lacks admin rights). Want me to: (a) publish a doc-version with the same forecast (summary tables), (b) stop so you can ask your admin to install the dashboard, or (c) try a different board?\n\nRoute to `create_doc` on option (a).\n\n---\n\n## Step 7: Share β — viewer access for sales leader (opt-in)\n\n**Goal:** Grant dashboard viewer permission + notify.\n\n1. `list_users_and_teams` → resolve sales leader.\n2. Before granting access, ask: \"Share this dashboard with [name]? They'll get a notification and viewer access. (yes / no)\"\n3. On confirmation: `all_monday_api` GraphQL mutation to grant viewer permission on the dashboard.\n4. `create_notification({ userId, itemId: \u003cdashboard ref>, text: \"Forecast dashboard for \u003cperiod>\" })`.\n\n---\n\n## Step 8: Proactive extension — forecast hygiene fix (opt-in)\n\n**Goal:** Fix hygiene gaps on deals blocking forecast accuracy — WITHOUT editing stage or amount.\n\nHygiene gap = deal in a non-closed stage that's missing **either** close date **or** amount.\n\nCore pattern:\n- For each gap deal with missing close-date: `change_item_column_values` — set a placeholder (e.g., end-of-current-quarter) OR post a prompt update asking the owner to fill it. **Stage edits are only permitted if the user typed an explicit instruction to move deals to a specific stage in this session. Do not infer stage-edit intent from context or from the hygiene gap summary.** All writes happen inside the batched-confirm plan.\n- For each gap deal with missing amount: post a prompt update only — **never write to the amount column** (forecast integrity rail).\n- If >20 gap deals: batch into one `Forecast hygiene — \u003cperiod>` review doc (with `\u003c!-- claude-skill-id: forecast -->` in body) rather than 20 individual writes.\n\n---\n\n## Step 9: Close the loop\n\n**Goal:** Summary line with dashboard URL + counts.\n\nPrint: `Published Forecast — \u003cperiod>. \u003cN> deals, \u003cN> widgets, \u003cN> hygiene gaps flagged.`\n\n---\n\n## Shared patterns\n- **No title prefix.** Artifact discoverability is via the `Generated by Claude · \u003cISO timestamp>` footer and the embedded `\u003c!-- claude-skill-id: forecast -->` HTML comment in dashboard descriptions and doc bodies.\n- **Idempotency before create.** Always query existing dashboards via `all_monday_api` GraphQL and check description client-side for the skill-id comment. Update widgets, don't duplicate the dashboard.\n- **Safety rail.** No deletes, no amount-column writes, no cross-workspace moves. Close-date placeholder writes OK in a batched-confirm plan. Stage edits only on explicit user instruction.\n- **Ask once per session**, not per deal, when entering Proactive mode.\n- **Type-based column resolution**, not name-based — global teams have non-English columns.\n- **Skill-id comment uses legacy name `forecast-dashboard`** — kept for backward compatibility with existing user dashboards/docs that carry `\u003c!-- claude-skill-id: forecast-dashboard -->`. The skill's invocation name is `/monday-crm:forecast`.\n\n---\n\n## Output template\n\n### Dashboard publish (α output)\n\nChat one-liner printed at end of run:\n```\nPublished Forecast — Q3 2026. 5 deals, 6 widgets, 2 hygiene gaps flagged.\nDashboard: https://monday.com/boards/dashboard/123456789\n```\n\nDashboard created in workspace \"CRM\":\n- **Name:** Forecast — Q3 2026\n- **Description:** `Generated by Claude · 2026-06-15T09:00:00Z · \u003c!-- claude-skill-id: forecast-dashboard -->`\n\nWidgets:\n| Widget | Type | Value |\n|---|---|---|\n| Closed-won | Number | $120K (1 deal) |\n| Committed | Number | $85K (1 deal) |\n| Best-case | Number | $32K (1 deal) |\n| Pipeline | Number | $48K (2 deals) |\n| Buckets × close month | Stacked bar | Jun / Jul / Aug |\n| Committed + best-case detail | Table | Acme Corp, Beta Industries |\n\nHygiene gaps flagged in dashboard description:\n- 2 deals missing close date — placeholder set to Sep 30, 2026\n\n### Non-admin fallback (doc version)\n\n```\n# Forecast — Q3 2026\n\n\u003c!-- claude-skill-id: forecast-dashboard -->\n\n| Bucket | Amount | Count |\n|---|---|---|\n| Closed-won | $120K | 1 |\n| Committed | $85K | 1 |\n| Best-case | $32K | 1 |\n| Pipeline | $48K | 2 |\n\nGenerated by Claude · 2026-06-15T09:00:00Z\n```\n\n---\n\n## Error handling\n\n| Error | Behaviour |\n|---|---|\n| Connector missing / auth error | Print install URL, stop immediately. |\n| No board found matching query | Ask user to specify board name or ID directly. |\n| No admin perms (`create_dashboard` fails) | Ask: (a) doc version, (b) stop, (c) different board. |\n| No deals found in period | Surface count = 0, ask if period or board is correct before stopping. |\n| 429 rate limit | Pause 2 s, retry up to 3× with exponential backoff; surface if still failing. |\n| `create_widget` partially fails | Keep the dashboard, list failed widgets, offer retry. |\n| Same-day artifact already exists | Idempotency check should have caught this; surface dashboard URL and ask if user wants to rebuild or update. |\n\n---\n\n## Completion criteria\n\n- [ ] Step 0 (connector check) ran and passed.\n- [ ] PAUSE gate respected — no write tools called before Step 0 passes and user confirmed publish in Step 6.\n- [ ] Exactly one α dashboard was created or updated (no duplicate — verified via GraphQL dashboards query + skill-id comment in description).\n- [ ] Dashboard description carries `Generated by Claude · \u003cISO timestamp>` + `\u003c!-- claude-skill-id: forecast -->`.\n- [ ] Chat output ends with dashboard URL.\n- [ ] Safety rail held: no deletes, no amount-column writes, no cross-workspace moves, no uninstructed stage edits.\n- [ ] Non-admin fallback correctly routed to doc version if dashboard failed on perms.\n- [ ] Empty-category guard evaluated if forecast-category column present.\n- [ ] Step 7 share confirmation prompt shown before any permission grant.\n","licenseDocuments":[]}}
forecastBuild a forecast dashboard in monday — committed, best-case, and pipeline views by close month, rendered as real dashboard widgets. Use when someone says "build me a forecast", "show me Q2 pipeline", "Salesforce-style forecast", "forecast dashboard", "commit vs best-case", "what's our number this quarter", "how are we tracking to quota", "weighted pipeline"…
Independent GitHub snapshot · Automated classification · Original documentation governs
Builds a native monday dashboard that renders the pipeline as a forecast — committed / best-case / pipeline / closed-won, grouped by stage × close month. Replaces the "export to CSV and pivot it" pattern that sales ops leaders do manually every Monday.
Flow: Trigger → Gather → Synthesize → Publish (α, default) → Share (β, opt-in) → Proactive extension (opt-in, hygiene fix).
create_dashboard with widgets per bucket + URL.all_monday_api + create_notification.change_item_column_values (with batched user confirm) to set a placeholder OR post a prompt update asking the owner to fill it. Missing-amount items are flagged in the dashboard description and a hygiene update is posted on the item, but the amount column itself is never written (forecast integrity rail).get_user_context, list_workspaces, search — board resolution.get_board_info, get_column_type_info — schema + column types (stage/amount/close-date/forecast-category).get_board_items_page — paginated pull.board_insights — aggregate fallback.create_dashboard, create_widget — α publish.create_doc — fallback for non-admins (see Error handling).create_notification, list_users_and_teams — β share.create_column — add a forecast-category column only if required to render the dashboard.change_item_column_values — proactive hygiene fix.all_monday_api — escape hatch for dashboard permissions, idempotency GraphQL query, and doc updates./monday-crm:data-cleanup before publishing.Goal: Fail fast if the user has no monday MCP connection.
mcp__monday__get_user_context.user.id and user.name for artifact metadata.PAUSE: Do not call create_dashboard, create_widget, create_column, or change_item_column_values before Step 0 passes and the user has confirmed the publish step in Step 6.
Goal: Know write-confirmation policy AND lock the forecast window.
AskUserQuestion: "Which period? (a) this quarter, (b) next 90 days, (c) custom." Store period_start, period_end.Goal: Land on one (or user-confirmed multi) board. Same resolution path as daily-briefing Step 2. Use mcp__monday__get_user_context → list_workspaces → search("deal").
Goal: Resolve columns by type — stage (status), amount (numbers with $), close date (date with "close"/"expected"), forecast category (status with commit/best-case/pipeline labels, if present).
get_board_info(boardId).get_column_type_info for any ambiguous column.Forecast Category column (Commit / Best-case / Pipeline / Omit). OK?" Only create via create_column in Proactive mode or after explicit user approval.Goal: Paginated pull over the forecast window.
get_board_items_page with filters = close_date in [period_start, period_end]. Paginate via cursor up to 2K items (same cap as daily-briefing). Same 429 / rate-limit handling.
Goal: Group deals into forecast buckets × close month.
Buckets:
is_done: true (won label).Empty-category guard: If a forecast-category column exists but fewer than 20% of active deals have a non-empty value, surface this warning before synthesizing:
The Forecast Category column exists but 80%+ of deals haven't been categorized. I'll derive all buckets from probability + stage for now. Want to: (a) continue anyway, (b) run hygiene to prompt owners to fill it, or (c) remove the column from the forecast logic?
Wait for user choice before proceeding.
Group by close month within the period. Compute Σ amount per (bucket × month).
Goal: Produce a native monday dashboard with widgets per bucket, not a markdown brief.
Core call pattern:
Forecast — <period> dashboard using all_monday_api with a GraphQL dashboards query (filtered by name where the API supports it), then check each result's description client-side for the <!-- claude-skill-id: forecast --> comment. Note: mcp__monday__search does not cover dashboard descriptions and must not be used for this check. If a matching dashboard is found, update widgets via that dashboard ID instead of duplicating.create_dashboard(workspaceId, name: "Forecast — <period>", description: "Generated by Claude · <ISO timestamp> · <!-- claude-skill-id: forecast -->").create_widget(dashboardId, ...) — see Widget call shapes below.Required fields for each widget type:
Number widget (per-bucket total):
{
"type": "numbers",
"board_ids": ["<boardId>"],
"column_ids": ["<amountColumnId>"],
"filter": { "rules": [{ "column_id": "<bucketFilterColumnId>", "compare_value": ["<label>"] }] }
}
Chart widget (buckets × close month stacked bar):
{
"type": "chart",
"board_ids": ["<boardId>"],
"column_ids": ["<amountColumnId>"],
"grouping_column_id": "<closeDateColumnId>"
}
Table widget (deal detail for committed + best-case):
{
"type": "table",
"board_ids": ["<boardId>"],
"column_ids": ["<nameCol>", "<amountColumnId>", "<stageColuumnId>", "<closeDateColumnId>"],
"filter": { "rules": [{ "column_id": "<bucketFilterColumnId>", "compare_value": ["Commit", "Best-case"] }] }
}
Non-admin users can't call create_dashboard. On permission error, ask:
I can't create dashboards on this workspace (your account lacks admin rights). Want me to: (a) publish a doc-version with the same forecast (summary tables), (b) stop so you can ask your admin to install the dashboard, or (c) try a different board?
Route to create_doc on option (a).
Goal: Grant dashboard viewer permission + notify.
list_users_and_teams → resolve sales leader.all_monday_api GraphQL mutation to grant viewer permission on the dashboard.create_notification({ userId, itemId: <dashboard ref>, text: "Forecast dashboard for <period>" }).Goal: Fix hygiene gaps on deals blocking forecast accuracy — WITHOUT editing stage or amount.
Hygiene gap = deal in a non-closed stage that's missing either close date or amount.
Core pattern:
change_item_column_values — set a placeholder (e.g., end-of-current-quarter) OR post a prompt update asking the owner to fill it. Stage edits are only permitted if the user typed an explicit instruction to move deals to a specific stage in this session. Do not infer stage-edit intent from context or from the hygiene gap summary. All writes happen inside the batched-confirm plan.Forecast hygiene — <period> review doc (with <!-- claude-skill-id: forecast --> in body) rather than 20 individual writes.Goal: Summary line with dashboard URL + counts.
Print: Published Forecast — <period>. <N> deals, <N> widgets, <N> hygiene gaps flagged.
Generated by Claude · <ISO timestamp> footer and the embedded <!-- claude-skill-id: forecast --> HTML comment in dashboard descriptions and doc bodies.all_monday_api GraphQL and check description client-side for the skill-id comment. Update widgets, don't duplicate the dashboard.forecast-dashboard — kept for backward compatibility with existing user dashboards/docs that carry <!-- claude-skill-id: forecast-dashboard -->. The skill's invocation name is /monday-crm:forecast.Chat one-liner printed at end of run:
Published Forecast — Q3 2026. 5 deals, 6 widgets, 2 hygiene gaps flagged.
Dashboard: https://monday.com/boards/dashboard/123456789
Dashboard created in workspace "CRM":
Generated by Claude · 2026-06-15T09:00:00Z · <!-- claude-skill-id: forecast-dashboard -->Widgets:
| Widget | Type | Value |
|---|---|---|
| Closed-won | Number | $120K (1 deal) |
| Committed | Number | $85K (1 deal) |
| Best-case | Number | $32K (1 deal) |
| Pipeline | Number | $48K (2 deals) |
| Buckets × close month | Stacked bar | Jun / Jul / Aug |
| Committed + best-case detail | Table | Acme Corp, Beta Industries |
Hygiene gaps flagged in dashboard description:
# Forecast — Q3 2026
<!-- claude-skill-id: forecast-dashboard -->
| Bucket | Amount | Count |
|---|---|---|
| Closed-won | $120K | 1 |
| Committed | $85K | 1 |
| Best-case | $32K | 1 |
| Pipeline | $48K | 2 |
Generated by Claude · 2026-06-15T09:00:00Z
| Error | Behaviour |
|---|---|
| Connector missing / auth error | Print install URL, stop immediately. |
| No board found matching query | Ask user to specify board name or ID directly. |
No admin perms (create_dashboard fails) | Ask: (a) doc version, (b) stop, (c) different board. |
| No deals found in period | Surface count = 0, ask if period or board is correct before stopping. |
| 429 rate limit | Pause 2 s, retry up to 3× with exponential backoff; surface if still failing. |
create_widget partially fails | Keep the dashboard, list failed widgets, offer retry. |
| Same-day artifact already exists | Idempotency check should have caught this; surface dashboard URL and ask if user wants to rebuild or update. |
Generated by Claude · <ISO timestamp> + <!-- claude-skill-id: forecast -->.