MetaList 0.6.1__tar.gz → 0.6.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 (449) hide show
  1. {metalist-0.6.1/metalist.egg-info → metalist-0.6.2}/PKG-INFO +18 -7
  2. {metalist-0.6.1 → metalist-0.6.2}/README.md +16 -5
  3. {metalist-0.6.1 → metalist-0.6.2}/app/exception_boundaries.py +5 -0
  4. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_switcher.py +55 -2
  5. {metalist-0.6.1 → metalist-0.6.2}/app/services/self_update.py +15 -18
  6. metalist-0.6.2/app/services/update_preflight.py +126 -0
  7. {metalist-0.6.1 → metalist-0.6.2}/app/version.py +1 -1
  8. {metalist-0.6.1 → metalist-0.6.2}/convert-from-legacy.py +4 -1
  9. {metalist-0.6.1 → metalist-0.6.2/metalist.egg-info}/PKG-INFO +18 -7
  10. {metalist-0.6.1 → metalist-0.6.2}/metalist.egg-info/SOURCES.txt +1 -0
  11. {metalist-0.6.1 → metalist-0.6.2}/pyproject.toml +1 -1
  12. {metalist-0.6.1 → metalist-0.6.2}/MANIFEST.in +0 -0
  13. {metalist-0.6.1 → metalist-0.6.2}/app/__init__.py +0 -0
  14. {metalist-0.6.1 → metalist-0.6.2}/app/api/__init__.py +0 -0
  15. {metalist-0.6.1 → metalist-0.6.2}/app/api/deps.py +0 -0
  16. {metalist-0.6.1 → metalist-0.6.2}/app/api/dev.py +0 -0
  17. {metalist-0.6.1 → metalist-0.6.2}/app/api/middleware/auth.py +0 -0
  18. {metalist-0.6.1 → metalist-0.6.2}/app/api/note_requests.py +0 -0
  19. {metalist-0.6.1 → metalist-0.6.2}/app/api/request_auth.py +0 -0
  20. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/ai.py +0 -0
  21. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/auth.py +0 -0
  22. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/backups.py +0 -0
  23. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/files.py +0 -0
  24. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/notes.py +0 -0
  25. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/ontology.py +0 -0
  26. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/reminders.py +0 -0
  27. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/remote_images.py +0 -0
  28. {metalist-0.6.1 → metalist-0.6.2}/app/api/routes/test.py +0 -0
  29. {metalist-0.6.1 → metalist-0.6.2}/app/api/transactions.py +0 -0
  30. {metalist-0.6.1 → metalist-0.6.2}/app/api/upload_limits.py +0 -0
  31. {metalist-0.6.1 → metalist-0.6.2}/app/config.py +0 -0
  32. {metalist-0.6.1 → metalist-0.6.2}/app/data_directory.py +0 -0
  33. {metalist-0.6.1 → metalist-0.6.2}/app/db/__init__.py +0 -0
  34. {metalist-0.6.1 → metalist-0.6.2}/app/db/backup_settings_sql.py +0 -0
  35. {metalist-0.6.1 → metalist-0.6.2}/app/db/engine.py +0 -0
  36. {metalist-0.6.1 → metalist-0.6.2}/app/db/file_schema.py +0 -0
  37. {metalist-0.6.1 → metalist-0.6.2}/app/db/file_session.py +0 -0
  38. {metalist-0.6.1 → metalist-0.6.2}/app/db/files_sql.py +0 -0
  39. {metalist-0.6.1 → metalist-0.6.2}/app/db/link_titles_sql.py +0 -0
  40. {metalist-0.6.1 → metalist-0.6.2}/app/db/live_recovery.py +0 -0
  41. {metalist-0.6.1 → metalist-0.6.2}/app/db/migrations.py +0 -0
  42. {metalist-0.6.1 → metalist-0.6.2}/app/db/notes_sql.py +0 -0
  43. {metalist-0.6.1 → metalist-0.6.2}/app/db/ontology_rules_sql.py +0 -0
  44. {metalist-0.6.1 → metalist-0.6.2}/app/db/reminders_sql.py +0 -0
  45. {metalist-0.6.1 → metalist-0.6.2}/app/db/retire_sounds.py +0 -0
  46. {metalist-0.6.1 → metalist-0.6.2}/app/db/schema.py +0 -0
  47. {metalist-0.6.1 → metalist-0.6.2}/app/db/search_history_sql.py +0 -0
  48. {metalist-0.6.1 → metalist-0.6.2}/app/db/session.py +0 -0
  49. {metalist-0.6.1 → metalist-0.6.2}/app/db/settings_sql.py +0 -0
  50. {metalist-0.6.1 → metalist-0.6.2}/app/db/tab_state_sql.py +0 -0
  51. {metalist-0.6.1 → metalist-0.6.2}/app/db/version.py +0 -0
  52. {metalist-0.6.1 → metalist-0.6.2}/app/encryption_audit.py +0 -0
  53. {metalist-0.6.1 → metalist-0.6.2}/app/https_proxy.py +0 -0
  54. {metalist-0.6.1 → metalist-0.6.2}/app/main.py +0 -0
  55. {metalist-0.6.1 → metalist-0.6.2}/app/models/commands.py +0 -0
  56. {metalist-0.6.1 → metalist-0.6.2}/app/models/database.py +0 -0
  57. {metalist-0.6.1 → metalist-0.6.2}/app/models/entities.py +0 -0
  58. {metalist-0.6.1 → metalist-0.6.2}/app/models/enums.py +0 -0
  59. {metalist-0.6.1 → metalist-0.6.2}/app/models/linked_list.py +0 -0
  60. {metalist-0.6.1 → metalist-0.6.2}/app/models/list_operations.py +0 -0
  61. {metalist-0.6.1 → metalist-0.6.2}/app/models/list_traversal.py +0 -0
  62. {metalist-0.6.1 → metalist-0.6.2}/app/models/note_crud.py +0 -0
  63. {metalist-0.6.1 → metalist-0.6.2}/app/models/utils.py +0 -0
  64. {metalist-0.6.1 → metalist-0.6.2}/app/presentation/__init__.py +0 -0
  65. {metalist-0.6.1 → metalist-0.6.2}/app/presentation/render/__init__.py +0 -0
  66. {metalist-0.6.1 → metalist-0.6.2}/app/presentation/render/note_renderer.py +0 -0
  67. {metalist-0.6.1 → metalist-0.6.2}/app/presentation/templates.py +0 -0
  68. {metalist-0.6.1 → metalist-0.6.2}/app/security/authenticated_logging.py +0 -0
  69. {metalist-0.6.1 → metalist-0.6.2}/app/security/encryption.py +0 -0
  70. {metalist-0.6.1 → metalist-0.6.2}/app/security/http_headers.py +0 -0
  71. {metalist-0.6.1 → metalist-0.6.2}/app/security/note_html.py +0 -0
  72. {metalist-0.6.1 → metalist-0.6.2}/app/security/request_boundary.py +0 -0
  73. {metalist-0.6.1 → metalist-0.6.2}/app/security/sensitive_cache.py +0 -0
  74. {metalist-0.6.1 → metalist-0.6.2}/app/security/sensitive_logging.py +0 -0
  75. {metalist-0.6.1 → metalist-0.6.2}/app/security/shell_execution.py +0 -0
  76. {metalist-0.6.1 → metalist-0.6.2}/app/security/validation_errors.py +0 -0
  77. {metalist-0.6.1 → metalist-0.6.2}/app/server_runtime.py +0 -0
  78. {metalist-0.6.1 → metalist-0.6.2}/app/services/__init__.py +0 -0
  79. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/__init__.py +0 -0
  80. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/actions.py +0 -0
  81. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/cloud_privacy.py +0 -0
  82. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/context.py +0 -0
  83. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/evidence_serialization.py +0 -0
  84. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/inference.py +0 -0
  85. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/investigation.py +0 -0
  86. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/model_policy.py +0 -0
  87. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/ollama_inference.py +0 -0
  88. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/openai_cost_tracking.py +0 -0
  89. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/openai_inference.py +0 -0
  90. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/permissions.py +0 -0
  91. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/prompt_settings.py +0 -0
  92. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/prompts/__init__.py +0 -0
  93. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/prompts/final-response.md +0 -0
  94. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/prompts/system.md +0 -0
  95. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/prompts/tool-result.md +0 -0
  96. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/retrieval_settings.py +0 -0
  97. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/runtime.py +0 -0
  98. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/scope.py +0 -0
  99. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/skill_settings.py +0 -0
  100. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/skills/__init__.py +0 -0
  101. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/skills/scoped-investigation.md +0 -0
  102. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/tagging.py +0 -0
  103. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/tagging_run.py +0 -0
  104. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/token_estimation.py +0 -0
  105. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/tools.py +0 -0
  106. {metalist-0.6.1 → metalist-0.6.2}/app/services/agent/trace.py +0 -0
  107. {metalist-0.6.1 → metalist-0.6.2}/app/services/ai_chat.py +0 -0
  108. {metalist-0.6.1 → metalist-0.6.2}/app/services/ai_chat_rendering.py +0 -0
  109. {metalist-0.6.1 → metalist-0.6.2}/app/services/ai_chat_stream.py +0 -0
  110. {metalist-0.6.1 → metalist-0.6.2}/app/services/auth.py +0 -0
  111. {metalist-0.6.1 → metalist-0.6.2}/app/services/auth_cache_state.py +0 -0
  112. {metalist-0.6.1 → metalist-0.6.2}/app/services/auth_service.py +0 -0
  113. {metalist-0.6.1 → metalist-0.6.2}/app/services/backlink_index.py +0 -0
  114. {metalist-0.6.1 → metalist-0.6.2}/app/services/backlinks.py +0 -0
  115. {metalist-0.6.1 → metalist-0.6.2}/app/services/backup_service.py +0 -0
  116. {metalist-0.6.1 → metalist-0.6.2}/app/services/backup_settings_service.py +0 -0
  117. {metalist-0.6.1 → metalist-0.6.2}/app/services/bulk_operation.py +0 -0
  118. {metalist-0.6.1 → metalist-0.6.2}/app/services/client_state_service.py +0 -0
  119. {metalist-0.6.1 → metalist-0.6.2}/app/services/content_cache.py +0 -0
  120. {metalist-0.6.1 → metalist-0.6.2}/app/services/content_formatting.py +0 -0
  121. {metalist-0.6.1 → metalist-0.6.2}/app/services/diagnostics.py +0 -0
  122. {metalist-0.6.1 → metalist-0.6.2}/app/services/embedded_references.py +0 -0
  123. {metalist-0.6.1 → metalist-0.6.2}/app/services/encryption.py +0 -0
  124. {metalist-0.6.1 → metalist-0.6.2}/app/services/exception_capture.py +0 -0
  125. {metalist-0.6.1 → metalist-0.6.2}/app/services/file_registry.py +0 -0
  126. {metalist-0.6.1 → metalist-0.6.2}/app/services/file_storage.py +0 -0
  127. {metalist-0.6.1 → metalist-0.6.2}/app/services/footnote_layout.py +0 -0
  128. {metalist-0.6.1 → metalist-0.6.2}/app/services/footnote_rendering.py +0 -0
  129. {metalist-0.6.1 → metalist-0.6.2}/app/services/hierarchy.py +0 -0
  130. {metalist-0.6.1 → metalist-0.6.2}/app/services/html_export.py +0 -0
  131. {metalist-0.6.1 → metalist-0.6.2}/app/services/html_unformatting.py +0 -0
  132. {metalist-0.6.1 → metalist-0.6.2}/app/services/hydration_state.py +0 -0
  133. {metalist-0.6.1 → metalist-0.6.2}/app/services/image_size_formatting.py +0 -0
  134. {metalist-0.6.1 → metalist-0.6.2}/app/services/inline_image_occurrences.py +0 -0
  135. {metalist-0.6.1 → metalist-0.6.2}/app/services/input_errors.py +0 -0
  136. {metalist-0.6.1 → metalist-0.6.2}/app/services/integrity.py +0 -0
  137. {metalist-0.6.1 → metalist-0.6.2}/app/services/latex_rendering.py +0 -0
  138. {metalist-0.6.1 → metalist-0.6.2}/app/services/link_titles.py +0 -0
  139. {metalist-0.6.1 → metalist-0.6.2}/app/services/login_rate_limit.py +0 -0
  140. {metalist-0.6.1 → metalist-0.6.2}/app/services/maintenance_mode.py +0 -0
  141. {metalist-0.6.1 → metalist-0.6.2}/app/services/managed_ollama_runtime.py +0 -0
  142. {metalist-0.6.1 → metalist-0.6.2}/app/services/markdown_rendering.py +0 -0
  143. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_deletion_jobs.py +0 -0
  144. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_deletion_worker.py +0 -0
  145. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_rename_jobs.py +0 -0
  146. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_rename_worker.py +0 -0
  147. {metalist-0.6.1 → metalist-0.6.2}/app/services/namespace_runtime_guard.py +0 -0
  148. {metalist-0.6.1 → metalist-0.6.2}/app/services/note_fullscreen.py +0 -0
  149. {metalist-0.6.1 → metalist-0.6.2}/app/services/note_image_tags.py +0 -0
  150. {metalist-0.6.1 → metalist-0.6.2}/app/services/note_ordering.py +0 -0
  151. {metalist-0.6.1 → metalist-0.6.2}/app/services/note_store.py +0 -0
  152. {metalist-0.6.1 → metalist-0.6.2}/app/services/ollama_provider.py +0 -0
  153. {metalist-0.6.1 → metalist-0.6.2}/app/services/ontology_rules_store.py +0 -0
  154. {metalist-0.6.1 → metalist-0.6.2}/app/services/openai_credentials.py +0 -0
  155. {metalist-0.6.1 → metalist-0.6.2}/app/services/password_note_fields.py +0 -0
  156. {metalist-0.6.1 → metalist-0.6.2}/app/services/reference_presentation.py +0 -0
  157. {metalist-0.6.1 → metalist-0.6.2}/app/services/reminders.py +0 -0
  158. {metalist-0.6.1 → metalist-0.6.2}/app/services/remote_image_proxy.py +0 -0
  159. {metalist-0.6.1 → metalist-0.6.2}/app/services/request_recovery.py +0 -0
  160. {metalist-0.6.1 → metalist-0.6.2}/app/services/resource_limits.py +0 -0
  161. {metalist-0.6.1 → metalist-0.6.2}/app/services/root_sorting.py +0 -0
  162. {metalist-0.6.1 → metalist-0.6.2}/app/services/runtime_generation.py +0 -0
  163. {metalist-0.6.1 → metalist-0.6.2}/app/services/runtime_hardening.py +0 -0
  164. {metalist-0.6.1 → metalist-0.6.2}/app/services/runtime_lock.py +0 -0
  165. {metalist-0.6.1 → metalist-0.6.2}/app/services/search_history.py +0 -0
  166. {metalist-0.6.1 → metalist-0.6.2}/app/services/search_history_storage.py +0 -0
  167. {metalist-0.6.1 → metalist-0.6.2}/app/services/search_index.py +0 -0
  168. {metalist-0.6.1 → metalist-0.6.2}/app/services/search_query.py +0 -0
  169. {metalist-0.6.1 → metalist-0.6.2}/app/services/search_text.py +0 -0
  170. {metalist-0.6.1 → metalist-0.6.2}/app/services/selected_text_tag.py +0 -0
  171. {metalist-0.6.1 → metalist-0.6.2}/app/services/session_timeout_service.py +0 -0
  172. {metalist-0.6.1 → metalist-0.6.2}/app/services/shell_session_service.py +0 -0
  173. {metalist-0.6.1 → metalist-0.6.2}/app/services/snapshot.py +0 -0
  174. {metalist-0.6.1 → metalist-0.6.2}/app/services/store.py +0 -0
  175. {metalist-0.6.1 → metalist-0.6.2}/app/services/structured_note_renderers.py +0 -0
  176. {metalist-0.6.1 → metalist-0.6.2}/app/services/sync.py +0 -0
  177. {metalist-0.6.1 → metalist-0.6.2}/app/services/sync_state.py +0 -0
  178. {metalist-0.6.1 → metalist-0.6.2}/app/services/tab_state.py +0 -0
  179. {metalist-0.6.1 → metalist-0.6.2}/app/services/tag_case.py +0 -0
  180. {metalist-0.6.1 → metalist-0.6.2}/app/services/tag_ontology.py +0 -0
  181. {metalist-0.6.1 → metalist-0.6.2}/app/services/tag_rename.py +0 -0
  182. {metalist-0.6.1 → metalist-0.6.2}/app/services/tag_suggestions.py +0 -0
  183. {metalist-0.6.1 → metalist-0.6.2}/app/services/tag_term_matching.py +0 -0
  184. {metalist-0.6.1 → metalist-0.6.2}/app/services/test_reset.py +0 -0
  185. {metalist-0.6.1 → metalist-0.6.2}/app/services/tokens.py +0 -0
  186. {metalist-0.6.1 → metalist-0.6.2}/app/services/undo_state.py +0 -0
  187. {metalist-0.6.1 → metalist-0.6.2}/app/services/update_backups.py +0 -0
  188. {metalist-0.6.1 → metalist-0.6.2}/app/services/view_cache.py +0 -0
  189. {metalist-0.6.1 → metalist-0.6.2}/app/services/view_diff.py +0 -0
  190. {metalist-0.6.1 → metalist-0.6.2}/app/services/view_state.py +0 -0
  191. {metalist-0.6.1 → metalist-0.6.2}/app/services/windows_process_control.py +0 -0
  192. {metalist-0.6.1 → metalist-0.6.2}/app/startup_environment.py +0 -0
  193. {metalist-0.6.1 → metalist-0.6.2}/app/startup_js_sanity.py +0 -0
  194. {metalist-0.6.1 → metalist-0.6.2}/app/startup_sanity.py +0 -0
  195. {metalist-0.6.1 → metalist-0.6.2}/app/startup_sanity_config.py +0 -0
  196. {metalist-0.6.1 → metalist-0.6.2}/app/static/config/command_palette_tags.json +0 -0
  197. {metalist-0.6.1 → metalist-0.6.2}/app/static/css/floating-notes.css +0 -0
  198. {metalist-0.6.1 → metalist-0.6.2}/app/static/css/forms.css +0 -0
  199. {metalist-0.6.1 → metalist-0.6.2}/app/static/css/main.css +0 -0
  200. {metalist-0.6.1 → metalist-0.6.2}/app/static/img/favicon.ico +0 -0
  201. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/locked.js +0 -0
  202. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/main.js +0 -0
  203. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/activity-tracker.js +0 -0
  204. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
  205. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  206. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  207. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
  208. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
  209. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
  210. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  211. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  212. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  213. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  214. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
  215. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/api-client.js +0 -0
  216. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/api-failure-classification-service.js +0 -0
  217. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/application-state.js +0 -0
  218. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/async-result.js +0 -0
  219. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/auth.js +0 -0
  220. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/client-state-api.js +0 -0
  221. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/client-state-migration.js +0 -0
  222. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  223. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  224. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  225. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/command-palette-controller.js +0 -0
  226. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
  227. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  228. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  229. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  230. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/command-palette/usage-store.js +0 -0
  231. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/config.js +0 -0
  232. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/connectivity-monitor.js +0 -0
  233. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  234. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  235. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  236. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  237. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  238. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/dom-utils-fixed.js +0 -0
  239. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/dom-utils.js +0 -0
  240. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/editor-commands.js +0 -0
  241. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/editor-selection.js +0 -0
  242. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/editor-toolbar.js +0 -0
  243. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/elapsed-time.js +0 -0
  244. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/error-handler.js +0 -0
  245. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/error-overlay.js +0 -0
  246. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/expected-errors.js +0 -0
  247. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/location-flags.js +0 -0
  248. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/login-namespace-picker.js +0 -0
  249. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/maintenance.js +0 -0
  250. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
  251. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
  252. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  253. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  254. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  255. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  256. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  257. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/base-modal.js +0 -0
  258. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  259. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  260. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  261. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/help-modal.js +0 -0
  262. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  263. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/namespace-modals.js +0 -0
  264. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  265. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  266. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  267. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/ontology-modal.js +0 -0
  268. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/password-modal.js +0 -0
  269. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  270. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/random-password-modal.js +0 -0
  271. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/reminder-modal.js +0 -0
  272. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  273. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  274. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  275. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/modals/version-info-modal.js +0 -0
  276. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  277. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  278. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  279. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  280. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  281. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  282. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  283. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  284. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  285. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  286. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/keyboard-events.js +0 -0
  287. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
  288. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  289. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/mode-context.js +0 -0
  290. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  291. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  292. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  293. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  294. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  295. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  296. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  297. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  298. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  299. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  300. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  301. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  302. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  303. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  304. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  305. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  306. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  307. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  308. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  309. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  310. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  311. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  312. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  313. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  314. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  315. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  316. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  317. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  318. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  319. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  320. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  321. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  322. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  323. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  324. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  325. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  326. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  327. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  328. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  329. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  330. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  331. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  332. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  333. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  334. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  335. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  336. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  337. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  338. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  339. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  340. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  341. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  342. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  343. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  344. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  345. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  346. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  347. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  348. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  349. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  350. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  351. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  352. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  353. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  354. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  355. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  356. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  357. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  358. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  359. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  360. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  361. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  362. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  363. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  364. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  365. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  366. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  367. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  368. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  369. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  370. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/note-html-sanitizer.js +0 -0
  371. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/password-generator.js +0 -0
  372. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/password-operation-response.js +0 -0
  373. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/password-policy.js +0 -0
  374. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/password-strength.js +0 -0
  375. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/reminder-store.js +0 -0
  376. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/reminder-surface-service.js +0 -0
  377. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/selection-markers.js +0 -0
  378. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/session-auth.js +0 -0
  379. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/tag-token.js +0 -0
  380. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/modules/uuid.js +0 -0
  381. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/namespace-deleted.js +0 -0
  382. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/namespace-renamed.js +0 -0
  383. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
  384. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
  385. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  386. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  387. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  388. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  389. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  390. {metalist-0.6.1 → metalist-0.6.2}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  391. {metalist-0.6.1 → metalist-0.6.2}/app/static/note-html-policy.json +0 -0
  392. {metalist-0.6.1 → metalist-0.6.2}/app/static/video/login-startup.mp4 +0 -0
  393. {metalist-0.6.1 → metalist-0.6.2}/app/templates/base.html +0 -0
  394. {metalist-0.6.1 → metalist-0.6.2}/app/templates/index.html +0 -0
  395. {metalist-0.6.1 → metalist-0.6.2}/app/templates/locked.html +0 -0
  396. {metalist-0.6.1 → metalist-0.6.2}/app/templates/maintenance.html +0 -0
  397. {metalist-0.6.1 → metalist-0.6.2}/app/templates/namespace_deleted.html +0 -0
  398. {metalist-0.6.1 → metalist-0.6.2}/app/templates/namespace_renamed.html +0 -0
  399. {metalist-0.6.1 → metalist-0.6.2}/app/templates/notes_list.html +0 -0
  400. {metalist-0.6.1 → metalist-0.6.2}/app/upload_limits.py +0 -0
  401. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/__init__.py +0 -0
  402. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/add_selected_text_tag.py +0 -0
  403. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/alphabetize_root_notes.py +0 -0
  404. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/base.py +0 -0
  405. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/bulk_tag_proposals.py +0 -0
  406. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/collapse.py +0 -0
  407. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/copy_note.py +0 -0
  408. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/create_child.py +0 -0
  409. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/create_note.py +0 -0
  410. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/create_sibling.py +0 -0
  411. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/delete_subtree.py +0 -0
  412. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/delete_tag.py +0 -0
  413. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/expand.py +0 -0
  414. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/indent.py +0 -0
  415. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/lock.py +0 -0
  416. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/move.py +0 -0
  417. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/move_to_top.py +0 -0
  418. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/outdent.py +0 -0
  419. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/paste_child.py +0 -0
  420. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/paste_sibling.py +0 -0
  421. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/prefetch_link_titles.py +0 -0
  422. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/prioritize.py +0 -0
  423. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/redo.py +0 -0
  424. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/rename_tag.py +0 -0
  425. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/reset_updated_at.py +0 -0
  426. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/resize_image.py +0 -0
  427. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/run_shell.py +0 -0
  428. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/search_comment_autofill.py +0 -0
  429. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/search_context_tags.py +0 -0
  430. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/set_collapse_bulk.py +0 -0
  431. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/set_collapse_in_context.py +0 -0
  432. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/split_note.py +0 -0
  433. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/tag_proposals.py +0 -0
  434. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/toggle_reference_mode.py +0 -0
  435. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/toggle_todo_done.py +0 -0
  436. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/undo.py +0 -0
  437. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/unformat_content.py +0 -0
  438. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/update_content.py +0 -0
  439. {metalist-0.6.1 → metalist-0.6.2}/app/usecases/view.py +0 -0
  440. {metalist-0.6.1 → metalist-0.6.2}/app/utils/__init__.py +0 -0
  441. {metalist-0.6.1 → metalist-0.6.2}/app/utils/encryption.py +0 -0
  442. {metalist-0.6.1 → metalist-0.6.2}/app/utils/text_utils.py +0 -0
  443. {metalist-0.6.1 → metalist-0.6.2}/main.py +0 -0
  444. {metalist-0.6.1 → metalist-0.6.2}/metalist.egg-info/dependency_links.txt +0 -0
  445. {metalist-0.6.1 → metalist-0.6.2}/metalist.egg-info/entry_points.txt +0 -0
  446. {metalist-0.6.1 → metalist-0.6.2}/metalist.egg-info/requires.txt +0 -0
  447. {metalist-0.6.1 → metalist-0.6.2}/metalist.egg-info/top_level.txt +0 -0
  448. {metalist-0.6.1 → metalist-0.6.2}/scripts/generate-lan-cert.sh +0 -0
  449. {metalist-0.6.1 → metalist-0.6.2}/setup.cfg +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
