arrayview 0.29.0__tar.gz → 0.29.2__tar.gz

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.
Files changed (216) hide show
  1. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/lifecycle.md +1 -1
  2. {arrayview-0.29.0 → arrayview-0.29.2}/PKG-INFO +1 -1
  3. arrayview-0.29.2/docs/vscode-window-routing-plan.md +37 -0
  4. {arrayview-0.29.0 → arrayview-0.29.2}/pyproject.toml +1 -1
  5. {arrayview-0.29.0 → arrayview-0.29.2}/scripts/release.sh +25 -16
  6. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_launcher.py +6 -4
  7. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_viewer.html +24 -88
  8. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_vscode_extension.py +1 -1
  9. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_vscode_signal.py +124 -93
  10. arrayview-0.29.2/src/arrayview/arrayview-opener.vsix +0 -0
  11. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_api.py +67 -4
  12. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_lifecycle_contract.py +165 -4
  13. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_view_component_integration.py +22 -0
  14. {arrayview-0.29.0 → arrayview-0.29.2}/uv.lock +1 -1
  15. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/extension.js +14 -1
  16. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/lifecycle_helpers.js +5 -0
  17. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/package.json +1 -1
  18. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/test_lifecycle_helpers.js +6 -0
  19. arrayview-0.29.0/src/arrayview/arrayview-opener.vsix +0 -0
  20. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/frontend-designer/SKILL.md +0 -0
  21. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/invocation-consistency/SKILL.md +0 -0
  22. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/modes-consistency/SKILL.md +0 -0
  23. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/SKILL.md +0 -0
  24. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
  25. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
  26. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
  27. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/running-code.md +0 -0
  28. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/session-management.md +0 -0
  29. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
  30. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
  31. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/tracing.md +0 -0
  32. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
  33. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/todo-workflow/SKILL.md +0 -0
  34. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
  35. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
  36. {arrayview-0.29.0 → arrayview-0.29.2}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
  37. {arrayview-0.29.0 → arrayview-0.29.2}/.github/copilot-instructions.md +0 -0
  38. {arrayview-0.29.0 → arrayview-0.29.2}/.github/workflows/docs.yml +0 -0
  39. {arrayview-0.29.0 → arrayview-0.29.2}/.github/workflows/python-publish.yml +0 -0
  40. {arrayview-0.29.0 → arrayview-0.29.2}/.gitignore +0 -0
  41. {arrayview-0.29.0 → arrayview-0.29.2}/.ignore +0 -0
  42. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/AGENTS.md +0 -0
  43. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/ROUTER.md +0 -0
  44. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/SETUP.md +0 -0
  45. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/SYNC.md +0 -0
  46. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/architecture.md +0 -0
  47. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/conventions.md +0 -0
  48. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/decisions.md +0 -0
  49. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/frontend.md +0 -0
  50. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/project-state.md +0 -0
  51. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/render-pipeline.md +0 -0
  52. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/setup.md +0 -0
  53. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/context/stack.md +0 -0
  54. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/INDEX.md +0 -0
  55. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/README.md +0 -0
  56. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/add-file-format.md +0 -0
  57. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/add-server-endpoint.md +0 -0
  58. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/animation-verify.md +0 -0
  59. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/debug-render.md +0 -0
  60. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/debug-vscode-extension-python.md +0 -0
  61. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/extend-compare-mode.md +0 -0
  62. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/extract-server-route-module.md +0 -0
  63. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/patterns/frontend-change.md +0 -0
  64. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/setup.sh +0 -0
  65. {arrayview-0.29.0 → arrayview-0.29.2}/.mex/sync.sh +0 -0
  66. {arrayview-0.29.0 → arrayview-0.29.2}/.opencode/opencode.json +0 -0
  67. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
  68. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
  69. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
  70. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
  71. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
  72. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
  73. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
  74. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
  75. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
  76. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
  77. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
  78. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
  79. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
  80. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
  81. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
  82. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
  83. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
  84. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
  85. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
  86. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
  87. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
  88. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
  89. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
  90. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
  91. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
  92. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
  93. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
  94. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
  95. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
  96. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
  97. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
  98. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
  99. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
  100. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
  101. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
  102. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
  103. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
  104. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
  105. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
  106. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
  107. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
  108. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
  109. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
  110. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
  111. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
  112. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
  113. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
  114. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
  115. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
  116. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
  117. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
  118. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
  119. {arrayview-0.29.0 → arrayview-0.29.2}/.playwright-cli/theme-dark.yml +0 -0
  120. {arrayview-0.29.0 → arrayview-0.29.2}/.python-version +0 -0
  121. {arrayview-0.29.0 → arrayview-0.29.2}/.vscode/settings.json +0 -0
  122. {arrayview-0.29.0 → arrayview-0.29.2}/AGENTS.md +0 -0
  123. {arrayview-0.29.0 → arrayview-0.29.2}/CONTRIBUTING.md +0 -0
  124. {arrayview-0.29.0 → arrayview-0.29.2}/DESIGN.md +0 -0
  125. {arrayview-0.29.0 → arrayview-0.29.2}/LICENSE +0 -0
  126. {arrayview-0.29.0 → arrayview-0.29.2}/README.md +0 -0
  127. {arrayview-0.29.0 → arrayview-0.29.2}/docs/comparing.md +0 -0
  128. {arrayview-0.29.0 → arrayview-0.29.2}/docs/configuration.md +0 -0
  129. {arrayview-0.29.0 → arrayview-0.29.2}/docs/display.md +0 -0
  130. {arrayview-0.29.0 → arrayview-0.29.2}/docs/index.md +0 -0
  131. {arrayview-0.29.0 → arrayview-0.29.2}/docs/launch-routing-refactor.md +0 -0
  132. {arrayview-0.29.0 → arrayview-0.29.2}/docs/lifecycle.md +0 -0
  133. {arrayview-0.29.0 → arrayview-0.29.2}/docs/loading.md +0 -0
  134. {arrayview-0.29.0 → arrayview-0.29.2}/docs/logo.png +0 -0
  135. {arrayview-0.29.0 → arrayview-0.29.2}/docs/measurement.md +0 -0
  136. {arrayview-0.29.0 → arrayview-0.29.2}/docs/remote.md +0 -0
  137. {arrayview-0.29.0 → arrayview-0.29.2}/docs/stylesheets/extra.css +0 -0
  138. {arrayview-0.29.0 → arrayview-0.29.2}/docs/viewing.md +0 -0
  139. {arrayview-0.29.0 → arrayview-0.29.2}/experiments/ws_tunnel_diag/ws_tunnel_diag.py +0 -0
  140. {arrayview-0.29.0 → arrayview-0.29.2}/matlab/arrayview.m +0 -0
  141. {arrayview-0.29.0 → arrayview-0.29.2}/mkdocs.yml +0 -0
  142. {arrayview-0.29.0 → arrayview-0.29.2}/plans/2026-04-14-immersive-animation.md +0 -0
  143. {arrayview-0.29.0 → arrayview-0.29.2}/plans/2026-05-07-unified-colormap-picker.md +0 -0
  144. {arrayview-0.29.0 → arrayview-0.29.2}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
  145. {arrayview-0.29.0 → arrayview-0.29.2}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
  146. {arrayview-0.29.0 → arrayview-0.29.2}/plans/egg-placement-mockup.html +0 -0
  147. {arrayview-0.29.0 → arrayview-0.29.2}/plans/refactoring_plan.md +0 -0
  148. {arrayview-0.29.0 → arrayview-0.29.2}/plans/roi-analysis-requirements.md +0 -0
  149. {arrayview-0.29.0 → arrayview-0.29.2}/plans/webview/LOG.md +0 -0
  150. {arrayview-0.29.0 → arrayview-0.29.2}/scripts/demo.py +0 -0
  151. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/ARCHITECTURE.md +0 -0
  152. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/__init__.py +0 -0
  153. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/__main__.py +0 -0
  154. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_analysis.py +0 -0
  155. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_app.py +0 -0
  156. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_codex_open.py +0 -0
  157. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_config.py +0 -0
  158. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_diff.py +0 -0
  159. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_icon.png +0 -0
  160. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_imaging.py +0 -0
  161. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_io.py +0 -0
  162. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_launch_plan.py +0 -0
  163. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_lifecycle.py +0 -0
  164. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_overlays.py +0 -0
  165. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_platform.py +0 -0
  166. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_render.py +0 -0
  167. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_analysis.py +0 -0
  168. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_export.py +0 -0
  169. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_loading.py +0 -0
  170. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_persistence.py +0 -0
  171. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_preload.py +0 -0
  172. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_query.py +0 -0
  173. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_rendering.py +0 -0
  174. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_segmentation.py +0 -0
  175. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_state.py +0 -0
  176. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_vectorfield.py +0 -0
  177. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_routes_websocket.py +0 -0
  178. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_segmentation.py +0 -0
  179. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_server.py +0 -0
  180. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_session.py +0 -0
  181. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_shell.html +0 -0
  182. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_synthetic_mri.py +0 -0
  183. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_torch.py +0 -0
  184. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_vectorfield.py +0 -0
  185. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_vscode.py +0 -0
  186. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/_vscode_browser.py +0 -0
  187. {arrayview-0.29.0 → arrayview-0.29.2}/src/arrayview/gsap.min.js +0 -0
  188. {arrayview-0.29.0 → arrayview-0.29.2}/tests/capture_v_animation.py +0 -0
  189. {arrayview-0.29.0 → arrayview-0.29.2}/tests/conftest.py +0 -0
  190. {arrayview-0.29.0 → arrayview-0.29.2}/tests/lifecycle_matrix.py +0 -0
  191. {arrayview-0.29.0 → arrayview-0.29.2}/tests/make_vectorfield_test_arrays.py +0 -0
  192. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_backend_shared.py +0 -0
  193. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_browser.py +0 -0
  194. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_cli.py +0 -0
  195. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_colorbar_hover_highlight.py +0 -0
  196. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_command_reachability.py +0 -0
  197. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_config.py +0 -0
  198. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_cross_mode_parametrized.py +0 -0
  199. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_interactions.py +0 -0
  200. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_io.py +0 -0
  201. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_large_arrays.py +0 -0
  202. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_launch_plan.py +0 -0
  203. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_loading_server.py +0 -0
  204. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_mode_consistency.py +0 -0
  205. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_mode_matrix.py +0 -0
  206. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_mode_roundtrip.py +0 -0
  207. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_nifti_meta.py +0 -0
  208. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_nifti_series.py +0 -0
  209. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_rgb_pixel_art.py +0 -0
  210. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_torch.py +0 -0
  211. {arrayview-0.29.0 → arrayview-0.29.2}/tests/test_view_component_unit.py +0 -0
  212. {arrayview-0.29.0 → arrayview-0.29.2}/tests/ui_audit.py +0 -0
  213. {arrayview-0.29.0 → arrayview-0.29.2}/tests/v_anim_frames/.gitkeep +0 -0
  214. {arrayview-0.29.0 → arrayview-0.29.2}/tests/visual_smoke.py +0 -0
  215. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/AGENTS.md +0 -0
  216. {arrayview-0.29.0 → arrayview-0.29.2}/vscode-extension/LICENSE +0 -0
