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/README.md +53 -17
- package/dist/chunk-O2ZOR3L2.mjs +869 -0
- package/dist/chunk-O2ZOR3L2.mjs.map +1 -0
- package/dist/index.js +534 -126
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -464
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/zustand-production.d.mts +3 -0
- package/dist/integrations/zustand-production.d.ts +3 -0
- package/dist/integrations/zustand-production.js +31 -0
- package/dist/integrations/zustand-production.js.map +1 -0
- package/dist/integrations/zustand-production.mjs +6 -0
- package/dist/integrations/zustand-production.mjs.map +1 -0
- package/dist/integrations/zustand.d.mts +6 -0
- package/dist/integrations/zustand.d.ts +6 -0
- package/dist/integrations/zustand.js +887 -0
- package/dist/integrations/zustand.js.map +1 -0
- package/dist/integrations/zustand.mjs +33 -0
- package/dist/integrations/zustand.mjs.map +1 -0
- package/package.json +22 -3
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
|
-
|
|
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.
|
|
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
|
|
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 (
|
|
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 &&
|
|
371
|
+
debug && showHUD && isWeb && /* @__PURE__ */ jsx2(BasisHUD, {})
|
|
808
372
|
] });
|
|
809
373
|
};
|
|
810
374
|
var useBasisConfig = () => useContext2(BasisContext);
|