@veleads/gtm 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,56 +1,111 @@
1
1
  ---
2
2
  name: 01-icp
3
- description: Stage 1 of the gtm-brain process. Turns intake and deal evidence into icp.md (rationale), icp.yaml (machine filters consumed by scripts) and signals.yaml (signals with weight, freshness and messaging angle), plus personas, offer, proof and voice. Ends at a hard stop for ICP sign-off by the project approver.
3
+ description: Stage 1 of the gtm-brain process. Turns research, intake and deal evidence into a layered ICP: a core profile every segment shares, 1–3 segments with what differs, personas, signals and exclusions. Writes icp.md (reasoning and hypotheses), icp.yaml (filters jobs use), signals.yaml, plus personas, offer, proof and voice. Ends at a hard stop for ICP sign-off by the project approver.
4
4
  ---
5
5
 
6
- # 01 · ICP research
6
+ # 01 · ICP
7
7
 
8
8
  ## Purpose
9
- Define who we target and why, in a form both humans (icp.md) and code (icp.yaml, signals.yaml) use.
9
+ Decide who we target and why, in a form people (`icp.md`) and jobs (`icp.yaml`, `signals.yaml`) both
10
+ use. **Stage 1 ends with a decision, not certainty.** From stage 2 on, gtm-brain assumes an approved
11
+ ICP. If you're unsure between candidates, approve the best one to three as segments and let results
12
+ decide; revising the ICP later is normal (change it, re-approve, continue).
10
13
 
11
14
  ## Inputs
12
- - `context/intake.md` (especially best customers, lost deals, triggers, exclusions)
13
- - Won/lost deal list from the stakeholders (company names, outcome, reason). No contacts.
15
+ - `context/research.md` (public customers, competitors, triggers) and the confirmed `context/intake.md`
16
+ - Won/lost deals from the stakeholders (company names, outcome, reason). No contacts.
14
17
  - Schemas: `.gtm/schemas/icp.schema.json`, `.gtm/schemas/signals.schema.json`
15
18
 
19
+ ## The five layers
20
+
21
+ | Layer | Question | Lives in |
22
+ |---|---|---|
23
+ | 1. **Core profile** | What kind of company fits *at all*? | `icp.yaml` → `core.firmographics` |
24
+ | 2. **Segments** | Which distinct groups do we treat differently? | `icp.yaml` → `segments` (only what differs from core) |
25
+ | 3. **Personas** | Who inside them do we contact? | `icp.yaml` → `personas`; pains and language in `personas.md` |
26
+ | 4. **Signals** | Who is likely to buy *now*? | `signals.yaml` |
27
+ | 5. **Exclusions** | Who must we never target? | `icp.yaml` → `exclusions` |
28
+
29
+ The *why* (pains, value proposition, proof, hypotheses) is human text in `icp.md`; the YAML holds only
30
+ what jobs filter on.
31
+
32
+ ## How core and segments combine
33
+ - A segment's final filters = **core, with every field the segment sets replacing the same core
34
+ field.** Lists are not combined: if core says `technologies_any: [A]` and a segment says `[B]`, the
35
+ segment uses only `[B]`.
36
+ - A segment can restrict `personas: [<ids>]`; otherwise it uses all personas.
37
+ - Exclusions apply to every segment.
38
+ - Check the result with **`npx gtm icp`**: it prints each segment's final filters and marks which fields
39
+ the segment set. Review that output, not the raw YAML.
40
+
41
+ ## Deciding core vs. segment
42
+ - **Core** = what every good-fit company has in common: usually industry family, size band, business
43
+ model, required tech. If removing it from one segment would feel wrong, it belongs in core.
44
+ - **A new segment** is justified only when something real differs:
45
+ - **filters** (region, sub-industry, size band, tech), and
46
+ - usually **treatment**: a different pain/angle, buyer, proof, language, compliance or send timezone.
47
+ A difference that changes neither filters nor treatment is not a segment.
48
+ - **Regions:** make a region its own segment when language, compliance, timezone or proof differ; it
49
+ will usually also be its own campaign (see `02-tam`).
50
+ - **One to three segments.** More dilutes volume per segment and makes results unreadable.
51
+ - **Ids** are short and say who: `uk-recruitment-agencies`, `de-recruitment-agencies`.
52
+
16
53
  ## Steps