@@ -60,7 +60,7 @@ This contract describes who owns the backend, when it starts, and what closes it
60
60
 
61
61
  - Remote or tunnel launches may persist when `--serve` or tunnel display ownership requires it.
62
62
  - VS Code tunnel display uses forwarded localhost URLs; the extension should configure the port, promote privacy when available, and resolve the URL with `asExternalUri`.
63
- - With multiple registered tunnel windows, a missing or stale `ARRAYVIEW_WINDOW_ID` must fail closed with a diagnostic rather than broadcasting to whichever window is focused.
63
+ - With multiple registered tunnel windows, a missing or stale `ARRAYVIEW_WINDOW_ID` uses the shared broadcast signal; only the focused VS Code window may claim it.
64
64
  - An exact registered `ARRAYVIEW_WINDOW_ID` wins; do not redirect it to a newer same-parent registration because live tunnel windows can share ancestry.
65
65
  - Plain SSH should use `localhost` forwarding guidance and stay transient unless a shared server was explicitly requested.
66
66
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.29.0
3
+ Version: 0.29.2
4
4
  Summary: Fast multi-dimensional array viewer
5
5
  Project-URL: Home, https://github.com/oscarvanderheide/arrayview
6
6
  Project-URL: Source, https://github.com/oscarvanderheide/arrayview
