@mindexec/cli 0.2.235 → 0.2.236

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindexec/cli",
3
- "version": "0.2.235",
3
+ "version": "0.2.236",
4
4
  "description": "MindExec local runtime and bridge CLI",
5
5
  "main": "server.js",
6
6
  "type": "module",
@@ -5,7 +5,7 @@
5
5
  const DEBUG = false;
6
6
  const FPS_DEBUG = false;
7
7
  const FRAME_PERF_DEBUG = false;
8
- const MINDMAP_CORE_BUILD_ID = '20260620-zoom-grid-style-freeze-v682';
8
+ const MINDMAP_CORE_BUILD_ID = '20260620-zoom-settle-idle-v683';
9
9
  const CanvasPhase = Object.freeze({
10
10
  Booting: 'booting',
11
11
  BoardFileLoading: 'board-file-loading',
@@ -113,6 +113,7 @@
113
113
  const CAMERA_MOTION_VISUAL_ONLY_FAST_PATH_ENABLED = true;
114
114
  const CAMERA_MOTION_WEBGL_CANVAS_TRANSFORM_ENABLED = true;
115
115
  const CAMERA_STATIONARY_INTERACTION_FRAME_DELAY_MS = 48;
116
+ const CAMERA_ZOOM_END_DELAY_MS = 150;
116
117
  const CAMERA_MOTION_GLOBAL_STYLE_CLASS_ENABLED = false;
117
118
  const CAMERA_DENSE_GLOBAL_STYLE_CLASS_ENABLED = false;
118
119
  const PIPELINE_PROFILE_SECTION_KEYS = Object.freeze([
@@ -1053,6 +1054,7 @@
1053
1054
  stationaryVisual: 0,
1054
1055
  residentVisual: 0,
1055
1056
  earlyCameraOnly: 0,
1057
+ zoomSettleIdle: 0,
1056
1058
  css3dCameraFast: 0,
1057
1059
  normal: 0,
1058
1060
  visibilityCulling: 0,
@@ -1088,6 +1090,10 @@
1088
1090
  return 'ultra-camera-only';
1089
1091
  }
1090
1092
 
1093
+ if (frameProfile.uaZoomSettleIdle === true) {
1094
+ return 'zoom-settle-idle';
1095
+ }
1096
+
1091
1097
  if (frameProfile.uaVisualOnlyMotion === true) {
1092
1098
  return 'visual-only';
1093
1099
  }
@@ -1158,6 +1164,9 @@
1158
1164
  mode === 'stationary-camera-navigation') {
1159
1165
  stats.earlyCameraOnly += 1;
1160
1166
  }
1167
+ if (mode === 'zoom-settle-idle') {
1168
+ stats.zoomSettleIdle += 1;
1169
+ }
1161
1170
  if (frameProfile.usedCss3dCameraFastPath === true) {
1162
1171
  stats.css3dCameraFast += 1;
1163
1172
  }
@@ -1187,7 +1196,8 @@
1187
1196
  const visualOnlyTotal = Number(stats.visualOnly || 0) +
1188
1197
  Number(stats.stationaryVisual || 0) +
1189
1198
  Number(stats.residentVisual || 0) +
1190
- Number(stats.earlyCameraOnly || 0);
1199
+ Number(stats.earlyCameraOnly || 0) +
1200
+ Number(stats.zoomSettleIdle || 0);
1191
1201
  stats.visualOnlyPercent = Number((visualOnlyTotal / total * 100).toFixed(1));
1192
1202
  stats.cameraFastPercent = Number((Number(stats.css3dCameraFast || 0) / total * 100).toFixed(1));
1193
1203
  stats.normalPercent = Number((Number(stats.normal || 0) / total * 100).toFixed(1));
@@ -1318,6 +1328,156 @@
1318
1328
  }
1319
1329
  }
1320
1330
 
