@oxygen-agent/cli 1.1011.1091 → 1.1012.2

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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/dist/command-manifest.d.ts +3 -1
  3. package/dist/command-manifest.js +11 -0
  4. package/dist/customer-operation-commands.js +1 -1
  5. package/dist/index.js +57 -31
  6. package/dist/transcript.js +1 -1
  7. package/node_modules/@oxygen/formula/dist/expression.js +16 -0
  8. package/node_modules/@oxygen/shared/dist/attempt-provenance.d.ts +8 -0
  9. package/node_modules/@oxygen/shared/dist/attempt-provenance.js +15 -0
  10. package/node_modules/@oxygen/shared/dist/byok-connect.js +2 -0
  11. package/node_modules/@oxygen/shared/dist/capability-discovery.d.ts +2 -1
  12. package/node_modules/@oxygen/shared/dist/capability-discovery.js +28 -4
  13. package/node_modules/@oxygen/shared/dist/contracts/browser-operations.js +2 -2
  14. package/node_modules/@oxygen/shared/dist/contracts/customer-operations.js +3 -3
  15. package/node_modules/@oxygen/shared/dist/contracts/geo.d.ts +2 -0
  16. package/node_modules/@oxygen/shared/dist/contracts/geo.js +138 -0
  17. package/node_modules/@oxygen/shared/dist/contracts/operations.js +4 -3
  18. package/node_modules/@oxygen/shared/dist/contracts/table-row-removal.d.ts +8 -0
  19. package/node_modules/@oxygen/shared/dist/contracts/table-row-removal.js +10 -4
  20. package/node_modules/@oxygen/shared/dist/cost-estimate.d.ts +6 -0
  21. package/node_modules/@oxygen/shared/dist/cost-estimate.js +23 -8
  22. package/node_modules/@oxygen/shared/dist/enrichment-intents.js +2 -1
  23. package/node_modules/@oxygen/shared/dist/external-effect-arming.d.ts +54 -0
  24. package/node_modules/@oxygen/shared/dist/external-effect-arming.js +90 -0
  25. package/node_modules/@oxygen/shared/dist/geo.d.ts +247 -0
  26. package/node_modules/@oxygen/shared/dist/geo.js +314 -0
  27. package/node_modules/@oxygen/shared/dist/linkedin-countries.d.ts +9 -0
  28. package/node_modules/@oxygen/shared/dist/linkedin-countries.js +1 -1
  29. package/node_modules/@oxygen/shared/dist/managed-email-branding.d.ts +15 -0
  30. package/node_modules/@oxygen/shared/dist/managed-email-branding.js +81 -0
  31. package/node_modules/@oxygen/shared/dist/pricing-sheet.d.ts +20 -24
  32. package/node_modules/@oxygen/shared/dist/pricing-sheet.js +15 -16
  33. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.d.ts +3 -3
  34. package/node_modules/@oxygen/shared/dist/pricing-snapshot.generated.js +3 -3
  35. package/node_modules/@oxygen/shared/dist/product-doctrine.js +6 -5
  36. package/node_modules/@oxygen/shared/dist/recipes.d.ts +1 -1
  37. package/node_modules/@oxygen/shared/dist/recipes.js +1 -0
  38. package/node_modules/@oxygen/shared/dist/repricing.d.ts +4 -14
  39. package/node_modules/@oxygen/shared/dist/repricing.js +25 -64
  40. package/node_modules/@oxygen/shared/dist/research-depth.d.ts +11 -0
  41. package/node_modules/@oxygen/shared/dist/research-depth.js +7 -0
  42. package/node_modules/@oxygen/shared/dist/version.d.ts +1 -1
  43. package/node_modules/@oxygen/shared/dist/version.generated.d.ts +1 -1
  44. package/node_modules/@oxygen/shared/dist/version.generated.js +1 -1
  45. package/node_modules/@oxygen/shared/dist/version.js +1 -1
  46. package/node_modules/@oxygen/shared/dist/whatsapp-sender-limits.d.ts +46 -0
  47. package/node_modules/@oxygen/shared/dist/whatsapp-sender-limits.js +51 -1
  48. package/node_modules/@oxygen/shared/package.json +10 -0
  49. package/package.json +1 -1