@@ -0,0 +1,37 @@
1
+ # VS Code Window Routing Plan
2
+
3
+ ## Problem
4
+
5
+ ArrayView can open the viewer tab in the wrong VS Code window when multiple
6
+ local windows and multiple remote/tunnel windows are active. The unsafe cases
7
+ are the ones where Python cannot prove the originating window and falls back to
8
+ writing multiple signal files or a shared signal file.
9
+
10
+ ## Contract
11
+
12
+ - An exact `ARRAYVIEW_WINDOW_ID` wins when its registration exists.
13
+ - A missing or stale `ARRAYVIEW_WINDOW_ID` with multiple active registrations
14
+ fails closed with a diagnostic.
15
+ - PID ancestry and IPC hook matching are allowed only when they identify a
16
+ single window.
17
+ - tmux client fallback is allowed only when all attached clients for the current
18
+ tmux session report the same `ARRAYVIEW_WINDOW_ID`.
19
+ - File-explorer opens launched by the extension keep using the extension's own
20
+ `ARRAYVIEW_WINDOW_ID`.
21
+
22
+ ## Implementation Slice
23
+
24
+ - Tighten `src/arrayview/_vscode_signal.py` window selection.
25
+ - Add focused lifecycle tests for local ambiguity, stale exact IDs, exact-ID
26
+ ownership, and tmux multi-client ambiguity.
27
+ - Avoid changing `_app.py` or the viewer frontend.
28
+
29
+ ## Manual Verification Targets
30
+
31
+ - Local VS Code terminal, one window: opens in that window.
32
+ - Local VS Code terminal, several windows: stale/missing exact ID prints a
33
+ diagnostic instead of opening elsewhere.
34
+ - Remote/tunnel terminal, several windows: exact ID opens the matching window;
35
+ stale/missing ID fails closed.
36
+ - File explorer custom editor: spawned Python receives the extension window ID
37
+ and opens back into the same window.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.29.0"
7
+ version = "0.29.2"
8
8
  description = "Fast multi-dimensional array viewer"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12"
