@oxygen-agent/cli 1.887.5 → 1.893.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,8 +1,8 @@
1
1
  // Knowledge Graph starter pack (the Karpathy LLM-wiki scaffold). A fresh workspace
2
- // self-seeds this page set on first onboarding / `oxygen knowledge seed` so the wiki
3
- // arrives alive: two active nav pages ([[start-here]] + the [[conventions]] schema page)
4
- // and seven draft stub hubs that show the shape of a healthy second brain without
5
- // grounding any AI copy until a human fills them.
2
+ // self-seeds this page set at tenant provisioning / first onboarding / `oxygen knowledge
3
+ // seed`, so the wiki arrives alive: two active nav pages ([[start-here]] + the
4
+ // [[conventions]] schema page) and nineteen draft stub hubs that show the shape of a
5
+ // healthy second brain without grounding any AI copy until a human fills them.
6
6
  //
7
7
  // The seeder (tenant-db `ensureKnowledgeScaffold`) is purely additive and version-gated:
8
8
  // it creates a page only when its slug is free (never overwriting a user's edits) and
@@ -10,9 +10,33 @@
10
10
  // and add pages with a higher `minScaffoldVersion` to ship a new wave; existing pages are
11
11
  // never rewritten by the scaffold. Bodies are the single source of truth for the starter
12
12
  // content — keep them dense and wikilinked.
