aida-workbench 0.1.0b5__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 (283) hide show
  1. aida_workbench-0.1.0b5/.git-blame-ignore-revs +14 -0
  2. aida_workbench-0.1.0b5/.github/workflows/ci.yml +127 -0
  3. aida_workbench-0.1.0b5/.github/workflows/publish.yml +51 -0
  4. aida_workbench-0.1.0b5/.gitignore +40 -0
  5. aida_workbench-0.1.0b5/AIEVALUATOR_EPICS_MCP_SETUP.md +312 -0
  6. aida_workbench-0.1.0b5/CHANGELOG.md +452 -0
  7. aida_workbench-0.1.0b5/CONTRIBUTING.md +46 -0
  8. aida_workbench-0.1.0b5/Claude outputs/pyirena_theme_before_after.png +0 -0
  9. aida_workbench-0.1.0b5/LICENSE +21 -0
  10. aida_workbench-0.1.0b5/PKG-INFO +164 -0
  11. aida_workbench-0.1.0b5/PLAN.md +381 -0
  12. aida_workbench-0.1.0b5/PLAN_INSTRUMENT_INTEGRATION.md +516 -0
  13. aida_workbench-0.1.0b5/README.md +123 -0
  14. aida_workbench-0.1.0b5/docs/README.md +41 -0
  15. aida_workbench-0.1.0b5/docs/coding-and-scripting.md +187 -0
  16. aida_workbench-0.1.0b5/docs/context-and-limits.md +130 -0
  17. aida_workbench-0.1.0b5/docs/documents.md +108 -0
  18. aida_workbench-0.1.0b5/docs/gui-overview.md +177 -0
  19. aida_workbench-0.1.0b5/docs/installation.md +139 -0
  20. aida_workbench-0.1.0b5/docs/knowledge-bases.md +174 -0
  21. aida_workbench-0.1.0b5/docs/mcp-servers.md +323 -0
  22. aida_workbench-0.1.0b5/docs/organizing-conversations.md +109 -0
  23. aida_workbench-0.1.0b5/docs/providers-and-secrets.md +212 -0
  24. aida_workbench-0.1.0b5/docs/pyirena.md +165 -0
  25. aida_workbench-0.1.0b5/docs/safety-and-permissions.md +187 -0
  26. aida_workbench-0.1.0b5/docs/workflows.md +286 -0
  27. aida_workbench-0.1.0b5/docs/workspaces.md +133 -0
  28. aida_workbench-0.1.0b5/environment.yml +8 -0
  29. aida_workbench-0.1.0b5/examples/config/config.yaml +35 -0
  30. aida_workbench-0.1.0b5/examples/config/mcp.json +20 -0
  31. aida_workbench-0.1.0b5/examples/config/providers.yaml +60 -0
  32. aida_workbench-0.1.0b5/examples/config/workspaces.yaml +61 -0
  33. aida_workbench-0.1.0b5/planning/COMPLETED.md +546 -0
  34. aida_workbench-0.1.0b5/planning/DESIGN.md +402 -0
  35. aida_workbench-0.1.0b5/planning/context_management.md +312 -0
  36. aida_workbench-0.1.0b5/planning/credentials_and_browser_automation.md +174 -0
  37. aida_workbench-0.1.0b5/planning/document_images.md +270 -0
  38. aida_workbench-0.1.0b5/planning/documents_implementation.md +523 -0
  39. aida_workbench-0.1.0b5/planning/gui_implementation_guide.md +451 -0
  40. aida_workbench-0.1.0b5/planning/improvement_plan_2026-08.md +1150 -0
  41. aida_workbench-0.1.0b5/planning/local_scientific_ai_agent_proposal.md +938 -0
  42. aida_workbench-0.1.0b5/planning/multiuser_plan.md +524 -0
  43. aida_workbench-0.1.0b5/planning/phase01_foundation.md +96 -0
  44. aida_workbench-0.1.0b5/planning/phase02_agent_core.md +154 -0
  45. aida_workbench-0.1.0b5/planning/phase03_mcp.md +183 -0
  46. aida_workbench-0.1.0b5/planning/phase04_persistence_workspaces.md +113 -0
  47. aida_workbench-0.1.0b5/planning/phase05_gui.md +190 -0
  48. aida_workbench-0.1.0b5/planning/phase06_documents.md +438 -0
  49. aida_workbench-0.1.0b5/planning/phase07_mcp_management.md +386 -0
  50. aida_workbench-0.1.0b5/planning/phase08_rag.md +241 -0
  51. aida_workbench-0.1.0b5/planning/phase09_coding_scripting.md +126 -0
  52. aida_workbench-0.1.0b5/planning/phase10_automation_distribution.md +127 -0
  53. aida_workbench-0.1.0b5/planning/phase10_scheduling_design.md +459 -0
  54. aida_workbench-0.1.0b5/planning/phase_future.md +84 -0
  55. aida_workbench-0.1.0b5/pyproject.toml +105 -0
  56. aida_workbench-0.1.0b5/skills/README.md +52 -0
  57. aida_workbench-0.1.0b5/skills/pyirena-usage.md +75 -0
  58. aida_workbench-0.1.0b5/skills/review-checklist.md +93 -0
  59. aida_workbench-0.1.0b5/skills/saxs-basics.md +70 -0
  60. aida_workbench-0.1.0b5/src/aida/__init__.py +7 -0
  61. aida_workbench-0.1.0b5/src/aida/artifacts/__init__.py +30 -0
  62. aida_workbench-0.1.0b5/src/aida/artifacts/base.py +96 -0
  63. aida_workbench-0.1.0b5/src/aida/artifacts/policy.py +83 -0
  64. aida_workbench-0.1.0b5/src/aida/artifacts/store.py +156 -0
  65. aida_workbench-0.1.0b5/src/aida/cli/__init__.py +6 -0
  66. aida_workbench-0.1.0b5/src/aida/cli/__main__.py +123 -0
  67. aida_workbench-0.1.0b5/src/aida/cli/chat.py +388 -0
  68. aida_workbench-0.1.0b5/src/aida/cli/config_cmds.py +139 -0
  69. aida_workbench-0.1.0b5/src/aida/cli/conversations.py +366 -0
  70. aida_workbench-0.1.0b5/src/aida/cli/doctor.py +465 -0
  71. aida_workbench-0.1.0b5/src/aida/cli/documents_cmds.py +170 -0
  72. aida_workbench-0.1.0b5/src/aida/cli/kb_cmds.py +416 -0
  73. aida_workbench-0.1.0b5/src/aida/cli/mcp_cmds.py +579 -0
  74. aida_workbench-0.1.0b5/src/aida/cli/run.py +216 -0
  75. aida_workbench-0.1.0b5/src/aida/cli/schedule_cmds.py +222 -0
  76. aida_workbench-0.1.0b5/src/aida/cli/workflow_cmds.py +232 -0
  77. aida_workbench-0.1.0b5/src/aida/cli/workspace_cmds.py +283 -0
  78. aida_workbench-0.1.0b5/src/aida/coding/__init__.py +9 -0
  79. aida_workbench-0.1.0b5/src/aida/coding/runner.py +312 -0
  80. aida_workbench-0.1.0b5/src/aida/coding/templates.py +65 -0
  81. aida_workbench-0.1.0b5/src/aida/coding/tools.py +181 -0
  82. aida_workbench-0.1.0b5/src/aida/config/__init__.py +4 -0
  83. aida_workbench-0.1.0b5/src/aida/config/logging_setup.py +86 -0
  84. aida_workbench-0.1.0b5/src/aida/config/paths.py +231 -0
  85. aida_workbench-0.1.0b5/src/aida/config/secrets.py +75 -0
  86. aida_workbench-0.1.0b5/src/aida/config/settings.py +1522 -0
  87. aida_workbench-0.1.0b5/src/aida/config/users.py +168 -0
  88. aida_workbench-0.1.0b5/src/aida/core/__init__.py +1 -0
  89. aida_workbench-0.1.0b5/src/aida/core/agent.py +351 -0
  90. aida_workbench-0.1.0b5/src/aida/core/confirmation.py +172 -0
  91. aida_workbench-0.1.0b5/src/aida/core/context.py +683 -0
  92. aida_workbench-0.1.0b5/src/aida/core/cost.py +45 -0
  93. aida_workbench-0.1.0b5/src/aida/core/events.py +297 -0
  94. aida_workbench-0.1.0b5/src/aida/core/headless.py +46 -0
  95. aida_workbench-0.1.0b5/src/aida/core/proc_lock.py +70 -0
  96. aida_workbench-0.1.0b5/src/aida/core/scheduler_runtime.py +367 -0
  97. aida_workbench-0.1.0b5/src/aida/core/scheduling.py +151 -0
  98. aida_workbench-0.1.0b5/src/aida/core/session.py +1358 -0
  99. aida_workbench-0.1.0b5/src/aida/core/tools.py +109 -0
  100. aida_workbench-0.1.0b5/src/aida/core/workflows.py +279 -0
  101. aida_workbench-0.1.0b5/src/aida/documents/__init__.py +7 -0
  102. aida_workbench-0.1.0b5/src/aida/documents/attachments.py +159 -0
  103. aida_workbench-0.1.0b5/src/aida/documents/figure_tools.py +361 -0
  104. aida_workbench-0.1.0b5/src/aida/documents/figures.py +311 -0
  105. aida_workbench-0.1.0b5/src/aida/documents/ocr/__init__.py +22 -0
  106. aida_workbench-0.1.0b5/src/aida/documents/ocr/mistral.py +346 -0
  107. aida_workbench-0.1.0b5/src/aida/documents/readers.py +455 -0
  108. aida_workbench-0.1.0b5/src/aida/documents/tools.py +207 -0
  109. aida_workbench-0.1.0b5/src/aida/documents/writers/__init__.py +2 -0
  110. aida_workbench-0.1.0b5/src/aida/documents/writers/docx_writer.py +68 -0
  111. aida_workbench-0.1.0b5/src/aida/documents/writers/md_obsidian.py +152 -0
  112. aida_workbench-0.1.0b5/src/aida/knowledge/__init__.py +1 -0
  113. aida_workbench-0.1.0b5/src/aida/knowledge/rag/__init__.py +12 -0
  114. aida_workbench-0.1.0b5/src/aida/knowledge/rag/chunking.py +159 -0
  115. aida_workbench-0.1.0b5/src/aida/knowledge/rag/index.py +208 -0
  116. aida_workbench-0.1.0b5/src/aida/knowledge/rag/ingest.py +394 -0
  117. aida_workbench-0.1.0b5/src/aida/knowledge/rag/retrieval.py +141 -0
  118. aida_workbench-0.1.0b5/src/aida/mcp/__init__.py +22 -0
  119. aida_workbench-0.1.0b5/src/aida/mcp/argument_coercion.py +198 -0
  120. aida_workbench-0.1.0b5/src/aida/mcp/config_io.py +88 -0
  121. aida_workbench-0.1.0b5/src/aida/mcp/groups.py +125 -0
  122. aida_workbench-0.1.0b5/src/aida/mcp/manager.py +480 -0
  123. aida_workbench-0.1.0b5/src/aida/mcp/pyirena_setup.py +251 -0
  124. aida_workbench-0.1.0b5/src/aida/mcp/results.py +137 -0
  125. aida_workbench-0.1.0b5/src/aida/mcp/server.py +567 -0
  126. aida_workbench-0.1.0b5/src/aida/persistence/__init__.py +24 -0
  127. aida_workbench-0.1.0b5/src/aida/persistence/cleanup.py +247 -0
  128. aida_workbench-0.1.0b5/src/aida/persistence/db.py +195 -0
  129. aida_workbench-0.1.0b5/src/aida/persistence/recorder.py +343 -0
  130. aida_workbench-0.1.0b5/src/aida/persistence/records.py +230 -0
  131. aida_workbench-0.1.0b5/src/aida/persistence/store.py +622 -0
  132. aida_workbench-0.1.0b5/src/aida/providers/__init__.py +1 -0
  133. aida_workbench-0.1.0b5/src/aida/providers/anthropic_.py +533 -0
  134. aida_workbench-0.1.0b5/src/aida/providers/base.py +242 -0
  135. aida_workbench-0.1.0b5/src/aida/providers/embeddings_base.py +51 -0
  136. aida_workbench-0.1.0b5/src/aida/providers/mock.py +114 -0
  137. aida_workbench-0.1.0b5/src/aida/providers/mock_embeddings.py +60 -0
  138. aida_workbench-0.1.0b5/src/aida/providers/openai_compat.py +451 -0
  139. aida_workbench-0.1.0b5/src/aida/providers/openai_compat_embeddings.py +54 -0
  140. aida_workbench-0.1.0b5/src/aida/providers/profiles.py +169 -0
  141. aida_workbench-0.1.0b5/src/aida/providers/vision.py +121 -0
  142. aida_workbench-0.1.0b5/src/aida/ui/__init__.py +6 -0
  143. aida_workbench-0.1.0b5/src/aida/ui/qt/__init__.py +5 -0
  144. aida_workbench-0.1.0b5/src/aida/ui/qt/_qt.py +144 -0
  145. aida_workbench-0.1.0b5/src/aida/ui/qt/app.py +85 -0
  146. aida_workbench-0.1.0b5/src/aida/ui/qt/artifact_widgets.py +198 -0
  147. aida_workbench-0.1.0b5/src/aida/ui/qt/bridge.py +769 -0
  148. aida_workbench-0.1.0b5/src/aida/ui/qt/chat_panel.py +724 -0
  149. aida_workbench-0.1.0b5/src/aida/ui/qt/code_editor_dialog.py +218 -0
  150. aida_workbench-0.1.0b5/src/aida/ui/qt/collapsible.py +108 -0
  151. aida_workbench-0.1.0b5/src/aida/ui/qt/conversations_sidebar.py +435 -0
  152. aida_workbench-0.1.0b5/src/aida/ui/qt/icon.py +23 -0
  153. aida_workbench-0.1.0b5/src/aida/ui/qt/input_box.py +334 -0
  154. aida_workbench-0.1.0b5/src/aida/ui/qt/knowledge_management_dialog.py +433 -0
  155. aida_workbench-0.1.0b5/src/aida/ui/qt/main_window.py +2053 -0
  156. aida_workbench-0.1.0b5/src/aida/ui/qt/mcp_management_dialog.py +1295 -0
  157. aida_workbench-0.1.0b5/src/aida/ui/qt/notes_panel.py +134 -0
  158. aida_workbench-0.1.0b5/src/aida/ui/qt/onboarding_dialog.py +151 -0
  159. aida_workbench-0.1.0b5/src/aida/ui/qt/profiles_dialog.py +693 -0
  160. aida_workbench-0.1.0b5/src/aida/ui/qt/python_highlighter.py +63 -0
  161. aida_workbench-0.1.0b5/src/aida/ui/qt/quick_tasks_panel.py +229 -0
  162. aida_workbench-0.1.0b5/src/aida/ui/qt/resources/app_icon.png +0 -0
  163. aida_workbench-0.1.0b5/src/aida/ui/qt/retrieval_widget.py +75 -0
  164. aida_workbench-0.1.0b5/src/aida/ui/qt/schedule_management_dialog.py +414 -0
  165. aida_workbench-0.1.0b5/src/aida/ui/qt/scheduler_bridge.py +136 -0
  166. aida_workbench-0.1.0b5/src/aida/ui/qt/selectors.py +543 -0
  167. aida_workbench-0.1.0b5/src/aida/ui/qt/settings_dialog.py +379 -0
  168. aida_workbench-0.1.0b5/src/aida/ui/qt/tool_call_widget.py +173 -0
  169. aida_workbench-0.1.0b5/src/aida/ui/qt/users_dialog.py +253 -0
  170. aida_workbench-0.1.0b5/src/aida/ui/qt/window_state.py +53 -0
  171. aida_workbench-0.1.0b5/src/aida/ui/qt/workflow_management_dialog.py +471 -0
  172. aida_workbench-0.1.0b5/src/aida/ui/qt/workspace_management_dialog.py +495 -0
  173. aida_workbench-0.1.0b5/src/aida/workspace/__init__.py +29 -0
  174. aida_workbench-0.1.0b5/src/aida/workspace/command_allowlist.py +93 -0
  175. aida_workbench-0.1.0b5/src/aida/workspace/files.py +782 -0
  176. aida_workbench-0.1.0b5/src/aida/workspace/safety.py +408 -0
  177. aida_workbench-0.1.0b5/src/aida/workspace/web.py +126 -0
  178. aida_workbench-0.1.0b5/src/aida/workspace/workspaces.py +219 -0
  179. aida_workbench-0.1.0b5/tests/__init__.py +0 -0
  180. aida_workbench-0.1.0b5/tests/conftest.py +28 -0
  181. aida_workbench-0.1.0b5/tests/mock_mcp_server.py +106 -0
  182. aida_workbench-0.1.0b5/tests/test_agent_loop.py +681 -0
  183. aida_workbench-0.1.0b5/tests/test_anthropic_provider_ping.py +75 -0
  184. aida_workbench-0.1.0b5/tests/test_artifacts.py +171 -0
  185. aida_workbench-0.1.0b5/tests/test_attachments.py +375 -0
  186. aida_workbench-0.1.0b5/tests/test_chat_cli.py +1040 -0
  187. aida_workbench-0.1.0b5/tests/test_chunking.py +116 -0
  188. aida_workbench-0.1.0b5/tests/test_coding_runner.py +89 -0
  189. aida_workbench-0.1.0b5/tests/test_coding_templates.py +66 -0
  190. aida_workbench-0.1.0b5/tests/test_coding_tools.py +320 -0
  191. aida_workbench-0.1.0b5/tests/test_command_allowlist.py +59 -0
  192. aida_workbench-0.1.0b5/tests/test_compaction.py +186 -0
  193. aida_workbench-0.1.0b5/tests/test_config_cmds.py +177 -0
  194. aida_workbench-0.1.0b5/tests/test_confirmation.py +152 -0
  195. aida_workbench-0.1.0b5/tests/test_context.py +660 -0
  196. aida_workbench-0.1.0b5/tests/test_contract_layering.py +44 -0
  197. aida_workbench-0.1.0b5/tests/test_conversations_cli.py +268 -0
  198. aida_workbench-0.1.0b5/tests/test_cost.py +45 -0
  199. aida_workbench-0.1.0b5/tests/test_doctor.py +425 -0
  200. aida_workbench-0.1.0b5/tests/test_document_readers.py +424 -0
  201. aida_workbench-0.1.0b5/tests/test_document_tools.py +235 -0
  202. aida_workbench-0.1.0b5/tests/test_document_writers.py +252 -0
  203. aida_workbench-0.1.0b5/tests/test_events.py +60 -0
  204. aida_workbench-0.1.0b5/tests/test_figures.py +306 -0
  205. aida_workbench-0.1.0b5/tests/test_headless.py +115 -0
  206. aida_workbench-0.1.0b5/tests/test_kb_cmds.py +437 -0
  207. aida_workbench-0.1.0b5/tests/test_keystone_image_roundtrip.py +152 -0
  208. aida_workbench-0.1.0b5/tests/test_knowledge_index.py +151 -0
  209. aida_workbench-0.1.0b5/tests/test_knowledge_ingest.py +432 -0
  210. aida_workbench-0.1.0b5/tests/test_knowledge_retrieval.py +127 -0
  211. aida_workbench-0.1.0b5/tests/test_logging_setup.py +55 -0
  212. aida_workbench-0.1.0b5/tests/test_main_cli_dispatch.py +76 -0
  213. aida_workbench-0.1.0b5/tests/test_mcp_argument_coercion.py +160 -0
  214. aida_workbench-0.1.0b5/tests/test_mcp_cmds.py +444 -0
  215. aida_workbench-0.1.0b5/tests/test_mcp_config_io.py +98 -0
  216. aida_workbench-0.1.0b5/tests/test_mcp_groups.py +152 -0
  217. aida_workbench-0.1.0b5/tests/test_mcp_manager.py +673 -0
  218. aida_workbench-0.1.0b5/tests/test_mcp_results.py +236 -0
  219. aida_workbench-0.1.0b5/tests/test_mcp_server.py +492 -0
  220. aida_workbench-0.1.0b5/tests/test_mock_embeddings.py +71 -0
  221. aida_workbench-0.1.0b5/tests/test_ocr.py +469 -0
  222. aida_workbench-0.1.0b5/tests/test_paths.py +103 -0
  223. aida_workbench-0.1.0b5/tests/test_persistence_cleanup.py +156 -0
  224. aida_workbench-0.1.0b5/tests/test_persistence_db.py +198 -0
  225. aida_workbench-0.1.0b5/tests/test_persistence_recorder.py +269 -0
  226. aida_workbench-0.1.0b5/tests/test_persistence_records.py +223 -0
  227. aida_workbench-0.1.0b5/tests/test_persistence_store.py +309 -0
  228. aida_workbench-0.1.0b5/tests/test_phase4_acceptance.py +245 -0
  229. aida_workbench-0.1.0b5/tests/test_phase6_acceptance.py +216 -0
  230. aida_workbench-0.1.0b5/tests/test_proc_lock.py +51 -0
  231. aida_workbench-0.1.0b5/tests/test_profiles.py +177 -0
  232. aida_workbench-0.1.0b5/tests/test_provider_lifecycle.py +174 -0
  233. aida_workbench-0.1.0b5/tests/test_provider_param_fallback.py +338 -0
  234. aida_workbench-0.1.0b5/tests/test_provider_translation.py +921 -0
  235. aida_workbench-0.1.0b5/tests/test_pyirena_setup.py +148 -0
  236. aida_workbench-0.1.0b5/tests/test_regressions_phase6.py +332 -0
  237. aida_workbench-0.1.0b5/tests/test_review_2026_08_findings.py +556 -0
  238. aida_workbench-0.1.0b5/tests/test_run_cli.py +219 -0
  239. aida_workbench-0.1.0b5/tests/test_schedule_cmds.py +128 -0
  240. aida_workbench-0.1.0b5/tests/test_scheduler_runtime.py +465 -0
  241. aida_workbench-0.1.0b5/tests/test_scheduling.py +159 -0
  242. aida_workbench-0.1.0b5/tests/test_secrets.py +65 -0
  243. aida_workbench-0.1.0b5/tests/test_settings.py +941 -0
  244. aida_workbench-0.1.0b5/tests/test_start_session.py +1281 -0
  245. aida_workbench-0.1.0b5/tests/test_users.py +457 -0
  246. aida_workbench-0.1.0b5/tests/test_web_tools.py +153 -0
  247. aida_workbench-0.1.0b5/tests/test_workflow_cmds.py +185 -0
  248. aida_workbench-0.1.0b5/tests/test_workflows.py +338 -0
  249. aida_workbench-0.1.0b5/tests/test_workspace.py +259 -0
  250. aida_workbench-0.1.0b5/tests/test_workspace_cmds.py +478 -0
  251. aida_workbench-0.1.0b5/tests/test_workspace_files.py +514 -0
  252. aida_workbench-0.1.0b5/tests/test_workspace_safety.py +576 -0
  253. aida_workbench-0.1.0b5/tests/ui/__init__.py +0 -0
  254. aida_workbench-0.1.0b5/tests/ui/_qt_test_utils.py +40 -0
  255. aida_workbench-0.1.0b5/tests/ui/conftest.py +148 -0
  256. aida_workbench-0.1.0b5/tests/ui/test_app.py +67 -0
  257. aida_workbench-0.1.0b5/tests/ui/test_artifact_widgets.py +162 -0
  258. aida_workbench-0.1.0b5/tests/ui/test_bridge.py +495 -0
  259. aida_workbench-0.1.0b5/tests/ui/test_bridge_lifecycle.py +323 -0
  260. aida_workbench-0.1.0b5/tests/ui/test_chat_panel.py +679 -0
  261. aida_workbench-0.1.0b5/tests/ui/test_code_editor_dialog.py +218 -0
  262. aida_workbench-0.1.0b5/tests/ui/test_collapsible.py +67 -0
  263. aida_workbench-0.1.0b5/tests/ui/test_conversations_sidebar.py +668 -0
  264. aida_workbench-0.1.0b5/tests/ui/test_icon.py +17 -0
  265. aida_workbench-0.1.0b5/tests/ui/test_input_box.py +339 -0
  266. aida_workbench-0.1.0b5/tests/ui/test_knowledge_management_dialog.py +504 -0
  267. aida_workbench-0.1.0b5/tests/ui/test_main_window.py +3438 -0
  268. aida_workbench-0.1.0b5/tests/ui/test_mcp_management_dialog.py +844 -0
  269. aida_workbench-0.1.0b5/tests/ui/test_notes_panel.py +113 -0
  270. aida_workbench-0.1.0b5/tests/ui/test_onboarding_dialog.py +104 -0
  271. aida_workbench-0.1.0b5/tests/ui/test_profiles_dialog.py +376 -0
  272. aida_workbench-0.1.0b5/tests/ui/test_python_highlighter.py +61 -0
  273. aida_workbench-0.1.0b5/tests/ui/test_qt_contract.py +127 -0
  274. aida_workbench-0.1.0b5/tests/ui/test_quick_tasks_panel.py +197 -0
  275. aida_workbench-0.1.0b5/tests/ui/test_schedule_management_dialog.py +325 -0
  276. aida_workbench-0.1.0b5/tests/ui/test_scheduler_bridge.py +274 -0
  277. aida_workbench-0.1.0b5/tests/ui/test_selectors.py +572 -0
  278. aida_workbench-0.1.0b5/tests/ui/test_settings_dialog.py +381 -0
  279. aida_workbench-0.1.0b5/tests/ui/test_tool_call_widget.py +122 -0
  280. aida_workbench-0.1.0b5/tests/ui/test_users_dialog.py +206 -0
  281. aida_workbench-0.1.0b5/tests/ui/test_window_state.py +47 -0
  282. aida_workbench-0.1.0b5/tests/ui/test_workflow_management_dialog.py +338 -0
  283. aida_workbench-0.1.0b5/tests/ui/test_workspace_management_dialog.py +393 -0