1331
+ function tryRunZoomSettleIdleFrame(module, loop, frameStart, isCameraMoving, shouldCaptureFramePerf, frameProfTimes, profileSection) {
1332
+ if (!module ||
1333
+ CAMERA_MOTION_VISUAL_ONLY_FAST_PATH_ENABLED !== true ||
1334
+ module.isZooming !== true ||
1335
+ isCameraMoving === true ||
1336
+ module.isPanning === true ||
1337
+ module.isLoading === true ||
1338
+ module.isSelecting === true ||
1339
+ module.isDraggingNode === true ||
1340
+ module.isDraggingMultipleNodes === true ||
1341
+ module.isResizing === true ||
1342
+ module.isWindowResizing === true ||
1343
+ module.useAnimation60Fps === true ||
1344
+ !module.camera) {
1345
+ return false;
1346
+ }
1347
+
1348
+ const lastZoomInput = Number(module._zoomInputTime || 0);
1349
+ if (lastZoomInput <= 0) {
1350
+ return false;
1351
+ }
1352
+
1353
+ const elapsedSinceZoomInput = frameStart - lastZoomInput;
1354
+ if (!Number.isFinite(elapsedSinceZoomInput) ||
1355
+ elapsedSinceZoomInput < 0 ||
1356
+ elapsedSinceZoomInput > CAMERA_ZOOM_END_DELAY_MS) {
1357
+ return false;
1358
+ }
1359
+
1360
+ const forceUpdateFrames = Math.max(0, Number(module._forceUpdateFrames || 0));
1361
+ const cameraNavigationForceFrames = Math.max(0, Number(module._cameraNavigationForceFrames || 0));
1362
+ const hasForcedUpdate = forceUpdateFrames > 0;
1363
+ const hasOnlyCameraNavigationForcedUpdate =
1364
+ hasForcedUpdate &&
1365
+ cameraNavigationForceFrames >= forceUpdateFrames;
1366
+ if (hasForcedUpdate && hasOnlyCameraNavigationForcedUpdate !== true) {
1367
+ return false;
1368
+ }
1369
+
1370
+ const hasEditingTextOverlayFocus = !!(
1371
+ String(module._textOverlayV2State?.editing?.nodeId || '').trim() ||
1372
+ String(module._editingOverlayState?.nodeId || '').trim()
1373
+ );
1374
+ if (hasEditingTextOverlayFocus) {
1375
+ return false;
1376
+ }
1377
+
1378
+ const hasPendingCss3dStructuralTransformWork = !!(
1379
+ (module._cssTransformDirtyIds?.size || 0) > 0 ||
1380
+ module._cssParentRepairNeeded === true
1381
+ );
1382
+ if (hasPendingCss3dStructuralTransformWork) {
1383
+ return false;
1384
+ }
1385
+
1386
+ if (module._css3dVisualChangedThisFrame === true ||
1387
+ module._css3dVisualChangedSinceLastRender === true) {
1388
+ module._css3dVisualDeferredForMotion = true;
1389
+ }
1390
+ if (module._overlayDirty === true ||
1391
+ String(module._textOverlayV2State?.selectionNodeId || '').trim() ||
1392
+ String(module._selectableTextOverlayNodeId || '').trim()) {
1393
+ module._deferPassiveOverlayRefresh = true;
1394
+ }
1395
+
1396
+ if (hasForcedUpdate) {
1397
+ module._forceUpdateFrames = Math.max(0, forceUpdateFrames - 1);
1398
+ if (cameraNavigationForceFrames > 0) {
1399
+ module._cameraNavigationForceFrames = Math.max(0, cameraNavigationForceFrames - 1);
1400
+ }
1401
+ }
1402
+
1403
+ module._lastVisibilityCullingSkipReason = 'ua-zoom-settle-idle';
1404
+ recordCameraMotionFastPathStatus(module, 'hit', 'ua-zoom-settle-idle');
1405
+ profileSection?.('uaZoomSettleIdle');
1406
+
1407
+ const frameEnd = typeof performance !== 'undefined' && typeof performance.now === 'function'
1408
+ ? performance.now()
1409
+ : Date.now();
1410
+ const frameDuration = frameEnd - frameStart;
1411
+ module._lastFrameDurationMs = frameDuration;
1412
+ module._lastFrameMetricsAt = frameEnd;
1413
+ module._lastWebglRenderInfo = {
1414
+ calls: 0,
1415
+ triangles: 0,
1416
+ points: 0,
1417
+ lines: 0,
1418
+ skipped: true,
1419
+ uaZoomSettleIdle: true
1420
+ };
1421
+
1422
+ if (shouldCaptureFramePerf) {
1423
+ const sectionTimes = {};
1424
+ Object.entries(frameProfTimes || {})
1425
+ .filter(([key, value]) => key !== 'visibleNodes' && typeof value === 'number')
1426
+ .forEach(([key, value]) => {
1427
+ sectionTimes[key] = Number(value.toFixed(2));
1428
+ });
1429
+ module._lastFramePerfProfile = {
1430
+ durationMs: Number(frameDuration.toFixed(2)),
1431
+ update: false,
1432
+ cameraZ: Number((module.camera?.position?.z || 0).toFixed(2)),
1433
+ isZooming: true,
1434
+ isPanning: false,
1435
+ isCameraMoving: false,
1436
+ isCameraNavigationActive: true,
1437
+ isInLodMode: module.lodRenderer?.isInLODMode === true,
1438
+ lodBand: module.lodRenderer?._currentLodBand || null,
1439
+ visibleNodes: Number(module._visibleIds?.size || module._prevVisibleIds?.size || 0),
1440
+ freezeVisibility: true,
1441
+ freezeLod: module.lodRenderer?.isInLODMode === true,
1442
+ freezeFullRes: module.lodRenderer?.isInLODMode !== true,
1443
+ residentMidFarStable: module.lodRenderer?.isInLODMode === true,
1444
+ residentDirty: false,
1445
+ residentBandChanging: false,
1446
+ viewSyncMode: 'ua-zoom-settle-idle',
1447
+ lodUpdateCalled: false,
1448
+ lodUpdateSkipped: true,
1449
+ lodUpdateSkipReason: 'ua-zoom-settle-idle',
1450
+ lodSkipReason: '',
1451
+ lodDirtyReason: '',
1452
+ lodDirtyState: null,
1453
+ viewSyncBreakdown: null,
1454
+ shouldRunVisibilityCulling: false,
1455
+ visibilityStableSkip: true,
1456
+ visibilitySkipReason: 'ua-zoom-settle-idle',
1457
+ incrementalPanVisibility: false,
1458
+ shouldSyncCss3dTransforms: false,
1459
+ shouldRenderCss3d: false,
1460
+ usedCss3dCameraFastPath: false,
1461
+ uaZoomSettleIdle: true,
1462
+ shouldSyncTextOverlays: false,
1463
+ usedPassiveOverlayCameraFastPath: false,
1464
+ passiveOverlaySuppressed: module._suppressPassiveDomOverlayDuringZoom === true,
1465
+ webgl: module._lastWebglRenderInfo || null,
1466
+ sections: sectionTimes
1467
+ };
1468
+ updateFramePerfPeakProfile(module, module._lastFramePerfProfile, frameEnd);
1469
+ } else if (module._lastFramePerfProfile) {
1470
+ module._lastFramePerfProfile = null;
1471
+ }
1472
+
1473
+ const remainingMs = Math.max(1, CAMERA_ZOOM_END_DELAY_MS - elapsedSinceZoomInput + 1);
1474
+ const nextDelayMs = Math.max(16, remainingMs);
1475
+ module._lastAnimationLoopDelayMs = nextDelayMs;
1476
+ module._animationLoopExecuting = false;
1477
+ module._scheduleAnimationLoop(loop, nextDelayMs);
1478
+ return true;
1479
+ }
1480
+
1321
1481
  function tryRunUltraEarlyCameraOnlyFrame(module, loop, frameStart, isCameraMoving, shouldCaptureFramePerf, frameProfTimes, profileSection) {
1322
1482
  const isCameraNavigationActive =
1323
1483
  isCameraMoving === true ||
@@ -5858,12 +6018,11 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5858
6018
 
5859
6019
  // ▼▼▼ [Fix] 줌 종료 쿨다운 - 휠 입력 후 일정 시간 대기 ▼▼▼
5860
6020
  // _zoomInputTime은 interactions.js에서 휠 입력 시 설정됨
5861
- const ZOOM_END_DELAY_MS = 150; // 통일된 딜레이 (패닝 전환 여유 확보)
5862
- const zoomNow = performance.now();
5863
- const lastZoomInput = this._zoomInputTime || 0;
5864
- const timeSinceLastInput = zoomNow - lastZoomInput;
5865
-
5866
- if (this.isZooming && !isCameraMoving && timeSinceLastInput > ZOOM_END_DELAY_MS) {
6021
+ const zoomNow = performance.now();
6022
+ const lastZoomInput = this._zoomInputTime || 0;
6023
+ const timeSinceLastInput = zoomNow - lastZoomInput;
6024
+
6025
+ if (this.isZooming && !isCameraMoving && timeSinceLastInput > CAMERA_ZOOM_END_DELAY_MS) {
5867
6026
  this.isZooming = false;
5868
6027
  this.cssRenderer?.domElement?.classList?.remove?.('is-zooming');
5869
6028
  if (FRAME_PERF_DEBUG) {
@@ -5997,6 +6156,17 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
5997
6156
  // 3. Unified Visibility & LOD Pass (One Loop to Rule Them All)
5998
6157
  // ----------------------------------------------------------------
5999
6158
  this.frameCount = (this.frameCount || 0) + 1;
6159
+ if (tryRunZoomSettleIdleFrame(
6160
+ this,
6161
+ loop,
6162
+ frameStart,
6163
+ isCameraMoving,
6164
+ shouldCaptureFramePerf,
6165
+ _frameProfTimes,
6166
+ _profileSection
6167
+ ) === true) {
6168
+ return;
6169
+ }
6000
6170
  if (tryRunUltraEarlyCameraOnlyFrame(
6001
6171
  this,
6002
6172
  loop,
@@ -7,8 +7,8 @@
7
7
  <title>MindExec | Business Execution OS for solo builders</title>
8
8
  <meta name="description" content="MindExec is an AI business execution OS for solo builders who want to turn notes, research, assets, and repeatable execution Skills into revenue-producing work." />
9
9
  <base href="/" />
10
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260620-zoom-grid-style-freeze-v682" />
11
- <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260620-zoom-grid-style-freeze-v682" />
10
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/app.css?v=20260620-zoom-settle-idle-v683" />
11
+ <link rel="stylesheet" href="_content/MindExecution.Shared/css/mind-map-overrides.css?v=20260620-zoom-settle-idle-v683" />
12
12
  <!-- ?占썩뼹??Font Awesome (local) ?占썩뼹??-->
13
13
  <link rel="stylesheet" href="_content/MindExecution.Shared/lib/font-awesome/css/all.min.css" />
14
14
  <!-- ?占썩뼯??-->
@@ -579,7 +579,7 @@
579
579
  }
580
580
 
581
581
  const base = '_content/MindExecution.Shared/js/';
582
- const scriptVersion = '20260620-zoom-grid-style-freeze-v682';
582
+ const scriptVersion = '20260620-zoom-settle-idle-v683';
583
583
  const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
584
584
  console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
585
585
  const criticalScripts = [
@@ -1,5 +1,5 @@
1
1
  self.assetsManifest = {
2
- "version": "Bb7gNuNW",
2
+ "version": "KArZP7YJ",
3
3
  "assets": [
4
4
  {
5
5
  "hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
@@ -78,7 +78,7 @@
78
78
  "url": "_content/MindExecution.Shared/js/marked.min.js"
79
79
  },
80
80
  {
81
- "hash": "sha256-f21NTYhVmQcqoeMozAXBeF/XGDlYcx+EQE8RyuJVaSE=",
81
+ "hash": "sha256-J1AAQdPBWPRzvMK4P6IyUry5TNB6qoLo8yhiW/ufe2k=",
82
82
  "url": "_content/MindExecution.Shared/js/mind-map-core.js"
83
83
  },
84
84
  {
@@ -834,7 +834,7 @@
834
834
  "url": "image-manifest.json"
835
835
  },
836
836
  {
837
- "hash": "sha256-Bf3v8t4sqye7cFE8ehvHN/FdvilUpZdu7Pg/xI5fAmc=",
837
+ "hash": "sha256-c0UqlDqATxAedVrrky+NGpj/3I4LHORPhKK546n0Jso=",
838
838
  "url": "index.html"
839
839
  },
840
840
  {
@@ -1,4 +1,4 @@
1
- /* Manifest version: Bb7gNuNW */
1
+ /* Manifest version: KArZP7YJ */
2
2
  // Hosted deployments should prefer the network over stale offline caches.
3
3
  // This service worker immediately clears old Blazor offline caches and unregisters itself.
4
4