17
- 1. From the best-customer list, find what the winners share: industry, size band, region, tech,
18
- business model. Write evidence, not guesses (e.g. "7 of 10 best customers use Sage 200").
19
- 2. Define 1–3 **segments**. Each segment must be expressible as filters in `icp.yaml`
20
- (`industries`, `employee_count`, `hq_countries`, `technologies_any/none`, `keywords_any/none`).
21
- If a criterion cannot be filtered, it belongs in `icp.md` as context, not in the YAML.
22
- 3. Define **personas** with `role` (decision_maker / champion / influencer / user), `titles_any`,
23
- `titles_none`, seniorities, departments. Write pains and language in `personas.md`.
24
- 4. Define **signals** in `signals.yaml`: for each, `level`, `source_hint` (kind of source, never a
25
- vendor), `weight` (0–100), `freshness_days`, and a `messaging_angle` copy can actually use.
26
- Only include signals that change *who* or *how* we message; fewer and stronger is better.
27
- 5. Write `offer.md` (low-friction outbound CTA) and finish `proof.md` / `voice.md` with the stakeholders.
28
- 6. Add `exclusions`: competitor domains, excluded industries/countries.
29
- 7. Estimate expected TAM range per segment (rough, from intake or a quick count if a TAM command is
30
- available). This sets up the stage-2 sanity check.
31
- 8. `npx gtm validate` must pass.
32
- 9. **HARD STOP.** Present to the human for sign-off: segments + filters, personas, exclusions,
33
- signals with weights, expected TAM range. Only after explicit approval from the named approver,
34
- record it: `npx gtm approve icp --by "<Name (role)>" --notes "<what was approved>"`. Quote the
35
- approval in the run log and commit both together.
54
+ 1. From `research.md` and intake, list what the **best customers share** (evidence, not guesses:
55
+ "7 of 10 best customers use Bullhorn"). These are core candidates.
56
+ 2. Group the remaining differences into **segment candidates**. For each, write in `icp.md`:
57
+ - **Hypothesis:** who, why they'd buy now, what proves it. _"UK agencies with 10+ open roles book
58
+ calls because hiring capacity is their bottleneck."_
59
+ - **Evidence:** wins, research, interviews.
60
+ - **Pain → value proposition → proof** for this segment.
61
+ - **Success criteria:** the number that would confirm it (e.g. "≥ 1.5 meetings per 100 contacts").
62
+ 3. Score candidates on paper (pain and urgency, ability to pay, reachability, market size, proof,
63
+ right to win). Drop clear losers; keep **one to three**.
64
+ 4. Write `icp.yaml`: `core.firmographics`, then `segments` with only their differences, then
65
+ `personas` (role, `titles_any`, **`titles_none`** to block junk, seniorities, departments) and
66
+ `exclusions` (competitor domains from research, excluded industries/countries). Any criterion that
67
+ can't be expressed as a filter stays in `icp.md` marked "context only".
68
+ 5. Write `signals.yaml`: for each signal `level`, `source_hint` (kind of source, never a vendor),
69
+ `weight` (0–100), `freshness_days`, and a `messaging_angle` a copywriter can use in one sentence.
70
+ Fewer and stronger is better.
71
+ 6. Run **`npx gtm icp`** and check every segment's final filters read as intended.
72
+ 7. Estimate the **expected TAM range per segment** (rough, from intake or research). It sets up the
73
+ stage-2 sanity check.
74
+ 8. Write `offer.md` (low-friction CTA) and finish `proof.md` / `voice.md` with the stakeholders.
75
+ 9. `npx gtm validate` must pass.
76
+ 10. **HARD STOP.** Present for sign-off: the `npx gtm icp` output (core + every segment's final
77
+ filters + personas), each segment's hypothesis and success criteria, exclusions, signals with
78
+ weights, expected TAM range. Record the approval:
79
+ - **GitHub approver** (`owners.approver` is `@handle`): commit the files on a branch, open a PR
80
+ (`gh pr create`), run `npx gtm track gate-open icp --pr <number>` and **stop**. After the
81
+ approver approves the PR on GitHub, run `npx gtm approve icp --pr <number>` (it verifies
82
+ the review on GitHub), commit the recorded approval and push it to the same PR branch, merge
83
+ once CI passes, then `npx gtm track gate-done icp`.
84
+ - **Named approver** (not on GitHub): present in the session; only after their explicit approval,
85
+ `npx gtm approve icp --by "<Name (role)>" --notes "<what was approved>"`.
86
+ Either way, quote the approval in the run log.
36
87
 
