@motebit/protocol 1.2.0 → 2.0.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.
Files changed (60) hide show
  1. package/README.md +4 -2
  2. package/dist/artifact-type.d.ts +144 -0
  3. package/dist/artifact-type.d.ts.map +1 -0
  4. package/dist/artifact-type.js +107 -0
  5. package/dist/artifact-type.js.map +1 -0
  6. package/dist/audience.d.ts +108 -0
  7. package/dist/audience.d.ts.map +1 -0
  8. package/dist/audience.js +104 -0
  9. package/dist/audience.js.map +1 -0
  10. package/dist/co-browse.d.ts +369 -0
  11. package/dist/co-browse.d.ts.map +1 -0
  12. package/dist/co-browse.js +64 -0
  13. package/dist/co-browse.js.map +1 -0
  14. package/dist/computer-use.d.ts +463 -3
  15. package/dist/computer-use.d.ts.map +1 -1
  16. package/dist/computer-use.js +40 -0
  17. package/dist/computer-use.js.map +1 -1
  18. package/dist/event-type.d.ts +62 -0
  19. package/dist/event-type.d.ts.map +1 -0
  20. package/dist/event-type.js +123 -0
  21. package/dist/event-type.js.map +1 -0
  22. package/dist/index.d.ts +257 -20
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +84 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/memory-events.d.ts +13 -0
  27. package/dist/memory-events.d.ts.map +1 -1
  28. package/dist/money.d.ts +33 -0
  29. package/dist/money.d.ts.map +1 -0
  30. package/dist/money.js +41 -0
  31. package/dist/money.js.map +1 -0
  32. package/dist/perception.d.ts +347 -0
  33. package/dist/perception.d.ts.map +1 -0
  34. package/dist/perception.js +9 -0
  35. package/dist/perception.js.map +1 -0
  36. package/dist/retention-policy.d.ts +8 -1
  37. package/dist/retention-policy.d.ts.map +1 -1
  38. package/dist/retention-policy.js +18 -0
  39. package/dist/retention-policy.js.map +1 -1
  40. package/dist/routing.d.ts +266 -0
  41. package/dist/routing.d.ts.map +1 -0
  42. package/dist/routing.js +88 -0
  43. package/dist/routing.js.map +1 -0
  44. package/dist/sensitivity.d.ts +123 -0
  45. package/dist/sensitivity.d.ts.map +1 -0
  46. package/dist/sensitivity.js +154 -0
  47. package/dist/sensitivity.js.map +1 -0
  48. package/dist/settlement-asset.d.ts +92 -0
  49. package/dist/settlement-asset.d.ts.map +1 -0
  50. package/dist/settlement-asset.js +82 -0
  51. package/dist/settlement-asset.js.map +1 -0
  52. package/dist/settlement-mode.d.ts +144 -13
  53. package/dist/settlement-mode.d.ts.map +1 -1
  54. package/dist/settlement-mode.js +45 -1
  55. package/dist/settlement-mode.js.map +1 -1
  56. package/dist/transparency.d.ts +116 -0
  57. package/dist/transparency.d.ts.map +1 -0
  58. package/dist/transparency.js +67 -0
  59. package/dist/transparency.js.map +1 -0
  60. package/package.json +1 -1
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Routing primitive — closed-registry types for the auto-router.
3
+ *
4
+ * The auto-router is the model-selection counterpart to the chrome
5
+ * matrix: `f(TaskShape × ProviderCapability × Constraints) →
6
+ * RoutingDecision`. This module defines the wire-shape types; the
7
+ * judgment-layer dispatcher (`dispatchRouting`) lives in BSL
8
+ * `@motebit/policy/src/auto-router.ts`. Consumers (motebit-cloud
9
+ * proxy, BYOK web layer, on-device runtime) call the dispatcher
10
+ * with their own provider catalogs.
11
+ *
12
+ * **Closed registry shape** — same closure pattern as `SuiteId`,
13
+ * `TokenAudience`, `ToolMode`, `ContentArtifactType`. The `TaskShape`
14
+ * literal union is the wire law; named constants are developer
15
+ * ergonomics; `ALL_TASK_SHAPES` is the canonical iteration order.
16
+ * Adding a task shape is intentional protocol-level work: a new
17
+ * entry here, a new arm in `REFERENCE_ROUTING_POLICY`, drift-gate
18
+ * coverage on every consumer.
19
+ *
20
+ * **TaskShape agility — the 7th instance of agility-as-role.**
21
+ * Per [`docs/doctrine/agility-as-role.md`], `TaskShape` is the
22
+ * closed registry (the role); the routing-policy itself is a
23
+ * consumer-side function (`Record<TaskShape, string>` today,
24
+ * potentially a learned function in the future) that branches on
25
+ * it. Distinguishing role (registry-shape) from policy
26
+ * (function-shape) avoids the conflation the codebase corrected
27
+ * for `Provider → InferenceHost`.
28
+ *
29
+ * **Lifted from `services/proxy/src/validation.ts`** (commit
30
+ * 95e3b7af's intelligence-source-agility refactor anticipated this
31
+ * landing site — the three unions `InferenceHost`, `ModelLab`,
32
+ * `Jurisdiction` were always destined for the protocol layer once
33
+ * a second consumer arrived):
34
+ * - `InferenceHost` — where the HTTP request actually goes.
35
+ * - `ModelLab` — who trained the weights.
36
+ * - `Jurisdiction` — legal locus of the host.
37
+ *
38
+ * Permissive floor, type-only, zero runtime deps. The dispatcher's
39
+ * judgment lives in `@motebit/policy`; this file stays pure types
40
+ * + closed-registry constants.
41
+ */
42
+ import type { SensitivityLevel } from "./index.js";
43
+ /**
44
+ * Where the HTTP request actually goes. The processor that receives
45
+ * the prompt bytes. Anthropic/OpenAI/Google appear here because they
46
+ * run their own hosted inference; Groq appears here because they
47
+ * host other labs' open-source weights on LPU hardware. `local-server`
48
+ * is the on-device case: the request goes to the user's own
49
+ * inference server (Ollama, LM Studio, llama.cpp, Jan, vLLM,
50
+ * text-generation-webui — all expose `/v1/chat/completions` via
51
+ * the OpenAI-compat shim), so the "host" is the user's own
52
+ * machine. Mirrors the `OnDeviceBackend` value of the same name
53
+ * in `@motebit/sdk`.
54
+ *
55
+ * The proxy NEVER routes to `local-server` — it's the on-device
56
+ * consumer's host. The proxy's exhaustive switches throw
57
+ * defensively when they encounter this value, naming the
58
+ * structural violation rather than silently degrading. Doctrine:
59
+ * `docs/doctrine/auto-routing-as-protocol-primitive.md` § "PR 3 —
60
+ * on-device consumer".
61
+ *
62
+ * Closed registry — adding a host is a protocol-level append +
63
+ * `MOTEBIT_CLOUD_ALLOWED_JURISDICTIONS` admission decision +
64
+ * downstream consumer updates.
65
+ */
66
+ export type InferenceHost = "anthropic" | "openai" | "google" | "groq" | "local-server";
67
+ /**
68
+ * Who trained the weights. Anthropic/OpenAI/Google appear here
69
+ * because they trained Claude/GPT/Gemini respectively; Meta appears
70
+ * here because Llama 3.3 70B is Meta's model (Groq just hosts it).
71
+ * OpenAI appears in BOTH this union AND `InferenceHost` (host =
72
+ * "openai" for gpt-5.4 at api.openai.com; lab = "openai" for
73
+ * gpt-oss-120b released as open weights and hosted by Groq). That's
74
+ * structurally correct — same entity can serve different roles.
75
+ *
76
+ * Mistral / Microsoft / Alibaba added 2026-05-14 alongside the PR 3
77
+ * on-device consumer landing: Mistral AI trains Mistral models,
78
+ * Microsoft trains Phi, Alibaba trains Qwen. All three appear as
79
+ * `lab` in the `ON_DEVICE_MODEL_CATALOG` (`@motebit/policy/on-device-router.ts`)
80
+ * since the canonical local-server suggested-models list
81
+ * (`@motebit/sdk::LOCAL_SERVER_SUGGESTED_MODELS`) includes Mistral,
82
+ * Phi-3, and Qwen2 alongside the existing Meta/Google entries. The
83
+ * proxy never sees these labs (it doesn't host their models); the
84
+ * registry expansion is purely consumer-side (the on-device
85
+ * dispatcher's catalog), which is why the registry's stated semantic
86
+ * "who trained the weights" generalizes cleanly without protocol-
87
+ * layer churn.
88
+ *
89
+ * Closed registry — adding a lab requires a model entry citing it.
90
+ */
91
+ export type ModelLab = "anthropic" | "openai" | "google" | "meta" | "mistral" | "microsoft" | "alibaba";
92
+ /**
93
+ * Legal locus of the host. Reflective of physical/legal reality,
94
+ * not pluggable. Drives the motebit-cloud admission predicate
95
+ * (`MOTEBIT_CLOUD_ALLOWED_JURISDICTIONS` in
96
+ * `services/proxy/src/validation.ts`). You can't swap a host's
97
+ * jurisdiction; the registry reflects legal reality.
98
+ *
99
+ * NOT an agility-as-role instance — it's a typed admission
100
+ * predicate, not a swappable role. Per
101
+ * [`docs/doctrine/agility-as-role.md`], jurisdiction lifts the
102
+ * previously-tribal "DeepSeek-is-BYOK-only-because-Chinese-hosted"
103
+ * decision into structural enforcement.
104
+ */
105
+ export type Jurisdiction = "US" | "CN" | "EU";
106
+ /**
107
+ * The closed set of task categories the auto-router branches on.
108
+ * Each task shape maps to a preferred model via
109
+ * `REFERENCE_ROUTING_POLICY` (in `@motebit/policy`); consumers
110
+ * (motebit-cloud / BYOK / on-device) override the policy as
111
+ * needed but the shape registry is interop law.
112
+ *
113
+ * Lifted verbatim from `services/proxy/src/validation.ts`'s
114
+ * `TASK_MODEL_MAP` keys (the seven task types the proxy's
115
+ * classifyTask-based router already produces in production).
116
+ *
117
+ * Adding a shape (e.g., `"voice-conversation"`, `"image-generation"`)
118
+ * is intentional protocol-level work: new entry here + new arm in
119
+ * `REFERENCE_ROUTING_POLICY` + drift-gate-induced coverage in
120
+ * every CONSUMER (motebit-cloud proxy + BYOK + on-device). The
121
+ * TaskShape registry is what's role-shaped; the routing-policy
122
+ * itself is a consumer-side function, not a role.
123
+ */
124
+ export type TaskShape = "quick" | "chat" | "reasoning" | "code" | "research" | "creative" | "math";
125
+ /** Fast / low-latency tasks (tool-heavy, short responses, sub-second feel). */
126
+ export declare const QUICK_TASK_SHAPE: TaskShape;
127
+ /** Conversational back-and-forth — the default. */
128
+ export declare const CHAT_TASK_SHAPE: TaskShape;
129
+ /** Deep reasoning — chain-of-thought, multi-step inference. */
130
+ export declare const REASONING_TASK_SHAPE: TaskShape;
131
+ /** Code-related — completion, review, debugging. */
132
+ export declare const CODE_TASK_SHAPE: TaskShape;
133
+ /** Research / long-context — synthesis across many sources. */
134
+ export declare const RESEARCH_TASK_SHAPE: TaskShape;
135
+ /** Creative writing — open-ended generation, voice, prose. */
136
+ export declare const CREATIVE_TASK_SHAPE: TaskShape;
137
+ /** Math / scientific — symbolic reasoning, calculation, proofs. */
138
+ export declare const MATH_TASK_SHAPE: TaskShape;
139
+ /**
140
+ * Canonical iteration order, frozen. Consumers that need to
141
+ * enumerate (drift gates, REFERENCE_ROUTING_POLICY validation,
142
+ * docs) use this so TypeScript sees the narrow union rather than
143
+ * `string[]`.
144
+ */
145
+ export declare const ALL_TASK_SHAPES: readonly TaskShape[];
146
+ /**
147
+ * Type guard — narrows `unknown` to `TaskShape`. Drift-gate-driven
148
+ * literal scanners use this to validate shapes; consumers that
149
+ * detect task shape from user intent (LLM classification,
150
+ * heuristics) call this before dispatching so an unchecked cast
151
+ * is a fail-open path the type system can't catch.
152
+ */
153
+ export declare function isTaskShape(value: unknown): value is TaskShape;
154
+ /**
155
+ * A model's capability profile — what the dispatcher needs to know
156
+ * to pick it. Lifted from `services/proxy/src/validation.ts`'s
157
+ * `ModelEntry` interface; the proxy now declares its
158
+ * `MODEL_CONFIG` entries satisfying `ProviderCapability[]`.
159
+ *
160
+ * Cost units: USD per million tokens. Same precision the proxy's
161
+ * `calculateCostMicro` consumes (input vs output billed
162
+ * separately).
163
+ */
164
+ export interface ProviderCapability {
165
+ /** Canonical model identifier — opaque to the dispatcher except as a return value. */
166
+ readonly modelName: string;
167
+ /** Where requests route. */
168
+ readonly host: InferenceHost;
169
+ /** Who trained the weights. */
170
+ readonly lab: ModelLab;
171
+ /** Legal locus of the host. */
172
+ readonly jurisdiction: Jurisdiction;
173
+ /** Input price (USD per million tokens). */
174
+ readonly inputCostPerMillion: number;
175
+ /** Output price (USD per million tokens). */
176
+ readonly outputCostPerMillion: number;
177
+ /**
178
+ * Maximum prompt+completion tokens the model will accept in a single
179
+ * call. Optional + additive per
180
+ * [`docs/doctrine/intelligence-pluggability-contract.md`](../../../docs/doctrine/intelligence-pluggability-contract.md) —
181
+ * consumers performing pre-flight admission (system-prompt + tools +
182
+ * rendered state + user message + output reserve ≤ window) read this
183
+ * to decide whether to deny honestly before invoking the model.
184
+ * Auto-routing dispatch does not consume this field today; admission
185
+ * is a sibling deny semantic to auto-router deny ("I can't pick"
186
+ * vs "the picked model can't carry").
187
+ */
188
+ readonly contextWindowTokens?: number;
189
+ }
190
+ /**
191
+ * Consumer-neutral constraints the dispatcher honors. **No
192
+ * motebit-cloud-specific fields** — balance-based filtering lives
193
+ * in `@motebit/policy::applyBalanceFilter` (a higher-order wrapper
194
+ * the proxy uses); BYOK and on-device consumers don't have balance
195
+ * and shouldn't see it in the protocol-layer constraint type.
196
+ *
197
+ * All fields optional — an empty constraint means "any
198
+ * jurisdiction, any cost, any capability." The dispatcher returns
199
+ * `{ kind: "deny", reason }` when constraints make every catalog
200
+ * entry ineligible.
201
+ */
202
+ export interface RoutingConstraint {
203
+ /**
204
+ * Restrict to this jurisdiction. Useful for compliance-bound
205
+ * tasks ("US-only routing") and the motebit-cloud admission
206
+ * predicate. Omit for "any jurisdiction the catalog offers."
207
+ */
208
+ readonly jurisdiction?: Jurisdiction;
209
+ /**
210
+ * Maximum acceptable input cost in USD per million tokens.
211
+ * Filters the catalog before policy lookup. Useful for
212
+ * cost-aware routing (operator-side budget caps,
213
+ * consumer-side cheap-tier preferences).
214
+ */
215
+ readonly maxInputCostPerMillion?: number;
216
+ /** Maximum acceptable output cost in USD per million tokens. */
217
+ readonly maxOutputCostPerMillion?: number;
218
+ /**
219
+ * Task requires tool-calling capability. When true, providers
220
+ * known not to support tools are excluded. Today the dispatcher
221
+ * treats all entries as tool-capable; this field is shipped for
222
+ * future capability-aware filtering when a provider that lacks
223
+ * tool support lands.
224
+ */
225
+ readonly requiresToolUse?: boolean;
226
+ /**
227
+ * Maximum acceptable sensitivity tier the routing target can
228
+ * handle. Sensitivity-elevated tasks (medical / financial /
229
+ * secret) MUST stay on sovereign or on-device routes — the
230
+ * dispatcher's caller is responsible for pre-filtering the
231
+ * catalog accordingly; this field documents the contract.
232
+ */
233
+ readonly sensitivityCeiling?: SensitivityLevel;
234
+ }
235
+ /**
236
+ * The dispatcher's typed output. Discriminated union — consumers
237
+ * pattern-match on `kind`:
238
+ *
239
+ * - `route`: a single provider was chosen. The caller invokes
240
+ * it directly.
241
+ * - `fallback`: a primary was preferred but cost / constraint
242
+ * forced a backup. The caller invokes `backup`; the `primary`
243
+ * and `reason` fields are observability surfaces (audit logs,
244
+ * chrome narration in PR 4+).
245
+ * - `deny`: no catalog entry satisfies the constraints. The
246
+ * caller is responsible for surfacing the denial (HTTP 4xx,
247
+ * UI message, etc.).
248
+ *
249
+ * Every variant carries `reason` for observability — the
250
+ * dispatcher's choice should always be human-legible, even when
251
+ * the choice is "I couldn't pick anything."
252
+ */
253
+ export type RoutingDecision = {
254
+ readonly kind: "route";
255
+ readonly model: string;
256
+ readonly reason: string;
257
+ } | {
258
+ readonly kind: "fallback";
259
+ readonly primary: string;
260
+ readonly backup: string;
261
+ readonly reason: string;
262
+ } | {
263
+ readonly kind: "deny";
264
+ readonly reason: string;
265
+ };
266
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Routing primitive — closed-registry types for the auto-router.
3
+ *
4
+ * The auto-router is the model-selection counterpart to the chrome
5
+ * matrix: `f(TaskShape × ProviderCapability × Constraints) →
6
+ * RoutingDecision`. This module defines the wire-shape types; the
7
+ * judgment-layer dispatcher (`dispatchRouting`) lives in BSL
8
+ * `@motebit/policy/src/auto-router.ts`. Consumers (motebit-cloud
9
+ * proxy, BYOK web layer, on-device runtime) call the dispatcher
10
+ * with their own provider catalogs.
11
+ *
12
+ * **Closed registry shape** — same closure pattern as `SuiteId`,
13
+ * `TokenAudience`, `ToolMode`, `ContentArtifactType`. The `TaskShape`
14
+ * literal union is the wire law; named constants are developer
15
+ * ergonomics; `ALL_TASK_SHAPES` is the canonical iteration order.
16
+ * Adding a task shape is intentional protocol-level work: a new
17
+ * entry here, a new arm in `REFERENCE_ROUTING_POLICY`, drift-gate
18
+ * coverage on every consumer.
19
+ *
20
+ * **TaskShape agility — the 7th instance of agility-as-role.**
21
+ * Per [`docs/doctrine/agility-as-role.md`], `TaskShape` is the
22
+ * closed registry (the role); the routing-policy itself is a
23
+ * consumer-side function (`Record<TaskShape, string>` today,
24
+ * potentially a learned function in the future) that branches on
25
+ * it. Distinguishing role (registry-shape) from policy
26
+ * (function-shape) avoids the conflation the codebase corrected
27
+ * for `Provider → InferenceHost`.
28
+ *
29
+ * **Lifted from `services/proxy/src/validation.ts`** (commit
30
+ * 95e3b7af's intelligence-source-agility refactor anticipated this
31
+ * landing site — the three unions `InferenceHost`, `ModelLab`,
32
+ * `Jurisdiction` were always destined for the protocol layer once
33
+ * a second consumer arrived):
34
+ * - `InferenceHost` — where the HTTP request actually goes.
35
+ * - `ModelLab` — who trained the weights.
36
+ * - `Jurisdiction` — legal locus of the host.
37
+ *
38
+ * Permissive floor, type-only, zero runtime deps. The dispatcher's
39
+ * judgment lives in `@motebit/policy`; this file stays pure types
40
+ * + closed-registry constants.
41
+ */
42
+ // === Named constants — same value, narrower type ============================
43
+ //
44
+ // Callers that import these get `TaskShape` typing without the union
45
+ // being inferred at every site. Two ergonomic shapes: pass a constant
46
+ // (`QUICK_TASK_SHAPE`) for documentation + grep affordance, or inline
47
+ // the literal — the union narrowing catches typos in either case.
48
+ /** Fast / low-latency tasks (tool-heavy, short responses, sub-second feel). */
49
+ export const QUICK_TASK_SHAPE = "quick";
50
+ /** Conversational back-and-forth — the default. */
51
+ export const CHAT_TASK_SHAPE = "chat";
52
+ /** Deep reasoning — chain-of-thought, multi-step inference. */
53
+ export const REASONING_TASK_SHAPE = "reasoning";
54
+ /** Code-related — completion, review, debugging. */
55
+ export const CODE_TASK_SHAPE = "code";
56
+ /** Research / long-context — synthesis across many sources. */
57
+ export const RESEARCH_TASK_SHAPE = "research";
58
+ /** Creative writing — open-ended generation, voice, prose. */
59
+ export const CREATIVE_TASK_SHAPE = "creative";
60
+ /** Math / scientific — symbolic reasoning, calculation, proofs. */
61
+ export const MATH_TASK_SHAPE = "math";
62
+ // === Iteration + type guard =================================================
63
+ /**
64
+ * Canonical iteration order, frozen. Consumers that need to
65
+ * enumerate (drift gates, REFERENCE_ROUTING_POLICY validation,
66
+ * docs) use this so TypeScript sees the narrow union rather than
67
+ * `string[]`.
68
+ */
69
+ export const ALL_TASK_SHAPES = Object.freeze([
70
+ "quick",
71
+ "chat",
72
+ "reasoning",
73
+ "code",
74
+ "research",
75
+ "creative",
76
+ "math",
77
+ ]);
78
+ /**
79
+ * Type guard — narrows `unknown` to `TaskShape`. Drift-gate-driven
80
+ * literal scanners use this to validate shapes; consumers that
81
+ * detect task shape from user intent (LLM classification,
82
+ * heuristics) call this before dispatching so an unchecked cast
83
+ * is a fail-open path the type system can't catch.
84
+ */
85
+ export function isTaskShape(value) {
86
+ return typeof value === "string" && ALL_TASK_SHAPES.includes(value);
87
+ }
88
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../src/routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAqGH,+EAA+E;AAC/E,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,sEAAsE;AACtE,kEAAkE;AAElE,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAc,OAAO,CAAC;AAEnD,mDAAmD;AACnD,MAAM,CAAC,MAAM,eAAe,GAAc,MAAM,CAAC;AAEjD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAc,WAAW,CAAC;AAE3D,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAc,MAAM,CAAC;AAEjD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAc,UAAU,CAAC;AAEzD,8DAA8D;AAC9D,MAAM,CAAC,MAAM,mBAAmB,GAAc,UAAU,CAAC;AAEzD,mEAAmE;AACnE,MAAM,CAAC,MAAM,eAAe,GAAc,MAAM,CAAC;AAEjD,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAyB,MAAM,CAAC,MAAM,CAAC;IACjE,OAAO;IACP,MAAM;IACN,WAAW;IACX,MAAM;IACN,UAAU;IACV,UAAU;IACV,MAAM;CACP,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,eAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC7F,CAAC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Sensitivity ladder algebra — pure math over the closed
3
+ * `SensitivityLevel` enum.
4
+ *
5
+ * The ladder is interop law. Every motebit implementation must agree
6
+ * on which tier dominates which, or the cross-implementation gate
7
+ * isn't interoperable: device A persisting a turn at "secret" must
8
+ * mean the same thing to device B's session-tier filter.
9
+ *
10
+ * Pure deterministic math over a closed enum — qualifies as a
11
+ * permissive-floor primitive per `packages/protocol/CLAUDE.md` rule 1
12
+ * ("deterministic math (semiring algebra, canonical JSON, hash
13
+ * primitives)"). The functions don't decide policy; they compose
14
+ * ordered values. Policy thresholds (e.g. "medical+ requires
15
+ * sovereign provider") live at the call site so call sites express
16
+ * intent at the right level.
17
+ *
18
+ * Graduation history: `rankSensitivity` had three local definitions
19
+ * by 2026-05-07 (runtime/motebit-runtime.ts, runtime/conversation.ts,
20
+ * ai-core/loop.ts) plus a fourth-shaped table (`LEVEL_RANK` +
21
+ * `higherLevel` in policy-invariants/computer-sensitivity.ts). The
22
+ * ai-core copy's JSDoc explicitly named graduation as the trigger:
23
+ * "if a third reader appears, the helper graduates." Past trigger.
24
+ *
25
+ * Naming distinction:
26
+ * - `rankSensitivity` — load-bearing primitive; ordinal int over the
27
+ * closed union. Comparable, hashable, monotonic.
28
+ * - `maxSensitivity` — typed wrapper for the join-semilattice
29
+ * composition (`max(a, b)`). Identity element is `None`. Used at
30
+ * every egress write boundary that floors message tier at
31
+ * `max(default, effective)`.
32
+ * - `sensitivityPermits` — typed wrapper for the read-side filter
33
+ * (`candidate <= upper`). Used at every egress READ boundary that
34
+ * excludes content tagged above the current effective tier.
35
+ *
36
+ * Not a semiring. There's only one operation (max-monoid / join-
37
+ * semilattice). Calling it a semiring would be a category error.
38
+ */
39
+ import type { SensitivityLevel } from "./index.js";
40
+ /**
41
+ * Ordinal rank for a `SensitivityLevel`. Returns 0 (`None`) through
42
+ * 4 (`Secret`) — see `SENSITIVITY_RANK` above. Use this as the
43
+ * comparison primitive; prefer `maxSensitivity` / `sensitivityPermits`
44
+ * at call sites that compose or filter.
45
+ */
46
+ export declare function rankSensitivity(level: SensitivityLevel): number;
47
+ /**
48
+ * Compose two sensitivity tiers: returns whichever has the higher
49
+ * rank. The join-semilattice composition that the egress-write floor
50
+ * arc depends on at every boundary (session × slab, default ×
51
+ * effective, persisted-tier × runtime-tier). Identity is `None`.
52
+ *
53
+ * Property: `maxSensitivity(a, None) === a` for all `a`.
54
+ */
55
+ export declare function maxSensitivity(a: SensitivityLevel, b: SensitivityLevel): SensitivityLevel;
56
+ /**
57
+ * Does the upper tier permit content tagged at `candidate`? Returns
58
+ * `true` iff `candidate <= upper` in the ladder. Used at every
59
+ * egress READ boundary (trimmed conversation history, memory-
60
+ * candidate filter at AI-context construction, future cross-device-
61
+ * sync filters).
62
+ *
63
+ * The dual of `maxSensitivity`: write-side floor stamps with
64
+ * `maxSensitivity`, read-side filter excludes via
65
+ * `!sensitivityPermits`. Both routes derive from the same single
66
+ * source of truth (`SENSITIVITY_RANK`), so a tier insertion remains
67
+ * a one-file change at the protocol layer.
68
+ *
69
+ * Property: `sensitivityPermits(upper, None) === true` for all
70
+ * `upper` (None content is admissible at every tier).
71
+ */
72
+ export declare function sensitivityPermits(upper: SensitivityLevel, candidate: SensitivityLevel): boolean;
73
+ /**
74
+ * Canonical iteration order over `SensitivityLevel`, frozen. The
75
+ * single source of truth for "every level" — drift gates,
76
+ * consumer-coverage scans, exhaustive switches, and the protocol's
77
+ * registry-coverage gate (`check-sensitivity-canonical`) all
78
+ * enumerate through this array.
79
+ *
80
+ * Ordered low → high to mirror `SENSITIVITY_RANK`: a consumer
81
+ * iterating in declaration order sees the ladder in the same order
82
+ * the algebra ranks it. Same shape as `ALL_SUITE_IDS`,
83
+ * `ALL_TOKEN_AUDIENCES`, `ALL_CONTENT_ARTIFACT_TYPES`,
84
+ * `ALL_TASK_SHAPES`. Adding a level is intentional protocol-level
85
+ * work: new enum member + new entry here + new entry in
86
+ * `SENSITIVITY_RANK` + drift-gate update.
87
+ *
88
+ * Values are the enum's string literals (not enum members) to avoid
89
+ * the init-order cycle the file's `import type` already documents.
90
+ */
91
+ export declare const ALL_SENSITIVITY_LEVELS: readonly SensitivityLevel[];
92
+ /**
93
+ * Type guard — narrows `unknown` to `SensitivityLevel`. Drift-gate-
94
+ * driven literal scanners use this to validate values pulled from
95
+ * wire-format payloads; consumers that derive sensitivity from
96
+ * user input call this before dispatching so an unchecked cast is
97
+ * a fail-open path the type system can't catch.
98
+ *
99
+ * Same shape as `isSuiteId`, `isTokenAudience`,
100
+ * `isContentArtifactType`, `isTaskShape`.
101
+ */
102
+ export declare function isSensitivityLevel(value: unknown): value is SensitivityLevel;
103
+ declare const __sensitivityCleared: unique symbol;
104
+ /**
105
+ * Precondition brand: `T` carrying the type-level proof that
106
+ * `assertSensitivityPermitsAiCall()` fired before the value left
107
+ * the gate.
108
+ *
109
+ * Produced only inside the runtime's gate method (the single
110
+ * authorized `as SensitivityCleared<T>` cast). Required as the
111
+ * deps parameter on `runTurn` / `runTurnStreaming`. Propagates
112
+ * through every indirect AI-egress path (`StreamingManager` resume,
113
+ * `PlanEngine` per-step) so the brand is the type-level proof a
114
+ * sensitivity check happened at the right moment.
115
+ *
116
+ * Doctrine: `docs/doctrine/security-boundaries.md` (privacy gate),
117
+ * CLAUDE.md ("Medical/financial/secret never reach external AI").
118
+ */
119
+ export type SensitivityCleared<T> = T & {
120
+ readonly [__sensitivityCleared]: true;
121
+ };
122
+ export {};
123
+ //# sourceMappingURL=sensitivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitivity.d.ts","sourceRoot":"","sources":["../src/sensitivity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAsBnD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAE/D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,CAEzF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAEhG;AAsBD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,gBAAgB,EAMtC,CAAC;AAEzB;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AA4BD,OAAO,CAAC,MAAM,oBAAoB,EAAE,OAAO,MAAM,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,oBAAoB,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Sensitivity ladder algebra — pure math over the closed
3
+ * `SensitivityLevel` enum.
4
+ *
5
+ * The ladder is interop law. Every motebit implementation must agree
6
+ * on which tier dominates which, or the cross-implementation gate
7
+ * isn't interoperable: device A persisting a turn at "secret" must
8
+ * mean the same thing to device B's session-tier filter.
9
+ *
10
+ * Pure deterministic math over a closed enum — qualifies as a
11
+ * permissive-floor primitive per `packages/protocol/CLAUDE.md` rule 1
12
+ * ("deterministic math (semiring algebra, canonical JSON, hash
13
+ * primitives)"). The functions don't decide policy; they compose
14
+ * ordered values. Policy thresholds (e.g. "medical+ requires
15
+ * sovereign provider") live at the call site so call sites express
16
+ * intent at the right level.
17
+ *
18
+ * Graduation history: `rankSensitivity` had three local definitions
19
+ * by 2026-05-07 (runtime/motebit-runtime.ts, runtime/conversation.ts,
20
+ * ai-core/loop.ts) plus a fourth-shaped table (`LEVEL_RANK` +
21
+ * `higherLevel` in policy-invariants/computer-sensitivity.ts). The
22
+ * ai-core copy's JSDoc explicitly named graduation as the trigger:
23
+ * "if a third reader appears, the helper graduates." Past trigger.
24
+ *
25
+ * Naming distinction:
26
+ * - `rankSensitivity` — load-bearing primitive; ordinal int over the
27
+ * closed union. Comparable, hashable, monotonic.
28
+ * - `maxSensitivity` — typed wrapper for the join-semilattice
29
+ * composition (`max(a, b)`). Identity element is `None`. Used at
30
+ * every egress write boundary that floors message tier at
31
+ * `max(default, effective)`.
32
+ * - `sensitivityPermits` — typed wrapper for the read-side filter
33
+ * (`candidate <= upper`). Used at every egress READ boundary that
34
+ * excludes content tagged above the current effective tier.
35
+ *
36
+ * Not a semiring. There's only one operation (max-monoid / join-
37
+ * semilattice). Calling it a semiring would be a category error.
38
+ */
39
+ /**
40
+ * Ordinal rank for `SensitivityLevel`: `none(0) < personal(1) <
41
+ * medical(2) < financial(3) < secret(4)`. The single source of truth
42
+ * for the ladder ordering — every consumer must derive comparison
43
+ * decisions from this rank, not from local enum-equality chains
44
+ * (`x === Medical || x === Financial || x === Secret`), so a future
45
+ * tier insertion remains a one-file change at the protocol layer.
46
+ *
47
+ * Keys are the enum's string values (not enum members) to avoid the
48
+ * init-order cycle described above. The `Record<SensitivityLevel,
49
+ * number>` type still binds the keys to the enum at the type layer.
50
+ */
51
+ const SENSITIVITY_RANK = Object.freeze({
52
+ none: 0,
53
+ personal: 1,
54
+ medical: 2,
55
+ financial: 3,
56
+ secret: 4,
57
+ });
58
+ /**
59
+ * Ordinal rank for a `SensitivityLevel`. Returns 0 (`None`) through
60
+ * 4 (`Secret`) — see `SENSITIVITY_RANK` above. Use this as the
61
+ * comparison primitive; prefer `maxSensitivity` / `sensitivityPermits`
62
+ * at call sites that compose or filter.
63
+ */
64
+ export function rankSensitivity(level) {
65
+ return SENSITIVITY_RANK[level];
66
+ }
67
+ /**
68
+ * Compose two sensitivity tiers: returns whichever has the higher
69
+ * rank. The join-semilattice composition that the egress-write floor
70
+ * arc depends on at every boundary (session × slab, default ×
71
+ * effective, persisted-tier × runtime-tier). Identity is `None`.
72
+ *
73
+ * Property: `maxSensitivity(a, None) === a` for all `a`.
74
+ */
75
+ export function maxSensitivity(a, b) {
76
+ return rankSensitivity(a) >= rankSensitivity(b) ? a : b;
77
+ }
78
+ /**
79
+ * Does the upper tier permit content tagged at `candidate`? Returns
80
+ * `true` iff `candidate <= upper` in the ladder. Used at every
81
+ * egress READ boundary (trimmed conversation history, memory-
82
+ * candidate filter at AI-context construction, future cross-device-
83
+ * sync filters).
84
+ *
85
+ * The dual of `maxSensitivity`: write-side floor stamps with
86
+ * `maxSensitivity`, read-side filter excludes via
87
+ * `!sensitivityPermits`. Both routes derive from the same single
88
+ * source of truth (`SENSITIVITY_RANK`), so a tier insertion remains
89
+ * a one-file change at the protocol layer.
90
+ *
91
+ * Property: `sensitivityPermits(upper, None) === true` for all
92
+ * `upper` (None content is admissible at every tier).
93
+ */
94
+ export function sensitivityPermits(upper, candidate) {
95
+ return rankSensitivity(candidate) <= rankSensitivity(upper);
96
+ }
97
+ // ── Canonical registry tooling ─────────────────────────────────────
98
+ //
99
+ // Closed-registry / structural-lock shape. Same five artifacts as
100
+ // `SuiteId` (`crypto-suite.ts`), `TokenAudience` (`audience.ts`),
101
+ // `ContentArtifactType` (`artifact-type.ts`), `TaskShape`
102
+ // (`routing.ts`):
103
+ //
104
+ // 1. closed type (the `SensitivityLevel` enum in `index.ts`)
105
+ // 2. canonical ordering (`SENSITIVITY_RANK` above)
106
+ // 3. frozen iteration array (`ALL_SENSITIVITY_LEVELS` below)
107
+ // 4. type guard (`isSensitivityLevel` below)
108
+ // 5. drift gate (`check-sensitivity-canonical` per `scripts/`)
109
+ //
110
+ // Pre-this-block, `SensitivityLevel` was the only top-tier closed
111
+ // registry without the iteration + guard pair — the gap surfaced in
112
+ // the registry-gate-family audit on 2026-05-14 (post panels-registry
113
+ // arc). The enum is preserved for back-compat with the ~900
114
+ // pre-existing literal sites; this block adds the missing canonical
115
+ // tooling next to it without converting the enum.
116
+ /**
117
+ * Canonical iteration order over `SensitivityLevel`, frozen. The
118
+ * single source of truth for "every level" — drift gates,
119
+ * consumer-coverage scans, exhaustive switches, and the protocol's
120
+ * registry-coverage gate (`check-sensitivity-canonical`) all
121
+ * enumerate through this array.
122
+ *
123
+ * Ordered low → high to mirror `SENSITIVITY_RANK`: a consumer
124
+ * iterating in declaration order sees the ladder in the same order
125
+ * the algebra ranks it. Same shape as `ALL_SUITE_IDS`,
126
+ * `ALL_TOKEN_AUDIENCES`, `ALL_CONTENT_ARTIFACT_TYPES`,
127
+ * `ALL_TASK_SHAPES`. Adding a level is intentional protocol-level
128
+ * work: new enum member + new entry here + new entry in
129
+ * `SENSITIVITY_RANK` + drift-gate update.
130
+ *
131
+ * Values are the enum's string literals (not enum members) to avoid
132
+ * the init-order cycle the file's `import type` already documents.
133
+ */
134
+ export const ALL_SENSITIVITY_LEVELS = Object.freeze([
135
+ "none",
136
+ "personal",
137
+ "medical",
138
+ "financial",
139
+ "secret",
140
+ ]);
141
+ /**
142
+ * Type guard — narrows `unknown` to `SensitivityLevel`. Drift-gate-
143
+ * driven literal scanners use this to validate values pulled from
144
+ * wire-format payloads; consumers that derive sensitivity from
145
+ * user input call this before dispatching so an unchecked cast is
146
+ * a fail-open path the type system can't catch.
147
+ *
148
+ * Same shape as `isSuiteId`, `isTokenAudience`,
149
+ * `isContentArtifactType`, `isTaskShape`.
150
+ */
151
+ export function isSensitivityLevel(value) {
152
+ return typeof value === "string" && ALL_SENSITIVITY_LEVELS.includes(value);
153
+ }
154
+ //# sourceMappingURL=sensitivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitivity.js","sourceRoot":"","sources":["../src/sensitivity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AASH;;;;;;;;;;;GAWG;AACH,MAAM,gBAAgB,GAA+C,MAAM,CAAC,MAAM,CAAC;IACjF,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;IACX,OAAO,EAAE,CAAC;IACV,SAAS,EAAE,CAAC;IACZ,MAAM,EAAE,CAAC;CACV,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAuB;IACrD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,CAAmB,EAAE,CAAmB;IACrE,OAAO,eAAe,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAuB,EAAE,SAA2B;IACrF,OAAO,eAAe,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,sEAAsE;AACtE,EAAE;AACF,kEAAkE;AAClE,kEAAkE;AAClE,0DAA0D;AAC1D,kBAAkB;AAClB,EAAE;AACF,+DAA+D;AAC/D,qDAAqD;AACrD,+DAA+D;AAC/D,+CAA+C;AAC/C,iEAAiE;AACjE,EAAE;AACF,kEAAkE;AAClE,oEAAoE;AACpE,qEAAqE;AACrE,4DAA4D;AAC5D,oEAAoE;AACpE,kDAAkD;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgC,MAAM,CAAC,MAAM,CAAC;IAC/E,MAAM;IACN,UAAU;IACV,SAAS;IACT,WAAW;IACX,QAAQ;CACa,CAAC,CAAC;AAEzB;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,sBAA4C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpG,CAAC"}