@@ -8,7 +8,7 @@ set -euo pipefail
8
8
  BUMP="minor"
9
9
  DRY_RUN=true
10
10
  NO_AI=false
11
- AI_TOOL="claude"
11
+ AI_TOOL="codex"
12
12
 
13
13
  usage() {
14
14
  cat <<EOF
@@ -16,7 +16,7 @@ Usage: $(basename "$0") [OPTIONS]
16
16
 
17
17
  Options:
18
18
  --bump {major,minor,patch} Version bump type (default: minor)
19
- --ai {claude,codex} AI tool for release notes (default: claude)
19
+ --ai {claude,codex} AI tool for release notes (default: codex)
20
20
  --execute Actually run (default is dry-run)
21
21
  --no-ai Skip AI release notes, use GitHub's --generate-notes
22
22
  -h, --help Show this help
@@ -116,9 +116,13 @@ Rules:
116
116
  if command -v "$CODEX_BIN" &>/dev/null; then
117
117
  echo "Generating release notes with Codex..."
118
118
  tmpfile=$(mktemp)
119
- trap 'rm -f "$tmpfile"' EXIT
120
- if printf '%s\n' "$PROMPT" | "$CODEX_BIN" exec --output-last-message "$tmpfile" - >/dev/null 2>/dev/null; then
119
+ errfile=$(mktemp)
120
+ trap 'rm -f "$tmpfile" "$errfile"' EXIT
121
+ if printf '%s\n' "$PROMPT" | "$CODEX_BIN" exec --output-last-message "$tmpfile" - >/dev/null 2>"$errfile"; then
121
122
  NOTES=$(<"$tmpfile")
123
+ elif [[ -s "$errfile" ]]; then
124
+ echo "Codex release notes failed:"
125
+ sed 's/^/ /' "$errfile"
122
126
  fi
123
127
  fi
124
128
  ;;
@@ -127,7 +131,19 @@ fi
127
131
 
128
132
  if [[ -z "$NOTES" ]]; then
129
133
  if [[ "$NO_AI" == false ]]; then
130
- echo "AI notes unavailable, falling back to --generate-notes"
134
+ echo "AI notes unavailable, falling back to commit-based notes"
135
+ fi
136
+ NOTES="## What's new in $TAG"
137
+ if [[ -n "$COMMITS" ]]; then
138
+ while IFS= read -r commit; do
139
+ [[ -z "$commit" ]] && continue
140
+ message="${commit#* }"
141
+ NOTES+=$'\n'
142
+ NOTES+="- ${message}"
143
+ done <<< "$COMMITS"
144
+ else
145
+ NOTES+=$'\n'
146
+ NOTES+="- Maintenance release."
131
147
  fi
132
148
  fi
133
149
 
@@ -146,17 +162,10 @@ run git push origin main
146
162
  run git tag "$TAG"
147
163
  run git push origin "$TAG"
148
164
 
149
- if [[ -n "$NOTES" ]]; then
150
- run gh release create "$TAG" \
151
- --title "$TAG" \
152
- --notes "$NOTES" \
153
- --prerelease
154
- else
155
- run gh release create "$TAG" \
156
- --title "$TAG" \
157
- --generate-notes \
158
- --prerelease
159
- fi
165
+ run gh release create "$TAG" \
166
+ --title "$TAG" \
167
+ --notes "$NOTES" \
168
+ --prerelease
160
169
 
161
170
  if [[ "$DRY_RUN" == true ]]; then
162
171
  echo ""
@@ -677,9 +677,7 @@ def _activate_early_cli_native_shell(
677
677
  notified = bool(notify_result.get("notified"))
678
678
  except Exception:
679
679
  notified = False
680
- if notified and _wait_for_native_shell_or_viewer_connection(
681
- port, viewer_before=viewer_before
682
- ):
680
+ if notified and _wait_for_viewer_connection(port, before=viewer_before):
683
681
  return True
684
682
  _vprint(
685
683
  "[ArrayView] Native window did not connect to the backend; falling back to browser",
@@ -1216,8 +1214,12 @@ def _handle_cli_spawned_daemon(
1216
1214
  and not is_remote
1217
1215
  and not overlay_files
1218
1216
  and not compare_files
1217
+ and not sys.platform.startswith("linux")
1219
1218
  ):
1220
- url_shell_early = _shell_url(port, sid, name)
1219
+ # Linux QtWebEngine denies sessionStorage to the viewer iframe when its
1220
+ # parent shell was created from inline data. Let Linux open the normal
1221
+ # HTTP shell after the daemon is listening instead.
1222
+ url_shell_early = f"http://{_LOOPBACK_HOST}:{port}/shell"
1221
1223
  early_native_shell_opened, early_native_shell_proc = _open_webview_cli_tracked(
1222
1224
  url_shell_early, 1400, 900, shell_port=port
1223
1225
  )
@@ -439,7 +439,6 @@
439
439
  #mv-cb { border: none; }
440
440
  .highlight { color: var(--highlight); font-weight: bold; }
441
441
  .dim-size { opacity: 0.28; font-size: 0.68em; font-weight: normal; }
442
- .dim-hover-idx { font-size: 0.68em; font-weight: normal; color: var(--dim-hover, #777); opacity: 1; }
443
442
  .active-dim { font-weight: bold; }
444
443
  .playing-dim { font-weight: bold; }
445
444
  .vfield-t-dim { color: var(--vfield-t-dim); }
@@ -3338,6 +3337,7 @@
3338
3337
  #mv-panes.mv-crosshair-active .mv-pane::after {
3339
3338
  content: ''; position: absolute; inset: 0; z-index: 4;
3340
3339
  box-shadow: inset 0 0 0 var(--mv-plane-border-width, 1px) var(--mv-plane-border, var(--active-dim));
3340
+ opacity: 0.45;
3341
3341
  border-radius: inherit; box-sizing: border-box;
3342
3342
  pointer-events: none;
3343
3343
  }
@@ -13885,7 +13885,6 @@
13885
13885
  if (!['circle', 'rect', 'freehand', 'floodfill'].includes(_roiShape)) _roiShape = 'circle';
13886
13886
  _roiVisible = true;
13887
13887
  hideAllPixelInfo();
13888
- _resetDimbarHover();
13889
13888
  canvas.style.cursor = 'crosshair';
13890
13889
  if (qmriActive) qmriViews.forEach(v => { v.canvas.style.cursor = 'crosshair'; });
13891
13890
  if (multiViewActive) mvViews.forEach(v => { v.canvas.style.cursor = 'crosshair'; });
@@ -16481,38 +16480,6 @@
16481
16480
  _updateMvPaneFill();
16482
16481
  }
16483
16482
 
16484
- function _dimHoverPadded(val, maxVal) {
16485
- const maxStr = String(maxVal);
16486
- const valStr = String(val);
16487
- const padLen = maxStr.length - valStr.length;
16488
- if (padLen <= 0) return '/' + valStr;
16489
- return '/<span style="opacity:0.28">' + '0'.repeat(padLen) + '</span>' + valStr;
16490
- }
16491
- function _updateDimbarHover(px, py, xLabel, yLabel, pz) {
16492
- // xLabel/yLabel: 'x','y','z' — which dimbar label to update (default x,y)
16493
- // pz: optional z index (for mosaic mode)
16494
- const xl = xLabel || 'x', yl = yLabel || 'y';
16495
- const xEl = document.getElementById('dim-' + xl + '-size');
16496
- const yEl = document.getElementById('dim-' + yl + '-size');
16497
- const zEl = document.getElementById('dim-z-size');
16498
- // Resolve label to shape dim index for padding width
16499
- const labelToDim = (multiViewActive || compareMvActive)
16500
- ? { x: (multiViewActive ? mvDims : compareMvDims)[0], y: (multiViewActive ? mvDims : compareMvDims)[1], z: (multiViewActive ? mvDims : compareMvDims)[2] }
16501
- : { x: dim_x, y: dim_y, z: dim_z };
16502
- const xMax = labelToDim[xl] >= 0 ? shape[labelToDim[xl]] : 1;
16503
- const yMax = labelToDim[yl] >= 0 ? shape[labelToDim[yl]] : 1;
16504
- if (xEl) { xEl.innerHTML = _dimHoverPadded(px, xMax); xEl.className = 'dim-hover-idx'; }
16505
- if (yEl) { yEl.innerHTML = _dimHoverPadded(py, yMax); yEl.className = 'dim-hover-idx'; }
16506
- if (zEl && pz != null) {
16507
- const zMax = dim_z >= 0 ? shape[dim_z] : 1;
16508
- zEl.innerHTML = _dimHoverPadded(pz + 1, zMax); zEl.className = 'dim-hover-idx';
16509
- }
16510
- }
16511
- function _resetDimbarHover() {
16512
- // Re-render dimbar to restore correct max sizes for all modes
16513
- renderInfo();
16514
- }
16515
-
16516
16483
  // Gnomon visibility: shown while a dim-bar token is hovered, or flashed
16517
16484
  // briefly when activeDim changes via h/l/←/→. Hidden otherwise.
16518
16485
  // In oblique mode the x/y labels no longer name axis-aligned directions,
@@ -17711,13 +17678,18 @@
17711
17678
 
17712
17679
  function saveState() {
17713
17680
  if (!sid) return;
17714
- sessionStorage.setItem('av_' + sid, JSON.stringify(collectStateSnapshot()));
17681
+ try {
17682
+ sessionStorage.setItem('av_' + sid, JSON.stringify(collectStateSnapshot()));
17683
+ } catch (e) {
17684
+ // Some embedded webviews deny storage access. Viewing must keep
17685
+ // working even when this optional convenience is unavailable.
17686
+ }
17715
17687
  }
17716
17688
 
17717
17689
  function restoreStateFromSessionStorage() {
17718
- const raw = sessionStorage.getItem('av_' + sid);
17719
- if (!raw) return false;
17720
17690
  try {
17691
+ const raw = sessionStorage.getItem('av_' + sid);
17692
+ if (!raw) return false;
17721
17693
  return applyStateSnapshot(JSON.parse(raw));
17722
17694
  } catch (e) {
17723
17695
  return false;
@@ -20117,7 +20089,6 @@
20117
20089
  showPixelInfo(document.getElementById('main-pixel-info'), { valueText: _pixelFmt(d.value, _activeNumericContext()), rawX, rawY }, e.clientX, e.clientY);
20118
20090
  }).catch(() => {});
20119
20091
  }
20120
- _updateDimbarHover(localX, localY, null, null, zIdx);
20121
20092
  return;
20122
20093
  }
20123
20094
 
@@ -20131,11 +20102,6 @@
20131
20102
  imgW: canvas.width,
20132
20103
  imgH: canvas.height,
20133
20104
  displayEl: document.getElementById('main-pixel-info'),
20134
- onResult: (d, px, py) => {
20135
- if (_pixelInfoActive() && !multiViewActive && !compareActive) {
20136
- _updateDimbarHover(px, py);
20137
- }
20138
- },
20139
20105
  });
