react-state-basis 0.5.1 → 0.6.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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,19 @@
1
1
  import {
2
2
  basis
3
3
  } from "./chunk-I5ZFRXQP.mjs";
4
+ import {
5
+ WINDOW_SIZE,
6
+ beginEffectTracking,
7
+ configureBasis,
8
+ endEffectTracking,
9
+ getBasisMetrics,
10
+ history,
11
+ printBasisHealthReport,
12
+ recordUpdate,
13
+ redundantLabels,
14
+ registerVariable,
15
+ unregisterVariable
16
+ } from "./chunk-O2ZOR3L2.mjs";
4
17
 
5
18
  // src/hooks.ts
6
19
  import * as React from "react";
@@ -18,463 +31,6 @@ import {
18
31
  useTransition as reactUseTransition,
19
32
  useDeferredValue as reactUseDeferredValue
20
33
  } from "react";
21
-
22
- // src/core/math.ts
23
- var calculateSimilarityCircular = (bufferA, headA, bufferB, headB, offset) => {
24
- const L = bufferA.length;
25
- let dot = 0, magA = 0, magB = 0;
26
- const baseOffset = ((headB - headA + offset) % L + L) % L;
27
- for (let i = 0; i < L; i++) {
28
- const valA = bufferA[i];
29
- let iB = i + baseOffset;
30
- if (iB >= L) {
31
- iB -= L;
32
- }
33
- const valB = bufferB[iB];
34
- dot += valA * valB;
35
- magA += valA * valA;
36
- magB += valB * valB;
37
- }
38
- if (magA === 0 || magB === 0) return 0;
39
- return dot / (Math.sqrt(magA) * Math.sqrt(magB));
40
- };
41
- var calculateCosineSimilarity = (A, B) => {
42
- let dot = 0, magA = 0, magB = 0;
43
- for (let i = 0; i < A.length; i++) {
44
- dot += A[i] * B[i];
45
- magA += A[i] * A[i];
46
- magB += B[i] * B[i];
47
- }
48
- return magA === 0 || magB === 0 ? 0 : dot / (Math.sqrt(magA) * Math.sqrt(magB));
49
- };
50
-
51
- // src/core/logger.ts
52
- var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined";
53
- var LAST_LOG_TIMES = /* @__PURE__ */ new Map();
54
- var LOG_COOLDOWN = 3e3;
55
- var STYLES = {
56
- basis: "background: #6c5ce7; color: white; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
57
- version: "background: #a29bfe; color: #2d3436; padding: 2px 6px; border-radius: 3px; margin-left: -4px;",
58
- headerRed: "background: #d63031; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
59
- headerBlue: "background: #0984e3; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
60
- headerGreen: "background: #00b894; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
61
- label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;",
62
- location: "color: #0984e3; font-family: monospace; font-weight: bold;",
63
- subText: "color: #636e72; font-size: 11px;",
64
- bold: "font-weight: bold;",
65
- action: "color: #00b894; font-weight: bold; border: 1px solid #00b894; padding: 0 4px; border-radius: 3px;",
66
- warning: "color: #d63031; font-weight: bold; border: 1px solid #d63031; padding: 0 4px; border-radius: 3px;"
67
- };
68
- var parseLabel = (label) => {
69
- const parts = label.split(" -> ");
70
- return { file: parts[0] || "Unknown", name: parts[1] || label };
71
- };
72
- var shouldLog = (key) => {
73
- const now = Date.now();
74
- const last = LAST_LOG_TIMES.get(key) || 0;
75
- if (now - last > LOG_COOLDOWN) {
76
- LAST_LOG_TIMES.set(key, now);
77
- return true;
78
- }
79
- return false;
80
- };
81
- var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
82
- if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
83
- const infoA = parseLabel(labelA);
84
- const infoB = parseLabel(labelB);
85
- const isContextMirror = metaA.role === "local" && metaB.role === "context" || metaB.role === "local" && metaA.role === "context";
86
- const local = metaA.role === "local" ? infoA : infoB;
87
- const context = metaA.role === "context" ? infoA : infoB;
88
- console.group(`%c \u264A BASIS | ${isContextMirror ? "CONTEXT MIRRORING" : "DUPLICATE STATE"} `, STYLES.headerRed);
89
- console.log(`%c\u{1F4CD} Location: %c${infoA.file}`, STYLES.bold, STYLES.location);
90
- if (isContextMirror) {
91
- console.log(
92
- `%cIssue:%c Local variable %c${local.name}%c is just a copy of Global Context %c${context.name}%c.
93
- %cConfidence: ${(sim * 100).toFixed(0)}%`,
94
- STYLES.bold,
95
- "",
96
- STYLES.label,
97
- "",
98
- STYLES.label,
99
- "",
100
- STYLES.subText
101
- );
102
- console.log(`%cFix:%c Use the context value directly to avoid state drift.`, STYLES.bold, STYLES.warning);
103
- } else {
104
- console.log(
105
- `%cIssue:%c %c${infoA.name}%c and %c${infoB.name}%c are synchronized (${(sim * 100).toFixed(0)}% correlation).`,
106
- STYLES.bold,
107
- "",
108
- STYLES.label,
109
- "",
110
- STYLES.label,
111
- ""
112
- );
113
- console.log(
114
- `%cFix:%c Merge states or calculate %c${infoB.name}%c from %c${infoA.name}%c via %cuseMemo%c.`,
115
- STYLES.bold,
116
- "",
117
- STYLES.label,
118
- "",
119
- STYLES.label,
120
- "",
121
- STYLES.action,
122
- ""
123
- );
124
- }
125
- console.groupEnd();
126
- };
127
- var displayHealthReport = (history2, threshold) => {
128
- if (!isWeb) return;
129
- const entries = Array.from(history2.entries());
130
- const totalVars = entries.length;
131
- if (totalVars === 0) return;
132
- const clusters = [];
133
- const processed = /* @__PURE__ */ new Set();
134
- let independentCount = 0;
135
- entries.forEach(([labelA, metaA]) => {
136
- if (processed.has(labelA)) return;
137
- const currentCluster = [labelA];
138
- processed.add(labelA);
139
- entries.forEach(([labelB, metaB]) => {
140
- if (labelA === labelB || processed.has(labelB)) return;
141
- const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
142
- if (sim > threshold) {
143
- if (metaA.role === "context" && metaB.role === "context") return;
144
- currentCluster.push(labelB);
145
- processed.add(labelB);
146
- }
147
- });
148
- if (currentCluster.length > 1) clusters.push(currentCluster);
149
- else independentCount++;
150
- });
151
- const systemRank = independentCount + clusters.length;
152
- const healthScore = systemRank / totalVars * 100;
153
- console.group(`%c \u{1F4CA} BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerGreen);
154
- console.log(
155
- `%cEfficiency: %c${healthScore.toFixed(1)}% %c(${systemRank}/${totalVars} Sources of Truth)`,
156
- STYLES.bold,
157
- `color: ${healthScore > 85 ? "#00b894" : "#d63031"}; font-weight: bold;`,
158
- STYLES.subText
159
- );
160
- if (clusters.length > 0) {
161
- console.log(`%cDetected ${clusters.length} Sync Issues:`, "font-weight: bold; color: #e17055; margin-top: 10px;");
162
- clusters.forEach((cluster, idx) => {
163
- const clusterMetas = cluster.map((l) => ({ label: l, meta: history2.get(l), info: parseLabel(l) }));
164
- const contexts = clusterMetas.filter((c) => c.meta.role === "context");
165
- const locals = clusterMetas.filter((c) => c.meta.role === "local");
166
- const names = clusterMetas.map((c) => `${c.meta.role === "context" ? "\u03A9 " : ""}${c.info.name}`).join(" \u27F7 ");
167
- console.group(` %c${idx + 1}%c ${names}`, "background: #e17055; color: white; border-radius: 50%; padding: 0 5px;", "font-family: monospace; font-weight: bold;");
168
- if (contexts.length > 0) {
169
- const ctxNames = contexts.map((c) => c.info.name).join(", ");
170
- console.log(`%cDiagnosis:%c Context Mirroring. Variables are copying from %c${ctxNames}%c.`, STYLES.bold, "", STYLES.label, "");
171
- console.log(`%cSolution:%c Use the context directly to avoid state drift.`, STYLES.bold, STYLES.action);
172
- } else {
173
- const isExplosion = locals.length > 2;
174
- if (isExplosion) {
175
- console.log(`%cDiagnosis:%c Boolean Explosion. Multiple states updating in sync.`, STYLES.bold, "");
176
- console.log(`%cSolution:%c Combine into a single %cstatus%c string or a %creducer%c.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
177
- } else {
178
- console.log(`%cDiagnosis:%c Redundant State. Variables always change together.`, STYLES.bold, "");
179
- console.log(`%cSolution:%c Derive one from the other via %cuseMemo%c.`, STYLES.bold, "", STYLES.label, "");
180
- }
181
- }
182
- console.groupEnd();
183
- });
184
- } else {
185
- console.log("%c\u2728 Your architecture is clean. No redundant state detected.", "color: #00b894; font-weight: bold;");
186
- }
187
- console.groupEnd();
188
- };
189
- var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
190
- if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;
191
- const target = parseLabel(targetLabel);
192
- const source = parseLabel(sourceLabel);
193
- const isContextTrigger = sourceMeta.role === "context";
194
- console.groupCollapsed(`%c \u26A1 BASIS | ${isContextTrigger ? "CONTEXT SYNC LEAK" : "DOUBLE RENDER"} `, STYLES.headerBlue);
195
- console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
196
- if (isContextTrigger) {
197
- console.log(`%cIssue:%c Context %c${source.name}%c updated, then local %c${target.name}%c followed 1 frame later.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
198
- console.log(`%cImpact: This forces React to render the component twice for every change.`, STYLES.subText);
199
- } else {
200
- console.log(`%cIssue:%c %c${source.name}%c triggers %c${target.name}%c in a separate frame.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
201
- }
202
- console.log(`%cFix:%c Derive %c${target.name}%c during the first render.`, STYLES.bold, STYLES.action, STYLES.label, "");
203
- console.groupEnd();
204
- };
205
- var displayViolentBreaker = (label, count, threshold) => {
206
- if (!isWeb) return;
207
- const parts = label.split(" -> ");
208
- console.group(`%c \u{1F6D1} BASIS CRITICAL | CIRCUIT BREAKER `, "background: #dc2626; color: white; font-weight: bold; padding: 8px 16px;");
209
- console.error(`INFINITE LOOP DETECTED
210
- Variable: ${parts[1] || label}
211
- Frequency: ${count} updates/sec`);
212
- console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, "color: #dc2626; font-weight: bold;");
213
- console.groupEnd();
214
- };
215
- var displayBootLog = (windowSize) => {
216
- if (!isWeb) return;
217
- console.log(`%cBasis%cAuditor%c | v0.5.x Architectural Forensics Active (Window: ${windowSize})`, STYLES.basis, STYLES.version, "color: #636e72; font-style: italic; margin-left: 8px;");
218
- };
219
-
220
- // src/core/constants.ts
221
- var WINDOW_SIZE = 50;
222
- var SIMILARITY_THRESHOLD = 0.88;
223
- var LOOP_THRESHOLD = 150;
224
- var VOLATILITY_THRESHOLD = 25;
225
-
226
- // src/core/analysis.ts
227
- var calculateAllSimilarities = (entryA, entryB) => {
228
- const sync = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 0);
229
- const bA = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 1);
230
- const aB = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, -1);
231
- return { sync, bA, aB, max: Math.max(sync, bA, aB) };
232
- };
233
- var shouldSkipComparison = (entryA, entryB, dirtyLabels2) => {
234
- if (entryA.label === entryB.label) return true;
235
- if (dirtyLabels2.has(entryB.label) && entryA.label > entryB.label) return true;
236
- return false;
237
- };
238
- var detectRedundancy = (entryA, entryB, similarities, redundantSet) => {
239
- const roleA = entryA.meta.role;
240
- const roleB = entryB.meta.role;
241
- if (roleA === "context" /* CONTEXT */ && roleB === "context" /* CONTEXT */) return;
242
- if (entryA.meta.density < 2 || entryB.meta.density < 2) return;
243
- if (roleA === "local" /* LOCAL */ && roleB === "context" /* CONTEXT */) {
244
- redundantSet.add(entryA.label);
245
- displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
246
- } else if (roleA === "context" /* CONTEXT */ && roleB === "local" /* LOCAL */) {
247
- redundantSet.add(entryB.label);
248
- displayRedundancyAlert(entryB.label, entryB.meta, entryA.label, entryA.meta, similarities.max);
249
- } else if (roleA === "local" /* LOCAL */ && roleB === "local" /* LOCAL */) {
250
- redundantSet.add(entryA.label);
251
- redundantSet.add(entryB.label);
252
- displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
253
- }
254
- };
255
- var detectCausalLeak = (entryA, entryB, similarities) => {
256
- if (entryA.isVolatile || entryB.isVolatile) return;
257
- if (similarities.bA === similarities.max) {
258
- displayCausalHint(entryB.label, entryB.meta, entryA.label, entryA.meta);
259
- } else if (similarities.aB === similarities.max) {
260
- displayCausalHint(entryA.label, entryA.meta, entryB.label, entryB.meta);
261
- }
262
- };
263
- var detectSubspaceOverlap = (dirtyEntries, allEntries, redundantSet, dirtyLabels2) => {
264
- let compCount = 0;
265
- for (const entryA of dirtyEntries) {
266
- for (const entryB of allEntries) {
267
- if (shouldSkipComparison(entryA, entryB, dirtyLabels2)) continue;
268
- compCount++;
269
- const similarities = calculateAllSimilarities(entryA, entryB);
270
- if (similarities.max > SIMILARITY_THRESHOLD) {
271
- detectRedundancy(entryA, entryB, similarities, redundantSet);
272
- detectCausalLeak(entryA, entryB, similarities);
273
- }
274
- }
275
- }
276
- return compCount;
277
- };
278
-
279
- // src/engine.ts
280
- var BASIS_INSTANCE_KEY = /* @__PURE__ */ Symbol.for("__basis_engine_instance__");
281
- var NULL_SIGNAL = {
282
- role: "proj" /* PROJECTION */,
283
- buffer: new Uint8Array(0),
284
- head: 0,
285
- density: 0,
286
- options: {}
287
- };
288
- var getGlobalInstance = () => {
289
- const root = globalThis;
290
- if (!root[BASIS_INSTANCE_KEY]) {
291
- root[BASIS_INSTANCE_KEY] = {
292
- config: { debug: false },
293
- history: /* @__PURE__ */ new Map(),
294
- currentTickBatch: /* @__PURE__ */ new Set(),
295
- redundantLabels: /* @__PURE__ */ new Set(),
296
- booted: false,
297
- tick: 0,
298
- isBatching: false,
299
- currentEffectSource: null,
300
- pausedVariables: /* @__PURE__ */ new Set(),
301
- metrics: {
302
- lastAnalysisTimeMs: 0,
303
- comparisonCount: 0,
304
- lastAnalysisTimestamp: 0,
305
- systemEntropy: 0
306
- },
307
- alertCount: 0,
308
- loopCounters: /* @__PURE__ */ new Map(),
309
- lastCleanup: Date.now()
310
- };
311
- }
312
- return root[BASIS_INSTANCE_KEY];
313
- };
314
- var instance = getGlobalInstance();
315
- var config = instance.config;
316
- var history = instance.history;
317
- var redundantLabels = instance.redundantLabels;
318
- var currentTickBatch = instance.currentTickBatch;
319
- var currentTickRegistry = {};
320
- var dirtyLabels = /* @__PURE__ */ new Set();
321
- var calculateTickEntropy = (tickIdx) => {
322
- let activeCount = 0;
323
- const total = instance.history.size;
324
- if (total === 0) return 1;
325
- instance.history.forEach((meta) => {
326
- if (meta.buffer[tickIdx] === 1) activeCount++;
327
- });
328
- return 1 - activeCount / total;
329
- };
330
- var analyzeBasis = () => {
331
- if (!instance.config.debug || dirtyLabels.size === 0) {
332
- return;
333
- }
334
- const scheduler = globalThis.requestIdleCallback || ((cb) => setTimeout(cb, 1));
335
- const snapshot = new Set(dirtyLabels);
336
- dirtyLabels.clear();
337
- scheduler(() => {
338
- const analysisStart = performance.now();
339
- const allEntries = [];
340
- const dirtyEntries = [];
341
- instance.history.forEach((meta, label) => {
342
- if (meta.options.suppressAll || meta.density === 0) return;
343
- const entry = {
344
- label,
345
- meta,
346
- isVolatile: meta.density > VOLATILITY_THRESHOLD
347
- };
348
- allEntries.push(entry);
349
- if (snapshot.has(label)) {
350
- dirtyEntries.push(entry);
351
- }
352
- });
353
- if (dirtyEntries.length === 0 || allEntries.length < 2) return;
354
- const nextRedundant = /* @__PURE__ */ new Set();
355
- instance.redundantLabels.forEach((l) => {
356
- if (!snapshot.has(l)) {
357
- nextRedundant.add(l);
358
- }
359
- });
360
- const compCount = detectSubspaceOverlap(
361
- dirtyEntries,
362
- allEntries,
363
- nextRedundant,
364
- snapshot
365
- );
366
- instance.redundantLabels.clear();
367
- nextRedundant.forEach((l) => {
368
- instance.redundantLabels.add(l);
369
- });
370
- instance.metrics.lastAnalysisTimeMs = performance.now() - analysisStart;
371
- instance.metrics.comparisonCount = compCount;
372
- instance.metrics.lastAnalysisTimestamp = Date.now();
373
- });
374
- };
375
- var processHeartbeat = () => {
376
- instance.tick++;
377
- instance.history.forEach((meta, label) => {
378
- const oldValue = meta.buffer[meta.head];
379
- const newValue = instance.currentTickBatch.has(label) ? 1 : 0;
380
- meta.buffer[meta.head] = newValue;
381
- if (oldValue !== newValue) {
382
- meta.density += newValue - oldValue;
383
- }
384
- meta.head = (meta.head + 1) % WINDOW_SIZE;
385
- });
386
- const lastHead = instance.history.size > 0 ? instance.tick % WINDOW_SIZE : 0;
387
- instance.metrics.systemEntropy = calculateTickEntropy(lastHead);
388
- instance.currentTickBatch.clear();
389
- currentTickRegistry = {};
390
- instance.isBatching = false;
391
- if (dirtyLabels.size > 0) {
392
- analyzeBasis();
393
- }
394
- };
395
- var recordUpdate = (label) => {
396
- if (!instance.config.debug) return true;
397
- if (instance.pausedVariables.has(label)) return false;
398
- const now = Date.now();
399
- if (now - instance.lastCleanup > 1e3) {
400
- instance.loopCounters.clear();
401
- instance.lastCleanup = now;
402
- }
403
- const count = (instance.loopCounters.get(label) || 0) + 1;
404
- instance.loopCounters.set(label, count);
405
- if (count > LOOP_THRESHOLD) {
406
- displayViolentBreaker(label, count, LOOP_THRESHOLD);
407
- instance.pausedVariables.add(label);
408
- return false;
409
- }
410
- if (instance.currentEffectSource && instance.currentEffectSource !== label) {
411
- const targetMeta = instance.history.get(label);
412
- const sourceMeta = instance.history.get(instance.currentEffectSource);
413
- if (targetMeta) {
414
- const sourceDensity = sourceMeta?.density || 0;
415
- const isVolatile = targetMeta.density > VOLATILITY_THRESHOLD || sourceDensity > VOLATILITY_THRESHOLD;
416
- if (!isVolatile) {
417
- displayCausalHint(label, targetMeta, instance.currentEffectSource, sourceMeta || NULL_SIGNAL);
418
- }
419
- }
420
- }
421
- if (currentTickRegistry[label]) return true;
422
- currentTickRegistry[label] = true;
423
- instance.currentTickBatch.add(label);
424
- dirtyLabels.add(label);
425
- if (!instance.isBatching) {
426
- instance.isBatching = true;
427
- requestAnimationFrame(processHeartbeat);
428
- }
429
- return true;
430
- };
431
- var configureBasis = (c) => {
432
- Object.assign(instance.config, c);
433
- if (instance.config.debug && !instance.booted) {
434
- displayBootLog(WINDOW_SIZE);
435
- instance.booted = true;
436
- }
437
- };
438
- var registerVariable = (l, o = {}) => {
439
- if (!instance.config.debug || o.suppressAll) return;
440
- if (!instance.history.has(l)) {
441
- instance.history.set(l, {
442
- buffer: new Uint8Array(WINDOW_SIZE),
443
- head: 0,
444
- density: 0,
445
- options: o,
446
- role: o.role || "local" /* LOCAL */
447
- });
448
- }
449
- };
450
- var unregisterVariable = (l) => {
451
- instance.history.delete(l);
452
- instance.loopCounters.delete(l);
453
- instance.pausedVariables.delete(l);
454
- instance.redundantLabels.delete(l);
455
- };
456
- var beginEffectTracking = (l) => {
457
- if (instance.config.debug) instance.currentEffectSource = l;
458
- };
459
- var endEffectTracking = () => {
460
- instance.currentEffectSource = null;
461
- };
462
- var printBasisHealthReport = (threshold = 0.5) => {
463
- if (!instance.config.debug) return;
464
- displayHealthReport(instance.history, threshold);
465
- };
466
- var getBasisMetrics = () => ({
467
- engine: "v0.5.x",
468
- hooks: instance.history.size,
469
- analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3),
470
- entropy: instance.metrics.systemEntropy.toFixed(3)
471
- });
472
- if (typeof window !== "undefined") {
473
- window.printBasisReport = printBasisHealthReport;
474
- window.getBasisMetrics = getBasisMetrics;
475
- }
476
-
477
- // src/hooks.ts
478
34
  var anonCount = 0;
