# GTM workflow spec: <workflow name>

- Status: draft | approved for pilot | live. Version: <n>. Date: <YYYY-MM-DD>. Author: <name or agent run>. Reviewers: <names>
- Decision: When <signal> happens for <eligible unit>, <owner> gets <action> within <time>, and <outcome> returns to <report>.
- Business owner: <name>. Operator: <name>. Stop-control owner: <name>
- Unit: <account | contact>. Roll-up rule if both: <rule>
- Success outcome and window: <for example sales-accepted opportunity within 45 days>. Baseline today: <value and source>
- Weekly capacity: <reviewers> x <minutes per week> / <minutes per review, default 8> = <tasks per week>

## Systems and placement

- Executing system per decision: identity <system>, exclusions <system>, enrichment <system>, score <system>, route <system>, enrollment <system>, writeback <system>
- Durable state (episodes, enrollment keys, run ledger): <system>, because <reason>
- Read-only design access per system: <export, read-only MCP tools, identity used>

## Signals

One block per signal (at most three in a first workflow):

- Signal <id> <name>, class <direct request | first-party | inferred | public change>
  - Source and event key: <source>:<source event ID> (fallback hash: <fields>)
  - Identity basis: <CRM ID | unique external ID | domain | email>
  - Clocks: occurred_at <field>, observed_at <field>, actioned_at <field>
  - Expiry: <days, from which date>. Unknown source date: research only
  - Evidence kept: <reference and wording rule>. Episode rule: <account plus play within expiry>
  - Action ceiling: <owner task | sequence only for unowned new business | research>
  - Check frequency and cost: <checks per period x unit cost>
  - Rule version: <id>

## Identity and exclusions

- Match order: <CRM ID, unique external ID, normalized domain or email>. Ambiguous: hold with both IDs. Lookup error: retried, never "no match"
- Exclusions before any paid step, with reason codes and source of truth: suppressed <source>, customer <source>, open opportunity <source>, active conversation <window and source>, internal or test or competitor or partner <list>, excluded regions <list>
- Snapshot age at run time: <hours, at most 24>
- Reconciliation per stage: input = excluded by reason + held + passed

## Enrichment

- Data points and fields, each with its consumer and freshness: <field: consumer, days>
- Waterfall per data point: stage <n> <provider>, route <native | own key>, unit cost <USD per candidate or lookup>, charged on misses <yes | no>
- Acceptance policy: <valid accepted; accept-all and unknown held; invalid rejected; identity mismatch rejected>
- Stop and retry rules: <stop at first accepted; 3 retries with Retry-After; no fall-through on error>
- Spend controls and where each is enforced: run conditions <column: condition>, auto-run <state>, approved view or record count <n>, credit limits <MCP or per-user limit; workbook or table limit on Enterprise>
- Per-record and batch limits that no tool enforces: <USD each; checked after every run in the usage view and the ledger>
- AI research outputs and evaluation result: <supported, contradicted, insufficient; precision on labeled set>

## Scoring

- Gates outside the points: <list>
- Fit conditions and window: <list>. Engagement conditions and window: <list>. Excluded inputs: email opens, unidentified page views
- Unknown handling: <no points, completeness flag, research route>
- Proactive band: <thresholds>. Weekly band size against capacity: <n of n>. Tie-breaker: <latest signal, then account ID>
- Score version stored with each decision: <property or field>

## Routing

- Precedence with rule IDs: <R01 replay ... R99 fallback>
- Pools and distribution: <pool: members, method>
- Availability source and covering rule: <source; covering rep acts, ownership unchanged>
- Response targets and escalation: <first attempt, backup, team lead; coverage hours>
- Fallback owner and deadline: <name, minutes>
- Policy file: <path>. Dry run on <period>, <n> episodes (at least 200): <paste the last line of route_dry_run.py>. Rules that never fired and their test rows: <rule ID: test row result>

## Outbound

- Plays: <sequence name and version, segment, message version, sender set, schedule, per-mailbox daily limit and forecast peak>
- Gate fields re-checked at enrollment: <list>
- Approval scope and expiry: <audience snapshot, message version, sender set, schedule; 7 days>
- Enrollment key: <contact plus play plus episode>; unknown outcome handling: <reconcile by key before retry>
- Suppression path per tool and client scope, with test result: <tool, scope, test date, result>
- Stop rules: <reply, unsubscribe, hard bounce, meeting, opportunity; out-of-office pauses; company-level stop yes or no>
- Reply ownership: <who owns replies, response target>
- Sender paths with header evidence: <domain: SPF, DKIM d=, DMARC result, one-click unsubscribe present, Postmaster spam rate or no data>
- Pause and resume rule: <spam rate 0.1%, batch hard bounces 2%, opt-outs plus negative replies 1% over 7 days where Postmaster has no data, placement test in spam>

## CRM writeback

- Contract: <path>. Field classes: never <list>, enrichment-owned <list>, shared with candidates <list>
- Update gate: <known ID plus approved change>. Create gate: <authoritative zero match, identity evidence, permission, serialized per key>
- Blank and clear handling per writer and the tool setting that enforces it: <writer: setting>
- Loop prevention: <business events only; write only when different>
- check_writeback.py summary line: <paste>
- Change log location and rollback by run: <where before-values are kept>

## Cost

- Meters and unit prices: <provider, validation, platform actions>
- Fixed allocation and review time: <USD per run, minutes per accepted record x rate>
- Cost per returned candidate: <value>. Marginal per accepted by stage: <values>. Blended per accepted: <value>
- Ceiling and its source: <USD, decisions.md entry>
- Billed reconciliation: <provider: modeled vs billed, variance>

## Monitoring

- Runbook: <path>. Stop control: <switch, who, last test date>
- Weekly review: <day, attendees>. Expansion rule: after four reviews, zero safety FAILs, acceptance at or above <target>, cost within model

## Pilot and acceptance

- Pilot job: records <n>, fields <list>, providers <list>, per-record limit <USD> and batch limit <USD> checked after the run, no enrollment, no sends, approver <name>
- Acceptance cases run, with evidence links: <AC IDs and results>. Live tests pending, with owners: <AC IDs, owner>

## Open decisions

- <question>: <owner, due date>

## Proposed martech-context updates (not written)

- stack.md: <change>
- decisions.md: <entry>
- data-dictionary.md: <properties added or clarified>