7
7
  Project-URL: Issues, https://github.com/evolvingstuff/metalist/issues
8
- Requires-Python: <3.14,>=3.10
8
+ Requires-Python: <3.15,>=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  Requires-Dist: argon2-cffi==25.1.0
11
11
  Requires-Dist: cryptography==50.0.0
@@ -48,6 +48,13 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
48
48
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
49
49
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
50
50
 
51
+ ## Changes in 0.6.2
52
+
53
+ - Namespace startup allows two minutes, with progress every five seconds, instead of failing after 12 seconds on a busy machine. `METALIST_STARTUP_TIMEOUT_SECONDS` can increase the allowance. Failed children are stopped and reaped.
54
+ - Updates preserve the running Python interpreter and validate a disposable installation and namespace startup before stopping live servers. uv then installs the tested package/dependency versions from its cache without network access.
55
+ - Python 3.14 is supported. Command-line legacy imports also work when Python lacks Tk's native GUI component.
56
+ - Release validation now includes the real uv update, backups, and multi-namespace restart on Windows, macOS, and Linux across Python 3.10–3.14.
57
+
51
58
  ## Changes in 0.6.1
52
59
 
53
60
  - Removed the unused performance overlay, including its menu option and background state updates, fixing a fatal redundant-state error during note rearranging. Obsolete overlay preferences and command usage are discarded automatically.