20140
20106
  });
20141
20107
  canvas.addEventListener('mouseleave', () => {
@@ -20154,8 +20120,7 @@
20154
20120
  if (_pixelInfoHeld) {
20155
20121
  _pixelInfoHeld = false;
20156
20122
  if (!_pixelInfoVisible) {
20157
- const piEl = document.getElementById('main-pixel-info');
20158
- if (piEl) piEl.style.display = 'none';
20123
+ hideAllPixelInfo();
20159
20124
  }
20160
20125
  }
20161
20126
  });
@@ -20924,7 +20889,6 @@
20924
20889
  if (!_pixelInfoVisible) {
20925
20890
  _clearHoverPins();
20926
20891
  hideAllPixelInfo();
20927
- _resetDimbarHover();
20928
20892
  const axEl = document.getElementById('main-axes-svg');
20929
20893
  if (axEl) {
20930
20894
  axEl.querySelector('.axes-lbl-x').textContent = 'x';
@@ -26047,21 +26011,6 @@
26047
26011
  imgH: view.lastH,
26048
26012
  view,
26049
26013
  displayEl: view.pixelInfoEl,
26050
- onResult: (d, px, py) => {
26051
- if (_pixelInfoActive()) {
26052
- // Map pane dims to dimbar x/y/z labels
26053
- const labels = ['x','y','z'];
26054
- const activeDims = multiViewActive ? mvDims : (compareMvActive ? compareMvDims : []);
26055
- const posX = activeDims.indexOf(view.dimX);
26056
- const posY = activeDims.indexOf(view.dimY);
26057
- const lblX = labels[posX] || 'x';
26058
- const lblY = labels[posY] || 'y';
26059
- const elX = document.getElementById('dim-' + lblX + '-size');
26060
- const elY = document.getElementById('dim-' + lblY + '-size');
26061
- if (elX) { elX.textContent = '/' + px; elX.className = 'dim-hover-idx'; }
26062
- if (elY) { elY.textContent = '/' + py; elY.className = 'dim-hover-idx'; }
26063
- }
26064
- },
26065
26014
  });