37
88
  ## Outputs
38
- `context/icp.md`, `icp.yaml`, `signals.yaml`, `personas.md`, `offer.md`, `proof.md`, `voice.md`.
89
+ `context/icp.md` (layers, hypotheses, evidence), `icp.yaml` (core + segments + personas +
90
+ exclusions), `signals.yaml`, `personas.md`, `offer.md`, `proof.md`, `voice.md`.
39
91
 
40
92
  ## Checklist
41
- - [ ] Every segment criterion in icp.md is either in icp.yaml or explicitly marked "context only"
42
- - [ ] Each persona has titles_none to block obvious junk (assistant, intern, interim...)
93
+ - [ ] Core holds what every segment shares; segments hold only real differences
94
+ - [ ] Every segment has a hypothesis, evidence and success criteria in `icp.md`
95
+ - [ ] One to three segments; each differs in filters and (usually) treatment
96
+ - [ ] `npx gtm icp` output reviewed: every segment's final filters read as intended
97
+ - [ ] Each persona has `titles_none` to block obvious junk (assistant, intern, interim...)
43
98
  - [ ] Each signal has a messaging angle a copywriter could use in one sentence
44
- - [ ] Signal weights sum to something sensible relative to campaign tier thresholds
45
- - [ ] Competitors and excluded industries listed
46
- - [ ] icp.md and icp.yaml agree
99
+ - [ ] Competitors (from research) and excluded industries listed
100
+ - [ ] `icp.md` and `icp.yaml` agree; non-filterable criteria marked "context only"
47
101
  - [ ] Approval recorded with `gtm approve icp`, not by hand
48
102
 
49
103
  ## Gate
50
104
  **ICP sign-off (hard stop).** Recorded with `npx gtm approve icp`, which pins a hash of the
51
- approved content. Any later change to segments, personas, exclusions or other ICP content makes
52
- `npx gtm validate` fail until the ICP is re-presented and approved again (or the change is reverted).
53
- Comments and formatting do not count as changes.
105
+ approved content (core, segments, personas, exclusions). Any later change makes `npx gtm validate`
106
+ fail until the ICP is re-presented and approved again (or the change is reverted). Comments and
107
+ formatting do not count as changes. Changing how volume is split between approved segments is a
108
+ campaign decision and needs no re-approval; adding or removing a segment does.
54
109
 
55
110
  ## Next
56
111
  Create a campaign (`npx gtm new-campaign <slug>`) and go to `.gtm/skills/02-tam/SKILL.md`.
@@ -17,19 +17,23 @@ Know how big the market is, and whether the ICP filters are right, before spendi
17
17
  1. Confirm the ICP gate is approved. If not, stop and go back to `01-icp`.
18
18
  2. Set `tam_id` in `config.yaml` (`<project>-tam-<YYYYqN>` or similar). Reuse an existing `tam_id`
19
19
  if the same project already has a TAM built from the same approved ICP.
20
- 3. Trigger the job: `npx gtm job tam <campaign>`. It reads segment filters from `icp.yaml`,
21
- pulls accounts through the configured account-source adapter, writes them to `accounts`, and
22
- prints counts per segment. **You do not page through accounts yourself.**
23
- 4. Funnel counts per segment:
20
+ 3. Set `config.yaml` → `tam.source` (the account source adapter; `mock-accounts` generates fictional
21
+ accounts to prove the pipeline, never for a real campaign) and `tam.max_accounts_per_segment`.
22
+ 4. Trigger the job: `npx gtm job tam <campaign>`. It validates, sends segment filters and exclusions
23
+ from `icp.yaml` to the workers, which page accounts through the adapter, upsert them into
24
+ `accounts` (re-runs update, never duplicate) and print counts per segment plus a run-log row.
25
+ **You do not page through accounts yourself.** If it says there is no Hatchet connection or keeps
26
+ waiting for a worker, stop and tell the human (AGENTS.md section 4).
27
+ 5. Funnel counts per segment (printed by the job):
24
28
  - **TAM**: accounts matching filters.