@@ -119,11 +126,11 @@ After the first installation, update and restart MetaList with one cross-platfor
119
126
  ```bash
120
127
  metalist update
121
128
  ```
122
- The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks the installer prerequisites, stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
129
+ The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
123
130
 
124
131
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
125
132
 
126
- Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
133
+ Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
127
134
 
128
135
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
129
136
 
@@ -283,6 +290,10 @@ convert-from-legacy.py --namespace work --input /path/to/legacy-export.json
283
290
 
284
291
  If `--namespace`, `--port`, or `--https-port` are omitted, the import script prompts for them and saves the resulting launch profile inside the target namespace DB. That means a one-time import into `work` can immediately seed later shorthand launches like `metalist work`.
285
292
 
293
+ Namespace startup allows 120 seconds per child, reports progress every five seconds, and stops/reaps a failed child instead of leaving it running after reporting failure. Set `METALIST_STARTUP_TIMEOUT_SECONDS` to a positive number of seconds to allow more time on a heavily loaded machine. A crashed child still fails immediately. This is a startup allowance, not a guarantee that any machine will finish within two minutes.
294
+
295
+ The preflight is a disposable empty namespace; it cannot guarantee startup against every real database or prevent a later disk/process failure. If installation succeeds but real namespace startup fails, the new package remains installed: resolve the reported startup issue and run `metalist` again. No automatic code/database rollback is attempted, and backups remain unchanged.
296
+
286
297
  ### Publishing
