react-state-basis 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -12
- package/dist/index.d.mts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +312 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +311 -203
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -20,6 +20,36 @@ import {
|
|
|
20
20
|
use as reactUse
|
|
21
21
|
} from "react";
|
|
22
22
|
|
|
23
|
+
// src/core/math.ts
|
|
24
|
+
var calculateSimilarityCircular = (bufferA, headA, bufferB, headB, offset) => {
|
|
25
|
+
const L = bufferA.length;
|
|
26
|
+
let dot = 0;
|
|
27
|
+
let magA = 0;
|
|
28
|
+
let magB = 0;
|
|
29
|
+
const headOffset = headB - headA + offset;
|
|
30
|
+
for (let i = 0; i < L; i++) {
|
|
31
|
+
const valA = bufferA[i];
|
|
32
|
+
let iB = i + headOffset;
|
|
33
|
+
if (iB < 0) iB += L;
|
|
34
|
+
else if (iB >= L) iB -= L;
|
|
35
|
+
const valB = bufferB[iB];
|
|
36
|
+
dot += valA * valB;
|
|
37
|
+
magA += valA * valA;
|
|
38
|
+
magB += valB * valB;
|
|
39
|
+
}
|
|
40
|
+
if (magA === 0 || magB === 0) return 0;
|
|
41
|
+
return dot / (Math.sqrt(magA) * Math.sqrt(magB));
|
|
42
|
+
};
|
|
43
|
+
var calculateCosineSimilarity = (A, B) => {
|
|
44
|
+
let dot = 0, magA = 0, magB = 0;
|
|
45
|
+
for (let i = 0; i < A.length; i++) {
|
|
46
|
+
dot += A[i] * B[i];
|
|
47
|
+
magA += A[i] * A[i];
|
|
48
|
+
magB += B[i] * B[i];
|
|
49
|
+
}
|
|
50
|
+
return magA === 0 || magB === 0 ? 0 : dot / (Math.sqrt(magA) * Math.sqrt(magB));
|
|
51
|
+
};
|
|
52
|
+
|
|
23
53
|
// src/core/logger.ts
|
|
24
54
|
var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
25
55
|
var LAST_LOG_TIMES = /* @__PURE__ */ new Map();
|
|
@@ -32,9 +62,11 @@ var STYLES = {
|
|
|
32
62
|
headerGreen: "background: #00b894; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
|
|
33
63
|
label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;",
|
|
34
64
|
location: "color: #0984e3; font-family: monospace; font-weight: bold;",
|
|
35
|
-
|
|
65
|
+
impact: "background: #f1f2f6; color: #2f3542; padding: 0 4px; border-radius: 3px; font-weight: bold;",
|
|
36
66
|
subText: "color: #636e72; font-size: 11px;",
|
|
37
|
-
bold: "font-weight: bold;"
|
|
67
|
+
bold: "font-weight: bold;",
|
|
68
|
+
actionMemo: "color: #00b894; font-weight: bold; border: 1px solid #00b894; padding: 0 4px; border-radius: 3px;",
|
|
69
|
+
actionDelete: "color: #d63031; font-weight: bold; border: 1px solid #d63031; padding: 0 4px; border-radius: 3px;"
|
|
38
70
|
};
|
|
39
71
|
var parseLabel = (label) => {
|
|
40
72
|
const parts = label.split(" -> ");
|
|
@@ -68,11 +100,11 @@ var displayRedundancyAlert = (labelA, labelB, sim) => {
|
|
|
68
100
|
if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
|
|
69
101
|
const infoA = parseLabel(labelA);
|
|
70
102
|
const infoB = parseLabel(labelB);
|
|
71
|
-
console.group(`%c \
|
|
103
|
+
console.group(`%c \u264A BASIS | TWIN STATE DETECTED `, STYLES.headerRed);
|
|
72
104
|
console.log(`%c\u{1F4CD} Location: %c${infoA.file}`, STYLES.bold, STYLES.location);
|
|
73
105
|
console.log(
|
|
74
|
-
`%
|
|
75
|
-
%
|
|
106
|
+
`%cThe Rhythm:%c %c${infoA.name}%c and %c${infoB.name}%c are moving in perfect sync.
|
|
107
|
+
%cThis indicates that one is a redundant shadow of the other. Confidence: ${(sim * 100).toFixed(0)}%`,
|
|
76
108
|
STYLES.bold,
|
|
77
109
|
"",
|
|
78
110
|
STYLES.label,
|
|
@@ -82,10 +114,12 @@ var displayRedundancyAlert = (labelA, labelB, sim) => {
|
|
|
82
114
|
STYLES.subText
|
|
83
115
|
);
|
|
84
116
|
console.log(
|
|
85
|
-
`%
|
|
86
|
-
|
|
117
|
+
`%cRecommended Fix:%c Derive %c${infoB.name}%c from %c${infoA.name}%c during the render pass.`,
|
|
118
|
+
STYLES.bold,
|
|
119
|
+
"",
|
|
120
|
+
STYLES.actionMemo,
|
|
87
121
|
"",
|
|
88
|
-
|
|
122
|
+
STYLES.bold,
|
|
89
123
|
""
|
|
90
124
|
);
|
|
91
125
|
console.groupEnd();
|
|
@@ -96,12 +130,12 @@ var displayCausalHint = (targetLabel, sourceLabel, method = "math") => {
|
|
|
96
130
|
const target = parseLabel(targetLabel);
|
|
97
131
|
const source = parseLabel(sourceLabel);
|
|
98
132
|
console.groupCollapsed(
|
|
99
|
-
`%c \
|
|
133
|
+
`%c \u26A1 BASIS | DOUBLE RENDER CYCLE `,
|
|
100
134
|
STYLES.headerBlue
|
|
101
135
|
);
|
|
102
136
|
console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
|
|
103
137
|
console.log(
|
|
104
|
-
`%
|
|
138
|
+
`%cThe Rhythm:%c %c${source.name}%c pulses, then %c${target.name}%c pulses one frame later.`,
|
|
105
139
|
STYLES.bold,
|
|
106
140
|
"",
|
|
107
141
|
STYLES.label,
|
|
@@ -110,78 +144,112 @@ var displayCausalHint = (targetLabel, sourceLabel, method = "math") => {
|
|
|
110
144
|
""
|
|
111
145
|
);
|
|
112
146
|
console.log(
|
|
113
|
-
`%
|
|
114
|
-
%cResult:%c This creates a %cDouble Render Cycle%c.`,
|
|
147
|
+
`%cThe Impact:%c You are forcing %c2 render passes%c for a single logical change.`,
|
|
115
148
|
STYLES.bold,
|
|
116
149
|
"",
|
|
150
|
+
STYLES.impact,
|
|
151
|
+
""
|
|
152
|
+
);
|
|
153
|
+
console.log(
|
|
154
|
+
`%cRecommended Fix:%c Remove the useEffect. Calculate %c${target.name}%c as a derived value or projection.`,
|
|
117
155
|
STYLES.bold,
|
|
118
156
|
"",
|
|
119
|
-
|
|
157
|
+
STYLES.actionDelete,
|
|
120
158
|
""
|
|
121
159
|
);
|
|
122
160
|
console.groupEnd();
|
|
123
161
|
};
|
|
124
|
-
var
|
|
162
|
+
var displayViolentBreaker = (label, count, threshold) => {
|
|
125
163
|
if (!isWeb) return;
|
|
126
|
-
const
|
|
127
|
-
console.group(
|
|
128
|
-
|
|
164
|
+
const parts = label.split(" -> ");
|
|
165
|
+
console.group(
|
|
166
|
+
`%c \u26A0\uFE0F CRITICAL SYSTEM ALERT | BASIS ENGINE `,
|
|
167
|
+
"background: #dc2626; color: white; font-weight: bold; padding: 8px 16px; font-size: 14px;"
|
|
168
|
+
);
|
|
169
|
+
console.error(
|
|
170
|
+
`%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`,
|
|
171
|
+
"color: #dc2626; font-weight: bold;"
|
|
172
|
+
);
|
|
173
|
+
console.error(
|
|
174
|
+
`%cINFINITE LOOP DETECTED
|
|
175
|
+
|
|
176
|
+
%cVariable: %c${parts[1] || label}
|
|
177
|
+
%cUpdate Frequency: %c${count} updates/sec
|
|
178
|
+
%cExpected Maximum: %c${threshold} updates
|
|
179
|
+
|
|
180
|
+
%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`,
|
|
181
|
+
"color: #dc2626; font-size: 16px; font-weight: bold;",
|
|
182
|
+
"color: #71717a; font-weight: bold;",
|
|
183
|
+
`color: white; background: #dc2626; padding: 2px 8px;`,
|
|
184
|
+
"color: #71717a; font-weight: bold;",
|
|
185
|
+
`color: #fbbf24; font-weight: bold;`,
|
|
186
|
+
"color: #71717a; font-weight: bold;",
|
|
187
|
+
`color: #fbbf24; font-weight: bold;`,
|
|
188
|
+
"color: #dc2626; font-weight: bold;"
|
|
189
|
+
);
|
|
190
|
+
console.log(
|
|
191
|
+
`%cDIAGNOSTICS:
|
|
192
|
+
1. Check for setState inside the render body.
|
|
193
|
+
2. Verify useEffect dependencies (missing or unstable refs).
|
|
194
|
+
3. Look for circular chains (State A -> B -> A).
|
|
195
|
+
|
|
196
|
+
%cSYSTEM ACTION: Update BLOCKED. Fix your code to resume monitoring.`,
|
|
197
|
+
"color: #71717a;",
|
|
198
|
+
"color: #dc2626; font-weight: bold;"
|
|
199
|
+
);
|
|
129
200
|
console.groupEnd();
|
|
130
201
|
};
|
|
131
|
-
var displayHealthReport = (history2,
|
|
202
|
+
var displayHealthReport = (history2, threshold) => {
|
|
132
203
|
const entries = Array.from(history2.entries());
|
|
133
204
|
const totalVars = entries.length;
|
|
134
205
|
if (totalVars === 0) return;
|
|
135
206
|
const clusters = [];
|
|
136
207
|
const processed = /* @__PURE__ */ new Set();
|
|
137
208
|
let independentCount = 0;
|
|
138
|
-
entries.forEach(([labelA,
|
|
209
|
+
entries.forEach(([labelA, metaA]) => {
|
|
139
210
|
if (processed.has(labelA)) return;
|
|
140
211
|
const currentCluster = [labelA];
|
|
141
212
|
processed.add(labelA);
|
|
142
|
-
entries.forEach(([labelB,
|
|
213
|
+
entries.forEach(([labelB, metaB]) => {
|
|
143
214
|
if (labelA === labelB || processed.has(labelB)) return;
|
|
144
|
-
const sim =
|
|
215
|
+
const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
|
|
145
216
|
if (sim > threshold) {
|
|
146
217
|
currentCluster.push(labelB);
|
|
147
218
|
processed.add(labelB);
|
|
148
219
|
}
|
|
149
220
|
});
|
|
150
|
-
if (currentCluster.length > 1)
|
|
151
|
-
|
|
152
|
-
} else {
|
|
153
|
-
independentCount++;
|
|
154
|
-
}
|
|
221
|
+
if (currentCluster.length > 1) clusters.push(currentCluster);
|
|
222
|
+
else independentCount++;
|
|
155
223
|
});
|
|
156
224
|
const systemRank = independentCount + clusters.length;
|
|
157
225
|
const healthScore = systemRank / totalVars * 100;
|
|
158
226
|
if (isWeb) {
|
|
159
227
|
console.group(`%c \u{1F4CA} BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerGreen);
|
|
160
228
|
console.log(
|
|
161
|
-
`%
|
|
229
|
+
`%cSystem Efficiency: %c${healthScore.toFixed(1)}% %c(Basis Vectors: ${systemRank} / Total Hooks: ${totalVars})`,
|
|
162
230
|
STYLES.bold,
|
|
163
231
|
`color: ${healthScore > 85 ? "#00b894" : "#d63031"}; font-size: 16px; font-weight: bold;`,
|
|
164
232
|
"color: #636e72; font-style: italic;"
|
|
165
233
|
);
|
|
166
234
|
if (clusters.length > 0) {
|
|
167
|
-
console.log(`%cDetected ${clusters.length}
|
|
235
|
+
console.log(`%cDetected ${clusters.length} Entangled Clusters:`, "font-weight: bold; color: #e17055; margin-top: 10px;");
|
|
168
236
|
clusters.forEach((cluster, idx) => {
|
|
169
237
|
const names = cluster.map((l) => parseLabel(l).name).join(" \u27F7 ");
|
|
170
238
|
console.log(` %c${idx + 1}%c ${names}`, "background: #e17055; color: white; border-radius: 50%; padding: 0 5px;", "font-family: monospace;");
|
|
171
239
|
});
|
|
172
|
-
console.log("%c\u{1F4A1}
|
|
240
|
+
console.log("%c\u{1F4A1} Analysis: These variables are mirrored. Storing them separately creates unnecessary work for React.", STYLES.subText);
|
|
173
241
|
} else {
|
|
174
|
-
console.log("%c\u2728 All state variables
|
|
242
|
+
console.log("%c\u2728 All state variables are independent. Your architectural Basis is healthy.", "color: #00b894; font-weight: bold; margin-top: 10px;");
|
|
175
243
|
}
|
|
176
|
-
if (totalVars > 0 && totalVars <
|
|
244
|
+
if (totalVars > 0 && totalVars < 20) {
|
|
177
245
|
console.groupCollapsed("%cView Full Correlation Matrix", "color: #636e72; font-size: 11px;");
|
|
178
246
|
const matrix = {};
|
|
179
|
-
entries.forEach(([labelA]) => {
|
|
247
|
+
entries.forEach(([labelA, metaA]) => {
|
|
180
248
|
const nameA = parseLabel(labelA).name;
|
|
181
249
|
matrix[nameA] = {};
|
|
182
|
-
entries.forEach(([labelB]) => {
|
|
250
|
+
entries.forEach(([labelB, metaB]) => {
|
|
183
251
|
const nameB = parseLabel(labelB).name;
|
|
184
|
-
const sim =
|
|
252
|
+
const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
|
|
185
253
|
matrix[nameA][nameB] = sim > threshold ? `\u274C ${(sim * 100).toFixed(0)}%` : `\u2705`;
|
|
186
254
|
});
|
|
187
255
|
});
|
|
@@ -189,183 +257,185 @@ var displayHealthReport = (history2, similarityFn, threshold) => {
|
|
|
189
257
|
console.groupEnd();
|
|
190
258
|
}
|
|
191
259
|
console.groupEnd();
|
|
192
|
-
} else {
|
|
193
|
-
console.log(`[BASIS HEALTH] Score: ${healthScore.toFixed(1)}% (State Distribution: ${systemRank}/${totalVars})`);
|
|
194
260
|
}
|
|
195
261
|
};
|
|
196
262
|
|
|
197
|
-
// src/core/math.ts
|
|
198
|
-
var calculateSimilarityWithOffset = (A, B, offsetA, offsetB, length) => {
|
|
199
|
-
let dot = 0;
|
|
200
|
-
let magA = 0;
|
|
201
|
-
let magB = 0;
|
|
202
|
-
for (let i = 0; i < length; i++) {
|
|
203
|
-
const valA = A[i + offsetA];
|
|
204
|
-
const valB = B[i + offsetB];
|
|
205
|
-
dot += valA * valB;
|
|
206
|
-
magA += valA * valA;
|
|
207
|
-
magB += valB * valB;
|
|
208
|
-
}
|
|
209
|
-
if (magA === 0 || magB === 0) return 0;
|
|
210
|
-
return dot / (Math.sqrt(magA) * Math.sqrt(magB));
|
|
211
|
-
};
|
|
212
|
-
var calculateCosineSimilarity = (A, B) => {
|
|
213
|
-
return calculateSimilarityWithOffset(A, B, 0, 0, A.length);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
263
|
// src/core/constants.ts
|
|
217
264
|
var WINDOW_SIZE = 50;
|
|
218
265
|
var SIMILARITY_THRESHOLD = 0.88;
|
|
219
266
|
var LOOP_THRESHOLD = 150;
|
|
220
|
-
var LOOP_WINDOW_MS = 1e3;
|
|
221
267
|
var ANALYSIS_INTERVAL = 5;
|
|
222
268
|
var VOLATILITY_THRESHOLD = 25;
|
|
223
269
|
|
|
224
270
|
// src/engine.ts
|
|
225
|
-
var
|
|
271
|
+
var BASIS_INSTANCE_KEY = /* @__PURE__ */ Symbol.for("__basis_engine_instance__");
|
|
226
272
|
var getGlobalInstance = () => {
|
|
227
|
-
const
|
|
228
|
-
if (!
|
|
229
|
-
|
|
273
|
+
const root = globalThis;
|
|
274
|
+
if (!root[BASIS_INSTANCE_KEY]) {
|
|
275
|
+
root[BASIS_INSTANCE_KEY] = {
|
|
230
276
|
config: { debug: false },
|
|
231
277
|
history: /* @__PURE__ */ new Map(),
|
|
232
278
|
currentTickBatch: /* @__PURE__ */ new Set(),
|
|
233
279
|
redundantLabels: /* @__PURE__ */ new Set(),
|
|
234
280
|
booted: false,
|
|
235
|
-
updateLog: [],
|
|
236
281
|
tick: 0,
|
|
237
282
|
isBatching: false,
|
|
238
|
-
currentEffectSource: null
|
|
283
|
+
currentEffectSource: null,
|
|
284
|
+
pausedVariables: /* @__PURE__ */ new Set(),
|
|
285
|
+
metrics: { lastAnalysisTimeMs: 0, comparisonCount: 0, lastAnalysisTimestamp: 0 },
|
|
286
|
+
alertCount: 0,
|
|
287
|
+
loopCounters: /* @__PURE__ */ new Map(),
|
|
288
|
+
lastCleanup: Date.now()
|
|
239
289
|
};
|
|
240
290
|
}
|
|
241
|
-
return
|
|
291
|
+
return root[BASIS_INSTANCE_KEY];
|
|
242
292
|
};
|
|
243
293
|
var instance = getGlobalInstance();
|
|
244
|
-
var config = instance
|
|
245
|
-
var
|
|
246
|
-
var
|
|
247
|
-
var redundantLabels = instance.redundantLabels;
|
|
248
|
-
var configureBasis = (newConfig) => {
|
|
249
|
-
Object.assign(instance.config, newConfig);
|
|
250
|
-
if (instance.config.debug && !instance.booted) {
|
|
251
|
-
displayBootLog(WINDOW_SIZE);
|
|
252
|
-
instance.booted = true;
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
var getTemporalSimilarity = (vecA, vecB) => {
|
|
256
|
-
const L = vecA.length;
|
|
257
|
-
const sync = calculateSimilarityWithOffset(vecA, vecB, 0, 0, L);
|
|
258
|
-
const bFollowsA = calculateSimilarityWithOffset(vecA, vecB, 0, 1, L - 1);
|
|
259
|
-
const aFollowsB = calculateSimilarityWithOffset(vecA, vecB, 1, 0, L - 1);
|
|
260
|
-
return { sync, bFollowsA, aFollowsB };
|
|
261
|
-
};
|
|
262
|
-
var getPulseDensity = (vec) => {
|
|
263
|
-
let sum = 0;
|
|
264
|
-
for (let i = 0; i < vec.length; i++) sum += vec[i];
|
|
265
|
-
return sum;
|
|
266
|
-
};
|
|
294
|
+
var { config, history, redundantLabels, currentTickBatch } = instance;
|
|
295
|
+
var currentTickRegistry = {};
|
|
296
|
+
var dirtyLabels = /* @__PURE__ */ new Set();
|
|
267
297
|
var analyzeBasis = () => {
|
|
268
298
|
if (!instance.config.debug) {
|
|
269
299
|
instance.redundantLabels.clear();
|
|
270
300
|
return;
|
|
271
301
|
}
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
302
|
+
const scheduler = globalThis.requestIdleCallback || ((cb) => setTimeout(cb, 1));
|
|
303
|
+
scheduler(() => {
|
|
304
|
+
const analysisStart = performance.now();
|
|
305
|
+
if (dirtyLabels.size === 0) return;
|
|
306
|
+
const allEntries = [];
|
|
307
|
+
const dirtyEntries = [];
|
|
308
|
+
instance.history.forEach((meta, label) => {
|
|
309
|
+
if (meta.options.suppressAll) return;
|
|
310
|
+
let density = 0;
|
|
311
|
+
for (let k = 0; k < meta.buffer.length; k++) density += meta.buffer[k];
|
|
312
|
+
if (density >= 2) {
|
|
313
|
+
const entry = { label, meta, density };
|
|
314
|
+
allEntries.push(entry);
|
|
315
|
+
if (dirtyLabels.has(label)) dirtyEntries.push(entry);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
if (dirtyEntries.length === 0 || allEntries.length < 2) {
|
|
319
|
+
dirtyLabels.clear();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const nextRedundant = /* @__PURE__ */ new Set();
|
|
323
|
+
let compCount = 0;
|
|
324
|
+
instance.redundantLabels.forEach((l) => {
|
|
325
|
+
if (!dirtyLabels.has(l)) nextRedundant.add(l);
|
|
326
|
+
});
|
|
327
|
+
for (const dirtyEntry of dirtyEntries) {
|
|
328
|
+
for (const otherEntry of allEntries) {
|
|
329
|
+
if (dirtyEntry.label === otherEntry.label) continue;
|
|
330
|
+
if (dirtyLabels.has(otherEntry.label) && dirtyEntry.label > otherEntry.label) continue;
|
|
331
|
+
compCount++;
|
|
332
|
+
const sync = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 0);
|
|
333
|
+
const bA = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 1);
|
|
334
|
+
const aB = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, -1);
|
|
335
|
+
const maxSim = Math.max(sync, bA, aB);
|
|
336
|
+
if (maxSim > SIMILARITY_THRESHOLD) {
|
|
337
|
+
const bothVolatile = dirtyEntry.density > VOLATILITY_THRESHOLD && otherEntry.density > VOLATILITY_THRESHOLD;
|
|
338
|
+
if (sync === maxSim && !bothVolatile) {
|
|
339
|
+
nextRedundant.add(dirtyEntry.label);
|
|
340
|
+
nextRedundant.add(otherEntry.label);
|
|
341
|
+
displayRedundancyAlert(dirtyEntry.label, otherEntry.label, sync);
|
|
342
|
+
} else if (bA === maxSim) displayCausalHint(otherEntry.label, dirtyEntry.label, "math");
|
|
343
|
+
else if (aB === maxSim) displayCausalHint(dirtyEntry.label, otherEntry.label, "math");
|
|
297
344
|
}
|
|
298
345
|
}
|
|
299
346
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
347
|
+
dirtyLabels.clear();
|
|
348
|
+
instance.redundantLabels.clear();
|
|
349
|
+
nextRedundant.forEach((l) => instance.redundantLabels.add(l));
|
|
350
|
+
instance.metrics.lastAnalysisTimeMs = performance.now() - analysisStart;
|
|
351
|
+
instance.metrics.comparisonCount = compCount;
|
|
352
|
+
instance.metrics.lastAnalysisTimestamp = Date.now();
|
|
353
|
+
});
|
|
354
|
+
};
|
|
355
|
+
var processHeartbeat = () => {
|
|
356
|
+
instance.tick++;
|
|
357
|
+
instance.history.forEach((meta, label) => {
|
|
358
|
+
meta.buffer[meta.head] = instance.currentTickBatch.has(label) ? 1 : 0;
|
|
359
|
+
meta.head = (meta.head + 1) % WINDOW_SIZE;
|
|
360
|
+
});
|
|
361
|
+
instance.currentTickBatch.clear();
|
|
362
|
+
currentTickRegistry = {};
|
|
363
|
+
instance.isBatching = false;
|
|
364
|
+
if (instance.tick % ANALYSIS_INTERVAL === 0) analyzeBasis();
|
|
303
365
|
};
|
|
304
366
|
var recordUpdate = (label) => {
|
|
305
367
|
if (!instance.config.debug) return true;
|
|
368
|
+
if (instance.pausedVariables.has(label)) return false;
|
|
306
369
|
const now = Date.now();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
instance.
|
|
370
|
+
if (now - instance.lastCleanup > 1e3) {
|
|
371
|
+
instance.loopCounters.clear();
|
|
372
|
+
instance.lastCleanup = now;
|
|
310
373
|
}
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
374
|
+
const count = (instance.loopCounters.get(label) || 0) + 1;
|
|
375
|
+
instance.loopCounters.set(label, count);
|
|
376
|
+
if (count > LOOP_THRESHOLD) {
|
|
377
|
+
displayViolentBreaker(label, count, LOOP_THRESHOLD);
|
|
378
|
+
instance.pausedVariables.add(label);
|
|
314
379
|
return false;
|
|
315
380
|
}
|
|
316
381
|
if (instance.currentEffectSource && instance.currentEffectSource !== label) {
|
|
317
382
|
displayCausalHint(label, instance.currentEffectSource, "tracking");
|
|
318
383
|
}
|
|
384
|
+
if (currentTickRegistry[label]) return true;
|
|
385
|
+
currentTickRegistry[label] = true;
|
|
319
386
|
instance.currentTickBatch.add(label);
|
|
387
|
+
dirtyLabels.add(label);
|
|
320
388
|
if (!instance.isBatching) {
|
|
321
389
|
instance.isBatching = true;
|
|
322
|
-
|
|
323
|
-
instance.tick++;
|
|
324
|
-
instance.history.forEach((vec, l) => {
|
|
325
|
-
vec.shift();
|
|
326
|
-
vec.push(instance.currentTickBatch.has(l) ? 1 : 0);
|
|
327
|
-
});
|
|
328
|
-
instance.currentTickBatch.clear();
|
|
329
|
-
instance.isBatching = false;
|
|
330
|
-
if (instance.tick % ANALYSIS_INTERVAL === 0) {
|
|
331
|
-
analyzeBasis();
|
|
332
|
-
}
|
|
333
|
-
}, 20);
|
|
390
|
+
requestAnimationFrame(processHeartbeat);
|
|
334
391
|
}
|
|
335
392
|
return true;
|
|
336
393
|
};
|
|
337
|
-
var
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
394
|
+
var configureBasis = (c) => {
|
|
395
|
+
Object.assign(instance.config, c);
|
|
396
|
+
if (instance.config.debug && !instance.booted) {
|
|
397
|
+
displayBootLog(WINDOW_SIZE);
|
|
398
|
+
instance.booted = true;
|
|
399
|
+
}
|
|
342
400
|
};
|
|
343
|
-
var registerVariable = (
|
|
344
|
-
if (!instance.config.debug) return;
|
|
345
|
-
if (!instance.history.has(
|
|
346
|
-
instance.history.set(
|
|
401
|
+
var registerVariable = (l, o = {}) => {
|
|
402
|
+
if (!instance.config.debug || o.suppressAll) return;
|
|
403
|
+
if (!instance.history.has(l)) {
|
|
404
|
+
instance.history.set(l, { buffer: new Uint8Array(WINDOW_SIZE), head: 0, options: o });
|
|
347
405
|
}
|
|
348
406
|
};
|
|
349
|
-
var unregisterVariable = (
|
|
350
|
-
instance.history.delete(
|
|
407
|
+
var unregisterVariable = (l) => {
|
|
408
|
+
instance.history.delete(l);
|
|
409
|
+
};
|
|
410
|
+
var beginEffectTracking = (l) => {
|
|
411
|
+
if (instance.config.debug) instance.currentEffectSource = l;
|
|
412
|
+
};
|
|
413
|
+
var endEffectTracking = () => {
|
|
414
|
+
instance.currentEffectSource = null;
|
|
351
415
|
};
|
|
352
416
|
var printBasisHealthReport = (threshold = 0.5) => {
|
|
353
417
|
if (!instance.config.debug) {
|
|
354
418
|
console.warn("[Basis] Cannot generate report. Debug mode is OFF.");
|
|
355
419
|
return;
|
|
356
420
|
}
|
|
357
|
-
displayHealthReport(instance.history,
|
|
421
|
+
displayHealthReport(instance.history, threshold);
|
|
358
422
|
};
|
|
423
|
+
var getBasisMetrics = () => ({
|
|
424
|
+
engine: "v0.4.2 (Ring Buffer)",
|
|
425
|
+
hooks: instance.history.size,
|
|
426
|
+
load: instance.metrics.comparisonCount,
|
|
427
|
+
analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3)
|
|
428
|
+
});
|
|
359
429
|
if (typeof window !== "undefined") {
|
|
360
430
|
window.printBasisReport = printBasisHealthReport;
|
|
431
|
+
window.getBasisMetrics = getBasisMetrics;
|
|
361
432
|
}
|
|
362
433
|
var __testEngine__ = {
|
|
363
434
|
instance,
|
|
364
|
-
config: instance.config,
|
|
365
435
|
history: instance.history,
|
|
366
|
-
currentTickBatch: instance.currentTickBatch,
|
|
367
436
|
configureBasis,
|
|
368
437
|
registerVariable,
|
|
438
|
+
unregisterVariable,
|
|
369
439
|
recordUpdate,
|
|
370
440
|
printBasisHealthReport,
|
|
371
441
|
beginEffectTracking,
|
|
@@ -380,7 +450,9 @@ function useState(initialState, label) {
|
|
|
380
450
|
const effectiveLabel = reactUseRef(label || getFallbackLabel("state")).current;
|
|
381
451
|
reactUseEffect(() => {
|
|
382
452
|
registerVariable(effectiveLabel);
|
|
383
|
-
return () =>
|
|
453
|
+
return () => {
|
|
454
|
+
unregisterVariable(effectiveLabel);
|
|
455
|
+
};
|
|
384
456
|
}, [effectiveLabel]);
|
|
385
457
|
const setter = reactUseCallback((newValue) => {
|
|
386
458
|
if (recordUpdate(effectiveLabel)) {
|
|
@@ -403,7 +475,9 @@ function useReducer(reducer, initialArg, init, label) {
|
|
|
403
475
|
);
|
|
404
476
|
reactUseEffect(() => {
|
|
405
477
|
registerVariable(effectiveLabel);
|
|
406
|
-
return () =>
|
|
478
|
+
return () => {
|
|
479
|
+
unregisterVariable(effectiveLabel);
|
|
480
|
+
};
|
|
407
481
|
}, [effectiveLabel]);
|
|
408
482
|
const basisDispatch = reactUseCallback((action) => {
|
|
409
483
|
if (recordUpdate(effectiveLabel)) {
|
|
@@ -475,7 +549,9 @@ function useOptimistic2(passthrough, reducer, label) {
|
|
|
475
549
|
const effectiveLabel = label || "anonymous_optimistic";
|
|
476
550
|
reactUseEffect(() => {
|
|
477
551
|
registerVariable(effectiveLabel);
|
|
478
|
-
return () =>
|
|
552
|
+
return () => {
|
|
553
|
+
unregisterVariable(effectiveLabel);
|
|
554
|
+
};
|
|
479
555
|
}, [effectiveLabel]);
|
|
480
556
|
const [state, reactAddOptimistic] = React.useOptimistic(passthrough, reducer);
|
|
481
557
|
const addOptimistic = reactUseCallback((payload) => {
|
|
@@ -496,7 +572,9 @@ function useActionState2(action, initialState, permalink, label) {
|
|
|
496
572
|
);
|
|
497
573
|
reactUseEffect(() => {
|
|
498
574
|
registerVariable(effectiveLabel);
|
|
499
|
-
return () =>
|
|
575
|
+
return () => {
|
|
576
|
+
unregisterVariable(effectiveLabel);
|
|
577
|
+
};
|
|
500
578
|
}, [effectiveLabel]);
|
|
501
579
|
const basisDispatch = reactUseCallback((payload) => {
|
|
502
580
|
if (recordUpdate(effectiveLabel)) {
|
|
@@ -557,7 +635,9 @@ var BasisHUD = () => {
|
|
|
557
635
|
useEffect2(() => {
|
|
558
636
|
if (!isExpanded) return;
|
|
559
637
|
let animationFrame;
|
|
638
|
+
let isMounted = true;
|
|
560
639
|
const draw = () => {
|
|
640
|
+
if (!isMounted) return;
|
|
561
641
|
const canvas = canvasRef.current;
|
|
562
642
|
if (!canvas) return;
|
|
563
643
|
const ctx = canvas.getContext("2d");
|
|
@@ -579,7 +659,10 @@ var BasisHUD = () => {
|
|
|
579
659
|
animationFrame = requestAnimationFrame(draw);
|
|
580
660
|
};
|
|
581
661
|
draw();
|
|
582
|
-
return () =>
|
|
662
|
+
return () => {
|
|
663
|
+
isMounted = false;
|
|
664
|
+
cancelAnimationFrame(animationFrame);
|
|
665
|
+
};
|
|
583
666
|
}, [isExpanded]);
|
|
584
667
|
return /* @__PURE__ */ jsxs("div", { style: getHUDContainerStyle(isExpanded), onClick: () => setIsExpanded(!isExpanded), children: [
|
|
585
668
|
/* @__PURE__ */ jsx(HUDHeader, { isExpanded }),
|
|
@@ -605,63 +688,87 @@ function renderEmptyState(ctx) {
|
|
|
605
688
|
ctx.fillText("Waiting for state transitions...", HUD_DIMENSIONS.PADDING, 30);
|
|
606
689
|
}
|
|
607
690
|
function renderMatrix(ctx, entries) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
691
|
+
const L = HUD_DIMENSIONS.WINDOW_SIZE;
|
|
692
|
+
const colW = HUD_DIMENSIONS.COL_WIDTH;
|
|
693
|
+
const rowH = HUD_DIMENSIONS.ROW_HEIGHT;
|
|
694
|
+
const pad = HUD_DIMENSIONS.PADDING;
|
|
695
|
+
const cellW = colW - 1.5;
|
|
696
|
+
const cellH = rowH - 4;
|
|
697
|
+
const gridPath = new Path2D();
|
|
698
|
+
const successPath = new Path2D();
|
|
699
|
+
const errorPath = new Path2D();
|
|
700
|
+
ctx.font = "11px Inter, Menlo, monospace";
|
|
701
|
+
let rowIndex = 0;
|
|
702
|
+
for (const [label, meta] of entries) {
|
|
703
|
+
const y = rowIndex * rowH + pad;
|
|
613
704
|
const isRedundant = redundantLabels.has(label);
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
ctx.beginPath();
|
|
621
|
-
ctx.roundRect(x, y, w, h, HUD_DIMENSIONS.RADIUS);
|
|
622
|
-
ctx.fill();
|
|
705
|
+
const { buffer, head } = meta;
|
|
706
|
+
let uiPos = 0;
|
|
707
|
+
const addToPath = (val, xIdx) => {
|
|
708
|
+
const x = xIdx * colW + pad;
|
|
709
|
+
if (val === 1) {
|
|
710
|
+
(isRedundant ? errorPath : successPath).rect(x, y, cellW, cellH);
|
|
623
711
|
} else {
|
|
624
|
-
|
|
712
|
+
gridPath.rect(x, y, cellW, cellH);
|
|
625
713
|
}
|
|
626
|
-
}
|
|
627
|
-
|
|
714
|
+
};
|
|
715
|
+
for (let i = head; i < L; i++) addToPath(buffer[i], uiPos++);
|
|
716
|
+
for (let i = 0; i < head; i++) addToPath(buffer[i], uiPos++);
|
|
717
|
+
const stateName = label.split(" -> ")[1] || label;
|
|
718
|
+
const textX = L * colW + pad + 10;
|
|
719
|
+
let density = 0;
|
|
720
|
+
for (let i = 0; i < L; i++) density += buffer[i];
|
|
721
|
+
const isVolatile = density > 25;
|
|
628
722
|
ctx.fillStyle = isRedundant ? HUD_THEME.error : isVolatile ? HUD_THEME.success : HUD_THEME.text;
|
|
629
|
-
ctx.
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
723
|
+
ctx.fillText((isRedundant ? "! " : isVolatile ? "~ " : "") + stateName, textX, y + 9);
|
|
724
|
+
rowIndex++;
|
|
725
|
+
}
|
|
726
|
+
ctx.fillStyle = HUD_THEME.grid;
|
|
727
|
+
ctx.fill(gridPath);
|
|
728
|
+
ctx.fillStyle = HUD_THEME.success;
|
|
729
|
+
ctx.fill(successPath);
|
|
730
|
+
ctx.fillStyle = HUD_THEME.error;
|
|
731
|
+
ctx.fill(errorPath);
|
|
637
732
|
}
|
|
638
|
-
var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ jsxs(
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
733
|
+
var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ jsxs(
|
|
734
|
+
"div",
|
|
735
|
+
{
|
|
736
|
+
style: {
|
|
737
|
+
padding: "10px 14px",
|
|
738
|
+
backgroundColor: isExpanded ? HUD_THEME.header : "transparent",
|
|
739
|
+
color: isExpanded ? "white" : HUD_THEME.header,
|
|
740
|
+
fontWeight: 600,
|
|
741
|
+
fontSize: "11px",
|
|
742
|
+
letterSpacing: "0.05em",
|
|
743
|
+
display: "flex",
|
|
744
|
+
justifyContent: "space-between",
|
|
745
|
+
alignItems: "center",
|
|
746
|
+
transition: "background 0.3s"
|
|
747
|
+
},
|
|
748
|
+
children: [
|
|
749
|
+
/* @__PURE__ */ jsx("span", { children: isExpanded ? "STATE BASIS MATRIX" : "\u{1F4D0} BASIS ACTIVE" }),
|
|
750
|
+
isExpanded && /* @__PURE__ */ jsx("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.4.2" })
|
|
751
|
+
]
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
var HUDFooter = () => /* @__PURE__ */ jsxs(
|
|
755
|
+
"div",
|
|
756
|
+
{
|
|
757
|
+
style: {
|
|
758
|
+
marginTop: "12px",
|
|
759
|
+
paddingTop: "8px",
|
|
760
|
+
borderTop: `1px solid ${HUD_THEME.grid}`,
|
|
761
|
+
color: HUD_THEME.textDim,
|
|
762
|
+
fontSize: "9px",
|
|
763
|
+
display: "flex",
|
|
764
|
+
justifyContent: "space-between"
|
|
765
|
+
},
|
|
766
|
+
children: [
|
|
767
|
+
/* @__PURE__ */ jsx("span", { children: "RING BUFFER ENGINE" }),
|
|
768
|
+
/* @__PURE__ */ jsx("span", { children: "ZERO ALLOC" })
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
);
|
|
665
772
|
|
|
666
773
|
// src/context.tsx
|
|
667
774
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -684,6 +791,7 @@ export {
|
|
|
684
791
|
BasisProvider,
|
|
685
792
|
basis,
|
|
686
793
|
configureBasis,
|
|
794
|
+
getBasisMetrics,
|
|
687
795
|
printBasisHealthReport,
|
|
688
796
|
use,
|
|
689
797
|
useActionState2 as useActionState,
|