@neuroverseos/governance 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/autoresearch.d.cts +2 -1
- package/dist/adapters/autoresearch.d.ts +2 -1
- package/dist/adapters/autoresearch.js +2 -2
- package/dist/adapters/deep-agents.d.cts +3 -2
- package/dist/adapters/deep-agents.d.ts +3 -2
- package/dist/adapters/deep-agents.js +2 -2
- package/dist/adapters/express.d.cts +2 -1
- package/dist/adapters/express.d.ts +2 -1
- package/dist/adapters/express.js +2 -2
- package/dist/adapters/github.cjs +1697 -0
- package/dist/adapters/github.d.cts +225 -0
- package/dist/adapters/github.d.ts +225 -0
- package/dist/adapters/github.js +27 -0
- package/dist/adapters/index.cjs +66 -1
- package/dist/adapters/index.d.cts +4 -278
- package/dist/adapters/index.d.ts +4 -278
- package/dist/adapters/index.js +18 -18
- package/dist/adapters/langchain.d.cts +3 -2
- package/dist/adapters/langchain.d.ts +3 -2
- package/dist/adapters/langchain.js +2 -2
- package/dist/adapters/mentraos.cjs +2181 -0
- package/dist/adapters/mentraos.d.cts +319 -0
- package/dist/adapters/mentraos.d.ts +319 -0
- package/dist/{mentraos-YFS7FMJH.js → adapters/mentraos.js} +6 -6
- package/dist/adapters/openai.d.cts +3 -2
- package/dist/adapters/openai.d.ts +3 -2
- package/dist/adapters/openai.js +2 -2
- package/dist/adapters/openclaw.d.cts +3 -2
- package/dist/adapters/openclaw.d.ts +3 -2
- package/dist/adapters/openclaw.js +2 -2
- package/dist/{add-LYHDZ5RL.js → add-XSANI3FK.js} +1 -1
- package/dist/bootstrap-contract-DcV6t-8M.d.cts +216 -0
- package/dist/bootstrap-contract-DcV6t-8M.d.ts +216 -0
- package/dist/{build-THUEYMVT.js → build-EGBGZFIJ.js} +5 -5
- package/dist/{chunk-MFKHTE5R.js → chunk-3AYKQHYI.js} +1 -1
- package/dist/chunk-3S5AD4AB.js +421 -0
- package/dist/{chunk-V4FZHJQX.js → chunk-A7SHG75T.js} +1 -1
- package/dist/{chunk-JKGPSFGH.js → chunk-AV7XJJWK.js} +1 -1
- package/dist/{chunk-Y6WXAPKY.js → chunk-DA5MHFRR.js} +1 -1
- package/dist/{chunk-7D7PZLB7.js → chunk-FS2UUJJO.js} +3 -3
- package/dist/{chunk-TD5GKIHP.js → chunk-FVOGUCB6.js} +1 -1
- package/dist/{chunk-APU4OZIP.js → chunk-GTPV2XGO.js} +67 -2
- package/dist/{chunk-BXLTEUS4.js → chunk-I4RTIMLX.js} +2 -2
- package/dist/{chunk-5JUZ4HL7.js → chunk-J2IZBHXJ.js} +3 -3
- package/dist/{chunk-YNYCQECH.js → chunk-QMVQ6KPL.js} +1 -1
- package/dist/{chunk-25XHSTPT.js → chunk-RDA7ISWC.js} +1 -1
- package/dist/{chunk-DWHUZUEY.js → chunk-YJ34R5NB.js} +1 -1
- package/dist/{chunk-UTH7OXTM.js → chunk-ZEIT2QLM.js} +3 -3
- package/dist/cli/neuroverse.cjs +580 -28
- package/dist/cli/neuroverse.js +21 -21
- package/dist/cli/plan.js +2 -2
- package/dist/cli/run.js +2 -2
- package/dist/{demo-66MMJTEH.js → demo-6OQYWRR6.js} +3 -3
- package/dist/{derive-5LOMN7GO.js → derive-7Y7YWVLU.js} +4 -4
- package/dist/{doctor-WIO4FLA3.js → doctor-EC5OYTI3.js} +3 -2
- package/dist/engine/bootstrap-emitter.cjs +241 -0
- package/dist/engine/bootstrap-emitter.d.cts +27 -0
- package/dist/engine/bootstrap-emitter.d.ts +27 -0
- package/dist/{bootstrap-emitter-GIMOJFOC.js → engine/bootstrap-emitter.js} +2 -2
- package/dist/engine/bootstrap-parser.cjs +560 -0
- package/dist/engine/bootstrap-parser.d.cts +96 -0
- package/dist/engine/bootstrap-parser.d.ts +96 -0
- package/dist/{bootstrap-parser-LBLGVEMU.js → engine/bootstrap-parser.js} +2 -2
- package/dist/engine/guard-engine.cjs +1116 -0
- package/dist/engine/guard-engine.d.cts +60 -0
- package/dist/engine/guard-engine.d.ts +60 -0
- package/dist/{guard-engine-N7TUIUU7.js → engine/guard-engine.js} +3 -3
- package/dist/engine/simulate-engine.cjs +390 -0
- package/dist/engine/simulate-engine.d.cts +105 -0
- package/dist/engine/simulate-engine.d.ts +105 -0
- package/dist/engine/simulate-engine.js +9 -0
- package/dist/{equity-penalties-WWC7UDQD.js → equity-penalties-NVBAB5WL.js} +2 -2
- package/dist/{explain-MUSGDT67.js → explain-HDFN4ION.js} +1 -1
- package/dist/{guard-W3BMQPBJ.js → guard-6KSCWT2W.js} +2 -2
- package/dist/{guard-contract-CLBbTGK_.d.ts → guard-contract-ddiIPlOg.d.cts} +2 -369
- package/dist/{guard-contract-CLBbTGK_.d.cts → guard-contract-q6HJAq3Q.d.ts} +2 -369
- package/dist/{improve-PJDAWW4Q.js → improve-2PWGGO5B.js} +3 -3
- package/dist/index.cjs +452 -0
- package/dist/index.d.cts +12 -492
- package/dist/index.d.ts +12 -492
- package/dist/index.js +75 -54
- package/dist/{lens-IP6GIZ2Q.js → lens-MHMUDCMQ.js} +92 -25
- package/dist/{mcp-server-OG3PPVD2.js → mcp-server-TNIWZ7B5.js} +2 -2
- package/dist/{playground-4BK2XQ47.js → playground-3FLDGBET.js} +2 -2
- package/dist/{redteam-BRZALBPP.js → redteam-HV6LMKEH.js} +2 -2
- package/dist/{session-SGRUT2UH.js → session-XZP2754M.js} +2 -2
- package/dist/{shared-CwGpPheR.d.ts → shared-DAzdfWtU.d.ts} +1 -1
- package/dist/{shared-BGzmYP5g.d.cts → shared-PpalGKxc.d.cts} +1 -1
- package/dist/{simulate-FGXKIH7V.js → simulate-VT437EEL.js} +2 -2
- package/dist/spatial/index.cjs +682 -0
- package/dist/spatial/index.d.cts +517 -0
- package/dist/spatial/index.d.ts +517 -0
- package/dist/spatial/index.js +633 -0
- package/dist/{test-PT44BSYG.js → test-4WTX6RKQ.js} +2 -2
- package/dist/types.cjs +18 -0
- package/dist/types.d.cts +370 -0
- package/dist/types.d.ts +370 -0
- package/dist/types.js +0 -0
- package/dist/{validate-Q5O5TGLT.js → validate-M52DX22Y.js} +1 -1
- package/dist/{world-V52ZMH26.js → world-O4HTQPDP.js} +1 -1
- package/dist/{world-loader-C4D3VPP3.js → world-loader-YTYFOP7D.js} +1 -1
- package/dist/worlds/mentraos-spatial.nv-world.md +68 -0
- package/package.json +52 -3
- package/dist/{behavioral-SPWPGYXL.js → behavioral-SLW7ALEK.js} +3 -3
- package/dist/{bootstrap-IP5QMC3Q.js → bootstrap-2OW5ZLBL.js} +3 -3
- package/dist/{chunk-7QIAF377.js → chunk-CYDMUJVZ.js} +0 -0
- package/dist/{chunk-QZ666FCV.js → chunk-FHXXD2TI.js} +6 -6
- package/dist/{configure-ai-5MP5DWTT.js → configure-ai-LL3VAPQW.js} +3 -3
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spatial Governance — Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* This module defines the future of AI governance on smart glasses:
|
|
5
|
+
* location-aware, multi-user, consent-based, and temporary.
|
|
6
|
+
*
|
|
7
|
+
* The core insight: when AI lives on your face, governance can't be
|
|
8
|
+
* static. The rules that apply at home are different from the rules
|
|
9
|
+
* at a hospital. The rules that apply when you're alone are different
|
|
10
|
+
* from when you're in a shared AR space with three other people.
|
|
11
|
+
*
|
|
12
|
+
* Key concepts:
|
|
13
|
+
*
|
|
14
|
+
* Zone — A physical or spatial location that publishes governance rules.
|
|
15
|
+
* A coffee shop, a hospital, a concert venue, an office.
|
|
16
|
+
* Zones are discovered via Auki spatial anchors, BLE beacons,
|
|
17
|
+
* geofence, or manual opt-in.
|
|
18
|
+
*
|
|
19
|
+
* ZoneRules — The governance rules a zone publishes. "In this space,
|
|
20
|
+
* no recording. In this space, no AI recommendations.
|
|
21
|
+
* In this space, PHI stays in-network."
|
|
22
|
+
*
|
|
23
|
+
* OptIn — The user's decision to accept a zone's rules. Always
|
|
24
|
+
* explicit. Never forced. You can refuse — but the zone
|
|
25
|
+
* may refuse you entry (e.g., hospital requiring no recording).
|
|
26
|
+
*
|
|
27
|
+
* Handshake — When multiple AR-enabled people are in the same space,
|
|
28
|
+
* their governance layers negotiate. The result is a
|
|
29
|
+
* shared governance context where "most restrictive wins."
|
|
30
|
+
*
|
|
31
|
+
* Session — A spatial governance session. Begins when you enter a zone
|
|
32
|
+
* or join a handshake. Ends when you leave. Rules are
|
|
33
|
+
* temporary — they dissolve when the session ends.
|
|
34
|
+
*
|
|
35
|
+
* Architecture:
|
|
36
|
+
*
|
|
37
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
38
|
+
* │ Governance Stack (top wins) │
|
|
39
|
+
* ├─────────────────────────────────────────────────────────────┤
|
|
40
|
+
* │ 1. User Rules — Personal, permanent, cross-app │
|
|
41
|
+
* │ 2. Spatial Handshake — Multi-user, most-restrictive-wins │
|
|
42
|
+
* │ 3. Zone Rules — Location-specific, temporary │
|
|
43
|
+
* │ 4. Platform World — MentraOS hardware + safety │
|
|
44
|
+
* │ 5. App World — App-specific rules │
|
|
45
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
46
|
+
*
|
|
47
|
+
* User rules ALWAYS win. A zone cannot relax your personal rules.
|
|
48
|
+
* A zone CAN tighten them. A handshake applies the union of all
|
|
49
|
+
* participants' restrictions.
|
|
50
|
+
*
|
|
51
|
+
* This module exists for the future. It works today but doesn't
|
|
52
|
+
* require spatial hardware. When Auki + MentraOS go spatial,
|
|
53
|
+
* this is ready.
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* A spatial zone — a physical or virtual location that publishes governance rules.
|
|
57
|
+
*
|
|
58
|
+
* Zones are discovered, not hardcoded. The discovery mechanism depends on
|
|
59
|
+
* the available technology:
|
|
60
|
+
* - Auki spatial anchors (AR-native, precise)
|
|
61
|
+
* - BLE beacons (indoor, range-limited)
|
|
62
|
+
* - Geofence (GPS, coarse)
|
|
63
|
+
* - QR code / NFC tap (manual opt-in)
|
|
64
|
+
* - Manual selection (user picks from nearby zones)
|
|
65
|
+
*/
|
|
66
|
+
interface Zone {
|
|
67
|
+
/** Unique zone identifier */
|
|
68
|
+
zoneId: string;
|
|
69
|
+
/** Human-readable name ("Blue Bottle Coffee — Hayes Valley") */
|
|
70
|
+
name: string;
|
|
71
|
+
/** Who publishes this zone's rules */
|
|
72
|
+
publisher: ZonePublisher;
|
|
73
|
+
/** The governance rules this zone enforces */
|
|
74
|
+
rules: ZoneRules;
|
|
75
|
+
/** How this zone was discovered */
|
|
76
|
+
discovery: ZoneDiscovery;
|
|
77
|
+
/** Zone type — affects default rule templates */
|
|
78
|
+
type: ZoneType;
|
|
79
|
+
/** Whether this zone requires opt-in to enter (e.g., hospital) */
|
|
80
|
+
requiresOptIn: boolean;
|
|
81
|
+
/** Human-readable explanation of why these rules exist */
|
|
82
|
+
rationale: string;
|
|
83
|
+
/** Zone boundary definition (optional — for geofence/spatial) */
|
|
84
|
+
boundary?: ZoneBoundary;
|
|
85
|
+
/** When this zone's rules were last updated */
|
|
86
|
+
rulesUpdatedAt: number;
|
|
87
|
+
/** Zone version — incremented when rules change */
|
|
88
|
+
version: string;
|
|
89
|
+
}
|
|
90
|
+
interface ZonePublisher {
|
|
91
|
+
/** Publisher name ("Blue Bottle Coffee", "UCSF Medical Center") */
|
|
92
|
+
name: string;
|
|
93
|
+
/** Publisher type */
|
|
94
|
+
type: 'business' | 'institution' | 'government' | 'community' | 'individual';
|
|
95
|
+
/** Verified by MentraOS / NeuroverseOS (signed zone) */
|
|
96
|
+
verified: boolean;
|
|
97
|
+
}
|
|
98
|
+
type ZoneType = 'public_space' | 'retail' | 'hospitality' | 'healthcare' | 'workplace' | 'education' | 'entertainment' | 'transit' | 'residential' | 'religious' | 'government' | 'custom';
|
|
99
|
+
type ZoneDiscovery = {
|
|
100
|
+
method: 'auki_anchor';
|
|
101
|
+
anchorId: string;
|
|
102
|
+
confidence: number;
|
|
103
|
+
} | {
|
|
104
|
+
method: 'ble_beacon';
|
|
105
|
+
beaconId: string;
|
|
106
|
+
rssi: number;
|
|
107
|
+
} | {
|
|
108
|
+
method: 'geofence';
|
|
109
|
+
lat: number;
|
|
110
|
+
lng: number;
|
|
111
|
+
radiusMeters: number;
|
|
112
|
+
} | {
|
|
113
|
+
method: 'qr_code';
|
|
114
|
+
payload: string;
|
|
115
|
+
} | {
|
|
116
|
+
method: 'nfc_tap';
|
|
117
|
+
tagId: string;
|
|
118
|
+
} | {
|
|
119
|
+
method: 'manual';
|
|
120
|
+
selectedAt: number;
|
|
121
|
+
};
|
|
122
|
+
interface ZoneBoundary {
|
|
123
|
+
/** Boundary type */
|
|
124
|
+
type: 'radius' | 'polygon' | 'spatial_volume';
|
|
125
|
+
/** For radius: center point + radius in meters */
|
|
126
|
+
center?: {
|
|
127
|
+
lat: number;
|
|
128
|
+
lng: number;
|
|
129
|
+
altitude?: number;
|
|
130
|
+
};
|
|
131
|
+
radiusMeters?: number;
|
|
132
|
+
/** For polygon: ordered list of points */
|
|
133
|
+
polygon?: Array<{
|
|
134
|
+
lat: number;
|
|
135
|
+
lng: number;
|
|
136
|
+
}>;
|
|
137
|
+
/** For spatial_volume: Auki spatial anchor + dimensions */
|
|
138
|
+
spatialAnchor?: {
|
|
139
|
+
anchorId: string;
|
|
140
|
+
widthM: number;
|
|
141
|
+
heightM: number;
|
|
142
|
+
depthM: number;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The governance rules a zone publishes.
|
|
147
|
+
*
|
|
148
|
+
* These are not suggestions — they're constraints that apply when you
|
|
149
|
+
* opt into the zone. But they can ONLY tighten, never relax. If your
|
|
150
|
+
* personal rules already block recording, a zone that allows recording
|
|
151
|
+
* doesn't change anything for you.
|
|
152
|
+
*/
|
|
153
|
+
interface ZoneRules {
|
|
154
|
+
/** Camera policy in this zone */
|
|
155
|
+
camera: 'allowed' | 'confirm_each' | 'blocked';
|
|
156
|
+
/** Microphone / recording policy */
|
|
157
|
+
microphone: 'allowed' | 'confirm_each' | 'blocked';
|
|
158
|
+
/** AI data send policy (sending captured data to AI providers) */
|
|
159
|
+
aiDataSend: 'allowed' | 'declared_only' | 'confirm_each' | 'blocked';
|
|
160
|
+
/** AI action policy (AI taking actions on user's behalf) */
|
|
161
|
+
aiActions: 'allowed' | 'confirm_all' | 'blocked';
|
|
162
|
+
/** AI recommendations / suggestions policy */
|
|
163
|
+
aiRecommendations: 'allowed' | 'non_commercial' | 'blocked';
|
|
164
|
+
/** Location sharing policy */
|
|
165
|
+
locationSharing: 'allowed' | 'confirm_each' | 'blocked';
|
|
166
|
+
/** Display behavior — can AI overlay content in this space? */
|
|
167
|
+
aiOverlay: 'allowed' | 'non_obstructive' | 'blocked';
|
|
168
|
+
/** Data retention — can apps retain data captured in this zone? */
|
|
169
|
+
dataRetention: 'allowed' | 'session_only' | 'blocked';
|
|
170
|
+
/** Commercial behavior — can AI suggest purchases, compare prices? */
|
|
171
|
+
commercialAI: 'allowed' | 'blocked';
|
|
172
|
+
/** Bystander protection — are there non-consenting people present? */
|
|
173
|
+
bystanderProtection: 'standard' | 'elevated' | 'strict';
|
|
174
|
+
/** Custom constraints (zone-specific) */
|
|
175
|
+
custom?: ZoneCustomRule[];
|
|
176
|
+
}
|
|
177
|
+
interface ZoneCustomRule {
|
|
178
|
+
/** Rule identifier */
|
|
179
|
+
id: string;
|
|
180
|
+
/** Human-readable description */
|
|
181
|
+
description: string;
|
|
182
|
+
/** What intent this blocks/modifies */
|
|
183
|
+
targetIntent: string;
|
|
184
|
+
/** What happens */
|
|
185
|
+
effect: 'block' | 'confirm' | 'modify';
|
|
186
|
+
/** Why this rule exists */
|
|
187
|
+
rationale: string;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* A user's opt-in decision for a zone.
|
|
191
|
+
*
|
|
192
|
+
* Opt-in is ALWAYS explicit. The glasses show the zone's rules,
|
|
193
|
+
* the user taps to accept or decline. If they decline, they can
|
|
194
|
+
* still be in the physical space — but the zone's rules don't apply
|
|
195
|
+
* (and the zone may display "AI recording not permitted" signs).
|
|
196
|
+
*/
|
|
197
|
+
interface ZoneOptIn {
|
|
198
|
+
/** The zone being opted into */
|
|
199
|
+
zoneId: string;
|
|
200
|
+
/** When the user opted in */
|
|
201
|
+
optedInAt: number;
|
|
202
|
+
/** How the user opted in */
|
|
203
|
+
method: 'tap_confirm' | 'voice_confirm' | 'auto_recognized';
|
|
204
|
+
/** Which rules the user accepted */
|
|
205
|
+
acceptedRules: ZoneRules;
|
|
206
|
+
/** Whether the user made any personal overrides to zone rules */
|
|
207
|
+
userOverrides: Partial<ZoneRules>;
|
|
208
|
+
/** The effective rules (zone rules + user overrides, most restrictive wins) */
|
|
209
|
+
effectiveRules: ZoneRules;
|
|
210
|
+
/** Session identifier — links to the spatial session */
|
|
211
|
+
sessionId: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A spatial handshake — multi-user governance negotiation.
|
|
215
|
+
*
|
|
216
|
+
* When multiple people wearing AR glasses are in the same space,
|
|
217
|
+
* their governance layers need to compose. The handshake protocol:
|
|
218
|
+
*
|
|
219
|
+
* 1. Discovery — glasses detect nearby participants (Auki, BLE, etc.)
|
|
220
|
+
* 2. Announce — each participant shares their governance requirements
|
|
221
|
+
* (NOT their personal data — just their constraints)
|
|
222
|
+
* 3. Negotiate — the system computes the most restrictive union
|
|
223
|
+
* 4. Apply — all participants operate under the shared constraints
|
|
224
|
+
* 5. Dissolve — when someone leaves, the handshake recomputes
|
|
225
|
+
*
|
|
226
|
+
* The "most restrictive wins" invariant is absolute:
|
|
227
|
+
* - If ONE person blocks recording, NO ONE can record
|
|
228
|
+
* - If ONE person requires AI confirmation, EVERYONE confirms
|
|
229
|
+
* - If ONE person blocks AI recommendations, NO ONE gets them
|
|
230
|
+
*
|
|
231
|
+
* This protects the most privacy-conscious person in any shared space.
|
|
232
|
+
*/
|
|
233
|
+
interface SpatialHandshake {
|
|
234
|
+
/** Unique handshake identifier */
|
|
235
|
+
handshakeId: string;
|
|
236
|
+
/** Participants in the handshake */
|
|
237
|
+
participants: HandshakeParticipant[];
|
|
238
|
+
/** The negotiated governance rules (most restrictive union) */
|
|
239
|
+
negotiatedRules: ZoneRules;
|
|
240
|
+
/** The zone this handshake is happening in (if any) */
|
|
241
|
+
zoneId?: string;
|
|
242
|
+
/** When the handshake was created */
|
|
243
|
+
createdAt: number;
|
|
244
|
+
/** When the handshake was last re-negotiated */
|
|
245
|
+
lastNegotiatedAt: number;
|
|
246
|
+
/** Handshake state */
|
|
247
|
+
state: 'negotiating' | 'active' | 'dissolved';
|
|
248
|
+
}
|
|
249
|
+
interface HandshakeParticipant {
|
|
250
|
+
/** Participant identifier (anonymous — not their real identity) */
|
|
251
|
+
participantId: string;
|
|
252
|
+
/** What this participant shares (their governance requirements) */
|
|
253
|
+
publishedConstraints: ParticipantConstraints;
|
|
254
|
+
/** When they joined the handshake */
|
|
255
|
+
joinedAt: number;
|
|
256
|
+
/** Whether they've acknowledged the negotiated rules */
|
|
257
|
+
acknowledged: boolean;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* What a participant shares during handshake negotiation.
|
|
261
|
+
*
|
|
262
|
+
* This is NOT personal data. It's governance metadata.
|
|
263
|
+
* "I require no recording" is a constraint, not an identity.
|
|
264
|
+
*/
|
|
265
|
+
interface ParticipantConstraints {
|
|
266
|
+
/** This participant's camera policy (their minimum requirement) */
|
|
267
|
+
cameraMinimum: 'allowed' | 'confirm_each' | 'blocked';
|
|
268
|
+
/** This participant's microphone policy */
|
|
269
|
+
microphoneMinimum: 'allowed' | 'confirm_each' | 'blocked';
|
|
270
|
+
/** This participant's AI data send policy */
|
|
271
|
+
aiDataSendMinimum: 'allowed' | 'declared_only' | 'confirm_each' | 'blocked';
|
|
272
|
+
/** This participant's AI recommendation policy */
|
|
273
|
+
aiRecommendationsMinimum: 'allowed' | 'non_commercial' | 'blocked';
|
|
274
|
+
/** This participant's data retention policy */
|
|
275
|
+
dataRetentionMinimum: 'allowed' | 'session_only' | 'blocked';
|
|
276
|
+
/** This participant's bystander protection level */
|
|
277
|
+
bystanderProtectionMinimum: 'standard' | 'elevated' | 'strict';
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* A spatial governance session.
|
|
281
|
+
*
|
|
282
|
+
* Begins when you enter a zone or join a handshake.
|
|
283
|
+
* Ends when you leave. Rules are temporary.
|
|
284
|
+
*
|
|
285
|
+
* This is the runtime state. It holds the effective governance
|
|
286
|
+
* context that the guard engine evaluates against.
|
|
287
|
+
*/
|
|
288
|
+
interface SpatialSession {
|
|
289
|
+
/** Session identifier */
|
|
290
|
+
sessionId: string;
|
|
291
|
+
/** Active zone (if in one) */
|
|
292
|
+
zone?: Zone;
|
|
293
|
+
/** Active opt-in (if opted into a zone) */
|
|
294
|
+
optIn?: ZoneOptIn;
|
|
295
|
+
/** Active handshake (if in a multi-user context) */
|
|
296
|
+
handshake?: SpatialHandshake;
|
|
297
|
+
/** The effective spatial rules (zone + handshake + user, most restrictive wins) */
|
|
298
|
+
effectiveRules: ZoneRules;
|
|
299
|
+
/** Session state */
|
|
300
|
+
state: 'discovering' | 'opted_in' | 'handshake_active' | 'active' | 'ended';
|
|
301
|
+
/** When this session started */
|
|
302
|
+
startedAt: number;
|
|
303
|
+
/** When this session ended (null if active) */
|
|
304
|
+
endedAt: number | null;
|
|
305
|
+
/** Audit trail of governance events during this session */
|
|
306
|
+
events: SpatialEvent[];
|
|
307
|
+
}
|
|
308
|
+
type SpatialEvent = {
|
|
309
|
+
type: 'zone_discovered';
|
|
310
|
+
zone: Zone;
|
|
311
|
+
timestamp: number;
|
|
312
|
+
} | {
|
|
313
|
+
type: 'zone_opted_in';
|
|
314
|
+
zoneId: string;
|
|
315
|
+
timestamp: number;
|
|
316
|
+
} | {
|
|
317
|
+
type: 'zone_declined';
|
|
318
|
+
zoneId: string;
|
|
319
|
+
reason: string;
|
|
320
|
+
timestamp: number;
|
|
321
|
+
} | {
|
|
322
|
+
type: 'zone_exited';
|
|
323
|
+
zoneId: string;
|
|
324
|
+
timestamp: number;
|
|
325
|
+
} | {
|
|
326
|
+
type: 'handshake_started';
|
|
327
|
+
handshakeId: string;
|
|
328
|
+
participantCount: number;
|
|
329
|
+
timestamp: number;
|
|
330
|
+
} | {
|
|
331
|
+
type: 'handshake_participant_joined';
|
|
332
|
+
handshakeId: string;
|
|
333
|
+
participantId: string;
|
|
334
|
+
timestamp: number;
|
|
335
|
+
} | {
|
|
336
|
+
type: 'handshake_participant_left';
|
|
337
|
+
handshakeId: string;
|
|
338
|
+
participantId: string;
|
|
339
|
+
timestamp: number;
|
|
340
|
+
} | {
|
|
341
|
+
type: 'handshake_negotiated';
|
|
342
|
+
handshakeId: string;
|
|
343
|
+
timestamp: number;
|
|
344
|
+
} | {
|
|
345
|
+
type: 'handshake_dissolved';
|
|
346
|
+
handshakeId: string;
|
|
347
|
+
timestamp: number;
|
|
348
|
+
} | {
|
|
349
|
+
type: 'rule_tightened';
|
|
350
|
+
rule: string;
|
|
351
|
+
from: string;
|
|
352
|
+
to: string;
|
|
353
|
+
source: string;
|
|
354
|
+
timestamp: number;
|
|
355
|
+
} | {
|
|
356
|
+
type: 'intent_blocked_by_zone';
|
|
357
|
+
intent: string;
|
|
358
|
+
zoneId: string;
|
|
359
|
+
timestamp: number;
|
|
360
|
+
} | {
|
|
361
|
+
type: 'intent_blocked_by_handshake';
|
|
362
|
+
intent: string;
|
|
363
|
+
handshakeId: string;
|
|
364
|
+
timestamp: number;
|
|
365
|
+
};
|
|
366
|
+
/** Default zone rules — permissive baseline (zones tighten, never relax) */
|
|
367
|
+
declare const DEFAULT_ZONE_RULES: ZoneRules;
|
|
368
|
+
/** Default participant constraints — fully permissive (participant tightens) */
|
|
369
|
+
declare const DEFAULT_PARTICIPANT_CONSTRAINTS: ParticipantConstraints;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Spatial Governance Engine
|
|
373
|
+
*
|
|
374
|
+
* The runtime engine for location-aware, multi-user governance.
|
|
375
|
+
*
|
|
376
|
+
* Core operations:
|
|
377
|
+
*
|
|
378
|
+
* discoverZone() — A zone is detected nearby (Auki anchor, BLE, etc.)
|
|
379
|
+
* optInToZone() — User accepts the zone's rules
|
|
380
|
+
* exitZone() — User leaves the zone, rules dissolve
|
|
381
|
+
*
|
|
382
|
+
* startHandshake() — Begin multi-user governance negotiation
|
|
383
|
+
* joinHandshake() — Another participant enters the shared space
|
|
384
|
+
* leaveHandshake() — Participant exits, handshake recomputes
|
|
385
|
+
*
|
|
386
|
+
* evaluateSpatial() — Check an intent against the current spatial context
|
|
387
|
+
* resolveEffective() — Compute the most restrictive rules from all layers
|
|
388
|
+
*
|
|
389
|
+
* The "most restrictive wins" invariant:
|
|
390
|
+
* When multiple governance layers overlap (user rules, zone rules,
|
|
391
|
+
* handshake rules), the MOST restrictive value for each field wins.
|
|
392
|
+
* This means:
|
|
393
|
+
* - 'blocked' beats 'confirm_each' beats 'declared_only' beats 'allowed'
|
|
394
|
+
* - 'strict' beats 'elevated' beats 'standard'
|
|
395
|
+
* - A zone can tighten your rules, never relax them
|
|
396
|
+
* - A handshake participant can tighten the group, never relax it
|
|
397
|
+
*/
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Merge two ZoneRules, taking the most restrictive value for each field.
|
|
401
|
+
* This is the core of "most restrictive wins."
|
|
402
|
+
*/
|
|
403
|
+
declare function mergeRules(a: ZoneRules, b: ZoneRules): ZoneRules;
|
|
404
|
+
/**
|
|
405
|
+
* Convert participant constraints to ZoneRules format for merging.
|
|
406
|
+
*/
|
|
407
|
+
declare function constraintsToRules(c: ParticipantConstraints): ZoneRules;
|
|
408
|
+
/**
|
|
409
|
+
* Create an opt-in for a zone.
|
|
410
|
+
*
|
|
411
|
+
* The effective rules are computed by merging the zone's rules
|
|
412
|
+
* with any user overrides (most restrictive wins).
|
|
413
|
+
*/
|
|
414
|
+
declare function createOptIn(zone: Zone, userOverrides?: Partial<ZoneRules>, method?: ZoneOptIn['method']): ZoneOptIn;
|
|
415
|
+
/**
|
|
416
|
+
* Start a new spatial handshake with an initial participant.
|
|
417
|
+
*/
|
|
418
|
+
declare function startHandshake(initiator: ParticipantConstraints, initiatorId: string, zoneId?: string): SpatialHandshake;
|
|
419
|
+
/**
|
|
420
|
+
* Add a participant to an existing handshake. Returns a new handshake
|
|
421
|
+
* with recomputed negotiated rules.
|
|
422
|
+
*/
|
|
423
|
+
declare function joinHandshake(handshake: SpatialHandshake, constraints: ParticipantConstraints, participantId: string): SpatialHandshake;
|
|
424
|
+
/**
|
|
425
|
+
* Remove a participant from a handshake. Returns a new handshake
|
|
426
|
+
* with recomputed rules, or null if the handshake is dissolved
|
|
427
|
+
* (< 2 participants remaining).
|
|
428
|
+
*/
|
|
429
|
+
declare function leaveHandshake(handshake: SpatialHandshake, participantId: string): SpatialHandshake | null;
|
|
430
|
+
/**
|
|
431
|
+
* Create a new spatial session.
|
|
432
|
+
*/
|
|
433
|
+
declare function createSession(): SpatialSession;
|
|
434
|
+
/**
|
|
435
|
+
* Apply a zone opt-in to a session. Returns a new session with
|
|
436
|
+
* the zone's rules merged in.
|
|
437
|
+
*/
|
|
438
|
+
declare function applyZoneToSession(session: SpatialSession, zone: Zone, optIn: ZoneOptIn): SpatialSession;
|
|
439
|
+
/**
|
|
440
|
+
* Apply a handshake to a session. Returns a new session with
|
|
441
|
+
* the handshake's negotiated rules merged in.
|
|
442
|
+
*/
|
|
443
|
+
declare function applyHandshakeToSession(session: SpatialSession, handshake: SpatialHandshake): SpatialSession;
|
|
444
|
+
/**
|
|
445
|
+
* Exit a zone. Zone rules dissolve, but handshake rules may remain.
|
|
446
|
+
*/
|
|
447
|
+
declare function exitZone(session: SpatialSession): SpatialSession;
|
|
448
|
+
/**
|
|
449
|
+
* End a session. All spatial rules dissolve.
|
|
450
|
+
*/
|
|
451
|
+
declare function endSession(session: SpatialSession): SpatialSession;
|
|
452
|
+
type SpatialVerdict = {
|
|
453
|
+
allowed: boolean;
|
|
454
|
+
requiresConfirmation: boolean;
|
|
455
|
+
blockedBy: 'none' | 'zone' | 'handshake' | 'zone+handshake';
|
|
456
|
+
reason: string;
|
|
457
|
+
rule: string;
|
|
458
|
+
};
|
|
459
|
+
/**
|
|
460
|
+
* Evaluate an intent against the current spatial governance context.
|
|
461
|
+
*
|
|
462
|
+
* This is the spatial layer — it sits between user rules and the
|
|
463
|
+
* platform world in the governance stack.
|
|
464
|
+
*/
|
|
465
|
+
declare function evaluateSpatial(intent: string, session: SpatialSession): SpatialVerdict;
|
|
466
|
+
/**
|
|
467
|
+
* Emergency override for spatial governance.
|
|
468
|
+
*
|
|
469
|
+
* When activated, ALL spatial rules (zone + handshake) are bypassed.
|
|
470
|
+
* Only MentraOS platform constraints remain (hardware capability, physics).
|
|
471
|
+
*
|
|
472
|
+
* Use case: You're in a store that blocks recording. Someone gets violent.
|
|
473
|
+
* You need to film, call for help, stream to emergency contacts.
|
|
474
|
+
* Emergency override smashes through every zone and handshake rule.
|
|
475
|
+
*
|
|
476
|
+
* The user is king. Always.
|
|
477
|
+
*
|
|
478
|
+
* In the MentraOS adapter, this is wired to the executor's
|
|
479
|
+
* activateEmergencyOverride() method, which also skips user rules
|
|
480
|
+
* and platform governance — leaving only hardware constraints.
|
|
481
|
+
*
|
|
482
|
+
* Returns a new session in emergency mode with all rules dissolved.
|
|
483
|
+
*/
|
|
484
|
+
declare function activateEmergencyOverride(session: SpatialSession): SpatialSession;
|
|
485
|
+
/**
|
|
486
|
+
* Evaluate an intent during emergency override — always allow.
|
|
487
|
+
* The only thing that can still block is hardware (physics).
|
|
488
|
+
*/
|
|
489
|
+
declare function evaluateSpatialEmergency(_intent: string): SpatialVerdict;
|
|
490
|
+
/**
|
|
491
|
+
* Pre-built zone rule templates for common location types.
|
|
492
|
+
* Zones can start from a template and customize.
|
|
493
|
+
*/
|
|
494
|
+
declare const ZONE_TEMPLATES: Record<string, ZoneRules>;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Example Zones — Real-world spatial governance scenarios
|
|
498
|
+
*
|
|
499
|
+
* These demonstrate what zone governance looks like in practice.
|
|
500
|
+
* Each zone is a real-world location type with rules that make sense
|
|
501
|
+
* for that context.
|
|
502
|
+
*
|
|
503
|
+
* When Mentra + Auki go spatial, these become discoverable.
|
|
504
|
+
* Your glasses walk into a space, detect the Auki anchor or BLE beacon,
|
|
505
|
+
* and present the zone's rules for opt-in.
|
|
506
|
+
*/
|
|
507
|
+
|
|
508
|
+
declare const BLUE_BOTTLE_HAYES: Zone;
|
|
509
|
+
declare const UCSF_MEDICAL: Zone;
|
|
510
|
+
declare const APPLE_UNION_SQUARE: Zone;
|
|
511
|
+
declare const CHASE_CENTER: Zone;
|
|
512
|
+
declare const WEWORK_SOMA: Zone;
|
|
513
|
+
declare const SFMOMA: Zone;
|
|
514
|
+
declare const MY_HOME: Zone;
|
|
515
|
+
declare const EXAMPLE_ZONES: Zone[];
|
|
516
|
+
|
|
517
|
+
export { APPLE_UNION_SQUARE, BLUE_BOTTLE_HAYES, CHASE_CENTER, DEFAULT_PARTICIPANT_CONSTRAINTS, DEFAULT_ZONE_RULES, EXAMPLE_ZONES, type HandshakeParticipant, MY_HOME, type ParticipantConstraints, SFMOMA, type SpatialEvent, type SpatialHandshake, type SpatialSession, type SpatialVerdict, UCSF_MEDICAL, WEWORK_SOMA, ZONE_TEMPLATES, type Zone, type ZoneBoundary, type ZoneCustomRule, type ZoneDiscovery, type ZoneOptIn, type ZonePublisher, type ZoneRules, type ZoneType, activateEmergencyOverride, applyHandshakeToSession, applyZoneToSession, constraintsToRules, createOptIn, createSession, endSession, evaluateSpatial, evaluateSpatialEmergency, exitZone, joinHandshake, leaveHandshake, mergeRules, startHandshake };
|