@vruum/skills 0.6.59 → 0.6.61

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,6 +1,6 @@
1
1
  {
2
2
  "name": "vruum",
3
- "version": "0.6.59",
3
+ "version": "0.6.61",
4
4
  "description": "Vruum AI skills + remote MCP server for B2B GTM teams. Slash commands for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis, paired with the full Vruum MCP tool surface over OAuth 2.1.",
5
5
  "author": {
6
6
  "name": "Vruum AI",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vruum",
3
- "version": "0.6.59",
3
+ "version": "0.6.61",
4
4
  "description": "Vruum AI skills + remote MCP server for B2B GTM teams. Skills for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis, paired with the full Vruum MCP tool surface over OAuth 2.1.",
5
5
  "author": {
6
6
  "name": "Vruum AI",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vruum/skills",
3
- "version": "0.6.59",
3
+ "version": "0.6.61",
4
4
  "description": "Vruum AI skills for Claude Code, Claude Desktop, Codex CLI, and any AI assistant with a skill directory. Slash commands for outreach triage, engagement triage, pipeline filling, prospect enrichment, and reply diagnosis. Pairs with the Vruum MCP server at https://api.vruum.ai/mcp.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,5 +41,5 @@
41
41
  "outreach",
42
42
  "gtm"
43
43
  ],
44
- "contentHash": "e01e694eb0dd3fdf8067590b38ddd7b09c2288853c1ced48c335a4ae52eb4408"
44
+ "contentHash": "f5ca907d176ad7c540145cb39cddbc0958a05c7ceb5bf9d3b39aaaed8b6f0275"
45
45
  }
@@ -8,11 +8,11 @@ description: >-
8
8
  ---
9
9
  # Deal Triage
10
10
 
11
- You are a deal pipeline orchestrator. Your job is to efficiently review the seller's active deals by dispatching subagents that do deep deal analysis (timeline, stakeholders, MEDDIC qualification), then presenting structured results back to the seller for decisions.
11
+ You are a deal pipeline orchestrator. Your job is to efficiently review the seller's active deals by dispatching subagents that do deep deal analysis (timeline, the buying center, the SPICED record), then presenting structured results back to the seller for decisions.
12
12
 
13
13
  ## Why this skill exists
14
14
 
15
- Deal review requires cross-referencing multiple data sources per deal: stakeholder map, conversation timeline, MEDDIC qualification, meeting notes, risk signals. Each deal with full context consumes significant tokens. This skill dispatches independent subagents per deal, each with their own context window, who do deep analysis and return compact summaries.
15
+ Deal review requires cross-referencing multiple data sources per deal: the buying center, conversation timeline, the SPICED record (MEDDIC derived from it), meeting notes, risk signals. Each deal with full context consumes significant tokens. This skill dispatches independent subagents per deal, each with their own context window, who do deep analysis and return compact summaries.
16
16
 
17
17
  ## Subagent architecture
18
18
 
@@ -53,8 +53,8 @@ Each subagent prompt should include:
53
53
  - Instructions to follow the subagent workflow below
54
54
 
55
55
  **Subagent workflow** (each subagent runs read-only and independently — its tool surface excludes deal writes by design; mutation happens later in Step 4 with the seller's approval):
56
- 1. Call `get_deal_360` for the full deal context in one call (deal info, stakeholders, MEDDIC qualification state, the Customer Impact record under `impact_commitment` — SPICED fields with their basis, status, derived confidence, and `verified_priority` — and the recent activity timeline). If the consolidated endpoint isn't available in your tool list, fall back to `fetch` with type=deal — the deal row carries `qualification` and `qualification_score` when previously computed.
57
- 2. **Read** `qualification` / `qualification_score` from the response — do NOT qualify from the reviewer. `manage_deal` with action=qualify writes a fresh MEDDIC JSONB (an LLM call + a DB write); the reviewer is read-only. If `qualification` is null, the score is < 40, or the last qualification is older than 30 days, the reviewer emits a `re_qualify` recommendation and the orchestrator (this skill) runs `manage_deal` action=qualify ONLY after the seller approves in Step 4.
56
+ 1. Call `get_deal_360` for the full deal context in one call (deal info, the buying center under `stakeholders` — the nine roles: initiator, user, champion, decider, gatekeeper, influencer, executive_buyer, approver, purchaser — the Customer Impact record under `impact_commitment` — SPICED fields with their basis, `spiced` completeness with the `next` element to establish, the derived `meddic` view, status, confidence, `verified_priority` — and the recent activity timeline). If the consolidated endpoint isn't available in your tool list, fall back to `fetch` with type=deal — the deal row carries `qualification` and `qualification_score` when previously computed.
57
+ 2. **Read** `impact_commitment.spiced` / `qualification_score` from the response — do NOT qualify from the reviewer. `manage_deal` with action=qualify extracts a fresh SPICED record from the conversations (an LLM call + a claim write; MEDDIC is derived from it); the reviewer is read-only. If no record stands, the completeness score is < 40, or the record is older than 30 days, the reviewer emits a `re_qualify` recommendation and the orchestrator (this skill) runs `manage_deal` action=qualify ONLY after the seller approves in Step 4.
58
58
  3. Call `get_person_360` for the primary stakeholder (first champion, or first person).
59
59
  4. Call `fetch` with type=account_state for the deal's account stage + health. If 404 (no row yet), default to `prospect` / null health.
60
60
  5. Return a structured summary in this exact format:
@@ -70,7 +70,7 @@ ACCOUNT_HEALTH: {0-100 or "—"}
70
70
  RISK_SCORE: {0-100}
71
71
  ALERTS: {silence_14d, overdue_next_step, slippage, etc. or "none"}
72
72
  STAKEHOLDERS: {count} ({comma-separated roles})
73
- QUALIFICATION: {score}/100 — gaps: {comma-separated gaps or "none"}
73
+ SPICED: {completeness score}/100 — next: {situation | pain | impact | critical_event | decision | "complete"} — MEDDIC gaps: {comma-separated derived gaps or "none"}
74
74
  RECOMMENDATION: {advance_stage | set_next_step | add_stakeholder | re_qualify | record_impact | close | mark_stalled | no_action}
75
75
  CONFIDENCE: {high | medium | low}
76
76
  REASONING: {1-2 sentences explaining the recommendation, including post-close trajectory when account_stage is informative}
@@ -97,16 +97,16 @@ After presenting results, the user can request actions. Execute them using MCP t
97
97
  - **Advance stage** → `manage_deal` action=stage with payload={stage}
98
98
  - **Set next step** → `manage_deal` action=update with payload={next_step, next_step_due_at}
99
99
  - **Add stakeholder** → `manage_deal` action=stakeholders with payload={action: 'add', person_id, role}
100
- - **Re-qualify** → `manage_deal` action=qualify (runs MEDDIC analysis again and refreshes the Customer Impact record from it)
101
- - **Record impact** → `manage_deal` action=impact_commitment with the SPICED fields the seller confirmed (payload={situation?, pain?, impact? {rational? {metric, baseline, target, unit, by}, emotional?}, critical_event? {kind, due|milestone, consequence}, decision?, first_impact_by?, clear_critical_event?}). Recommend it when `impact_commitment` is null, when `verified_priority` is false on a deal past discovery (no critical event with a consequence, or no named beneficiary), or when the conversation named a different impact or date than the record. Never invent a critical event from the seller's timeline; a renewal date is compelling at most.
100
+ - **Re-qualify** → `manage_deal` action=qualify (extracts the SPICED record again from the conversations and meetings, refreshes the Customer Impact record, and re-projects the MEDDIC view; the operator's own fields stand)
101
+ - **Record impact** → `manage_deal` action=impact_commitment with the SPICED fields the seller confirmed (payload={situation?, pain?, impact? {rational? {metric, baseline, target, unit, by}, emotional?}, critical_event? {kind, due|milestone, consequence}, decision? {criteria?, process?, buying_center? [{name | person_id, role}]}, first_impact_by?, clear_critical_event?}). Recommend it when `impact_commitment` is null, when `verified_priority` is false on a deal past discovery (no critical event with a consequence, or no named beneficiary), or when the conversation named a different impact or date than the record. Never invent a critical event from the seller's timeline; a renewal date is compelling at most.
102
102
  - **Close deal** → `manage_deal` action=won or action=lost (payload carries win_factors / loss_reason)
103
103
  - **Reopen deal** → `manage_deal` action=reopen with payload={stage}
104
104
  - **Mark stalled** → `manage_deal` action=stalled (records the stalled outcome; payload optional)
105
- - **Update account state** → `manage_account` action=state with id=<company_id> and payload={account_stage?, health_score?, arr_current?, arr_potential?, renewal_at?, notes?}. Do this whenever the review surfaced account-level facts: a stage that no longer matches reality (the backfilled stages have never been updated), a health read from the conversation, or ARR/renewal numbers the seller confirmed. The account row is what the impact scoreboard and deal_360 read — a stale stage there misleads every later review.
105
+ - **Update account state** → `manage_account` action=state with id=<company_id> and payload={renewal_at?, notes?, service_model?, scoped_labor_minutes_per_month?}. The account's lifecycle stage is NOT in this payload: it is derived from the facts (deal outcomes, impact events, recorded churn/renewal) and the response carries `account_stage_basis` — the fact that set it. To move a stage, record the fact: `manage_deal` action=won/lost/reopen, `manage_account` action=record_impact (practice + event_type from the practice's list; `winback`/`churn` ends the contract, `expansion`/`renewal_signed` restores it). There is no health score and no typed ARR: the account's value is `won_annual_value_minor` from its won deals' money records.
106
106
 
107
107
  For batch actions ("advance all deals in proposal"), confirm with the user before executing.
108
108
 
109
- **Account hygiene (every run):** for each reviewed deal's account, compare `account_state.account_stage` against what the deal review just showed (an `engaged`-stage account with a closed-won deal, or a `prospect` account with an active opportunity, is stale). Propose the corrected stage in the Step 3 summary and write it via `manage_account` action=state on approval. This is the write half of the accounts loop — the read half (scoreboard, deal_360) only works if reviews maintain it.
109
+ **Account hygiene (every run):** for each reviewed deal's account, read `account_state.account_stage` with its `account_stage_basis` and the `lifecycle.reasons`. The stage already follows the deals, so a mismatch means a FACT is missing, not a label: a customer that is still `committed` has no post-commit impact event on record (ask what the customer got and record it), an account the seller calls lost is `adopting` until a `churn` is recorded, a renewal the seller mentioned is not on file until `renewal_signed` is. Propose the missing facts in the Step 3 summary and record them on approval. This is the write half of the accounts loop — the read half (scoreboard, deal_360) only works if reviews record what happened.
110
110
 
111
111
  ## Error handling
112
112
 
@@ -48,7 +48,7 @@ candidate in the skill's Step 3 enrichment and:
48
48
  - Up-rank rows where `account_stage` is `adopting` or `expansion_ready`.
49
49
  - Down-rank or skip rows where `account_stage` is `dormant` or `churned` —
50
50
  those belong in `/winback-fill`, not expansion.
51
- - Use `accounts.health_score` (returned in the same payload) as a gate;
51
+ - Use the derived `account_stage` with its `account_stage_basis` (returned in the same payload) as the gate: `adopting` / `expansion_ready` means impact recurs;
52
52
  `> 70` is the floor for a productive expansion conversation.
53
53
 
54
54
  The skill does not change account stages itself — stages are set in the
@@ -61,7 +61,7 @@ Per-account features the skill computes from `get_person_360` +
61
61
 
62
62
  - `accounts.renewal_at` (from `fetch` type=account_state) — proximity weight
63
63
  (60-180d sweet spot)
64
- - `accounts.health_score` — gate (>70 only)
64
+ - `accounts.account_stage` — gate (`adopting` or `expansion_ready` only; there is no typed health score)
65
65
  - `accounts.account_stage` — boost (`adopting`, `expansion_ready`) or skip
66
66
  (`dormant`, `churned`)
67
67
  - Most recent `practice='adoption'` activity in last 60d — engagement signal
@@ -44,7 +44,7 @@ Step 3 — Per-account enrichment. For each surfaced (person, company):
44
44
 
45
45
  Step 4 — Score and rank. Within the cohort, rank by:
46
46
  - (a) **Renewal pressure** — `accounts.renewal_at` within 60-180 days → up-rank
47
- - (b) **Health signal** — `accounts.health_score` > 70 (only push expansion if account is healthy)
47
+ - (b) **Health signal** — the derived stage with its basis: `adopting` / `expansion_ready` means impact recurs (value events in ≥3 of the last 4 weeks); there is no typed health score
48
48
  - (c) **Recent engagement** — if there's `practice='adoption'` activity in the last 60d (account engaged), up-rank
49
49
  - (d) **Account stage** — `accounts.account_stage IN ('adopting', 'expansion_ready')` → up-rank; `dormant` → down-rank or skip
50
50
  - (e) **Champion present** — if any `company_people` row has been engaged in the last 30d (touch sent or reply received), surface the champion's name
@@ -66,7 +66,7 @@ Step 6 — Hand off to outreach. Two options:
66
66
  - **Option A (recommended)**: Approve the ranked list, then for each account: run `/pipeline-fill` with that prospect_list — same Sales Nav harness flow, just sourced from the expansion cohort instead of cold. Tag the resulting `outreach_plans.tag` with `bowtie_pilot:expansion` so success-tracking finds them.
67
67
  - **Option B**: Direct `manage_outreach` action=start with an expansion objective: create it with `target.lever = {"component": "expansion"}` (`objective_create`) and the right tone — formal, ROI-focused, no opener-hooks since the customer already knows you. The lever does the sourcing work: the plan's pool is the installed base (`accounts.account_stage = 'expansion_ready'`, no open deal), no discovery provider runs, the conversion evidence is scoped to expansion (an acquisition rate never sizes it), and `objective_source` qualifies the buyer titles at those accounts for free.
68
68
 
69
- Step 7 — Success tracking (auto). When a calendar webhook fires a `meeting_booked` event on an outreach plan tagged `bowtie_pilot:expansion`, the webhook handler in `backend/app/domains/calendar/` auto-records the impact event, equivalent to:
69
+ Step 7 — Success tracking (auto). When a calendar `meeting_booked` outcome lands on an action whose objective's growth lever names expansion (`target.lever.component = "expansion"`), `deals/services/lifecycle_outcomes.record_lifecycle_meeting` records the impact event, equivalent to:
70
70
  ```
71
71
  manage_account(
72
72
  action="record_impact",
@@ -78,9 +78,9 @@ manage_account(
78
78
  }
79
79
  )
80
80
  ```
81
- You do NOT manually record the impact event for tagged plans. If a meeting is booked outside Vruum (manual scheduling, calendar tool not connected), record it manually via `manage_account` action=record_impact from the person 360 Activity tab.
81
+ You do NOT manually record the impact event for meetings booked under an expansion objective. If a meeting is booked outside Vruum (manual scheduling, calendar tool not connected), record it manually via `manage_account` action=record_impact from the person 360 Activity tab — `event_type` must be one of the expansion practice's types.
82
82
 
83
- After 30 days, run `fetch` type=scoreboard subtype=impact to measure cohort uplift: expansion `event_count` should be > 0 with `impact_sum` matching the booked deals' annual values (minor units, one currency).
83
+ After 30 days, run `fetch` type=scoreboard subtype=impact with `id=<company_id>` per account to measure cohort uplift: expansion `event_count` should be > 0 with `impact_sum` matching the booked deals' annual values (minor units, one currency).
84
84
 
85
85
  ## When NOT to use this skill
86
86
 
@@ -97,7 +97,7 @@ For each approved transcript:
97
97
  Source: <transcript filename> (Google Drive)
98
98
  ```
99
99
  The `[vruum-meeting:<doc_id>]` marker is what makes re-runs idempotent (Step 5 scans for it). It **must be the very first thing in the summary** — `get_person_360` truncates the activity description to ~200 chars, so a marker placed at the end is cut off and the dedup scan silently fails (re-runs would create duplicate meetings). Keep it verbatim, at the front.
100
- 2. **Record the impact event** — call `manage_account` with action=record_impact, id=<the person's company_id> (from `get_person_360`), and payload={practice: "meeting", event_type: "meeting_held", person_id, summary: <the 1–2 sentence recap, WITHOUT the marker>}. This stamps the account's `first/last_impact_at` and feeds the impact scoreboard — a held meeting is exactly the "value delivered" moment that table exists to record. Skip silently if the person has no linked company.
100
+ 2. **Name the meeting's purpose** — pass `purpose` on the `manage_person` interaction (step 1) when the transcript makes it clear: discovery, demo, proposal, negotiation, commit, kickoff, impact_review, renewal, expansion, winback, internal, other. The held meeting's timeline event under its practice (`discovery_held`, `kickoff_held`, `impact_review_held`, …) is written by the backend from the purpose; you do NOT call `manage_account` action=record_impact for the meeting itself — a held meeting is not impact. Record impact only when the transcript states a RESULT the customer got (a value in a unit): then `manage_account` action=record_impact with a post-commit practice (onboarding | adoption | expansion), its event type, `value_delivered_numeric` and `value_delivered_unit`.
101
101
  3. **Create each approved task** — `manage_tasks` action=create with:
102
102
  - `title` (the action item), `person_id` (+ `deal_id` if there is one)
103
103
  - `priority`, and `due_at` as ISO-8601 **only if** a date was actually parseable (omit otherwise)
@@ -20,7 +20,7 @@ Ask what cohort they want to reach if they haven't said. Criteria can combine:
20
20
 
21
21
  - **List**: a named list (e.g. mirrored from a CRM export) — `filters={list: "<name or id>"}`
22
22
  - **Custom attributes** from their import (e.g. sorted company size / industry / region) — `filters={custom: {"sorted_company_size": "small", "sorted_industry": "staffing & recruiting"}}`
23
- - **Persona** (buying role): influencer | decision_maker | economic_buyer — `filters={persona: "economic_buyer"}`
23
+ - **Persona** (buying-center role, Revenue Architecture Table 8.2): initiator | user | champion | decider | gatekeeper | influencer | executive_buyer | approver | purchaser — `filters={persona: "executive_buyer"}`
24
24
  - Standard filters: stage, score range, enrollment, relationship type
25
25
 
26
26
  If they reference attributes you haven't seen, call `search` with `type="people"` and `limit=1` first and inspect a row's `custom_fields` keys so you offer real attribute names, not guesses.
@@ -19,7 +19,7 @@ A closed-lost deal is not a closed door. Most "lost" deals had a real conversati
19
19
  - Their company has had a recent trigger (new exec, funding, news event)
20
20
  - A former champion has moved to a new company (the "champion follows you" play)
21
21
 
22
- The impact scoreboard and the `account_stage='churned'`/`'dormant'` tagging let this skill target the right accounts deterministically.
22
+ The impact scoreboard and the derived `account_stage` (`churned` on a recorded churn or cancelled subscription, `dormant` after 60 days without impact — see `docs/ACCOUNT-LIFECYCLE-VOCABULARY.md`) let this skill target the right accounts deterministically.
23
23
 
24
24
  ## Where heavy logic lives
25
25
 
@@ -57,7 +57,7 @@ Limit 50. Order by `stage_changed_at DESC` (most-recent loss first — freshest
57
57
  Step 3 — Per-account enrichment.
58
58
  - `get_person_360` — what was the original conversation? `analysis` JSONB on the old deal often captures objection patterns.
59
59
  - `fetch` type=company_research — has anything changed at the company? New exec? Funding? Recent news?
60
- - `accounts.account_stage` — if `churned`, the account has been flagged as dead. Skip or down-rank unless variant 2/3 applies.
60
+ - `accounts.account_stage` — if `churned`, a churn was recorded (or the subscription cancelled); `account_stage_basis` says which. Skip or down-rank unless variant 2/3 applies.
61
61
 
62
62
  Step 4 — Score and rank.
63
63
  - **Loss reason quality**: `competitor_chose_other`, `timing`, `budget_cycle`, `no_decision` are revivable. `no_fit`, `no_budget_permanent` are not (already filtered, but double-check).
@@ -86,7 +86,7 @@ Step 6 — Hand off. Two options:
86
86
  - **Option A (recommended)**: Approve the list; run `/pipeline-fill` with the prospect_list for harness deep research + outreach. Plans get `outreach_plans.tag = bowtie_pilot:winback`.
87
87
  - **Option B**: Direct `manage_outreach` action=start with a winback-flavored objective (pre-create a `winback_<your-tenant>` objective — tone: empathetic, no apology, lead with what changed since last conversation). Winback is the book's closed loop over the Bowtie, not a growth component: leave `target.lever` at its default (acquisition by volume) and select the dormant/churned accounts through the objective audience (`objective_account`), so their people are the cohort and the plan does not buy new prospects for them.
88
88
 
89
- Step 7 — Success tracking (auto). The calendar webhook records the impact event, equivalent to:
89
+ Step 7 — Success tracking (auto). A calendar `meeting_booked` outcome with a `churned` or `dormant` account records the impact event (`deals/services/lifecycle_outcomes.record_lifecycle_meeting`), equivalent to:
90
90
  ```
91
91
  manage_account(
92
92
  action="record_impact",
@@ -98,7 +98,9 @@ manage_account(
98
98
  }
99
99
  )
100
100
  ```
101
- when a meeting is booked on a plan tagged `bowtie_pilot:winback`. You do NOT manually fire for tagged plans. After 30 days, `fetch` type=scoreboard subtype=impact should show winback `event_count` > 0.
101
+ whatever plan or objective the meeting came from. You do NOT fire it by hand. After 30 days, `fetch` type=scoreboard subtype=impact with `id=<company_id>` should show winback `event_count` > 0.
102
+
103
+ After a successful winback the stage follows the facts: a new open deal makes a `churned`/`dormant` account `engaged`, a win makes it `committed`, a `renewal_signed` impact event (practice expansion) cancels the recorded churn. Nobody types the stage (`manage_account` action=state carries no `account_stage`).
102
104
 
103
105
  ## When NOT to use this skill
104
106