26066
26015
  });
26067
26016
  cv.addEventListener('mouseleave', () => {
@@ -26072,7 +26021,6 @@
26072
26021
  if (tq) tq.classList.remove('visible');
26073
26022
  _roiSuppressPixelInfo = false;
26074
26023
  if (!mvDraggingView && view.pixelInfoEl) view.pixelInfoEl.style.display = 'none';
26075
- if (_pixelInfoActive()) _resetDimbarHover();
26076
26024
  });
26077
26025
  // Click-to-copy: multiview canvases
26078
26026
  let _mvClickDown = null;
@@ -26935,7 +26883,6 @@
26935
26883
  view,
26936
26884
  onResult: (d, px, py) => {
26937
26885
  if (_pixelInfoActive()) {
26938
- _updateDimbarHover(px, py);
26939
26886
  return; // hover mode: only show hovered pane's value
26940
26887
  }
26941
26888
  // Non-hover: fetch for all other qmri views at same pixel
@@ -26962,10 +26909,9 @@
26962
26909
  });
26963
26910
  });
26964
26911
  cv.addEventListener('mouseleave', () => {
26965
- if (_qmriLoupeDrag && _qmriLoupeDrag.canvas === cv) _endQmriLoupe();
26966
- qmriViews.forEach(v => { if (v.pixelInfoEl) v.pixelInfoEl.style.display = 'none'; });
26967
- if (_pixelInfoActive()) _resetDimbarHover();
26968
- });
26912
+ if (_qmriLoupeDrag && _qmriLoupeDrag.canvas === cv) _endQmriLoupe();
26913
+ qmriViews.forEach(v => { if (v.pixelInfoEl) v.pixelInfoEl.style.display = 'none'; });
26914
+ });
26969
26915
  // ROI drawing on qMRI canvases