13
+ //
14
+ // BINDING RULE — a scaffold wave adds ZERO active pages. Every content page ships
15
+ // `status: "draft"` with `seed` in its tags; only the two nav pages are active, and they
16
+ // are written full rather than as stubs. `retrieveWorkspaceKnowledge` selects on
17
+ // `status = 'active'` with MIN_BODY_CHARS = 80, so an ACTIVE stub is grounding material:
18
+ // "Stub — fill me. ## Firmographics —" would be injected verbatim into a customer's cold
19
+ // email as company knowledge. Promoting a stub to active is the user's act, never the
20
+ // scaffold's.
21
+ //
22
+ // NEVER SEED `outreach-learnings`, `won-lost-learnings`, or `meeting-learnings`. tenant-db
23
+ // `ensureLearningsPage` get-or-creates them as `active` on the first reply, deal, or
24
+ // meeting and returns an existing row UNTOUCHED — seeding them as draft stubs would pin
25
+ // them draft forever and silently break the learning loop's read half. They stay dashed
26
+ // unresolved links in [[campaign-learnings]] until the loop creates them for real.
13
27
  /** Monotonic scaffold cursor stored in knowledge_state.scaffold_version. Bump to ship a
14
- * new wave of starter pages (tag them with a higher minScaffoldVersion). */
15
- export const KNOWLEDGE_SCAFFOLD_VERSION = 1;
28
+ * new wave of starter pages (tag them with a higher minScaffoldVersion).
29
+ * v1: the 9-page core. v2: twelve GTM stubs (voice/brand/messaging/objections, three
30
+ * motion playbooks + qualification, and the personas/customers/research/metrics hubs). */
31
+ // KNOWN LIMITATION of a create-only seeder, accepted deliberately: on a workspace
32
+ // UPGRADED from an earlier wave, the new pages get no inbound links, because the hub that
33
+ // would link them (start-here) already exists and the scaffold never rewrites an existing
34
+ // page. Those pages are reachable through `knowledge index`, search and the graph, and
35
+ // `knowledge lint` excludes unfilled stubs from `orphans` so they are not reported as
36
+ // unfixable noise. Do NOT "fix" this by having the seeder patch existing bodies —
37
+ // never-overwrite is the entire safety property of this mechanism, and trading it for a
38
+ // tidier link graph on upgraded workspaces is a bad trade.
39
+ export const KNOWLEDGE_SCAFFOLD_VERSION = 2;
16
40
  const START_HERE_BODY = `# Start here
17
41
 
18
42
  This is the workspace's knowledge wiki — one shared, compounding second brain for every human and every AI agent here. It replaces scattered Notion docs, chat history, and one-off prompts.
@@ -24,13 +48,11 @@ This is the workspace's knowledge wiki — one shared, compounding second brain
24
48
  - **Trust travels.** Every claim cites its source. Canonical live copy (voice / brand / [[positioning]]) is human-approved; everything else auto-writes as revertible revisions. See [[conventions]].
25
49
 
26
50
  ## Hubs
27
- - [[icp]] — who we sell to
28
- - [[positioning]] — how we describe ourselves vs. alternatives
29
- - [[offers]] — what we sell and for how much
30
- - [[competitors]] — competitor teardowns (map of content)
31
- - [[playbooks]] — how we run each GTM motion (map of content)
32
- - [[campaign-learnings]] — what outreach and meetings taught us
33
- - [[decisions]] — standing GTM decisions and what would reverse them
51
+ - **Who we sell to** — [[icp]] accounts · [[personas]] buyers · [[customers]] who bought and why
52
+ - **What we say** — [[positioning]] vs. alternatives · [[voice]] how we sound · [[brand]] the promise and the provable claims · [[messaging]] hooks by persona · [[objections]] pushback and our answers
53
+ - **What we sell** — [[offers]] packages and prices · [[competitors]] teardowns
54
+ - **How we run it** — [[playbooks]] one page per motion · [[qualification]] the fit gate
55
+ - **What we learned** — [[campaign-learnings]] outcomes · [[metrics]] the numbers and their definitions · [[research]] dated investigations · [[decisions]] standing calls and what reverses them
34
56
 
35
57
  ## Seeing the shape
36
58
  \`oxygen knowledge graph\` (or the web graph) shows hubs, orphans, and dashed unresolved links — the gaps worth filling next. \`oxygen knowledge lint\` is the health report.
@@ -62,10 +84,10 @@ Index-first → open only relevant pages → answer citing slugs → file durabl
62
84
  | \`schema\` | describes the wiki itself (this page) |
63
85
 
64
86
  ## Slugs
65
- Flat kebab: lowercase alphanumerics + dashes, no slashes, ≤120 chars. **Immutable once created** — choose the durable name (\`competitor-clay\`, not \`clay-notes-july\`). No folders; types, tags, and [[wikilinks]] organize. Reserved (never create): \`index\`, \`log\`, \`schema\`, \`company-profile\`, \`readme\`.
87
+ Flat kebab: lowercase alphanumerics + dashes, no slashes, ≤120 chars. **Immutable once created** — choose the durable name (\`competitor-clay\`, not \`clay-notes-july\`). No folders; types, tags, and wikilinks organize. Reserved (never create): \`index\`, \`log\`, \`schema\`, \`company-profile\`, \`readme\`.
66
88
 
67
89
  ## Wikilinks
68
- \`[[slug]]\`, \`[[slug|alias]]\`, \`[[slug#heading]]\` all key to the slug. **Linking to a page that doesn't exist yet is good** — the dashed node is a visible to-do. Every page should link out (avoid dead-ends) and be linked to (avoid orphans).
90
+ Wrap a slug in double square brackets to link it. Three forms all resolve to the same page — bare (\`slug\`), aliased (\`slug|display text\`), and heading-anchored (\`slug#heading\`) — because the alias and the heading are stripped before lookup. **Linking to a page that doesn't exist yet is good** — the dashed node is a visible to-do. Every page should link out (avoid dead-ends) and be linked to (avoid orphans).
69
91
 
70
92
  ## New page vs. edit
71
93
  New page when it's a distinct entity/concept you'd link to from elsewhere. Edit in place when it's an attribute or update of an existing page. Search first (\`oxygen knowledge search\`) — near-duplicate slugs rot the graph.
@@ -87,14 +109,14 @@ Prune agent-derived claims once a human verifies the same fact. A contested clai
87
109
  Record standing calls in [[decisions]] using the template there. Every decision needs a rationale AND a \`## Reversal condition\` — the observable evidence that would flip it — so agents can flag when new data contradicts a standing decision.
88
110
 
89
111
  ## Stub-fill contract
90
- Seeded stubs (tag \`seed\`, still at revision 1, \`status: draft\`) are scaffolding. Replace the body with real cited content, keep the [[wikilinks]], set \`status: active\`. **No approval needed.** Until filled they stay draft and never ground AI copy. \`oxygen knowledge lint\` lists unfilled stubs.
112
+ Seeded stubs (tag \`seed\`, still at revision 1, \`status: draft\`) are scaffolding. Replace the body with real cited content, keep the wikilinks, set \`status: active\`. **No approval needed.** Until filled they stay draft and never ground AI copy. \`oxygen knowledge lint\` lists unfilled stubs.
91
113
 
92
114
  ## Lint discipline
93
- Run \`oxygen knowledge lint\` regularly. It reports orphans, dead-ends, unresolved links (ranked by demand), untagged pages, duplicate titles, oversized hubs, missing summaries/canonicals, stale/oversized pages, unfilled stubs, and decisions missing a reversal condition. \`oxygen knowledge lint relink\` rebuilds edges after bulk edits.
115
+ Run \`oxygen knowledge lint\` regularly — it is the health report, and it names its own categories, so read its output rather than a list here. Three worth knowing by name: **contradictions** (a page tagged \`disputed\` is silently excluded from every AI answer; \`disputed\` + \`verified\` together is a trust conflict; two active pages of the same live-copy type compete inside one prompt), **unfilled stubs** (ranked by how many pages already link to them — fill those first), and **stale** (untouched for 90 days, or *superseded*: sources filed onto the page after its last edit, which on a learnings page means \`oxygen knowledge synthesize\` is overdue, not that anything broke). \`oxygen knowledge lint relink\` rebuilds edges after bulk edits.
94
116
  `;
