Ein Claude Skill, der einen entworfenen Gebietszuschnitt nimmt und berichtet, was er tatsächlich bewirkt: wo die Abdeckung bricht, welche Gebiete mehr Quote tragen, als ihre Reps erreichen können, und welche Named Accounts zu einem Preis den Besitzer wechseln, der Beachtung verdient. Er läuft, bevor der Zuschnitt an die Reps geht, solange die Regeln noch editierbar sind, und endet mit einem Urteil von ready, revise oder blocked. Er schreibt niemals eine Zuweisung ins CRM zurück.
Das Bundle liegt unter apps/web/public/artifacts/territory-carve-impact-simulator-skill/ und enthält SKILL.md sowie drei Referenz-Templates: references/1-carve-input-template.md (den vorgeschlagenen Zuschnitt — geordnete Regeln, Rep-Roster, Stichtag), references/2-coverage-thresholds-template.md (das Kapazitätsmodell der Organisation, die Ramp-Kurve, die Disruptionstoleranzen und die geschützten Accounts) und references/3-sample-output-format.md (das exakte Markdown, das der Skill ausgibt, mit einem ausgearbeiteten Beispiel).
Wann Sie ihn einsetzen
Zwei bis vier Wochen vor einem Realignment zum Geschäftsjahresbeginn oder zur Jahresmitte, auf einem Zuschnitt, den jemand entworfen und niemand belastet hat. Dieses Zeitfenster wiegt schwerer, als es klingt: Ein Zuschnitt wird in dem Moment politisch teuer, in dem die Reps die Karte sehen, und der Skill liest carve_status aus der Zuschnitt-Spec — ein Report nach der Kommunikation eröffnet deshalb mit dem Hinweis, dass die empfohlenen Änderungen jetzt Glaubwürdigkeit und nicht nur Aufwand kosten. Läufe für ein einzelnes Segment sind ebenfalls sinnvoll — ein Pod, der dem großen Realignment vorausgeht — genauso wie ein nachträglicher Lauf, wenn ein Segment den Plan verfehlt und niemand sagen kann, ob das Coverage-Design oder die Ausführung schuld ist.
Der Teil, der sich rechnet, ist die Gewichtung. Jedes Planungswerkzeug kann zählen, wie viele Accounts den Besitzer wechseln, und diese Zahl ist nahezu wertlos: Ein Zuschnitt, der 200 schlafende Accounts verschiebt, ist gratis, einer, der zwölf Accounts mit Late-Stage-Pipeline und einem Rep mit drei Jahren Beziehungsdauer verschiebt, ist es nicht — und die ungewichtete Zählung ordnet beide falsch herum. Der Skill sortiert Churn nach materieller offener Pipeline multipliziert mit einem Beziehungsdauer-Faktor, was eine Änderungsliste von 200 Accounts typischerweise auf vier oder fünf Zeilen eindampft, die den Großteil des Risikos tragen.
Wann Sie ihn NICHT einsetzen
Einen Zuschnitt erzeugen. Er bewertet einen Zuschnitt, den jemand anderes entworfen hat. Er schlägt keine Regeln vor, balanciert keine Accounts und sucht keine optimale Aufteilung. Ohne Entwurf gibt es nichts zu simulieren.
Zurückschreiben nach Salesforce. Der Skill ist auf jedem Objekt, das er anfasst, nur lesend. Gebietsänderungen werden in dem System ausgeführt, das sie verantwortet, nachdem ein Mensch den Plan freigegeben hat; die Ausgabe in einen automatischen Zuweisungsjob zu hängen, entfernt genau die Entscheidung, für die das Werkzeug existiert.
Comp-Inputs. Der Kapazitätsreport sagt, ob ein Gebiet eine bereits gesetzte Quote tragen kann. Führen Sie ihn in die Comp-Berechnung, haben Sie einen direkten Anreiz geschaffen, über die Inputs zu streiten: Produktivitätsbänder werden neu verhandelt, Ramp-Kurven werden zum Verhandlungsgegenstand, und das Modell beschreibt die Realität nicht mehr.
Zuschnitte, die nur als Tabelle mit Account-IDs existieren. Eine Liste aus Account-Rep-Paaren lässt sich nicht gegen das simulieren, was die Routing-Engine zum Go-live tut. Wandeln Sie sie in Regeln um und simulieren Sie diese; wenn die Regeln die Tabelle nicht reproduzieren, ist genau diese Abweichung der Befund.
Books ohne Ownership-Historie. Wenn AccountHistory keine OwnerId-Änderungen aufzeichnet, liest sich die Beziehungsdauer überall als null und jeder Zuschnitt wirkt billig. Der Skill gibt unterhalb von history_coverage_floor_pct ein blocked zurück, statt eine Churn-Zahl auszugeben, die er nicht stützen kann.
Setup
Schreiben Sie den Zuschnitt als geordnete Regeln. Ersetzen Sie in references/1-carve-input-template.md die Beispielregeln durch Ihre eigenen, in der Reihenfolge, in der die Routing-Engine sie auswerten wird, und verwenden Sie Salesforce-API-Feldnamen statt Labels. Die Reihenfolge ist tragend: Der Skill wertet nach First-Match-Wins aus, um die Ausführung abzubilden, also verändert ein Umsortieren der Regeln die Zuweisungskarte.
Entscheiden Sie über die Auffangregel. Das Template liefert eine letzte Regel mit, die alles auffängt. Behalten Sie sie, ist no_rule_matched immer null und der Coverage-Report wird zur Frage nach der Pool-Größe; entfernen Sie sie, tauchen echte Regellücken namentlich auf. Entscheiden Sie bewusst, statt die Vorgabe des Templates zu erben.
Füllen Sie die Threshold-Datei. Leiten Sie in references/2-coverage-thresholds-template.md die productivity_bands aus Ihrem eigenen Closed-Won der letzten zwölf Monate je voll gerampter Rep ab — 75. Perzentil für high, Median für mid, 25. Perzentil für low — statt aus einem Benchmark. Setzen Sie max_revenue_churn_pct explizit: Die 25% des Templates lassen ein Viertel der Umsatzbeziehungen eines Gebiets wechseln, bevor überhaupt etwas anschlägt, was für volumengetriebenes Mid-Market passt und für High-Touch-Enterprise viel zu locker ist.
Backtesten Sie die Ramp-Kurve. Lassen Sie einmal dry_run: true laufen, bevor Sie einer Kapazitätszahl trauen. Der Lauf vergleicht Ihre Kurve mit der Attainment der Neueinstellungskohorte des Vorjahres und meldet die Differenz — die Lücke zwischen der Ramp, die Finance genehmigt hat, und der, die die Kohorte tatsächlich geliefert hat, ist meist der größte Einzelfehler in einem Kapazitätsmodell.
Installieren und Rechte eng ziehen. Legen Sie das Bundle nach ~/.claude/skills/territory-carve-impact-simulator/ und setzen Sie SFDC_TOKEN mit Lesezugriff auf Account, AccountHistory, Opportunity, OpportunityHistory, User und UserTerritory2Association. Nur-Lesen ist der richtige Scope, keine Vorsichtsmaßnahme.
Was der Skill tatsächlich tut
Er läuft in zwei Durchgängen, und die Trennung ist Absicht. Der erste Durchgang weist jeden Account zu, indem er die Zuschnittregeln in der deklarierten Reihenfolge auswertet, beim ersten Treffer stoppt und den getroffenen Regelindex festhält. Der zweite rechnet die Auswirkungen gegen diese fertige Zuweisungskarte. Churn und Kapazität inline zu berechnen, während die Regeln noch aufgelöst werden, zählt jeden Account doppelt, den mehr als eine Regel beanspruchen könnte — und da First-Match-Wins bedeutet, dass ihn nur eine tatsächlich beansprucht, beschreiben diese Inline-Zahlen einen Zuschnitt, den es nie geben wird.
Nicht zugewiesene Accounts werden nach zwei Ursachen getrennt statt in einen Topf geworfen: no_rule_matched ist eine Coverage-Lücke, null_input_field eine Datenlücke, und der Skill benennt das verursachende Feld. Beides zu vermischen schickt ein Planungsteam in ein Regel-Redesign, obwohl die Lösung ein Backfill ist. Im ausgearbeiteten Beispiel in references/3-sample-output-format.md landen 387 Accounts nur deshalb im Mid-Market, weil Account.AnnualRevenue null ist und sie die beiden darüberliegenden Enterprise-Regeln übersprungen haben — Segmentierung, die aus Versehen passiert und in einer einzigen Zahl für nicht zugewiesene Accounts unsichtbar bleibt.
Kapazität ist ramp-adjustierte quotentragende Kapazität, nicht Headcount mal Durchschnittsquote: Jeder Rep steuert sein Produktivitätsband bei, skaliert mit dem Ramp-Faktor des Monats, in dem sein Startdatum ihn zum Stichtag verortet. Ein nach Account-Anzahl ausbalanciertes Gebiet, das zwei Reps mit Start sechs Wochen vor Go-live aufnimmt, zeigt hier eine Unterdeckung — genau das Versagen, das ein nach Account-Anzahl ausbalancierter Zuschnitt zu verbergen gebaut ist.
Diese Arithmetik läuft in Code und nicht über das Lesen der Datensätze durch das Modell. Ein Planungsgespräch bricht in dem Moment zusammen, in dem zwei Läufe desselben Zuschnitts unterschiedliche Zahlen liefern, und ein Modell, das mehrere tausend Account-Zeilen liest, ist nicht reproduzierbar. Die Aufgabe des Modells sind die Rangfolge, die Erzählung und der Abschnitt „was zu ändern ist”.
Kostenrealität
Weil die Arbeit auf Datensatzebene in Code passiert, skaliert der Token-Aufwand mit der Größe der Zusammenfassung, nicht mit der Größe des Books. Ein Zuschnitt mit 5.000 Accounts und 30 Reps kostet rund 2 bis 4 USD pro Simulation auf Claude Sonnet 5 zu den veröffentlichten API-Preisen von 3 USD je Million Input-Tokens und 15 USD je Million Output-Tokens — die Referenzdateien, die aggregierten Tabellen und der Report selbst, nicht die 5.000 Zeilen. Diese Zahl ist eine Schätzung, abgeleitet aus dem Token-Preis und der typischen Reportlänge; sie bewegt sich mit dem Umfang der gewünschten Erzählung, nicht mit der Account-Zahl. Ein Planungszyklus braucht fünf bis fünfzehn Läufe, während der Zuschnitt überarbeitet wird, also kalkulieren Sie rund 50 USD API-Ausgaben für den Zyklus.
Der Vergleich, der zählt, ist Zeit. Ein RevOps-Analyst, der diese drei Sichten von Hand erstellt — das Account-Book gegen die vorgeschlagenen Regeln pivotieren, Pipeline und Ownership-Historie joinen, ein ramp-gewichtetes Kapazitätsmodell bauen — verbringt drei bis fünf Tage je Iteration, weshalb die meisten Teams es genau einmal tun und danach aus der ersten Version heraus argumentieren. Der Skill macht aus jeder Iteration einen Lauf von fünfzehn Minuten plus eine Stunde Lesezeit, und genau das lässt fünf Überarbeitungen in ein Planungsfenster passen statt einer.
Gegen die Alternativen
Salesforce Sales Planning — veröffentlicht mit 75 USD pro Nutzer und Monat bei jährlicher Abrechnung (Preisseite des Anbieters, geprüft am 2026-08-10), mit Hierarchy Management, Segment Design und Territory Planning; im Agentforce 1 Sales Edition zu 550 USD pro Nutzer und Monat enthalten. Für eine Vertriebsorganisation mit 40 Seats liegt das eigenständige Add-on bei rund 36.000 USD im Jahr. Nehmen Sie die Plattform, wenn der Zuschnitt ein gesteuertes, versioniertes Artefakt im CRM sein soll und Plan und Ausführung in einem System liegen; nehmen Sie den Skill, wenn Sie ein Pre-mortem zu einem Zuschnitt brauchen, den jemand bereits in einer Tabelle entworfen hat. Beides schließt sich nicht aus: Den Skill gegen einen in Sales Planning erstellten Zuschnitt laufen zu lassen, ist eine vernünftige Zweitmeinung, weil die Plattform, die den Plan erzeugt hat, nicht der naheliegende Ort ist, um nach Gründen für sein Scheitern zu suchen.
Fullcast — eine Plan-to-Execution-Plattform für Gebiet, Quote, Kapazität und Routing, Preis auf Anfrage, nichts veröffentlicht. Die richtige Wahl, wenn Ihr Zuschnitt kontinuierlich statt jährlich ist: Gebiete, die sich anpassen, während Accounts und Headcount sich bewegen, mit synchron gehaltenem Plan und Routing-Regelwerk. Der Skill hat überhaupt keine Ausführungsebene und verliert bei dieser Arbeitsweise deutlich.
Die Tabelle — die tatsächliche Ausgangslage in den meisten Unternehmen, und sie liefert den Zuschnitt, der ausgerollt und in Woche drei leise überarbeitet wird. Sie kann Disruption nicht gewichten und Ramp nicht modellieren, versagt also genau bei den beiden Fragen, die entscheiden, ob der Zuschnitt hält.
Ausrollen und im Quartal nachbessern — der ehrliche Standardfall. Die Kosten tauchen nie als Budgetposition auf; sie zeigen sich als ein Segment, das den Plan verfehlt, und zwei Enterprise-Reps, die im zweiten Monat kündigen — zu einem Zeitpunkt, an dem niemand beides dem Zuschnitt zuschreibt.
Fallstricke
Ein CRM-Snapshot, der vor dem Go-live veraltet. Guard: Der Ausgabe-Header trägt snapshot_date und eine Frist für den erneuten Lauf, standardmäßig 14 Tage aus snapshot_staleness_days. Die Frist steht im Header, nicht in einer Fußnote, und der Report erklärt die Zahlen danach für ungültig.
Ownership-Historie auf Account.OwnerId nicht aktiviert. Die Beziehungsdauer fällt stillschweigend auf null und jeder Zuschnitt liest sich billig. Guard: Der Skill prüft die Abdeckung dieses Feldes in AccountHistory und gibt unterhalb der Schwelle ein blocked zurück, statt eine Zahl zu melden, die er nicht stützen kann.
Eine Ramp-Kurve, die HR geschrieben hat und nicht die Daten. Guard: dry_run backtestet die Kurve gegen die Vorjahreskohorte und warnt, wenn die beobachteten Monate bis zur vollen Produktivität die Datei um mehr als ramp_tolerance_months überschreiten, und meldet die beobachtete Kurve neben der konfigurierten.
Eine Liste geschützter Accounts, die nur wächst. Sobald jeder Account, an dem jemand hängt, geschützt ist, hört die Liste auf, ein Signal zu sein, und wird zum Veto gegen jedes Realignment. Guard: Jeder Eintrag trägt eine datierte Begründung, und das last_reviewed-Datum der Threshold-Datei löst bei jedem Report, der älter als 180 Tage ist, ein Warnbanner aus.
revise als Veto lesen. Das Urteil benennt Gebiete und Accounts, keine Entscheidung. Die Führung kann einen Zuschnitt mit Kapazitätslücke bewusst ausrollen, weil ein Hiring-Plan sie im zweiten Quartal schließt. Guard: Der Abschnitt „was zu ändern ist” beziffert die Korrektur in Einheiten — rund 1,2 Mio. Quote verschieben, einen Account herausnehmen — sodass das Akzeptieren des Risikos eine ausdrückliche Entscheidung mit Größenangabe ist.
Stack
Salesforce — Accounts, Ownership-Historie, offene Pipeline, Stage-Historie der Opportunities, Nutzerdatensätze
Claude — Regelauswertung, Impact-Ranking, Report-Synthese; die Arithmetik läuft in Code, nicht im Kontext
Die Zuschnitt-Spec und die Threshold-Datei — die beiden Inputs, die die Ausgabe spezifisch für Ihre Organisation statt generisch machen
Ein Routing- oder Territory-Management-System — Fullcast, LeanData oder Salesforce Territory Management, dort wo der freigegebene Zuschnitt tatsächlich ausgeführt wird
---
name: territory-carve-impact-simulator
description: Simulate a proposed sales territory carve before it ships to reps. Evaluates the carve's assignment rules against the live account book, then reports coverage gaps, quota-capacity shortfalls, and named-account churn weighted by open pipeline and relationship tenure. Emits ready / revise / blocked — never an automatic rollout.
---
# Territory carve impact simulator
## When to invoke
Whenever someone has a drafted territory carve — a set of assignment rules, a rep roster, and an effective date — and nobody has yet checked what it does to coverage, capacity, and existing relationships. The canonical moment is two to four weeks before a fiscal-year or mid-year realignment, while the carve is still editable. Also valid: a single-segment carve (one pod, one region) that a sales leader wants to move ahead of the wider realignment, and an after-the-fact run against a carve that already shipped, to explain why a segment is missing plan.
Take a carve spec (`references/1-carve-input-template.md`), an org thresholds file (`references/2-coverage-thresholds-template.md`), and read-only Salesforce access. Produce the Markdown report in `references/3-sample-output-format.md`.
Do NOT invoke this skill for:
- **Generating a carve.** This skill scores a carve someone else designed. It does not propose rules, rebalance accounts, or search for an optimal split. If there is no draft carve, there is nothing to simulate.
- **Writing assignments back to Salesforce.** The skill is read-only on every object it touches. Territory changes are executed by the routing or territory-management system that owns them, after a human approves the plan.
- **Comp or quota-setting decisions.** The capacity report says whether a territory can carry the quota someone already assigned it. It does not set quota, and its output must not flow into comp calculations — that turns a planning tool into a negotiation instrument and the inputs start getting gamed.
- **Carves with no documented rules.** A carve that exists only as a spreadsheet of account IDs and rep names cannot be simulated against what the routing engine will actually do. Ask for the rules, or convert the spreadsheet into rules first and simulate those.
- **Books with untracked ownership history.** If `AccountHistory` does not record `OwnerId` changes, the churn report has no baseline and the skill returns `blocked` rather than a churn number that looks authoritative and is not.
## Inputs
- Required: `carve_path` — path to the carve spec (rules in declared priority order, rep roster, effective date). See `references/1-carve-input-template.md`.
- Required: `thresholds_path` — path to the org's thresholds and capacity model. See `references/2-coverage-thresholds-template.md`.
- Required: `sfdc_token` — Salesforce session token with read on `Account`, `AccountHistory`, `Opportunity`, `OpportunityHistory`, `User`, and `UserTerritory2Association`. Read-only is the correct scope; the skill must not write.
- Optional: `segment_filter` — restrict the simulation to one segment or region. Coverage gaps outside the filter are reported as informational, not as failures.
- Optional: `snapshot_date` — ISO date for the CRM snapshot. Defaults to the run date. Recorded in the output header and used to compute the re-run deadline.
- Optional: `dry_run` — boolean, default `false`. When `true`, the skill backtests the thresholds file's ramp curve against last year's new-hire cohort and reports the delta instead of running the full simulation.
## Reference files
Read all three from `references/` before computing anything. Without the thresholds file the skill has no definition of "shortfall" and will not guess one.
- `references/1-carve-input-template.md` — the proposed carve. Rules are an ordered list; the roster carries each rep's segment, start date, and assigned quota.
- `references/2-coverage-thresholds-template.md` — the org's capacity model, ramp curve, disruption tolerances, protected-account list, and material-deal floor.
- `references/3-sample-output-format.md` — the exact Markdown the skill emits. Downstream consumers (a Slack digest, a planning deck) parse this shape.
## Method
Run in order. Steps 2 and 4 carry the engineering choices; do not collapse them.
1. **Load and validate.** Parse both reference files. If any rule references a Salesforce field that does not exist in the org's schema, stop and return `blocked` naming the field — a rule against a missing field silently matches nothing and produces a coverage gap that looks like a design flaw.
2. **Assign every account, first-match-wins, in declared order.** Evaluate the carve rules in the order they appear in the carve spec, and stop at the first rule that matches each account. This mirrors how the routing engine will execute them at go-live. Do not use set-union or any-rule-matches semantics: those produce a different assignment map than the one that ships, which makes the entire simulation decorative. Record the matched rule index per account. Accounts that match nothing land in an unassigned bucket, split into two causes — `no_rule_matched` (a genuine coverage gap) and `null_input_field` (a data gap, with the offending field named). Conflating those two sends a planning team to redesign rules when the real fix is a backfill.
3. **Compute the assignment diff.** For each account, compare the simulated owner against the current `Account.OwnerId`. Join open opportunities, prior-year closed-won amount, and relationship tenure (months since the current owner's first logged activity or first closed-won on that account, whichever is earlier).
4. **Score three impact dimensions.** Do the arithmetic in code, not by reading numbers into the reasoning context — the coverage and capacity figures must be reproducible run to run, and a model reading thousands of records will not be.
- **Coverage.** Unassigned accounts by cause; accounts assigned to a rep whose roster entry has no start date on or before the effective date; territories with zero assigned accounts.
- **Quota capacity.** Per territory: ramp-adjusted quota-carrying capacity against assigned quota. Capacity is `sum over reps of (ramp factor at effective date × that rep's historical productivity band)`, not headcount times average quota. The ramp factor comes from the curve in the thresholds file, so a territory that balances on account count but absorbs three reps in month two shows a shortfall here rather than passing.
- **Named-account churn.** Rank accounts changing owner by weighted disruption, not by count. Weight is open pipeline in stages at or past the thresholds file's `material_stage`, multiplied by a tenure factor. Moving 200 dormant accounts is cheap; moving 12 accounts with late-stage pipeline held by a rep with three years of tenure is not, and an unweighted count reports the opposite.
5. **Emit one of three verdicts.** `ready` (no threshold breached), `revise` (thresholds breached, with the specific territories and accounts named), or `blocked` (a data problem makes the numbers untrustworthy — stale snapshot, missing field history, unresolvable schema reference). There is deliberately no "ship it" verdict and no automatic rollout: the skill's job is to make the cost of the carve visible before a human decides.
## Output format
The skill emits Markdown in exactly this shape. Full worked example with populated rows in `references/3-sample-output-format.md`.
```markdown
# Territory carve simulation — FY27 Enterprise realignment
snapshot_date: 2026-08-10 | effective_date: 2026-11-01 | re-run by: 2026-08-24
accounts evaluated: 4,812 | territories: 22 | reps: 31
## Verdict: revise
Two territories breach the capacity floor and one protected account moves to a
ramping rep. Coverage is clean.
## 1. Coverage
| bucket | accounts | cause |
|---|---|---|
| assigned | 4,798 | — |
| unassigned | 9 | no_rule_matched |
| unassigned | 5 | null_input_field (Account.Industry) |
| empty territories | 0 | — |
## 2. Quota capacity
| territory | assigned quota | ramp-adj. capacity | gap | flag |
|---|---|---|---|---|
| ENT-WEST-2 | 4,200,000 | 2,940,000 | -1,260,000 | shortfall |
| ENT-EAST-1 | 3,800,000 | 3,910,000 | +110,000 | ok |
## 3. Named-account churn (ranked by weighted disruption)
| account | from | to | open pipeline (material) | tenure (mo) | flag |
|---|---|---|---|---|---|
| Northwind Traders | A. Okafor | J. Reyes (ramp m2) | 890,000 | 41 | protected |
| Contoso Fabrics | A. Okafor | S. Baptiste | 410,000 | 18 | review |
## 4. What to change
- ENT-WEST-2: capacity gap of 1.26M against a 4.2M quota. Either move ~1.2M of
quota to ENT-EAST-1, or the two month-two reps need a ramp allowance.
- Northwind Traders is on the protected list and its receiving rep is in month 2.
Carve it out or delay the transfer to the following quarter.
```
## Watch-outs
- **Stale CRM ownership data makes the carve look cleaner than it is.** Guard: the output header carries `snapshot_date` and a re-run deadline (default 14 days). If the carve ships after that date the numbers are void, and the report says so in the header rather than in a footnote nobody reads.
- **Field history not tracked on `Account.OwnerId`.** Tenure and churn baselines silently collapse to zero, which reads as "nothing is moving." Guard: the skill checks whether `AccountHistory` contains `OwnerId` rows and returns `blocked` when coverage of that field is below the thresholds file's `history_coverage_floor`.
- **Rules written against fields with nulls.** Guard: the unassigned bucket is split by cause and names the specific field, so a backfill problem never gets misread as a rule-design problem.
- **A carve that balances the metric by shredding relationships.** Guard: churn is ranked by weighted disruption and protected accounts are surfaced by name, so the tradeoff appears in the report rather than in a rep's resignation two months later.
- **A ramp curve HR wrote rather than one the data supports.** Guard: `dry_run` mode backtests the curve against last year's new-hire cohort attainment. If observed months-to-full-productivity exceeds the file's curve by more than the thresholds file's `ramp_tolerance_months`, the skill warns before using the curve and reports the observed curve alongside it.
- **Simulating a carve that has already been socialized.** Once reps have seen the map, a `revise` verdict is politically expensive and gets ignored. Guard: the skill records `carve_status` from the carve spec, and when it is `socialized` the report opens with the note that revisions now carry a communication cost, so the leader weighs it explicitly rather than discovering it in the meeting.
# Carve input template
Replace the contents below with your real proposed carve. Two sections are required: `rules` (ordered) and `roster`. The example values are a mid-market/enterprise split for a US SaaS org — overwrite them, do not extend them.
## Metadata
```yaml
carve_name: FY27 Enterprise realignment
effective_date: 2026-11-01
carve_status: draft # draft | reviewed | socialized
owner: revops@example.com
routing_engine: salesforce-territory-management # or leandata, fullcast, custom-apex
```
`carve_status` changes how the report opens. Set it honestly: `socialized` means reps have already seen the map, and the simulator will say so in the header because revisions after that point cost credibility as well as effort.
## Rules — ordered, first match wins
The simulator evaluates these top to bottom and stops at the first match, because that is what the routing engine does at go-live. **Order is load-bearing.** If you reorder rules here, re-run the simulation; the assignment map changes.
Each rule needs `id`, `territory`, and `match`. `match` is a list of conditions, all of which must hold (AND). Use Salesforce API field names, not labels.
```yaml
rules:
- id: 1
territory: ENT-STRATEGIC
match:
- field: Account.Strategic_Account__c
op: equals
value: true
- id: 2
territory: ENT-WEST-1
match:
- field: Account.AnnualRevenue
op: gte
value: 500000000
- field: Account.BillingState
op: in
value: [CA, WA, OR, NV, AZ]
- id: 3
territory: ENT-WEST-2
match:
- field: Account.AnnualRevenue
op: gte
value: 100000000
- field: Account.BillingState
op: in
value: [CA, WA, OR, NV, AZ]
- id: 4
territory: MM-WEST
match:
- field: Account.BillingState
op: in
value: [CA, WA, OR, NV, AZ]
- id: 99
territory: UNASSIGNED-POOL
match:
- field: Account.Id
op: exists
```
Supported `op` values: `equals`, `not_equals`, `gte`, `lte`, `in`, `not_in`, `contains`, `exists`, `is_null`.
**On the catch-all.** Rule 99 above catches everything the earlier rules missed. Including one means your `no_rule_matched` count will always be zero and the coverage report shifts from "which accounts have no owner" to "how big is the pool." Both are valid designs; pick deliberately. Omit the catch-all if you want the simulator to surface genuine rule gaps by name.
**On nulls.** A rule condition against a null field does not match. If `Account.AnnualRevenue` is null on 400 accounts, those accounts skip rules 2 and 3 and fall through to rule 4 — silently landing in mid-market. The simulator reports these separately as `null_input_field` so you can tell a data problem from a design problem, but only if you have not masked them with a catch-all.
## Roster
One entry per quota-carrying rep in the carve. `start_date` is the rep's quota-carrying start date, not their hire date — the ramp factor is computed from it against the effective date.
```yaml
roster:
- user_id: 0053000000ABCDE
name: A. Okafor
territory: ENT-WEST-1
start_date: 2023-02-13
assigned_quota: 3800000
productivity_band: high # high | mid | low | unproven
- user_id: 0053000000FGHIJ
name: J. Reyes
territory: ENT-WEST-2
start_date: 2026-09-15
assigned_quota: 2100000
productivity_band: unproven
- user_id: 0053000000KLMNO
name: S. Baptiste
territory: ENT-WEST-2
start_date: 2026-09-01
assigned_quota: 2100000
productivity_band: unproven
```
`productivity_band` maps to a multiplier in the thresholds file. Use `unproven` for anyone without four full quarters of attainment history at this company — assigning them a band from their previous employer's numbers is how a capacity model gets optimistic.
## Territories with no roster entry
A territory that appears in `rules` but not in `roster` is reported as an empty territory, not as an error. That is a real and sometimes intentional state (an open req you plan to fill). The simulator counts its accounts as uncovered capacity and says so.
# Coverage and capacity thresholds template
This file is the org's definition of "too far." The simulator computes numbers regardless; these values decide which numbers become a `revise` verdict. Every value below ships populated with a defensible starting point — replace them with yours rather than accepting them, because a threshold nobody argued about is a threshold nobody enforces.
## Capacity model
```yaml
capacity:
productivity_bands: # annual new-business capacity per fully ramped rep, in ARR
high: 1600000
mid: 1100000
low: 700000
unproven: 900000 # deliberately mid-minus, not mid
shortfall_tolerance_pct: 10 # a territory may be under capacity by this much before flagging
```
Set `productivity_bands` from your own last-four-quarters attainment distribution, not from a benchmark report. The right way to derive them: take trailing-12-month closed-won new business per fully ramped rep in the segment, sort it, and use the 75th percentile for `high`, the median for `mid`, and the 25th percentile for `low`.
`unproven` sits below `mid` on purpose. A new hire's expected capacity is not the team median — the median is computed over people who survived their ramp.
## Ramp curve
The fraction of full productivity a rep carries in each month after their quota-carrying start date. The simulator applies the factor for the month the effective date falls in, then straight-lines the remainder of the fiscal period.
```yaml
ramp:
curve: # month after start_date : productivity factor
1: 0.00
2: 0.05
3: 0.15
4: 0.30
5: 0.45
6: 0.60
7: 0.75
8: 0.85
9: 0.95
10: 1.00
ramp_tolerance_months: 2 # dry_run warns if observed ramp exceeds the curve by more than this
```
The curve above is a 10-month enterprise ramp. A transactional mid-market motion typically reaches 1.00 in four to six months; a multi-year enterprise cycle can run past twelve. Use `dry_run` to backtest the curve against your last new-hire cohort before trusting it — the gap between the curve finance approved and the one the cohort actually produced is usually the largest single error in a capacity model.
## Disruption tolerances
```yaml
disruption:
material_stage: "Stage 3 - Validation" # opportunities at or past this stage count as material
material_deal_floor: 250000 # open amount above which a single moving deal is flagged
max_revenue_churn_pct: 25 # per territory, share of prior-year closed-won changing owner
tenure_weight_months: 24 # relationships older than this get the full tenure multiplier
```
`max_revenue_churn_pct` is the one to argue about. At 25%, a quarter of a territory's revenue relationships change hands before anyone objects. Teams with a high-touch enterprise motion often set this to 10-15%; teams doing volume mid-market can live at 40% because the relationship is with the product, not the rep.
## Protected accounts
Accounts that must not change owner without an explicit decision. These are surfaced by name in the churn report regardless of where they rank on weighted disruption.
```yaml
protected_accounts:
- account_id: 0013000000ABCDE
name: Northwind Traders
reason: renewal in Q1, single-threaded on current owner
- account_id: 0013000000FGHIJ
name: Contoso Fabrics
reason: active executive escalation
```
Keep this list short and dated. A protected list that grows every cycle and never shrinks stops being a signal and starts being a veto — review it at the start of each carve and drop entries whose reason has expired.
## Data quality floors
```yaml
data_quality:
history_coverage_floor_pct: 60 # share of accounts with at least one OwnerId row in AccountHistory
snapshot_staleness_days: 14 # re-run required if the carve ships later than this
```
`history_coverage_floor_pct` guards the churn baseline. Below this, `AccountHistory` is not reliably capturing ownership changes and tenure figures will read low across the board — which makes every carve look cheap. The simulator returns `blocked` rather than reporting a number it cannot support.
## Review date
```yaml
last_reviewed: 2026-08-10
```
The simulator prepends a warning to every report when this date is more than 180 days old. Thresholds drift as segments and headcount change, and a stale thresholds file produces confident verdicts against a model of a company that no longer exists.
# Sample output format
The exact Markdown the skill emits. Downstream consumers parse this shape — a Slack digest that reads the verdict line, a planning deck that lifts the three tables. Keep the heading text and column order stable; add columns at the right if you extend it.
Numbers below are illustrative. The values are internally consistent so you can check a renderer against them.
---
# Territory carve simulation — FY27 Enterprise realignment
snapshot_date: 2026-08-10 | effective_date: 2026-11-01 | re-run by: 2026-08-24
carve_status: draft | routing_engine: salesforce-territory-management
accounts evaluated: 4,812 | territories: 22 | reps: 31
thresholds last_reviewed: 2026-08-10
## Verdict: revise
Coverage is clean. Two territories breach the capacity floor, and one protected account moves to a rep who will be in month two on the effective date. Fixing both is a quota reallocation and a single carve-out, not a redesign.
## 1. Coverage
| bucket | accounts | cause | detail |
|---|---|---|---|
| assigned | 4,798 | — | matched rules 1-8 |
| unassigned | 9 | no_rule_matched | BillingState outside the five listed regions |
| unassigned | 5 | null_input_field | Account.Industry is null |
| empty territories | 0 | — | — |
**Rule match distribution.** Rule 4 (`MM-WEST`) absorbed 1,204 accounts, of which 387 reached it only because `Account.AnnualRevenue` was null and they skipped rules 2 and 3. That is a data gap presenting as a segmentation decision: those 387 accounts are being routed to mid-market by default, not by design. Backfill revenue on them before the effective date or accept that mid-market inherits an unknown number of enterprise-sized accounts.
## 2. Quota capacity
Ramp-adjusted capacity at the effective date, against assigned quota. Shortfall flags at more than 10% below assigned quota per the thresholds file.
| territory | reps | assigned quota | ramp-adj. capacity | gap | flag |
|---|---|---|---|---|---|
| ENT-WEST-1 | 2 | 3,800,000 | 3,910,000 | +110,000 | ok |
| ENT-WEST-2 | 2 | 4,200,000 | 2,940,000 | -1,260,000 | shortfall |
| ENT-EAST-1 | 3 | 5,100,000 | 5,340,000 | +240,000 | ok |
| ENT-EAST-2 | 2 | 3,600,000 | 3,120,000 | -480,000 | shortfall |
| MM-WEST | 6 | 6,600,000 | 6,720,000 | +120,000 | ok |
ENT-WEST-2 carries two reps with quota-carrying start dates in September 2026, putting both at month two on 2026-11-01 — a 0.05 ramp factor each. The territory is assigned 4.2M against an effective capacity of 2.94M. The account count is balanced against ENT-WEST-1; the capacity is not, which is what an account-count-balanced carve hides.
## 3. Named-account churn
Ranked by weighted disruption: material open pipeline multiplied by a tenure factor. Accounts on the protected list appear regardless of rank.
| account | from | to | material open pipeline | tenure (mo) | weighted | flag |
|---|---|---|---|---|---|---|
| Northwind Traders | A. Okafor | J. Reyes (ramp m2) | 890,000 | 41 | 890,000 | protected |
| Fabrikam Industrial | A. Okafor | S. Baptiste (ramp m3) | 620,000 | 33 | 620,000 | review |
| Contoso Fabrics | L. Zhang | S. Baptiste (ramp m3) | 410,000 | 18 | 307,500 | review |
| Tailspin Logistics | L. Zhang | M. Osei | 280,000 | 9 | 105,000 | ok |
**Aggregate.** 214 accounts change owner. 178 of them carry no open pipeline and no closed-won in the prior year — those are free to move. The four rows above account for 71% of total weighted disruption, which is the useful framing: this carve is not risky in general, it is risky for four accounts.
**Per-territory revenue churn.** ENT-WEST-2 sees 31% of its prior-year closed-won revenue change owner, against a 25% tolerance. ENT-WEST-1 sees 12%. No other territory exceeds 20%.
## 4. What to change
- **ENT-WEST-2 capacity.** A 1.26M gap against a 4.2M quota. Move roughly 1.2M of quota to ENT-EAST-1 and MM-WEST, which both have headroom, or grant a documented ramp allowance for the two September starters. Leaving it as drafted sets two new reps against a number the model says they cannot reach.
- **ENT-EAST-2 capacity.** A 480K gap, inside a single rep's band. One account-set adjustment closes it.
- **Northwind Traders.** On the protected list, 890K of material pipeline, 41 months of tenure with the current owner, receiving rep in month two. Carve it out of the realignment or delay the transfer one quarter.
- **Fabrikam Industrial.** Not protected, but the same shape. Worth an explicit decision rather than an implicit one.
- **387 null-revenue accounts routing to mid-market.** Backfill `Account.AnnualRevenue` before 2026-11-01 or re-run after the backfill; the mid-market capacity number above assumes they belong there.
## 5. Re-run conditions
Re-run this simulation if any of the following happens before the effective date:
- The carve rules change or are reordered.
- The roster changes (a start date moves, a rep leaves, a req is filled).
- 2026-08-24 passes without the carve shipping — the CRM snapshot exceeds the 14-day staleness floor.
- The null-revenue backfill completes.