26970
26916
  if (rectRoiMode) cv.style.cursor = 'crosshair';
26971
26917
  cv.addEventListener('mousemove', (e) => {
@@ -27029,6 +26975,11 @@
27029
26975
  }
27030
26976
  });
27031
26977
  cv.addEventListener('mousedown', (e) => {
26978
+ if (!rectRoiMode && e.button === 0 && !e.shiftKey && !e.metaKey && !e.ctrlKey && !e.altKey
26979
+ && !_cropActive && !_segMode && !_rulerMode) {
26980
+ _pixelInfoHeld = true;
26981
+ cv.dispatchEvent(new MouseEvent('mousemove', { clientX: e.clientX, clientY: e.clientY, bubbles: true }));
26982
+ }
27032
26983
  if (!rectRoiMode || e.button !== 0 || e.shiftKey || e.metaKey) return;
27033
26984
  e.preventDefault(); sink.focus();
27034
26985
  const rect = cv.getBoundingClientRect();
@@ -27449,15 +27400,17 @@
27449
27400
  view,
27450
27401
  displayEl: view.pixelInfoEl,
27451
27402
  qmriRole: view.qmriRole,
27452
- onResult: (d, px, py) => {
27453
- if (_pixelInfoActive()) _updateDimbarHover(px, py);
27454
- },
27455
27403
  });
