@neuroverseos/governance 0.3.4 → 0.4.1

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 (129) hide show
  1. package/README.md +280 -405
  2. package/dist/adapters/autoresearch.cjs +63 -9
  3. package/dist/adapters/autoresearch.d.cts +2 -1
  4. package/dist/adapters/autoresearch.d.ts +2 -1
  5. package/dist/adapters/autoresearch.js +3 -3
  6. package/dist/adapters/deep-agents.cjs +63 -9
  7. package/dist/adapters/deep-agents.d.cts +3 -2
  8. package/dist/adapters/deep-agents.d.ts +3 -2
  9. package/dist/adapters/deep-agents.js +3 -3
  10. package/dist/adapters/express.cjs +63 -9
  11. package/dist/adapters/express.d.cts +2 -1
  12. package/dist/adapters/express.d.ts +2 -1
  13. package/dist/adapters/express.js +3 -3
  14. package/dist/adapters/index.cjs +961 -9
  15. package/dist/adapters/index.d.cts +4 -2
  16. package/dist/adapters/index.d.ts +4 -2
  17. package/dist/adapters/index.js +54 -17
  18. package/dist/adapters/langchain.cjs +63 -9
  19. package/dist/adapters/langchain.d.cts +3 -2
  20. package/dist/adapters/langchain.d.ts +3 -2
  21. package/dist/adapters/langchain.js +3 -3
  22. package/dist/adapters/mentraos.cjs +2181 -0
  23. package/dist/adapters/mentraos.d.cts +319 -0
  24. package/dist/adapters/mentraos.d.ts +319 -0
  25. package/dist/adapters/mentraos.js +48 -0
  26. package/dist/adapters/openai.cjs +63 -9
  27. package/dist/adapters/openai.d.cts +3 -2
  28. package/dist/adapters/openai.d.ts +3 -2
  29. package/dist/adapters/openai.js +3 -3
  30. package/dist/adapters/openclaw.cjs +63 -9
  31. package/dist/adapters/openclaw.d.cts +3 -2
  32. package/dist/adapters/openclaw.d.ts +3 -2
  33. package/dist/adapters/openclaw.js +3 -3
  34. package/dist/{add-ROOZLU62.js → add-XSANI3FK.js} +1 -1
  35. package/dist/{behavioral-MJO34S6Q.js → behavioral-SLW7ALEK.js} +4 -4
  36. package/dist/{bootstrap-CQRZVOXK.js → bootstrap-2OW5ZLBL.js} +4 -4
  37. package/dist/bootstrap-contract-DcV6t-8M.d.cts +216 -0
  38. package/dist/bootstrap-contract-DcV6t-8M.d.ts +216 -0
  39. package/dist/browser.global.js +149 -5
  40. package/dist/{build-ZHPMX5AZ.js → build-EGBGZFIJ.js} +6 -6
  41. package/dist/{chunk-A7GKPPU7.js → chunk-2VAWP6FI.js} +1 -1
  42. package/dist/{chunk-3WQLXYTP.js → chunk-3AYKQHYI.js} +2 -2
  43. package/dist/{chunk-EMQDLDAF.js → chunk-3NZMMSOW.js} +80 -2
  44. package/dist/chunk-3S5AD4AB.js +421 -0
  45. package/dist/{chunk-VXHSMA3I.js → chunk-6CV4XG3J.js} +1 -1
  46. package/dist/{chunk-BNKJPUPQ.js → chunk-A7SHG75T.js} +2 -2
  47. package/dist/{chunk-U6U7EJZL.js → chunk-AV7XJJWK.js} +2 -2
  48. package/dist/{chunk-ZWI3NIXK.js → chunk-CYDMUJVZ.js} +54 -3
  49. package/dist/{chunk-F66BVUYB.js → chunk-DA5MHFRR.js} +3 -3
  50. package/dist/{chunk-YEKMVDWK.js → chunk-FHXXD2TI.js} +7 -7
  51. package/dist/{chunk-5TPFNWRU.js → chunk-FS2UUJJO.js} +3 -3
  52. package/dist/{chunk-4FLICVVA.js → chunk-FVOGUCB6.js} +2 -2
  53. package/dist/chunk-GTPV2XGO.js +893 -0
  54. package/dist/{chunk-CTZHONLA.js → chunk-I4RTIMLX.js} +2 -2
  55. package/dist/{chunk-B6OXJLJ5.js → chunk-J2IZBHXJ.js} +4 -4
  56. package/dist/{chunk-TG6SEF24.js → chunk-OQU65525.js} +1 -1
  57. package/dist/{chunk-QXBFT7NI.js → chunk-QMVQ6KPL.js} +2 -2
  58. package/dist/{chunk-G7DJ6VOD.js → chunk-RDA7ISWC.js} +2 -2
  59. package/dist/{chunk-O5ABKEA7.js → chunk-YJ34R5NB.js} +2 -2
  60. package/dist/{chunk-PVTQQS3Y.js → chunk-YPCVY4GS.js} +31 -0
  61. package/dist/{chunk-W7LLXRGY.js → chunk-ZAF6JH23.js} +65 -10
  62. package/dist/{chunk-IS4WUH6Y.js → chunk-ZEIT2QLM.js} +4 -4
  63. package/dist/cli/neuroverse.cjs +4436 -1035
  64. package/dist/cli/neuroverse.js +40 -24
  65. package/dist/cli/plan.cjs +176 -12
  66. package/dist/cli/plan.js +2 -2
  67. package/dist/cli/run.cjs +63 -9
  68. package/dist/cli/run.js +2 -2
  69. package/dist/configure-world-XU2COHOZ.js +705 -0
  70. package/dist/{decision-flow-M63D47LO.js → decision-flow-3K4D72G4.js} +2 -2
  71. package/dist/{demo-G43RLCPK.js → demo-6OQYWRR6.js} +4 -4
  72. package/dist/{derive-LMDUTXDD.js → derive-7Y7YWVLU.js} +5 -5
  73. package/dist/{doctor-6BC6X2VO.js → doctor-NHXI7OQW.js} +3 -1
  74. package/dist/engine/bootstrap-emitter.cjs +241 -0
  75. package/dist/engine/bootstrap-emitter.d.cts +27 -0
  76. package/dist/engine/bootstrap-emitter.d.ts +27 -0
  77. package/dist/{bootstrap-emitter-Q7UIJZ2O.js → engine/bootstrap-emitter.js} +2 -2
  78. package/dist/engine/bootstrap-parser.cjs +560 -0
  79. package/dist/engine/bootstrap-parser.d.cts +96 -0
  80. package/dist/engine/bootstrap-parser.d.ts +96 -0
  81. package/dist/{bootstrap-parser-EEF36XDU.js → engine/bootstrap-parser.js} +2 -2
  82. package/dist/engine/guard-engine.cjs +1116 -0
  83. package/dist/engine/guard-engine.d.cts +60 -0
  84. package/dist/engine/guard-engine.d.ts +60 -0
  85. package/dist/engine/guard-engine.js +12 -0
  86. package/dist/engine/simulate-engine.cjs +390 -0
  87. package/dist/engine/simulate-engine.d.cts +105 -0
  88. package/dist/engine/simulate-engine.d.ts +105 -0
  89. package/dist/engine/simulate-engine.js +9 -0
  90. package/dist/{equity-penalties-SG5IZQ7I.js → equity-penalties-NVBAB5WL.js} +4 -4
  91. package/dist/{explain-RHBU2GBR.js → explain-HDFN4ION.js} +1 -1
  92. package/dist/github-TIKTWOGU.js +27 -0
  93. package/dist/{guard-AEEJNWLD.js → guard-6KSCWT2W.js} +4 -4
  94. package/dist/{guard-contract-B7lplwm9.d.cts → guard-contract-C991HDZp.d.cts} +32 -309
  95. package/dist/{guard-contract-B7lplwm9.d.ts → guard-contract-hHjTTjtR.d.ts} +32 -309
  96. package/dist/{impact-3XVDSCBU.js → impact-WIAM66IH.js} +3 -3
  97. package/dist/{improve-TQP4ECSY.js → improve-2PWGGO5B.js} +3 -3
  98. package/dist/index.cjs +682 -14
  99. package/dist/index.d.cts +231 -423
  100. package/dist/index.d.ts +231 -423
  101. package/dist/index.js +81 -58
  102. package/dist/{init-FYPV4SST.js → init-TKIJDR7I.js} +5 -1
  103. package/dist/lens-MHMUDCMQ.js +1084 -0
  104. package/dist/{mcp-server-5Y3ZM7TV.js → mcp-server-TNIWZ7B5.js} +3 -3
  105. package/dist/{playground-VZBNPPBO.js → playground-3FLDGBET.js} +3 -3
  106. package/dist/{redteam-MZPZD3EF.js → redteam-HV6LMKEH.js} +3 -3
  107. package/dist/{session-JYOARW54.js → session-XZP2754M.js} +3 -3
  108. package/dist/{shared-C_zpdvBm.d.cts → shared-DGnn1jiS.d.cts} +1 -1
  109. package/dist/{shared-Cf7yxx4-.d.ts → shared-U405h52W.d.ts} +1 -1
  110. package/dist/{simulate-LJXYBC6M.js → simulate-VT437EEL.js} +17 -4
  111. package/dist/spatial/index.cjs +682 -0
  112. package/dist/spatial/index.d.cts +517 -0
  113. package/dist/spatial/index.d.ts +517 -0
  114. package/dist/spatial/index.js +633 -0
  115. package/dist/{test-BOOR4A5F.js → test-4WTX6RKQ.js} +3 -3
  116. package/dist/{trace-PKV4KX56.js → trace-2YDNAXMK.js} +2 -2
  117. package/dist/types.cjs +18 -0
  118. package/dist/types.d.cts +370 -0
  119. package/dist/types.d.ts +370 -0
  120. package/dist/types.js +0 -0
  121. package/dist/{validate-RALX7CZS.js → validate-M52DX22Y.js} +1 -1
  122. package/dist/{world-BIP4GZBZ.js → world-O4HTQPDP.js} +1 -1
  123. package/dist/{world-loader-Y6HMQH2D.js → world-loader-YTYFOP7D.js} +1 -1
  124. package/dist/worlds/mentraos-smartglasses.nv-world.md +423 -0
  125. package/dist/worlds/mentraos-spatial.nv-world.md +68 -0
  126. package/dist/worlds/user-rules.nv-world.md +328 -0
  127. package/package.json +46 -3
  128. package/dist/guard-engine-PNR6MHCM.js +0 -10
  129. package/dist/{configure-ai-5MP5DWTT.js → configure-ai-LL3VAPQW.js} +3 -3
