← All tools

Tool 02 · RevOps · Open source

GTM Control Room

Bring your revenue, pipeline and demand metrics into one view, with clear definitions, targets and the next actions behind the numbers. It answers five management questions from a governed metric dictionary, a deterministic engine and a decision loop — and it is public by design.

Connect your toolsDefine what countsSee what needs attentionRun the next move
9views
15governed metrics
5management questions
MITopen source
The demo

Are we on track? One screen, thirty seconds.

The demo runs entirely in your browser on a synthetic dataset — invented companies, invented people, a permanent Demo data badge. Nothing is sent anywhere. It is one self-contained file of about 5 MB, so it is best opened on a laptop.

GTM Control Room overview: headline cards for bookings, qualified pipeline, open pipeline and coverage against targets, a needs-attention list and the sales calendar
The Overview. Every headline card shows actual, target, attainment, pacing for a partial period and change against the prior period; below it, the exceptions that need a manager and the sales calendar. Click to open the working demo.

What you can do in it

  1. Switch Weeks / Months / Quarters / Years and toggle last year — comparisons are cut to the same elapsed days.
  2. Open What counts? behind any number: definition, version, owner, limitations, supporting records.
  3. See a data-quality issue and its consequence on Data health — including a failed GA4 credential and a stale ads export.
  4. Change the assumed deal value on the sales calendar and read the required pace.
  5. Generate the review agenda from the snapshot and record a decision with an owner and a due date.
  6. Export a configuration starter from Brain & goals to begin your own workspace.
01

Read it in thirty seconds

Three screens carry most of the value. Each is a real view from the demo, not a mock-up.

The What counts? drawer for new-business bookings: actual, target, pacing baseline, prior period and last year cut to elapsed days, limitations, the definition as operation, filters and unit, and breakdowns by segment
What counts? — behind every number. Actual against target, the pacing baseline, prior period and last year on the same elapsed days, the limitations that apply right now, then the definition itself: the operation, the population filters, the unit, the source, the policy document. Breakdowns by segment and channel underneath.
the scorecard cell, everywhere €821.7K / €780K ← actual / target 105% · 133% pace ← attainment; pacing when the period is partial +66% vs prior* ← change vs prior period (* equivalent elapsed days)
Data health view: a matrix of metric states with reasons, findings and sources, then data issues for RevOps and business exceptions for managers
Data health — which numbers need caution, as concrete evidence rather than a trust score. Each metric carries a state (ready, partial, stale, blocked) with its reason. Data issues go to RevOps or the source owner; business exceptions — 24 of 42 qualified deals with no activity for 14 days, €1.76M — go to the manager, with the remedy and the records.
GTM Council view: an agenda generated from the snapshot and a decision log with owner, due date and outcome
GTM Council — the management loop. An agenda generated from the current snapshot, a decision log where every entry has an owner, a due date and a follow-up check, and the snapshot id pinned to each decision so "did it help?" can be answered next week.
02

What makes it different

Most dashboards show numbers. This one shows numbers and the case for believing them. Three properties do most of the work:

Definitions

A definition behind every number

Each metric is a JSON definition using approved operations only — population filters, time behaviour, unit, source, owner, version. The drawer shows it; the engine computes from it; nothing else does arithmetic.

A number nobody can explain is a number nobody trusts.
Honesty

Unavailable is not zero

Missing data, a zero denominator, a blocked capability: the result is null with a reason, shown as Unavailable or Blocked. Coverage with nothing left to close says "Target achieved", never infinity.

A failed source stays visible — never hidden behind a stale number.
Decisions

Decisions tied to snapshots

A review keeps the snapshot it looked at. Decisions carry an owner, a due date and a follow-up check written at the time. Outcomes are recorded before the next review.

No new numbers in the room — disputed figures become data issues.

The ten non-negotiables

These hold in every phase of the build. A session may not trade them for speed — they are written into the repository's standing brief and into the decision records.