95
117
  const ICP_BODY = `# ICP — ideal customer profile
96
118
 
97
- > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the [[wikilinks]], then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
119
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
98
120
 
99
121
  ## Firmographics
100
122
  - Company type / size / stage:
@@ -108,7 +130,7 @@ const ICP_BODY = `# ICP — ideal customer profile
108
130
  - Who we should NOT pursue and why:
109
131
 
110
132
  ## Buyer personas
111
- - Link one [[persona]] page per buyer (economic buyer, champion, user).
133
+ - The buyers inside a fit account live in [[personas]] — one \`persona\` page each (economic buyer, champion, user).
112
134
 
113
135
  ## Basis
114
136
  - Cite the deals, calls, or market data this is drawn from. Contradicting evidence should route through [[campaign-learnings]] and update [[positioning]].
@@ -134,7 +156,7 @@ const POSITIONING_BODY = `# Positioning
134
156
  `;
135
157
  const OFFERS_BODY = `# Offers
136
158
 
137
- > **Stub — fill me.** Seeded scaffolding — fill, keep [[wikilinks]], set \`status: active\`. See [[conventions]].
159
+ > **Stub — fill me.** Seeded scaffolding — fill, keep the wikilinks, set \`status: active\`. See [[conventions]].
138
160
 
139
161
  ## Offers
140
162
  For each: name, who it's for ([[icp]]), price/packaging, the outcome it delivers, and qualifying criteria.
@@ -147,11 +169,10 @@ Tie each offer to the value in [[positioning]] and the motions in [[playbooks]].
147
169
  `;
148
170
  const COMPETITORS_BODY = `# Competitors (map of content)
149
171
 
150
- > **Stub — fill me.** This is a hub. Create one \`competitor\` page per rival (e.g. \`[[competitor-clay]]\`) and link it here; then fill this overview. See [[conventions]].
172
+ > **Stub — fill me.** This is a hub. Create one \`competitor\` page per rival — durable slugs like \`competitor-clay\`, \`competitor-apollo\` — wikilink each one here, then fill this overview. See [[conventions]].
151
173
 
152
174
  ## Landscape
153
- - One line per competitor + link to its teardown page.
154
- - [[competitor-example]] — replace with real teardowns.
175
+ - One line per competitor, wikilinked to its own teardown page. Replace this line with the real ones.
155
176
 
156
177
  ## Our stance
157
178
  - Where we consistently win / lose (draw from [[positioning]] and [[campaign-learnings]]).
@@ -162,6 +183,7 @@ const PLAYBOOKS_BODY = `# Playbooks (map of content)
162
183
 
163
184
  ## Motions
164
185
  - [[playbook-outbound]] — cold outbound
186
+ - [[playbook-inbound]] — inbound, referrals, and self-serve signups
165
187
  - [[playbook-nurture]] — nurture / re-engagement
166
188
  - (add: demo, onboarding, expansion)
167
189
 
@@ -178,6 +200,8 @@ Learning-worthy outcomes auto-file as **immutable sources** (facts, no approval)
178
200
  - completed meetings + notes → [[meeting-learnings]]
179
201
  - A/B auto-winners and human edits to AI drafts → the relevant learnings page
180
202
 
203
+ Those three pages do not exist yet — the first reply, closed deal, or completed meeting creates each one automatically, which is why they show as dashed unresolved links until then.
204
+
181
205
  ## Distill
182
206
  \`oxygen knowledge synthesize\` (and the opt-in scheduled agent) turns accumulated sources into learnings-page revisions — with citations and a "what would change our mind" line per recommendation. Retrieval then grounds the NEXT campaign's drafts on them.
183
207
 
@@ -201,11 +225,258 @@ The observable evidence that would flip this decision.
201
225
 
202
226
  Every decision MUST have a \`## Reversal condition\` — \`oxygen knowledge lint\` flags decision pages that lack one. Record the call in the log too: \`oxygen knowledge log append --event decision --slug <page> --summary "<what/why>"\`.
203
227
  `;