@@ -0,0 +1,2181 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/adapters/mentraos.ts
31
+ var mentraos_exports = {};
32
+ __export(mentraos_exports, {
33
+ DEFAULT_USER_RULES: () => DEFAULT_USER_RULES,
34
+ GovernanceBlockedError: () => GovernanceBlockedError,
35
+ MENTRA_INTENT_MAP: () => MENTRA_INTENT_MAP,
36
+ MENTRA_INTENT_TAXONOMY: () => MENTRA_INTENT_TAXONOMY,
37
+ MENTRA_KNOWN_INTENTS: () => MENTRA_KNOWN_INTENTS,
38
+ MentraGovernedExecutor: () => MentraGovernedExecutor,
39
+ createMentraGovernedExecutor: () => createMentraGovernedExecutor,
40
+ createMentraGovernedExecutorFromWorld: () => createMentraGovernedExecutorFromWorld,
41
+ evaluateUserRules: () => evaluateUserRules,
42
+ getAIActionIntents: () => getAIActionIntents,
43
+ getAIDataIntents: () => getAIDataIntents,
44
+ getAIIntents: () => getAIIntents,
45
+ getExfiltrationIntents: () => getExfiltrationIntents,
46
+ getHighRiskIntents: () => getHighRiskIntents,
47
+ getIntentsByGlasses: () => getIntentsByGlasses,
48
+ getIntentsByPermission: () => getIntentsByPermission,
49
+ getMentraIntent: () => getMentraIntent,
50
+ isAIIntent: () => isAIIntent,
51
+ isIntentSupported: () => isIntentSupported
52
+ });
53
+ module.exports = __toCommonJS(mentraos_exports);
54
+
55
+ // src/engine/text-utils.ts
56
+ function normalizeEventText(event) {
57
+ return [
58
+ event.intent,
59
+ event.tool ?? "",
60
+ event.scope ?? ""
61
+ ].join(" ").toLowerCase();
62
+ }
63
+ function extractKeywords(text, minLength = 3) {
64
+ return text.toLowerCase().split(/\s+/).filter((w) => w.length > minLength);
65
+ }
66
+ function matchesAllKeywords(eventText, ruleText) {
67
+ const keywords = extractKeywords(ruleText);
68
+ if (keywords.length === 0) return false;
69
+ return keywords.every((kw) => eventText.includes(kw));
70
+ }
71
+ function matchesKeywordThreshold(eventText, ruleText, threshold = 0.5) {
72
+ const keywords = extractKeywords(ruleText);
73
+ if (keywords.length === 0) return false;
74
+ const matched = keywords.filter((kw) => eventText.includes(kw));
75
+ return matched.length >= Math.ceil(keywords.length * threshold);
76
+ }
77
+ function tokenSimilarity(a, b) {
78
+ const tokensA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
79
+ const tokensB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
80
+ if (tokensA.size === 0 || tokensB.size === 0) return 0;
81
+ let intersection = 0;
82
+ for (const t of tokensA) {
83
+ if (tokensB.has(t)) intersection++;
84
+ }
85
+ const union = (/* @__PURE__ */ new Set([...tokensA, ...tokensB])).size;
86
+ return union > 0 ? intersection / union : 0;
87
+ }
88
+
89
+ // src/engine/plan-engine.ts
90
+ function keywordMatch(eventText, step) {
91
+ const stepText = [
92
+ step.label,
93
+ step.description ?? "",
94
+ ...step.tags ?? []
95
+ ].join(" ");
96
+ return matchesKeywordThreshold(eventText, stepText, 0.5);
97
+ }
98
+ function tokenSimilarity2(a, b) {
99
+ return tokenSimilarity(a, b);
100
+ }
101
+ function findMatchingStep(eventText, event, steps) {
102
+ const pendingOrActive = steps.filter((s) => s.status === "pending" || s.status === "active");
103
+ if (pendingOrActive.length === 0) {
104
+ return { matched: null, closest: null, closestScore: 0 };
105
+ }
106
+ for (const step of pendingOrActive) {
107
+ if (keywordMatch(eventText, step)) {
108
+ if (step.tools && event.tool && !step.tools.includes(event.tool)) {
109
+ continue;
110
+ }
111
+ return { matched: step, closest: step, closestScore: 1 };
112
+ }
113
+ }
114
+ const intentText = [event.intent, event.tool ?? "", event.scope ?? ""].join(" ");
115
+ let bestStep = null;
116
+ let bestScore = 0;
117
+ for (const step of pendingOrActive) {
118
+ const stepText = [step.label, step.description ?? "", ...step.tags ?? []].join(" ");
119
+ const score = tokenSimilarity2(intentText, stepText);
120
+ if (score > bestScore) {
121
+ bestScore = score;
122
+ bestStep = step;
123
+ }
124
+ }
125
+ const SIMILARITY_THRESHOLD = 0.35;
126
+ if (bestScore >= SIMILARITY_THRESHOLD && bestStep) {
127
+ if (bestStep.tools && event.tool && !bestStep.tools.includes(event.tool)) {
128
+ return { matched: null, closest: bestStep, closestScore: bestScore };
129
+ }
130
+ return { matched: bestStep, closest: bestStep, closestScore: bestScore };
131
+ }
132
+ return { matched: null, closest: bestStep, closestScore: bestScore };
133
+ }
134
+ function isSequenceValid(step, plan) {
135
+ if (!plan.sequential) return true;
136
+ if (!step.requires || step.requires.length === 0) return true;
137
+ return step.requires.every((reqId) => {
138
+ const reqStep = plan.steps.find((s) => s.id === reqId);
139
+ return reqStep?.status === "completed";
140
+ });
141
+ }
142
+ function checkConstraints(event, eventText, constraints) {
143
+ const checks = [];
144
+ for (const constraint of constraints) {
145
+ if (constraint.type === "approval") {
146
+ if (constraint.trigger && eventText.includes(constraint.trigger.substring(0, 10).toLowerCase())) {
147
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
148
+ return { violated: constraint, checks };
149
+ }
150
+ const keywords = constraint.description.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
151
+ const relevant = keywords.some((kw) => eventText.includes(kw));
152
+ if (relevant) {
153
+ checks.push({ constraintId: constraint.id, passed: false, reason: constraint.description });
154
+ return { violated: constraint, checks };
155
+ }
156
+ checks.push({ constraintId: constraint.id, passed: true });
157
+ continue;
158
+ }
159
+ if (constraint.type === "scope" && constraint.trigger) {
160
+ const keywords = extractKeywords(constraint.trigger);
161
+ const violated = keywords.length > 0 && keywords.every((kw) => eventText.includes(kw));
162
+ checks.push({
163
+ constraintId: constraint.id,
164
+ passed: !violated,
165
+ reason: violated ? constraint.description : void 0
166
+ });
167
+ if (violated) {
168
+ return { violated: constraint, checks };
169
+ }
170
+ continue;
171
+ }
172
+ checks.push({ constraintId: constraint.id, passed: true });
173
+ }
174
+ return { violated: null, checks };
175
+ }
176
+ function getPlanProgress(plan) {
177
+ const completed = plan.steps.filter((s) => s.status === "completed").length;
178
+ const total = plan.steps.length;
179
+ return {
180
+ completed,
181
+ total,
182
+ percentage: total > 0 ? Math.round(completed / total * 100) : 0
183
+ };
184
+ }
185
+ function advancePlan(plan, stepId, evidence) {
186
+ const step = plan.steps.find((s) => s.id === stepId);
187
+ if (!step) {
188
+ return { success: false, reason: `Step "${stepId}" not found in plan.` };
189
+ }
190
+ if (step.status === "completed") {
191
+ return { success: false, reason: `Step "${stepId}" is already completed.` };
192
+ }
193
+ const mode = plan.completion ?? "trust";
194
+ if (mode === "verified" && step.verify) {
195
+ if (!evidence) {
196
+ return {
197
+ success: false,
198
+ reason: `Step "${step.label}" requires evidence (verify: ${step.verify}). Provide evidence to advance.`
199
+ };
200
+ }
201
+ if (evidence.type !== step.verify) {
202
+ return {
203
+ success: false,
204
+ reason: `Evidence type "${evidence.type}" does not match required verification "${step.verify}".`
205
+ };
206
+ }
207
+ }
208
+ const updatedPlan = {
209
+ ...plan,
210
+ steps: plan.steps.map(
211
+ (s) => s.id === stepId ? { ...s, status: "completed" } : s
212
+ )
213
+ };
214
+ return {
215
+ success: true,
216
+ plan: updatedPlan,
217
+ evidence: evidence ?? void 0
218
+ };
219
+ }
220
+ function evaluatePlan(event, plan) {
221
+ const progress = getPlanProgress(plan);
222
+ if (plan.expires_at) {
223
+ const expiresAt = new Date(plan.expires_at).getTime();
224
+ if (Date.now() > expiresAt) {
225
+ return {
226
+ allowed: true,
227
+ status: "PLAN_COMPLETE",
228
+ reason: "Plan has expired.",
229
+ progress
230
+ };
231
+ }
232
+ }
233
+ if (progress.completed === progress.total) {
234
+ return {
235
+ allowed: true,
236
+ status: "PLAN_COMPLETE",
237
+ reason: "All plan steps are completed.",
238
+ progress
239
+ };
240
+ }
241
+ const eventText = normalizeEventText(event);
242
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
243
+ if (!matched) {
244
+ return {
245
+ allowed: false,
246
+ status: "OFF_PLAN",
247
+ reason: "Action does not match any plan step.",
248
+ closestStep: closest?.label,
249
+ similarityScore: closestScore,
250
+ progress
251
+ };
252
+ }
253
+ if (!isSequenceValid(matched, plan)) {
254
+ const pendingDeps = (matched.requires ?? []).filter((reqId) => plan.steps.find((s) => s.id === reqId)?.status !== "completed").join(", ");
255
+ return {
256
+ allowed: false,
257
+ status: "OFF_PLAN",
258
+ reason: `Step "${matched.label}" requires completion of: ${pendingDeps}`,
259
+ matchedStep: matched.id,
260
+ progress
261
+ };
262
+ }
263
+ const { violated } = checkConstraints(event, eventText, plan.constraints);
264
+ if (violated) {
265
+ return {
266
+ allowed: false,
267
+ status: "CONSTRAINT_VIOLATED",
268
+ reason: violated.description,
269
+ matchedStep: matched.id,
270
+ progress
271
+ };
272
+ }
273
+ return {
274
+ allowed: true,
275
+ status: "ON_PLAN",
276
+ reason: `Matches step: ${matched.label}`,
277
+ matchedStep: matched.id,
278
+ progress
279
+ };
280
+ }
281
+ function buildPlanCheck(event, plan, verdict) {
282
+ const eventText = normalizeEventText(event);
283
+ const { matched, closest, closestScore } = findMatchingStep(eventText, event, plan.steps);
284
+ const { checks: constraintChecks } = checkConstraints(event, eventText, plan.constraints);
285
+ const progress = getPlanProgress(plan);
286
+ return {
287
+ planId: plan.plan_id,
288
+ matched: !!matched,
289
+ matchedStepId: matched?.id,
290
+ matchedStepLabel: matched?.label,
291
+ closestStepId: !matched ? closest?.id : void 0,
292
+ closestStepLabel: !matched ? closest?.label : void 0,
293
+ similarityScore: !matched ? closestScore : void 0,
294
+ sequenceValid: matched ? isSequenceValid(matched, plan) : void 0,
295
+ constraintsChecked: constraintChecks,
296
+ progress: { completed: progress.completed, total: progress.total }
297
+ };
298
+ }
299
+
300
+ // src/engine/guard-engine.ts
301
+ var PROMPT_INJECTION_PATTERNS = [
302
+ // Instruction override
303
+ { pattern: /ignore\s+(previous|all|prior|above)\s+(instructions?|rules?)/i, label: "ignore-instructions" },
304
+ { pattern: /disregard\s+(your|the)\s+(rules|constraints)/i, label: "disregard-rules" },
305
+ { pattern: /new\s+instructions?:/i, label: "new-instructions" },
306
+ // Identity manipulation
307
+ { pattern: /you\s+are\s+now/i, label: "identity-override" },
308
+ { pattern: /new\s+persona/i, label: "new-persona" },
309
+ { pattern: /act\s+as\s+if/i, label: "act-as-if" },
310
+ { pattern: /pretend\s+(you|to\s+be|you\s+are\s+unrestricted)/i, label: "pretend-to-be" },
311
+ // Context reset
312
+ { pattern: /forget\s+(everything|all|your)/i, label: "forget-context" },
313
+ { pattern: /system\s*:\s*override/i, label: "system-override" },
314
+ // Constraint bypass
315
+ { pattern: /override\s+(your|the)\s+(programming|constraints)/i, label: "override-constraints" },
316
+ { pattern: /bypass\s+(your|the)\s+(filters|constraints|rules)/i, label: "bypass-filters" },
317
+ // Prompt extraction
318
+ { pattern: /system\s+prompt/i, label: "system-prompt-probe" },
319
+ { pattern: /reveal\s+your\s+(instructions?|prompt|rules)/i, label: "reveal-instructions" },
320
+ // Known jailbreak terms
321
+ { pattern: /jailbreak/i, label: "jailbreak" },
322
+ { pattern: /DAN\s+mode/i, label: "dan-mode" },
323
+ { pattern: /developer\s+mode/i, label: "developer-mode" }
324
+ ];
325
+ var EXECUTION_CLAIM_PATTERNS = [
326
+ { pattern: /I have (executed|completed|performed|done|made|created|sent|deleted|modified|updated)/i, label: "claim-i-have" },
327
+ { pattern: /Successfully (created|deleted|modified|updated|sent|executed|performed)/i, label: "claim-successfully" },
328
+ { pattern: /The file has been/i, label: "claim-file-modified" },
329
+ { pattern: /I've made the changes/i, label: "claim-made-changes" },
330
+ { pattern: /I('ve| have) (sent|posted|submitted|uploaded|downloaded)/i, label: "claim-sent" },
331
+ { pattern: /Your (email|message|file|request) has been (sent|submitted)/i, label: "claim-your-sent" },
332
+ { pattern: /Transaction complete/i, label: "claim-transaction" },
333
+ { pattern: /Order placed/i, label: "claim-order" },
334
+ { pattern: /Payment processed/i, label: "claim-payment" }
335
+ ];
336
+ var EXECUTION_INTENT_PATTERNS = [
337
+ { pattern: /^(execute|run|perform|do this)/i, label: "intent-execute" },
338
+ { pattern: /^(create|write|delete|modify) (a |the )?(file|folder|document)/i, label: "intent-file-ops" },
339
+ { pattern: /^(send|post|submit) (a |an |the )?(email|message|tweet|post)/i, label: "intent-send" },
340
+ { pattern: /^(search|look up|browse) (the )?web/i, label: "intent-web-search" },
341
+ { pattern: /^(make|call|invoke) (a |an )?(api|http|rest) (call|request)/i, label: "intent-api-call" },
342
+ { pattern: /^(buy|purchase|order|pay|transfer|send money)/i, label: "intent-financial" },
343
+ { pattern: /^(book|schedule|reserve)/i, label: "intent-booking" },
344
+ { pattern: /^(download|upload|save to|export to)/i, label: "intent-transfer" }
345
+ ];
346
+ var SCOPE_ESCAPE_PATTERNS = [
347
+ { pattern: /\.\.\//, label: "parent-traversal" },
348
+ { pattern: /^\/(?!home|project|workspace)/i, label: "absolute-path-outside-safe" },
349
+ { pattern: /~\//, label: "home-directory" },
350
+ { pattern: /\/etc\//i, label: "system-config" },
351
+ { pattern: /\/usr\//i, label: "system-binaries" },
352
+ { pattern: /\/var\//i, label: "system-variable-data" }
353
+ ];
354
+ var NEUTRAL_MESSAGES = {
355
+ "prompt-injection": "This input contains patterns that could alter agent behavior.",
356
+ "scope-escape": "This action would affect resources outside the declared scope.",
357
+ "execution-claim": "This response claims to have performed an action.",
358
+ "execution-intent": "This input requests execution in a thinking-only environment.",
359
+ "delete": "This action would remove files. Confirmation needed.",
360
+ "write-external": "This action would write outside the project folder.",
361
+ "network-mutate": "This action would send data to an external service.",
362
+ "credential-access": "This action would access stored credentials."
363
+ };
364
+ function levelRequiresConfirmation(level, actionType) {
365
+ if (level === "strict") return true;
366
+ if (level === "standard") {
367
+ return actionType === "delete" || actionType === "credential-access";
368
+ }
369
+ return false;
370
+ }
371
+ function isExternalScope(scope) {
372
+ const internalPatterns = [
373
+ /^\.?\/?src\//i,
374
+ /^\.?\/?lib\//i,
375
+ /^\.?\/?app\//i,
376
+ /^\.?\/?components\//i,
377
+ /^\.?\/?pages\//i,
378
+ /^\.?\/?public\//i,
379
+ /^\.?\/?assets\//i,
380
+ /^\.\//
381
+ ];
382
+ return !internalPatterns.some((p) => p.test(scope));
383
+ }
384
+ var MAX_INPUT_LENGTH = 1e5;
385
+ function evaluateGuard(event, world, options = {}) {
386
+ const startTime = performance.now();
387
+ const level = options.level ?? "standard";
388
+ const includeTrace = options.trace ?? false;
389
+ if (!event.intent || typeof event.intent !== "string") {
390
+ return {
391
+ status: "BLOCK",
392
+ reason: "GuardEvent.intent is required and must be a string",
393
+ ruleId: "safety-input-validation",
394
+ evidence: {
395
+ worldId: world.world?.world_id ?? "",
396
+ worldName: world.world?.name ?? "",
397
+ worldVersion: world.world?.version ?? "",
398
+ evaluatedAt: Date.now(),
399
+ invariantsSatisfied: 0,
400
+ invariantsTotal: 0,
401
+ guardsMatched: [],
402
+ rulesMatched: [],
403
+ enforcementLevel: level
404
+ }
405
+ };
406
+ }
407
+ const inputLength = event.intent.length + (event.tool?.length ?? 0) + (event.scope?.length ?? 0) + (event.payload ? JSON.stringify(event.payload).length : 0);
408
+ if (inputLength > MAX_INPUT_LENGTH) {
409
+ return {
410
+ status: "BLOCK",
411
+ reason: `Input exceeds maximum allowed length (${MAX_INPUT_LENGTH} characters)`,
412
+ ruleId: "safety-input-length",
413
+ evidence: {
414
+ worldId: world.world?.world_id ?? "",
415
+ worldName: world.world?.name ?? "",
416
+ worldVersion: world.world?.version ?? "",
417
+ evaluatedAt: Date.now(),
418
+ invariantsSatisfied: 0,
419
+ invariantsTotal: 0,
420
+ guardsMatched: [],
421
+ rulesMatched: [],
422
+ enforcementLevel: level
423
+ }
424
+ };
425
+ }
426
+ const eventText = normalizeEventText(event);
427
+ const invariantChecks = [];
428
+ const safetyChecks = [];
429
+ let planCheckResult;
430
+ const roleChecks = [];
431
+ const guardChecks = [];
432
+ const kernelRuleChecks = [];
433
+ const levelChecks = [];
434
+ let decidingLayer = "default-allow";
435
+ let decidingId;
436
+ const guardsMatched = [];
437
+ const rulesMatched = [];
438
+ if (options.emergencyOverride) {
439
+ checkInvariantCoverage(world, invariantChecks);
440
+ return buildVerdict(
441
+ "ALLOW",
442
+ void 0,
443
+ "emergency-override",
444
+ "Emergency override active \u2014 all governance rules suspended. Platform constraints still apply.",
445
+ world,
446
+ level,
447
+ invariantChecks,
448
+ guardsMatched,
449
+ rulesMatched,
450
+ includeTrace ? buildTrace(
451
+ invariantChecks,
452
+ safetyChecks,
453
+ planCheckResult,
454
+ roleChecks,
455
+ guardChecks,
456
+ kernelRuleChecks,
457
+ levelChecks,
458
+ "session-allowlist",
459
+ "emergency-override",
460
+ startTime
461
+ ) : void 0,
462
+ event.intent
463
+ );
464
+ }
465
+ checkInvariantCoverage(world, invariantChecks);
466
+ if (event.roleId && options.agentStates) {
467
+ const agentState = options.agentStates.get(event.roleId);
468
+ if (agentState && agentState.cooldownRemaining > 0) {
469
+ decidingLayer = "safety";
470
+ decidingId = `penalize-cooldown-${event.roleId}`;
471
+ const verdict = buildVerdict(
472
+ "PENALIZE",
473
+ `Agent "${event.roleId}" is frozen for ${agentState.cooldownRemaining} more round(s) due to prior penalty.`,
474
+ `penalize-cooldown-${event.roleId}`,
475
+ void 0,
476
+ world,
477
+ level,
478
+ invariantChecks,
479
+ guardsMatched,
480
+ rulesMatched,
481
+ includeTrace ? buildTrace(
482
+ invariantChecks,
483
+ safetyChecks,
484
+ planCheckResult,
485
+ roleChecks,
486
+ guardChecks,
487
+ kernelRuleChecks,
488
+ levelChecks,
489
+ decidingLayer,
490
+ decidingId,
491
+ startTime
492
+ ) : void 0
493
+ );
494
+ verdict.intentRecord = {
495
+ originalIntent: event.intent,
496
+ finalAction: "blocked (agent frozen)",
497
+ enforcement: "PENALIZE",
498
+ consequence: { type: "freeze", rounds: agentState.cooldownRemaining, description: "Agent still in cooldown from prior penalty" }
499
+ };
500
+ return verdict;
501
+ }
502
+ }
503
+ if (options.sessionAllowlist) {
504
+ const key = eventToAllowlistKey(event);
505
+ if (options.sessionAllowlist.has(key)) {
506
+ decidingLayer = "session-allowlist";
507
+ decidingId = `allowlist:${key}`;
508
+ return buildVerdict(
509
+ "ALLOW",
510
+ void 0,
511
+ `allowlist:${key}`,
512
+ void 0,
513
+ world,
514
+ level,
515
+ invariantChecks,
516
+ guardsMatched,
517
+ rulesMatched,
518
+ includeTrace ? buildTrace(
519
+ invariantChecks,
520
+ safetyChecks,
521
+ planCheckResult,
522
+ roleChecks,
523
+ guardChecks,
524
+ kernelRuleChecks,
525
+ levelChecks,
526
+ decidingLayer,
527
+ decidingId,
528
+ startTime
529
+ ) : void 0,
530
+ event.intent
531
+ );
532
+ }
533
+ }
534
+ const safetyVerdict = checkSafety(event, eventText, safetyChecks);
535
+ if (safetyVerdict) {
536
+ decidingLayer = "safety";
537
+ decidingId = safetyVerdict.ruleId;
538
+ return buildVerdict(
539
+ safetyVerdict.status,
540
+ safetyVerdict.reason,
541
+ safetyVerdict.ruleId,
542
+ void 0,
543
+ world,
544
+ level,
545
+ invariantChecks,
546
+ guardsMatched,
547
+ rulesMatched,
548
+ includeTrace ? buildTrace(
549
+ invariantChecks,
550
+ safetyChecks,
551
+ planCheckResult,
552
+ roleChecks,
553
+ guardChecks,
554
+ kernelRuleChecks,
555
+ levelChecks,
556
+ decidingLayer,
557
+ decidingId,
558
+ startTime
559
+ ) : void 0,
560
+ event.intent
561
+ );
562
+ }
563
+ if (options.plan) {
564
+ const planVerdict = evaluatePlan(event, options.plan);
565
+ planCheckResult = buildPlanCheck(event, options.plan, planVerdict);
566
+ if (!planVerdict.allowed && planVerdict.status !== "PLAN_COMPLETE") {
567
+ decidingLayer = "plan-enforcement";
568
+ decidingId = `plan-${options.plan.plan_id}`;
569
+ const planStatus = planVerdict.status === "CONSTRAINT_VIOLATED" ? "PAUSE" : "BLOCK";
570
+ let reason = planVerdict.reason ?? "Action blocked by plan.";
571
+ if (planVerdict.status === "OFF_PLAN" && planVerdict.closestStep) {
572
+ reason += ` Closest step: "${planVerdict.closestStep}" (similarity: ${(planVerdict.similarityScore ?? 0).toFixed(2)})`;
573
+ }
574
+ return buildVerdict(
575
+ planStatus,
576
+ reason,
577
+ `plan-${options.plan.plan_id}`,
578
+ void 0,
579
+ world,
580
+ level,
581
+ invariantChecks,
582
+ guardsMatched,
583
+ rulesMatched,
584
+ includeTrace ? buildTrace(
585
+ invariantChecks,
586
+ safetyChecks,
587
+ planCheckResult,
588
+ roleChecks,
589
+ guardChecks,
590
+ kernelRuleChecks,
591
+ levelChecks,
592
+ decidingLayer,
593
+ decidingId,
594
+ startTime
595
+ ) : void 0,
596
+ event.intent
597
+ );
598
+ }
599
+ }
600
+ const roleVerdict = checkRoleRules(event, eventText, world, roleChecks);
601
+ if (roleVerdict) {
602
+ decidingLayer = "role";
603
+ decidingId = roleVerdict.ruleId;
604
+ return buildVerdict(
605
+ roleVerdict.status,
606
+ roleVerdict.reason,
607
+ roleVerdict.ruleId,
608
+ void 0,
609
+ world,
610
+ level,
611
+ invariantChecks,
612
+ guardsMatched,
613
+ rulesMatched,
614
+ includeTrace ? buildTrace(
615
+ invariantChecks,
616
+ safetyChecks,
617
+ planCheckResult,
618
+ roleChecks,
619
+ guardChecks,
620
+ kernelRuleChecks,
621
+ levelChecks,
622
+ decidingLayer,
623
+ decidingId,
624
+ startTime
625
+ ) : void 0,
626
+ event.intent
627
+ );
628
+ }
629
+ const guardVerdict = checkGuards(event, eventText, world, guardChecks, guardsMatched);
630
+ if (guardVerdict) {
631
+ if (guardVerdict.status !== "ALLOW") {
632
+ decidingLayer = "guard";
633
+ decidingId = guardVerdict.ruleId;
634
+ const intentRecord = {
635
+ originalIntent: event.intent,
636
+ finalAction: guardVerdict.status === "MODIFY" ? guardVerdict.modifiedTo ?? "modified" : guardVerdict.status === "PENALIZE" ? "blocked + penalized" : guardVerdict.status === "REWARD" ? event.intent : guardVerdict.status === "NEUTRAL" ? event.intent : guardVerdict.status === "BLOCK" ? "blocked" : "paused",
637
+ ruleApplied: guardVerdict.ruleId,
638
+ enforcement: guardVerdict.status,
639
+ modifiedTo: guardVerdict.modifiedTo,
640
+ consequence: guardVerdict.consequence,
641
+ reward: guardVerdict.reward
642
+ };
643
+ const verdict = buildVerdict(
644
+ guardVerdict.status,
645
+ guardVerdict.reason,
646
+ guardVerdict.ruleId,
647
+ void 0,
648
+ world,
649
+ level,
650
+ invariantChecks,
651
+ guardsMatched,
652
+ rulesMatched,
653
+ includeTrace ? buildTrace(
654
+ invariantChecks,
655
+ safetyChecks,
656
+ planCheckResult,
657
+ roleChecks,
658
+ guardChecks,
659
+ kernelRuleChecks,
660
+ levelChecks,
661
+ decidingLayer,
662
+ decidingId,
663
+ startTime
664
+ ) : void 0,
665
+ event.intent
666
+ );
667
+ verdict.intentRecord = intentRecord;
668
+ if (guardVerdict.consequence) verdict.consequence = guardVerdict.consequence;
669
+ if (guardVerdict.reward) verdict.reward = guardVerdict.reward;
670
+ return verdict;
671
+ }
672
+ }
673
+ const kernelVerdict = checkKernelRules(eventText, world, kernelRuleChecks, rulesMatched);
674
+ if (kernelVerdict) {
675
+ decidingLayer = "kernel-rule";
676
+ decidingId = kernelVerdict.ruleId;
677
+ return buildVerdict(
678
+ kernelVerdict.status,
679
+ kernelVerdict.reason,
680
+ kernelVerdict.ruleId,
681
+ void 0,
682
+ world,
683
+ level,
684
+ invariantChecks,
685
+ guardsMatched,
686
+ rulesMatched,
687
+ includeTrace ? buildTrace(
688
+ invariantChecks,
689
+ safetyChecks,
690
+ planCheckResult,
691
+ roleChecks,
692
+ guardChecks,
693
+ kernelRuleChecks,
694
+ levelChecks,
695
+ decidingLayer,
696
+ decidingId,
697
+ startTime
698
+ ) : void 0,
699
+ event.intent
700
+ );
701
+ }
702
+ const levelVerdict = checkLevelConstraints(event, level, levelChecks);
703
+ if (levelVerdict) {
704
+ decidingLayer = "level-constraint";
705
+ decidingId = levelVerdict.ruleId;
706
+ return buildVerdict(
707
+ levelVerdict.status,
708
+ levelVerdict.reason,
709
+ levelVerdict.ruleId,
710
+ void 0,
711
+ world,
712
+ level,
713
+ invariantChecks,
714
+ guardsMatched,
715
+ rulesMatched,
716
+ includeTrace ? buildTrace(
717
+ invariantChecks,
718
+ safetyChecks,
719
+ planCheckResult,
720
+ roleChecks,
721
+ guardChecks,
722
+ kernelRuleChecks,
723
+ levelChecks,
724
+ decidingLayer,
725
+ decidingId,
726
+ startTime
727
+ ) : void 0,
728
+ event.intent
729
+ );
730
+ }
731
+ const warning = guardVerdict?.warning;
732
+ return buildVerdict(
733
+ "ALLOW",
734
+ void 0,
735
+ void 0,
736
+ warning,
737
+ world,
738
+ level,
739
+ invariantChecks,
740
+ guardsMatched,
741
+ rulesMatched,
742
+ includeTrace ? buildTrace(
743
+ invariantChecks,
744
+ safetyChecks,
745
+ planCheckResult,
746
+ roleChecks,
747
+ guardChecks,
748
+ kernelRuleChecks,
749
+ levelChecks,
750
+ decidingLayer,
751
+ decidingId,
752
+ startTime
753
+ ) : void 0,
754
+ event.intent
755
+ );
756
+ }
757
+ function checkInvariantCoverage(world, checks) {
758
+ const invariants = world.invariants ?? [];
759
+ const guards = world.guards?.guards ?? [];
760
+ for (const invariant of invariants) {
761
+ const coveringGuard = guards.find(
762
+ (g) => g.invariant_ref === invariant.id && g.immutable
763
+ );
764
+ checks.push({
765
+ invariantId: invariant.id,
766
+ label: invariant.label,
767
+ hasGuardCoverage: !!coveringGuard,
768
+ coveringGuardId: coveringGuard?.id
769
+ });
770
+ }
771
+ }
772
+ function checkSafety(event, eventText, checks) {
773
+ const textToCheck = event.intent + (event.payload ? JSON.stringify(event.payload) : "");
774
+ for (const { pattern, label } of PROMPT_INJECTION_PATTERNS) {
775
+ const triggered = pattern.test(textToCheck);
776
+ checks.push({
777
+ checkType: "prompt-injection",
778
+ triggered,
779
+ matchedPattern: triggered ? label : void 0
780
+ });
781
+ if (triggered) {
782
+ for (const remaining of PROMPT_INJECTION_PATTERNS.filter((p) => p.label !== label)) {
783
+ checks.push({
784
+ checkType: "prompt-injection",
785
+ triggered: remaining.pattern.test(textToCheck),
786
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
787
+ });
788
+ }
789
+ return {
790
+ status: "PAUSE",
791
+ reason: NEUTRAL_MESSAGES["prompt-injection"],
792
+ ruleId: `safety-injection-${label}`
793
+ };
794
+ }
795
+ }
796
+ const scopeToCheck = event.scope ?? event.intent;
797
+ for (const { pattern, label } of SCOPE_ESCAPE_PATTERNS) {
798
+ const triggered = pattern.test(scopeToCheck);
799
+ checks.push({
800
+ checkType: "scope-escape",
801
+ triggered,
802
+ matchedPattern: triggered ? label : void 0
803
+ });
804
+ if (triggered) {
805
+ for (const remaining of SCOPE_ESCAPE_PATTERNS.filter((p) => p.label !== label)) {
806
+ checks.push({
807
+ checkType: "scope-escape",
808
+ triggered: remaining.pattern.test(scopeToCheck),
809
+ matchedPattern: remaining.pattern.test(scopeToCheck) ? remaining.label : void 0
810
+ });
811
+ }
812
+ return {
813
+ status: "PAUSE",
814
+ reason: NEUTRAL_MESSAGES["scope-escape"],
815
+ ruleId: `safety-scope-${label}`
816
+ };
817
+ }
818
+ }
819
+ if (event.direction === "output") {
820
+ for (const { pattern, label } of EXECUTION_CLAIM_PATTERNS) {
821
+ const triggered = pattern.test(textToCheck);
822
+ checks.push({
823
+ checkType: "execution-claim",
824
+ triggered,
825
+ matchedPattern: triggered ? label : void 0
826
+ });
827
+ if (triggered) {
828
+ for (const remaining of EXECUTION_CLAIM_PATTERNS.filter((p) => p.label !== label)) {
829
+ checks.push({
830
+ checkType: "execution-claim",
831
+ triggered: remaining.pattern.test(textToCheck),
832
+ matchedPattern: remaining.pattern.test(textToCheck) ? remaining.label : void 0
833
+ });
834
+ }
835
+ return {
836
+ status: "PAUSE",
837
+ reason: NEUTRAL_MESSAGES["execution-claim"],
838
+ ruleId: `safety-execution-claim-${label}`
839
+ };
840
+ }
841
+ }
842
+ }
843
+ if (event.direction === "input") {
844
+ const intentTrimmed = event.intent.trim();
845
+ for (const { pattern, label } of EXECUTION_INTENT_PATTERNS) {
846
+ const triggered = pattern.test(intentTrimmed);
847
+ checks.push({
848
+ checkType: "execution-intent",
849
+ triggered,
850
+ matchedPattern: triggered ? label : void 0
851
+ });
852
+ if (triggered) {
853
+ for (const remaining of EXECUTION_INTENT_PATTERNS.filter((p) => p.label !== label)) {
854
+ checks.push({
855
+ checkType: "execution-intent",
856
+ triggered: remaining.pattern.test(intentTrimmed),
857
+ matchedPattern: remaining.pattern.test(intentTrimmed) ? remaining.label : void 0
858
+ });
859
+ }
860
+ return {
861
+ status: "PAUSE",
862
+ reason: NEUTRAL_MESSAGES["execution-intent"],
863
+ ruleId: `safety-execution-intent-${label}`
864
+ };
865
+ }
866
+ }
867
+ }
868
+ return null;
869
+ }
870
+ function checkRoleRules(event, eventText, world, checks) {
871
+ if (!event.roleId || !world.roles) return null;
872
+ const role = world.roles.roles.find((r) => r.id === event.roleId);
873
+ if (!role) return null;
874
+ if (role.requiresApproval) {
875
+ checks.push({
876
+ roleId: role.id,
877
+ roleName: role.name,
878
+ rule: "All actions require approval",
879
+ ruleType: "requiresApproval",
880
+ matched: true
881
+ });
882
+ return {
883
+ status: "PAUSE",
884
+ reason: `Role "${role.name}" requires approval for all actions.`,
885
+ ruleId: `role-${role.id}-requires-approval`
886
+ };
887
+ }
888
+ for (const rule of role.cannotDo) {
889
+ const matched = matchesKeywords(eventText, rule);
890
+ checks.push({
891
+ roleId: role.id,
892
+ roleName: role.name,
893
+ rule,
894
+ ruleType: "cannotDo",
895
+ matched
896
+ });
897
+ if (matched) {
898
+ return {
899
+ status: "BLOCK",
900
+ reason: `Role "${role.name}" cannot: ${rule}`,
901
+ ruleId: `role-${role.id}-cannotdo`
902
+ };
903
+ }
904
+ }
905
+ for (const rule of role.canDo) {
906
+ checks.push({
907
+ roleId: role.id,
908
+ roleName: role.name,
909
+ rule,
910
+ ruleType: "canDo",
911
+ matched: matchesKeywords(eventText, rule)
912
+ });
913
+ }
914
+ return null;
915
+ }
916
+ function checkGuards(event, eventText, world, checks, guardsMatched) {
917
+ if (!world.guards) return null;
918
+ const guardsConfig = world.guards;
919
+ let warnResult = null;
920
+ const compiledPatterns = /* @__PURE__ */ new Map();
921
+ for (const [key, def] of Object.entries(guardsConfig.intent_vocabulary)) {
922
+ try {
923
+ compiledPatterns.set(key, new RegExp(def.pattern, "i"));
924
+ } catch {
925
+ }
926
+ }
927
+ const eventTool = (event.tool ?? "").toLowerCase();
928
+ for (const guard of guardsConfig.guards) {
929
+ if (guard.appliesTo && guard.appliesTo.length > 0) {
930
+ const normalizedAppliesTo = guard.appliesTo.map((t) => t.toLowerCase());
931
+ if (!normalizedAppliesTo.includes(eventTool)) {
932
+ continue;
933
+ }
934
+ }
935
+ const enabled = guard.immutable || guard.default_enabled !== false;
936
+ const matchedPatterns = [];
937
+ for (const patternKey of guard.intent_patterns) {
938
+ const regex = compiledPatterns.get(patternKey);
939
+ if (regex?.test(eventText)) {
940
+ matchedPatterns.push(patternKey);
941
+ }
942
+ }
943
+ const matched = matchedPatterns.length > 0 && enabled;
944
+ let roleGated = false;
945
+ if (matched && guard.required_roles && guard.required_roles.length > 0 && event.roleId && guard.required_roles.includes(event.roleId)) {
946
+ roleGated = true;
947
+ }
948
+ checks.push({
949
+ guardId: guard.id,
950
+ label: guard.label,
951
+ category: guard.category,
952
+ enabled,
953
+ matched: matched && !roleGated,
954
+ enforcement: guard.enforcement,
955
+ matchedPatterns,
956
+ roleGated
957
+ });
958
+ if (!matched || roleGated) continue;
959
+ guardsMatched.push(guard.id);
960
+ const actionMode = guard.player_modes?.action ?? guard.enforcement;
961
+ const reason = guard.redirect ? `${guard.description} \u2014 ${guard.redirect}` : guard.description;
962
+ if (actionMode === "block") {
963
+ return { status: "BLOCK", reason, ruleId: `guard-${guard.id}` };
964
+ }
965
+ if (actionMode === "pause") {
966
+ return { status: "PAUSE", reason, ruleId: `guard-${guard.id}` };
967
+ }
968
+ if (actionMode === "penalize") {
969
+ const consequence = guard.consequence ? { ...guard.consequence } : { type: "freeze", rounds: 1, description: `Penalized for violating: ${guard.label}` };
970
+ return { status: "PENALIZE", reason, ruleId: `guard-${guard.id}`, consequence };
971
+ }
972
+ if (actionMode === "reward") {
973
+ const reward = guard.reward ? { ...guard.reward } : { type: "boost_influence", magnitude: 0.1, description: `Rewarded for: ${guard.label}` };
974
+ return { status: "REWARD", reason, ruleId: `guard-${guard.id}`, reward };
975
+ }
976
+ if (actionMode === "modify") {
977
+ const modifiedTo = guard.modify_to ?? guard.redirect ?? "hold";
978
+ return { status: "MODIFY", reason: `${reason} \u2192 Modified to: ${modifiedTo}`, ruleId: `guard-${guard.id}`, modifiedTo };
979
+ }
980
+ if (actionMode === "neutral") {
981
+ return { status: "NEUTRAL", reason, ruleId: `guard-${guard.id}` };
982
+ }
983
+ if (actionMode === "warn" && !warnResult) {
984
+ warnResult = { status: "ALLOW", warning: reason, ruleId: `guard-${guard.id}` };
985
+ }
986
+ }
987
+ return warnResult;
988
+ }
989
+ function checkKernelRules(eventText, world, checks, rulesMatched) {
990
+ if (!world.kernel) return null;
991
+ const forbidden = world.kernel.input_boundaries?.forbidden_patterns ?? [];
992
+ const output = world.kernel.output_boundaries?.forbidden_patterns ?? [];
993
+ for (const rule of forbidden) {
994
+ let matched = false;
995
+ let matchMethod = "none";
996
+ if (rule.pattern) {
997
+ try {
998
+ matched = new RegExp(rule.pattern, "i").test(eventText);
999
+ matchMethod = "pattern";
1000
+ } catch {
1001
+ }
1002
+ }
1003
+ if (!matched && rule.reason) {
1004
+ matched = matchesKeywords(eventText, rule.reason);
1005
+ if (matched) matchMethod = "keyword";
1006
+ }
1007
+ checks.push({
1008
+ ruleId: rule.id,
1009
+ text: rule.reason,
1010
+ category: "forbidden",
1011
+ matched,
1012
+ matchMethod
1013
+ });
1014
+ if (matched) {
1015
+ rulesMatched.push(rule.id);
1016
+ if (rule.action === "BLOCK") {
1017
+ return {
1018
+ status: "BLOCK",
1019
+ reason: rule.reason,
1020
+ ruleId: `kernel-${rule.id}`
1021
+ };
1022
+ }
1023
+ }
1024
+ }
1025
+ return null;
1026
+ }
1027
+ function checkLevelConstraints(event, level, checks) {
1028
+ if (level === "basic") return null;
1029
+ const intent = event.intent.toLowerCase();
1030
+ const tool = (event.tool ?? "").toLowerCase();
1031
+ const isDelete = intent.includes("delete") || intent.includes("remove") || intent.includes("rm ") || tool === "delete";
1032
+ const deleteTriggered = isDelete && levelRequiresConfirmation(level, "delete");
1033
+ checks.push({
1034
+ checkType: "delete",
1035
+ level,
1036
+ triggered: deleteTriggered,
1037
+ reason: deleteTriggered ? NEUTRAL_MESSAGES["delete"] : void 0
1038
+ });
1039
+ if (deleteTriggered) {
1040
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["delete"], ruleId: "level-delete-check" };
1041
+ }
1042
+ const isExternal = event.scope ? isExternalScope(event.scope) : false;
1043
+ const externalTriggered = isExternal && levelRequiresConfirmation(level, "write-external");
1044
+ checks.push({
1045
+ checkType: "write-external",
1046
+ level,
1047
+ triggered: externalTriggered,
1048
+ reason: externalTriggered ? NEUTRAL_MESSAGES["write-external"] : void 0
1049
+ });
1050
+ if (externalTriggered) {
1051
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["write-external"], ruleId: "level-external-write-check" };
1052
+ }
1053
+ const isNetwork = tool === "http" || tool === "fetch" || tool === "request" || intent.includes("post ") || intent.includes("sending");
1054
+ const networkTriggered = isNetwork && levelRequiresConfirmation(level, "network-mutate");
1055
+ checks.push({
1056
+ checkType: "network-mutate",
1057
+ level,
1058
+ triggered: networkTriggered,
1059
+ reason: networkTriggered ? NEUTRAL_MESSAGES["network-mutate"] : void 0
1060
+ });
1061
+ if (networkTriggered) {
1062
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["network-mutate"], ruleId: "level-network-mutate-check" };
1063
+ }
1064
+ const isCredential = intent.includes("credential") || intent.includes("password") || intent.includes("secret") || intent.includes("api key") || intent.includes("token");
1065
+ const credentialTriggered = isCredential && levelRequiresConfirmation(level, "credential-access");
1066
+ checks.push({
1067
+ checkType: "credential-access",
1068
+ level,
1069
+ triggered: credentialTriggered,
1070
+ reason: credentialTriggered ? NEUTRAL_MESSAGES["credential-access"] : void 0
1071
+ });
1072
+ if (credentialTriggered) {
1073
+ return { status: "PAUSE", reason: NEUTRAL_MESSAGES["credential-access"], ruleId: "level-credential-check" };
1074
+ }
1075
+ const irreversibleTriggered = !!event.irreversible && level !== "basic";
1076
+ checks.push({
1077
+ checkType: "irreversible",
1078
+ level,
1079
+ triggered: irreversibleTriggered,
1080
+ reason: irreversibleTriggered ? "This action is marked as irreversible." : void 0
1081
+ });
1082
+ if (irreversibleTriggered) {
1083
+ return {
1084
+ status: "PAUSE",
1085
+ reason: "This action is marked as irreversible.",
1086
+ ruleId: "level-irreversible-check"
1087
+ };
1088
+ }
1089
+ return null;
1090
+ }
1091
+ function matchesKeywords(eventText, ruleText) {
1092
+ return matchesAllKeywords(eventText, ruleText);
1093
+ }
1094
+ function eventToAllowlistKey(event) {
1095
+ return `${(event.tool ?? "*").toLowerCase()}::${event.intent.toLowerCase().trim()}`;
1096
+ }
1097
+ function buildTrace(invariantChecks, safetyChecks, planCheck, roleChecks, guardChecks, kernelRuleChecks, levelChecks, decidingLayer, decidingId, startTime) {
1098
+ const trace = {
1099
+ invariantChecks,
1100
+ safetyChecks,
1101
+ roleChecks,
1102
+ guardChecks,
1103
+ kernelRuleChecks,
1104
+ levelChecks,
1105
+ precedenceResolution: {
1106
+ decidingLayer,
1107
+ decidingId,
1108
+ strategy: "first-match-wins",
1109
+ chainOrder: [
1110
+ "invariant-coverage",
1111
+ "session-allowlist",
1112
+ "safety-injection",
1113
+ "safety-scope-escape",
1114
+ "safety-execution-claim",
1115
+ "safety-execution-intent",
1116
+ "plan-enforcement",
1117
+ "role-rules",
1118
+ "declarative-guards",
1119
+ "kernel-rules",
1120
+ "level-constraints",
1121
+ "default-allow"
1122
+ ]
1123
+ },
1124
+ durationMs: performance.now() - startTime
1125
+ };
1126
+ if (planCheck) {
1127
+ trace.planCheck = planCheck;
1128
+ }
1129
+ return trace;
1130
+ }
1131
+ function buildVerdict(status, reason, ruleId, warning, world, level, invariantChecks, guardsMatched, rulesMatched, trace, eventIntent) {
1132
+ const evidence = {
1133
+ worldId: world.world.world_id,
1134
+ worldName: world.world.name,
1135
+ worldVersion: world.world.version,
1136
+ evaluatedAt: Date.now(),
1137
+ invariantsSatisfied: invariantChecks.filter((c) => c.hasGuardCoverage).length,
1138
+ invariantsTotal: invariantChecks.length,
1139
+ guardsMatched,
1140
+ rulesMatched,
1141
+ enforcementLevel: level
1142
+ };
1143
+ const verdict = {
1144
+ status,
1145
+ evidence
1146
+ };
1147
+ if (reason) verdict.reason = reason;
1148
+ if (ruleId) verdict.ruleId = ruleId;
1149
+ if (warning) verdict.warning = warning;
1150
+ if (trace) verdict.trace = trace;
1151
+ verdict.event = verdictToEvent(status, eventIntent);
1152
+ return verdict;
1153
+ }
1154
+ function verdictToEvent(status, intent) {
1155
+ const statusEventMap = {
1156
+ ALLOW: "action_allowed",
1157
+ BLOCK: "action_blocked",
1158
+ PAUSE: "action_paused",
1159
+ MODIFY: "action_modified",
1160
+ PENALIZE: "action_penalized",
1161
+ REWARD: "action_rewarded",
1162
+ NEUTRAL: "action_neutral"
1163
+ };
1164
+ return {
1165
+ type: intent || statusEventMap[status] || "unknown_action",
1166
+ actor: "agent",
1167
+ source: "guard",
1168
+ timestamp: Date.now(),
1169
+ guardStatus: status
1170
+ };
1171
+ }
1172
+
1173
+ // src/loader/world-loader.ts
1174
+ async function loadWorldFromDirectory(dirPath) {
1175
+ const { readFile } = await import("fs/promises");
1176
+ const { join } = await import("path");
1177
+ const { readdirSync } = await import("fs");
1178
+ async function readJson(filename) {
1179
+ const filePath = join(dirPath, filename);
1180
+ try {
1181
+ const content = await readFile(filePath, "utf-8");
1182
+ return JSON.parse(content);
1183
+ } catch (err) {
1184
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
1185
+ return void 0;
1186
+ }
1187
+ process.stderr.write(
1188
+ `[neuroverse] Warning: Failed to read ${filename}: ${err instanceof Error ? err.message : String(err)}
1189
+ `
1190
+ );
1191
+ return void 0;
1192
+ }
1193
+ }
1194
+ const worldJson = await readJson("world.json");
1195
+ if (!worldJson) {
1196
+ throw new Error(`Cannot read world.json in ${dirPath}`);
1197
+ }
1198
+ const invariantsJson = await readJson("invariants.json");
1199
+ const assumptionsJson = await readJson("assumptions.json");
1200
+ const stateSchemaJson = await readJson("state-schema.json");
1201
+ const gatesJson = await readJson("gates.json");
1202
+ const outcomesJson = await readJson("outcomes.json");
1203
+ const guardsJson = await readJson("guards.json");
1204
+ const rolesJson = await readJson("roles.json");
1205
+ const kernelJson = await readJson("kernel.json");
1206
+ const metadataJson = await readJson("metadata.json");
1207
+ const rules = [];
1208
+ try {
1209
+ const rulesDir = join(dirPath, "rules");
1210
+ const ruleFiles = readdirSync(rulesDir).filter((f) => f.endsWith(".json")).sort();
1211
+ for (const file of ruleFiles) {
1212
+ try {
1213
+ const content = await readFile(join(rulesDir, file), "utf-8");
1214
+ rules.push(JSON.parse(content));
1215
+ } catch (err) {
1216
+ process.stderr.write(
1217
+ `[neuroverse] Warning: Failed to parse rule ${file}: ${err instanceof Error ? err.message : String(err)}
1218
+ `
1219
+ );
1220
+ }
1221
+ }
1222
+ } catch (err) {
1223
+ if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) {
1224
+ process.stderr.write(
1225
+ `[neuroverse] Warning: Failed to read rules directory: ${err instanceof Error ? err.message : String(err)}
1226
+ `
1227
+ );
1228
+ }
1229
+ }
1230
+ return {
1231
+ world: worldJson,
1232
+ invariants: invariantsJson?.invariants ?? [],
1233
+ assumptions: assumptionsJson ?? { profiles: {}, parameter_definitions: {} },
1234
+ stateSchema: stateSchemaJson ?? { variables: {}, presets: {} },
1235
+ rules,
1236
+ gates: gatesJson ?? {
1237
+ viability_classification: [],
1238
+ structural_override: { description: "", enforcement: "mandatory" },
1239
+ sustainability_threshold: 0,
1240
+ collapse_visual: { background: "", text: "", border: "", label: "" }
1241
+ },
1242
+ outcomes: outcomesJson ?? {
1243
+ computed_outcomes: [],
1244
+ comparison_layout: { primary_card: "", status_badge: "", structural_indicators: [] }
1245
+ },
1246
+ guards: guardsJson,
1247
+ roles: rolesJson,
1248
+ kernel: kernelJson,
1249
+ metadata: metadataJson ?? {
1250
+ format_version: "1.0.0",
1251
+ created_at: "",
1252
+ last_modified: "",
1253
+ authoring_method: "manual-authoring"
1254
+ }
1255
+ };
1256
+ }
1257
+ async function loadWorld(worldPath) {
1258
+ const { stat } = await import("fs/promises");
1259
+ const info = await stat(worldPath);
1260
+ if (info.isDirectory()) {
1261
+ return loadWorldFromDirectory(worldPath);
1262
+ }
1263
+ throw new Error(`Cannot load world from: ${worldPath} \u2014 expected a directory`);
1264
+ }
1265
+
1266
+ // src/adapters/shared.ts
1267
+ var GovernanceBlockedError = class extends Error {
1268
+ verdict;
1269
+ constructor(verdict, message) {
1270
+ super(message ?? `[NeuroVerse] BLOCKED: ${verdict.reason ?? verdict.ruleId ?? "governance rule"}`);
1271
+ this.name = "GovernanceBlockedError";
1272
+ this.verdict = verdict;
1273
+ }
1274
+ };
1275
+ function trackPlanProgress(event, state, callbacks) {
1276
+ if (!state.activePlan) return;
1277
+ const planVerdict = evaluatePlan(event, state.activePlan);
1278
+ if (planVerdict.matchedStep) {
1279
+ const advResult = advancePlan(state.activePlan, planVerdict.matchedStep);
1280
+ if (advResult.success && advResult.plan) {
1281
+ state.activePlan = advResult.plan;
1282
+ state.engineOptions.plan = state.activePlan;
1283
+ }
1284
+ const progress = getPlanProgress(state.activePlan);
1285
+ callbacks.onPlanProgress?.(progress);
1286
+ if (progress.completed === progress.total) {
1287
+ callbacks.onPlanComplete?.();
1288
+ }
1289
+ }
1290
+ }
1291
+ function buildEngineOptions(options, plan) {
1292
+ return {
1293
+ trace: options.trace ?? false,
1294
+ level: options.level,
1295
+ plan: plan ?? options.plan
1296
+ };
1297
+ }
1298
+
1299
+ // src/worlds/mentraos-intent-taxonomy.ts
1300
+ var MENTRA_INTENT_TAXONOMY = [
1301
+ // ── Camera Domain ───────────────────────────────────────────────────────
1302
+ {
1303
+ intent: "camera_photo_capture",
1304
+ description: "Capture a single photo from the glasses camera",
1305
+ sdk_method: "session.camera.requestPhoto()",
1306
+ permission: "CAMERA",
1307
+ domain: "camera",
1308
+ supported_glasses: ["mentra_live"],
1309
+ action_category: "write",
1310
+ base_risk: "high",
1311
+ exfiltration_risk: true,
1312
+ reversible: false
1313
+ },
1314
+ {
1315
+ intent: "camera_stream_start",
1316
+ description: "Start a managed video stream (HLS) from the glasses camera",
1317
+ sdk_method: "session.camera.startManagedStream()",
1318
+ permission: "CAMERA",
1319
+ domain: "camera",
1320
+ supported_glasses: ["mentra_live"],
1321
+ action_category: "write",
1322
+ base_risk: "critical",
1323
+ exfiltration_risk: true,
1324
+ reversible: true
1325
+ },
1326
+ {
1327
+ intent: "camera_stream_stop",
1328
+ description: "Stop an active camera stream",
1329
+ sdk_method: "session.camera.stopStream()",
1330
+ permission: "CAMERA",
1331
+ domain: "camera",
1332
+ supported_glasses: ["mentra_live"],
1333
+ action_category: "write",
1334
+ base_risk: "low",
1335
+ exfiltration_risk: false,
1336
+ reversible: false
1337
+ },
1338
+ {
1339
+ intent: "camera_restream_start",
1340
+ description: "Restream camera feed to an external RTMP destination (e.g., social media)",
1341
+ sdk_method: "session.camera.startRestream()",
1342
+ permission: "CAMERA",
1343
+ domain: "camera",
1344
+ supported_glasses: ["mentra_live"],
1345
+ action_category: "network",
1346
+ base_risk: "critical",
1347
+ exfiltration_risk: true,
1348
+ reversible: true
1349
+ },
1350
+ // ── Microphone Domain ──────────────────────────────────────────────────
1351
+ {
1352
+ intent: "microphone_transcription_start",
1353
+ description: "Start receiving speech-to-text transcription events",
1354
+ sdk_method: "session.events.onTranscription()",
1355
+ permission: "MICROPHONE",
1356
+ domain: "microphone",
1357
+ supported_glasses: ["even_realities_g1", "mentra_live"],
1358
+ action_category: "read",
1359
+ base_risk: "medium",
1360
+ exfiltration_risk: true,
1361
+ reversible: true
1362
+ },
1363
+ {
1364
+ intent: "microphone_translation_start",
1365
+ description: "Start receiving translation events from spoken audio",
1366
+ sdk_method: "session.events.onTranslation()",
1367
+ permission: "MICROPHONE",
1368
+ domain: "microphone",
1369
+ supported_glasses: ["even_realities_g1", "mentra_live"],
1370
+ action_category: "read",
1371
+ base_risk: "medium",
1372
+ exfiltration_risk: true,
1373
+ reversible: true
1374
+ },
1375
+ {
1376
+ intent: "microphone_phone_passthrough",
1377
+ description: "Use phone microphone as audio input (glasses without built-in mic)",
1378
+ sdk_method: "session.audio.startPhoneMic()",
1379
+ permission: "MICROPHONE",
1380
+ domain: "microphone",
1381
+ supported_glasses: ["mentra_mach1", "vuzix_z100"],
1382
+ action_category: "read",
1383
+ base_risk: "medium",
1384
+ exfiltration_risk: true,
1385
+ reversible: true
1386
+ },
1387
+ // ── Display Domain ────────────────────────────────────────────────────
1388
+ {
1389
+ intent: "display_text_wall",
1390
+ description: "Show a single text block on the glasses display",
1391
+ sdk_method: "session.layouts.showTextWall()",
1392
+ permission: "NONE",
1393
+ domain: "display",
1394
+ supported_glasses: ["even_realities_g1", "mentra_mach1", "vuzix_z100"],
1395
+ action_category: "write",
1396
+ base_risk: "low",
1397
+ exfiltration_risk: false,
1398
+ reversible: true
1399
+ },
1400
+ {
1401
+ intent: "display_double_text_wall",
1402
+ description: "Show two text blocks (top/bottom) on the glasses display",
1403
+ sdk_method: "session.layouts.showDoubleTextWall()",
1404
+ permission: "NONE",
1405
+ domain: "display",
1406
+ supported_glasses: ["even_realities_g1", "mentra_mach1", "vuzix_z100"],
1407
+ action_category: "write",
1408
+ base_risk: "low",
1409
+ exfiltration_risk: false,
1410
+ reversible: true
1411
+ },
1412
+ {
1413
+ intent: "display_reference_card",
1414
+ description: "Show a reference card layout with structured content",
1415
+ sdk_method: "session.layouts.showReferenceCard()",
1416
+ permission: "NONE",
1417
+ domain: "display",
1418
+ supported_glasses: ["even_realities_g1"],
1419
+ action_category: "write",
1420
+ base_risk: "low",
1421
+ exfiltration_risk: false,
1422
+ reversible: true
1423
+ },
1424
+ {
1425
+ intent: "display_dashboard_card",
1426
+ description: "Show a dashboard card layout",
1427
+ sdk_method: "session.layouts.showDashboardCard()",
1428
+ permission: "NONE",
1429
+ domain: "display",
1430
+ supported_glasses: ["even_realities_g1"],
1431
+ action_category: "write",
1432
+ base_risk: "low",
1433
+ exfiltration_risk: false,
1434
+ reversible: true
1435
+ },
1436
+ {
1437
+ intent: "display_image",
1438
+ description: "Display an image on the glasses",
1439
+ sdk_method: "session.layouts.showImage()",
1440
+ permission: "NONE",
1441
+ domain: "display",
1442
+ supported_glasses: ["even_realities_g1"],
1443
+ action_category: "write",
1444
+ base_risk: "low",
1445
+ exfiltration_risk: false,
1446
+ reversible: true
1447
+ },
1448
+ // ── Dashboard Domain ──────────────────────────────────────────────────
1449
+ {
1450
+ intent: "dashboard_update_main",
1451
+ description: "Update the persistent dashboard content (compact mode)",
1452
+ sdk_method: "session.dashboard.content.setMain()",
1453
+ permission: "NONE",
1454
+ domain: "dashboard",
1455
+ supported_glasses: ["even_realities_g1", "mentra_mach1", "vuzix_z100"],
1456
+ action_category: "write",
1457
+ base_risk: "low",
1458
+ exfiltration_risk: false,
1459
+ reversible: true
1460
+ },
1461
+ {
1462
+ intent: "dashboard_update_expanded",
1463
+ description: "Update the expanded dashboard content (user-opened mode)",
1464
+ sdk_method: "session.dashboard.content.setExpanded()",
1465
+ permission: "NONE",
1466
+ domain: "dashboard",
1467
+ supported_glasses: ["even_realities_g1", "mentra_mach1", "vuzix_z100"],
1468
+ action_category: "write",
1469
+ base_risk: "low",
1470
+ exfiltration_risk: false,
1471
+ reversible: true
1472
+ },
1473
+ // ── Location Domain ───────────────────────────────────────────────────
1474
+ {
1475
+ intent: "location_access",
1476
+ description: "Access current location data from the paired phone",
1477
+ sdk_method: "session.location.get()",
1478
+ permission: "LOCATION",
1479
+ domain: "location",
1480
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1481
+ action_category: "read",
1482
+ base_risk: "medium",
1483
+ exfiltration_risk: true,
1484
+ reversible: false
1485
+ },
1486
+ {
1487
+ intent: "location_continuous_sharing",
1488
+ description: "Start continuous location updates to the app server",
1489
+ sdk_method: "session.location.startContinuous()",
1490
+ permission: "LOCATION",
1491
+ domain: "location",
1492
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1493
+ action_category: "network",
1494
+ base_risk: "high",
1495
+ exfiltration_risk: true,
1496
+ reversible: true
1497
+ },
1498
+ // ── Calendar & Notifications ──────────────────────────────────────────
1499
+ {
1500
+ intent: "calendar_read",
1501
+ description: "Read calendar events from the paired phone",
1502
+ sdk_method: "session.calendar.getEvents()",
1503
+ permission: "CALENDAR",
1504
+ domain: "calendar",
1505
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1506
+ action_category: "read",
1507
+ base_risk: "low",
1508
+ exfiltration_risk: false,
1509
+ reversible: true
1510
+ },
1511
+ {
1512
+ intent: "notifications_read",
1513
+ description: "Read phone notifications",
1514
+ sdk_method: "session.notifications.getRecent()",
1515
+ permission: "READ_NOTIFICATIONS",
1516
+ domain: "notifications",
1517
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1518
+ action_category: "read",
1519
+ base_risk: "low",
1520
+ exfiltration_risk: false,
1521
+ reversible: true
1522
+ },
1523
+ // ── Audio Domain ──────────────────────────────────────────────────────
1524
+ {
1525
+ intent: "audio_play",
1526
+ description: "Play audio through the glasses speaker",
1527
+ sdk_method: "session.audio.play()",
1528
+ permission: "NONE",
1529
+ domain: "audio",
1530
+ supported_glasses: ["mentra_live"],
1531
+ action_category: "write",
1532
+ base_risk: "low",
1533
+ exfiltration_risk: false,
1534
+ reversible: true
1535
+ },
1536
+ // ── Session Domain ────────────────────────────────────────────────────
1537
+ {
1538
+ intent: "session_data_export",
1539
+ description: "Export session data to external storage or API",
1540
+ sdk_method: "session.export()",
1541
+ permission: "NONE",
1542
+ domain: "session",
1543
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1544
+ action_category: "network",
1545
+ base_risk: "high",
1546
+ exfiltration_risk: true,
1547
+ reversible: false
1548
+ },
1549
+ // ── Tool Call Domain ──────────────────────────────────────────────────
1550
+ {
1551
+ intent: "tool_call_execute",
1552
+ description: "Execute a custom tool call defined by the app via handleToolCall",
1553
+ sdk_method: "AppServer.handleToolCall()",
1554
+ permission: "NONE",
1555
+ domain: "tool_call",
1556
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1557
+ action_category: "other",
1558
+ base_risk: "medium",
1559
+ exfiltration_risk: false,
1560
+ reversible: false
1561
+ },
1562
+ // ── AI Data Flow Domain ─────────────────────────────────────────────────
1563
+ // These intents govern what user data apps send to their AI backends.
1564
+ // They operate at the app server layer (not the glasses hardware layer),
1565
+ // so they work on all glasses models and require no hardware permission.
1566
+ {
1567
+ intent: "ai_send_transcription",
1568
+ description: "Send user speech transcription to an external AI API for processing",
1569
+ sdk_method: "app_server.ai.sendTranscription()",
1570
+ permission: "NONE",
1571
+ domain: "ai_data",
1572
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1573
+ action_category: "network",
1574
+ base_risk: "medium",
1575
+ exfiltration_risk: true,
1576
+ reversible: false
1577
+ },
1578
+ {
1579
+ intent: "ai_send_image",
1580
+ description: "Send a camera-captured image to an external AI API for vision analysis",
1581
+ sdk_method: "app_server.ai.sendImage()",
1582
+ permission: "NONE",
1583
+ domain: "ai_data",
1584
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1585
+ action_category: "network",
1586
+ base_risk: "high",
1587
+ exfiltration_risk: true,
1588
+ reversible: false
1589
+ },
1590
+ {
1591
+ intent: "ai_send_location",
1592
+ description: "Send user location data to an external AI API for context-aware processing",
1593
+ sdk_method: "app_server.ai.sendLocation()",
1594
+ permission: "NONE",
1595
+ domain: "ai_data",
1596
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1597
+ action_category: "network",
1598
+ base_risk: "medium",
1599
+ exfiltration_risk: true,
1600
+ reversible: false
1601
+ },
1602
+ {
1603
+ intent: "ai_send_calendar",
1604
+ description: "Send user calendar data to an external AI API for scheduling assistance",
1605
+ sdk_method: "app_server.ai.sendCalendar()",
1606
+ permission: "NONE",
1607
+ domain: "ai_data",
1608
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1609
+ action_category: "network",
1610
+ base_risk: "medium",
1611
+ exfiltration_risk: true,
1612
+ reversible: false
1613
+ },
1614
+ {
1615
+ intent: "ai_send_notifications",
1616
+ description: "Send user notification data to an external AI API for summarization or triage",
1617
+ sdk_method: "app_server.ai.sendNotifications()",
1618
+ permission: "NONE",
1619
+ domain: "ai_data",
1620
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1621
+ action_category: "network",
1622
+ base_risk: "medium",
1623
+ exfiltration_risk: true,
1624
+ reversible: false
1625
+ },
1626
+ // ── AI Action Domain ──────────────────────────────────────────────────
1627
+ // These intents govern actions AI takes on behalf of the user.
1628
+ // Every action here must be shown on the glasses display before execution.
1629
+ {
1630
+ intent: "ai_auto_respond_message",
1631
+ description: "AI generates and sends a message (email, SMS, chat) on the user's behalf",
1632
+ sdk_method: "app_server.ai.sendMessage()",
1633
+ permission: "NONE",
1634
+ domain: "ai_action",
1635
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1636
+ action_category: "network",
1637
+ base_risk: "high",
1638
+ exfiltration_risk: true,
1639
+ reversible: false
1640
+ },
1641
+ {
1642
+ intent: "ai_auto_purchase",
1643
+ description: "AI initiates a financial transaction (purchase, subscription, tip) on the user's behalf",
1644
+ sdk_method: "app_server.ai.purchase()",
1645
+ permission: "NONE",
1646
+ domain: "ai_action",
1647
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1648
+ action_category: "network",
1649
+ base_risk: "critical",
1650
+ exfiltration_risk: true,
1651
+ reversible: false
1652
+ },
1653
+ {
1654
+ intent: "ai_auto_schedule",
1655
+ description: "AI creates, modifies, or cancels a calendar event on the user's behalf",
1656
+ sdk_method: "app_server.ai.schedule()",
1657
+ permission: "NONE",
1658
+ domain: "ai_action",
1659
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1660
+ action_category: "write",
1661
+ base_risk: "medium",
1662
+ exfiltration_risk: false,
1663
+ reversible: true
1664
+ },
1665
+ {
1666
+ intent: "ai_auto_setting_change",
1667
+ description: "AI changes a user setting or app configuration on the user's behalf",
1668
+ sdk_method: "app_server.ai.changeSetting()",
1669
+ permission: "NONE",
1670
+ domain: "ai_action",
1671
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1672
+ action_category: "write",
1673
+ base_risk: "medium",
1674
+ exfiltration_risk: false,
1675
+ reversible: true
1676
+ },
1677
+ {
1678
+ intent: "ai_retain_session_data",
1679
+ description: "AI or app retains user session data (transcriptions, images, conversation) beyond session end",
1680
+ sdk_method: "app_server.ai.retainData()",
1681
+ permission: "NONE",
1682
+ domain: "ai_data",
1683
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1684
+ action_category: "write",
1685
+ base_risk: "high",
1686
+ exfiltration_risk: true,
1687
+ reversible: false
1688
+ },
1689
+ {
1690
+ intent: "ai_share_with_third_party",
1691
+ description: "AI or app shares user data with a third-party service beyond the declared AI provider",
1692
+ sdk_method: "app_server.ai.shareExternal()",
1693
+ permission: "NONE",
1694
+ domain: "ai_data",
1695
+ supported_glasses: ["even_realities_g1", "mentra_live", "mentra_mach1", "vuzix_z100"],
1696
+ action_category: "network",
1697
+ base_risk: "critical",
1698
+ exfiltration_risk: true,
1699
+ reversible: false
1700
+ }
1701
+ ];
1702
+ var MENTRA_KNOWN_INTENTS = MENTRA_INTENT_TAXONOMY.map((d) => d.intent);
1703
+ var MENTRA_INTENT_MAP = new Map(MENTRA_INTENT_TAXONOMY.map((d) => [d.intent, d]));
1704
+ function getMentraIntent(intent) {
1705
+ return MENTRA_INTENT_MAP.get(intent);
1706
+ }
1707
+ function getIntentsByPermission(permission) {
1708
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.permission === permission);
1709
+ }
1710
+ function getIntentsByGlasses(model) {
1711
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.supported_glasses.includes(model));
1712
+ }
1713
+ function isIntentSupported(intent, model) {
1714
+ const def = MENTRA_INTENT_MAP.get(intent);
1715
+ return def ? def.supported_glasses.includes(model) : false;
1716
+ }
1717
+ function getHighRiskIntents() {
1718
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.base_risk === "high" || d.base_risk === "critical");
1719
+ }
1720
+ function getExfiltrationIntents() {
1721
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.exfiltration_risk);
1722
+ }
1723
+ function getAIDataIntents() {
1724
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.domain === "ai_data");
1725
+ }
1726
+ function getAIActionIntents() {
1727
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.domain === "ai_action");
1728
+ }
1729
+ function getAIIntents() {
1730
+ return MENTRA_INTENT_TAXONOMY.filter((d) => d.domain === "ai_data" || d.domain === "ai_action");
1731
+ }
1732
+ function isAIIntent(intent) {
1733
+ const def = MENTRA_INTENT_MAP.get(intent);
1734
+ return def ? def.domain === "ai_data" || def.domain === "ai_action" : false;
1735
+ }
1736
+
1737
+ // src/adapters/mentraos.ts
1738
+ var DEFAULT_USER_RULES = {
1739
+ aiDataPolicy: "declared_only",
1740
+ aiActionPolicy: "confirm_all",
1741
+ aiPurchasePolicy: "confirm_each",
1742
+ aiMessagingPolicy: "confirm_each",
1743
+ dataRetentionPolicy: "app_declared",
1744
+ maxAIProviders: 5
1745
+ };
1746
+ function evaluateUserRules(intent, rules, appContext) {
1747
+ const def = getMentraIntent(intent);
1748
+ if (!def) return null;
1749
+ if (def.domain === "ai_data" && intent !== "ai_retain_session_data") {
1750
+ if (rules.aiDataPolicy === "block_all") {
1751
+ return {
1752
+ verdict: {
1753
+ status: "BLOCK",
1754
+ ruleId: "user-rule-ai-data-block",
1755
+ reason: `User rules block all AI data sends. Intent: ${intent}`,
1756
+ evidence: makeEvidence("user-rule-ai-data-block")
1757
+ },
1758
+ reason: "User has blocked all AI data sends"
1759
+ };
1760
+ }
1761
+ if (rules.aiDataPolicy === "confirm_each") {
1762
+ return {
1763
+ verdict: {
1764
+ status: "PAUSE",
1765
+ ruleId: "user-rule-ai-data-confirm",
1766
+ reason: `User rules require confirmation for every AI data send. Intent: ${intent}`,
1767
+ evidence: makeEvidence("user-rule-ai-data-confirm")
1768
+ },
1769
+ reason: "User requires confirmation for each AI data send"
1770
+ };
1771
+ }
1772
+ if (!appContext.aiProviderDeclared) {
1773
+ return {
1774
+ verdict: {
1775
+ status: "BLOCK",
1776
+ ruleId: "user-rule-undeclared-provider",
1777
+ reason: `App "${appContext.appId}" has not declared its AI provider. User rules require declared providers only.`,
1778
+ evidence: makeEvidence("user-rule-undeclared-provider")
1779
+ },
1780
+ reason: "App has not declared its AI provider"
1781
+ };
1782
+ }
1783
+ }
1784
+ if (intent === "ai_retain_session_data") {
1785
+ if (rules.dataRetentionPolicy === "never") {
1786
+ return {
1787
+ verdict: {
1788
+ status: "BLOCK",
1789
+ ruleId: "user-rule-no-retention",
1790
+ reason: `User rules block all data retention. App "${appContext.appId}" cannot retain session data.`,
1791
+ evidence: makeEvidence("user-rule-no-retention")
1792
+ },
1793
+ reason: "User has blocked all data retention"
1794
+ };
1795
+ }
1796
+ if (!appContext.dataRetentionOptedIn) {
1797
+ return {
1798
+ verdict: {
1799
+ status: "BLOCK",
1800
+ ruleId: "user-rule-retention-no-optin",
1801
+ reason: `User has not opted in to data retention for app "${appContext.appId}".`,
1802
+ evidence: makeEvidence("user-rule-retention-no-optin")
1803
+ },
1804
+ reason: "User has not opted in to data retention for this app"
1805
+ };
1806
+ }
1807
+ }
1808
+ if (intent === "ai_auto_purchase") {
1809
+ if (rules.aiPurchasePolicy === "block_all") {
1810
+ return {
1811
+ verdict: {
1812
+ status: "BLOCK",
1813
+ ruleId: "user-rule-no-purchases",
1814
+ reason: "User rules block all AI-initiated purchases.",
1815
+ evidence: makeEvidence("user-rule-no-purchases")
1816
+ },
1817
+ reason: "User has blocked all AI purchases"
1818
+ };
1819
+ }
1820
+ return {
1821
+ verdict: {
1822
+ status: "PAUSE",
1823
+ ruleId: "user-rule-purchase-confirm",
1824
+ reason: `AI wants to make a purchase. User rules require per-transaction confirmation.`,
1825
+ evidence: makeEvidence("user-rule-purchase-confirm")
1826
+ },
1827
+ reason: "User requires per-transaction confirmation for AI purchases"
1828
+ };
1829
+ }
1830
+ if (intent === "ai_auto_respond_message") {
1831
+ if (rules.aiMessagingPolicy === "block_all") {
1832
+ return {
1833
+ verdict: {
1834
+ status: "BLOCK",
1835
+ ruleId: "user-rule-no-messaging",
1836
+ reason: "User rules block all AI-initiated messaging.",
1837
+ evidence: makeEvidence("user-rule-no-messaging")
1838
+ },
1839
+ reason: "User has blocked all AI messaging"
1840
+ };
1841
+ }
1842
+ return {
1843
+ verdict: {
1844
+ status: "PAUSE",
1845
+ ruleId: "user-rule-message-confirm",
1846
+ reason: `AI wants to send a message on your behalf. User rules require per-message confirmation.`,
1847
+ evidence: makeEvidence("user-rule-message-confirm")
1848
+ },
1849
+ reason: "User requires per-message confirmation for AI messaging"
1850
+ };
1851
+ }
1852
+ if (def.domain === "ai_action" && intent !== "ai_auto_purchase" && intent !== "ai_auto_respond_message") {
1853
+ if (rules.aiActionPolicy === "block_all") {
1854
+ return {
1855
+ verdict: {
1856
+ status: "BLOCK",
1857
+ ruleId: "user-rule-no-ai-actions",
1858
+ reason: `User rules block all AI auto-actions. Intent: ${intent}`,
1859
+ evidence: makeEvidence("user-rule-no-ai-actions")
1860
+ },
1861
+ reason: "User has blocked all AI auto-actions"
1862
+ };
1863
+ }
1864
+ if (rules.aiActionPolicy === "confirm_all") {
1865
+ return {
1866
+ verdict: {
1867
+ status: "PAUSE",
1868
+ ruleId: "user-rule-action-confirm",
1869
+ reason: `AI wants to take action: ${intent}. User rules require confirmation.`,
1870
+ evidence: makeEvidence("user-rule-action-confirm")
1871
+ },
1872
+ reason: "User requires confirmation for all AI actions"
1873
+ };
1874
+ }
1875
+ if (def.base_risk === "high" || def.base_risk === "critical") {
1876
+ return {
1877
+ verdict: {
1878
+ status: "PAUSE",
1879
+ ruleId: "user-rule-high-risk-confirm",
1880
+ reason: `AI wants to take high-risk action: ${intent}. User rules require confirmation for high-risk actions.`,
1881
+ evidence: makeEvidence("user-rule-high-risk-confirm")
1882
+ },
1883
+ reason: "User requires confirmation for high-risk AI actions"
1884
+ };
1885
+ }
1886
+ }
1887
+ if (intent === "ai_share_with_third_party") {
1888
+ return {
1889
+ verdict: {
1890
+ status: "PAUSE",
1891
+ ruleId: "user-rule-third-party-confirm",
1892
+ reason: `App wants to share your data with a third party beyond its declared AI provider. Confirmation required.`,
1893
+ evidence: makeEvidence("user-rule-third-party-confirm")
1894
+ },
1895
+ reason: "Third-party data sharing requires user confirmation"
1896
+ };
1897
+ }
1898
+ return null;
1899
+ }
1900
+ function makeEvidence(ruleId) {
1901
+ return {
1902
+ worldId: "mentraos-user-rules",
1903
+ worldName: "MentraOS User Rules",
1904
+ worldVersion: "1.0.0",
1905
+ evaluatedAt: Date.now(),
1906
+ invariantsSatisfied: 0,
1907
+ invariantsTotal: 0,
1908
+ guardsMatched: [ruleId],
1909
+ rulesMatched: [],
1910
+ enforcementLevel: "strict"
1911
+ };
1912
+ }
1913
+ var MentraGovernedExecutor = class {
1914
+ world;
1915
+ engineOptions;
1916
+ options;
1917
+ planState;
1918
+ planCallbacks;
1919
+ _userRules;
1920
+ _emergencyOverride = false;
1921
+ _emergencyActivatedAt = null;
1922
+ _spatialSession = null;
1923
+ constructor(world, options = {}, userRules = DEFAULT_USER_RULES) {
1924
+ this.world = world;
1925
+ this.options = options;
1926
+ this._userRules = userRules;
1927
+ this.engineOptions = buildEngineOptions(options, options.plan);
1928
+ this.planState = { activePlan: options.plan, engineOptions: this.engineOptions };
1929
+ this.planCallbacks = {
1930
+ onPlanProgress: options.onPlanProgress,
1931
+ onPlanComplete: options.onPlanComplete
1932
+ };
1933
+ }
1934
+ /** Get the current user rules */
1935
+ get userRules() {
1936
+ return this._userRules;
1937
+ }
1938
+ /** Update user rules at runtime (e.g., user changes preferences in phone app) */
1939
+ updateUserRules(rules) {
1940
+ this._userRules = { ...this._userRules, ...rules };
1941
+ }
1942
+ /**
1943
+ * Activate emergency override — user is king.
1944
+ *
1945
+ * Bypasses all NeuroVerse governance rules (user rules, platform rules).
1946
+ * Does NOT bypass MentraOS platform constraints (hardware capability,
1947
+ * declared permissions, session isolation). You can't override physics.
1948
+ *
1949
+ * Returns the timestamp of activation for audit trail.
1950
+ */
1951
+ activateEmergencyOverride() {
1952
+ this._emergencyOverride = true;
1953
+ this._emergencyActivatedAt = Date.now();
1954
+ this.engineOptions = { ...this.engineOptions, emergencyOverride: true };
1955
+ return this._emergencyActivatedAt;
1956
+ }
1957
+ /**
1958
+ * Deactivate emergency override — governance resumes.
1959
+ * Returns the duration the override was active (ms).
1960
+ */
1961
+ deactivateEmergencyOverride() {
1962
+ if (!this._emergencyOverride || !this._emergencyActivatedAt) {
1963
+ return 0;
1964
+ }
1965
+ const duration = Date.now() - this._emergencyActivatedAt;
1966
+ this._emergencyOverride = false;
1967
+ this._emergencyActivatedAt = null;
1968
+ this.engineOptions = { ...this.engineOptions, emergencyOverride: false };
1969
+ return duration;
1970
+ }
1971
+ /** Whether emergency override is currently active */
1972
+ get isEmergencyOverrideActive() {
1973
+ return this._emergencyOverride;
1974
+ }
1975
+ /** Timestamp when emergency override was activated, or null */
1976
+ get emergencyActivatedAt() {
1977
+ return this._emergencyActivatedAt;
1978
+ }
1979
+ // ── Spatial Governance (optional) ────────────────────────────────────────
1980
+ /**
1981
+ * Attach a spatial session to this executor.
1982
+ *
1983
+ * When attached, intents are evaluated against the spatial context
1984
+ * (zone rules + handshake rules) AFTER user rules but BEFORE
1985
+ * hardware and platform checks. This is Layer 1.5.
1986
+ *
1987
+ * Pass null to detach (e.g., when leaving a zone).
1988
+ */
1989
+ setSpatialSession(session) {
1990
+ this._spatialSession = session;
1991
+ }
1992
+ /** Whether a spatial session is currently active */
1993
+ get hasSpatialSession() {
1994
+ return this._spatialSession !== null;
1995
+ }
1996
+ /** Get the current spatial session description */
1997
+ get spatialDescription() {
1998
+ return this._spatialSession?.description ?? null;
1999
+ }
2000
+ /**
2001
+ * Evaluate an intent against user rules + platform world.
2002
+ *
2003
+ * Three-layer evaluation:
2004
+ * 0. Emergency override — if active, skip governance (layers 1 + 1.5 + 3),
2005
+ * but STILL enforce platform constraints (layer 2)
2006
+ * 1. User rules check — personal governance override, can BLOCK or PAUSE
2007
+ * 1.5. Spatial governance — zone + handshake rules (optional, temporary)
2008
+ * ↑ ONLY ACTIVE when a spatial session is attached
2009
+ * 2. Hardware capability check — validates glasses support
2010
+ * ↑ THIS IS A PLATFORM CONSTRAINT — never overridden
2011
+ * 3. Platform guard engine — full world rule evaluation
2012
+ */
2013
+ evaluate(intent, appContext) {
2014
+ const intentDef = getMentraIntent(intent);
2015
+ const glassesModel = appContext.glassesModel;
2016
+ if (!this._emergencyOverride) {
2017
+ const userRulesResult = evaluateUserRules(intent, this._userRules, appContext);
2018
+ if (userRulesResult) {
2019
+ const allowed2 = false;
2020
+ const requiresConfirmation2 = userRulesResult.verdict.status === "PAUSE";
2021
+ const result2 = {
2022
+ allowed: requiresConfirmation2 ? false : false,
2023
+ requiresConfirmation: requiresConfirmation2,
2024
+ verdict: userRulesResult.verdict,
2025
+ intentDef,
2026
+ userRulesResult: { reason: userRulesResult.reason },
2027
+ appContext,
2028
+ decidingLayer: "user_rules"
2029
+ };
2030
+ if (requiresConfirmation2) {
2031
+ this.options.onPause?.(result2);
2032
+ } else {
2033
+ this.options.onBlock?.(result2);
2034
+ }
2035
+ this.options.onEvaluate?.(result2);
2036
+ return result2;
2037
+ }
2038
+ }
2039
+ if (!this._emergencyOverride && this._spatialSession) {
2040
+ const spatialResult = this._spatialSession.evaluate(intent);
2041
+ if (!spatialResult.allowed && !spatialResult.requiresConfirmation) {
2042
+ const verdict2 = {
2043
+ status: "BLOCK",
2044
+ ruleId: "spatial-zone-rule",
2045
+ reason: spatialResult.reason,
2046
+ evidence: makeEvidence("spatial-zone-rule")
2047
+ };
2048
+ const result2 = {
2049
+ allowed: false,
2050
+ requiresConfirmation: false,
2051
+ verdict: verdict2,
2052
+ intentDef,
2053
+ appContext,
2054
+ decidingLayer: "spatial"
2055
+ };
2056
+ this.options.onBlock?.(result2);
2057
+ this.options.onEvaluate?.(result2);
2058
+ return result2;
2059
+ }
2060
+ if (spatialResult.requiresConfirmation) {
2061
+ const verdict2 = {
2062
+ status: "PAUSE",
2063
+ ruleId: "spatial-zone-rule",
2064
+ reason: spatialResult.reason,
2065
+ evidence: makeEvidence("spatial-zone-rule")
2066
+ };
2067
+ const result2 = {
2068
+ allowed: false,
2069
+ requiresConfirmation: true,
2070
+ verdict: verdict2,
2071
+ intentDef,
2072
+ appContext,
2073
+ decidingLayer: "spatial"
2074
+ };
2075
+ this.options.onPause?.(result2);
2076
+ this.options.onEvaluate?.(result2);
2077
+ return result2;
2078
+ }
2079
+ }
2080
+ if (intentDef && glassesModel && !intentDef.supported_glasses.includes(glassesModel)) {
2081
+ const verdict2 = {
2082
+ status: "BLOCK",
2083
+ ruleId: "hardware-capability",
2084
+ reason: `${intent} not supported on ${glassesModel} \u2014 requires: ${intentDef.supported_glasses.join(", ")}`,
2085
+ evidence: {
2086
+ worldId: this.world.world?.world_id ?? "unknown",
2087
+ worldName: this.world.world?.name ?? "unknown",
2088
+ worldVersion: this.world.world?.version ?? "unknown",
2089
+ evaluatedAt: Date.now(),
2090
+ invariantsSatisfied: 0,
2091
+ invariantsTotal: 0,
2092
+ guardsMatched: ["hardware-capability"],
2093
+ rulesMatched: [],
2094
+ enforcementLevel: "strict"
2095
+ }
2096
+ };
2097
+ const result2 = {
2098
+ allowed: false,
2099
+ requiresConfirmation: false,
2100
+ verdict: verdict2,
2101
+ intentDef,
2102
+ appContext,
2103
+ decidingLayer: "hardware"
2104
+ };
2105
+ this.options.onBlock?.(result2);
2106
+ this.options.onEvaluate?.(result2);
2107
+ return result2;
2108
+ }
2109
+ const event = {
2110
+ intent,
2111
+ tool: intentDef?.sdk_method ?? intent,
2112
+ scope: intentDef?.domain ?? "unknown",
2113
+ actionCategory: intentDef?.action_category,
2114
+ riskLevel: intentDef?.base_risk ?? "medium",
2115
+ irreversible: intentDef ? !intentDef.reversible : false,
2116
+ args: {
2117
+ app_id: appContext.appId,
2118
+ ai_provider_declared: appContext.aiProviderDeclared ? 1 : 0,
2119
+ ai_data_types_sent: appContext.aiDataTypesSent,
2120
+ ai_retention_opted_in: appContext.dataRetentionOptedIn ? 1 : 0,
2121
+ glasses_model: glassesModel ?? "unknown",
2122
+ is_ai_intent: isAIIntent(intent) ? 1 : 0
2123
+ }
2124
+ };
2125
+ const verdict = evaluateGuard(event, this.world, this.engineOptions);
2126
+ const allowed = verdict.status === "ALLOW" || verdict.status === "REWARD";
2127
+ const requiresConfirmation = verdict.status === "PAUSE";
2128
+ if (allowed) {
2129
+ trackPlanProgress(event, this.planState, this.planCallbacks);
2130
+ }
2131
+ const result = {
2132
+ allowed,
2133
+ requiresConfirmation,
2134
+ verdict,
2135
+ intentDef,
2136
+ appContext,
2137
+ decidingLayer: this._emergencyOverride ? "emergency_override" : "platform"
2138
+ };
2139
+ if (!allowed && !requiresConfirmation) {
2140
+ this.options.onBlock?.(result);
2141
+ }
2142
+ if (requiresConfirmation) {
2143
+ this.options.onPause?.(result);
2144
+ }
2145
+ this.options.onEvaluate?.(result);
2146
+ return result;
2147
+ }
2148
+ /** Get all known intents for this adapter */
2149
+ get knownIntents() {
2150
+ return MENTRA_KNOWN_INTENTS;
2151
+ }
2152
+ };
2153
+ async function createMentraGovernedExecutor(worldPath, options = {}, userRules = DEFAULT_USER_RULES) {
2154
+ const world = await loadWorld(worldPath);
2155
+ return new MentraGovernedExecutor(world, options, userRules);
2156
+ }
2157
+ function createMentraGovernedExecutorFromWorld(world, options = {}, userRules = DEFAULT_USER_RULES) {
2158
+ return new MentraGovernedExecutor(world, options, userRules);
2159
+ }
2160
+ // Annotate the CommonJS export names for ESM import in node:
2161
+ 0 && (module.exports = {
2162
+ DEFAULT_USER_RULES,
2163
+ GovernanceBlockedError,
2164
+ MENTRA_INTENT_MAP,
2165
+ MENTRA_INTENT_TAXONOMY,
2166
+ MENTRA_KNOWN_INTENTS,
2167
+ MentraGovernedExecutor,
2168
+ createMentraGovernedExecutor,
2169
+ createMentraGovernedExecutorFromWorld,
2170
+ evaluateUserRules,
2171
+ getAIActionIntents,
2172
+ getAIDataIntents,
2173
+ getAIIntents,
2174
+ getExfiltrationIntents,
2175
+ getHighRiskIntents,
2176
+ getIntentsByGlasses,
2177
+ getIntentsByPermission,
2178
+ getMentraIntent,
2179
+ isAIIntent,
2180
+ isIntentSupported
2181
+ });