27456
27404
  });
27405
+ cv.addEventListener('mousedown', (e) => {
27406
+ if (e.button !== 0 || e.shiftKey || e.metaKey || e.ctrlKey || e.altKey
27407
+ || _cropActive || _segMode || _rulerMode) return;
27408
+ _pixelInfoHeld = true;
27409
+ cv.dispatchEvent(new MouseEvent('mousemove', { clientX: e.clientX, clientY: e.clientY, bubbles: true }));
27410
+ });
27457
27411
  cv.addEventListener('mouseleave', () => {
27458
27412
  if (_qmriLoupeDrag && _qmriLoupeDrag.canvas === cv) _endQmriLoupe();
27459
27413
  compareQmriViews.forEach(v => { if (v.pixelInfoEl) v.pixelInfoEl.style.display = 'none'; });
27460
- if (_pixelInfoActive()) _resetDimbarHover();
27461
27414
  });
27462
27415
  if (!httpTransport) {
27463
27416
  view.ws = createTransport(sidVal,
@@ -27936,20 +27889,6 @@
27936
27889
  imgH: view.lastH,
27937
27890
  view,
27938
27891
  displayEl: view.pixelInfoEl,
27939
- onResult: (d, px, py) => {
27940
- if (_pixelInfoActive()) {
27941
- const labels = ['x','y','z'];
27942
- const activeDims = compareMvDims || [];
27943
- const posX = activeDims.indexOf(view.dimX);
27944
- const posY = activeDims.indexOf(view.dimY);
27945
- const lblX = labels[posX] || 'x';
27946
- const lblY = labels[posY] || 'y';
27947
- const elX = document.getElementById('dim-' + lblX + '-size');
27948
- const elY = document.getElementById('dim-' + lblY + '-size');
27949
- if (elX) { elX.textContent = '/' + px; elX.className = 'dim-hover-idx'; }
27950
- if (elY) { elY.textContent = '/' + py; elY.className = 'dim-hover-idx'; }
27951
- }
27952
- },
27953
27892
  });
27954
27893
  });
27955
27894
  cv.addEventListener('mouseleave', () => {
@@ -27957,7 +27896,6 @@
27957
27896
  if (!cmvDraggingView) {
27958
27897
  compareMvViews.forEach(v => { if (v.pixelInfoEl) v.pixelInfoEl.style.display = 'none'; });
27959
27898
  }
27960
- if (_pixelInfoActive()) _resetDimbarHover();
27961
27899
  });
27962
27900
  // Click-to-copy: compare-multiview canvases
27963
27901
  let _cmvClickDown = null;
@@ -30116,7 +30054,6 @@
30116
30054
  displayEl: piEl,
30117
30055
  onResult: (d, px, py) => {
30118
30056
  if (!_pixelInfoActive()) return;
30119
- _updateDimbarHover(px, py);
30120
30057
  // Show value on other compare panes at the same pixel
30121
30058
  const ver = indices.join(',') + ':' + dim_x + ':' + dim_y + ':' + complexMode + ':' + logScale;
30122
30059
  compareCanvases.forEach((ocv, j) => {
@@ -30145,7 +30082,6 @@
30145
30082
  cv.addEventListener('mouseleave', () => {
30146
30083
  _comparePiEls.forEach(p => { if (p) p.style.display = 'none'; });
30147
30084
  hideCompareCrosshairs();
30148
- if (_pixelInfoActive()) _resetDimbarHover();
30149
30085
  });
30150
30086
  });
30151
30087
  // Click-to-copy: compare canvases
@@ -44,7 +44,7 @@ def _vscode_app_bundle() -> str | None:
44
44
 
45
45
  _VSCODE_EXT_INSTALLED = False # cached so we only check once per process
46
46
  _VSCODE_EXT_FRESH_INSTALL = False # True if we just installed it this session
47
- _VSCODE_EXT_VERSION = "0.14.33" # current bundled extension version
47
+ _VSCODE_EXT_VERSION = "0.14.35" # current bundled extension version
48
48
 
49
49
  def _bundled_vscode_vsix_version(vsix_path: str) -> str | None:
50
50
  """Return the bundled opener extension version recorded inside the VSIX."""