228
+ // ---------------------------------------------------------------------------
229
+ // Scaffold v2 — twelve GTM stubs. All draft + `seed`-tagged (see the binding rule
230
+ // at the top of this file). Every body opens with the same stub contract line and
231
+ // links out to at least one other page, so the wave adds no dead-ends.
232
+ // ---------------------------------------------------------------------------
233
+ const VOICE_BODY = `# Voice
234
+
235
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
236
+
237
+ ## Register
238
+ - Speaker (founder / team / product) and audience:
239
+ - Contractions, humour, emoji — allowed or never:
240
+ - One idea per sentence. Hard word cap:
241
+
242
+ ## Words
243
+ | Use | Avoid |
244
+ |---|---|
245
+ | (our word for the problem) | (the jargon it replaces) |
246
+
247
+ Banned hedges: just, hope this finds you well, wanted to reach out, circling back, solution, leverage.
248
+
249
+ ## Worked examples
250
+ - **We would send:** one real sentence of ours
251
+ - **We would not send:** the same idea, wrong — and why it fails
252
+
253
+ ## Canonical
254
+ Not pinned. Pinning it (\`oxygen knowledge page pin voice --approved\`) is a human-approved act — canonical voice grounds live copy. Claims are [[brand]]; what we do is [[positioning]].
255
+ `;
256
+ const BRAND_BODY = `# Brand
257
+
258
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
259
+
260
+ ## The promise (one line)
261
+ What a buyer gets from us and cannot get from the alternative named in [[positioning]]:
262
+
263
+ ## Claims
264
+ | We can substantiate | Proof (number, customer, doc) |
265
+ |---|---|
266
+ | 1 | |
267
+ | 2 | |
268
+ | 3 | |
269
+
270
+ Cannot substantiate yet — never write these until the proof is real: 1. 2. 3.
271
+
272
+ ## The ask (CTA ladder)
273
+ Smallest commitment first: reply → short call → pilot → paid. Never skip a rung on a first touch. Per-persona wording is [[messaging]]; what is actually sold is [[offers]].
274
+
275
+ ## Naming
276
+ Exact spelling and capitalisation of the company, the product, and each feature; one word or two; what we never call ourselves or the category. How it all sounds is [[voice]].
277
+ `;
278
+ const MESSAGING_BODY = `# Messaging playbook
279
+
280
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
281
+
282
+ Once active this page grounds outbound and reply drafts — every line here becomes copy a prospect reads.
283
+
284
+ ## Hooks by persona
285
+ | Persona | Trigger (why now) | Opening line, in their words |
286
+ |---|---|---|
287
+ | (one row per page in [[personas]]) | | |
288
+
289
+ ## Proof points — numbers only
290
+ | Claim | Number | Source |
291
+ |---|---|---|
292
+
293
+ No number, no claim. Pull them from closed deals and [[campaign-learnings]].
294
+
295
+ ## CTA ladder (soft to hard)
296
+ One-word reply → send the teardown → fifteen minutes → pilot.
297
+
298
+ ## What we never say
299
+ The banned hedges in [[voice]]; anything absent from the proof table in [[brand]]; a competitor smear — counter with [[positioning]].
300
+ `;
301
+ const OBJECTIONS_BODY = `# Objections
302
+
303
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
304
+
305
+ ## Handling
306
+ | Objection | Really asking | Our answer | Proof | Walk when |
307
+ |---|---|---|---|---|
308
+ | Too expensive | Is the outcome worth it? | | | |
309
+ | We use (rival) | What breaks if we switch? | see [[competitors]] | | |
310
+ | Not now | Is there a trigger? | | | no trigger named twice |
311
+ | Must ask someone | Who decides? | | | buyer absent twice |
312
+
313
+ ## Rules
314
+ One rebuttal, then a question — never two. Answer price with the outcome in [[offers]], not a discount. Never claim more about a rival than [[competitors]] proves.
315
+
316
+ ## When to walk
317
+ The hard-no list is [[icp]], the fit gate [[qualification]] — a stall matching one is a no, not a nurture. Feed the pattern to [[positioning]].
318
+ `;
319
+ const PLAYBOOK_OUTBOUND_BODY = `# Outbound playbook
320
+
321
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
322
+
323
+ ## Target and list
324
+ - Slice of [[icp]] this motion works (narrower than all of it):
325
+ - List source, and the filter that decides who is in:
326
+ - Offer we lead with, from [[offers]]:
327
+
328
+ ## Cadence
329
+ | Step | Day | Channel | Angle from [[messaging]] |
330
+ |---|---|---|---|
331
+ | 1 | 0 | | |
332
+ | 2 | | | |
333
+
334
+ Daily volume per sender:
335
+
336
+ ## Never enroll
337
+ Customers, open opportunities, anyone touched in the last N days, opt-outs, competitors.
338
+
339
+ ## Is it working
340
+ Reply rate, positive-reply rate, meetings per 1,000 sent — set a target for each. Outcomes land in [[campaign-learnings]].
341
+
342
+ ## Exits
343
+ Positive reply → [[qualification]]. Silent at the last step → [[playbook-nurture]]. Hard no → suppress.
344
+ `;
345
+ const PLAYBOOK_NURTURE_BODY = `# Nurture playbook
346
+
347
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
348
+
349
+ ## Who enters the not-now pile
350
+ - Not-now replies, stalled deals, no-shows, churned accounts, and still-fit [[icp]] leads who finished [[playbook-outbound]] silent.
351
+ - Who never enters: a hard no, an opt-out, anyone out of ICP.
352
+
353
+ ## Cadence
354
+ | Touch | Timing | What we send |
355
+ |---|---|---|
356
+ | 1 | | |
357
+ | 2 | | |
358
+
359
+ One touch per N weeks, no sequence pressure. Angles come from [[messaging]]; anything quoting an [[offers]] price must still be true when it lands.
360
+
361
+ ## Exit
362
+ A reply or a live trigger → [[qualification]]. Two full cycles with zero engagement → drop them, and log why in [[campaign-learnings]].
363
+ `;
364
+ const PLAYBOOK_INBOUND_BODY = `# Inbound playbook
365
+
366
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
367
+
368
+ ## Sources
369
+ | Source | Where it lands | Owner |
370
+ |---|---|---|
371
+ | Content / SEO | | |
372
+ | LinkedIn engagement | | |
373
+ | Product signups | | |
374
+ | Referrals | | |
375
+
376
+ ## Response SLA
377
+ Business hours, and off hours. Speed is the whole edge here — name the slowest reply we accept, then hold it.
378
+
379
+ ## First touch
380
+ - Match the person to a page in [[personas]] and answer in their language ([[messaging]]). Never a generic template.
381
+ - The one question worth asking first:
382
+
383
+ ## Routing
384
+ Run [[qualification]] before booking anything. Self-serve signups go to their own path. Anyone outside [[icp]] gets the honest no, fast.
385
+ `;
386
+ const QUALIFICATION_BODY = `# Qualification
387
+
388
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
389
+
390
+ ## Five discovery questions
391
+ Each one surfaces a pain, its cost, or the buying process — never a feature preference.
392
+ 1.
393
+ 2.
394
+ 3.
395
+ 4.
396
+ 5.
397
+
398
+ ## Must be true to advance
399
+ - A named pain one of our [[offers]] actually removes:
400
+ - Someone in the room who can spend:
401
+ - A date they want it working by:
402
+
403
+ ## Disqualifiers
404
+ The hard-no list is [[icp]] — do not copy it here. Add only what shows up on a call and ICP cannot see: no budget owner, no timeline, or a blocker we cannot move (see [[objections]]).
405
+
406
+ ## What counts as a next step
407
+ A booked meeting with a named person and a date on it. Not "send me info", not "circle back in Q3".
408
+ `;
409
+ const PERSONAS_BODY = `# Personas (map of content)
410
+
411
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
412
+
413
+ ## Roster
414
+ | Persona | Job to be done | Pain that costs them money | Trigger to buy now | Where they spend time |
415
+ |---|---|---|---|---|
416
+ | | | | | |
417
+
418
+ Create one page per buyer as type \`persona\` — slugs like \`persona-vp-sales\`, \`persona-founder\` — and link it in the first column. Cover the economic buyer, the champion, and whoever blocks the deal.
419
+
420
+ ## Rules
421
+ - Split a persona only when the pain or the trigger differs. Same pain, different title is one persona.
422
+ - Quote their words verbatim; those quotes become the hooks in [[messaging]].
423
+ - What they push back on belongs in [[objections]], not here.
424
+
425
+ Personas sit inside the account-level fit defined in [[icp]].
426
+ `;
427
+ const CUSTOMERS_BODY = `# Customers (map of content)
428
+
429
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
430
+
431
+ ## Roster
432
+ | Customer | Offer bought | Why they bought | Outcome number | Referenceable? |
433
+ |---|---|---|---|---|
434
+ | | | | | |
435
+
436
+ Create one page per customer as type \`entity\`, slugged with the company name, and wikilink it in the first column. Keep it to the deal story: what broke before, what they compared us to, what changed after.
437
+
438
+ ## Scope
439
+ Live account state — plan, seats, renewal, open tickets — is cheaper to re-fetch than to mirror, so it stays out (the density bar in [[conventions]]). This page holds only the durable narrative no query can rebuild.
440
+
441
+ Patterns here sharpen [[icp]], prove [[offers]], and supply the proof lines in [[messaging]].
442
+ `;
443
+ const RESEARCH_BODY = `# Research (map of content)
444
+
445
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
446
+
447
+ ## What lands here
448
+ Dated investigations as type \`research_note\`, slugged \`research-2026-03-pricing\`. Link each below, newest first. Agent-derived notes land here too, tagged \`agent-derived\` until verified.
449
+
450
+ Hub vs. note: a hub like [[icp]] or [[competitors]] holds the standing answer and is rewritten. A note is dated evidence, never rewritten — when it moves that answer, edit the hub and cite the note.
451
+
452
+ ## Note template
453
+ - **Question** — the one thing this note answers
454
+ - **Method** — what was searched, asked, or measured, over how many
455
+ - **Findings** — each with the URL or call it came from
456
+ - **What would change our mind** — evidence that would invalidate it
457
+ `;
458
+ const METRICS_BODY = `# Metrics
459
+
460
+ > **Stub — fill me.** Seeded scaffolding. Replace with real, cited content, keep the wikilinks, then set \`status: active\`. No approval needed. Draft stubs do not ground AI copy. How-to: [[conventions]].
461
+
462
+ ## The five numbers we steer by
463
+ | Metric | How we define it exactly | Current target | Where the live number lives |
464
+ |---|---|---|---|
465
+ | | | | |
466
+
467
+ Five, not fifteen. A number that would not change a decision this quarter is not one of them.
468
+
469
+ ## Do not paste live values here
470
+ This page holds definitions and targets — argued over once, then reused. The values live in Dashboards, which are always current; a pasted number is stale the next day, and the density bar in [[conventions]] rules out mirroring anything cheaper to re-fetch.
471
+
472
+ Moving a target is a call: record it in [[decisions]] with its reversal condition. Why it moved is evidence: that goes to [[campaign-learnings]].
473
+ `;
204
474
  /**
205
- * The 9-page starter pack. Two active nav pages first (start-here + the conventions schema
206
- * page), then the seven draft stub hubs (tag `seed`). `positioning` seeds as a NON-canonical
207
- * draft so it writes freely — pinning canonical positioning stays a separate human-approved
208
- * act. All at minScaffoldVersion 1 (the first wave).
475
+ * The 21-page starter pack. Two active nav pages first (start-here + the conventions
476
+ * schema page), then nineteen draft stub hubs (tag `seed`) — seven from wave 1 and
477
+ * twelve from wave 2. `positioning` seeds as a NON-canonical draft so it writes freely;
478
+ * pinning canonical positioning stays a separate human-approved act. Wave 2 adds ZERO
479
+ * active pages, per the binding rule at the top of this file.
209
480
  */