#RuleWhat it prevents
01One source per metric; overlaps need an explicit precedence rule.Two systems disagreeing about the same number.
02All arithmetic in one deterministic engine. No numbers computed in the UI, the analyst or by a model.Cards, scorecard and analyst drifting apart.
03A definition is configuration, not code: approved operations and declarative filters only.An uploaded document silently rewriting a live calculation.
04Unavailable is null with a reason, never 0.A broken feed reading as a collapse in bookings.
05Every result carries query id, snapshot id, definition version, coverage and comparison windows.A figure on a slide nobody can trace.
06Point-in-time values come from history or snapshots, never today's values.Last quarter's pipeline quietly rewritten by this week's edits.
07Re-imports and retries never inflate totals — dedup keys are declared.Double-counted bookings after a sync retry.
08Failures are visible on the page.A stale number presented as current.
09Targets come from the goals sheet the leadership team edits; scope must match exactly.A segment filter silently compared against the company-wide target.
10Credentials only on the server; demo data is invented; no client data in the repository.A token in the browser, or a real account in a public repo.
The analyst has guardrails, not opinions

"Ask the analyst" answers five approved questions — Why are we behind target? What changed? Can we trust this number? Where is the gap by segment and channel? What needs attention this week? — from the same engine output the cards show. It never computes a figure of its own. Ask it to convert MRR to ARR and it declines, naming the guardrail: that conversion is not a defined metric. A model-backed version, when it comes, reads the same evidence bundle and may only rephrase and prioritise; any number it outputs must already exist in the bundle.

03

What is inside

Nine views, one question each

ViewThe question it answersWhat is on it
OverviewAre we on track?Headline cards, needs-attention list, sales calendar, open decisions, analyst
ScorecardEvery metric, every periodSections × periods; partial markers; year-over-year on elapsed days; footnotes
PipelineWhat can close, what needs attention?Open and created pipeline by period, segment, channel, stage; deal inspection with flags
Demand & outboundEnough qualified demand?Leads, meetings, target-account coverage, follow-up SLA, paid lead cost, campaigns
RetentionRetaining and expanding value?NRR and GRR against target, expansion, movements
Data healthWhich numbers need caution?Metric-state matrix, data issues, business exceptions with records
Brain & goalsWhat does each number mean?Metric dictionary, targets, process and channel dictionaries, policies, proposals, export
GTM CouncilWhat will we do about it?Generated agenda, decision log, record a decision
ConnectionsWhat data is available?Source status, freshness, coverage, capability matrix, failed-query alert

Fifteen governed metrics — the subscription new-business pack

MetricFoundationSection
New-business bookingsAgreed new-business contracted value in the booking period, per the bookings policyNew business
New-business winsQualified new-business opportunities closed wonNew business
Qualified pipeline createdValue at first entry into the approved qualified stageNew business
Open qualified pipelineEligible open value at the selected snapshot — point in timeNew business
Remaining-target coverageEligible pipeline due in the window ÷ remaining bookings targetNew business
Closed-deal win rateQualified wins ÷ qualified wins plus losses closed in the periodNew business
Sales cycleMedian days qualification → win, won populationNew business
Leads createdNon-test leads created, all channelsDemand
Held external meetingsDistinct completed meetings meeting the external-attendee ruleDemand
Target-account coverageTarget accounts with qualifying activity ÷ eligible target accountsDemand
Follow-up SLA attainmentLeads followed up within the window ÷ eligible leadsDemand
Paid lead costCampaign spend ÷ paid-channel CRM leadsDemand
Net revenue retentionOpening cohort after expansion, contraction and churn ÷ openingRetention
Gross revenue retentionAs NRR without expansionRetention
Expansion ARRRecurring revenue added by existing customersRetention

Every definition is built from eight approved operations — the only executable vocabulary:

sumcountcount_distinctratiomedian_durationpoint_in_timeretentioncoverage

Adding an operation is an engine change with tests, a schema change and a decision record. It is never done from a document upload. Rates are recalculated from underlying counts, never averaged; pipeline snapshots are never summed; bookings, revenue, ARR and cash stay separate value bases.

Worked example · coverage

Quarter target €300,000; booked to date €180,000 → remaining €120,000. Open qualified pipeline with a close date inside the quarter €360,000 → coverage 3.0×. Deals without a close date are excluded and listed on Data health. If booked ≥ target: "Target achieved". The sales calendar at an assumed €40,000 per win shows three additional wins required, against the remaining calendar and working days — a planning calculation, not a forecast.

04

Run it on your data

Node 20 or later. No dependencies, no build step. Sixty seconds to the demo; an afternoon to a first view of your own exports.