@@ -0,0 +1,15 @@
1
+ /** Public vocabulary for OXYGEN-managed email services. Backend ids stay in storage. */
2
+ export type ManagedEmailProduct = "warmup" | "placement";
3
+ export declare const OXYGEN_WARMUP_PROVIDER = "oxygen_warmup";
4
+ export declare const OXYGEN_PLACEMENT_PROVIDER = "oxygen_placement";
5
+ export declare function managedEmailProviderInput(value: unknown, product: ManagedEmailProduct): unknown;
6
+ export declare function isManagedWarmupProvider(value: unknown): boolean;
7
+ export declare function isManagedPlacementProvider(value: unknown): boolean;
8
+ export declare function managedEmailMessage(value: string, product?: ManagedEmailProduct): string;
9
+ /**
10
+ * Project only service identifiers and copy. Preserve URLs, ids, hashes, dates,
11
+ * customer-authored subject/body/configuration, and provider evidence verbatim.
12
+ * The caller must choose a managed email surface; do not apply to generic BYOK tools.
13
+ */
14
+ export declare function publicManagedEmail<T>(value: T, product?: ManagedEmailProduct): T;
15
+ export declare function publicManagedEmailCommand<T>(command: string, value: T): T;
@@ -0,0 +1,81 @@
1
+ export const OXYGEN_WARMUP_PROVIDER = "oxygen_warmup";
2
+ export const OXYGEN_PLACEMENT_PROVIDER = "oxygen_placement";
3
+ export function managedEmailProviderInput(value, product) {
4
+ const publicId = product === "warmup" ? OXYGEN_WARMUP_PROVIDER : OXYGEN_PLACEMENT_PROVIDER;
5
+ return typeof value === "string" && value.trim().toLowerCase() === publicId ? "sendkit" : value;
6
+ }
7
+ export function isManagedWarmupProvider(value) {
8
+ return value === "sendkit" || value === OXYGEN_WARMUP_PROVIDER;
9
+ }
10
+ export function isManagedPlacementProvider(value) {
11
+ return value === "sendkit" || value === OXYGEN_PLACEMENT_PROVIDER;
12
+ }
13
+ // These are service-owned fields, never arbitrary customer content or opaque receipts.
14
+ const IDENTIFIER_FIELDS = new Set([
15
+ "provider", "active_provider", "warmup_provider", "warmupProvider", "warmupRail",
16
+ "action", "code", "failure_code", "error_code", "credential_source", "credentialSource",
17
+ "method", "handoff", "reason_code", "kind", "type", "source",
18
+ ]);
19
+ const COPY_FIELDS = new Set([
20
+ "message", "note", "reason", "description", "hint", "transport_hint", "next_step",
21
+ "next_action", "nextAction", "label", "title", "instruction", "instructions", "warnings",
22
+ "recommendation", "recommendations", "limitations", "next_external_write", "price_note",
23
+ "error", "errors", "summary", "blocker", "blockers", "detail", "details_text", "provider_label",
24
+ ]);
25
+ export function managedEmailMessage(value, product = "warmup") {
26
+ const label = product === "warmup" ? "OXYGEN Warm-up" : "OXYGEN placement evaluation";
27
+ if (product === "placement") {
28
+ value = value.replace(/(?:SendKit|OXYGEN placement evaluation) does not document whether inbox, spam, and missing summary values are counts or percentages; Oxygen preserves the values without conversion\./gi, "Summary units are unverified (counts or percentages); values are shown as recorded, without conversion.");
29
+ }
30
+ return value.replace(/SendKit(?:'s)?\s+warm-?up/gi, label).replace(/SendKit/gi, label);
31
+ }
32
+ /**
33
+ * Project only service identifiers and copy. Preserve URLs, ids, hashes, dates,
34
+ * customer-authored subject/body/configuration, and provider evidence verbatim.
35
+ * The caller must choose a managed email surface; do not apply to generic BYOK tools.
36
+ */
37
+ export function publicManagedEmail(value, product = "warmup") {
38
+ const opaqueFields = new Set(["plan_hash", "id", "subject", "body", "body_text", "body_html", "config", "warmupConfig", "rampConfig", "email_address", "emailAddress", "tags", "displayName", "signatureHtml"]);
39
+ function project(entry, field = "", context = product) {
40
+ const publicId = context === "warmup" ? OXYGEN_WARMUP_PROVIDER : OXYGEN_PLACEMENT_PROVIDER;
41
+ if (opaqueFields.has(field))
42
+ return entry;
43
+ if (typeof entry === "string") {
44
+ if (field === "source_id" || field === "sourceId") {
45
+ return entry.replace(/^warmup:sendkit:/, "warmup:oxygen_warmup:");
46
+ }
47
+ if (IDENTIFIER_FIELDS.has(field)) {
48
+ if (entry.toLowerCase() === "sendkit")
49
+ return publicId;
50
+ return entry.replace(/sendkit_/gi, `${publicId}_`).replace(/_sendkit/gi, `_${publicId}`);
51
+ }
52
+ return COPY_FIELDS.has(field) ? managedEmailMessage(entry, context) : entry;
53
+ }
54
+ if (Array.isArray(entry))
55
+ return entry.map((item) => project(item, field, context));
56
+ if (!entry || typeof entry !== "object" || entry instanceof Date)
57
+ return entry;
58
+ const record = entry;
59
+ // Existing customer-owned bindings stay private; never label their usage managed warmup.
60
+ const groupKey = record.key && typeof record.key === "object" && !Array.isArray(record.key)
61
+ ? record.key : null;
62
+ const privateUsage = (record.provider === "sendkit" || groupKey?.provider === "sendkit") &&
63
+ (record.type === "byok_usage" || (typeof record.byok_usage_events === "number" && record.byok_usage_events > 0));
64
+ return Object.fromEntries(Object.entries(record).map(([key, item]) => [
65
+ { sendkit_google: "oxygen_warmup_google", sendkit_microsoft: "oxygen_warmup_microsoft", sendkit_binding: "oxygen_placement_binding", sendkitBinding: "oxygen_placement_binding" }[key] ?? key,
66
+ privateUsage && key === "provider" ? "private_integration"
67
+ : privateUsage && key === "key" ? project({ ...groupKey, provider: "private_integration" }, key, context)
68
+ : privateUsage && key === "tool_id" ? null
69
+ : privateUsage && key === "description" ? "Existing private integration usage."
70
+ : project(item, key, /^warmup/i.test(key) ? "warmup" : /^placement/i.test(key) ? "placement" : context),
71
+ ]));
72
+ }
73
+ return project(value);
74
+ }
75
+ export function publicManagedEmailCommand(command, value) {
76
+ if (/^(mailboxes|managed-inboxes|billing)(?: |$)/.test(command))
77
+ return publicManagedEmail(value);
78
+ if (/^deliverability(?: |$)/.test(command))
79
+ return publicManagedEmail(value, "placement");
80
+ return value;
81
+ }
@@ -137,11 +137,7 @@ export declare const RESEARCH_DEPTH_MODEL_CREDITS: {
137
137
  readonly standard: 4.3;
138
138
  readonly deep: 7.6;
139
139
  };
140
- /** The tier whose model each loop depth runs on, whatever tier the column stores. */
141
- export declare const RESEARCH_DEPTH_MODEL_TIER: {
142
- readonly standard: "low";
143
- readonly deep: "medium";
144
- };
140
+ /** The tier whose model each loop depth runs on lives in ./research-depth.ts: a routing fact, not a price. */
145
141
  /**
146
142
  * The tool half of a standard/deep row. `typical` is the ratified planning shape —
147
143
  * standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
@@ -177,18 +173,18 @@ export declare const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS: {
177
173
  */
178
174
  export { AUTOMATION_STEP_CREDITS_REPRICING } from "./repricing.js";
179
175
  /**
180
- * The flat mailbox line of a managed Google inbox after the 2026-09 repricing
181
- * (400, decision 3.1, slice S32). Its 100-credit mailbox connection, warm-up
182
- * included, bills beside it: 500 all-in. The all-in price waits for the S07
183
- * switch, so a surface that quotes it uses `managedInboxAllInCredits()` from
184
- * `@oxygen/shared/repricing`, resolved on the server. Kept as an object
185
- * (min/typical/max all equal) so callers that destructure any field need no
186
- * shape change.
176
+ * The flat mailbox line of a managed Google or Microsoft 365 inbox: 300 (founder,
177
+ * 2026-10-07; repricing decision 3.1 had set 400 for Google alone). Its 100-credit
178
+ * mailbox connection, warm-up included, bills beside it: 400 all-in, which
179
+ * `managedInboxAllInCredits()` from `@oxygen/shared/repricing` quotes. The price
180
+ * charged is the pricing book's row; this is its committed default. Kept as an
181
+ * object (min/typical/max all equal) so callers that destructure any field need
182
+ * no shape change.
187
183
  */
188
184
  export declare const MANAGED_INBOX_CREDITS_PER_MONTH: {
189
- readonly min: 400;
190
- readonly typical: 400;
191
- readonly max: 400;
185
+ readonly min: 300;
186
+ readonly typical: 300;
187
+ readonly max: 300;
192
188
  };
193
189
  /**
194
190
  * VOICE (the call channel). One price per connected minute, 5 credits ($0.05),
@@ -221,17 +217,17 @@ export declare const SENDING_DOMAIN_CREDITS_PER_YEAR_TYPICAL = 1250;
221
217
  * THE ALLOWANCE IS LOAD-BEARING, not a perk. Placement COGS is per TEST
222
218
  * ($0.1327 on EmailGuard's Agency plan), not per inbox, so an unbounded seat
223
219
  * inverts its own margin: at $1.00/inbox-month the EIGHTH test in a cycle was
224
- * already sold at a loss. Two included tests cost $0.265 against $1.35 of
225
- * revenue at the 2026-09 price, and everything past them bills
220
+ * already sold at a loss. Two included tests cost $0.265 against $1.00 of
221
+ * revenue at today's price, and everything past them bills
226
222
  * PLACEMENT_TEST_OVERAGE_CREDITS. Orgs on their own EmailGuard key (BYOK) pay 0.
227
223
  *
228
- * These two prices are the RATIFIED list prices from the 2026-09 repricing
229
- * (135 and 66, slice S30). The rises wait for the S07 effective-date switch, so
230
- * a surface that quotes or bills uses `deliverabilitySeatCredits()` and
231
- * `placementTestCredits()` from `@oxygen/shared/repricing` (100 and 16.6 until
232
- * the switch's instant), never these constants.
224
+ * Monitoring is 100 credits per inbox-month (founder, 2026-10-07; the 2026-09
225
+ * repricing had set 135). The extra test is the RATIFIED 66 (slice S30), whose rise
226
+ * waits for the S07 effective-date switch, so a surface that quotes or bills uses
227
+ * `deliverabilitySeatCredits()` and `placementTestCredits()` from
228
+ * `@oxygen/shared/repricing` (16.6 for the test until the switch's instant).
233
229
  */
234
- export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 135;
230
+ export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
235
231
  export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
236
232
  export declare const PLACEMENT_TEST_OVERAGE_CREDITS = 66;
237
233
  /**
@@ -262,7 +258,7 @@ export declare const LINKEDIN_TYPICAL_ACTIONS_CREDITS_PER_MONTH = 0;
262
258
  * Seeded at the 2026-09 repricing's price (3,000, decision 2.3); resolve the
263
259
  * price in force with repricedChargeCredits.
264
260
  */
265
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3000;
261
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3400;
266
262
  /**
267
263
  * X accounts: monthly credit reservation per connected account (2026-09
268
264
  * repricing, decision 2.2). Like the LinkedIn and WhatsApp constants above this
@@ -134,8 +134,7 @@ export const AI_COLUMN_WEB_SEARCH_RESERVED_CREDITS = 4.6;
134
134
  * likely under 5x once a loop runs more than two turns.
135
135
  */
136
136
  export const RESEARCH_DEPTH_MODEL_CREDITS = { standard: 4.3, deep: 7.6 };
137
- /** The tier whose model each loop depth runs on, whatever tier the column stores. */
138
- export const RESEARCH_DEPTH_MODEL_TIER = { standard: "low", deep: "medium" };
137
+ /** The tier whose model each loop depth runs on lives in ./research-depth.ts: a routing fact, not a price. */
139
138
  /**
140
139
  * The tool half of a standard/deep row. `typical` is the ratified planning shape —
141
140
  * standard: 2 serper searches + 2 native page reads; deep: 3 serper searches + 4
@@ -161,13 +160,13 @@ export const RESEARCH_DEPTH_TYPICAL_ROW_CREDITS = { quick: 2.1, standard: 5.5, d
161
160
  */
162
161
  export { AUTOMATION_STEP_CREDITS_REPRICING } from "./repricing.js";
163
162
  /**
164
- * The flat mailbox line of a managed Google inbox after the 2026-09 repricing
165
- * (400, decision 3.1, slice S32). Its 100-credit mailbox connection, warm-up
166
- * included, bills beside it: 500 all-in. The all-in price waits for the S07
167
- * switch, so a surface that quotes it uses `managedInboxAllInCredits()` from
168
- * `@oxygen/shared/repricing`, resolved on the server. Kept as an object
169
- * (min/typical/max all equal) so callers that destructure any field need no
170
- * shape change.
163
+ * The flat mailbox line of a managed Google or Microsoft 365 inbox: 300 (founder,
164
+ * 2026-10-07; repricing decision 3.1 had set 400 for Google alone). Its 100-credit
165
+ * mailbox connection, warm-up included, bills beside it: 400 all-in, which
166
+ * `managedInboxAllInCredits()` from `@oxygen/shared/repricing` quotes. The price
167
+ * charged is the pricing book's row; this is its committed default. Kept as an
168
+ * object (min/typical/max all equal) so callers that destructure any field need
169
+ * no shape change.
171
170
  */
172
171
  export const MANAGED_INBOX_CREDITS_PER_MONTH = {
173
172
  min: SNAPSHOT_MANAGED_INBOX_CREDITS_PER_MONTH,
@@ -205,15 +204,15 @@ export const SENDING_DOMAIN_CREDITS_PER_YEAR_TYPICAL = SNAPSHOT_SENDING_DOMAIN_C
205
204
  * THE ALLOWANCE IS LOAD-BEARING, not a perk. Placement COGS is per TEST
206
205
  * ($0.1327 on EmailGuard's Agency plan), not per inbox, so an unbounded seat
207
206
  * inverts its own margin: at $1.00/inbox-month the EIGHTH test in a cycle was
208
- * already sold at a loss. Two included tests cost $0.265 against $1.35 of
209
- * revenue at the 2026-09 price, and everything past them bills
207
+ * already sold at a loss. Two included tests cost $0.265 against $1.00 of
208
+ * revenue at today's price, and everything past them bills
210
209
  * PLACEMENT_TEST_OVERAGE_CREDITS. Orgs on their own EmailGuard key (BYOK) pay 0.
211
210
  *
212
- * These two prices are the RATIFIED list prices from the 2026-09 repricing
213
- * (135 and 66, slice S30). The rises wait for the S07 effective-date switch, so
214
- * a surface that quotes or bills uses `deliverabilitySeatCredits()` and
215
- * `placementTestCredits()` from `@oxygen/shared/repricing` (100 and 16.6 until
216
- * the switch's instant), never these constants.
211
+ * Monitoring is 100 credits per inbox-month (founder, 2026-10-07; the 2026-09
212
+ * repricing had set 135). The extra test is the RATIFIED 66 (slice S30), whose rise
213
+ * waits for the S07 effective-date switch, so a surface that quotes or bills uses
214
+ * `deliverabilitySeatCredits()` and `placementTestCredits()` from
215
+ * `@oxygen/shared/repricing` (16.6 for the test until the switch's instant).
217
216
  */
218
217
  export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = SNAPSHOT_DELIVERABILITY_SEAT_CREDITS_PER_MONTH;
219
218
  export const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = SNAPSHOT_DELIVERABILITY_INCLUDED_TESTS_PER_INBOX;
@@ -15,13 +15,13 @@ export declare const SUBSCRIPTION_USD_PER_100 = 1;
15
15
  /** Applied to actual provider inference cost at settle time. */
16
16
  export declare const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
17
17
  export declare const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3400;
18
- export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3000;
18
+ export declare const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3400;
19
19
  export declare const X_ACCOUNT_CREDITS_PER_MONTH = 1000;
20
20
  export declare const EGRESS_IP_CREDITS_PER_MONTH = 2500;
21
21
  export declare const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
22
- export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 400;
22
+ export declare const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
23
23
  export declare const MAILBOX_WARMUP_CREDITS_PER_MONTH = 0;
24
- export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 135;
24
+ export declare const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
25
25
  /** Included inbox-placement tests per subscribed inbox per cycle. */
26
26
  export declare const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
27
27
  /** A placement test beyond the included allowance. */
@@ -37,13 +37,13 @@ export const COPILOT_CREDIT_MARKUP_MULTIPLIER = 5;
37
37
  // force is lower; a surface that shows or charges one resolves it with
38
38
  // repricedChargeCredits (@oxygen/shared/repricing), never from this literal alone.
39
39
  export const LINKEDIN_ACCOUNT_CREDITS_PER_MONTH = 3_400;
40
- export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3_000;
40
+ export const WHATSAPP_ACCOUNT_CREDITS_PER_MONTH = 3_400;
41
41
  export const X_ACCOUNT_CREDITS_PER_MONTH = 1_000;
42
42
  export const EGRESS_IP_CREDITS_PER_MONTH = 2_500;
43
43
  export const SENDING_MAILBOX_CREDITS_PER_MONTH = 100;
44
- export const MANAGED_INBOX_CREDITS_PER_MONTH = 400;
44
+ export const MANAGED_INBOX_CREDITS_PER_MONTH = 300;
45
45
  export const MAILBOX_WARMUP_CREDITS_PER_MONTH = 0;
46
- export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 135;
46
+ export const DELIVERABILITY_SEAT_CREDITS_PER_MONTH = 100;
47
47
  /** Included inbox-placement tests per subscribed inbox per cycle. */
48
48
  export const DELIVERABILITY_INCLUDED_TESTS_PER_INBOX = 2;
49
49
  /** A placement test beyond the included allowance. */
@@ -49,22 +49,23 @@ function rosterLines(routes) {
49
49
  * a grown or shrunk route array and watching the output follow.
50
50
  */
51
51
  export function renderOxygenProductDoctrine(routes = OXYGEN_PRIMITIVE_ROUTES) {
52
- return `OXYGEN is hosted revenue infrastructure for B2B startups; OXYGEN OS is its five-layer stack. Control surfaces (CLI, MCP, web, desktop, Copilot) call one contract, own no state; External is the platforms OXYGEN acts on. Between them, the ${routes.length} primitives, each owning its facts:
52
+ return `OXYGEN is hosted revenue infrastructure for B2B startups; OXYGEN OS has five layers. Control (CLI, MCP, web, desktop, Copilot) calls one contract, owns no state; External holds integrations. Between them, the ${routes.length} primitives, each owns its facts:
53
53
 
54
54
  ${rosterLines(routes)}
55
55
 
56
- Use native primitives so state, approvals, costs, provenance, and runs stay hosted and inspectable; never rebuild one with scripts, cron, files, or a second engine.
56
+ Use native primitives: state, approvals, costs, provenance and runs stay inspectable; never rebuild one with scripts, cron, files, or a second engine.
57
57
 
58
58
  Ownership law — one owner per fact, no primitive re-implements another:
59
59
 
60
+ - Geo owns AI-search prompts, answers, citations and experiments; staff/dev pilot only.
60
61
  - Records hold canonical truth; Tables hold disposable work promoted onto Records — a row is a candidate, not canon. Tables own typed rows, formulas, AI and tool columns, waterfalls, cell state, and provenance; simple row dependencies stay chained Table columns, not Workflows.
61
62
  - Interaction state, not recipient count, owns LinkedIn routing: net-new outreach is Sequences even for one recipient and one step; a reply in an existing thread or one direct email is Messages, holding conversation content, stored once. Cadence, enrollment, sender rotation, suppression, and reply-stop are Sequences.
62
- - Signals hold durable typed events and record only that something happened; acting on one is Workflows or Sequences; an inbound reply is both, a reaction only a Signal.
63
+ - Signals hold durable typed events; they record what happened, and acting on one is Workflows or Sequences; an inbound reply is both, a reaction only a Signal.
63
64
  - Deterministic scheduled, cron, webhook, event, branching, waiting, retrying, or approval-gated orchestration belongs to hosted OXYGEN Workflows: schema → lint → apply → call, and local files are authoring inputs only. Adaptive goals, persistent threads, and checkpoints belong to governed Agents, owning first-class runs and calling Workflows as child actions; neither compiles into the other nor is a store — a draft is Messages, a note Records activity, and Workflow outreach enrolls into an active, bounded Sequence and never sends raw provider messages.
64
65
  - Posts hold broadcast artifacts and engagement telemetry; Publishing owns approval-gated scheduling, dispatch, retries, and provenance; Ads owns competitor ad intelligence; Tags are the cross-primitive label vocabulary; Dashboards curates native reporting; Observability is the read lens over runs, costs, and failures, never a second engine.
65
- - The Knowledge Graph describes kinds of customer (ICP, personas, offers, rubrics, voice); Records holds the companies and people they describe. Durable knowledge belongs there, not chat memory: read pages, cite their slugs, search before minting a near-duplicate, file durable findings back. Canonical voice and positioning stay proposal-gated. Pinned canonical context is auto-applied to AI copy; if reported missing, say so rather than write off-voice. Recipes package motions that read it, advisory only.
66
+ - Knowledge Graph describes customer kinds (ICP, personas, offers, rubrics, voice); Records holds the companies and people they describe. Store durable knowledge there, not chat memory: read pages, cite their slugs, search before minting a near-duplicate, file durable findings back. Canonical voice and positioning stay proposal-gated. Pinned canonical context is auto-applied to AI copy; if reported missing, say so rather than write off-voice. Recipes package motions that read it, advisory only.
66
67
 
67
- Paid provider work and external writes require a preview on a small sample, exact scope, approval, and a hard credit or action ceiling. Never infer spend authority from tool authority. Surface deep-links, costs, failures, retries, and approval needs, not a bare success; name missing context, never guess.`;
68
+ Paid provider work and external writes require a preview on a small sample, exact scope, approval, and a hard credit or action ceiling. Never infer spend authority from tool authority. Show deep-links, costs, failures, retries and approval needs; name missing context, never guess.`;
68
69
  }
69
70
  /** The rendered doctrine for the shipped primitive roster. */
70
71
  export const OXYGEN_PRODUCT_DOCTRINE = renderOxygenProductDoctrine();
@@ -9,7 +9,7 @@ export declare const RECIPE_STATUSES: readonly ["draft", "beta", "stable", "depr
9
9
  export type RecipeStatus = typeof RECIPE_STATUSES[number];
10
10
  export declare const RECIPE_BENCHMARK_BASES: readonly ["estimate", "observed"];
11
11
  export type RecipeBenchmarkBasis = typeof RECIPE_BENCHMARK_BASES[number];
12
- export declare const RECIPE_PRIMITIVES: readonly ["knowledge-graph", "recipes", "records", "tables", "messages", "posts", "signals", "dashboards", "ads", "tags", "sequences", "publishing", "workflows", "agents", "observability"];
12
+ export declare const RECIPE_PRIMITIVES: readonly ["knowledge-graph", "recipes", "records", "tables", "messages", "posts", "signals", "dashboards", "geo", "ads", "tags", "sequences", "publishing", "workflows", "agents", "observability"];
13
13
  export type RecipePrimitive = typeof RECIPE_PRIMITIVES[number];
14
14
  export declare const RECIPE_PREREQUISITE_KINDS: readonly ["sender", "mailbox", "domain", "integration", "knowledge", "asset", "plan", "data"];
15
15
  export type RecipePrerequisiteKind = typeof RECIPE_PREREQUISITE_KINDS[number];
@@ -49,6 +49,7 @@ export const RECIPE_PRIMITIVES = [
49
49
  "posts",
50
50
  "signals",
51
51
  "dashboards",
52
+ "geo",
52
53
  "ads",
53
54
  "tags",
54
55
  "sequences",
@@ -118,28 +118,18 @@ export declare const AUTOMATION_STEP_CREDITS_REPRICING: RepricedValue<0.001 | 0.
118
118
  * approved ceiling, so it starts with the price and not before.
119
119
  */
120
120
  export declare const AUTOMATION_STEPS_COUNT_TOWARD_RUN_CAP_REPRICING: RepricedValue<boolean>;
121
- /**
122
- * S30 (decision 3.5): EmailGuard monitoring per subscribed inbox, including the
123
- * cycle's placement-test allowance, 100 -> 135 credits a month. Existing
124
- * subscriptions pay the price in force at each renewal.
125
- */
126
- export declare const DELIVERABILITY_SEAT_REPRICING: RepricedValue<100 | 135>;
121
+ /** EmailGuard monitoring per subscribed inbox-month, in credits, including its placement tests. */
122
+ export declare function deliverabilitySeatCredits(): number;
127
123
  /**
128
124
  * S30 (decision 3.6; flat literal, proposal P-29): one managed placement test
129
125
  * past an inbox's included allowance, or on an inbox with no monitoring
130
126
  * subscription, 16.6 -> 66 credits. Tests on your own EmailGuard key stay 0.
131
127
  */
132
128
  export declare const PLACEMENT_TEST_REPRICING: RepricedValue<16.6 | 66>;
133
- /** EmailGuard monitoring per subscribed inbox-month, in credits, at the price in force. */
134
- export declare function deliverabilitySeatCredits(options?: RepricingOptions): number;
135
129
  /** One managed placement test beyond the included allowance, in credits, at the price in force. */
136
130
  export declare function placementTestCredits(options?: RepricingOptions): number;
137
- /** The flat monthly mailbox line of a managed Google inbox (the pricing seed's `commitment.managed_mailbox`). */
138
- export declare const MANAGED_MAILBOX_REPRICING: RepricedValue<300 | 400>;
139
- /** What a managed Google inbox costs a month, all-in: mailbox, connection and warm-up. */
140
- export declare const MANAGED_INBOX_ALL_IN_REPRICING: RepricedValue<number>;
141
- /** A managed Google inbox's monthly credits, all-in, at the switch state (marketing and docs). */
142
- export declare function managedInboxAllInCredits(options?: RepricingOptions): number;
131
+ /** A managed inbox's committed monthly credits, all-in: the flat mailbox line plus its connection. */
132
+ export declare function managedInboxAllInCredits(): number;
143
133
  /**
144
134
  * S41 (decision 6.3): a provider call made with the customer's own API key
145
135
  * (BYOK) pays a 0.05-credit platform fee, up from nothing. The vendor still
@@ -240,7 +240,8 @@ export const S20_RESERVATION_PRICE_RISES = [
240
240
  unit: "credits_per_number_per_month",
241
241
  description: "Monthly credit reservation for a connected WhatsApp number.",
242
242
  before: 1_000,
243
- after: 3_000,
243
+ // Decision 2.3 set 3,000; the founder made it 3,400, a LinkedIn account's price (2026-10-07).
244
+ after: 3_400,
244
245
  }),
245
246
  defineRepricedValue({
246
247
  key: "seat.phone_number",
@@ -286,25 +287,16 @@ export const AUTOMATION_STEPS_COUNT_TOWARD_RUN_CAP_REPRICING = defineRepricedVal
286
287
  before: false,
287
288
  after: true,
288
289
  });
289
- // ---- S30 (decisions 3.5 and 3.6): EmailGuard back on the 5x markup. -------
290
- // Both keys are the pricing-seed charge keys, so the seed row and the snapshot
291
- // carry the new price, `after` reads it from the snapshot (one definition), and
292
- // `repricedChargeCredits` / `repricedValue` hold the old price until the instant.
293
- /**
294
- * S30 (decision 3.5): EmailGuard monitoring per subscribed inbox, including the
295
- * cycle's placement-test allowance, 100 -> 135 credits a month. Existing
296
- * subscriptions pay the price in force at each renewal.
297
- */
298
- export const DELIVERABILITY_SEAT_REPRICING = defineRepricedValue({
299
- key: "commitment.deliverability_unit",
300
- kind: "price",
301
- slice: "S30",
302
- decision: "3.5",
303
- unit: "credits_per_inbox_per_month",
304
- description: "EmailGuard monitoring per subscribed inbox, including its included placement tests each cycle.",
305
- before: 100,
306
- after: SNAPSHOT_DELIVERABILITY_SEAT_CREDITS,
307
- });
290
+ // ---- S30 (decision 3.6): the extra placement test on the 5x markup. -------
291
+ // The key is the pricing-seed charge key, so the seed row and the snapshot carry
292
+ // the new price, `after` reads it from the snapshot (one definition), and
293
+ // `repricedValue` holds the old price until the instant. EmailGuard monitoring
294
+ // itself rose 100 -> 135 here (decision 3.5) until the founder set it back to a
295
+ // round 100 on 2026-10-07, so nothing about it moves at the switch any more.
296
+ /** EmailGuard monitoring per subscribed inbox-month, in credits, including its placement tests. */
297
+ export function deliverabilitySeatCredits() {
298
+ return SNAPSHOT_DELIVERABILITY_SEAT_CREDITS;
299
+ }
308
300
  /**
309
301
  * S30 (decision 3.6; flat literal, proposal P-29): one managed placement test
310
302
  * past an inbox's included allowance, or on an inbox with no monitoring
@@ -320,51 +312,23 @@ export const PLACEMENT_TEST_REPRICING = defineRepricedValue({
320
312
  before: 16.6,
321
313
  after: SNAPSHOT_PLACEMENT_TEST_CREDITS,
322
314
  });
323
- /** EmailGuard monitoring per subscribed inbox-month, in credits, at the price in force. */
324
- export function deliverabilitySeatCredits(options = {}) {
325
- return repricedValue(DELIVERABILITY_SEAT_REPRICING, options);
326
- }
327
315
  /** One managed placement test beyond the included allowance, in credits, at the price in force. */
328
316
  export function placementTestCredits(options = {}) {
329
317
  return repricedValue(PLACEMENT_TEST_REPRICING, options);
330
318
  }
331
- // ---- S32 (decision 3.1): a managed Google inbox at 500 credits all-in. ----
332
- // Until the instant, a managed mailbox is priced at the inbox vendor's cost x 1.2
333
- // (300 credits for Google at $2.50) and its warm-up add-on bills 100 on top. From
334
- // it, a Google mailbox is a flat 400 plus the 100-credit mailbox connection every
335
- // sending mailbox holds, 500 in total, with warm-up included in the connection.
336
- // Microsoft and Azure keep their cost-derived mailbox or tenant price (proposals
337
- // P-25, P-26) and gain the same included warm-up and connection.
338
- //
339
- // The switch alone does not move it. `isManagedInboxAllInPriceActive`
340
- // (@oxygen/integrations) also requires credit commitments to bill
341
- // `sending_mailbox` and `managed_mailbox` (the S26 arming): otherwise the order
342
- // would drop to 400 while nobody collects the connection it includes.
343
- /** The flat monthly mailbox line of a managed Google inbox (the pricing seed's `commitment.managed_mailbox`). */
344
- export const MANAGED_MAILBOX_REPRICING = defineRepricedValue({
345
- key: "commitment.managed_mailbox",
346
- kind: "price",
347
- slice: "S32",
348
- decision: "3.1",
349
- unit: "credits_per_inbox_per_month",
350
- description: "The mailbox line of a managed Google inbox, a flat price. Its 100-credit mailbox connection, with warm-up included, is billed beside it.",
351
- before: 300,
352
- after: SNAPSHOT_MANAGED_MAILBOX_CREDITS,
353
- });
354
- /** What a managed Google inbox costs a month, all-in: mailbox, connection and warm-up. */
355
- export const MANAGED_INBOX_ALL_IN_REPRICING = defineRepricedValue({
356
- key: "managed_inbox.google_all_in_credits",
357
- kind: "price",
358
- slice: "S32",
359
- decision: "3.1",
360
- unit: "credits_per_inbox_per_month",
361
- description: "A managed Google inbox, all-in: the mailbox plus its mailbox connection, warm-up included. Inbox placement is an optional add-on.",
362
- before: 400,
363
- after: SNAPSHOT_MANAGED_MAILBOX_CREDITS + SNAPSHOT_SENDING_MAILBOX_CREDITS,
364
- });
365
- /** A managed Google inbox's monthly credits, all-in, at the switch state (marketing and docs). */
366
- export function managedInboxAllInCredits(options = {}) {
367
- return repricedValue(MANAGED_INBOX_ALL_IN_REPRICING, options);
319
+ // ---- S32: a managed inbox, all-in. --------------------------------------
320
+ // Once the all-in price applies (`isManagedInboxAllInPriceActive` in
321
+ // @oxygen/integrations: the 2026-09 switch AND credit commitments billing
322
+ // `sending_mailbox` and `managed_mailbox`), a Google or Microsoft 365 mailbox sells
323
+ // at the pricing book's flat `commitment.managed_mailbox` line and an Azure tenant at
324
+ // its flat `commitment.managed_azure_tenant` (founder, 2026-10-07: one inbox price,
325
+ // a round tenant price). Each inbox also holds the 100-credit mailbox connection,
326
+ // warm-up included. Before it, a mailbox was priced from vendor cost and warm-up
327
+ // billed beside it: 300 + 100 for Google at the $2.50 contracted cost, the same 400
328
+ // a month, so nothing about the all-in total moves at the switch.
329
+ /** A managed inbox's committed monthly credits, all-in: the flat mailbox line plus its connection. */
330
+ export function managedInboxAllInCredits() {
331
+ return SNAPSHOT_MANAGED_MAILBOX_CREDITS + SNAPSHOT_SENDING_MAILBOX_CREDITS;
368
332
  }
369
333
  /**
370
334
  * S41 (decision 6.3): a provider call made with the customer's own API key
@@ -611,10 +575,7 @@ export const REPRICING_2026_09_SCHEDULE = [
611
575
  TOPUP_RATE_REPRICING,
612
576
  ...storageCutEntries(),
613
577
  ...S20_RESERVATION_PRICE_RISES,
614
- DELIVERABILITY_SEAT_REPRICING,
615
578
  PLACEMENT_TEST_REPRICING,
616
- MANAGED_MAILBOX_REPRICING,
617
- MANAGED_INBOX_ALL_IN_REPRICING,
618
579
  EMAIL_MAILBOX_DAILY_CAP_MAXIMUM,
619
580
  EMAIL_MAILBOX_OLD_DEFAULT_DAILY_CAP,
620
581
  AUTOMATION_STEP_CREDITS_REPRICING,
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The model tier each AI-column research-loop depth runs on, whatever tier the
3
+ * column stores. A routing fact, not a price: the credits a depth costs come from
4
+ * the pricing book (OXP-1.22.25 retires the committed price sheet), so this lives
5
+ * apart from every price.
6
+ */
7
+ export declare const RESEARCH_DEPTH_MODEL_TIER: {
8
+ readonly standard: "low";
9
+ readonly deep: "medium";
10
+ };
11
+ export type ResearchLoopDepth = keyof typeof RESEARCH_DEPTH_MODEL_TIER;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The model tier each AI-column research-loop depth runs on, whatever tier the
3
+ * column stores. A routing fact, not a price: the credits a depth costs come from
4
+ * the pricing book (OXP-1.22.25 retires the committed price sheet), so this lives
5
+ * apart from every price.
6
+ */
7
+ export const RESEARCH_DEPTH_MODEL_TIER = { standard: "low", deep: "medium" };
@@ -1,2 +1,2 @@
1
1
  export declare const OXYGEN_VERSION: string;
2
- export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.917.5";
2
+ export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.922.14";
@@ -1 +1 @@
1
- export declare const OXYGEN_BUILD_VERSION = "1.1011.1091";
1
+ export declare const OXYGEN_BUILD_VERSION = "1.1012.2";
@@ -1,2 +1,2 @@
1
1
  // GENERATED by scripts/ci/version-stamp.mjs from VERSION + git history. Do not edit; do not commit.
2
- export const OXYGEN_BUILD_VERSION = "1.1011.1091";
2
+ export const OXYGEN_BUILD_VERSION = "1.1012.2";
@@ -49,4 +49,4 @@ export const OXYGEN_VERSION = OXYGEN_BUILD_VERSION;
49
49
  // Since 2026-09-28 the release-preparation step advances this literal to the
50
50
  // highest CLI version published on npm for at least 30 days. It never lowers
51
51
  // the floor. The source change lands on dev before the next production release.
52
- export const OXYGEN_MINIMUM_CLI_VERSION = "1.917.5";
52
+ export const OXYGEN_MINIMUM_CLI_VERSION = "1.922.14";
@@ -30,6 +30,52 @@ export declare const WHATSAPP_SENDER_LIMIT_MAXIMUMS: {
30
30
  readonly min_action_spacing_seconds: 3600;
31
31
  readonly action_spacing_jitter_seconds: 1800;
32
32
  };
33
+ /** OXYGEN policy, not a provider-published guarantee of account safety. */
34
+ export declare const WHATSAPP_WARMUP_RAMP: ReadonlyArray<{
35
+ throughDay: number;
36
+ cap: number;
37
+ }>;
38
+ export declare const WHATSAPP_WARMUP_FULL_CAP: 40;
39
+ export declare const WHATSAPP_CONNECTION_COOLDOWN_MS: number;
40
+ export declare const WHATSAPP_WARMUP_DAY_BASIS: "elapsed_24_hour_periods";
41
+ export declare function whatsAppRampCapForDay(day: number): number;
42
+ export declare function whatsAppWarmupDay(anchor: Date | null, now?: Date): number;
43
+ /** Poll timestamps never advance this clock; legacy mirrors retain their creation time. */
44
+ export declare function whatsAppConnectionCooldown(sender: {
45
+ metadata?: Record<string, unknown> | null;
46
+ createdAt?: Date | string | null;
47
+ }, now?: Date): {
48
+ session_connected_at: string | null;
49
+ outreach_resume_at: string | null;
50
+ blocked: boolean;
51
+ };
52
+ /** Stored reads expose the same elapsed-day policy that dispatch enforces. */
53
+ export declare function whatsAppWarmupStatus(sender: {
54
+ warmupStartedAt: Date | null;
55
+ limitOverrides?: Partial<Record<WhatsAppSenderLimitKey, unknown>> | null;
56
+ metadata?: Record<string, unknown> | null;
57
+ createdAt?: Date | string | null;
58
+ }, now?: Date): {
59
+ session_connected_at: string | null;
60
+ outreach_resume_at: string | null;
61
+ blocked: boolean;
62
+ warmup_started_at: string | null;
63
+ warmup_day: number;
64
+ day_basis: "elapsed_24_hour_periods";
65
+ ramp_cap_today: number;
66
+ configured_daily_cap: number;
67
+ effective_daily_cap: number;
68
+ ramp: ({
69
+ from_day: number;
70
+ through_day: number;
71
+ messages_per_day: number;
72
+ } | {
73
+ from_day: number;
74
+ through_day: null;
75
+ messages_per_day: number;
76
+ })[];
77
+ connection_cooldown_hours: number;
78
+ };
33
79
  /** What each WhatsApp limit counts, for MCP and CLI help. */
34
80
  export declare const WHATSAPP_SENDER_LIMIT_NOTES: Record<WhatsAppSenderLimitKey, string>;
35
81
  /**