react-state-basis 0.4.2 → 0.5.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.js CHANGED
@@ -33,12 +33,14 @@ __export(index_exports, {
33
33
  BasisProvider: () => BasisProvider,
34
34
  basis: () => basis,
35
35
  configureBasis: () => configureBasis,
36
+ createContext: () => createContext,
36
37
  getBasisMetrics: () => getBasisMetrics,
37
38
  printBasisHealthReport: () => printBasisHealthReport,
38
39
  use: () => use,
39
- useActionState: () => useActionState2,
40
+ useActionState: () => useActionState,
40
41
  useBasisConfig: () => useBasisConfig,
41
42
  useCallback: () => useCallback,
43
+ useContext: () => useContext,
42
44
  useDebugValue: () => useDebugValue2,
43
45
  useDeferredValue: () => useDeferredValue,
44
46
  useEffect: () => useEffect,
@@ -47,7 +49,7 @@ __export(index_exports, {
47
49
  useInsertionEffect: () => useInsertionEffect2,
48
50
  useLayoutEffect: () => useLayoutEffect,
49
51
  useMemo: () => useMemo,
50
- useOptimistic: () => useOptimistic2,
52
+ useOptimistic: () => useOptimistic,
51
53
  useReducer: () => useReducer,
52
54
  useRef: () => useRef,
53
55
  useState: () => useState,
@@ -63,15 +65,14 @@ var import_react = require("react");
63
65
  // src/core/math.ts
64
66
  var calculateSimilarityCircular = (bufferA, headA, bufferB, headB, offset) => {
65
67
  const L = bufferA.length;
66
- let dot = 0;
67
- let magA = 0;
68
- let magB = 0;
69
- const headOffset = headB - headA + offset;
68
+ let dot = 0, magA = 0, magB = 0;
69
+ const baseOffset = ((headB - headA + offset) % L + L) % L;
70
70
  for (let i = 0; i < L; i++) {
71
71
  const valA = bufferA[i];
72
- let iB = i + headOffset;
73
- if (iB < 0) iB += L;
74
- else if (iB >= L) iB -= L;
72
+ let iB = i + baseOffset;
73
+ if (iB >= L) {
74
+ iB -= L;
75
+ }
75
76
  const valB = bufferB[iB];
76
77
  dot += valA * valB;
77
78
  magA += valA * valA;
@@ -93,7 +94,7 @@ var calculateCosineSimilarity = (A, B) => {
93
94
  // src/core/logger.ts
94
95
  var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined";
95
96
  var LAST_LOG_TIMES = /* @__PURE__ */ new Map();
96
- var LOG_COOLDOWN = 5e3;
97
+ var LOG_COOLDOWN = 3e3;
97
98
  var STYLES = {
98
99
  basis: "background: #6c5ce7; color: white; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
99
100
  version: "background: #a29bfe; color: #2d3436; padding: 2px 6px; border-radius: 3px; margin-left: -4px;",
@@ -102,11 +103,10 @@ var STYLES = {
102
103
  headerGreen: "background: #00b894; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
103
104
  label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;",
104
105
  location: "color: #0984e3; font-family: monospace; font-weight: bold;",
105
- impact: "background: #f1f2f6; color: #2f3542; padding: 0 4px; border-radius: 3px; font-weight: bold;",
106
106
  subText: "color: #636e72; font-size: 11px;",
107
107
  bold: "font-weight: bold;",
108
- actionMemo: "color: #00b894; font-weight: bold; border: 1px solid #00b894; padding: 0 4px; border-radius: 3px;",
109
- actionDelete: "color: #d63031; font-weight: bold; border: 1px solid #d63031; padding: 0 4px; border-radius: 3px;"
108
+ action: "color: #00b894; font-weight: bold; border: 1px solid #00b894; padding: 0 4px; border-radius: 3px;",
109
+ warning: "color: #d63031; font-weight: bold; border: 1px solid #d63031; padding: 0 4px; border-radius: 3px;"
110
110
  };
111
111
  var parseLabel = (label) => {
112
112
  const parts = label.split(" -> ");
@@ -117,129 +117,58 @@ var shouldLog = (key) => {
117
117
  const last = LAST_LOG_TIMES.get(key) || 0;
118
118
  if (now - last > LOG_COOLDOWN) {
119
119
  LAST_LOG_TIMES.set(key, now);
120
- if (LAST_LOG_TIMES.size > 100) {
121
- const cutoff = now - 36e5;
122
- for (const [k, v] of LAST_LOG_TIMES.entries()) {
123
- if (v < cutoff) LAST_LOG_TIMES.delete(k);
124
- }
125
- }
126
120
  return true;
127
121
  }
128
122
  return false;
129
123
  };
130
- var displayBootLog = (windowSize) => {
131
- if (!isWeb) return;
132
- console.log(
133
- `%cBasis%cAuditor%c | Temporal Analysis Active (Window: ${windowSize})`,
134
- STYLES.basis,
135
- STYLES.version,
136
- "color: #636e72; font-style: italic; margin-left: 8px;"
137
- );
138
- };
139
- var displayRedundancyAlert = (labelA, labelB, sim) => {
124
+ var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
140
125
  if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
141
126
  const infoA = parseLabel(labelA);
142
127
  const infoB = parseLabel(labelB);
143
- console.group(`%c \u264A BASIS | TWIN STATE DETECTED `, STYLES.headerRed);
128
+ const isContextMirror = metaA.role === "local" && metaB.role === "context" || metaB.role === "local" && metaA.role === "context";
129
+ const local = metaA.role === "local" ? infoA : infoB;
130
+ const context = metaA.role === "context" ? infoA : infoB;
131
+ console.group(`%c \u264A BASIS | ${isContextMirror ? "CONTEXT MIRRORING" : "DUPLICATE STATE"} `, STYLES.headerRed);
144
132
  console.log(`%c\u{1F4CD} Location: %c${infoA.file}`, STYLES.bold, STYLES.location);
145
- console.log(
146
- `%cThe Rhythm:%c %c${infoA.name}%c and %c${infoB.name}%c are moving in perfect sync.
147
- %cThis indicates that one is a redundant shadow of the other. Confidence: ${(sim * 100).toFixed(0)}%`,
148
- STYLES.bold,
149
- "",
150
- STYLES.label,
151
- "",
152
- STYLES.label,
153
- "",
154
- STYLES.subText
155
- );
156
- console.log(
157
- `%cRecommended Fix:%c Derive %c${infoB.name}%c from %c${infoA.name}%c during the render pass.`,
158
- STYLES.bold,
159
- "",
160
- STYLES.actionMemo,
161
- "",
162
- STYLES.bold,
163
- ""
164
- );
165
- console.groupEnd();
166
- };
167
- var displayCausalHint = (targetLabel, sourceLabel, method = "math") => {
168
- const key = `causal-${sourceLabel}-${targetLabel}`;
169
- if (!isWeb || !shouldLog(key)) return;
170
- const target = parseLabel(targetLabel);
171
- const source = parseLabel(sourceLabel);
172
- console.groupCollapsed(
173
- `%c \u26A1 BASIS | DOUBLE RENDER CYCLE `,
174
- STYLES.headerBlue
175
- );
176
- console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
177
- console.log(
178
- `%cThe Rhythm:%c %c${source.name}%c pulses, then %c${target.name}%c pulses one frame later.`,
179
- STYLES.bold,
180
- "",
181
- STYLES.label,
182
- "",
183
- STYLES.label,
184
- ""
185
- );
186
- console.log(
187
- `%cThe Impact:%c You are forcing %c2 render passes%c for a single logical change.`,
188
- STYLES.bold,
189
- "",
190
- STYLES.impact,
191
- ""
192
- );
193
- console.log(
194
- `%cRecommended Fix:%c Remove the useEffect. Calculate %c${target.name}%c as a derived value or projection.`,
195
- STYLES.bold,
196
- "",
197
- STYLES.actionDelete,
198
- ""
199
- );
200
- console.groupEnd();
201
- };
202
- var displayViolentBreaker = (label, count, threshold) => {
203
- if (!isWeb) return;
204
- const parts = label.split(" -> ");
205
- console.group(
206
- `%c \u26A0\uFE0F CRITICAL SYSTEM ALERT | BASIS ENGINE `,
207
- "background: #dc2626; color: white; font-weight: bold; padding: 8px 16px; font-size: 14px;"
208
- );
209
- console.error(
210
- `%c\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
211
- "color: #dc2626; font-weight: bold;"
212
- );
213
- console.error(
214
- `%cINFINITE LOOP DETECTED
215
-
216
- %cVariable: %c${parts[1] || label}
217
- %cUpdate Frequency: %c${count} updates/sec
218
- %cExpected Maximum: %c${threshold} updates
219
-
220
- %c\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
221
- "color: #dc2626; font-size: 16px; font-weight: bold;",
222
- "color: #71717a; font-weight: bold;",
223
- `color: white; background: #dc2626; padding: 2px 8px;`,
224
- "color: #71717a; font-weight: bold;",
225
- `color: #fbbf24; font-weight: bold;`,
226
- "color: #71717a; font-weight: bold;",
227
- `color: #fbbf24; font-weight: bold;`,
228
- "color: #dc2626; font-weight: bold;"
229
- );
230
- console.log(
231
- `%cDIAGNOSTICS:
232
- 1. Check for setState inside the render body.
233
- 2. Verify useEffect dependencies (missing or unstable refs).
234
- 3. Look for circular chains (State A -> B -> A).
235
-
236
- %cSYSTEM ACTION: Update BLOCKED. Fix your code to resume monitoring.`,
237
- "color: #71717a;",
238
- "color: #dc2626; font-weight: bold;"
239
- );
133
+ if (isContextMirror) {
134
+ console.log(
135
+ `%cIssue:%c Local variable %c${local.name}%c is just a copy of Global Context %c${context.name}%c.
136
+ %cConfidence: ${(sim * 100).toFixed(0)}%`,
137
+ STYLES.bold,
138
+ "",
139
+ STYLES.label,
140
+ "",
141
+ STYLES.label,
142
+ "",
143
+ STYLES.subText
144
+ );
145
+ console.log(`%cFix:%c Use the context value directly to avoid state drift.`, STYLES.bold, STYLES.warning);
146
+ } else {
147
+ console.log(
148
+ `%cIssue:%c %c${infoA.name}%c and %c${infoB.name}%c are synchronized (${(sim * 100).toFixed(0)}% correlation).`,
149
+ STYLES.bold,
150
+ "",
151
+ STYLES.label,
152
+ "",
153
+ STYLES.label,
154
+ ""
155
+ );
156
+ console.log(
157
+ `%cFix:%c Merge states or calculate %c${infoB.name}%c from %c${infoA.name}%c via %cuseMemo%c.`,
158
+ STYLES.bold,
159
+ "",
160
+ STYLES.label,
161
+ "",
162
+ STYLES.label,
163
+ "",
164
+ STYLES.action,
165
+ ""
166
+ );
167
+ }
240
168
  console.groupEnd();
241
169
  };
242
170
  var displayHealthReport = (history2, threshold) => {
171
+ if (!isWeb) return;
243
172
  const entries = Array.from(history2.entries());
244
173
  const totalVars = entries.length;
245
174
  if (totalVars === 0) return;
@@ -254,6 +183,7 @@ var displayHealthReport = (history2, threshold) => {
254
183
  if (labelA === labelB || processed.has(labelB)) return;
255
184
  const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
256
185
  if (sim > threshold) {
186
+ if (metaA.role === "context" && metaB.role === "context") return;
257
187
  currentCluster.push(labelB);
258
188
  processed.add(labelB);
259
189
  }
@@ -263,52 +193,141 @@ var displayHealthReport = (history2, threshold) => {
263
193
  });
264
194
  const systemRank = independentCount + clusters.length;
265
195
  const healthScore = systemRank / totalVars * 100;
266
- if (isWeb) {
267
- console.group(`%c \u{1F4CA} BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerGreen);
268
- console.log(
269
- `%cSystem Efficiency: %c${healthScore.toFixed(1)}% %c(Basis Vectors: ${systemRank} / Total Hooks: ${totalVars})`,
270
- STYLES.bold,
271
- `color: ${healthScore > 85 ? "#00b894" : "#d63031"}; font-size: 16px; font-weight: bold;`,
272
- "color: #636e72; font-style: italic;"
273
- );
274
- if (clusters.length > 0) {
275
- console.log(`%cDetected ${clusters.length} Entangled Clusters:`, "font-weight: bold; color: #e17055; margin-top: 10px;");
276
- clusters.forEach((cluster, idx) => {
277
- const names = cluster.map((l) => parseLabel(l).name).join(" \u27F7 ");
278
- console.log(` %c${idx + 1}%c ${names}`, "background: #e17055; color: white; border-radius: 50%; padding: 0 5px;", "font-family: monospace;");
279
- });
280
- console.log("%c\u{1F4A1} Analysis: These variables are mirrored. Storing them separately creates unnecessary work for React.", STYLES.subText);
281
- } else {
282
- console.log("%c\u2728 All state variables are independent. Your architectural Basis is healthy.", "color: #00b894; font-weight: bold; margin-top: 10px;");
283
- }
284
- if (totalVars > 0 && totalVars < 20) {
285
- console.groupCollapsed("%cView Full Correlation Matrix", "color: #636e72; font-size: 11px;");
286
- const matrix = {};
287
- entries.forEach(([labelA, metaA]) => {
288
- const nameA = parseLabel(labelA).name;
289
- matrix[nameA] = {};
290
- entries.forEach(([labelB, metaB]) => {
291
- const nameB = parseLabel(labelB).name;
292
- const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
293
- matrix[nameA][nameB] = sim > threshold ? `\u274C ${(sim * 100).toFixed(0)}%` : `\u2705`;
294
- });
295
- });
296
- console.table(matrix);
196
+ console.group(`%c \u{1F4CA} BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerGreen);
197
+ console.log(
198
+ `%cEfficiency: %c${healthScore.toFixed(1)}% %c(${systemRank}/${totalVars} Sources of Truth)`,
199
+ STYLES.bold,
200
+ `color: ${healthScore > 85 ? "#00b894" : "#d63031"}; font-weight: bold;`,
201
+ STYLES.subText
202
+ );
203
+ if (clusters.length > 0) {
204
+ console.log(`%cDetected ${clusters.length} Sync Issues:`, "font-weight: bold; color: #e17055; margin-top: 10px;");
205
+ clusters.forEach((cluster, idx) => {
206
+ const clusterMetas = cluster.map((l) => ({ label: l, meta: history2.get(l), info: parseLabel(l) }));
207
+ const contexts = clusterMetas.filter((c) => c.meta.role === "context");
208
+ const locals = clusterMetas.filter((c) => c.meta.role === "local");
209
+ const names = clusterMetas.map((c) => `${c.meta.role === "context" ? "\u03A9 " : ""}${c.info.name}`).join(" \u27F7 ");
210
+ console.group(` %c${idx + 1}%c ${names}`, "background: #e17055; color: white; border-radius: 50%; padding: 0 5px;", "font-family: monospace; font-weight: bold;");
211
+ if (contexts.length > 0) {
212
+ const ctxNames = contexts.map((c) => c.info.name).join(", ");
213
+ console.log(`%cDiagnosis:%c Context Mirroring. Variables are copying from %c${ctxNames}%c.`, STYLES.bold, "", STYLES.label, "");
214
+ console.log(`%cSolution:%c Use the context directly to avoid state drift.`, STYLES.bold, STYLES.action);
215
+ } else {
216
+ const isExplosion = locals.length > 2;
217
+ if (isExplosion) {
218
+ console.log(`%cDiagnosis:%c Boolean Explosion. Multiple states updating in sync.`, STYLES.bold, "");
219
+ console.log(`%cSolution:%c Combine into a single %cstatus%c string or a %creducer%c.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
220
+ } else {
221
+ console.log(`%cDiagnosis:%c Redundant State. Variables always change together.`, STYLES.bold, "");
222
+ console.log(`%cSolution:%c Derive one from the other via %cuseMemo%c.`, STYLES.bold, "", STYLES.label, "");
223
+ }
224
+ }
297
225
  console.groupEnd();
298
- }
299
- console.groupEnd();
226
+ });
227
+ } else {
228
+ console.log("%c\u2728 Your architecture is clean. No redundant state detected.", "color: #00b894; font-weight: bold;");
229
+ }
230
+ console.groupEnd();
231
+ };
232
+ var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
233
+ if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;
234
+ const target = parseLabel(targetLabel);
235
+ const source = parseLabel(sourceLabel);
236
+ const isContextTrigger = sourceMeta.role === "context";
237
+ console.groupCollapsed(`%c \u26A1 BASIS | ${isContextTrigger ? "CONTEXT SYNC LEAK" : "DOUBLE RENDER"} `, STYLES.headerBlue);
238
+ console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
239
+ if (isContextTrigger) {
240
+ 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, "");
241
+ console.log(`%cImpact: This forces React to render the component twice for every change.`, STYLES.subText);
242
+ } else {
243
+ console.log(`%cIssue:%c %c${source.name}%c triggers %c${target.name}%c in a separate frame.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
300
244
  }
245
+ console.log(`%cFix:%c Derive %c${target.name}%c during the first render.`, STYLES.bold, STYLES.action, STYLES.label, "");
246
+ console.groupEnd();
247
+ };
248
+ var displayViolentBreaker = (label, count, threshold) => {
249
+ if (!isWeb) return;
250
+ const parts = label.split(" -> ");
251
+ console.group(`%c \u{1F6D1} BASIS CRITICAL | CIRCUIT BREAKER `, "background: #dc2626; color: white; font-weight: bold; padding: 8px 16px;");
252
+ console.error(`INFINITE LOOP DETECTED
253
+ Variable: ${parts[1] || label}
254
+ Frequency: ${count} updates/sec`);
255
+ console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, "color: #dc2626; font-weight: bold;");
256
+ console.groupEnd();
257
+ };
258
+ var displayBootLog = (windowSize) => {
259
+ if (!isWeb) return;
260
+ 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;");
301
261
  };
302
262
 
303
263
  // src/core/constants.ts
304
264
  var WINDOW_SIZE = 50;
305
265
  var SIMILARITY_THRESHOLD = 0.88;
306
266
  var LOOP_THRESHOLD = 150;
307
- var ANALYSIS_INTERVAL = 5;
308
267
  var VOLATILITY_THRESHOLD = 25;
309
268
 
269
+ // src/core/analysis.ts
270
+ var calculateAllSimilarities = (entryA, entryB) => {
271
+ const sync = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 0);
272
+ const bA = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 1);
273
+ const aB = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, -1);
274
+ return { sync, bA, aB, max: Math.max(sync, bA, aB) };
275
+ };
276
+ var shouldSkipComparison = (entryA, entryB, dirtyLabels2) => {
277
+ if (entryA.label === entryB.label) return true;
278
+ if (dirtyLabels2.has(entryB.label) && entryA.label > entryB.label) return true;
279
+ return false;
280
+ };
281
+ var detectRedundancy = (entryA, entryB, similarities, redundantSet) => {
282
+ const roleA = entryA.meta.role;
283
+ const roleB = entryB.meta.role;
284
+ if (roleA === "context" /* CONTEXT */ && roleB === "context" /* CONTEXT */) return;
285
+ if (entryA.meta.density < 2 || entryB.meta.density < 2) return;
286
+ if (roleA === "local" /* LOCAL */ && roleB === "context" /* CONTEXT */) {
287
+ redundantSet.add(entryA.label);
288
+ displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
289
+ } else if (roleA === "context" /* CONTEXT */ && roleB === "local" /* LOCAL */) {
290
+ redundantSet.add(entryB.label);
291
+ displayRedundancyAlert(entryB.label, entryB.meta, entryA.label, entryA.meta, similarities.max);
292
+ } else if (roleA === "local" /* LOCAL */ && roleB === "local" /* LOCAL */) {
293
+ redundantSet.add(entryA.label);
294
+ redundantSet.add(entryB.label);
295
+ displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
296
+ }
297
+ };
298
+ var detectCausalLeak = (entryA, entryB, similarities) => {
299
+ if (entryA.isVolatile || entryB.isVolatile) return;
300
+ if (similarities.bA === similarities.max) {
301
+ displayCausalHint(entryB.label, entryB.meta, entryA.label, entryA.meta);
302
+ } else if (similarities.aB === similarities.max) {
303
+ displayCausalHint(entryA.label, entryA.meta, entryB.label, entryB.meta);
304
+ }
305
+ };
306
+ var detectSubspaceOverlap = (dirtyEntries, allEntries, redundantSet, dirtyLabels2) => {
307
+ let compCount = 0;
308
+ for (const entryA of dirtyEntries) {
309
+ for (const entryB of allEntries) {
310
+ if (shouldSkipComparison(entryA, entryB, dirtyLabels2)) continue;
311
+ compCount++;
312
+ const similarities = calculateAllSimilarities(entryA, entryB);
313
+ if (similarities.max > SIMILARITY_THRESHOLD) {
314
+ detectRedundancy(entryA, entryB, similarities, redundantSet);
315
+ detectCausalLeak(entryA, entryB, similarities);
316
+ }
317
+ }
318
+ }
319
+ return compCount;
320
+ };
321
+
310
322
  // src/engine.ts
311
323
  var BASIS_INSTANCE_KEY = /* @__PURE__ */ Symbol.for("__basis_engine_instance__");
324
+ var NULL_SIGNAL = {
325
+ role: "proj" /* PROJECTION */,
326
+ buffer: new Uint8Array(0),
327
+ head: 0,
328
+ density: 0,
329
+ options: {}
330
+ };
312
331
  var getGlobalInstance = () => {
313
332
  const root = globalThis;
314
333
  if (!root[BASIS_INSTANCE_KEY]) {
@@ -322,7 +341,12 @@ var getGlobalInstance = () => {
322
341
  isBatching: false,
323
342
  currentEffectSource: null,
324
343
  pausedVariables: /* @__PURE__ */ new Set(),
325
- metrics: { lastAnalysisTimeMs: 0, comparisonCount: 0, lastAnalysisTimestamp: 0 },
344
+ metrics: {
345
+ lastAnalysisTimeMs: 0,
346
+ comparisonCount: 0,
347
+ lastAnalysisTimestamp: 0,
348
+ systemEntropy: 0
349
+ },
326
350
  alertCount: 0,
327
351
  loopCounters: /* @__PURE__ */ new Map(),
328
352
  lastCleanup: Date.now()
@@ -331,62 +355,61 @@ var getGlobalInstance = () => {
331
355
  return root[BASIS_INSTANCE_KEY];
332
356
  };
333
357
  var instance = getGlobalInstance();
334
- var { config, history, redundantLabels, currentTickBatch } = instance;
358
+ var config = instance.config;
359
+ var history = instance.history;
360
+ var redundantLabels = instance.redundantLabels;
361
+ var currentTickBatch = instance.currentTickBatch;
335
362
  var currentTickRegistry = {};
336
363
  var dirtyLabels = /* @__PURE__ */ new Set();
364
+ var calculateTickEntropy = (tickIdx) => {
365
+ let activeCount = 0;
366
+ const total = instance.history.size;
367
+ if (total === 0) return 1;
368
+ instance.history.forEach((meta) => {
369
+ if (meta.buffer[tickIdx] === 1) activeCount++;
370
+ });
371
+ return 1 - activeCount / total;
372
+ };
337
373
  var analyzeBasis = () => {
338
- if (!instance.config.debug) {
339
- instance.redundantLabels.clear();
374
+ if (!instance.config.debug || dirtyLabels.size === 0) {
340
375
  return;
341
376
  }
342
377
  const scheduler = globalThis.requestIdleCallback || ((cb) => setTimeout(cb, 1));
378
+ const snapshot = new Set(dirtyLabels);
379
+ dirtyLabels.clear();
343
380
  scheduler(() => {
344
381
  const analysisStart = performance.now();
345
- if (dirtyLabels.size === 0) return;
346
382
  const allEntries = [];
347
383
  const dirtyEntries = [];
348
384
  instance.history.forEach((meta, label) => {
349
- if (meta.options.suppressAll) return;
350
- let density = 0;
351
- for (let k = 0; k < meta.buffer.length; k++) density += meta.buffer[k];
352
- if (density >= 2) {
353
- const entry = { label, meta, density };
354
- allEntries.push(entry);
355
- if (dirtyLabels.has(label)) dirtyEntries.push(entry);
385
+ if (meta.options.suppressAll || meta.density === 0) return;
386
+ const entry = {
387
+ label,
388
+ meta,
389
+ isVolatile: meta.density > VOLATILITY_THRESHOLD
390
+ };
391
+ allEntries.push(entry);
392
+ if (snapshot.has(label)) {
393
+ dirtyEntries.push(entry);
356
394
  }
357
395
  });
358
- if (dirtyEntries.length === 0 || allEntries.length < 2) {
359
- dirtyLabels.clear();
360
- return;
361
- }
396
+ if (dirtyEntries.length === 0 || allEntries.length < 2) return;
362
397
  const nextRedundant = /* @__PURE__ */ new Set();
363
- let compCount = 0;
364
398
  instance.redundantLabels.forEach((l) => {
365
- if (!dirtyLabels.has(l)) nextRedundant.add(l);
366
- });
367
- for (const dirtyEntry of dirtyEntries) {
368
- for (const otherEntry of allEntries) {
369
- if (dirtyEntry.label === otherEntry.label) continue;
370
- if (dirtyLabels.has(otherEntry.label) && dirtyEntry.label > otherEntry.label) continue;
371
- compCount++;
372
- const sync = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 0);
373
- const bA = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 1);
374
- const aB = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, -1);
375
- const maxSim = Math.max(sync, bA, aB);
376
- if (maxSim > SIMILARITY_THRESHOLD) {
377
- const bothVolatile = dirtyEntry.density > VOLATILITY_THRESHOLD && otherEntry.density > VOLATILITY_THRESHOLD;
378
- if (sync === maxSim && !bothVolatile) {
379
- nextRedundant.add(dirtyEntry.label);
380
- nextRedundant.add(otherEntry.label);
381
- displayRedundancyAlert(dirtyEntry.label, otherEntry.label, sync);
382
- } else if (bA === maxSim) displayCausalHint(otherEntry.label, dirtyEntry.label, "math");
383
- else if (aB === maxSim) displayCausalHint(dirtyEntry.label, otherEntry.label, "math");
384
- }
399
+ if (!snapshot.has(l)) {
400
+ nextRedundant.add(l);
385
401
  }
386
- }
387
- dirtyLabels.clear();
402
+ });
403
+ const compCount = detectSubspaceOverlap(
404
+ dirtyEntries,
405
+ allEntries,
406
+ nextRedundant,
407
+ snapshot
408
+ );
388
409
  instance.redundantLabels.clear();
389
- nextRedundant.forEach((l) => instance.redundantLabels.add(l));
410
+ nextRedundant.forEach((l) => {
411
+ instance.redundantLabels.add(l);
412
+ });
390
413
  instance.metrics.lastAnalysisTimeMs = performance.now() - analysisStart;
391
414
  instance.metrics.comparisonCount = compCount;
392
415
  instance.metrics.lastAnalysisTimestamp = Date.now();
@@ -395,13 +418,22 @@ var analyzeBasis = () => {
395
418
  var processHeartbeat = () => {
396
419
  instance.tick++;
397
420
  instance.history.forEach((meta, label) => {
398
- meta.buffer[meta.head] = instance.currentTickBatch.has(label) ? 1 : 0;
421
+ const oldValue = meta.buffer[meta.head];
422
+ const newValue = instance.currentTickBatch.has(label) ? 1 : 0;
423
+ meta.buffer[meta.head] = newValue;
424
+ if (oldValue !== newValue) {
425
+ meta.density += newValue - oldValue;
426
+ }
399
427
  meta.head = (meta.head + 1) % WINDOW_SIZE;
400
428
  });
429
+ const lastHead = instance.history.size > 0 ? instance.tick % WINDOW_SIZE : 0;
430
+ instance.metrics.systemEntropy = calculateTickEntropy(lastHead);
401
431
  instance.currentTickBatch.clear();
402
432
  currentTickRegistry = {};
403
433
  instance.isBatching = false;
404
- if (instance.tick % ANALYSIS_INTERVAL === 0) analyzeBasis();
434
+ if (dirtyLabels.size > 0) {
435
+ analyzeBasis();
436
+ }
405
437
  };
406
438
  var recordUpdate = (label) => {
407
439
  if (!instance.config.debug) return true;
@@ -419,7 +451,15 @@ var recordUpdate = (label) => {
419
451
  return false;
420
452
  }
421
453
  if (instance.currentEffectSource && instance.currentEffectSource !== label) {
422
- displayCausalHint(label, instance.currentEffectSource, "tracking");
454
+ const targetMeta = instance.history.get(label);
455
+ const sourceMeta = instance.history.get(instance.currentEffectSource);
456
+ if (targetMeta) {
457
+ const sourceDensity = sourceMeta?.density || 0;
458
+ const isVolatile = targetMeta.density > VOLATILITY_THRESHOLD || sourceDensity > VOLATILITY_THRESHOLD;
459
+ if (!isVolatile) {
460
+ displayCausalHint(label, targetMeta, instance.currentEffectSource, sourceMeta || NULL_SIGNAL);
461
+ }
462
+ }
423
463
  }
424
464
  if (currentTickRegistry[label]) return true;
425
465
  currentTickRegistry[label] = true;
@@ -441,11 +481,20 @@ var configureBasis = (c) => {
441
481
  var registerVariable = (l, o = {}) => {
442
482
  if (!instance.config.debug || o.suppressAll) return;
443
483
  if (!instance.history.has(l)) {
444
- instance.history.set(l, { buffer: new Uint8Array(WINDOW_SIZE), head: 0, options: o });
484
+ instance.history.set(l, {
485
+ buffer: new Uint8Array(WINDOW_SIZE),
486
+ head: 0,
487
+ density: 0,
488
+ options: o,
489
+ role: o.role || "local" /* LOCAL */
490
+ });
445
491
  }
446
492
  };
447
493
  var unregisterVariable = (l) => {
448
494
  instance.history.delete(l);
495
+ instance.loopCounters.delete(l);
496
+ instance.pausedVariables.delete(l);
497
+ instance.redundantLabels.delete(l);
449
498
  };
450
499
  var beginEffectTracking = (l) => {
451
500
  if (instance.config.debug) instance.currentEffectSource = l;
@@ -454,67 +503,47 @@ var endEffectTracking = () => {
454
503
  instance.currentEffectSource = null;
455
504
  };
456
505
  var printBasisHealthReport = (threshold = 0.5) => {
457
- if (!instance.config.debug) {
458
- console.warn("[Basis] Cannot generate report. Debug mode is OFF.");
459
- return;
460
- }
506
+ if (!instance.config.debug) return;
461
507
  displayHealthReport(instance.history, threshold);
462
508
  };
463
509
  var getBasisMetrics = () => ({
464
- engine: "v0.4.2 (Ring Buffer)",
510
+ engine: "v0.5.x",
465
511
  hooks: instance.history.size,
466
- load: instance.metrics.comparisonCount,
467
- analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3)
512
+ analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3),
513
+ entropy: instance.metrics.systemEntropy.toFixed(3)
468
514
  });
469
515
  if (typeof window !== "undefined") {
470
516
  window.printBasisReport = printBasisHealthReport;
471
517
  window.getBasisMetrics = getBasisMetrics;
472
518
  }
473
- var __testEngine__ = {
474
- instance,
475
- history: instance.history,
476
- configureBasis,
477
- registerVariable,
478
- unregisterVariable,
479
- recordUpdate,
480
- printBasisHealthReport,
481
- beginEffectTracking,
482
- endEffectTracking
483
- };
484
519
 
485
520
  // src/hooks.ts
486
521
  var anonCount = 0;
487
522
  var getFallbackLabel = (type) => `anon_${type}_${anonCount++}`;
523
+ var React19 = React;
488
524
  function useState(initialState, label) {
489
525
  const [val, setVal] = (0, import_react.useState)(initialState);
490
526
  const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("state")).current;
491
527
  (0, import_react.useEffect)(() => {
492
- registerVariable(effectiveLabel);
528
+ registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
493
529
  return () => {
494
530
  unregisterVariable(effectiveLabel);
495
531
  };
496
532
  }, [effectiveLabel]);
497
- const setter = (0, import_react.useCallback)((newValue) => {
533
+ const setter = (0, import_react.useCallback)((value) => {
498
534
  if (recordUpdate(effectiveLabel)) {
499
- setVal(newValue);
535
+ setVal(value);
500
536
  }
501
537
  }, [effectiveLabel]);
502
538
  return [val, setter];
503
539
  }
504
- function useRef(initialValue, _label) {
505
- return (0, import_react.useRef)(initialValue);
506
- }
507
540
  function useReducer(reducer, initialArg, init, label) {
508
- const isLazyInit = typeof init === "function";
509
- const providedLabel = isLazyInit ? label : typeof init === "string" ? init : void 0;
541
+ const isLazy = typeof init === "function";
542
+ const providedLabel = label || (typeof init === "string" ? init : void 0);
510
543
  const effectiveLabel = (0, import_react.useRef)(providedLabel || getFallbackLabel("reducer")).current;
511
- const [state, dispatch] = (0, import_react.useReducer)(
512
- reducer,
513
- initialArg,
514
- isLazyInit ? init : void 0
515
- );
544
+ const [state, dispatch] = isLazy ? (0, import_react.useReducer)(reducer, initialArg, init) : (0, import_react.useReducer)(reducer, initialArg);
516
545
  (0, import_react.useEffect)(() => {
517
- registerVariable(effectiveLabel);
546
+ registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
518
547
  return () => {
519
548
  unregisterVariable(effectiveLabel);
520
549
  };
@@ -523,20 +552,47 @@ function useReducer(reducer, initialArg, init, label) {
523
552
  if (recordUpdate(effectiveLabel)) {
524
553
  dispatch(action);
525
554
  }
526
- }, [effectiveLabel]);
555
+ }, [effectiveLabel, dispatch]);
527
556
  return [state, basisDispatch];
528
557
  }
558
+ function createContext(defaultValue, label) {
559
+ const context = (0, import_react.createContext)(defaultValue);
560
+ const effectiveLabel = label || getFallbackLabel("context");
561
+ Object.defineProperty(context, "_basis_label", {
562
+ value: effectiveLabel,
563
+ writable: false,
564
+ enumerable: false
565
+ });
566
+ return context;
567
+ }
568
+ function useContext(context) {
569
+ const val = (0, import_react.useContext)(context);
570
+ const label = context._basis_label;
571
+ (0, import_react.useLayoutEffect)(() => {
572
+ if (label) {
573
+ registerVariable(label, { role: "context" /* CONTEXT */ });
574
+ recordUpdate(label);
575
+ }
576
+ }, [val, label]);
577
+ return val;
578
+ }
529
579
  function useMemo(factory, deps, label) {
530
- const effectiveLabel = label || "anonymous_projection";
580
+ const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("proj")).current;
531
581
  (0, import_react.useEffect)(() => {
532
- if (config.debug) console.log(`%c [Basis] Valid Projection: "${effectiveLabel}" `, "color: #2ecc71; font-weight: bold;");
582
+ registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
583
+ return () => {
584
+ unregisterVariable(effectiveLabel);
585
+ };
533
586
  }, [effectiveLabel]);
534
587
  return (0, import_react.useMemo)(factory, deps || []);
535
588
  }
536
589
  function useCallback(callback, deps, label) {
537
- const effectiveLabel = label || "anonymous_callback";
590
+ const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("cb")).current;
538
591
  (0, import_react.useEffect)(() => {
539
- if (config.debug) console.log(`%c [Basis] Stable Callback: "${effectiveLabel}" `, "color: #2ecc71; font-weight: bold;");
592
+ registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
593
+ return () => {
594
+ unregisterVariable(effectiveLabel);
595
+ };
540
596
  }, [effectiveLabel]);
541
597
  return (0, import_react.useCallback)(callback, deps);
542
598
  }
@@ -544,56 +600,29 @@ function useEffect(effect, deps, label) {
544
600
  const effectiveLabel = label || "anonymous_effect";
545
601
  (0, import_react.useEffect)(() => {
546
602
  beginEffectTracking(effectiveLabel);
547
- const cleanup = effect();
603
+ const destructor = effect();
548
604
  endEffectTracking();
549
- return cleanup;
605
+ return typeof destructor === "function" ? destructor : void 0;
550
606
  }, deps);
551
607
  }
552
608
  function useLayoutEffect(effect, deps, label) {
553
609
  const effectiveLabel = label || "anonymous_layout_effect";
554
610
  (0, import_react.useLayoutEffect)(() => {
555
611
  beginEffectTracking(effectiveLabel);
556
- const cleanup = effect();
612
+ const destructor = effect();
557
613
  endEffectTracking();
558
- return cleanup;
614
+ return typeof destructor === "function" ? destructor : void 0;
559
615
  }, deps);
560
616
  }
561
- function useTransition(_label) {
562
- const [isPending, startTransition] = (0, import_react.useTransition)();
563
- const effectiveLabel = _label || "anonymous_transition";
564
- const basisStartTransition = (callback) => {
565
- if (config.debug) console.log(`%c [Basis] Transition Started: "${effectiveLabel}" `, "color: #e67e22; font-weight: bold;");
566
- startTransition(callback);
567
- };
568
- return [isPending, basisStartTransition];
569
- }
570
- function useDeferredValue(value, initialValueOrLabel, label) {
571
- const isLabelAsSecondArg = typeof initialValueOrLabel === "string" && label === void 0;
572
- const actualInitialValue = isLabelAsSecondArg ? void 0 : initialValueOrLabel;
573
- const effectiveLabel = isLabelAsSecondArg ? initialValueOrLabel : label || "anonymous_deferred";
574
- const deferredValue = (0, import_react.useDeferredValue)(value, actualInitialValue);
575
- (0, import_react.useEffect)(() => {
576
- if (config.debug && value !== deferredValue) console.log(`%c [Basis] Value Deferred: "${effectiveLabel}" `, "color: #e67e22; font-weight: bold;");
577
- }, [value, deferredValue, effectiveLabel]);
578
- return deferredValue;
579
- }
580
- var useId2 = (label) => React.useId();
581
- var useDebugValue2 = React.useDebugValue;
582
- var useImperativeHandle2 = React.useImperativeHandle;
583
- var useInsertionEffect2 = React.useInsertionEffect;
584
- var useSyncExternalStore = import_react.useSyncExternalStore;
585
- function use(usable) {
586
- return (0, import_react.use)(usable);
587
- }
588
- function useOptimistic2(passthrough, reducer, label) {
589
- const effectiveLabel = label || "anonymous_optimistic";
617
+ function useOptimistic(passthrough, reducer, label) {
618
+ const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("optimistic")).current;
590
619
  (0, import_react.useEffect)(() => {
591
- registerVariable(effectiveLabel);
620
+ registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
592
621
  return () => {
593
622
  unregisterVariable(effectiveLabel);
594
623
  };
595
624
  }, [effectiveLabel]);
596
- const [state, reactAddOptimistic] = React.useOptimistic(passthrough, reducer);
625
+ const [state, reactAddOptimistic] = React19.useOptimistic(passthrough, reducer);
597
626
  const addOptimistic = (0, import_react.useCallback)((payload) => {
598
627
  if (recordUpdate(effectiveLabel)) {
599
628
  reactAddOptimistic(payload);
@@ -601,17 +630,13 @@ function useOptimistic2(passthrough, reducer, label) {
601
630
  }, [effectiveLabel, reactAddOptimistic]);
602
631
  return [state, addOptimistic];
603
632
  }
604
- function useActionState2(action, initialState, permalink, label) {
605
- const isLabelAsThirdArg = typeof permalink === "string" && label === void 0;
606
- const actualPermalink = isLabelAsThirdArg ? void 0 : permalink;
607
- const effectiveLabel = isLabelAsThirdArg ? permalink : label || "anonymous_action_state";
608
- const [state, reactDispatch, isPending] = React.useActionState(
609
- action,
610
- initialState,
611
- actualPermalink
612
- );
633
+ function useActionState(action, initialState, permalink, label) {
634
+ const isLabelArg = typeof permalink === "string" && label === void 0;
635
+ const effectiveLabel = (0, import_react.useRef)(isLabelArg ? permalink : label || getFallbackLabel("action_state")).current;
636
+ const actualPermalink = isLabelArg ? void 0 : permalink;
637
+ const [state, reactDispatch, isPending] = React19.useActionState(action, initialState, actualPermalink);
613
638
  (0, import_react.useEffect)(() => {
614
- registerVariable(effectiveLabel);
639
+ registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
615
640
  return () => {
616
641
  unregisterVariable(effectiveLabel);
617
642
  };
@@ -623,6 +648,15 @@ function useActionState2(action, initialState, permalink, label) {
623
648
  }, [effectiveLabel, reactDispatch]);
624
649
  return [state, basisDispatch, isPending];
625
650
  }
651
+ var useRef = import_react.useRef;
652
+ var useId2 = React.useId;
653
+ var useDebugValue2 = React.useDebugValue;
654
+ var useImperativeHandle2 = React.useImperativeHandle;
655
+ var useInsertionEffect2 = React.useInsertionEffect;
656
+ var useSyncExternalStore = import_react.useSyncExternalStore;
657
+ var useTransition = import_react.useTransition;
658
+ var useDeferredValue = import_react.useDeferredValue;
659
+ var use = React19.use;
626
660
 
627
661
  // src/context.tsx
628
662
  var import_react3 = require("react");
@@ -674,10 +708,15 @@ var BasisHUD = () => {
674
708
  const canvasRef = (0, import_react2.useRef)(null);
675
709
  (0, import_react2.useEffect)(() => {
676
710
  if (!isExpanded) return;
677
- let animationFrame;
678
711
  let isMounted = true;
712
+ let animationFrame = null;
679
713
  const draw = () => {
680
- if (!isMounted) return;
714
+ if (!isMounted) {
715
+ if (animationFrame !== null) {
716
+ cancelAnimationFrame(animationFrame);
717
+ }
718
+ return;
719
+ }
681
720
  const canvas = canvasRef.current;
682
721
  if (!canvas) return;
683
722
  const ctx = canvas.getContext("2d");
@@ -685,31 +724,27 @@ var BasisHUD = () => {
685
724
  const entries = Array.from(history.entries());
686
725
  const dpr = window.devicePixelRatio || 1;
687
726
  const rawWidth = HUD_DIMENSIONS.WINDOW_SIZE * HUD_DIMENSIONS.COL_WIDTH + HUD_DIMENSIONS.LABEL_WIDTH + HUD_DIMENSIONS.PADDING * 2;
688
- const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2, 60);
727
+ const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2, 80);
689
728
  updateCanvasSize(canvas, rawWidth, rawHeight, dpr);
690
729
  ctx.save();
691
730
  ctx.scale(dpr, dpr);
692
731
  ctx.clearRect(0, 0, rawWidth, rawHeight);
693
- if (entries.length === 0) {
694
- renderEmptyState(ctx);
695
- } else {
696
- renderMatrix(ctx, entries);
697
- }
732
+ if (entries.length === 0) renderEmptyState(ctx);
733
+ else renderMatrix(ctx, entries);
698
734
  ctx.restore();
699
735
  animationFrame = requestAnimationFrame(draw);
700
736
  };
701
- draw();
737
+ animationFrame = requestAnimationFrame(draw);
702
738
  return () => {
703
739
  isMounted = false;
704
- cancelAnimationFrame(animationFrame);
740
+ if (animationFrame !== null) {
741
+ cancelAnimationFrame(animationFrame);
742
+ }
705
743
  };
706
744
  }, [isExpanded]);
707
745
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: getHUDContainerStyle(isExpanded), onClick: () => setIsExpanded(!isExpanded), children: [
708
746
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HUDHeader, { isExpanded }),
709
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "10px 14px 15px 14px" }, children: [
710
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("canvas", { ref: canvasRef, style: { display: "block" } }),
711
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HUDFooter, {})
712
- ] })
747
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "10px 14px 15px 14px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("canvas", { ref: canvasRef, style: { display: "block" } }) })
713
748
  ] });
714
749
  };
715
750
  function updateCanvasSize(canvas, w, h, dpr) {
@@ -736,18 +771,22 @@ function renderMatrix(ctx, entries) {
736
771
  const cellH = rowH - 4;
737
772
  const gridPath = new Path2D();
738
773
  const successPath = new Path2D();
774
+ const contextPath = new Path2D();
739
775
  const errorPath = new Path2D();
740
776
  ctx.font = "11px Inter, Menlo, monospace";
741
777
  let rowIndex = 0;
742
778
  for (const [label, meta] of entries) {
743
779
  const y = rowIndex * rowH + pad;
744
- const isRedundant = redundantLabels.has(label);
780
+ const isContext = meta.role === "context";
781
+ const isRedundant = !isContext && redundantLabels.has(label);
745
782
  const { buffer, head } = meta;
746
783
  let uiPos = 0;
747
784
  const addToPath = (val, xIdx) => {
748
785
  const x = xIdx * colW + pad;
749
786
  if (val === 1) {
750
- (isRedundant ? errorPath : successPath).rect(x, y, cellW, cellH);
787
+ if (isContext) contextPath.rect(x, y, cellW, cellH);
788
+ else if (isRedundant) errorPath.rect(x, y, cellW, cellH);
789
+ else successPath.rect(x, y, cellW, cellH);
751
790
  } else {
752
791
  gridPath.rect(x, y, cellW, cellH);
753
792
  }
@@ -756,17 +795,16 @@ function renderMatrix(ctx, entries) {
756
795
  for (let i = 0; i < head; i++) addToPath(buffer[i], uiPos++);
757
796
  const stateName = label.split(" -> ")[1] || label;
758
797
  const textX = L * colW + pad + 10;
759
- let density = 0;
760
- for (let i = 0; i < L; i++) density += buffer[i];
761
- const isVolatile = density > 25;
762
- ctx.fillStyle = isRedundant ? HUD_THEME.error : isVolatile ? HUD_THEME.success : HUD_THEME.text;
763
- ctx.fillText((isRedundant ? "! " : isVolatile ? "~ " : "") + stateName, textX, y + 9);
798
+ ctx.fillStyle = isContext ? HUD_THEME.header : isRedundant ? HUD_THEME.error : HUD_THEME.text;
799
+ ctx.fillText((isContext ? "\u03A9 " : isRedundant ? "! " : "") + stateName, textX, y + 9);
764
800
  rowIndex++;
765
801
  }
766
802
  ctx.fillStyle = HUD_THEME.grid;
767
803
  ctx.fill(gridPath);
768
804
  ctx.fillStyle = HUD_THEME.success;
769
805
  ctx.fill(successPath);
806
+ ctx.fillStyle = HUD_THEME.header;
807
+ ctx.fill(contextPath);
770
808
  ctx.fillStyle = HUD_THEME.error;
771
809
  ctx.fill(errorPath);
772
810
  }
@@ -787,25 +825,7 @@ var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)
787
825
  },
788
826
  children: [
789
827
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: isExpanded ? "STATE BASIS MATRIX" : "\u{1F4D0} BASIS ACTIVE" }),
790
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.4.2" })
791
- ]
792
- }
793
- );
794
- var HUDFooter = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
795
- "div",
796
- {
797
- style: {
798
- marginTop: "12px",
799
- paddingTop: "8px",
800
- borderTop: `1px solid ${HUD_THEME.grid}`,
801
- color: HUD_THEME.textDim,
802
- fontSize: "9px",
803
- display: "flex",
804
- justifyContent: "space-between"
805
- },
806
- children: [
807
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "RING BUFFER ENGINE" }),
808
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "ZERO ALLOC" })
828
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.5.x" })
809
829
  ]
810
830
  }
811
831
  );
@@ -814,7 +834,11 @@ var HUDFooter = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
814
834
  var import_jsx_runtime2 = require("react/jsx-runtime");
815
835
  var BasisContext = (0, import_react3.createContext)({ debug: false });
816
836
  var isWeb2 = typeof window !== "undefined" && typeof window.document !== "undefined";
817
- var BasisProvider = ({ children, debug = true }) => {
837
+ var BasisProvider = ({
838
+ children,
839
+ debug = true,
840
+ showHUD = true
841
+ }) => {
818
842
  (0, import_react3.useLayoutEffect)(() => {
819
843
  configureBasis({ debug });
820
844
  if (isWeb2) {
@@ -823,7 +847,7 @@ var BasisProvider = ({ children, debug = true }) => {
823
847
  }, [debug]);
824
848
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(BasisContext.Provider, { value: { debug }, children: [
825
849
  children,
826
- debug && isWeb2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BasisHUD, {})
850
+ debug && showHUD && isWeb2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BasisHUD, {})
827
851
  ] });
828
852
  };
829
853
  var useBasisConfig = () => (0, import_react3.useContext)(BasisContext);
@@ -846,12 +870,14 @@ function basis() {
846
870
  BasisProvider,
847
871
  basis,
848
872
  configureBasis,
873
+ createContext,
849
874
  getBasisMetrics,
850
875
  printBasisHealthReport,
851
876
  use,
852
877
  useActionState,
853
878
  useBasisConfig,
854
879
  useCallback,
880
+ useContext,
855
881
  useDebugValue,
856
882
  useDeferredValue,
857
883
  useEffect,