react-state-basis 0.6.0 โ 0.6.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 +42 -8
- package/dist/chunk-E3D6YEKB.mjs +877 -0
- package/dist/chunk-E3D6YEKB.mjs.map +1 -0
- package/dist/index.js +121 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -884
- 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 +893 -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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/math.ts","../src/core/graph.ts","../src/core/constants.ts","../src/core/label.ts","../src/core/ranker.ts","../src/core/logger.ts","../src/core/analysis.ts","../src/engine.ts"],"sourcesContent":["// src/core/math.ts\n\n/**\n * CIRCULAR SIMILARITY (v0.5.x)\n * Calculates Cosine Similarity across circular buffers.\n * \n * Optimization: Pre-normalizes the circular offset using a single modulo operation \n * outside the hot loop. This ensures the inner loop stays linearized (no division) \n * while remaining robust against extreme lead/lag values.\n */\nexport const calculateSimilarityCircular = (\n bufferA: Uint8Array,\n headA: number,\n bufferB: Uint8Array,\n headB: number,\n offset: number\n): number => {\n const L = bufferA.length;\n let dot = 0, magA = 0, magB = 0;\n\n const baseOffset = ((headB - headA + offset) % L + L) % L;\n\n for (let i = 0; i < L; i++) {\n const valA = bufferA[i];\n\n let iB = i + baseOffset;\n if (iB >= L) {\n iB -= L;\n }\n\n const valB = bufferB[iB];\n\n dot += valA * valB;\n magA += valA * valA;\n magB += valB * valB;\n }\n\n // Prevent Divide-by-Zero (Orthogonal/Idle result)\n if (magA === 0 || magB === 0) return 0;\n\n // Cosine Similarity Formula: (A ยท B) / (||A|| * ||B||)\n return dot / (Math.sqrt(magA) * Math.sqrt(magB));\n};\n\nexport const calculateCosineSimilarity = (A: Uint8Array, B: Uint8Array): number => {\n let dot = 0, magA = 0, magB = 0;\n for (let i = 0; i < A.length; i++) {\n dot += A[i] * B[i];\n magA += A[i] * A[i];\n magB += B[i] * B[i];\n }\n return (magA === 0 || magB === 0) ? 0 : dot / (Math.sqrt(magA) * Math.sqrt(magB));\n};\n","// src/core/graph.ts\n\nexport const calculateSpectralInfluence = (\n graph: Map<string, Map<string, number>>,\n maxIterations = 20,\n tolerance = 0.001\n) => {\n const nodes = Array.from(new Set([...graph.keys(), ...Array.from(graph.values()).flatMap(m => [...m.keys()])]));\n if (nodes.length === 0) return new Map<string, number>();\n\n let scores = new Map<string, number>();\n // Initialize: Every node starts with equal weight\n nodes.forEach(n => scores.set(n, 1 / nodes.length));\n\n for (let i = 0; i < maxIterations; i++) {\n const nextScores = new Map<string, number>();\n let totalWeight = 0;\n\n nodes.forEach(source => {\n let influence = 0;\n const outgoing = graph.get(source);\n\n if (outgoing) {\n outgoing.forEach((weight, target) => {\n // Rule: Source is important if it triggers targets that are active/important\n // We skip self-loops (source === target) to prevent artificial inflation\n if (source !== target) {\n influence += (scores.get(target) || 0) * weight;\n }\n });\n }\n // Every node has a \"Base\" existence weight to prevent sinks from reaching 0\n nextScores.set(source, influence + 0.01);\n totalWeight += (influence + 0.01);\n });\n\n // Normalize\n let delta = 0;\n nextScores.forEach((val, key) => {\n const normalized = val / totalWeight;\n const diff = normalized - (scores.get(key) || 0);\n delta += diff * diff;\n nextScores.set(key, normalized);\n });\n\n scores = nextScores;\n if (Math.sqrt(delta) < tolerance) break;\n }\n\n return scores;\n};\n","// src/core/constants.ts\n\nexport const WINDOW_SIZE = 50;\nexport const SIMILARITY_THRESHOLD = 0.88;\nexport const LOOP_THRESHOLD = 150;\nexport const LOOP_WINDOW_MS = 1000;\nexport const ANALYSIS_INTERVAL = 5;\n\nexport const VOLATILITY_THRESHOLD = 25;\n\nexport const INSTANCE_SEP = '##';","// src/core/label.ts\n\nimport { INSTANCE_SEP } from './constants';\n\nexport const stripInstance = (label: string): string => {\n const idx = label.indexOf(INSTANCE_SEP);\n return idx === -1 ? label : label.slice(0, idx);\n};\n\nexport const parseLabel = (label: string) => {\n const base = stripInstance(label);\n const parts = base.split(' -> ');\n return { file: parts[0] || \"Unknown\", name: parts[1] || base };\n};\n\nexport const isSameField = (labelA: string, labelB: string): boolean =>\n stripInstance(labelA) === stripInstance(labelB);","// src/core/ranker.ts\n\nimport { calculateSpectralInfluence } from './graph';\nimport { RingBufferMetadata, SignalRole, RankedIssue, ViolationDetail } from './types';\nimport { parseLabel } from './label';\n\nexport const identifyTopIssues = (\n graph: Map<string, Map<string, number>>,\n history: Map<string, RingBufferMetadata>,\n redundantLabels: Set<string>,\n violationMap: Map<string, ViolationDetail[]>\n): RankedIssue[] => {\n const results: RankedIssue[] = [];\n\n const influence = calculateSpectralInfluence(graph);\n\n const isEffect = (label: string) =>\n label.includes('effect_L') ||\n label.includes('useLayoutEffect') ||\n label.includes('useInsertionEffect');\n\n const isEvent = (label: string) => label.startsWith('Event_Tick_');\n\n // --- EVENT AGGREGATION MAP ---\n const eventSignatures = new Map<string, { count: number, score: number, targets: string[] }>();\n\n // 1. FILTER & PROCESS DRIVERS\n const drivers = Array.from(graph.entries())\n .filter(([label, targets]) => {\n if (targets.size === 0) return false;\n\n // AGGREGATE EVENTS\n if (isEvent(label)) {\n const validTargets = Array.from(targets.keys()).filter(t => {\n const meta = history.get(t);\n return meta && meta.role !== SignalRole.CONTEXT;\n });\n\n if (validTargets.length > 1) {\n const signature = validTargets.sort().join('|');\n const existing = eventSignatures.get(signature);\n if (existing) {\n existing.count++;\n existing.score = Math.max(existing.score, influence.get(label) || 0);\n } else {\n eventSignatures.set(signature, {\n count: 1,\n score: influence.get(label) || 0,\n targets: validTargets\n });\n }\n }\n return false;\n }\n\n // STANDARD NODE FILTERING\n const meta = history.get(label);\n if (meta?.role === SignalRole.CONTEXT) return false;\n if (meta?.role === SignalRole.PROJECTION) return false;\n\n const score = influence.get(label) || 0;\n if (isEffect(label) && targets.size > 0) return true;\n if (targets.size < 2 && score < 0.05) return false;\n\n return true;\n })\n .sort((a, b) => {\n const scoreA = influence.get(a[0]) || 0;\n const scoreB = influence.get(b[0]) || 0;\n return scoreB - scoreA;\n });\n\n // 2. INJECT AGGREGATED EVENTS (Top Priority)\n const sortedEvents = Array.from(eventSignatures.entries())\n .sort((a, b) => b[1].targets.length - a[1].targets.length);\n\n sortedEvents.slice(0, 2).forEach(([sig, data]) => {\n // Borrow the filename from the first target\n const primaryVictim = parseLabel(data.targets[0]);\n\n // We construct a label that looks like \"File.tsx -> Interaction Name\"\n // This tricks the Logger into printing the correct file location.\n const smartLabel = `${primaryVictim.file} -> Global Event (${primaryVictim.name})`;\n\n results.push({\n label: smartLabel,\n metric: 'influence',\n score: 1.0,\n reason: `Global Sync Event: An external trigger is updating ${data.targets.length} roots simultaneously. Occurred ${data.count} times.`,\n violations: data.targets.map(t => ({\n type: 'causal_leak',\n target: t\n }))\n });\n });\n\n // 3. GENERATE STANDARD ISSUES\n drivers.slice(0, 3 - results.length).forEach(([label, targets]) => {\n const targetNames = Array.from(targets.keys());\n\n if (isEffect(label)) {\n results.push({\n label,\n metric: 'influence',\n score: influence.get(label) || 0,\n reason: `Side-Effect Driver: Hook writes to state during render.`,\n violations: targetNames.map(t => ({ type: 'causal_leak', target: t }))\n });\n return;\n }\n\n results.push({\n label,\n metric: 'influence',\n score: influence.get(label) || targets.size,\n reason: `Sync Driver: Acts as a \"Prime Mover\" for ${targets.size} downstream signals.`,\n violations: targetNames.map(t => ({ type: 'causal_leak', target: t }))\n });\n });\n\n // 4. DENSITY FALLBACK\n if (results.length === 0) {\n const sortedDensity = Array.from(history.entries())\n .filter(([label, meta]) =>\n meta.role === SignalRole.LOCAL &&\n !redundantLabels.has(label) &&\n meta.density > 25\n )\n .sort((a, b) => b[1].density - a[1].density);\n\n sortedDensity.slice(0, 3).forEach(([label, meta]) => {\n results.push({\n label,\n metric: 'density',\n score: meta.density,\n reason: `High Frequency: potential main-thread saturation.`,\n violations: []\n });\n });\n }\n\n return results;\n};","// src/core/logger.ts\n\nimport { calculateCosineSimilarity } from \"./math\";\nimport { identifyTopIssues } from \"./ranker\";\nimport { RingBufferMetadata, SignalRole, RankedIssue, ViolationDetail } from \"./types\";\nimport { instance } from \"../engine\";\nimport { parseLabel } from \"./label\";\n\nconst isWeb = typeof window !== 'undefined' && typeof window.document !== 'undefined';\nconst LAST_LOG_TIMES = new Map<string, number>();\nconst LOG_COOLDOWN = 3000;\n\nconst THEME = {\n identity: \"#6C5CE7\", // Purple (Brand)\n problem: \"#D63031\", // Red (Bugs)\n solution: \"#FBC531\", // Yellow (Fixes)\n context: \"#0984E3\", // Blue (Locations)\n muted: \"#9AA0A6\", // Gray (Metadata)\n border: \"#2E2E35\",\n success: \"#00b894\", // Green (Good Score)\n};\n\nconst STYLES = {\n // Structure\n basis: `background: ${THEME.identity}; color: white; font-weight: bold; padding: 2px 6px; border-radius: 3px;`,\n headerIdentity: `background: ${THEME.identity}; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;`,\n headerProblem: `background: ${THEME.problem}; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;`,\n version: `background: #a29bfe; color: #2d3436; padding: 2px 6px; border-radius: 3px; margin-left: -4px;`,\n\n // Actions\n actionLabel: `color: ${THEME.solution}; font-weight: bold;`,\n actionPill: `color: ${THEME.solution}; font-weight: bold; border: 1px solid ${THEME.solution}; padding: 0 4px; border-radius: 3px;`,\n\n // Context\n impactLabel: `color: ${THEME.context}; font-weight: bold;`,\n location: `color: ${THEME.context}; font-family: monospace; font-weight: bold;`,\n\n // Text\n subText: `color: ${THEME.muted}; font-size: 11px;`,\n bold: \"font-weight: bold;\",\n label: \"background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;\",\n};\n\nconst shouldLog = (key: string) => {\n const now = Date.now();\n const last = LAST_LOG_TIMES.get(key) || 0;\n if (now - last > LOG_COOLDOWN) {\n LAST_LOG_TIMES.set(key, now);\n return true;\n }\n return false;\n};\n\n// Helper: Detects boolean flags vs data\nconst isBooleanLike = (name: string) =>\n /^(is|has|can|should|did|will|show|hide)(?=[A-Z_])/.test(name);\n\n// --- SUGGESTION LOGIC ---\nconst getSuggestedFix = (issue: RankedIssue, info: { name: string }): string => {\n\n // 1. GLOBAL EVENT (Split State)\n if (issue.label.includes('Global Event')) {\n return `These variables update together but live in different hooks/files. Consolidate them into a single %cuseReducer%c or atomic store update.`;\n }\n\n const violations = issue.violations || [];\n const leaks = violations.filter(v => v.type === 'causal_leak');\n const mirrors = violations.filter(v => v.type === 'context_mirror');\n const duplicates = violations.filter(v => v.type === 'duplicate_state');\n\n // 2. CONTEXT MIRRORING (Shadow State)\n if (mirrors.length > 0) {\n return `Local state is 'shadowing' Global Context. This creates two sources of truth. ` +\n `Delete the local state and consume the %cContext%c value directly.`;\n }\n\n // 3. EFFECT CHAINS (Double Render)\n if (leaks.length > 0) {\n const targetName = parseLabel(leaks[0].target).name;\n\n // If driven by an Effect\n if (issue.label.includes('effect')) {\n return `This Effect triggers a synchronous re-render of ${targetName}. ` +\n `Calculate ${targetName} during the render phase (Derived State) or wrap in %cuseMemo%c if expensive.`;\n }\n // If driven by State (A -> B)\n return `State cascading detected. ${info.name} triggers ${targetName} in a separate frame. ` +\n `Merge them into one object to update simultaneously.`;\n }\n\n // 4. DUPLICATE STATE (Restored Logic)\n if (duplicates.length > 0) {\n // Boolean Explosion Logic\n if (isBooleanLike(info.name)) {\n return `Boolean Explosion detected. Multiple flags are toggling in sync. ` +\n `Replace impossible states with a single %cstatus%c string ('idle' | 'loading' | 'success').`;\n }\n return `Redundant State detected. This variable carries no unique information. ` +\n `Derive it from the source variable during render, or use %cuseMemo%c to cache the result.`;\n }\n\n // 5. HIGH FREQUENCY\n if (issue.metric === 'density') {\n return `High-Frequency Update. This variable updates faster than the frame rate. ` +\n `Apply %cdebounce%c or move to a Ref to unblock the main thread.`;\n }\n\n return `Check the dependency chain of ${info.name}.`;\n};\n\n\nexport const displayHealthReport = (history: Map<string, RingBufferMetadata>, threshold: number, violationMap: Map<string, ViolationDetail[]>) => {\n if (!isWeb) return;\n const entries = Array.from(history.entries());\n if (entries.length === 0) return;\n\n const topIssues = identifyTopIssues(instance.graph, history, instance.redundantLabels, violationMap);\n\n console.group(`%c ๐ BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerIdentity);\n\n // 1. REFACTOR PRIORITIES\n if (topIssues.length > 0) {\n console.log(`%c๐ฏ REFACTOR PRIORITIES %c(PRIME MOVERS)`,\n `font-weight: bold; color: ${THEME.identity}; margin-top: 10px;`,\n `font-weight: normal; color: ${THEME.muted}; font-style: italic;`\n );\n\n topIssues.forEach((issue, idx) => {\n const info = parseLabel(issue.label);\n const icon = issue.metric === 'influence' ? 'โก' : '๐';\n\n const pColor = idx === 0 ? THEME.problem : idx === 1 ? THEME.solution : THEME.identity;\n\n let displayName = info.name;\n let displayFile = info.file;\n\n if (issue.label.includes('Global Event')) {\n displayName = info.name;\n displayFile = info.file;\n }\n\n console.group(\n ` %c${idx + 1}%c ${icon} ${displayName} %c(${displayFile})`,\n `background: ${pColor}; color: ${idx === 1 ? 'black' : 'white'}; border-radius: 50%; padding: 0 5px;`,\n \"font-family: monospace; font-weight: 700;\",\n `color: ${THEME.muted}; font-size: 10px; font-weight: normal; font-style: italic;`\n );\n\n console.log(`%c${issue.reason}`, `color: ${THEME.muted}; font-style: italic;`);\n\n // IMPACTS: Grouped by File\n if (issue.violations.length > 0) {\n const byFile = new Map<string, string[]>();\n\n issue.violations.forEach(v => {\n if (issue.label.includes('Global Event') && v.type === 'context_mirror') return;\n const { file, name } = parseLabel(v.target);\n if (!byFile.has(file)) byFile.set(file, []);\n byFile.get(file)!.push(name);\n });\n\n const impactParts: string[] = [];\n byFile.forEach((vars, file) => {\n const varList = vars.join(', ');\n impactParts.push(`${file} (${varList})`);\n });\n\n if (impactParts.length > 0) {\n console.log(`%cImpacts: %c${impactParts.join(' + ')}`, STYLES.impactLabel, \"\");\n }\n }\n\n // SOLUTION\n const fix = getSuggestedFix(issue, info);\n const fixParts = fix.split('%c');\n\n if (fixParts.length === 3) {\n console.log(\n `%cSolution: %c${fixParts[0]}%c${fixParts[1]}%c${fixParts[2]}`,\n STYLES.actionLabel,\n \"\",\n STYLES.actionPill,\n \"\"\n );\n } else {\n console.log(\n `%cSolution: %c${fix}`,\n STYLES.actionLabel,\n \"\"\n );\n }\n\n console.groupEnd();\n });\n console.log(\"\\n\");\n }\n\n // 2. EFFICIENCY SCORE\n const clusters: string[][] = [];\n const processed = new Set<string>();\n let independentCount = 0;\n\n // A. Redundancy Check\n entries.forEach(([labelA, metaA]) => {\n if (processed.has(labelA)) return;\n const currentCluster = [labelA];\n processed.add(labelA);\n entries.forEach(([labelB, metaB]) => {\n if (labelA === labelB || processed.has(labelB)) return;\n if (calculateCosineSimilarity(metaA.buffer, metaB.buffer) > threshold) {\n if (metaA.role === SignalRole.CONTEXT && metaB.role === SignalRole.CONTEXT) return;\n currentCluster.push(labelB);\n processed.add(labelB);\n }\n });\n if (currentCluster.length > 1) clusters.push(currentCluster); else independentCount++;\n });\n\n // B. Causality Check (Graph Penalty)\n const totalVars = entries.length;\n const redundancyScore = ((independentCount + clusters.length) / totalVars) * 100;\n\n let internalEdges = 0;\n instance.graph.forEach((targets, source) => {\n if (source.startsWith('Event_Tick_')) return;\n internalEdges += targets.size;\n });\n\n const causalPenalty = (internalEdges / totalVars) * 100;\n\n let healthScore = redundancyScore - causalPenalty;\n if (healthScore < 0) healthScore = 0;\n\n const scoreColor = healthScore > 85 ? THEME.success : THEME.problem;\n\n console.log(`%cSystem Efficiency: %c${healthScore.toFixed(1)}%`,\n STYLES.bold, `color: ${scoreColor}; font-weight: bold;`\n );\n console.log(`%cSources of Truth: ${independentCount + clusters.length}/${totalVars} | Causal Leaks: ${internalEdges}`, STYLES.subText);\n\n // 3. SYNC ISSUES\n if (clusters.length > 0) {\n console.log(`%cDetected ${clusters.length} Sync Issues:`, `font-weight: bold; color: ${THEME.problem}; margin-top: 10px;`);\n\n clusters.forEach((cluster, idx) => {\n const clusterMetas = cluster.map(l => ({\n label: l,\n meta: history.get(l)!,\n name: parseLabel(l).name\n }));\n const hasCtx = clusterMetas.some(c =>\n c.meta.role === SignalRole.CONTEXT || c.meta.role === SignalRole.STORE\n );\n\n const names = clusterMetas.map(c => {\n const prefix = c.meta.role === SignalRole.STORE ? 'ฮฃ ' : c.meta.role === SignalRole.CONTEXT ? 'ฮฉ ' : '';\n return `${prefix}${c.name}`;\n }).join(' โท ');\n\n console.group(` %c${idx + 1}%c ${names}`, `background: ${THEME.problem}; color: white; border-radius: 50%; padding: 0 5px;`, \"font-family: monospace; font-weight: bold;\");\n\n if (hasCtx) {\n const hasStore = clusterMetas.some(c => c.meta.role === SignalRole.STORE);\n const sourceType = hasStore ? 'External Store' : 'global context';\n console.log(`%cDiagnosis: ${hasStore ? 'Store' : 'Context'} Mirroring. Local state is shadowing ${sourceType}.`, `color: ${THEME.problem};`);\n console.log(`%cSolution: Use ${sourceType} directly to avoid state drift.`, STYLES.actionLabel);\n } else {\n const boolKeywords = ['is', 'has', 'can', 'should', 'loading', 'success', 'error', 'active', 'enabled', 'open', 'visible'];\n const boolCount = clusterMetas.filter(c =>\n boolKeywords.some(kw => c.name.toLowerCase().startsWith(kw))\n ).length;\n\n const isBoolExplosion = cluster.length > 2 && (boolCount / cluster.length) > 0.5;\n if (isBoolExplosion) {\n console.log(`%cDiagnosis:%c Boolean Explosion. Multiple booleans updating in sync.`, STYLES.bold, \"\");\n console.log(`%cSolution:%c Combine into a single %cstatus%c string or a %creducer%c.`, STYLES.actionLabel, \"\", STYLES.actionPill, \"\", STYLES.actionPill, \"\");\n } else if (cluster.length > 2) {\n console.log(`%cDiagnosis:%c Sibling Updates. These states respond to the same event.`, STYLES.bold, \"\");\n console.log(`%cSolution:%c This may be intentional. If not, consolidate into a %creducer%c.`, STYLES.actionLabel, \"\", STYLES.actionPill, \"\");\n } else {\n console.log(`%cDiagnosis:%c Redundant State. Variables always change together.`, STYLES.bold, \"\");\n console.log(`%cSolution:%c Derive one from the other via %cuseMemo%c.`, STYLES.actionLabel, \"\", STYLES.actionPill, \"\");\n }\n }\n console.groupEnd();\n });\n } else {\n console.log(\"%cโจ Your architecture is clean. No redundant state detected.\", `color: ${THEME.success}; font-weight: bold;`);\n }\n console.groupEnd();\n};\n\n// --- LIVE STREAM LOGGERS ---\n\nexport const displayRedundancyAlert = (labelA: string, metaA: RingBufferMetadata, labelB: string, metaB: RingBufferMetadata, sim: number) => {\n if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;\n const infoA = parseLabel(labelA);\n const infoB = parseLabel(labelB);\n const isContextMirror = (metaA.role === SignalRole.LOCAL && metaB.role === SignalRole.CONTEXT) ||\n (metaB.role === SignalRole.LOCAL && metaA.role === SignalRole.CONTEXT);\n\n const isStoreMirror = (metaA.role === SignalRole.LOCAL && metaB.role === SignalRole.STORE) ||\n (metaB.role === SignalRole.LOCAL && metaA.role === SignalRole.STORE);\n\n const alertType = isContextMirror ? 'CONTEXT MIRRORING' : isStoreMirror ? 'STORE MIRRORING' : 'DUPLICATE STATE';\n console.group(`%c โ BASIS | ${alertType} `, STYLES.headerProblem);\n console.log(`%c๐ Location: %c${infoA.file}`, STYLES.bold, STYLES.location);\n console.log(`%cIssue:%c ${infoA.name} and ${infoB.name} are synchronized (${(sim * 100).toFixed(0)}%).`, STYLES.bold, \"\");\n\n if (isContextMirror || isStoreMirror) {\n const sourceType = isStoreMirror ? 'External Store' : 'Global Context';\n console.log(`%cFix:%c Local state is 'shadowing' ${sourceType}. Delete the local state and consume the %c${sourceType}%c value directly.`,\n STYLES.bold, \"\",\n STYLES.actionPill, \"\"\n );\n } else {\n if (isBooleanLike(infoA.name) || isBooleanLike(infoB.name)) {\n console.log(`%cFix:%c Boolean Explosion detected. Merge flags into a single %cstatus%c string or %cuseReducer%c.`,\n STYLES.bold, \"\",\n STYLES.actionPill, \"\",\n STYLES.actionPill, \"\"\n );\n } else {\n console.log(`%cFix:%c Redundant State detected. Derive %c${infoB.name}%c from %c${infoA.name}%c during render, or use %cuseMemo%c.`,\n STYLES.bold, \"\",\n STYLES.label, \"\",\n STYLES.label, \"\",\n STYLES.actionPill, \"\"\n );\n }\n }\n console.groupEnd();\n};\n\nexport const displayCausalHint = (targetLabel: string, targetMeta: RingBufferMetadata, sourceLabel: string, sourceMeta: RingBufferMetadata) => {\n if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;\n const target = parseLabel(targetLabel);\n const source = parseLabel(sourceLabel);\n const headerType = sourceMeta.role === SignalRole.CONTEXT\n ? 'CONTEXT SYNC LEAK'\n : sourceMeta.role === SignalRole.STORE\n ? 'STORE SYNC LEAK'\n : 'DOUBLE RENDER';\n\n const isEffect = sourceLabel.includes('effect') || sourceLabel.includes('useLayoutEffect');\n\n console.groupCollapsed(`%c โก BASIS | ${headerType} `, STYLES.headerProblem);\n console.log(`%c๐ Location: %c${target.file}`, STYLES.bold, STYLES.location);\n console.log(`%cIssue:%c ${source.name} triggers ${target.name} in separate frames.`, STYLES.bold, \"\");\n\n if (isEffect) {\n console.log(`%cFix:%c Derive %c${target.name}%c during the render phase (remove effect) or wrap in %cuseMemo%c.`,\n STYLES.bold, \"\",\n STYLES.label, \"\",\n STYLES.actionPill, \"\"\n );\n } else {\n console.log(`%cFix:%c Merge %c${target.name}%c with %c${source.name}%c into a single state update.`,\n STYLES.bold, \"\",\n STYLES.label, \"\",\n STYLES.label, \"\"\n );\n }\n console.groupEnd();\n};\n\nexport const displayViolentBreaker = (label: string, count: number, threshold: number) => {\n if (!isWeb) return;\n const { name } = parseLabel(label);\n console.group(`%c ๐ BASIS CRITICAL | CIRCUIT BREAKER `, STYLES.headerProblem);\n console.error(`INFINITE LOOP DETECTED\\nVariable: ${name}\\nFrequency: ${count} updates/sec`);\n console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, `color: ${THEME.problem}; font-weight: bold;`);\n console.groupEnd();\n};\n\nexport const displayBootLog = (windowSize: number) => {\n if (!isWeb) return;\n console.log(`%cBasis%cAuditor%c \"Graph Era\" (Window: ${windowSize})`, STYLES.basis, STYLES.version, `color: ${THEME.muted}; font-style: italic; margin-left: 8px;`);\n};","// src/core/analysis.ts\n\nimport * as UI from './logger';\nimport { calculateSimilarityCircular } from './math';\nimport { SIMILARITY_THRESHOLD } from './constants';\nimport { SignalRole, Entry, ViolationDetail } from './types';\nimport { isSameField } from './label';\n\ninterface Similarities {\n sync: number;\n bA: number;\n aB: number;\n max: number;\n}\n\nconst CAUSAL_MARGIN = 0.05;\n\n// --- NOISE REDUCTION ---\n// Check if a node is directly driven by a Virtual Event.\nconst isEventDriven = (label: string, graph: Map<string, Map<string, number>>): boolean => {\n for (const [parent, targets] of graph.entries()) {\n if (parent.startsWith('Event_Tick_') && targets.has(label)) {\n return true;\n }\n }\n return false;\n};\n\nconst calculateAllSimilarities = (entryA: Entry, entryB: Entry): Similarities => {\n const sync = calculateSimilarityCircular(\n entryA.meta.buffer,\n entryA.meta.head,\n entryB.meta.buffer,\n entryB.meta.head,\n 0\n );\n\n const bA = calculateSimilarityCircular(\n entryA.meta.buffer,\n entryA.meta.head,\n entryB.meta.buffer,\n entryB.meta.head,\n 1\n );\n\n const aB = calculateSimilarityCircular(\n entryA.meta.buffer,\n entryA.meta.head,\n entryB.meta.buffer,\n entryB.meta.head,\n -1\n );\n\n return { sync, bA, aB, max: Math.max(sync, bA, aB) };\n};\n\nconst shouldSkipComparison = (\n entryA: Entry,\n entryB: Entry,\n dirtyLabels: Set<string>\n): boolean => {\n if (entryA.label === entryB.label) return true;\n\n if (isSameField(entryA.label, entryB.label)) return true;\n\n if (dirtyLabels.has(entryB.label) && entryA.label > entryB.label) return true;\n return false;\n};\n\nconst pushViolation = (\n map: Map<string, ViolationDetail[]>,\n source: string,\n detail: ViolationDetail\n) => {\n if (!map.has(source)) {\n map.set(source, []);\n }\n const list = map.get(source)!;\n const exists = list.some(\n v => v.type === detail.type && v.target === detail.target\n );\n if (!exists) {\n list.push(detail);\n }\n};\n\nconst isGlobalSource = (role: SignalRole): boolean =>\n role === SignalRole.CONTEXT || role === SignalRole.STORE;\n\nconst detectRedundancy = (\n entryA: Entry,\n entryB: Entry,\n similarities: Similarities,\n redundantSet: Set<string>,\n violationMap: Map<string, ViolationDetail[]>\n): void => {\n const roleA = entryA.meta.role;\n const roleB = entryB.meta.role;\n\n if (isGlobalSource(roleA) && isGlobalSource(roleB)) return;\n if (entryA.meta.density < 2 || entryB.meta.density < 2) return;\n\n if (roleA === SignalRole.LOCAL && isGlobalSource(roleB)) {\n redundantSet.add(entryA.label);\n pushViolation(violationMap, entryB.label, { type: 'context_mirror', target: entryA.label, similarity: similarities.max });\n UI.displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);\n }\n else if (isGlobalSource(roleA) && roleB === SignalRole.LOCAL) {\n redundantSet.add(entryB.label);\n pushViolation(violationMap, entryA.label, { type: 'context_mirror', target: entryB.label, similarity: similarities.max });\n UI.displayRedundancyAlert(entryB.label, entryB.meta, entryA.label, entryA.meta, similarities.max);\n }\n else if (roleA === SignalRole.LOCAL && roleB === SignalRole.LOCAL) {\n redundantSet.add(entryA.label);\n redundantSet.add(entryB.label);\n pushViolation(violationMap, entryA.label, { type: 'duplicate_state', target: entryB.label, similarity: similarities.max });\n pushViolation(violationMap, entryB.label, { type: 'duplicate_state', target: entryA.label, similarity: similarities.max });\n UI.displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);\n }\n};\n\nconst detectCausalLeak = (\n entryA: Entry,\n entryB: Entry,\n similarities: Similarities,\n violationMap: Map<string, ViolationDetail[]>,\n graph: Map<string, Map<string, number>>\n): void => {\n if (entryA.isVolatile || entryB.isVolatile) return;\n\n if (similarities.max - similarities.sync < CAUSAL_MARGIN) return;\n\n const addLeak = (source: string, target: string) => {\n if (isEventDriven(target, graph)) return;\n\n if (!violationMap.has(source)) {\n violationMap.set(source, []);\n }\n violationMap.get(source)!.push({ type: 'causal_leak', target });\n \n const sourceEntry = source === entryA.label ? entryA : entryB;\n const targetEntry = source === entryA.label ? entryB : entryA;\n UI.displayCausalHint(target, targetEntry.meta, source, sourceEntry.meta);\n };\n\n // bA High = A[t] matches B[t+1]. A happens before B.\n // Source: A, Target: B\n if (similarities.bA === similarities.max) {\n addLeak(entryA.label, entryB.label);\n }\n // aB High = A[t+1] matches B[t]. B happens before A.\n // Source: B, Target: A\n else if (similarities.aB === similarities.max) {\n addLeak(entryB.label, entryA.label);\n }\n};\n\nexport const detectSubspaceOverlap = (\n dirtyEntries: Entry[],\n allEntries: Entry[],\n redundantSet: Set<string>,\n dirtyLabels: Set<string>,\n graph: Map<string, Map<string, number>>\n): { compCount: number; violationMap: Map<string, ViolationDetail[]> } => {\n let compCount = 0;\n const violationMap = new Map<string, ViolationDetail[]>();\n\n for (const entryA of dirtyEntries) {\n for (const entryB of allEntries) {\n if (shouldSkipComparison(entryA, entryB, dirtyLabels)) continue;\n\n compCount++;\n const similarities = calculateAllSimilarities(entryA, entryB);\n\n if (similarities.max > SIMILARITY_THRESHOLD) {\n detectRedundancy(entryA, entryB, similarities, redundantSet, violationMap);\n detectCausalLeak(entryA, entryB, similarities, violationMap, graph);\n }\n }\n }\n\n return { compCount, violationMap };\n};","// src/engine.ts\n\nimport * as UI from './core/logger';\nimport { detectSubspaceOverlap } from './core/analysis';\nimport {\n SignalRole,\n StateOptions,\n RingBufferMetadata,\n BasisEngineState,\n Entry,\n ViolationDetail\n} from './core/types';\nimport {\n WINDOW_SIZE,\n LOOP_THRESHOLD,\n VOLATILITY_THRESHOLD\n} from './core/constants';\n\n// --- Static Internal State ---\n\nconst BASIS_INSTANCE_KEY = Symbol.for('__basis_engine_instance__');\n\nconst GRAPH_CLEANUP_INTERVAL = 5000; // Run every 5 seconds\nconst EVENT_TTL = 10000; // Keep events for 10 seconds\n\nconst NULL_SIGNAL: RingBufferMetadata = {\n role: SignalRole.PROJECTION,\n buffer: new Uint8Array(0),\n head: 0,\n density: 0,\n options: {}\n};\n\n// --- v0.6.0 EVENT TOPOLOGY ---\nlet activeEventId: string | null = null;\nlet activeEventTimer: any = null;\n\n// Garbage Collect old Event Nodes\nconst pruneGraph = () => {\n const now = Date.now();\n\n // Only checking the keys (Source Nodes)\n for (const source of instance.graph.keys()) {\n if (source.startsWith('Event_Tick_')) {\n // Extract timestamp from \"Event_Tick_1738492...\"\n const parts = source.split('_');\n const timestamp = parseInt(parts[2], 10);\n \n if (now - timestamp > EVENT_TTL) {\n instance.graph.delete(source);\n }\n }\n }\n};\n\nconst getEventId = () => {\n if (!activeEventId) {\n activeEventId = `Event_Tick_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;\n\n requestAnimationFrame(() => {\n activeEventId = null;\n });\n }\n return activeEventId;\n};\n\n// GLOBAL SINGLETON HMR BRIDGE\nconst getGlobalInstance = (): BasisEngineState => {\n const root = globalThis as any;\n if (!root[BASIS_INSTANCE_KEY]) {\n root[BASIS_INSTANCE_KEY] = {\n config: { debug: false },\n history: new Map<string, RingBufferMetadata>(),\n currentTickBatch: new Set<string>(),\n redundantLabels: new Set<string>(),\n booted: false,\n tick: 0,\n isBatching: false,\n currentEffectSource: null,\n lastStateUpdate: null,\n pausedVariables: new Set<string>(),\n graph: new Map<string, Map<string, number>>(),\n violationMap: new Map<string, ViolationDetail[]>(),\n metrics: {\n lastAnalysisTimeMs: 0,\n comparisonCount: 0,\n lastAnalysisTimestamp: 0,\n systemEntropy: 0\n },\n alertCount: 0,\n loopCounters: new Map<string, number>(),\n lastCleanup: Date.now()\n };\n }\n return root[BASIS_INSTANCE_KEY];\n};\n\nexport const instance = getGlobalInstance();\n\nexport const config = instance.config;\nexport const history = instance.history;\nexport const redundantLabels = instance.redundantLabels;\nexport const currentTickBatch = instance.currentTickBatch;\n\nlet currentTickRegistry: Record<string, boolean> = {};\nconst dirtyLabels = new Set<string>();\n\n// TEMPORAL ENTROPY\nconst calculateTickEntropy = (tickIdx: number) => {\n let activeCount = 0;\n const total = instance.history.size;\n if (total === 0) return 1;\n\n instance.history.forEach((meta: RingBufferMetadata) => {\n if (meta.buffer[tickIdx] === 1) activeCount++;\n });\n return 1 - (activeCount / total);\n};\n\nexport const recordEdge = (source: string, target: string) => {\n if (!source || !target || source === target) return;\n if (!instance.graph.has(source)) {\n instance.graph.set(source, new Map());\n }\n const targets = instance.graph.get(source)!;\n targets.set(target, (targets.get(target) || 0) + 1);\n};\n\nexport const analyzeBasis = () => {\n if (!instance.config.debug || dirtyLabels.size === 0) {\n return;\n }\n\n const scheduler = (globalThis as any).requestIdleCallback || ((cb: any) => setTimeout(cb, 1));\n const snapshot = new Set(dirtyLabels);\n dirtyLabels.clear();\n\n scheduler(() => {\n const analysisStart = performance.now();\n const allEntries: Entry[] = [];\n const dirtyEntries: Entry[] = [];\n\n instance.history.forEach((meta: RingBufferMetadata, label: string) => {\n if (meta.options.suppressAll || meta.density === 0) return;\n\n const entry: Entry = {\n label, meta,\n isVolatile: meta.density > VOLATILITY_THRESHOLD\n };\n\n allEntries.push(entry);\n if (snapshot.has(label)) {\n dirtyEntries.push(entry);\n }\n });\n\n if (dirtyEntries.length === 0 || allEntries.length < 2) return;\n\n const nextRedundant = new Set<string>();\n instance.redundantLabels.forEach((l: string) => {\n if (!snapshot.has(l)) {\n nextRedundant.add(l);\n }\n });\n\n const { compCount, violationMap } = detectSubspaceOverlap(\n dirtyEntries,\n allEntries,\n nextRedundant,\n snapshot,\n instance.graph\n );\n\n instance.redundantLabels.clear();\n nextRedundant.forEach((l: string) => {\n instance.redundantLabels.add(l);\n });\n\n violationMap.forEach((newList, label) => {\n const existing = instance.violationMap.get(label) || [];\n newList.forEach(detail => {\n const alreadyExists = existing.some(\n v => v.type === detail.type && v.target === detail.target\n );\n if (!alreadyExists) {\n existing.push(detail);\n }\n });\n instance.violationMap.set(label, existing);\n });\n\n if (instance.violationMap.size > 500) {\n const keys = Array.from(instance.violationMap.keys()).slice(0, 200);\n keys.forEach(k => instance.violationMap.delete(k));\n }\n\n instance.metrics.lastAnalysisTimeMs = performance.now() - analysisStart;\n instance.metrics.comparisonCount = compCount;\n instance.metrics.lastAnalysisTimestamp = Date.now();\n });\n};\n\nconst processHeartbeat = () => {\n instance.tick++;\n\n instance.history.forEach((meta: RingBufferMetadata, label: string) => {\n const oldValue = meta.buffer[meta.head];\n const newValue = instance.currentTickBatch.has(label) ? 1 : 0;\n\n meta.buffer[meta.head] = newValue;\n if (oldValue !== newValue) {\n meta.density += (newValue - oldValue);\n }\n\n meta.head = (meta.head + 1) % WINDOW_SIZE;\n });\n\n const lastHead = (instance.history.size > 0) ? (instance.tick % WINDOW_SIZE) : 0;\n instance.metrics.systemEntropy = calculateTickEntropy(lastHead);\n\n instance.currentTickBatch.clear();\n currentTickRegistry = {};\n instance.isBatching = false;\n instance.lastStateUpdate = null;\n\n if (dirtyLabels.size > 0) {\n analyzeBasis();\n }\n};\n\n// INTERCEPTION LAYER\nexport const recordUpdate = (label: string): boolean => {\n if (!instance.config.debug) return true;\n if (instance.pausedVariables.has(label)) return false;\n\n const now = Date.now();\n if (now - instance.lastCleanup > 1000) {\n instance.loopCounters.clear();\n instance.lastCleanup = now;\n\n pruneGraph();\n }\n\n const count = (instance.loopCounters.get(label) || 0) + 1;\n instance.loopCounters.set(label, count);\n\n if (count > LOOP_THRESHOLD) {\n UI.displayViolentBreaker(label, count, LOOP_THRESHOLD);\n instance.pausedVariables.add(label);\n return false;\n }\n\n const meta = instance.history.get(label);\n\n // --- CAUSAL RESOLUTION ---\n let edgeSource: string | null = null;\n\n // PRIORITY 1: Explicit Effect Driver\n // If we are inside an effect, it IS the cause.\n if (instance.currentEffectSource) {\n edgeSource = instance.currentEffectSource;\n }\n // PRIORITY 2: The Event Horizon (Siblings)\n // We removed the synchronous state-to-state link here.\n // If A and B update in the same event handler, they are siblings (Event -> A, Event -> B).\n // They are NOT a dependency chain (A -> B).\n else {\n edgeSource = getEventId();\n }\n\n // Record graph edge\n if (edgeSource && edgeSource !== label) {\n recordEdge(edgeSource, label);\n\n // Hinting Logic (only for non-events)\n if (instance.currentEffectSource && instance.currentEffectSource !== label) {\n\n const sourceMeta = instance.history.get(instance.currentEffectSource) || NULL_SIGNAL;\n\n // Volatility Guard\n if (meta && sourceMeta && meta.density < VOLATILITY_THRESHOLD && sourceMeta.density < VOLATILITY_THRESHOLD) {\n UI.displayCausalHint(label, meta, instance.currentEffectSource, sourceMeta);\n }\n }\n }\n\n // Source Tracking\n // We still track this for future features, but we don't use it for \n // immediate causal attribution anymore to prevent sibling-glomming.\n if (meta && meta.role === SignalRole.LOCAL && !instance.currentEffectSource) {\n instance.lastStateUpdate = label;\n }\n\n if (currentTickRegistry[label]) return true;\n\n currentTickRegistry[label] = true;\n instance.currentTickBatch.add(label);\n dirtyLabels.add(label);\n\n if (!instance.isBatching) {\n instance.isBatching = true;\n requestAnimationFrame(processHeartbeat);\n }\n\n return true;\n};\n\n// --- LIFECYCLE API ---\n\nexport const configureBasis = (c: any) => {\n Object.assign(instance.config, c);\n if (instance.config.debug && !instance.booted) {\n UI.displayBootLog(WINDOW_SIZE);\n instance.booted = true;\n }\n};\n\nexport const registerVariable = (l: string, o: StateOptions = {}) => {\n if (o.suppressAll) return;\n\n if (!instance.history.has(l)) {\n instance.history.set(l, {\n buffer: new Uint8Array(WINDOW_SIZE),\n head: 0,\n density: 0,\n options: o,\n role: o.role || SignalRole.LOCAL\n });\n }\n};\n\nexport const unregisterVariable = (l: string) => {\n instance.history.delete(l);\n instance.loopCounters.delete(l);\n instance.pausedVariables.delete(l);\n instance.redundantLabels.delete(l);\n};\n\nexport const beginEffectTracking = (l: string) => {\n if (instance.config.debug) instance.currentEffectSource = l;\n};\n\nexport const endEffectTracking = () => {\n instance.currentEffectSource = null;\n};\n\nexport const printBasisHealthReport = (threshold = 0.5) => {\n if (!instance.config.debug) return;\n UI.displayHealthReport(instance.history, threshold, instance.violationMap);\n};\n\nexport const getBasisMetrics = () => ({\n engine: 'v0.6.x',\n hooks: instance.history.size,\n analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3),\n entropy: instance.metrics.systemEntropy.toFixed(3)\n});\n\nif (typeof window !== 'undefined') {\n (window as any).printBasisReport = printBasisHealthReport;\n (window as any).getBasisMetrics = getBasisMetrics;\n}\n\nexport const __testEngine__ = {\n instance,\n history,\n configureBasis,\n registerVariable,\n unregisterVariable,\n recordUpdate,\n printBasisHealthReport,\n analyzeBasis,\n beginEffectTracking,\n endEffectTracking\n};\n"],"mappings":"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","names":["history","redundantLabels","meta","history","dirtyLabels"]}
|
package/dist/index.js
CHANGED
|
@@ -126,11 +126,26 @@ var calculateSpectralInfluence = (graph, maxIterations = 20, tolerance = 1e-3) =
|
|
|
126
126
|
return scores;
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
-
// src/core/
|
|
129
|
+
// src/core/constants.ts
|
|
130
|
+
var WINDOW_SIZE = 50;
|
|
131
|
+
var SIMILARITY_THRESHOLD = 0.88;
|
|
132
|
+
var LOOP_THRESHOLD = 150;
|
|
133
|
+
var VOLATILITY_THRESHOLD = 25;
|
|
134
|
+
var INSTANCE_SEP = "##";
|
|
135
|
+
|
|
136
|
+
// src/core/label.ts
|
|
137
|
+
var stripInstance = (label) => {
|
|
138
|
+
const idx = label.indexOf(INSTANCE_SEP);
|
|
139
|
+
return idx === -1 ? label : label.slice(0, idx);
|
|
140
|
+
};
|
|
130
141
|
var parseLabel = (label) => {
|
|
131
|
-
const
|
|
132
|
-
|
|
142
|
+
const base = stripInstance(label);
|
|
143
|
+
const parts = base.split(" -> ");
|
|
144
|
+
return { file: parts[0] || "Unknown", name: parts[1] || base };
|
|
133
145
|
};
|
|
146
|
+
var isSameField = (labelA, labelB) => stripInstance(labelA) === stripInstance(labelB);
|
|
147
|
+
|
|
148
|
+
// src/core/ranker.ts
|
|
134
149
|
var identifyTopIssues = (graph, history2, redundantLabels2, violationMap) => {
|
|
135
150
|
const results = [];
|
|
136
151
|
const influence = calculateSpectralInfluence(graph);
|
|
@@ -260,10 +275,6 @@ var STYLES = {
|
|
|
260
275
|
bold: "font-weight: bold;",
|
|
261
276
|
label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;"
|
|
262
277
|
};
|
|
263
|
-
var parseLabel2 = (label) => {
|
|
264
|
-
const parts = label.split(" -> ");
|
|
265
|
-
return { file: parts[0] || "Unknown", name: parts[1] || label };
|
|
266
|
-
};
|
|
267
278
|
var shouldLog = (key) => {
|
|
268
279
|
const now = Date.now();
|
|
269
280
|
const last = LAST_LOG_TIMES.get(key) || 0;
|
|
@@ -286,7 +297,7 @@ var getSuggestedFix = (issue, info) => {
|
|
|
286
297
|
return `Local state is 'shadowing' Global Context. This creates two sources of truth. Delete the local state and consume the %cContext%c value directly.`;
|
|
287
298
|
}
|
|
288
299
|
if (leaks.length > 0) {
|
|
289
|
-
const targetName =
|
|
300
|
+
const targetName = parseLabel(leaks[0].target).name;
|
|
290
301
|
if (issue.label.includes("effect")) {
|
|
291
302
|
return `This Effect triggers a synchronous re-render of ${targetName}. Calculate ${targetName} during the render phase (Derived State) or wrap in %cuseMemo%c if expensive.`;
|
|
292
303
|
}
|
|
@@ -316,7 +327,7 @@ var displayHealthReport = (history2, threshold, violationMap) => {
|
|
|
316
327
|
`font-weight: normal; color: ${THEME.muted}; font-style: italic;`
|
|
317
328
|
);
|
|
318
329
|
topIssues.forEach((issue, idx) => {
|
|
319
|
-
const info =
|
|
330
|
+
const info = parseLabel(issue.label);
|
|
320
331
|
const icon = issue.metric === "influence" ? "\u26A1" : "\u{1F4C8}";
|
|
321
332
|
const pColor = idx === 0 ? THEME.problem : idx === 1 ? THEME.solution : THEME.identity;
|
|
322
333
|
let displayName = info.name;
|
|
@@ -336,7 +347,7 @@ var displayHealthReport = (history2, threshold, violationMap) => {
|
|
|
336
347
|
const byFile = /* @__PURE__ */ new Map();
|
|
337
348
|
issue.violations.forEach((v) => {
|
|
338
349
|
if (issue.label.includes("Global Event") && v.type === "context_mirror") return;
|
|
339
|
-
const { file, name } =
|
|
350
|
+
const { file, name } = parseLabel(v.target);
|
|
340
351
|
if (!byFile.has(file)) byFile.set(file, []);
|
|
341
352
|
byFile.get(file).push(name);
|
|
342
353
|
});
|
|
@@ -411,14 +422,21 @@ var displayHealthReport = (history2, threshold, violationMap) => {
|
|
|
411
422
|
const clusterMetas = cluster.map((l) => ({
|
|
412
423
|
label: l,
|
|
413
424
|
meta: history2.get(l),
|
|
414
|
-
name:
|
|
425
|
+
name: parseLabel(l).name
|
|
415
426
|
}));
|
|
416
|
-
const hasCtx = clusterMetas.some(
|
|
417
|
-
|
|
427
|
+
const hasCtx = clusterMetas.some(
|
|
428
|
+
(c) => c.meta.role === "context" /* CONTEXT */ || c.meta.role === "store" /* STORE */
|
|
429
|
+
);
|
|
430
|
+
const names = clusterMetas.map((c) => {
|
|
431
|
+
const prefix = c.meta.role === "store" /* STORE */ ? "\u03A3 " : c.meta.role === "context" /* CONTEXT */ ? "\u03A9 " : "";
|
|
432
|
+
return `${prefix}${c.name}`;
|
|
433
|
+
}).join(" \u27F7 ");
|
|
418
434
|
console.group(` %c${idx + 1}%c ${names}`, `background: ${THEME.problem}; color: white; border-radius: 50%; padding: 0 5px;`, "font-family: monospace; font-weight: bold;");
|
|
419
435
|
if (hasCtx) {
|
|
420
|
-
|
|
421
|
-
|
|
436
|
+
const hasStore = clusterMetas.some((c) => c.meta.role === "store" /* STORE */);
|
|
437
|
+
const sourceType = hasStore ? "External Store" : "global context";
|
|
438
|
+
console.log(`%cDiagnosis: ${hasStore ? "Store" : "Context"} Mirroring. Local state is shadowing ${sourceType}.`, `color: ${THEME.problem};`);
|
|
439
|
+
console.log(`%cSolution: Use ${sourceType} directly to avoid state drift.`, STYLES.actionLabel);
|
|
422
440
|
} else {
|
|
423
441
|
const boolKeywords = ["is", "has", "can", "should", "loading", "success", "error", "active", "enabled", "open", "visible"];
|
|
424
442
|
const boolCount = clusterMetas.filter(
|
|
@@ -445,15 +463,18 @@ var displayHealthReport = (history2, threshold, violationMap) => {
|
|
|
445
463
|
};
|
|
446
464
|
var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
|
|
447
465
|
if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
|
|
448
|
-
const infoA =
|
|
449
|
-
const infoB =
|
|
466
|
+
const infoA = parseLabel(labelA);
|
|
467
|
+
const infoB = parseLabel(labelB);
|
|
450
468
|
const isContextMirror = metaA.role === "local" /* LOCAL */ && metaB.role === "context" /* CONTEXT */ || metaB.role === "local" /* LOCAL */ && metaA.role === "context" /* CONTEXT */;
|
|
451
|
-
|
|
469
|
+
const isStoreMirror = metaA.role === "local" /* LOCAL */ && metaB.role === "store" /* STORE */ || metaB.role === "local" /* LOCAL */ && metaA.role === "store" /* STORE */;
|
|
470
|
+
const alertType = isContextMirror ? "CONTEXT MIRRORING" : isStoreMirror ? "STORE MIRRORING" : "DUPLICATE STATE";
|
|
471
|
+
console.group(`%c \u264A BASIS | ${alertType} `, STYLES.headerProblem);
|
|
452
472
|
console.log(`%c\u{1F4CD} Location: %c${infoA.file}`, STYLES.bold, STYLES.location);
|
|
453
473
|
console.log(`%cIssue:%c ${infoA.name} and ${infoB.name} are synchronized (${(sim * 100).toFixed(0)}%).`, STYLES.bold, "");
|
|
454
|
-
if (isContextMirror) {
|
|
474
|
+
if (isContextMirror || isStoreMirror) {
|
|
475
|
+
const sourceType = isStoreMirror ? "External Store" : "Global Context";
|
|
455
476
|
console.log(
|
|
456
|
-
`%cFix:%c Local state is 'shadowing'
|
|
477
|
+
`%cFix:%c Local state is 'shadowing' ${sourceType}. Delete the local state and consume the %c${sourceType}%c value directly.`,
|
|
457
478
|
STYLES.bold,
|
|
458
479
|
"",
|
|
459
480
|
STYLES.actionPill,
|
|
@@ -488,11 +509,11 @@ var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
|
|
|
488
509
|
};
|
|
489
510
|
var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
|
|
490
511
|
if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;
|
|
491
|
-
const target =
|
|
492
|
-
const source =
|
|
493
|
-
const
|
|
512
|
+
const target = parseLabel(targetLabel);
|
|
513
|
+
const source = parseLabel(sourceLabel);
|
|
514
|
+
const headerType = sourceMeta.role === "context" /* CONTEXT */ ? "CONTEXT SYNC LEAK" : sourceMeta.role === "store" /* STORE */ ? "STORE SYNC LEAK" : "DOUBLE RENDER";
|
|
494
515
|
const isEffect = sourceLabel.includes("effect") || sourceLabel.includes("useLayoutEffect");
|
|
495
|
-
console.groupCollapsed(`%c \u26A1 BASIS | ${
|
|
516
|
+
console.groupCollapsed(`%c \u26A1 BASIS | ${headerType} `, STYLES.headerProblem);
|
|
496
517
|
console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
|
|
497
518
|
console.log(`%cIssue:%c ${source.name} triggers ${target.name} in separate frames.`, STYLES.bold, "");
|
|
498
519
|
if (isEffect) {
|
|
@@ -520,10 +541,10 @@ var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
|
|
|
520
541
|
};
|
|
521
542
|
var displayViolentBreaker = (label, count, threshold) => {
|
|
522
543
|
if (!isWeb) return;
|
|
523
|
-
const
|
|
544
|
+
const { name } = parseLabel(label);
|
|
524
545
|
console.group(`%c \u{1F6D1} BASIS CRITICAL | CIRCUIT BREAKER `, STYLES.headerProblem);
|
|
525
546
|
console.error(`INFINITE LOOP DETECTED
|
|
526
|
-
Variable: ${
|
|
547
|
+
Variable: ${name}
|
|
527
548
|
Frequency: ${count} updates/sec`);
|
|
528
549
|
console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, `color: ${THEME.problem}; font-weight: bold;`);
|
|
529
550
|
console.groupEnd();
|
|
@@ -533,12 +554,6 @@ var displayBootLog = (windowSize) => {
|
|
|
533
554
|
console.log(`%cBasis%cAuditor%c "Graph Era" (Window: ${windowSize})`, STYLES.basis, STYLES.version, `color: ${THEME.muted}; font-style: italic; margin-left: 8px;`);
|
|
534
555
|
};
|
|
535
556
|
|
|
536
|
-
// src/core/constants.ts
|
|
537
|
-
var WINDOW_SIZE = 50;
|
|
538
|
-
var SIMILARITY_THRESHOLD = 0.88;
|
|
539
|
-
var LOOP_THRESHOLD = 150;
|
|
540
|
-
var VOLATILITY_THRESHOLD = 25;
|
|
541
|
-
|
|
542
557
|
// src/core/analysis.ts
|
|
543
558
|
var CAUSAL_MARGIN = 0.05;
|
|
544
559
|
var isEventDriven = (label, graph) => {
|
|
@@ -575,6 +590,7 @@ var calculateAllSimilarities = (entryA, entryB) => {
|
|
|
575
590
|
};
|
|
576
591
|
var shouldSkipComparison = (entryA, entryB, dirtyLabels2) => {
|
|
577
592
|
if (entryA.label === entryB.label) return true;
|
|
593
|
+
if (isSameField(entryA.label, entryB.label)) return true;
|
|
578
594
|
if (dirtyLabels2.has(entryB.label) && entryA.label > entryB.label) return true;
|
|
579
595
|
return false;
|
|
580
596
|
};
|
|
@@ -590,16 +606,17 @@ var pushViolation = (map, source, detail) => {
|
|
|
590
606
|
list.push(detail);
|
|
591
607
|
}
|
|
592
608
|
};
|
|
609
|
+
var isGlobalSource = (role) => role === "context" /* CONTEXT */ || role === "store" /* STORE */;
|
|
593
610
|
var detectRedundancy = (entryA, entryB, similarities, redundantSet, violationMap) => {
|
|
594
611
|
const roleA = entryA.meta.role;
|
|
595
612
|
const roleB = entryB.meta.role;
|
|
596
|
-
if (roleA
|
|
613
|
+
if (isGlobalSource(roleA) && isGlobalSource(roleB)) return;
|
|
597
614
|
if (entryA.meta.density < 2 || entryB.meta.density < 2) return;
|
|
598
|
-
if (roleA === "local" /* LOCAL */ && roleB
|
|
615
|
+
if (roleA === "local" /* LOCAL */ && isGlobalSource(roleB)) {
|
|
599
616
|
redundantSet.add(entryA.label);
|
|
600
617
|
pushViolation(violationMap, entryB.label, { type: "context_mirror", target: entryA.label, similarity: similarities.max });
|
|
601
618
|
displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
|
|
602
|
-
} else if (roleA
|
|
619
|
+
} else if (isGlobalSource(roleA) && roleB === "local" /* LOCAL */) {
|
|
603
620
|
redundantSet.add(entryB.label);
|
|
604
621
|
pushViolation(violationMap, entryA.label, { type: "context_mirror", target: entryB.label, similarity: similarities.max });
|
|
605
622
|
displayRedundancyAlert(entryB.label, entryB.meta, entryA.label, entryA.meta, similarities.max);
|
|
@@ -658,7 +675,6 @@ var NULL_SIGNAL = {
|
|
|
658
675
|
options: {}
|
|
659
676
|
};
|
|
660
677
|
var activeEventId = null;
|
|
661
|
-
var activeEventTimer = null;
|
|
662
678
|
var pruneGraph = () => {
|
|
663
679
|
const now = Date.now();
|
|
664
680
|
for (const source of instance.graph.keys()) {
|
|
@@ -674,10 +690,9 @@ var pruneGraph = () => {
|
|
|
674
690
|
var getEventId = () => {
|
|
675
691
|
if (!activeEventId) {
|
|
676
692
|
activeEventId = `Event_Tick_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;
|
|
677
|
-
|
|
678
|
-
activeEventTimer = setTimeout(() => {
|
|
693
|
+
requestAnimationFrame(() => {
|
|
679
694
|
activeEventId = null;
|
|
680
|
-
}
|
|
695
|
+
});
|
|
681
696
|
}
|
|
682
697
|
return activeEventId;
|
|
683
698
|
};
|
|
@@ -870,7 +885,7 @@ var configureBasis = (c) => {
|
|
|
870
885
|
}
|
|
871
886
|
};
|
|
872
887
|
var registerVariable = (l, o = {}) => {
|
|
873
|
-
if (
|
|
888
|
+
if (o.suppressAll) return;
|
|
874
889
|
if (!instance.history.has(l)) {
|
|
875
890
|
instance.history.set(l, {
|
|
876
891
|
buffer: new Uint8Array(WINDOW_SIZE),
|
|
@@ -911,39 +926,52 @@ if (typeof window !== "undefined") {
|
|
|
911
926
|
// src/hooks.ts
|
|
912
927
|
var anonCount = 0;
|
|
913
928
|
var getFallbackLabel = (type) => `anon_${type}_${anonCount++}`;
|
|
929
|
+
var reactUseId = React.useId;
|
|
930
|
+
var legacyInstanceCounter = 0;
|
|
931
|
+
var useInstanceId = () => {
|
|
932
|
+
const [legacyId] = (0, import_react.useState)(
|
|
933
|
+
() => typeof reactUseId === "function" ? "" : `legacy_${legacyInstanceCounter++}`
|
|
934
|
+
);
|
|
935
|
+
return typeof reactUseId === "function" ? reactUseId() : legacyId;
|
|
936
|
+
};
|
|
937
|
+
var withInstance = (label, instanceId) => `${label}${INSTANCE_SEP}${instanceId}`;
|
|
914
938
|
var React19 = React;
|
|
915
939
|
function useState(initialState, label) {
|
|
916
940
|
const [val, setVal] = (0, import_react.useState)(initialState);
|
|
917
941
|
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("state")).current;
|
|
942
|
+
const instanceId = useInstanceId();
|
|
943
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
918
944
|
(0, import_react.useEffect)(() => {
|
|
919
|
-
registerVariable(
|
|
945
|
+
registerVariable(storageKey, { role: "local" /* LOCAL */ });
|
|
920
946
|
return () => {
|
|
921
|
-
unregisterVariable(
|
|
947
|
+
unregisterVariable(storageKey);
|
|
922
948
|
};
|
|
923
|
-
}, [
|
|
949
|
+
}, [storageKey]);
|
|
924
950
|
const setter = (0, import_react.useCallback)((value) => {
|
|
925
|
-
if (recordUpdate(
|
|
951
|
+
if (recordUpdate(storageKey)) {
|
|
926
952
|
setVal(value);
|
|
927
953
|
}
|
|
928
|
-
}, [
|
|
954
|
+
}, [storageKey]);
|
|
929
955
|
return [val, setter];
|
|
930
956
|
}
|
|
931
957
|
function useReducer(reducer, initialArg, init, label) {
|
|
932
958
|
const isLazy = typeof init === "function";
|
|
933
959
|
const providedLabel = label || (typeof init === "string" ? init : void 0);
|
|
934
960
|
const effectiveLabel = (0, import_react.useRef)(providedLabel || getFallbackLabel("reducer")).current;
|
|
961
|
+
const instanceId = useInstanceId();
|
|
962
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
935
963
|
const [state, dispatch] = isLazy ? (0, import_react.useReducer)(reducer, initialArg, init) : (0, import_react.useReducer)(reducer, initialArg);
|
|
936
964
|
(0, import_react.useEffect)(() => {
|
|
937
|
-
registerVariable(
|
|
965
|
+
registerVariable(storageKey, { role: "local" /* LOCAL */ });
|
|
938
966
|
return () => {
|
|
939
|
-
unregisterVariable(
|
|
967
|
+
unregisterVariable(storageKey);
|
|
940
968
|
};
|
|
941
|
-
}, [
|
|
969
|
+
}, [storageKey]);
|
|
942
970
|
const basisDispatch = (0, import_react.useCallback)((action) => {
|
|
943
|
-
if (recordUpdate(
|
|
971
|
+
if (recordUpdate(storageKey)) {
|
|
944
972
|
dispatch(action);
|
|
945
973
|
}
|
|
946
|
-
}, [
|
|
974
|
+
}, [storageKey, dispatch]);
|
|
947
975
|
return [state, basisDispatch];
|
|
948
976
|
}
|
|
949
977
|
function createContext(defaultValue, label) {
|
|
@@ -969,28 +997,34 @@ function useContext(context) {
|
|
|
969
997
|
}
|
|
970
998
|
function useMemo(factory, deps, label) {
|
|
971
999
|
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("proj")).current;
|
|
1000
|
+
const instanceId = useInstanceId();
|
|
1001
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
972
1002
|
(0, import_react.useEffect)(() => {
|
|
973
|
-
registerVariable(
|
|
1003
|
+
registerVariable(storageKey, { role: "proj" /* PROJECTION */ });
|
|
974
1004
|
return () => {
|
|
975
|
-
unregisterVariable(
|
|
1005
|
+
unregisterVariable(storageKey);
|
|
976
1006
|
};
|
|
977
|
-
}, [
|
|
1007
|
+
}, [storageKey]);
|
|
978
1008
|
return (0, import_react.useMemo)(factory, deps || []);
|
|
979
1009
|
}
|
|
980
1010
|
function useCallback(callback, deps, label) {
|
|
981
1011
|
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("cb")).current;
|
|
1012
|
+
const instanceId = useInstanceId();
|
|
1013
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
982
1014
|
(0, import_react.useEffect)(() => {
|
|
983
|
-
registerVariable(
|
|
1015
|
+
registerVariable(storageKey, { role: "proj" /* PROJECTION */ });
|
|
984
1016
|
return () => {
|
|
985
|
-
unregisterVariable(
|
|
1017
|
+
unregisterVariable(storageKey);
|
|
986
1018
|
};
|
|
987
|
-
}, [
|
|
1019
|
+
}, [storageKey]);
|
|
988
1020
|
return (0, import_react.useCallback)(callback, deps);
|
|
989
1021
|
}
|
|
990
1022
|
function useEffect(effect, deps, label) {
|
|
991
1023
|
const effectiveLabel = label || "anonymous_effect";
|
|
1024
|
+
const instanceId = useInstanceId();
|
|
1025
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
992
1026
|
(0, import_react.useEffect)(() => {
|
|
993
|
-
beginEffectTracking(
|
|
1027
|
+
beginEffectTracking(storageKey);
|
|
994
1028
|
const destructor = effect();
|
|
995
1029
|
endEffectTracking();
|
|
996
1030
|
return typeof destructor === "function" ? destructor : void 0;
|
|
@@ -998,8 +1032,10 @@ function useEffect(effect, deps, label) {
|
|
|
998
1032
|
}
|
|
999
1033
|
function useLayoutEffect(effect, deps, label) {
|
|
1000
1034
|
const effectiveLabel = label || "anonymous_layout_effect";
|
|
1035
|
+
const instanceId = useInstanceId();
|
|
1036
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
1001
1037
|
(0, import_react.useLayoutEffect)(() => {
|
|
1002
|
-
beginEffectTracking(
|
|
1038
|
+
beginEffectTracking(storageKey);
|
|
1003
1039
|
const destructor = effect();
|
|
1004
1040
|
endEffectTracking();
|
|
1005
1041
|
return typeof destructor === "function" ? destructor : void 0;
|
|
@@ -1007,36 +1043,40 @@ function useLayoutEffect(effect, deps, label) {
|
|
|
1007
1043
|
}
|
|
1008
1044
|
function useOptimistic(passthrough, reducer, label) {
|
|
1009
1045
|
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("optimistic")).current;
|
|
1046
|
+
const instanceId = useInstanceId();
|
|
1047
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
1010
1048
|
(0, import_react.useEffect)(() => {
|
|
1011
|
-
registerVariable(
|
|
1049
|
+
registerVariable(storageKey, { role: "local" /* LOCAL */ });
|
|
1012
1050
|
return () => {
|
|
1013
|
-
unregisterVariable(
|
|
1051
|
+
unregisterVariable(storageKey);
|
|
1014
1052
|
};
|
|
1015
|
-
}, [
|
|
1053
|
+
}, [storageKey]);
|
|
1016
1054
|
const [state, reactAddOptimistic] = React19.useOptimistic(passthrough, reducer);
|
|
1017
1055
|
const addOptimistic = (0, import_react.useCallback)((payload) => {
|
|
1018
|
-
if (recordUpdate(
|
|
1056
|
+
if (recordUpdate(storageKey)) {
|
|
1019
1057
|
reactAddOptimistic(payload);
|
|
1020
1058
|
}
|
|
1021
|
-
}, [
|
|
1059
|
+
}, [storageKey, reactAddOptimistic]);
|
|
1022
1060
|
return [state, addOptimistic];
|
|
1023
1061
|
}
|
|
1024
1062
|
function useActionState(action, initialState, permalink, label) {
|
|
1025
1063
|
const isLabelArg = typeof permalink === "string" && label === void 0;
|
|
1026
1064
|
const effectiveLabel = (0, import_react.useRef)(isLabelArg ? permalink : label || getFallbackLabel("action_state")).current;
|
|
1027
1065
|
const actualPermalink = isLabelArg ? void 0 : permalink;
|
|
1066
|
+
const instanceId = useInstanceId();
|
|
1067
|
+
const storageKey = withInstance(effectiveLabel, instanceId);
|
|
1028
1068
|
const [state, reactDispatch, isPending] = React19.useActionState(action, initialState, actualPermalink);
|
|
1029
1069
|
(0, import_react.useEffect)(() => {
|
|
1030
|
-
registerVariable(
|
|
1070
|
+
registerVariable(storageKey, { role: "local" /* LOCAL */ });
|
|
1031
1071
|
return () => {
|
|
1032
|
-
unregisterVariable(
|
|
1072
|
+
unregisterVariable(storageKey);
|
|
1033
1073
|
};
|
|
1034
|
-
}, [
|
|
1074
|
+
}, [storageKey]);
|
|
1035
1075
|
const basisDispatch = (0, import_react.useCallback)((payload) => {
|
|
1036
|
-
if (recordUpdate(
|
|
1076
|
+
if (recordUpdate(storageKey)) {
|
|
1037
1077
|
reactDispatch(payload);
|
|
1038
1078
|
}
|
|
1039
|
-
}, [
|
|
1079
|
+
}, [storageKey, reactDispatch]);
|
|
1040
1080
|
return [state, basisDispatch, isPending];
|
|
1041
1081
|
}
|
|
1042
1082
|
var useRef = import_react.useRef;
|
|
@@ -1112,7 +1152,14 @@ var BasisHUD = () => {
|
|
|
1112
1152
|
if (!canvas) return;
|
|
1113
1153
|
const ctx = canvas.getContext("2d");
|
|
1114
1154
|
if (!ctx) return;
|
|
1115
|
-
const entries = Array.from(history.entries())
|
|
1155
|
+
const entries = Array.from(history.entries()).sort((a, b) => {
|
|
1156
|
+
const roleOrder = (role) => {
|
|
1157
|
+
if (role === "context") return 0;
|
|
1158
|
+
if (role === "store") return 1;
|
|
1159
|
+
return 2;
|
|
1160
|
+
};
|
|
1161
|
+
return roleOrder(a[1].role) - roleOrder(b[1].role);
|
|
1162
|
+
});
|
|
1116
1163
|
const dpr = window.devicePixelRatio || 1;
|
|
1117
1164
|
const rawWidth = HUD_DIMENSIONS.WINDOW_SIZE * HUD_DIMENSIONS.COL_WIDTH + HUD_DIMENSIONS.LABEL_WIDTH + HUD_DIMENSIONS.PADDING * 2;
|
|
1118
1165
|
const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2, 80);
|
|
@@ -1168,7 +1215,7 @@ function renderMatrix(ctx, entries) {
|
|
|
1168
1215
|
let rowIndex = 0;
|
|
1169
1216
|
for (const [label, meta] of entries) {
|
|
1170
1217
|
const y = rowIndex * rowH + pad;
|
|
1171
|
-
const isContext = meta.role === "context";
|
|
1218
|
+
const isContext = meta.role === "context" || meta.role === "store";
|
|
1172
1219
|
const isRedundant = !isContext && redundantLabels.has(label);
|
|
1173
1220
|
const { buffer, head } = meta;
|
|
1174
1221
|
let uiPos = 0;
|
|
@@ -1184,10 +1231,11 @@ function renderMatrix(ctx, entries) {
|
|
|
1184
1231
|
};
|
|
1185
1232
|
for (let i = head; i < L; i++) addToPath(buffer[i], uiPos++);
|
|
1186
1233
|
for (let i = 0; i < head; i++) addToPath(buffer[i], uiPos++);
|
|
1187
|
-
const stateName = label.
|
|
1234
|
+
const stateName = parseLabel(label).name;
|
|
1188
1235
|
const textX = L * colW + pad + 10;
|
|
1189
1236
|
ctx.fillStyle = isContext ? HUD_THEME.header : isRedundant ? HUD_THEME.error : HUD_THEME.text;
|
|
1190
|
-
|
|
1237
|
+
const prefix = meta.role === "store" ? "\u03A3 " : isContext ? "\u03A9 " : isRedundant ? "! " : "";
|
|
1238
|
+
ctx.fillText(prefix + stateName, textX, y + 9);
|
|
1191
1239
|
rowIndex++;
|
|
1192
1240
|
}
|
|
1193
1241
|
ctx.fillStyle = HUD_THEME.grid;
|
|
@@ -1216,7 +1264,7 @@ var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)
|
|
|
1216
1264
|
},
|
|
1217
1265
|
children: [
|
|
1218
1266
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: isExpanded ? "STATE BASIS MATRIX" : "\u{1F4D0} BASIS ACTIVE" }),
|
|
1219
|
-
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.
|
|
1267
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.6.x" })
|
|
1220
1268
|
]
|
|
1221
1269
|
}
|
|
1222
1270
|
);
|