# run the demo git clone https://github.com/RevenuePuzzles/revops-claude-dash.git cd revops-claude-dash npm run dev # → http://localhost:8787/app/ # other commands npm run check # validate configuration + run the tests npm run fixtures # regenerate the synthetic dataset (seeded) npm run build:static # one self-contained HTML file in dist/

Three steps to your own workspace

  1. Export. Pull deals, deal history, companies, contacts and engagements from your CRM; campaign spend from ads; movements from billing. Put them in fixtures/<workspace>/ following the data model.
  2. Map. Copy config/workspaces/demo/ — or use Brain & goals → Export starter — and edit the workspace profile, the metric definitions, targets.csv, the channel dictionary, process definitions and inspection rules. npm run validate checks every file against its schema.
  3. Review. Point the app at the workspace and run. The first Monday: read the Overview, open the drawer on anything surprising, fix what Data health lists, record the decisions.

Portable now, connected next

Working today — portable mode

  • Engine: ISO weeks, fiscal quarters, partial windows, eight operations, targets with exact scope, pacing, prior and prior-year on equivalent elapsed days — 29 tests, green.
  • Quality: nine check types; data issues separated from business exceptions.
  • Analyst v1: five approved questions; declines undefined calculations.
  • Nine views, drawer, filters, grain switcher, states, failed-source banner, sales calendar, decision log, configuration export.
  • Static single-file build that renders and computes identically.

Skeleton — the connected pilot

  • HubSpot adapter: server-side only; probes stage, amount and close-date history at discover; Monday pipeline snapshots; a failed run never partial-commits.
  • Cloudflare Worker + D1 + R2 behind the same eight endpoints the dashboard already uses, so the UI does not change between modes.
  • Import UI with a mapping editor and preview on the Connections view.
  • Sign-in with domain restriction; reviews and decisions as server records with an audit log.

The contracts for all of it — sockets, adapters, API, security, testing — are written in docs/. A source can change without the dashboard changing; that is the point of the socket layer.

05

Built in the open

The repository is both the implementable specification — seventeen documents, five JSON schemas, ten locked decision records, a build checklist — and the working portable version. It is written so a Claude Code session or a human engineer can pick it up cold and build the next phase without asking what "qualified pipeline" means.

Every session follows the same standing brief: read the status document, pick the next unchecked item, meet its acceptance condition, verify it the way finance would, update the status. Discovered work becomes a new checklist item, never a quietly widened one.

Where the checklist stands

Phase 1 · Reporting contract — profile, policies, dictionaries, 15 metrics, goals sheet, rules, golden questions7 of 8
Phase 2 · Portable core — engine, quality, nine views, fixtures, analyst, validation, static build8 of 10
Phase 3 · Connected pilot — Worker, D1, R2, sign-in, HubSpot sync, failure handling0 of 6
Phase 4 · Management workflow — sales calendar and decision log portable; server records next2 of 4
Phase 5 · Reusable blueprint — starter export done; services pack, Salesforce adapter, import round trip1 of 4
Phase 6 · AI analyst — evidence bundle done; provider socket with number validator next1 of 3

Counts from docs/build-checklist.md at the time of writing; the repository's STATUS.md is the live version.

Why open

Reporting is where GTM engagements go quiet: everyone agrees the numbers matter, nobody can say which definition produced them. Publishing the engine, the dictionary and the decisions makes the argument inspectable — and lets a client's RevOps team own the result rather than rent it.

Limits

What it does not do yet

  • Portable mode reads static files; there is no import UI yet (the CSV adapter exists as a module).
  • Decisions recorded in the demo live in your browser only.
  • The HubSpot adapter and the Worker are skeletons with contracts and TODOs; there is no server-side authorisation yet.
  • Coverage can inflate when the remaining target is small — the remaining amount is shown next to the ratio so it is read with the gap.
  • Forecasting models, attribution beyond sourced/influenced, free-form AI questions over raw records and multi-currency consolidation are out of scope for the pilot.

The demo dataset is generated by a seeded script with deliberate data-quality cases (a duplicate booking, an expired credential, a stale export, unmapped channels). No client data exists anywhere in the repository. MIT licence © Revenue Puzzles.

Want this on your numbers?

The reporting contract — definitions, ownership, goals — is agreed in a workshop before anything is built; the portable version then runs on your exports within days. Tell me what is going on and I will say whether it fits.