287
298
  For the real user-facing install flow:
288
299
  ```bash
@@ -292,15 +303,15 @@ uv tool install metalist
292
303
  metalist
293
304
  ```
294
305
 
295
- This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.13.
306
+ This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.14.
296
307
 
297
308
  Recommended release path:
298
309
  1. In the existing PyPI project `metalist`, configure GitHub Trusted Publishing for `evolvingstuff/metalist` and the workflow file `.github/workflows/publish-pypi.yml`.
299
- 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.13. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
310
+ 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.14. Every matrix job also exercises the real `metalist update` path with uv, backups, interpreter preservation, and two-namespace restart against a local release index. The old-version fixture carries the candidate updater so this validates the mechanism being shipped; it does not retroactively fix older installed updaters. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
300
311
  3. Only after every required check passes, create and push the release tag for that same commit. Any intervening change requires a new validation run before tagging. Branch and pull-request runs validate without publishing.
301
312
  4. The tag workflow repeats validation and publishes the same artifacts tested by its full matrix. Manual publication also requires all checks to pass. Users can then run it with `uvx metalist`, install it persistently with `uv tool install metalist`, or install it with `pip install metalist`.
302
313
 
303
- If `--input` is omitted, a file picker opens (when `tkinter` is available).
314
+ If `--input` is omitted, a file picker opens (when `tkinter` and its native `_tkinter` component are available).
304
315
  Notes tagged with `@implies` are converted into ontology rules and are not imported as notes. Legacy rules that are invalid under the current ontology grammar are reported and skipped while valid rules continue importing.
