Cowork Rollup
A read-only rollup of what your plugins did in Claude Cowork: every run, its outcome and counts, and the brain state behind it — assembled from the telemetry and brain sync the control-plane MCP receives.
Overview
The work happens in Cowork; this is where you see the result on salesascode.com. Every skill reports emit_telemetry when it finishes and sync_brain for the brain files it touched. The rollup at /rollup turns that stream into a per-account cockpit.
Scoped to your account. A run by your plugins never appears on anyone else's rollup.
What it shows
- What changed (last 30 days). Real output, not just run counts — the totals each plugin reported (emails drafted, meetings prepped, hours saved, and any other numbers a skill emits), plus runs and "actions" this week versus last week and this month versus last with the percentage change. "This month" is the trailing 30 days compared to the 30 days before them — rolling windows of equal length, so opening the page on the 2nd never compares two days against a full month. Outcome totals come straight from the
countsa skill sends toemit_telemetry; no extra wiring. - Plugin health. Every plugin you own and whether it is working: "Healthy", "Not started yet" (licensed but never run — the clearest signal to act on), or "Last run failed". A header tally flags how many are erroring or unused. This shows even before anything has run, so a freshly licensed account immediately sees its plugins listed.
- By plugin. A card per plugin with total runs, the last run time, any errors, and a runs-per-day trend sparkline (see below). Each plugin name links to its per-plugin drill-down (see below).
- Recent runs. The latest runs across all plugins — plugin, skill, outcome, the counts line the skill produced, and when. Failed runs carry a categorized error badge (see below), and every row links to its run drill-down page.
- Brain state. One row per scope (signal-weights, icp-registry, decision-log, funnel-brain, content calendar, and so on) with its latest sync time, key and snapshot counts, and a change highlight — e.g. "+5 keys · 2 changed since last sync 3d ago". Each row links to that scope's full snapshot timeline (see below).
- Plugin coordination. A dependency + data-flow diagram over your licensed plugins, with missing-dependency and stale-upstream warnings (see below).
- Drafts ready to send. Outreach drafted for you overnight, waiting on your review (see below).
- Your hosted drafts. When your plan runs skills server-side (the hosted runtime) and you've turned on delivery, the AI's drafts land here — each expandable to read in full, with a Dismiss to clear it once you've used it. Draft-only: nothing is ever sent on your behalf. The card hides itself until a draft arrives.
- Questions to ask. Worked deals with a real gap in what you know, and the specific question to close it (see below).
Drafts ready to send
Overnight, a scheduled agent reads your account signals and drafts outreach for the contacts worth a touch that day. Those drafts land in the Drafts ready to send card, highest-quality first. Nothing is ever sent for you — every send is an explicit click.
- Send. Emails the draft as written, via your connected Gmail.
- Use my edits. Edit the draft in place, then toggle this before sending to send your version instead of the original. Your edits are recorded and feed back into how future drafts are written.
- Skip. Drops the draft — no send, no re-surface.
- Snooze 24h. Re-surfaces the same draft tomorrow.
A draft with no email address on the contact shows "no email" and can't be sent until you add one. Leads sourced from someone engaging with your content appear on Content Studio under Warm leads instead, so the same person never shows up in both places.
Questions to ask
Overnight, a scheduled agent looks at your worked deals — the ones past qualification, with a live close date and real MEDDPICC evidence — and finds the specific thing you still don't know about each: no economic buyer named, no decision process mapped, no compelling metric quantified. For each gap it drafts the actual question to ask that buyer next, in a discovery style that opens a conversation instead of inviting a one-word answer.
- Ask this first. Each deal leads with the single highest-leverage question — the one you can't leave the next conversation without asking.
- Asked it. Marks the question handled and retires the card. The record is kept, not deleted.
- Dismiss. Drops it if it's not useful.
Only worked deals ever appear here — a deal you opened yesterday won't generate "ask who the economic buyer is", because an unstarted deal is supposed to have gaps. So an empty card means "nothing worth asking right now", never noise. Questions surface only once your pipeline actually holds opportunities with MEDDPICC detail; until then the card stays quiet.
Brain-state timeline
Brain sync is append-only, so every scope keeps a history of snapshots. The Brain State card links each scope to /rollup/brain/[scope], where you can see how that brain evolved:
- Sync timeline. An inline chart (no external libraries) with one dot per sync, oldest to newest. A filled dot changed the brain; a hollow dot re-synced with no key changes; a grey dot is the first sync. Hover a dot for its date, key count, and change count.
- Snapshots & changes. A feed of every sync, newest first, and exactly what changed versus the one before it — keys added, changed, or removed, plus a count of unchanged keys. The card highlights on the rollup are the diff of the two most recent snapshots.
- Metadata only. The timeline shows top-level key names and counts, never raw values. "Changed" is detected by comparing a stable hash of each value between snapshots, so the page can tell you a key's value moved without ever exposing what it holds — the same metadata-first posture as the rest of the rollup.
- Honest empty states. A scope with a single snapshot shows "no prior sync to compare"; a scope that was never synced (or belongs to another account) is not found. The same data is available as JSON at
/api/me/brain-timeline?scope=<scope>.
Live activity
Skills that declare their start (the start_run MCP tool) show up while they work, not just after:
- Running now. A strip at the top of the page with each in-flight run — skill, plugin, a spinner, and the elapsed time ticking live. It refreshes about every 30 seconds while the tab is open (nothing polls in the background), and when a run finishes the spinner flips to its outcome badge with a link to the drill-down.
- Stale runs. A run that declared a start but has been silent for 30 minutes — no heartbeat, no final report — is flagged stale instead of pretending to run forever. Stale usually means the skill crashed or the session was abandoned; re-run it in Cowork.
- Timeline. The same recent runs grouped per day as a compact started → completed view (collapsible; today open by default). Runs still in flight show an open arrow.
Plugin versions that don't declare starts never appear as running — their runs land directly in Recent runs when they finish, exactly as before.
Performance trends
Each plugin card carries a runs-per-day sparkline for the active window, with a 7d / 30d / 90d toggle above the grid. Under the sparkline: the plugin's median run duration and its error rate over the window. Bars for days with at least one failed run are tinted red; hover any bar for that day's exact counts.
- Deterministic math, no AI. Runs are bucketed per UTC day; duration is the standard median over finished runs; error rate is errors divided by finished runs. Every number is reproducible from your run history.
- Honest error rates. Runs still running — or gone stale — have no outcome yet, so they count as activity but are excluded from the error-rate denominator and the duration median. A day where nothing finished shows "—", not a fake 0%.
- Honest history. A plugin with fewer than two active days in the window shows "Not enough history yet" instead of a made-up flat line.
The trend data (per plugin, and per skill within each plugin) comes from GET /api/me/rollup-trends?window=7d|30d|90d, scoped to your account.
Plugin coordination
The Sales as Code plugins are designed to feed each other — Company OS Core writes your company dossier and voice, the role engines read it, and each engine produces brain scopes the next one consumes. The Plugin coordination card draws that as a small diagram (inline SVG, no external libraries) over the plugins you actually own:
- Nodes are your licensed plugins. Company OS Core sits on top (marked ★); the rest hang off it. Each node's ring is green when healthy, amber when never started, red when its last run failed, and the glyph shows its run count. Hover a node for its status.
- Solid lines are requirements. Every paid plugin requires Company OS Core; the solid edges show those dependencies between the plugins you own.
- Dashed lines are real data-flow. A dashed arrow from A to B means A synced a brain scope that B reads — derived by intersecting each plugin's declared scope interests (what it writes vs. what it reads) with the scopes actually observed in your brain sync. No observed sync, no arrow. Hover an arrow for the scope flowing across it.
Below the diagram, coordination warnings flag things to fix, each linking straight to the fix:
- Missing dependency. You licensed a role engine but not the Company OS Core it depends on — links to pricing.
- Ran before Core set up. An engine has runs but the Core dossier was never synced, so it never read your company context. Run Core's setup skill first.
- Idle plugin. A plugin you own that hasn't run in the last 7 days (or never has) — a churn signal, links to Connect.
- Stale upstream. An active plugin is reading brain data from a producer that hasn't re-synced in over two weeks, so it is working from stale inputs — re-run the producer.
Honest empty state: with only one plugin licensed there is nothing to coordinate, so the card says so and links to the plugin catalog. Warnings are deterministic rules over your own run and sync history — no AI, every one reproducible.
Goals & targets
The Goals card turns the rollup from a receipt into a pace check. Set a target against any outcome your plugins actually report and see how far along you are this week or month:
- Any metric your plugins emit. The metric dropdown is built from the outcome keys your telemetry has actually carried (like
contacts_researched,meetings_prepped,emails_drafted) — never a hardcoded list. If a plugin has never reported a number, there is nothing to set a goal on yet, and the card says so. - Deterministic progress. Progress is the plain sum of that metric's counts across your runs inside the window — a run missing the key counts as 0, and multiple plugins that report the same key all add up. Every number is reproducible from your run history; no AI in the math.
- Week or month, calendar-aligned. "Per month" is the current calendar month (UTC); "per week" is the current week starting Monday. A progress bar fills toward the target with the current total and percentage.
- Personal or team goals. A personal goal tracks your own telemetry. If you own a team, you can set a team goal that sums every member's telemetry — only the team owner can create, edit, or delete team goals.
- Edit & delete. Adjust a target or remove a goal any time from the card. Honest empty state: with no goals set, the card reads "Set a goal to track pace."
The same data is available as JSON at GET /api/me/goals.
Pace & behind-pace alerts
Each goal shows a pace badge — Ahead, On pace, or Behind — computed deterministically by comparing how far through the window you are with how far toward target you are (within a ±15% band of the straight-line expectation). The progress bar tints red when you fall behind. Nothing here is a guess; every status is reproducible from your run history.
- Behind-pace email. A daily cron checks every active goal and, when one is behind pace, emails the owner once per window (never more than once a month for a monthly goal, or once a week for a weekly one). The email carries the exact progress, how far the window has elapsed, and the single suggested next action.
- Optional Slack nudge. If you have configured a personal Slack incoming webhook (Settings → API), the same behind-pace nudge is also posted there. It is best-effort — a Slack hiccup never blocks the email.
- Quiet by design. On-pace and ahead goals are never alerted. If email is not configured on the deployment, the cron simply logs instead of sending, and the once-per-window ledger still prevents duplicates.
Suggested next actions
The Suggested next actions card is a small, fixed rule table over your telemetry — no AI, every card hand-checkable:
- No content published in 7 days (and you own Content Engine) → run the Content Calendar skill.
- Stalled deals reported in telemetry → run the Deal Closer skill on them (with the count).
- A goal behind pace → run the plugin that actually moves that metric — determined from which plugin most recently reported the metric's counts, not a hardcoded mapping.
Each card either links straight to Connect (when you don't yet own the suggested plugin) or shows a copyable Claude Cowork prompt you can paste to run the skill. Cards appear only when their condition is actually true, so an all-green rollup shows none.
Run drill-down
Every row in Recent Runs links to /rollup/run/[id] — one run, in full:
- At a glance. Outcome, duration, when it ran, and the client-supplied run id.
- What went wrong. When a run failed, a categorized error badge —
auth,entitlement,rate limit,provider,skill logic, orunknown— with the detail line the skill sent and a one-line hint on what to do about that category. Runs from plugin versions that predate the taxonomy show as "uncategorized" — upgrade the plugin in Cowork to get categorized failures. - Full run payload. Everything the skill reported to
emit_telemetry, rendered as a key/value table (stored whole, 64KB cap at ingest). Runs recorded before payload capture shipped fall back to their counts line, honestly labeled. - Brain syncs from the run. When the plugin passes the shared run id (
run_ref) on itssync_braincalls, the drill-down shows exactly the snapshots that run produced — labeled as an exact match. Older runs without it fall back to a time-window match, honestly labeled: treat that as "what landed around this run", not a guaranteed causal link. - Re-run in Cowork. A copyable prompt (skill, plugin, and the previous run's outcome/counts/error context) you can paste straight into Claude Cowork to run the same skill again.
Per-plugin drill-down
Every plugin you own has its own page at /rollup/[pluginId], reachable by clicking a plugin anywhere it appears on the rollup — its health card, its By plugin card name, or its node in the coordination diagram. It pulls that plugin's slice of the cockpit into one place:
- Health at a glance. Status (Healthy / Not started yet / Last run failed), total runs, error count, and last-run time.
- Trend. The plugin's runs-per-day sparkline for the active window (7d / 30d / 90d toggle), plus median duration and error rate — and a sparkline per skill underneath, from the same
/api/me/rollup-trendsdata. No chart library; the same inline-SVG sparklines used across the rollup. - Coordination. Just this plugin's edges from the coordination map — what it requires, what requires it, the brain scopes it feeds to other plugins, and the scopes it is fed by — with any warnings that name this plugin. Each linked plugin opens its own drill-down.
- Brain scopes. The scopes this plugin has synced, each with its change highlight and a link to that scope's full timeline.
- Error log. This plugin's recent failed runs with their categorized error badge, each linking to the run drill-down, plus a copyable Retry in Cowork prompt that lists the failed skills and their error categories to paste straight into Claude Cowork.
- Run history. The most recent runs of just this plugin, in the same table used on the main rollup (the plugin column dropped, since it is redundant here).
Honest scoping: a plugin you don't own — or a made-up id — is "Plugin not found", indistinguishable from one that doesn't exist. Every section has an empty state (a plugin that has never run shows a connect prompt, not fake data).
Filter by account
When your skills tag their runs with an account (the optional account_ref label they pass to emit_telemetry — a domain or account name), the rollup gains an Account filter above the activity:
- Scope to one account. Pick an account from the dropdown (each option shows its run count) to scope the Recent runs table, the By plugin summary, and the Timeline to just that account's runs. "All accounts" clears it. The filter lives in the URL (
/rollup?account=acme.com), so a scoped view is linkable. - Metadata only.
account_refis a free-text label — a domain likeacme.comor a name — never synced CRM records or contact data. It is the same account you already know; the rollup just groups by it. - Honest empty state. Until a skill passes an account, the card reads "No account labels yet" and explains what unlocks the filter. Plugin versions that don't send
account_refstill appear in every unscoped view exactly as before.
Whether a skill tags its runs is up to the plugin (they ship from the marketplace repo). A skill that works a specific account should pass its domain; one with no single account omits it. See the API reference for the label convention.
Dossier completeness
A compact GTM Context Dossier card rides along near the top of the rollup: a meter scoring how many of the six dossier sections are filled (company, products, founder, voice, ICP, competitors) and a consumed-by line showing which plugins have actually read your context — Core once your session pulls config, and each plugin with when it last synced brain state against it. The card appears only when it's relevant (you own the Content Engine, a dossier exists, or something has consumed it) and links to /onboarding/dossier to sharpen it. Full detail: GTM Context Dossier.
How it fills up
- Connect to Cowork and run a plugin's setup skill.
- As skills run, they call
emit_telemetryandsync_brainagainst the control-plane MCP. - This page reads the resulting
plugin_runsandbrain_syncrecords, scoped to your account.
Until a plugin runs, the rollup shows an empty state with a link to connect.
Weekly digest email
Every Monday, the control plane emails you a recap of the same data — runs and "actions" this week versus last, what changed, and any plugin that is idle or erroring — so you stay in the loop without logging in. You only get it if your plugins ran in the last week. Every email has a one-click unsubscribe; you can also opt out from account settings.
How you compare
When your deployment enables cross-tenant benchmarks, a "How you compare" card shows your activity per won opportunity against the anonymized median band across every team on the deployment — never any other team's raw data. It appears only when the deployment flag is on, at least five teams have data, and you have not opted out (Settings → Data). Read-only. Full detail: docs/privacy/cross-tenant-benchmarks.md.
Privacy
Telemetry and brain sync are metadata-first. The rollup shows run counts, outcomes, and brain state — never raw third-party contact data (lead lists, email bodies), unless you have explicitly opted in to richer sync. You own this data and can export or delete it.
A short "Metadata only — no raw PII by default" card sits at the top of the rollup as a standing reminder of this, linking to the full explainer on the Trust & security page (which also carries the security one-pager and our honest SOC 2 roadmap statement).
Related
- Connect to Cowork — get your plugins running so this fills up.
- API Keys & MCP — the control-plane tools that feed this rollup.
- Team rollup (
/team-admin/rollup) — the same outcome metrics across a team, plus a rep-vs-team leaderboard (members ranked by actions, each compared to the team median) and the team's week-over-week.