25
29
  - **Reachable**: accounts where at least one target persona can be found (from the job's
26
30
  persona count, or a sample-based estimate marked as an estimate).
27
31
  - **Active segment**: reachable minus exclusions and suppression.
28
- 5. Sanity check: compare against the expected range. Spot-check 20 random accounts in the DB console
32
+ 6. Sanity check: compare against the expected range. Spot-check 20 random accounts in the DB console
29
33
  (name, industry, size); count how many are clearly ICP. Do not paste the rows anywhere.
30
- 6. If the spot check finds a pattern of bad matches, propose an `icp.yaml` filter change. That
34
+ 7. If the spot check finds a pattern of bad matches, propose an `icp.yaml` filter change. That
31
35
  change resets the ICP gate, so present it to the human first.
32
- 7. Write `tam/<tam_id>.md` from `.gtm/templates/outputs/tam-summary.md` and the run log.
36
+ 8. Write `tam/<tam_id>.md` from `.gtm/templates/outputs/tam-summary.md` and the run log.
33
37
 
34
38
  ## Outputs
35
39
  - Rows in `accounts` (Postgres), tagged `project_id`, `tam_id`, `run_id`.
@@ -28,9 +28,15 @@ the approver signed off.
28
28
  5. Self-review against the checklist below, then render each step once with a fictional example
29
29
  lead (fictional name and company) for the human.
30
30
  6. **HARD STOP.** Present all variants for sign-off. Edits requested → change, re-present,
31
- still pending. Only after explicit approval from the named approver, record it:
32
- `npx gtm approve copy <campaign> --by "<Name (role)>" --notes "<what was approved>"`. Quote the
33
- approval in the run log and commit `copy.md`, `config.yaml` and the run log together.
31
+ still pending. Record the approval:
32
+ - **GitHub approver** (`owners.approver` is `@handle`): commit the files on a branch, open a PR
33
+ (`gh pr create`), run `npx gtm track gate-open copy <campaign> --pr <number>` and **stop**. After the
34
+ approver approves the PR on GitHub, run `npx gtm approve copy <campaign> --pr <number>` (it verifies
35
+ the review on GitHub), commit the recorded approval and push it to the same PR branch, merge
36
+ once CI passes, then `npx gtm track gate-done copy <campaign>`.
37
+ - **Named approver** (not on GitHub): present in the session; only after their explicit approval,
38
+ `npx gtm approve copy <campaign> --by "<Name (role)>" --notes "<what was approved>"`.
39
+ Either way, quote the approval in the run log.
34
40
 
35
41
  ## Outputs
36
42
  `copy.md` (status line at top reflects the gate). Run log.
@@ -17,7 +17,7 @@ Get the approved leads and copy into the sender safely, and start sending only o
17
17
  sequence from `copy.md`, pushes leads in send tiers, sets the schedule from `sending`. Write the
18
18
  returned reference into `config.yaml` → `sending.sender_campaign_ref`.
19
19
  3. Read the push counts: accepted vs. rejected (with reasons). Rejections > 2% → investigate first.
20
- 4. **HARD STOP: go/no-go.** Present: leads pushed by tier, daily volume and ramp, first send
20
+ 4. Run `npx gtm track gate-open launch <campaign>`. **HARD STOP: go/no-go.** Present: leads pushed by tier, daily volume and ramp, first send
21
21
  date/time, spend so far vs. cap, QA summary, sender campaign ref (paused). Ask the campaign owner
22
22
  or GTM engineer for an explicit go. Record in `config.yaml` → `gates.launch` per AGENTS.md section 4.