@@ -0,0 +1,14 @@
1
+ # Revisions `git blame` should look through rather than at.
2
+ #
3
+ # Enable it once per clone:
4
+ # git config blame.ignoreRevsFile .git-blame-ignore-revs
5
+ # (GitHub's blame view honours this file automatically.)
6
+ #
7
+ # Only ever add a commit that changed *no behaviour*. A mixed commit cannot
8
+ # be un-mixed later, which is why the formatting pass below was kept
9
+ # deliberately separate from the work around it.
10
+
11
+ # Formatting: ruff format across the tree, 2026-09-05.
12
+ # Verified AST-identical before and after, except 14 files where only
13
+ # docstring indentation changed.
14
+ 70d5d0b90f53ba32333a2db864c77c0387de199b
@@ -0,0 +1,127 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python-version: ["3.11", "3.13"]
16
+ runs-on: ${{ matrix.os }}
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ # PySide6's QtGui module dynamically links these at import time even
26
+ # under QT_QPA_PLATFORM=offscreen (set in tests/ui/conftest.py) — the
27
+ # offscreen platform plugin avoids needing a real display, but the
28
+ # shared libraries themselves still have to be present. A bare
29
+ # ubuntu-latest runner has none of them, so tests/ui's whole
30
+ # collection failed at `import PySide6.QtGui` with
31
+ # "ImportError: libEGL.so.1: cannot open shared object file".
32
+ - name: Install Qt runtime libraries (Linux, headless)
33
+ if: runner.os == 'Linux'
34
+ run: |
35
+ sudo apt-get update
36
+ sudo apt-get install -y \
37
+ libegl1 libgl1 \
38
+ libxkbcommon0 libxkbcommon-x11-0 \
39
+ libxcb-cursor0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 \
40
+ libxcb-randr0 libxcb-render-util0 libxcb-shape0 libxcb-xinerama0 \
41
+ libdbus-1-3
42
+
43
+ - name: Install package (dev, gui, docs, ocr extras)
44
+ # `ocr` is only httpx, which the openai/anthropic SDKs already pull
45
+ # in — installing it explicitly means CI exercises the real
46
+ # optional-import path rather than the stubs alone.
47
+ run: pip install -e ".[dev,gui,docs,ocr]"
48
+
49
+ - name: Ruff lint
50
+ run: ruff check .
51
+
52
+ # Added after a one-off `ruff format` pass over the whole tree
53
+ # (see .git-blame-ignore-revs). Gating it only made sense once the
54
+ # tree was already clean: doing it the other way round turns main red
55
+ # on the very commit that fixes it.
56
+ - name: Ruff format check
57
+ run: ruff format --check .
58
+
59
+ # Two invocations, not one `pytest -v` over the whole tree: every GUI
60
+ # test shares a single process-wide QApplication (Qt disallows more
61
+ # than one) plus a fresh QThread+asyncio loop per test
62
+ # (tests/ui/conftest.py's `loop_thread`), and the non-GUI suite spawns
63
+ # its own real subprocesses (MCP manager/server tests, coding-tool
64
+ # tests). Combined into one pytest process, the two together push
65
+ # cumulative Qt object/thread churn on one long-lived QApplication
66
+ # high enough to occasionally hit a native crash deep in Qt's own
67
+ # event/timer dispatch — a segfault on Linux, an access violation on
68
+ # Windows, at a different call site each time, always somewhere under
69
+ # ChatBridge's background loop or later Qt event delivery, never at a
70
+ # line this project owns. Splitting the run in two roughly halves the
71
+ # cumulative churn either half accumulates and has not reproduced the
72
+ # crash across many repeated local runs (see
73
+ # planning/improvement_plan_2026-08.md's "Known issues" section for
74
+ # the full writeup and the longer-term follow-up options).
75
+ - name: Pytest (non-GUI)
76
+ run: pytest -v --ignore=tests/ui
77
+
78
+ - name: Pytest (GUI)
79
+ run: pytest -v tests/ui
80
+
81
+ # Validates the artifact users actually install, which the test job above
82
+ # does not: it runs against an editable install of the source tree, so a
83
+ # packaging mistake — a subpackage missing from the wheel, a bundled
84
+ # skills file not included, a dependency declared but unresolvable —
85
+ # passes every test and still breaks `pip install aida-workbench`. One
86
+ # cheap job, one OS: packaging errors of this kind are not
87
+ # platform-specific.
88
+ package:
89
+ runs-on: ubuntu-latest
90
+ steps:
91
+ - uses: actions/checkout@v4
92
+
93
+ - name: Set up Python
94
+ uses: actions/setup-python@v5
95
+ with:
96
+ python-version: "3.11"
97
+
98
+ - name: Build the wheel and sdist
99
+ run: |
100
+ pip install build
101
+ python -m build
102
+
103
+ - name: Install the built wheel into a clean environment
104
+ run: |
105
+ python -m venv /tmp/wheel-check
106
+ /tmp/wheel-check/bin/pip install dist/*.whl
107
+
108
+ - name: Verify the installed package imports and its console script runs
109
+ run: |
110
+ /tmp/wheel-check/bin/python -c "import aida; print(aida.__version__ if hasattr(aida, '__version__') else 'ok')"
111
+ /tmp/wheel-check/bin/aida --help > /dev/null
112
+
113
+ - name: Verify the bundled skills travelled inside the wheel
114
+ # `pip install aida-workbench` users have no repo to copy these
115
+ # from — see the hatch build config's note on why they are packaged.
116
+ run: |
117
+ /tmp/wheel-check/bin/python -c "
118
+ from aida.config.paths import bundled_skills_dir
119
+ source = bundled_skills_dir()
120
+ assert source is not None, 'bundled skills are missing from the wheel'
121
+ entries = list(source.iterdir())
122
+ assert entries, f'{source} is present but empty'
123
+ print(f'{len(entries)} bundled skill entr(ies) present')
124
+ "
125
+
126
+ - name: pip check (declared dependencies actually resolve)
127
+ run: /tmp/wheel-check/bin/pip check
@@ -0,0 +1,51 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build distribution
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.13"
18
+
19
+ - name: Install build
20
+ run: python -m pip install --upgrade build
21
+
22
+ - name: Build package
23
+ run: python -m build
24
+
25
+ - name: Upload distributions
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: python-package-distributions
29
+ path: dist/
30
+
31
+ publish:
32
+ name: Publish to PyPI
33
+ needs: build
34
+ runs-on: ubuntu-latest
35
+
36
+ environment:
37
+ name: pypi
38
+ url: https://pypi.org/p/aida-workbench
39
+
40
+ permissions:
41
+ id-token: write
42
+
43
+ steps:
44
+ - name: Download distributions
45
+ uses: actions/download-artifact@v4
46
+ with:
47
+ name: python-package-distributions
48
+ path: dist/
49
+
50
+ - name: Publish to PyPI
51
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,40 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+
11
+ # AIDA on-device state must never live in the repo.
12
+ # NOTE: intentionally NOT a bare `secrets*` glob — that pattern also matches
13
+ # (and silently drops from git / from built wheels) src/aida/config/secrets.py,
14
+ # the module that *implements* the no-secrets-on-disk guarantee. Real secrets
15
+ # never reach YAML/JSON in the first place (see aida.config.secrets +
16
+ # tests/test_secrets.py); these entries only guard against a stray file.
17
+ .aida/
18
+ *.db
19
+ logs/
20
+ secrets.yaml
21
+ secrets.json
22
+ secrets.env
23
+ .env
24
+ .env.*
25
+
26
+ # Editors / OS
27
+ .DS_Store
28
+ .idea/
29
+ .vscode/
30
+ *.swp
31
+
32
+ # Test / coverage
33
+ .pytest_cache/
34
+ .ruff_cache/
35
+ htmlcov/
36
+ .coverage
37
+ .playwright-mcp/*
38
+
39
+ #to delete
40
+ _to_delete/*
@@ -0,0 +1,312 @@
1
+ # Wiring aievaluator-mcp and epics-mcp into Aida — setup + readiness check
2
+
3
+ **Status: 2026-09-03, night-before-testing checklist.** Both repos are far
4
+ further along than the plan from earlier today assumed — this isn't a "here's
5
+ the design" document, it's "here's what's actually built, here's the mcp.json
6
+ to add, and here's the exact list of things that still need doing before PV
7
+ access will work tomorrow."
8
+
9
+ I reviewed both repos' current code (not just docs) — `aievaluator` at
10
+ commit `6cfcc59`, `epics-mcp` at commit `dd3d0c9`. I could not run anything
11
+ against your real conda environments or the instrument from here (this
12
+ session's shell reaches your files but not your actual `aievaluator`/
13
+ `epics-mcp` conda environments or `usaxscontrol`), so the "run tomorrow"
14
+ commands below are the verification I couldn't do for you.
15
+
16
+ ## 1. Bottom line
17
+
18
+ Both packages are **code-complete for a stdio, single-machine, read-mostly
19
+ test tomorrow.** Nothing structural is missing. What's actually left is:
20
+ (a) two setup steps neither README currently spells out that will silently
21
+ break the connection if skipped, (b) filling in your real
22
+ `EPICS_CA_ADDR_LIST`, (c) the mcp.json entries below, and (d) the
23
+ verification commands to run before opening Aida, so a failure shows up as
24
+ a clear CLI error instead of a confusing tool-call failure inside a chat.
25
+
26
+ ## 2. What's actually implemented (I read the code, not just the plan)
27
+
28
+ ### aievaluator (0.1.0)
29
+
30
+ Fully built: `checks/{beam,energy,flux,tunes,fitness}.py` as library
31
+ functions, `epics_io.py` (single CA interface), YAML config
32
+ (`~/.aievaluator/instrument.yaml`, auto-seeded), `cli.py` (9 subcommands),
33
+ `aievaluator-mcp` (7 tools: `check_beam_status`, `check_energy_match`,
34
+ `check_flux`, `check_tunes`, `fitness_report`, `read_pvs`,
35
+ `describe_checks`), `doctor.py`, three skill files, a test suite that runs
36
+ with no IOC. `tools/*.py` and `fitness_report.sh` are kept as deprecation
37
+ shims, so nothing that already depends on them broke.
38
+
39
+ Genuinely open (from the repo's own PLAN.md, not my speculation):
40
+
41
+ - **The PV names and thresholds in `instrument_usaxs.yaml` have never been
42
+ checked against the live instrument.** They were carried over verbatim
43
+ from the old `tools/*.py` scripts while the instrument was offline for
44
+ commissioning. PLAN.md calls this out explicitly as a gate that still
45
+ has to happen "before this package is used for a real fitness report or
46
+ a real 'is the beam OK' answer." **This is what tomorrow's test actually
47
+ validates** — go in expecting to find at least one stale PV name or
48
+ threshold, not expecting everything to just work.
49
+ - BeamlineAdvisor hasn't been switched over to import `aievaluator.checks`
50
+ yet (still has its own duplicate PV logic) — not a blocker for you
51
+ testing aievaluator-mcp from Aida, just still open.
52
+ - `--transport http` prints "not implemented" and exits — irrelevant
53
+ tomorrow, since Aida launches this as a local stdio subprocess.
54
+
55
+ ### epics-mcp (0.1.0.dev0)
56
+
57
+ Also fully built, further than its own README currently admits — **the
58
+ README's top line still says "Status: pre-alpha. No implementation yet,"
59
+ which is now false; everything below exists in `src/epics_mcp/`:**
60
+ `policy.py` (539 lines — the deny/allow/write engine, glob + `re:` regex,
61
+ deny-shadowing checks, confirm tokens), `ca_client.py` (pyepics + a
62
+ `FakeBackend` for testing without EPICS), `catalog.py`, `audit.py`,
63
+ `ratelimit.py`, `server.py` (6 tools: `epics_pv_get`, `epics_pv_info`,
64
+ `epics_pv_watch`, `epics_policy_describe`, `epics_pv_search`, and
65
+ `epics_pv_put` — registered only when the policy allows writes at all),
66
+ `cli.py`, `doctor.py`. Two example policies
67
+ (`policy_usaxs_readonly.yaml`, `policy_usaxs_staff.yaml`) and a PV catalog.
68
+ Tests cover the policy engine, CA client, catalog, audit, rate limiter,
69
+ CLI, and a full stdio session against `FakeBackend`.
70
+
71
+ Genuinely open:
72
+
73
+ - **Never exercised against a live IOC or even a `softIoc`.** The write
74
+ path (confirm tokens, rate limiting, audit) is verified end-to-end
75
+ against `FakeBackend` only. Tomorrow, with real PV access, is the first
76
+ time any of this touches a real Channel Access server.
77
+ - The staff policy's write rules beyond `usxLAX:userCalc*.A` are marked
78
+ `TODO(verify)` in the file itself — PV names taken from a design doc,
79
+ not a live `caget`. **Don't deploy `policy_usaxs_staff.yaml` as-is; start
80
+ read-only.** (Detail below.)
81
+ - `--transport http` has no bearer-token auth yet — irrelevant tomorrow,
82
+ same reason as aievaluator.
83
+ - **Fix the README's status line** — five-minute doc fix, but worth doing
84
+ so nobody re-derives "is this built yet?" from a stale sentence again.
85
+
86
+ ## 3. Two setup steps that will silently break things if skipped
87
+
88
+ Neither of these is a bug — they're just not obvious from either README,
89
+ and both fail *quietly* (a PV that should connect just won't, or a skill
90
+ that should load just won't be there) rather than with a clear error.
91
+
92
+ **A. Aida does not pass your shell's environment through to MCP
93
+ subprocesses.** I checked `src/aida/mcp/server.py`: it builds an explicit
94
+ `env` dict for each server subprocess (scratch `TMPDIR`/`TEMP`/`TMP` plus
95
+ whatever `mcp.json`'s own `env` block says) and hands that to the MCP
96
+ SDK's `StdioServerParameters`, which does **not** inherit your terminal's
97
+ full environment the way a normally-launched `aievaluator-mcp` from a
98
+ terminal would. Concretely: **if `EPICS_CA_ADDR_LIST` isn't set explicitly
99
+ in the server's `env` block in `mcp.json`, the subprocess Aida launches
100
+ won't have it**, even though `aievaluator doctor` run by hand in the same
101
+ terminal works fine. The symptom would be every PV coming back
102
+ `"connected": false` from inside Aida while the CLI tools work standalone
103
+ — confusing to debug blind. The mcp.json below sets this explicitly; you
104
+ need to fill in the real value(s) for your network (marked below).
105
+
106
+ **B. The PV catalog file has to sit next to the policy file you copy, not
107
+ just next to the example.** `epics-mcp`'s policy loader resolves
108
+ `catalog: pv_catalog_usaxs.txt` relative to the *copied* policy file's own
109
+ directory (`policy.py`'s `Policy.load`), not the repo's `examples/`
110
+ directory. The README's copy command only copies the policy file:
111
+
112
+ ```bash
113
+ cp examples/policy_usaxs_readonly.yaml ~/.epics-mcp/policies/usaxs-user.yaml
114
+ ```
115
+
116
+ Without also copying the catalog, `epics_pv_search` silently returns
117
+ nothing (the server logs a warning and starts anyway — it does not
118
+ refuse to start, so this is easy to miss). Copy both:
119
+
120
+ ```bash
121
+ mkdir -p ~/.epics-mcp/policies
122
+ cp examples/policy_usaxs_readonly.yaml ~/.epics-mcp/policies/usaxs-user.yaml
123
+ cp examples/pv_catalog_usaxs.txt ~/.epics-mcp/policies/pv_catalog_usaxs.txt
124
+ # staff policy, if/when you use it:
125
+ cp examples/policy_usaxs_staff.yaml ~/.epics-mcp/policies/usaxs-staff.yaml
126
+ cp examples/pv_catalog_usaxs.txt ~/.epics-mcp/policies/pv_catalog_usaxs.txt # same file, already there
127
+ ```
128
+
129
+ **C. (smaller) Skills have to be copied into `~/.aida/skills/`, not
130
+ referenced from the aievaluator repo path.** Aida resolves a workspace's
131
+ `skills: [...]` names against `~/.aida/skills/<name>.md` (`aida.core.context.
132
+ skill_path`) — it does not read them from wherever aievaluator happens to
133
+ be checked out.
134
+
135
+ ```bash
136
+ mkdir -p ~/.aida/skills
137
+ cp ~/GitHub/aievaluator/skills/aievaluator.md ~/.aida/skills/
138
+ cp ~/GitHub/aievaluator/skills/usaxs-instrument.md ~/.aida/skills/
139
+ ```
140
+
141
+ `epics-mcp` doesn't ship a skill file at all yet (each tool's own docstring
142
+ is reasonably thorough, since FastMCP surfaces those to the model — this
143
+ is a nice-to-have, not a blocker for tomorrow).
144
+
145
+ ## 4. mcp.json entries to add
146
+
147
+ Merge this into your real `~/.aida/mcp.json` (I can't write to that path
148
+ from here — it's outside the folders connected to this session; the
149
+ folders I can reach are the three repo checkouts). Adjust the two
150
+ `command` paths if your actual conda env prefixes differ from what your
151
+ shell showed me (`/opt/miniconda3/envs/aievaluator`,
152
+ `/opt/miniconda3/envs/epics-mcp`), and **fill in the real
153
+ `EPICS_CA_ADDR_LIST`** — I don't have your beamline's actual CA gateway
154
+ address, and a wrong or placeholder value will connect to nothing.
155
+
156
+ ```json
157
+ {
158
+ "mcpServers": {
159
+ "aievaluator-mcp": {
160
+ "command": "/opt/miniconda3/envs/aievaluator/bin/aievaluator-mcp",
161
+ "args": [],
162
+ "env": {
163
+ "EPICS_CA_ADDR_LIST": "FILL_IN_YOUR_CA_GATEWAY",
164
+ "EPICS_CA_AUTO_ADDR_LIST": "NO"
165
+ },
166
+ "groups": ["instrument-status", "instrument-staff"],
167
+ "skills": ["aievaluator", "usaxs-instrument"],
168
+ "confirm_tools": ["fitness_report"]
169
+ },
170
+ "epics-mcp-user": {
171
+ "command": "/opt/miniconda3/envs/epics-mcp/bin/epics-mcp",
172
+ "args": ["--policy", "usaxs-user"],
173
+ "env": {
174
+ "EPICS_CA_ADDR_LIST": "FILL_IN_YOUR_CA_GATEWAY",
175
+ "EPICS_CA_AUTO_ADDR_LIST": "NO"
176
+ },
177
+ "groups": ["instrument-status"],
178
+ "skills": [],
179
+ "disabled_tools": []
180
+ },
181
+ "epics-mcp-staff": {
182
+ "command": "/opt/miniconda3/envs/epics-mcp/bin/epics-mcp",
183
+ "args": ["--policy", "usaxs-staff"],
184
+ "env": {
185
+ "EPICS_CA_ADDR_LIST": "FILL_IN_YOUR_CA_GATEWAY",
186
+ "EPICS_CA_AUTO_ADDR_LIST": "NO"
187
+ },
188
+ "groups": ["instrument-staff"],
189
+ "skills": [],
190
+ "confirm_tools": ["epics_pv_put"]
191
+ }
192
+ }
193
+ }
194
+ ```
195
+
196
+ Notes on the choices above:
197
+
198
+ - **Two `epics-mcp` server entries, not one.** A single `mcp.json` entry
199
+ is one fixed `command`/`args`, and the policy is chosen by
200
+ `--policy NAME` on the command line — there's no way to expose both a
201
+ read-only and a write-capable mode from one entry. `epics-mcp-user`
202
+ (read-only) and `epics-mcp-staff` (write-enabled) are two separate
203
+ subprocesses, two separate groups, so a `usaxs-user` workspace can point
204
+ `mcp_group` at `instrument-status` and structurally never see
205
+ `epics_pv_put`.
206
+ - **`confirm_tools: ["epics_pv_put"]` on the staff server is a second,
207
+ client-side layer on top of the confirm-token protocol
208
+ `epics_pv_put` already has built in** (a non-`confirm: true` write rule,
209
+ like `usxLAX:userCalc*.A`, writes on the first call otherwise). Given
210
+ neither the write path nor the instrument have ever been tested
211
+ together, I'd keep this on even after things are working — it's cheap
212
+ insurance for a tool that changes hardware state.
213
+ - **`confirm_tools: ["fitness_report"]`** on aievaluator matches the
214
+ hand-off table the aievaluator repo's own PLAN.md wrote for AIDA — it's
215
+ the one tool in that server that writes anything (to the Obsidian
216
+ vault).
217
+ - **I put `aievaluator-mcp` in both groups** since its tools are read-only
218
+ regardless of who's asking; only the `epics-mcp-*` split needs to differ
219
+ between the two groups.
220
+ - `EPICS_CA_AUTO_ADDR_LIST: "NO"` is a guess at your usual convention
221
+ (explicit address list, no auto-discovery) — set it to match however
222
+ you normally run `caget` on this network; if you don't know, leave it
223
+ unset and only set `EPICS_CA_ADDR_LIST`.
224
+
225
+ You don't have to fold these into workspaces to test connectivity — `aida
226
+ mcp server test <name>` (step 5 below) works against the raw server entry.
227
+ Workspaces (`usaxs-user` / `usaxs-staff` pointing `mcp_group` at
228
+ `instrument-status` / `instrument-staff`) are worth creating once the
229
+ servers themselves are confirmed working — happy to draft
230
+ `workspaces.yaml` entries for those next, once tomorrow's test tells us
231
+ whether the group split above is actually the shape you want.
232
+
233
+ ## 5. Exact commands to run before opening Aida tomorrow
234
+
235
+ In order — each one gates the next, and each failure tells you exactly
236
+ what's still missing rather than surfacing as a vague tool-call error
237
+ inside a chat session.
238
+
239
+ ```bash
240
+ # 1. Confirm both console scripts actually exist and import cleanly —
241
+ # catches an incomplete `pip install -e` before anything else does.
242
+ conda run -n aievaluator aievaluator --help
243
+ conda run -n epics-mcp epics-mcp --version
244
+
245
+ # 2. aievaluator's own reachability check (config, pyepics, one PV,
246
+ # Tiled, the Obsidian mount) — run this FIRST, it's the fastest way
247
+ # to find a wrong PV name or an unreachable network mount.
248
+ conda run -n aievaluator aievaluator doctor
249
+
250
+ # 3. Policy setup, if not already done (see §3.B above) — then validate
251
+ # the policy file loads and shows the rules you expect, with no live
252
+ # PV access yet.
253
+ conda run -n epics-mcp epics-mcp --policy usaxs-user --check
254
+
255
+ # 4. epics-mcp's own reachability check — same shape as #2, plus
256
+ # catalog + audit-log-writable checks specific to epics-mcp.
257
+ conda run -n epics-mcp epics-mcp doctor --policy usaxs-user
258
+
259
+ # 5. A real PV read from each package's own CLI, bypassing Aida and MCP
260
+ # entirely — the cleanest possible signal that Channel Access itself
261
+ # works from this machine before adding Aida's subprocess-env layer
262
+ # (§3.A) on top.
263
+ conda run -n aievaluator aievaluator check-beam --pretty
264
+ conda run -n epics-mcp epics-mcp --policy usaxs-user --check # rules only
265
+ # then, once EPICS_CA_ADDR_LIST is exported in this shell:
266
+ conda run -n aievaluator python -c "from aievaluator.epics_io import EpicsIO; io = EpicsIO(timeout=5.0); print(io.read('XFD:srCurrent')); io.close()"
267
+
268
+ # 6. Only once 1-5 are all green: add the mcp.json entries from §4 (with
269
+ # the real EPICS_CA_ADDR_LIST filled in), then from Aida:
270
+ aida mcp server test aievaluator-mcp # expect: OK — 7 tool(s)
271
+ aida mcp server test epics-mcp-user # expect: OK — 5 tool(s) (no pv_put, read-only)
272
+ aida mcp server test epics-mcp-staff # expect: OK — 6 tool(s) (pv_put present)
273
+ ```
274
+
275
+ If step 2 or 4 fails on the Tiled or Obsidian checks specifically, that's
276
+ network/mount reachability from wherever you're running this (a laptop vs.
277
+ `usaxscontrol` will differ), not a code problem — worth knowing before you
278
+ read too much into it.
279
+
280
+ ## 6. If PV access itself isn't available tomorrow
281
+
282
+ Both servers work today with the read-only checks disabled and everything
283
+ else exercised: `epics-mcp --backend fake` serves canned values with no
284
+ EPICS installed at all (built for exactly this), and every aievaluator
285
+ test already runs against `FakeEpicsIO`. So even without real PV access
286
+ tomorrow you can still validate: both console scripts run, both `--check`/
287
+ `doctor` commands behave sensibly, `aida mcp server test` lists the right
288
+ tool counts for each of the three entries, and — for `epics-mcp-user`,
289
+ which is the one that most needs to be right before staff ever sees it —
290
+ that `epics_pv_put` really is absent from the tool list Aida sees. That
291
+ last check *is* the read-only boundary working; it doesn't need beam.
292
+
293
+ ## 7. Priority order if you only have time for some of this
294
+
295
+ 1. §3.A and §3.B (env passthrough, catalog copy) — skip these and nothing
296
+ above will work, and the failure will look like an instrument problem.
297
+ 2. §5 steps 1–5, standalone, no Aida involved — isolates "is Channel
298
+ Access working from this machine at all" from "is Aida configured
299
+ right."
300
+ 3. §4's mcp.json, with the real `EPICS_CA_ADDR_LIST`.
301
+ 4. §5 step 6 — `aida mcp server test` for all three entries.
302
+ 5. Only after all of the above are green: try the staff write path
303
+ (`usxLAX:userCalc*.A`, the one verified-safe write rule) — through
304
+ `epics-mcp --policy usaxs-staff` on its own CLI-adjacent doctor first
305
+ if one existed, otherwise directly through `epics_pv_put` in a Aida
306
+ chat, expecting the `confirm_required` round-trip on any rule marked
307
+ `confirm: true`, and no round-trip at all (single call, immediate
308
+ write) for `usxLAX:userCalc*.A`, which has `confirm: false`.
309
+ 6. Everything else in §2 ("genuinely open") is real work but isn't gating
310
+ tomorrow's test — including the live-instrument PV/threshold
311
+ validation, which tomorrow's test *starts* rather than something that
312
+ has to be finished first.