305
316
 
306
317
  ### Run Tests
@@ -12,6 +12,13 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
12
12
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
13
13
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
14
14
 
15
+ ## Changes in 0.6.2
16
+
17
+ - Namespace startup allows two minutes, with progress every five seconds, instead of failing after 12 seconds on a busy machine. `METALIST_STARTUP_TIMEOUT_SECONDS` can increase the allowance. Failed children are stopped and reaped.
18
+ - Updates preserve the running Python interpreter and validate a disposable installation and namespace startup before stopping live servers. uv then installs the tested package/dependency versions from its cache without network access.
19
+ - Python 3.14 is supported. Command-line legacy imports also work when Python lacks Tk's native GUI component.
20
+ - Release validation now includes the real uv update, backups, and multi-namespace restart on Windows, macOS, and Linux across Python 3.10–3.14.
21
+
15
22
  ## Changes in 0.6.1
16
23
 
17
24
  - Removed the unused performance overlay, including its menu option and background state updates, fixing a fatal redundant-state error during note rearranging. Obsolete overlay preferences and command usage are discarded automatically.
@@ -83,11 +90,11 @@ After the first installation, update and restart MetaList with one cross-platfor
83
90
  ```bash
84
91
  metalist update
85
92
  ```
86
- The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks the installer prerequisites, stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
93
+ The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
87
94
 
88
95
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
89
96
 
90
- Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
97
+ Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
91
98
 
92
99
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
93
100
 
@@ -247,6 +254,10 @@ convert-from-legacy.py --namespace work --input /path/to/legacy-export.json
247
254
 
248
255
  If `--namespace`, `--port`, or `--https-port` are omitted, the import script prompts for them and saves the resulting launch profile inside the target namespace DB. That means a one-time import into `work` can immediately seed later shorthand launches like `metalist work`.
249
256
 
257
+ Namespace startup allows 120 seconds per child, reports progress every five seconds, and stops/reaps a failed child instead of leaving it running after reporting failure. Set `METALIST_STARTUP_TIMEOUT_SECONDS` to a positive number of seconds to allow more time on a heavily loaded machine. A crashed child still fails immediately. This is a startup allowance, not a guarantee that any machine will finish within two minutes.
258
+
259
+ The preflight is a disposable empty namespace; it cannot guarantee startup against every real database or prevent a later disk/process failure. If installation succeeds but real namespace startup fails, the new package remains installed: resolve the reported startup issue and run `metalist` again. No automatic code/database rollback is attempted, and backups remain unchanged.
260
+
250
261
  ### Publishing
251
262
  For the real user-facing install flow:
252
263
  ```bash
@@ -256,15 +267,15 @@ uv tool install metalist
256
267
  metalist
257
268
  ```
258
269
 
259
- This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.13.
270
+ This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.14.
260
271
 
261
272
  Recommended release path:
262
273
  1. In the existing PyPI project `metalist`, configure GitHub Trusted Publishing for `evolvingstuff/metalist` and the workflow file `.github/workflows/publish-pypi.yml`.
263
- 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.13. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
274
+ 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.14. Every matrix job also exercises the real `metalist update` path with uv, backups, interpreter preservation, and two-namespace restart against a local release index. The old-version fixture carries the candidate updater so this validates the mechanism being shipped; it does not retroactively fix older installed updaters. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
264
275
  3. Only after every required check passes, create and push the release tag for that same commit. Any intervening change requires a new validation run before tagging. Branch and pull-request runs validate without publishing.
265
276
  4. The tag workflow repeats validation and publishes the same artifacts tested by its full matrix. Manual publication also requires all checks to pass. Users can then run it with `uvx metalist`, install it persistently with `uv tool install metalist`, or install it with `pip install metalist`.
266
277
 
267
- If `--input` is omitted, a file picker opens (when `tkinter` is available).
278
+ If `--input` is omitted, a file picker opens (when `tkinter` and its native `_tkinter` component are available).
268
279
  Notes tagged with `@implies` are converted into ontology rules and are not imported as notes. Legacy rules that are invalid under the current ontology grammar are reported and skipped while valid rules continue importing.
269
280
 
270
281
  ### Run Tests