23
23
  5. Only after approval: `npx gtm job activate <campaign>`. Set `stage: results`.
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: research
3
+ description: Researches the business this project runs outbound for (product, pricing, positioning, public customers, competitors, buying triggers) from public sources before anyone is asked questions. Writes context/research.md with a source URL for every claim. Used first in stage 00-intake and re-run before new campaigns or when the market changes.
4
+ ---
5
+
6
+ # Research: the business, its customers and competitors
7
+
8
+ ## Purpose
9
+ Do the homework so stakeholders are only asked what research can't answer. Every fact is sourced,
10
+ so nothing invented reaches the ICP or the copy.
11
+
12
+ ## Inputs
13
+ - The business name and website (from `project.yaml` → `name`, or ask for the URL; that is the only
14
+ question allowed before researching).
15
+ - Existing `context/research.md` when re-running (update it; keep the history section).
16
+
17
+ ## Rules
18
+ 1. **Source every claim** with a URL in the same line. No source → it doesn't go in.
19
+ 2. **Public information only.** No paywalled content, no logging in, no scraping behind forms.
20
+ 3. **Companies, not people.** Record company names and domains. Do not collect names, emails or
21
+ profiles of individuals (prospect data belongs in Postgres via jobs, never in git).
22
+ 4. **Don't guess.** Unknown is a valid answer; mark it `unknown` and list it under open questions.
23
+ 5. **Mark confidence:** `confirmed` (the business's own site says it), `likely` (credible third
24
+ party: reviews, press), `inferred` (your reading of several sources; say why).
25
+ 6. **No web access?** Ask the human for the website URL and to paste the text of the home, product,
26
+ pricing and customers pages, then work from that and say so in the file.
27
+
28
+ ## Steps
29
+ 1. **The business:** home, product/solutions, pricing, customers/case studies, about, careers,
30
+ blog/news. Capture: what they sell (one sentence), who it is for, pricing model and visible price
31
+ points, proof points with numbers, positioning words they repeat.
32
+ 2. **Public customers:** logos and case studies on their site, plus credible mentions (press,
33
+ reviews). For each: company name, domain, industry/size/region/tech if visible, source. These are
34
+ **suppression candidates** (don't cold-email customers) and the main input for the ICP layers:
35
+ - **Core candidates:** traits most customers share (industry family, size band, required tech,
36
+ business model). Say how many share it ("7 of 10 use Bullhorn").
37
+ - **Segment candidates:** clusters that differ in a filter *and* in treatment (region/language,
38
+ sub-industry, size band, buyer). For each: the cluster, its members, and why it might need a
39
+ different angle.
40
+ 3. **Competitors (3–5):** from "alternatives to <business>" searches, review-site categories and
41
+ comparison pages. For each: domain, one-line positioning, pricing if public, how the business
42
+ differs. These are **exclusion candidates** for `icp.yaml`.
43
+ 4. **Market and triggers:** what makes a company buy now (hiring for X, new leader, funding,
44
+ migration, regulation), with sources. These seed `signals.yaml`.
45
+ 5. **Write `context/research.md`** from `.gtm/templates/project/research.md`.
46
+ 6. **Summarise for the human** in 5 lines: what you found, the strongest ICP hint, top competitors,
47
+ and the open questions only they can answer.
48
+
49
+ ## Outputs
50
+ `context/research.md`: sourced facts, customers (suppression candidates), **core candidates** and
51
+ **segment candidates** for the ICP, competitors (exclusion candidates), triggers (signal candidates),
52
+ open questions. Candidates are suggestions until a
53
+ stakeholder confirms them in intake or ICP.
54
+
55
+ ## Checklist
56
+ - [ ] Every claim has a URL and a confidence mark
57
+ - [ ] No individuals' personal data
58
+ - [ ] Customers and competitors listed with domains
59
+ - [ ] Open questions listed (only what research can't answer)
60
+
61
+ ## Next
62
+ Back to `.gtm/skills/00-intake/SKILL.md` (draft intake from research), or the stage that asked for a refresh.
@@ -5,6 +5,9 @@ campaign_id: __CAMPAIGN_ID__
5
5
  owner: __OWNER__
6
6
  stage: icp
7
7
  tam_id: __PROJECT_ID__-tam-TODO
8
+ tam:
9
+ source: mock-accounts # mock-accounts proves the pipeline locally; replace with a real account source
10
+ max_accounts_per_segment: 500
8
11
  segments: [segment-one]
9
12
  personas: [persona-one]
10
13
 
@@ -1,15 +1,51 @@
1
1
  # ICP: __PROJECT_NAME__
2
2
 
3
- > Human-readable rationale. The machine-readable version is `icp.yaml`. Keep them in sync.
3
+ > Written in stage `01-icp` from `research.md`, intake and won/lost deals. This file holds the *why*;
4
+ > `icp.yaml` holds the filters jobs use. Keep them in sync, and review the final filters with
5
+ > `npx gtm icp`. Mark anything that can't be a filter as **(context only)**.
4
6
 
5
- ## Who buys
7
+ ## Summary
8
+ One paragraph: who we sell to, the problem we solve for them, and why now.
6
9
 
7
- ## Segments
8
- 1. **<segment-id>**: description and evidence (win rate, cycle length, deal size).
10
+ ## 1. Core profile (every segment)
11
+ What every good-fit company has in common, with evidence.
9
12
 
10
- ## Personas
11
- - **<persona-id> (role):** titles, why they care.
13
+ | Criterion | Value | Evidence |
14
+ |---|---|---|
15
+ | Industry family | | _e.g. 8 of 10 best customers are staffing agencies_ |
16
+ | Size band | | |
17
+ | Business model | | (context only, if not filterable) |
18
+ | Required tech | | |
12
19
 
13
- ## Why they buy (evidence from won deals)
20
+ ## 2. Segments
21
+ One to three. Each differs from core in filters **and** (usually) treatment.
14
22
 
15
- ## Exclusions
23
+ ### <segment-id>
24
+ - **Who (filters beyond core):** _e.g. HQ in GB_
25
+ - **Hypothesis:** who, why they'd buy now, what proves it.
26
+ _"UK agencies with 10+ open roles book calls because hiring capacity is their bottleneck."_
27
+ - **Evidence:** wins, research, interviews.
28
+ - **Pain → value proposition → proof:**
29
+ - **Buyer / personas:** all, or only <persona-ids>
30
+ - **Treatment:** language, compliance basis, send timezone, offer differences (if any)
31
+ - **Expected TAM range:** _e.g. 2,000–4,000 companies_
32
+ - **Success criteria:** _e.g. ≥ 1.5 meetings per 100 contacts after 300 contacts_
33
+
34
+ ## 3. Personas
35
+ - **<persona-id> (decision_maker / champion / influencer / user):** titles, what they care about.
36
+ Details and language in `personas.md`.
37
+
38
+ ## 4. Signals (why now)
39
+ The triggers in `signals.yaml`, in plain words, with the angle each gives the copy.
40
+
41
+ ## 5. Exclusions
42
+ - Competitors (from `research.md`):
43
+ - Excluded industries / countries:
44
+ - Existing customers and open deals: loaded as suppression lists (never written here).
45
+
46
+ ## Candidates considered and dropped
47
+ | Candidate | Why dropped |
48
+ |---|---|
49
+
50
+ ## Decision log
51
+ - <YYYY-MM-DD>: first ICP drafted.
@@ -1,21 +1,30 @@
1
1
  # yaml-language-server: $schema=../.gtm/schemas/icp.schema.json
2
+ # Layers: core (every segment) → segments (only what differs) → personas → exclusions. Signals live in
3
+ # signals.yaml. A segment field REPLACES the same core field. Review the result with `npx gtm icp`.
2
4
  version: 2
3
5
  project_id: __PROJECT_ID__
4
6
  approval:
5
7
  status: pending # only a named human approves (AGENTS.md hard stop)
6
8
  approved_by: null
7
9
  approved_at: null
10
+ core:
11
+ firmographics:
12
+ industries: [TODO] # what every good-fit company shares
13
+ employee_count: {min: 20, max: 500}
8
14
  segments:
9
15
  - id: segment-one
10
- description: TODO
16
+ description: TODO # who, in a few words
11
17
  firmographics:
12
- industries: []
13
- employee_count: {min: 50, max: 1000}
14
- hq_countries: []
18
+ hq_countries: [] # only what differs from core, e.g. [GB]
19
+ # - id: segment-two
20
+ # description: ...
21
+ # firmographics: {hq_countries: [DE, AT, CH], employee_count: {min: 50, max: 1000}}
22
+ # personas: [persona-one] # optional: restrict personas for this segment
15
23
  personas:
16
24
  - id: persona-one
17
25
  role: decision_maker
18
26
  titles_any: [TODO]
27
+ titles_none: [Assistant, Intern]
19
28
  seniorities: []
20
29
  departments: []
21
30
  exclusions:
@@ -1,29 +1,44 @@
1
1
  # Intake: __PROJECT_NAME__
2
2
 
3
- > Stage 0 output. Fill every section; write "unknown" rather than leaving blanks.
3
+ > Stage 0 output. Drafted from `context/research.md` first; stakeholders only answer what research
4
+ > couldn't. Mark each field `(researched: <source>; confirm)`, `(confirmed by <who>)` or `(needs you)`.
5
+ > Write "unknown" rather than leaving blanks.
4
6
 
5
7
  ## Company
6
8
  - **What they sell (one sentence):**
9
+ _e.g. "Outbound lead generation for B2B SaaS, delivered as a managed service."_
7
10
  - **Website:**
8
- - **ACV / sales cycle / sales motion:**
11
+ - **Deal size, sales cycle and motion:** average first-year value, days from first call to signature,
12
+ and how deals close.
13
+ _e.g. "~$15k/year, 30–45 days, founder-led demo then proposal."_
9
14
  - **Current customers (count, typical size, industries, regions):**
10
15
  - **Why outbound now:**
11
16
 
12
17
  ## Goals
13
- - **Target (meetings / pipeline) and timeframe:**
14
- - **Meeting definition (who, what qualifies):**
18
+ - **Target and timeframe:** a number you can check later.
19
+ _e.g. "20 qualified meetings in 60 days."_
20
+ - **What counts as a meeting:** who must attend and what makes it qualified.
21
+ _e.g. "Head of Sales or founder at a 20–200 person SaaS company books a 30-min call."_
15
22
 
16
- ## Questionnaire
17
- 1. Top 10 best customers. Why did each buy? (company names only, no contacts)
23
+ ## Owners and regions
24
+ (Recorded in `project.yaml`, explained here.)
25
+ - **GTM engineer:** runs the agent and the jobs. _e.g. "@abdullah"_
26
+ - **SDRs:** handle replies and booked meetings. _e.g. "@sara", or "none yet"_
27
+ - **Approver:** says yes to the ICP and the copy before anything is sent. Must not be the person who
28
+ opens the PRs (GitHub doesn't allow approving your own PR). _e.g. "@maria (co-founder)"_
29
+ - **Regions:** where prospects are; drives privacy rules (GDPR for UK/EU) and TAM filters.
30
+ _e.g. "UK and US"_
31
+
32
+ ## Questionnaire (research pre-fills what it can)
33
+ 1. Best customers (up to 10, company names only). Why did each buy?
18
34
  2. Last 5 lost deals. Why did each lose?
19
- 3. Who signs, who champions, who blocks?
35
+ 3. Who signs, who champions, who blocks? (roles, not names)
20
36
  4. Top 3 competitors and how you win against each.
21
37
  5. Triggers that make a prospect buy now (hiring, funding, new leader, migration...).
22
38
  6. Proof you can use in outbound (case studies, numbers, logos) and what is off-limits.
23
39
  7. Tone: words you love, words you hate.
24
- 8. Regions you can legally and commercially serve.
25
- 9. Previous outbound: what was sent, results, which lists.
26
- 10. Anyone or anything we must never contact.
40
+ 8. Previous outbound: what was sent, results, which lists.
41
+ 9. Anyone or anything we must never contact.
27
42
 
28
43
  ## Constraints
29
44
  -
@@ -40,4 +55,4 @@
40
55
  | Calendar / booking link | stakeholder | |
41
56
  | Lawful basis documented (LIA for EU/UK legitimate interest) | stakeholder + GTM team | |
42
57
  | Privacy notice URL | stakeholder | |
43
- | Named approver for ICP + copy | stakeholder | |
58
+ | GitHub: owners added to the repo; `npx gtm github setup --apply` run | GTM team | |
@@ -4,9 +4,13 @@ project_id: __PROJECT_ID__
4
4
  name: __PROJECT_NAME__
5
5
  status: onboarding
6
6
  started_at: __TODAY__
7
+ # Owners: use GitHub handles (@username). An approver handle makes ICP/copy sign-off a PR review that
8
+ # GitHub enforces (CODEOWNERS). Use a plain name only for an approver who isn't on GitHub.
7
9
  owners:
8
- gtm_engineer: TODO
9
- sdrs: []
10
- approver: TODO # person who signs off ICP and copy for this project
11
- regions: [TODO]
10
+ gtm_engineer: TODO # e.g. "@abdullah": runs the agent and jobs
11
+ sdrs: [] # e.g. ["@sara"]: handle replies and meetings
12
+ approver: TODO # e.g. "@maria": signs off ICP and copy
13
+ regions: [TODO] # where prospects are, e.g. [UK, US]
12
14
  features: {} # opt-in core features (see .gtm/ CHANGELOG / FEATURES)
15
+ tracker:
16
+ kind: github # mirror stages and gates as GitHub issues (`npx gtm track`); "none" to switch off
@@ -0,0 +1,45 @@
1
+ # Research: __PROJECT_NAME__
2
+
3
+ > Written by the `research` skill. Every claim has a source URL and a confidence mark
4
+ > (confirmed / likely / inferred). Candidates are suggestions until a stakeholder confirms them.
5
+ > Companies only: no individuals' personal data.
6
+
7
+ - **Researched on:** <YYYY-MM-DD> by <agent / person>
8
+ - **Website:**
9
+ - **Web access:** yes / no (worked from pasted page text)
10
+
11
+ ## The business
12
+ | Fact | Value | Source | Confidence |
13
+ |---|---|---|---|
14
+ | What they sell (one sentence) | | | |
15
+ | Who it's for | | | |
16
+ | Pricing model / price points | | | |
17
+ | Proof points (numbers) | | | |
18
+ | Positioning words they repeat | | | |
19
+
20
+ ## Public customers (suppression candidates)
21
+ | Company | Domain | Industry / size | Source |
22
+ |---|---|---|---|
23
+
24
+ ### ICP hints
25
+ **Core candidates** (traits most customers share):
26
+ | Trait | How many customers share it | Source |
27
+ |---|---|---|
28
+
29
+ **Segment candidates** (clusters that differ in filters and treatment):
30
+ | Cluster | Differs by | Members | Why it may need its own angle |
31
+ |---|---|---|---|
32
+
33
+ ## Competitors (exclusion candidates)
34
+ | Competitor | Domain | Positioning | Pricing | How we differ | Source |
35
+ |---|---|---|---|---|---|
36
+
37
+ ## Buying triggers (signal candidates)
38
+ | Trigger | Why it matters | Source |
39
+ |---|---|---|
40
+
41
+ ## Open questions (only stakeholders can answer)
42
+ -
43
+
44
+ ## History
45
+ - <YYYY-MM-DD>: first research
@@ -22,3 +22,7 @@ npx gtm validate
22
22
  ## Core upgrades
23
23
  A weekly workflow opens a PR when a new core is released (`.github/workflows/gtm-upgrade.yml`).
24
24
  Manually: `npx gtm upgrade` (refuses while a campaign is between QA and launch).
25
+
26
+ ## GitHub
27
+ Approvals and tracking run through GitHub: see `.gtm/guides/github.md` (owners as `@handles`,
28
+ `npx gtm github setup --apply`, PR-based sign-off, the org-wide board).
@@ -6,6 +6,7 @@ on:
6
6
 
7
7
  permissions:
8
8
  contents: read
9
+ pull-requests: read # gtm validate --verify-github reads PR reviews
9
10
 
10
11
  jobs:
11
12
  check:
@@ -25,5 +26,7 @@ jobs:
25
26
  fi
26
27
  - name: Core files untouched and in sync
27
28
  run: npx gtm sync --check
28
- - name: Validate project repo
29
- run: npx gtm validate
29
+ - name: Validate project repo (and verify GitHub approvals)
30
+ run: npx gtm validate --verify-github
31
+ env:
32
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veleads/gtm",
3
- "version": "0.3.0",
3
+ "version": "0.6.0",
4
4
  "description": "gtm-brain core: process kit (AGENTS.md, skills, templates, schemas) and the gtm CLI for client repos",
5
5
  "keywords": [
6
6
  "gtm",
@@ -34,11 +34,13 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "yaml": "^2.8.1",
37
- "zod": "^4.1.0"
37
+ "zod": "^4.1.0",
38
+ "@hatchet-dev/typescript-sdk": "1.43.0"
38
39
  },
39
40
  "devDependencies": {
40
41
  "tsup": "^8.5.0",
41
- "@gtm/schemas": "0.0.0"
42
+ "@gtm/schemas": "0.0.0",
43
+ "@gtm/core": "0.0.0"
42
44
  },
43
45
  "homepage": "https://github.com/Veleads/gtm-core#readme",
44
46
  "bugs": {