479
35
  var getFallbackLabel = (type) => `anon_${type}_${anonCount++}`;
480
36
  var React19 = React;
@@ -678,7 +234,14 @@ var BasisHUD = () => {
678
234
  if (!canvas) return;
679
235
  const ctx = canvas.getContext("2d");
680
236
  if (!ctx) return;
681
- const entries = Array.from(history.entries());
237
+ const entries = Array.from(history.entries()).sort((a, b) => {
238
+ const roleOrder = (role) => {
239
+ if (role === "context") return 0;
240
+ if (role === "store") return 1;
241
+ return 2;
242
+ };
243
+ return roleOrder(a[1].role) - roleOrder(b[1].role);
244
+ });
682
245
  const dpr = window.devicePixelRatio || 1;
683
246
  const rawWidth = HUD_DIMENSIONS.WINDOW_SIZE * HUD_DIMENSIONS.COL_WIDTH + HUD_DIMENSIONS.LABEL_WIDTH + HUD_DIMENSIONS.PADDING * 2;
684
247
  const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2, 80);
@@ -734,7 +297,7 @@ function renderMatrix(ctx, entries) {
734
297
  let rowIndex = 0;
735
298
  for (const [label, meta] of entries) {
736
299
  const y = rowIndex * rowH + pad;
737
- const isContext = meta.role === "context";
300
+ const isContext = meta.role === "context" || meta.role === "store";
738
301
  const isRedundant = !isContext && redundantLabels.has(label);
739
302
  const { buffer, head } = meta;
740
303
  let uiPos = 0;
@@ -753,7 +316,8 @@ function renderMatrix(ctx, entries) {
753
316
  const stateName = label.split(" -> ")[1] || label;
754
317
  const textX = L * colW + pad + 10;
755
318
  ctx.fillStyle = isContext ? HUD_THEME.header : isRedundant ? HUD_THEME.error : HUD_THEME.text;
756
- ctx.fillText((isContext ? "\u03A9 " : isRedundant ? "! " : "") + stateName, textX, y + 9);
319
+ const prefix = meta.role === "store" ? "\u03A3 " : isContext ? "\u03A9 " : isRedundant ? "! " : "";
320
+ ctx.fillText(prefix + stateName, textX, y + 9);
757
321
  rowIndex++;
758
322
  }
759
323
  ctx.fillStyle = HUD_THEME.grid;
@@ -782,7 +346,7 @@ var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ jsxs(
782
346
  },
783
347
  children: [
784
348
  /* @__PURE__ */ jsx("span", { children: isExpanded ? "STATE BASIS MATRIX" : "\u{1F4D0} BASIS ACTIVE" }),
785
- isExpanded && /* @__PURE__ */ jsx("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.5.x" })
349
+ isExpanded && /* @__PURE__ */ jsx("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.6.x" })
786
350
  ]
787
351
  }
788
352
  );
@@ -790,7 +354,7 @@ var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ jsxs(
790
354
  // src/context.tsx
791
355
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
792
356
  var BasisContext = createContext2({ debug: false });
793
- var isWeb2 = typeof window !== "undefined" && typeof window.document !== "undefined";
357
+ var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined";
794
358
  var BasisProvider = ({
795
359
  children,
796
360
  debug = true,
@@ -798,13 +362,13 @@ var BasisProvider = ({
798
362
  }) => {
799
363
  useLayoutEffect2(() => {
800
364
  configureBasis({ debug });
801
- if (isWeb2) {
365
+ if (isWeb) {
802
366
  window._basis_debug = debug;
803
367
  }
804
368
  }, [debug]);
805
369
  return /* @__PURE__ */ jsxs2(BasisContext.Provider, { value: { debug }, children: [
806
370
  children,
807
- debug && showHUD && isWeb2 && /* @__PURE__ */ jsx2(BasisHUD, {})
371
+ debug && showHUD && isWeb && /* @__PURE__ */ jsx2(BasisHUD, {})
808
372
  ] });
809
373
  };
810
374
  var useBasisConfig = () => useContext2(BasisContext);