@@ -5,6 +5,11 @@ syntax suppressions and is consumed by runtime capture and the startup gate.
5
5
  """
6
6
 
7
7
  CAPTURE_BOUNDARIES = {
8
+ # Release smoke polls only its own disposable HTTP listeners during an actual update.
9
+ 'scripts/smoke_self_update.py:_has_updated_namespace:probe_capture': ('HTTPError',),
10
+ # A child can exit between poll and terminate; hung children must be killed and reaped.
11
+ 'app/services/namespace_switcher.py:_stop_failed_namespace_launch:terminate_capture': ('ProcessLookupError',),
12
+ 'app/services/namespace_switcher.py:_stop_failed_namespace_launch:wait_capture': ('TimeoutExpired',),
8
13
  # Translate explicitly validated domain input/resource rejection.
9
14
  'app/api/routes/auth.py:_delete_namespace_from_body:delete_capture': ('NamespaceInputRejected', 'FileNotFoundError'),
10
15
  # Translate explicitly validated domain input/resource rejection.
@@ -41,7 +41,8 @@ from app.services.input_errors import NamespaceInputRejected
41
41
 
42
42
  _PROJECT_ROOT = Path(__file__).resolve().parents[2]
43
43
  _PLACEHOLDER_NEW_NAMESPACE = "new-namespace"
44
- _LAUNCH_READY_TIMEOUT_SECONDS = 12.0
44
+ _LAUNCH_READY_TIMEOUT_SECONDS = 120.0
45
+ _LAUNCH_PROGRESS_INTERVAL_SECONDS = 5.0
45
46
  _PORT_PROBE_TIMEOUT_SECONDS = 0.75
46
47
  _READY_POLL_INTERVAL_SECONDS = 0.25
47
48
  _PROCESS_WAIT_POLL_INTERVAL_SECONDS = 0.25
@@ -1568,6 +1569,7 @@ def _launch_namespace_process(
1568
1569
  if name in child_environ:
1569
1570
  del child_environ[name]
1570
1571
  child_environ[ORCHESTRATED_CHILD_ENV_NAME] = "1"
1572
+ child_environ["PYTHONUNBUFFERED"] = "1"
1571
1573
  command = _resolve_main_launch_command(environ=child_environ)
1572
1574
  command.extend(
1573
1575
  [
@@ -1664,18 +1666,69 @@ def _read_namespace_launch_log_tail(*, log_path: Path, log_start_offset: int) ->
1664
1666
  return tail
1665
1667
 
1666
1668
 
1669
+ def _stop_failed_namespace_launch(*, process: subprocess.Popen[bytes]) -> None:
1670
+ if process.poll() is not None:
1671
+ return
1672
+ terminate_capture = CapturedExceptionContext(
1673
+ ProcessLookupError,
1674
+ boundary='app/services/namespace_switcher.py:_stop_failed_namespace_launch:terminate_capture',
1675
+ )
1676
+ with terminate_capture:
1677
+ process.terminate()
1678
+ wait_capture = CapturedExceptionContext(
1679
+ subprocess.TimeoutExpired,
1680
+ boundary='app/services/namespace_switcher.py:_stop_failed_namespace_launch:wait_capture',
1681
+ )
1682
+ with wait_capture:
1683
+ process.wait(timeout=_TERMINATE_GRACE_SECONDS)
1684
+ if wait_capture.captured_exception is not None:
1685
+ process.kill()
1686
+ process.wait(timeout=_KILL_GRACE_SECONDS)
1687
+
1688
+
1667
1689
  def _wait_for_namespace_ready(
1668
1690
  *,
1669
1691
  environ: Mapping[str, str],
1670
1692
  namespace: str,
1671
1693
  port: int,
1672
1694
  launched_process: NamespaceLaunchProcess,
1695
+ ) -> None:
1696
+ is_ready = False
1697
+ try:
1698
+ _poll_namespace_readiness(
1699
+ environ=environ, namespace=namespace, port=port,
1700
+ launched_process=launched_process,
1701
+ )
1702
+ is_ready = True
1703
+ finally:
1704
+ if not is_ready:
1705
+ _stop_failed_namespace_launch(process=launched_process.process)
1706
+
1707
+
1708
+ def _poll_namespace_readiness(
1709
+ *,
1710
+ environ: Mapping[str, str],
1711
+ namespace: str,
1712
+ port: int,
1713
+ launched_process: NamespaceLaunchProcess,
1673
1714
  ) -> None:
1674
1715
  main_server_config = resolve_main_server_config(environ=environ)
1675
1716
  connect_host = resolve_backend_connect_host(host=main_server_config.host)
1676
1717
  api_prefix = resolve_api_prefix(environ=environ)
1677
- deadline = time.monotonic() + _LAUNCH_READY_TIMEOUT_SECONDS
1718
+ started_at = time.monotonic()
1719
+ timeout_text = environ.get("METALIST_STARTUP_TIMEOUT_SECONDS")
1720
+ timeout = _LAUNCH_READY_TIMEOUT_SECONDS
1721
+ if timeout_text is not None:
1722
+ if not timeout_text.isascii() or not timeout_text.isdigit() or int(timeout_text) <= 0:
1723
+ raise ValueError("METALIST_STARTUP_TIMEOUT_SECONDS must be a positive integer")
1724
+ timeout = float(timeout_text)
1725
+ deadline = started_at + timeout
1726
+ next_progress = started_at + _LAUNCH_PROGRESS_INTERVAL_SECONDS
1678
1727
  while time.monotonic() < deadline:
1728
+ now = time.monotonic()
1729
+ if now >= next_progress:
1730
+ print(f"Still starting namespace {namespace} ({now - started_at:.0f}s elapsed)...", flush=True)
1731
+ next_progress = now + _LAUNCH_PROGRESS_INTERVAL_SECONDS
1679
1732
  exit_code = launched_process.process.poll()
1680
1733
  if exit_code is not None:
1681
1734
  log_tail = _read_namespace_launch_log_tail(
@@ -17,6 +17,7 @@ from app.server_runtime import resolve_namespaces_directory
17
17
  from app.services.exception_capture import CapturedExceptionContext
18
18
  from app.services.namespace_switcher import stop_all_namespace_processes_for_update
19
19
  from app.services.update_backups import backup_all_namespaces_for_update
20
+ from app.services.update_preflight import prepare_update as _prepare_update
20
21
 
21
22
 
22
23
  _WINDOWS_CREATE_NEW_CONSOLE = 0x00000010
@@ -73,13 +74,20 @@ def schedule_self_update(
73
74
  if uv_executable is None:
74
75
  raise RuntimeError("uv executable was not found on PATH; MetaList was not stopped")
75
76
 
77
+ if platform_name == "win32":
78
+ _resolve_windows_powershell()
79
+ elif not Path("/bin/sh").is_file():
80
+ raise RuntimeError("/bin/sh is required for MetaList self-update; MetaList was not stopped")
81
+ install_command = _prepare_update(
82
+ uv_executable=uv_executable, target_version=target_version, environ=environ,
83
+ )
76
84
  updater_command: list[str]
77
85
  updater_options: dict[str, object]
78
86
  if platform_name == "win32":
79
87
  powershell_executable = _resolve_windows_powershell()
80
88
  updater_command = _build_windows_updater_command(
81
89
  powershell_executable=powershell_executable,
82
- uv_executable=uv_executable,
90
+ install_command=install_command,
83
91
  metalist_executable=metalist_executable,
84
92
  current_pid=current_pid,
85
93
  target_version=target_version,
@@ -95,7 +103,7 @@ def schedule_self_update(
95
103
  raise RuntimeError("/bin/sh is required for MetaList self-update; MetaList was not stopped")
96
104
  updater_command = _build_posix_updater_command(
97
105
  shell_executable=str(shell_path),
98
- uv_executable=uv_executable,
106
+ install_command=install_command,
99
107
  metalist_executable=metalist_executable,
100
108
  current_pid=current_pid,
101
109
  target_version=target_version,
@@ -207,18 +215,17 @@ def _quote_powershell_literal(value: str) -> str:
207
215
  def _build_windows_updater_command(
208
216
  *,
209
217
  powershell_executable: str,
210
- uv_executable: str,
218
+ install_command: list[str],
211
219
  metalist_executable: str,
212
220
  current_pid: int,
213
221
  target_version: str,
214
222
  ) -> list[str]:
215
- quoted_uv = _quote_powershell_literal(uv_executable)
223
+ quoted_install = " ".join(_quote_powershell_literal(part) for part in install_command)
216
224
  quoted_metalist = _quote_powershell_literal(metalist_executable)
217
- quoted_package = _quote_powershell_literal(f"metalist=={target_version}")
218
225
  script = (
219
226
  f"while (Get-Process -Id {current_pid} -ErrorAction SilentlyContinue) "
220
227
  "{ Start-Sleep -Milliseconds 100 }; "
221
- f"& {quoted_uv} tool install --force --reinstall --refresh {quoted_package}; "
228
+ f"& {quoted_install}; "
222
229
  "if ($LASTEXITCODE -ne 0) { "
223
230
  "Write-Host 'MetaList update failed. Review the uv output above.' -ForegroundColor Red; "
224
231
  "Start-Sleep -Seconds 10; exit $LASTEXITCODE }; "
@@ -243,22 +250,12 @@ def _build_windows_updater_command(
243
250
  def _build_posix_updater_command(
244
251
  *,
245
252
  shell_executable: str,
246
- uv_executable: str,
253
+ install_command: list[str],
247
254
  metalist_executable: str,
248
255
  current_pid: int,
249
256
  target_version: str,
250
257
  ) -> list[str]:
251
- uv_command = shlex.join(
252
- [
253
- uv_executable,
254
- "tool",
255
- "install",
256
- "--force",
257
- "--reinstall",
258
- "--refresh",
259
- f"metalist=={target_version}",
260
- ]
261
- )
258
+ uv_command = shlex.join(install_command)
262
259
  metalist_command = shlex.join([metalist_executable])
263
260
  script = (
264
261
  f"while kill -0 {current_pid} 2>/dev/null; do sleep 0.1; done\n"
@@ -0,0 +1,126 @@
1
+ """Validate an update in a disposable installation before stopping live namespaces."""
2
+ from __future__ import annotations
3
+
4
+ from collections.abc import Mapping
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ import socket
9
+ import subprocess
10
+ import sys
11
+ from tempfile import TemporaryDirectory
12
+
13
+ import httpx
14
+
15
+ from app.services.namespace_switcher import NamespaceLaunchProcess
16
+ from app.services.namespace_switcher import _stop_failed_namespace_launch
17
+ from app.services.namespace_switcher import _wait_for_namespace_ready
18
+
19
+
20
+ def _run_checked(command: list[str], *, environ: Mapping[str, str], directory: Path) -> str:
21
+ completed = subprocess.run(
22
+ command, env=dict(environ), cwd=directory, capture_output=True,
23
+ text=True, encoding="utf-8", check=False, timeout=600,
24
+ )
25
+ if completed.returncode != 0:
26
+ raise RuntimeError(
27
+ "Update preflight failed; the current installation and running namespaces "
28
+ f"were not changed.\n{completed.stdout}\n{completed.stderr}"
29
+ )
30
+ return completed.stdout
31
+
32
+
33
+ def _probe_candidate(*, python: str, executable: str, directory: Path,
34
+ environ: Mapping[str, str], target_version: str) -> None:
35
+ probe_environ = {
36
+ key: value for key, value in environ.items()
37
+ if not key.startswith(("METALIST_", "UVICORN_", "SECURITY_", "PYTHON"))
38
+ and key not in {"TEST_MODE", "API_PREFIX", "V1_API_PREFIX", "SQL_TRACE"}
39
+ }
40
+ probe_environ.update(
41
+ METALIST_DATA_DIRECTORY=str(directory / "probe-data"),
42
+ METALIST_ENVIRONMENT="production", METALIST_AUTO_GENERATE_TLS="0",
43
+ PYTHONUNBUFFERED="1", PYTHONUTF8="1", TEST_MODE="0",
44
+ )
45
+ if "METALIST_STARTUP_TIMEOUT_SECONDS" in environ:
46
+ probe_environ["METALIST_STARTUP_TIMEOUT_SECONDS"] = environ["METALIST_STARTUP_TIMEOUT_SECONDS"]
47
+ with socket.socket() as reservation:
48
+ reservation.bind(("127.0.0.1", 0))
49
+ port = reservation.getsockname()[1]
50
+ _run_checked([
51
+ python, "-I", "-c",
52
+ "import sys; from app.server_runtime import save_namespace_launch_profile; "
53
+ "save_namespace_launch_profile(namespace='update-probe', port=int(sys.argv[1]), https_port=None, mcp_port=None)",
54
+ str(port),
55
+ ], environ=probe_environ, directory=directory)
56
+ log_path = directory / "startup.log"
57
+ with log_path.open("wb") as log:
58
+ process = subprocess.Popen(
59
+ [executable, "--namespace", "update-probe", "--port", str(port)],
60
+ cwd=directory, env=probe_environ, stdout=log, stderr=subprocess.STDOUT,
61
+ )
62
+ try:
63
+ _wait_for_namespace_ready(
64
+ environ=probe_environ, namespace="update-probe", port=port,
65
+ launched_process=NamespaceLaunchProcess(process, log_path, 0),
66
+ )
67
+ with httpx.Client(
68
+ base_url=f"http://127.0.0.1:{port}", timeout=15, trust_env=False,
69
+ headers={"X-Metalist-Tab-Id": "00000000-0000-4000-8000-000000000001"},
70
+ ) as client:
71
+ status = client.get("/api2/auth/status")
72
+ status.raise_for_status()
73
+ if status.json()["version"] != target_version:
74
+ raise RuntimeError("Update candidate started with the wrong version")
75
+ for path in ("/", "/static/js/main.js", "/static/css/main.css", "/static/note-html-policy.json"):
76
+ response = client.get(path)
77
+ response.raise_for_status()
78
+ if len(response.content) == 0:
79
+ raise RuntimeError(f"Update candidate has an empty runtime resource: {path}")
80
+ finally:
81
+ _stop_failed_namespace_launch(process=process)
82
+
83
+
84
+ def prepare_update(*, uv_executable: str, target_version: str,
85
+ environ: Mapping[str, str]) -> list[str]:
86
+ # A tool environment is replaced during install: pin its external base interpreter.
87
+ python = str(Path(sys._base_executable).resolve())
88
+ if not Path(python).is_file():
89
+ raise RuntimeError("The current base Python interpreter is missing; MetaList was not stopped")
90
+ print(f"Checking MetaList v{target_version} installation and startup with Python {sys.version.split()[0]}...", flush=True)
91
+ with TemporaryDirectory(prefix="metalist-update-check-") as temporary:
92
+ directory = Path(temporary)
93
+ stage_environ = dict(environ)
94
+ stage_environ.update(UV_TOOL_DIR=str(directory / "tools"), UV_TOOL_BIN_DIR=str(directory / "bin"))
95
+ _run_checked([
96
+ uv_executable, "tool", "install", "--python", python,
97
+ "--refresh", "--compile-bytecode", f"metalist=={target_version}",
98
+ ], environ=stage_environ, directory=directory)
99
+ if sys.platform == "win32":
100
+ scripts = directory / "tools" / "metalist" / "Scripts"
101
+ candidate_python = str(scripts / "python.exe")
102
+ candidate_cli = str(scripts / "metalist.exe")
103
+ else:
104
+ scripts = directory / "tools" / "metalist" / "bin"
105
+ candidate_python = str(scripts / "python")
106
+ candidate_cli = str(scripts / "metalist")
107
+ identity = json.loads(_run_checked([
108
+ candidate_python, "-I", "-c",
109
+ "import sys,json,importlib.metadata; print(json.dumps([list(sys.version_info[:2]),importlib.metadata.version('metalist')]))",
110
+ ], environ=stage_environ, directory=directory))
111
+ if identity != [list(sys.version_info[:2]), target_version]:
112
+ raise RuntimeError("Update preflight changed Python or installed the wrong MetaList version")
113
+ _run_checked([uv_executable, "pip", "check", "--python", candidate_python], environ=stage_environ, directory=directory)
114
+ frozen = _run_checked([uv_executable, "pip", "freeze", "--python", candidate_python], environ=stage_environ, directory=directory)
115
+ _probe_candidate(python=candidate_python, executable=candidate_cli, directory=directory,
116
+ environ=environ, target_version=target_version)
117
+ # Keep the exact tested dependency set. Offline installation reuses the warmed uv cache.
118
+ command = [uv_executable, "tool", "install", "--force", "--offline", "--python", python,
119
+ "--compile-bytecode", f"metalist=={target_version}"]
120
+ for requirement in frozen.splitlines():
121
+ if "==" not in requirement or requirement.startswith("-"):
122
+ raise RuntimeError(f"Update preflight produced an unpinned requirement: {requirement}")
123
+ if requirement.split("==")[0].casefold() != "metalist":
124
+ command.extend(["--with", requirement])
125
+ print("Update installation and startup check passed; packages are cached for offline installation.", flush=True)
126
+ return command
@@ -1,3 +1,3 @@
1
1
  """Single authoritative MetaList application version."""
2
2
 
3
- __version__ = "0.6.1"
3
+ __version__ = "0.6.2"
@@ -26,7 +26,10 @@ tk = None # type: ignore[assignment]
26
26
  filedialog = None # type: ignore[assignment]
27
27
  _TK_IMPORT_ERROR = None
28
28
 
29
- if importlib.util.find_spec("tkinter") is not None:
29
+ if (
30
+ importlib.util.find_spec("tkinter") is not None
31
+ and importlib.util.find_spec("_tkinter") is not None
32
+ ):
30
33
  import tkinter as tk
31
34
  from tkinter import filedialog
32
35
  else:
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
7
7
  Project-URL: Issues, https://github.com/evolvingstuff/metalist/issues
8
- Requires-Python: <3.14,>=3.10
8
+ Requires-Python: <3.15,>=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  Requires-Dist: argon2-cffi==25.1.0
11
11
  Requires-Dist: cryptography==50.0.0
@@ -48,6 +48,13 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
48
48
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
49
49
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
50
50
 
51
+ ## Changes in 0.6.2
52
+
53
+ - Namespace startup allows two minutes, with progress every five seconds, instead of failing after 12 seconds on a busy machine. `METALIST_STARTUP_TIMEOUT_SECONDS` can increase the allowance. Failed children are stopped and reaped.
54
+ - Updates preserve the running Python interpreter and validate a disposable installation and namespace startup before stopping live servers. uv then installs the tested package/dependency versions from its cache without network access.
55
+ - Python 3.14 is supported. Command-line legacy imports also work when Python lacks Tk's native GUI component.
56
+ - Release validation now includes the real uv update, backups, and multi-namespace restart on Windows, macOS, and Linux across Python 3.10–3.14.
57
+
51
58
  ## Changes in 0.6.1
52
59
 
53
60
  - Removed the unused performance overlay, including its menu option and background state updates, fixing a fatal redundant-state error during note rearranging. Obsolete overlay preferences and command usage are discarded automatically.
@@ -119,11 +126,11 @@ After the first installation, update and restart MetaList with one cross-platfor
119
126
  ```bash
120
127
  metalist update
121
128
  ```
122
- The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks the installer prerequisites, stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
129
+ The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
123
130
 
124
131
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
125
132
 
126
- Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It installs the exact version reported by PyPI with a forced cache refresh, launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
133
+ Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update`; direct pip/uv install commands do not run it.
127
134
 
128
135
  For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
129
136
 
@@ -283,6 +290,10 @@ convert-from-legacy.py --namespace work --input /path/to/legacy-export.json
283
290
 
284
291
  If `--namespace`, `--port`, or `--https-port` are omitted, the import script prompts for them and saves the resulting launch profile inside the target namespace DB. That means a one-time import into `work` can immediately seed later shorthand launches like `metalist work`.
285
292
 
293
+ Namespace startup allows 120 seconds per child, reports progress every five seconds, and stops/reaps a failed child instead of leaving it running after reporting failure. Set `METALIST_STARTUP_TIMEOUT_SECONDS` to a positive number of seconds to allow more time on a heavily loaded machine. A crashed child still fails immediately. This is a startup allowance, not a guarantee that any machine will finish within two minutes.
294
+
295
+ The preflight is a disposable empty namespace; it cannot guarantee startup against every real database or prevent a later disk/process failure. If installation succeeds but real namespace startup fails, the new package remains installed: resolve the reported startup issue and run `metalist` again. No automatic code/database rollback is attempted, and backups remain unchanged.
296
+
286
297
  ### Publishing
287
298
  For the real user-facing install flow:
288
299
  ```bash
@@ -292,15 +303,15 @@ uv tool install metalist
292
303
  metalist
293
304
  ```
294
305
 
295
- This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.13.
306
+ This repo now packages itself under the PyPI distribution name `metalist`. Current releases support Python 3.10 through 3.14.
296
307
 
297
308
  Recommended release path:
298
309
  1. In the existing PyPI project `metalist`, configure GitHub Trusted Publishing for `evolvingstuff/metalist` and the workflow file `.github/workflows/publish-pypi.yml`.
299
- 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.13. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
310
+ 2. Push the candidate commit to a branch and wait for the `Publish to PyPI` validation workflow to pass for that exact commit. GitHub-hosted Windows, macOS, and Linux runners install the built wheel and test application startup outside the source checkout on Python 3.10 through 3.14. Every matrix job also exercises the real `metalist update` path with uv, backups, interpreter preservation, and two-namespace restart against a local release index. The old-version fixture carries the candidate updater so this validates the mechanism being shipped; it does not retroactively fix older installed updaters. You do not need those operating systems locally. Archive verification also checks runtime files, including agent Markdown resources, against both the wheel and source distribution.
300
311
  3. Only after every required check passes, create and push the release tag for that same commit. Any intervening change requires a new validation run before tagging. Branch and pull-request runs validate without publishing.
301
312
  4. The tag workflow repeats validation and publishes the same artifacts tested by its full matrix. Manual publication also requires all checks to pass. Users can then run it with `uvx metalist`, install it persistently with `uv tool install metalist`, or install it with `pip install metalist`.
302
313
 
303
- If `--input` is omitted, a file picker opens (when `tkinter` is available).
314
+ If `--input` is omitted, a file picker opens (when `tkinter` and its native `_tkinter` component are available).
304
315
  Notes tagged with `@implies` are converted into ontology rules and are not imported as notes. Legacy rules that are invalid under the current ontology grammar are reported and skipped while valid rules continue importing.
305
316
 
306
317
  ### Run Tests
@@ -159,6 +159,7 @@ app/services/test_reset.py
159
159
  app/services/tokens.py
160
160
  app/services/undo_state.py
161
161
  app/services/update_backups.py
162
+ app/services/update_preflight.py
162
163
  app/services/view_cache.py
163
164
  app/services/view_diff.py
164
165
  app/services/view_state.py
@@ -7,7 +7,7 @@ name = "metalist"
7
7
  dynamic = ["version"]
8
8
  description = "A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync."
9
9
  readme = "README.md"
10
- requires-python = ">=3.10,<3.14"
10
+ requires-python = ">=3.10,<3.15"
11
11
  dependencies = [
12
12
  "argon2-cffi==25.1.0",
13
13
  "cryptography==50.0.0",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes