@vruum/skills 0.6.20 → 0.6.22

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.20",
3
+ "version": "0.6.22",
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.20",
3
+ "version": "0.6.22",
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.20",
3
+ "version": "0.6.22",
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": {
@@ -42,5 +42,5 @@
42
42
  "outreach",
43
43
  "gtm"
44
44
  ],
45
- "contentHash": "4ce9cba156c1aac9c8ccc3815020b6ee2ac510056092877763e9ee0f606bd805"
45
+ "contentHash": "749e37edf64565e38525384c6d7a817834a8ccbcf2e020d130a8e5821cda843f"
46
46
  }
@@ -20,18 +20,25 @@ This is an analyst's job, not a batch import. The attribution step (which person
20
20
  - **Drive connected to Vruum.** The transcripts must be syncing into the knowledge base via the connector. If KB search turns up none of your recent meetings, the connection may be down or PDFs may not be admitted — say so and stop; this skill reads what's synced, it doesn't fix the connector.
21
21
  - **Vruum MCP** for: `search` (kb + people reads), `get_person_360`, `manage_person` (to log the meeting as a `meeting`-kind interaction), `manage_tasks`, `get_tasks`.
22
22
 
23
- ### Step 1 — Find the transcripts
23
+ ### Step 1 — Establish the recency window, then find NEW transcripts
24
24
 
25
- Search the knowledge base for meeting-shaped documents:
25
+ **This skill is incremental and go-forward.** It ingests only meetings newer than the last one already logged, and never re-ingests the historical archive (a connected Drive can hold years of old transcripts — those stay KB-searchable but are not turned into CRM activity/tasks).
26
26
 
27
- - `search` type=kb with `filters={query: "meeting notes transcript", include_content: false}` for a compact catalog (id, name, summary, date).
28
- - Identify transcripts by their **filename shape**, not just the query these tools name files predictably:
29
- - **Gemini:** `… - Notes by Gemini`, `Notes by Gemini for …`, `… - Transcript`, `… - Live Notes`
30
- - **Read.ai:** `… - Read Meeting Report`, `Read AI …`, `… Smart Notes`
31
- - Default to a **recent window** (e.g. the last 2 weeks) unless the user asks for more.
32
- - Present the candidates as a short list: `name · meeting date · one-line summary`. Ask which to process (default: **all that aren't already logged** — Step 5 detects those).
27
+ 1. **Get the watermark.** Call `get_daily_briefing` and read `latest_logged_meeting_at` the date of the most recent meeting already logged for this tenant.
28
+ - **Set** the window is everything *after* that date.
29
+ - **`null`** (no meeting logged yet first run) **ask the operator for a seed date** ("Ingest meetings since when? (default: last 30 days)"). Never silently default to the whole archive.
33
30
 
34
- > Alternative source: if you have a Google Drive MCP pointed at the same Drive and a transcript hasn't synced into the KB yet, you can read it directly (`search_files` `read_file_content` for Docs, `download_file_content` for Read.ai PDFs) and feed the text into Step 3. Lead with the KB — it's tenant-scoped and is what the connector already pulled.
31
+ 2. **Find candidates.** `search` type=kb with `filters={query: "meeting notes transcript live notes", include_content: false}`. Connector results carry `source_kind='connector'`, the meeting date in `modified_at`, a Drive `url`, and predictable filename shapes:
32
+ - **Gemini:** `… - Notes by Gemini`, `… - Transcript`, `… - Live Notes`
33
+ - **Read.ai:** `… - Read Meeting Report`, `… Smart Notes`
34
+
35
+ 3. **Apply the window — drop everything at/before the watermark** (or the seed date). The Drive's historical archive is intentionally left KB-searchable-only, NOT re-ingested into the CRM. Logging an old meeting (and minting "follow up next week" tasks from a meeting that happened a year ago) is noise.
36
+
37
+ 4. Present the surviving candidates as a short list: `name · meeting date · one-line summary`. **If none are newer than the watermark, say so and stop** — there are no new meetings to ingest.
38
+
39
+ > **One meeting, one record.** Gemini + Read.ai often produce 3-4 artifacts per meeting (`- Transcript`, `- Live Notes`, `Read Meeting Report`, `- Chat`). Pick the single richest one (usually `- Transcript` or `Notes by Gemini`) and ingest that — don't log the same meeting multiple times.
40
+
41
+ > Alternative source: if you have a Google Drive MCP on the same Drive and a meeting hasn't synced into the KB yet, read it directly (`search_files` → `read_file_content` / `download_file_content`) and feed the text into Step 3. Lead with the KB — it's tenant-scoped and is what the connector already pulled.
35
42
 
36
43
  ### Step 2 — Read each chosen transcript in full
37
44
 
@@ -36,7 +36,7 @@ Keep it short. The user knows their queue — they just need the numbers to deci
36
36
 
37
37
  ### Step 2: Build the dispatch list and categorize
38
38
 
39
- Once the user says go (or picks a focus area), pull the lightweight message queue via `search` with type=messages and limit=100 — make TWO cheap calls: `status=needs_draft` (the authoring lane) and `status=draft` (the review lane). Each returns message IDs, person names, categories, sequence numbers, and match scores WITHOUT message content — very cheap on tokens. Tag each item with its status so dispatch routes it to the right mode: `needs_draft` → authoring, `draft` → review. (Omitting the status filter returns the default actionable set — needs_draft + draft + approved — but pull the two lanes explicitly so already-approved messages awaiting send don't enter triage.)
39
+ Once the user says go (or picks a focus area), pull the lightweight message queue via `search` with type=messages, `fields=compact` and limit=100 — make TWO cheap calls: `status=needs_draft` (the authoring lane) and `status=draft` (the review lane). `fields=compact` returns message_id, person_name, category, sequence_number, channel, status, match_score, touches_completed, and campaign_id WITHOUT message content — very cheap on tokens. Tag each item with its status so dispatch routes it to the right mode: `needs_draft` → authoring, `draft` → review. (Omitting the status filter returns the default actionable set — needs_draft + draft + approved — but pull the two lanes explicitly so already-approved messages awaiting send don't enter triage.)
40
40
 
41
41
  **Authoring mode (needs_draft items).** The backend no longer writes outreach prose — touches arrive as `needs_draft` items carrying the decision context (channel, touch number, signals) and no content. These are not rewrites; they are blank pages. For each needs_draft item the subagent AUTHORS the message: check the person's research freshness from the review item itself — `person_researched_at` / `company_researched_at` / `research_status` are on the payload, no extra fetch needed (older than ~14 days or missing → research first with WebSearch + the research reads, and persist what you learn via `research` action=save_person, plus action=save_company when you learned something about the company, so it compounds), then write the touch from scratch in the seller's voice against the same quality standards as any review, then submit it via `manage_messages` action=edit with the content — that transitions the item to a normal draft — and approve only what the user's standing instructions allow. Inbound replies also arrive as needs_draft (category inbound_reply, with the conversation attached): author the reply with full thread context. If a prospect turns out to be a bad fit at authoring time, skip the item and say why — authoring is the second qualification gate, not an obligation to write.
42
42
 
@@ -46,7 +46,7 @@ Categorize into three processing groups:
46
46
  2. **Follow-ups** (sequence_number >= 2) — need research and quality check
47
47
  3. **T1 initials** (sequence_number = 1) — usually structural check only
48
48
 
49
- Present the queue composition before dispatching:
49
+ Present the queue composition before dispatching. For the counts in one call, use `search` with type=messages and `view=breakdown` — it returns grouped counts (by status, category, sequence/touch number, channel, and campaign) over the whole queue plus a compact items page, so you don't have to tally the pages yourself:
50
50
 
51
51
  "Oaklet: 15 T1s, 5 T2s, 1 T3, 0 replies. How do you want to handle each group?"
52
52