210
481
  export const KNOWLEDGE_SEED_PAGES = [
211
482
  {
@@ -237,6 +508,7 @@ export const KNOWLEDGE_SEED_PAGES = [
237
508
  summary: "Stub: the ideal customer profile — firmographics, triggers, and disqualifiers that define who we sell to. Fill with cited content and set active.",
238
509
  body: ICP_BODY,
239
510
  minScaffoldVersion: 1,
511
+ researchable: true,
240
512
  },
241
513
  {
242
514
  slug: "positioning",
@@ -247,6 +519,7 @@ export const KNOWLEDGE_SEED_PAGES = [
247
519
  summary: "Stub (non-canonical): how we describe ourselves against alternatives — for whom, the core value, and proof. Pinning the canonical positioning is a separate human-approved act.",
248
520
  body: POSITIONING_BODY,
249
521
  minScaffoldVersion: 1,
522
+ researchable: true,
250
523
  },
251
524
  {
252
525
  slug: "offers",
@@ -257,6 +530,7 @@ export const KNOWLEDGE_SEED_PAGES = [
257
530
  summary: "Stub: what we sell — packages, pricing, and the qualifying criteria per offer. Fill with cited content and set active.",
258
531
  body: OFFERS_BODY,
259
532
  minScaffoldVersion: 1,
533
+ researchable: true,
260
534
  },
261
535
  {
262
536
  slug: "competitors",
@@ -264,9 +538,10 @@ export const KNOWLEDGE_SEED_PAGES = [
264
538
  title: "Competitors (map of content)",
265
539
  status: "draft",
266
540
  tags: ["seed", "moc", "competitors"],
267
- summary: "Stub map-of-content: index of competitor teardown pages. Create one [[competitor-<name>]] page each; this hub links them and summarizes our overall competitive stance.",
541
+ summary: "Stub map-of-content: index of competitor teardown pages. Create one competitor-<name> page each; this hub links them and summarizes our overall competitive stance.",
268
542
  body: COMPETITORS_BODY,
269
543
  minScaffoldVersion: 1,
544
+ researchable: true,
270
545
  },
271
546
  {
272
547
  slug: "playbooks",
@@ -274,7 +549,7 @@ export const KNOWLEDGE_SEED_PAGES = [
274
549
  title: "Playbooks (map of content)",
275
550
  status: "draft",
276
551
  tags: ["seed", "moc", "playbooks"],
277
- summary: "Stub map-of-content: index of how-we-run-it playbooks (outbound, nurture, demo, expansion). Create one playbook page per motion and link it here.",
552
+ summary: "Stub map-of-content: index of how-we-run-it playbooks (outbound, inbound, nurture, demo, expansion). Create one playbook page per motion and link it here.",
278
553
  body: PLAYBOOKS_BODY,
279
554
  minScaffoldVersion: 1,
280
555
  },
@@ -298,4 +573,138 @@ export const KNOWLEDGE_SEED_PAGES = [
298
573
  body: DECISIONS_BODY,
299
574
  minScaffoldVersion: 1,
300
575
  },
576
+ {
577
+ slug: "voice",
578
+ type: "voice",
579
+ title: "Voice",
580
+ status: "draft",
581
+ tags: ["seed", "voice", "copy"],
582
+ summary: "Stub (non-canonical): how the workspace sounds — register and audience, the one-idea-per-sentence rule, words to use and avoid, banned hedges, and a would-send / would-not-send example pair. Fill it and set active; pinning the canonical voice is a separate human-approved act.",
583
+ body: VOICE_BODY,
584
+ minScaffoldVersion: 2,
585
+ researchable: true,
586
+ },
587
+ {
588
+ slug: "brand",
589
+ type: "brand",
590
+ title: "Brand",
591
+ status: "draft",
592
+ tags: ["seed", "brand", "copy"],
593
+ summary: "Stub (non-canonical): the promise in one line, the three claims we can substantiate with proof and the ones we cannot, the CTA ladder from reply to paid, and naming rules. Fill it and set active; pinning canonical brand copy stays human-approved.",
594
+ body: BRAND_BODY,
595
+ minScaffoldVersion: 2,
596
+ researchable: true,
597
+ },
598
+ {
599
+ slug: "messaging",
600
+ type: "message_playbook",
601
+ title: "Messaging playbook",
602
+ status: "draft",
603
+ tags: ["seed", "messaging", "copy"],
604
+ summary: "Stub: the message playbook — hooks and triggers per persona, proof points that must carry a number, the soft-to-hard CTA ladder, and what we never say. Once filled and set active it grounds outbound and reply drafts, so every claim needs its number and source.",
605
+ body: MESSAGING_BODY,
606
+ minScaffoldVersion: 2,
607
+ researchable: true,
608
+ },
609
+ {
610
+ slug: "objections",
611
+ type: "message_playbook",
612
+ title: "Objections",
613
+ status: "draft",
614
+ tags: ["seed", "objections", "sales"],
615
+ summary: "Stub: objection handling — a table of the objection, what the buyer is really asking, our answer, the proof behind it, and the point where we walk. Fill it and set active; it then grounds call prep and reply drafts.",
616
+ body: OBJECTIONS_BODY,
617
+ minScaffoldVersion: 2,
618
+ },
619
+ {
620
+ slug: "playbook-outbound",
621
+ type: "playbook",
622
+ title: "Outbound playbook",
623
+ status: "draft",
624
+ tags: ["seed", "playbook", "outbound"],
625
+ summary: "Stub: the cold outbound motion — which slice of the ICP it works, where the list comes from, channel/cadence and daily volume per sender, the never-enroll suppression list, the three numbers that say it is working, and where a reply exits to. Fill with real cadence and targets, then set active.",
626
+ body: PLAYBOOK_OUTBOUND_BODY,
627
+ minScaffoldVersion: 2,
628
+ },
629
+ {
630
+ slug: "playbook-inbound",
631
+ type: "playbook",
632
+ title: "Inbound playbook",
633
+ status: "draft",
634
+ tags: ["seed", "playbook", "inbound"],
635
+ summary: "Stub: the inbound motion — the sources (content/SEO, LinkedIn engagement, product signups, referrals) and where each lands, the response SLA in and out of business hours, a persona-matched first touch, and how a lead is routed, self-served, or refused. Fill and set active.",
636
+ body: PLAYBOOK_INBOUND_BODY,
637
+ minScaffoldVersion: 2,
638
+ },
639
+ {
640
+ slug: "playbook-nurture",
641
+ type: "playbook",
642
+ title: "Nurture playbook",
643
+ status: "draft",
644
+ tags: ["seed", "playbook", "nurture"],
645
+ summary: "Stub: the not-now motion — who enters the pile (not-now replies, stalled deals, no-shows, churned accounts, silent outbound finishers), who never does, the low-pressure touch cadence and what each touch sends, and the exit back to qualification or out. Fill and set active.",
646
+ body: PLAYBOOK_NURTURE_BODY,
647
+ minScaffoldVersion: 2,
648
+ },
649
+ {
650
+ slug: "qualification",
651
+ type: "playbook",
652
+ title: "Qualification",
653
+ status: "draft",
654
+ tags: ["seed", "sales", "qualification"],
655
+ summary: "Stub: the discovery and fit gate — five discovery questions, the must-be-true criteria to advance, sales-stage disqualifiers only (the hard-no list stays in the ICP page and is never copied here), and what actually counts as a next step. Fill and set active.",
656
+ body: QUALIFICATION_BODY,
657
+ minScaffoldVersion: 2,
658
+ },
659
+ {
660
+ slug: "personas",
661
+ type: "topic",
662
+ title: "Personas (map of content)",
663
+ status: "draft",
664
+ tags: ["seed", "moc", "personas"],
665
+ summary: "Stub map-of-content: the buyer roster — one row per persona covering job to be done, the pain that costs them money, the buy-now trigger, and where they spend time. Create one persona-typed page per buyer (persona-vp-sales, persona-founder) and link it here. This is the hub the ICP and start-here pages point at.",
666
+ body: PERSONAS_BODY,
667
+ minScaffoldVersion: 2,
668
+ },
669
+ {
670
+ slug: "customers",
671
+ type: "topic",
672
+ title: "Customers (map of content)",
673
+ status: "draft",
674
+ tags: ["seed", "moc", "customers"],
675
+ summary: "Stub map-of-content: the customer roster — offer bought, why they bought in their own words, the outcome number, and whether they are referenceable. Create one entity-typed page per customer and link it here; live account state (plan, seats, renewal, tickets) stays out, per the density bar.",
676
+ body: CUSTOMERS_BODY,
677
+ minScaffoldVersion: 2,
678
+ researchable: true,
679
+ },
680
+ {
681
+ slug: "research",
682
+ type: "topic",
683
+ title: "Research (map of content)",
684
+ status: "draft",
685
+ tags: ["seed", "moc", "research"],
686
+ summary: "Stub map-of-content for dated research_note pages: what belongs in a note versus a standing-answer hub, the note template (question, method, findings with URLs, what would change our mind), and the rule that agent-derived notes land here tagged agent-derived until a human verifies them.",
687
+ body: RESEARCH_BODY,
688
+ minScaffoldVersion: 2,
689
+ },
690
+ {
691
+ slug: "metrics",
692
+ type: "topic",
693
+ title: "Metrics",
694
+ status: "draft",
695
+ tags: ["seed", "moc", "metrics"],
696
+ summary: "Stub: the five numbers we steer by — metric, exact definition, current target, and where the live number actually lives. Definitions and targets only; live values belong in Dashboards, per the density bar in conventions. Moving a target is a decision; why it moved is a campaign learning.",
697
+ body: METRICS_BODY,
698
+ minScaffoldVersion: 2,
699
+ },
301
700
  ];
701
+ /**
702
+ * Seed slugs a domain-grounded research pass could genuinely draft from the company's
703
+ * PUBLIC web presence — what they sell, who they say they sell to, how they sound, who
704
+ * bought. Derived from the manifest's `researchable` flag (never a second hand-kept list),
705
+ * and consumed by `oxygen knowledge lint`'s researchable check, which reports the ones
706
+ * still sitting unfilled at revision 1 on a workspace that has a company domain.
707
+ */
708
+ export const KNOWLEDGE_RESEARCHABLE_SEED_SLUGS = KNOWLEDGE_SEED_PAGES
709
+ .filter((page) => page.researchable === true)
710
+ .map((page) => page.slug);
@@ -1,4 +1,4 @@
1
- export declare const OXYGEN_VERSION = "1.887.5";
1
+ export declare const OXYGEN_VERSION = "1.893.0";
2
2
  export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.181.0";
3
3
  export declare const MANAGED_INBOX_MINIMUM_CLI_VERSION = "1.326.2";
4
4
  export declare const SUPPORT_AGENT_REPLY_MINIMUM_CLI_VERSION = "1.747.0";
@@ -1,4 +1,4 @@
1
- export const OXYGEN_VERSION = "1.887.5";
1
+ export const OXYGEN_VERSION = "1.893.0";
2
2
  // The GLOBAL CLI compatibility floor: the oldest CLI allowed to call any
3
3
  // operational route. Raising it hard-rejects every older CLI from the entire
4
4
  // product, so it obeys one law, enforced by scripts/ci/cli-min-version-gate.mjs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxygen-agent/cli",
3
- "version": "1.887.5",
3
+ "version": "1.893.0",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",