@galaxyproject/orbit 0.0.0 → 0.9.0

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 (451) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/LICENSE +21 -0
  3. package/README.md +760 -5
  4. package/bin/legacy-mcp-config.js +363 -0
  5. package/bin/orbit.js +810 -0
  6. package/bin/pi-extension-path.d.ts +4 -0
  7. package/bin/pi-extension-path.js +44 -0
  8. package/bin/provider-auth.d.ts +22 -0
  9. package/bin/provider-auth.js +77 -0
  10. package/bin/thinking-pref.js +38 -0
  11. package/bin/update-check.d.ts +15 -0
  12. package/bin/update-check.js +137 -0
  13. package/extensions/cli-update/index.ts +32 -0
  14. package/extensions/orbit/activity-hooks.ts +141 -0
  15. package/extensions/orbit/activity.ts +116 -0
  16. package/extensions/orbit/agent-dir.ts +11 -0
  17. package/extensions/orbit/auto-resume.ts +352 -0
  18. package/extensions/orbit/config.ts +3 -0
  19. package/extensions/orbit/confusables.ts +1 -0
  20. package/extensions/orbit/context.ts +957 -0
  21. package/extensions/orbit/dashboard-commands.ts +191 -0
  22. package/extensions/orbit/dashboard-store.ts +473 -0
  23. package/extensions/orbit/dashboard-tools.ts +1185 -0
  24. package/extensions/orbit/empty-completion.ts +99 -0
  25. package/extensions/orbit/evidence-gate.ts +1276 -0
  26. package/extensions/orbit/evidence-override-command.ts +294 -0
  27. package/extensions/orbit/exec-guard/bash-risk.ts +1408 -0
  28. package/extensions/orbit/exec-guard/gate.ts +181 -0
  29. package/extensions/orbit/exec-guard/guardian-config.ts +54 -0
  30. package/extensions/orbit/exec-guard/index.ts +1 -0
  31. package/extensions/orbit/exec-guard/model-tier.ts +36 -0
  32. package/extensions/orbit/exec-guard/path-jail.ts +54 -0
  33. package/extensions/orbit/exec-guard/policy.ts +342 -0
  34. package/extensions/orbit/exec-guard/runtime-state.ts +15 -0
  35. package/extensions/orbit/exec-guard/sensitive-read.ts +525 -0
  36. package/extensions/orbit/exec-guard/types.ts +42 -0
  37. package/extensions/orbit/execution-commands.ts +134 -0
  38. package/extensions/orbit/feedback-command.ts +81 -0
  39. package/extensions/orbit/feedback.ts +96 -0
  40. package/extensions/orbit/galaxy-api.test.ts +122 -0
  41. package/extensions/orbit/galaxy-api.ts +606 -0
  42. package/extensions/orbit/galaxy-artifact-link-guidance.ts +5 -0
  43. package/extensions/orbit/galaxy-destructive-gate.ts +113 -0
  44. package/extensions/orbit/galaxy-enrich.ts +1108 -0
  45. package/extensions/orbit/galaxy-failure.ts +101 -0
  46. package/extensions/orbit/galaxy-fixture.ts +126 -0
  47. package/extensions/orbit/galaxy-history-guard.ts +233 -0
  48. package/extensions/orbit/galaxy-job-block.ts +347 -0
  49. package/extensions/orbit/galaxy-job-ops.ts +288 -0
  50. package/extensions/orbit/galaxy-live-source.ts +929 -0
  51. package/extensions/orbit/galaxy-markdown-adapter.ts +248 -0
  52. package/extensions/orbit/galaxy-op-policy.ts +332 -0
  53. package/extensions/orbit/galaxy-ops-tools.ts +326 -0
  54. package/extensions/orbit/galaxy-output-store.ts +80 -0
  55. package/extensions/orbit/galaxy-output.ts +346 -0
  56. package/extensions/orbit/galaxy-page-binding.ts +222 -0
  57. package/extensions/orbit/galaxy-page-markdown-guidance.ts +15 -0
  58. package/extensions/orbit/galaxy-page-ops.ts +159 -0
  59. package/extensions/orbit/galaxy-page-sync.test.ts +417 -0
  60. package/extensions/orbit/galaxy-page-sync.ts +318 -0
  61. package/extensions/orbit/galaxy-pages-api.ts +203 -0
  62. package/extensions/orbit/galaxy-pages-sync.ts +409 -0
  63. package/extensions/orbit/galaxy-poll-guard.ts +189 -0
  64. package/extensions/orbit/galaxy-poller.ts +706 -0
  65. package/extensions/orbit/galaxy-provenance.ts +623 -0
  66. package/extensions/orbit/galaxy-reconcile.ts +956 -0
  67. package/extensions/orbit/galaxy-recovery.ts +176 -0
  68. package/extensions/orbit/galaxy-repeat-guard.ts +55 -0
  69. package/extensions/orbit/galaxy-submission-capture.ts +707 -0
  70. package/extensions/orbit/galaxy-submission.ts +502 -0
  71. package/extensions/orbit/galaxy-tool-source.ts +78 -0
  72. package/extensions/orbit/galaxy-tool-wrap.ts +234 -0
  73. package/extensions/orbit/galaxy-udt-block.ts +127 -0
  74. package/extensions/orbit/galaxy-upload-tus.ts +334 -0
  75. package/extensions/orbit/galaxy-upload.ts +300 -0
  76. package/extensions/orbit/galaxy-version-capture.ts +65 -0
  77. package/extensions/orbit/git.ts +173 -0
  78. package/extensions/orbit/harness-block-fields.ts +597 -0
  79. package/extensions/orbit/index.ts +593 -0
  80. package/extensions/orbit/init-gate.ts +284 -0
  81. package/extensions/orbit/instructions-command.ts +136 -0
  82. package/extensions/orbit/invocation-failure-hint.ts +57 -0
  83. package/extensions/orbit/iwc-plan-check.ts +94 -0
  84. package/extensions/orbit/lesson-command.ts +303 -0
  85. package/extensions/orbit/lesson-hint.ts +245 -0
  86. package/extensions/orbit/lesson-nudge.ts +106 -0
  87. package/extensions/orbit/lessons/compose.ts +177 -0
  88. package/extensions/orbit/lessons/counters.ts +120 -0
  89. package/extensions/orbit/lessons/enabled.ts +116 -0
  90. package/extensions/orbit/lessons/matcher.ts +346 -0
  91. package/extensions/orbit/lessons/paths.ts +286 -0
  92. package/extensions/orbit/lessons/pi-event-contract.ts +105 -0
  93. package/extensions/orbit/lessons/propose-replay.ts +103 -0
  94. package/extensions/orbit/lessons/propose-tool.ts +222 -0
  95. package/extensions/orbit/lessons/propose.ts +502 -0
  96. package/extensions/orbit/lessons/replay.ts +89 -0
  97. package/extensions/orbit/lessons/reproduction-index.ts +83 -0
  98. package/extensions/orbit/lessons/search-tool.ts +99 -0
  99. package/extensions/orbit/lessons/search.ts +136 -0
  100. package/extensions/orbit/lessons/store.ts +415 -0
  101. package/extensions/orbit/lessons/text.ts +36 -0
  102. package/extensions/orbit/lessons/types.ts +69 -0
  103. package/extensions/orbit/lessons/user-dir.ts +24 -0
  104. package/extensions/orbit/lessons/user-lesson.ts +88 -0
  105. package/extensions/orbit/lessons/wrapper.ts +61 -0
  106. package/extensions/orbit/lessons-command.ts +147 -0
  107. package/extensions/orbit/local-exec.ts +39 -0
  108. package/extensions/orbit/mcp-output.ts +179 -0
  109. package/extensions/orbit/mcp-servers.test.ts +24 -0
  110. package/extensions/orbit/mcp-servers.ts +25 -0
  111. package/extensions/orbit/model-script.ts +351 -0
  112. package/extensions/orbit/notebook-anchors.ts +342 -0
  113. package/extensions/orbit/notebook-writer.ts +863 -0
  114. package/extensions/orbit/observation-allowlists.ts +1109 -0
  115. package/extensions/orbit/observation-replay.ts +148 -0
  116. package/extensions/orbit/observation-triggers.ts +563 -0
  117. package/extensions/orbit/observation-ui.ts +175 -0
  118. package/extensions/orbit/observations-command.ts +421 -0
  119. package/extensions/orbit/observations-config.ts +200 -0
  120. package/extensions/orbit/observations.ts +1381 -0
  121. package/extensions/orbit/profiles.ts +270 -0
  122. package/extensions/orbit/progress-updates.ts +95 -0
  123. package/extensions/orbit/proposal-commands.ts +882 -0
  124. package/extensions/orbit/provenance-fs-file.ts +59 -0
  125. package/extensions/orbit/provenance-fs.ts +32 -0
  126. package/extensions/orbit/provenance-memory-fs.ts +59 -0
  127. package/extensions/orbit/record-store-file.ts +177 -0
  128. package/extensions/orbit/record-store-page.ts +77 -0
  129. package/extensions/orbit/record-store-seam.ts +47 -0
  130. package/extensions/orbit/record-store.ts +149 -0
  131. package/extensions/orbit/registry-carrier.ts +107 -0
  132. package/extensions/orbit/registry-eligibility.ts +95 -0
  133. package/extensions/orbit/registry-evaluation.ts +403 -0
  134. package/extensions/orbit/registry-evaluator.ts +519 -0
  135. package/extensions/orbit/registry-import.ts +91 -0
  136. package/extensions/orbit/registry-lock.ts +221 -0
  137. package/extensions/orbit/registry-memory-fs.ts +42 -0
  138. package/extensions/orbit/registry-page-carrier.ts +103 -0
  139. package/extensions/orbit/registry-proposal.ts +1348 -0
  140. package/extensions/orbit/registry-runtime.ts +234 -0
  141. package/extensions/orbit/registry-schema.ts +735 -0
  142. package/extensions/orbit/registry-submitter.ts +59 -0
  143. package/extensions/orbit/registry-templates.ts +346 -0
  144. package/extensions/orbit/registry.ts +476 -0
  145. package/extensions/orbit/sandbox/index.ts +120 -0
  146. package/extensions/orbit/sandbox/sandbox-bash.ts +93 -0
  147. package/extensions/orbit/sandbox/sandbox-config.ts +87 -0
  148. package/extensions/orbit/sandbox/sandbox-init-message.ts +28 -0
  149. package/extensions/orbit/secret-redaction.ts +247 -0
  150. package/extensions/orbit/session-index/cwd.ts +18 -0
  151. package/extensions/orbit/session-index/db.ts +56 -0
  152. package/extensions/orbit/session-index/indexer.ts +154 -0
  153. package/extensions/orbit/session-index/is-enabled.ts +17 -0
  154. package/extensions/orbit/session-index/parse.ts +254 -0
  155. package/extensions/orbit/session-index/query.ts +209 -0
  156. package/extensions/orbit/session-index/schema.ts +72 -0
  157. package/extensions/orbit/session-index/tools.ts +152 -0
  158. package/extensions/orbit/session-lifecycle.ts +321 -0
  159. package/extensions/orbit/skill-triggers.ts +159 -0
  160. package/extensions/orbit/skills-command.ts +48 -0
  161. package/extensions/orbit/skills-discovery.ts +435 -0
  162. package/extensions/orbit/skills.ts +84 -0
  163. package/extensions/orbit/sra-import-gate.ts +77 -0
  164. package/extensions/orbit/state.ts +265 -0
  165. package/extensions/orbit/submission-replay.ts +147 -0
  166. package/extensions/orbit/sync-command.ts +157 -0
  167. package/extensions/orbit/teams/critic-parser.ts +93 -0
  168. package/extensions/orbit/teams/dispatcher.ts +210 -0
  169. package/extensions/orbit/teams/is-enabled.ts +22 -0
  170. package/extensions/orbit/teams/tool.ts +187 -0
  171. package/extensions/orbit/teams/types.ts +57 -0
  172. package/extensions/orbit/teams/validate.ts +42 -0
  173. package/extensions/orbit/tester-id-command.ts +133 -0
  174. package/extensions/orbit/tools-sync.ts +279 -0
  175. package/extensions/orbit/tools.ts +1300 -0
  176. package/extensions/orbit/types.ts +41 -0
  177. package/extensions/orbit/ui-bridge.ts +55 -0
  178. package/extensions/orbit/ulid.ts +60 -0
  179. package/extensions/orbit/user-instructions.ts +388 -0
  180. package/extensions/orbit/vendor/skills/_catalog.json +68 -0
  181. package/extensions/orbit/vendor/skills/_manifest.json +1106 -0
  182. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/SKILL.md +112 -0
  183. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_provenance.json +218 -0
  184. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_required_tools.json +33 -0
  185. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_verify.json +4 -0
  186. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/add.json +50 -0
  187. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-extract.json +51 -0
  188. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-next-step.json +42 -0
  189. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-validate.json +140 -0
  190. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/list.json +32 -0
  191. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/galaxy-tool-job-failure-reference.md +137 -0
  192. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/open-requirements-ledger.md +173 -0
  193. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-tool-summary.schema.json +175 -0
  194. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
  195. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/SKILL.md +82 -0
  196. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_provenance.json +133 -0
  197. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_required_tools.json +16 -0
  198. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_verify.json +4 -0
  199. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/cli/draft-validate.json +140 -0
  200. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/galaxy-workflow-draft-format.md +135 -0
  201. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
  202. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
  203. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/SKILL.md +84 -0
  204. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_provenance.json +166 -0
  205. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_verify.json +29 -0
  206. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/galaxy-workflow-testability-design.md +136 -0
  207. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  208. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-test-data-conventions.md +308 -0
  209. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-asserts-idioms.md +246 -0
  210. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-workflow-test-architecture.md +151 -0
  211. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
  212. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  213. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/tests-format.schema.json +7328 -0
  214. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/SKILL.md +127 -0
  215. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_provenance.json +198 -0
  216. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_required_tools.json +16 -0
  217. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_verify.json +4 -0
  218. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/cli/convert.json +123 -0
  219. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/galaxy-data-flow-draft-contract.md +129 -0
  220. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  221. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-test-data-conventions.md +308 -0
  222. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/open-requirements-ledger.md +173 -0
  223. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/SKILL.md +73 -0
  224. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_provenance.json +160 -0
  225. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_verify.json +4 -0
  226. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.md +43 -0
  227. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.yml +1250 -0
  228. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-tool-job-failure-reference.md +137 -0
  229. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  230. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  231. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/nextflow-operators-to-galaxy-collection-recipes.md +98 -0
  232. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-asserts-idioms.md +246 -0
  233. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-workflow-test-architecture.md +151 -0
  234. package/extensions/orbit/vendor/skills/discover-shed-tool/SKILL.md +174 -0
  235. package/extensions/orbit/vendor/skills/discover-shed-tool/_provenance.json +130 -0
  236. package/extensions/orbit/vendor/skills/discover-shed-tool/_required_tools.json +18 -0
  237. package/extensions/orbit/vendor/skills/discover-shed-tool/_verify.json +17 -0
  238. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-revisions.json +48 -0
  239. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-search.json +95 -0
  240. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-versions.json +39 -0
  241. package/extensions/orbit/vendor/skills/discover-shed-tool/references/notes/component-tool-shed-search.md +230 -0
  242. package/extensions/orbit/vendor/skills/discover-shed-tool/references/schemas/galaxy-tool-discovery.schema.json +231 -0
  243. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/SKILL.md +93 -0
  244. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_provenance.json +201 -0
  245. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_required_tools.json +28 -0
  246. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_verify.json +17 -0
  247. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/planemo.md +44 -0
  248. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/validate-tests.json +40 -0
  249. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/galaxy-workflow-testability-design.md +136 -0
  250. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  251. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-test-data-conventions.md +308 -0
  252. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
  253. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
  254. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
  255. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/tests-format.schema.json +7328 -0
  256. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/SKILL.md +81 -0
  257. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_provenance.json +93 -0
  258. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_verify.json +17 -0
  259. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
  260. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  261. package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/SKILL.md +81 -0
  262. package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/_assembly.json +23 -0
  263. package/extensions/orbit/vendor/skills/run-workflow-test/SKILL.md +79 -0
  264. package/extensions/orbit/vendor/skills/run-workflow-test/_provenance.json +125 -0
  265. package/extensions/orbit/vendor/skills/run-workflow-test/_required_tools.json +28 -0
  266. package/extensions/orbit/vendor/skills/run-workflow-test/_verify.json +4 -0
  267. package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/planemo.md +44 -0
  268. package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/validate-tests.json +40 -0
  269. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  270. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
  271. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
  272. package/extensions/orbit/vendor/skills/run-workflow-test/references/schemas/tests-format.schema.json +7328 -0
  273. package/extensions/orbit/vendor/skills/skills/LICENSE +21 -0
  274. package/extensions/orbit/vendor/skills/skills/collection-manipulation/README.md +39 -0
  275. package/extensions/orbit/vendor/skills/skills/collection-manipulation/SKILL.md +892 -0
  276. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/api-patterns.md +927 -0
  277. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/apply-rules.md +1482 -0
  278. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/test-patterns.md +996 -0
  279. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/tools.md +609 -0
  280. package/extensions/orbit/vendor/skills/skills/galaxy-data-libraries/SKILL.md +170 -0
  281. package/extensions/orbit/vendor/skills/skills/galaxy-integration/README.md +162 -0
  282. package/extensions/orbit/vendor/skills/skills/galaxy-integration/SKILL.md +99 -0
  283. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/README.md +119 -0
  284. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/tool-checking.md +419 -0
  285. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/workflow-testing.md +617 -0
  286. package/extensions/orbit/vendor/skills/skills/galaxy-integration/galaxy-integration.md +614 -0
  287. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/SKILL.md +144 -0
  288. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/average_col3.ipynb +68 -0
  289. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/extract_sample_metadata.ipynb +190 -0
  290. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/variant_annotation.ipynb +816 -0
  291. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/vcp_variant_map.ipynb +443 -0
  292. package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/README.md +165 -0
  293. package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/galaxy_tool_checker.py +521 -0
  294. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/SKILL.md +128 -0
  295. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/gotchas.md +135 -0
  296. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/history-access.md +132 -0
  297. package/extensions/orbit/vendor/skills/skills/reproduciblify/SKILL.md +146 -0
  298. package/extensions/orbit/vendor/skills/skills/reproduciblify/references/directives.yml +496 -0
  299. package/extensions/orbit/vendor/skills/skills/udt-authoring/SKILL.md +245 -0
  300. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/01-minimal-echo.yml +27 -0
  301. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/02-single-data-in-out.yml +27 -0
  302. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/03-multiple-data-js.yml +28 -0
  303. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/04-select-integer-boolean.yml +41 -0
  304. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/05-resource-requirements.yml +25 -0
  305. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/06-biocontainer-tool.yml +38 -0
  306. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/07-inline-python-script.yml +56 -0
  307. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/08-configfile-script.yml +74 -0
  308. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/common-mistakes.md +76 -0
  309. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/schema-reference.md +155 -0
  310. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/templating.md +196 -0
  311. package/extensions/orbit/vendor/skills/skills/udt-authoring/scripts/validate.py +109 -0
  312. package/extensions/orbit/vendor/skills/skills/workflow-reports/README.md +71 -0
  313. package/extensions/orbit/vendor/skills/skills/workflow-reports/SKILL.md +190 -0
  314. package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/histology-staining.md +145 -0
  315. package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/tissue-microarray-analysis.md +176 -0
  316. package/extensions/orbit/vendor/skills/skills/workflow-reports/references/directives.md +415 -0
  317. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/SKILL.md +98 -0
  318. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_provenance.json +93 -0
  319. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_required_tools.json +28 -0
  320. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_verify.json +17 -0
  321. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/convert.json +123 -0
  322. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/foundry.md +25 -0
  323. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/validate.json +142 -0
  324. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  325. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/SKILL.md +74 -0
  326. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_provenance.json +71 -0
  327. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_required_tools.json +16 -0
  328. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_verify.json +4 -0
  329. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/cli/validate.json +142 -0
  330. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  331. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-testability-design.md +136 -0
  332. package/extensions/orbit/vendor-skills.ts +283 -0
  333. package/extensions/orbit/workspace-state-dir.ts +46 -0
  334. package/extensions/orbit-handoff/index.ts +73 -0
  335. package/extensions/orbit-handoff/orbit-launcher.ts +142 -0
  336. package/extensions/whats-new/index.ts +98 -0
  337. package/lessons/LICENSE +17 -0
  338. package/lessons/README.md +117 -0
  339. package/lessons/SCHEMA.md +187 -0
  340. package/lessons/build-snapshot.mjs +311 -0
  341. package/lessons/data/downloaded-file-is-not-what-its-extension-says.md +61 -0
  342. package/lessons/galaxy-api/403-history-is-a-hard-stop.md +57 -0
  343. package/lessons/galaxy-api/collection-into-single-dataset-input.md +61 -0
  344. package/lessons/galaxy-api/connectedvalue-in-command-line.md +62 -0
  345. package/lessons/galaxy-api/hid-is-not-an-id.md +59 -0
  346. package/lessons/galaxy-api/invoke-workflow-inputs-not-params.md +60 -0
  347. package/lessons/galaxy-api/repeat-param-pipe-keys.md +63 -0
  348. package/lessons/galaxy-api/run-tool-returns-on-submit.md +61 -0
  349. package/lessons/galaxy-tools/reference-index-not-on-server.md +62 -0
  350. package/lessons/log.md +42 -0
  351. package/lessons/reproduction/input-population-mismatch.md +59 -0
  352. package/lessons/reproduction/methods-text-vs-executed-parameters.md +62 -0
  353. package/lessons/snapshot.json +1004 -0
  354. package/lessons/stats/de-contrast-direction-and-sample-labels.md +63 -0
  355. package/lessons/stats/na-coerced-to-zero-in-filters.md +59 -0
  356. package/lessons/validate.mjs +1219 -0
  357. package/package.json +103 -5
  358. package/shared/agent-prompt.d.ts +8 -0
  359. package/shared/agent-prompt.js +15 -0
  360. package/shared/approval-prompt.d.ts +4 -0
  361. package/shared/approval-prompt.js +61 -0
  362. package/shared/brain-env.d.ts +14 -0
  363. package/shared/brain-env.js +108 -0
  364. package/shared/brain-exit.d.ts +20 -0
  365. package/shared/brain-exit.js +149 -0
  366. package/shared/capability-profile.d.ts +16 -0
  367. package/shared/capability-profile.js +75 -0
  368. package/shared/config-source.d.ts +13 -0
  369. package/shared/config-source.js +17 -0
  370. package/shared/confusables.d.ts +3 -0
  371. package/shared/confusables.js +93 -0
  372. package/shared/custom-provider.d.ts +45 -0
  373. package/shared/custom-provider.js +169 -0
  374. package/shared/dashboard-contract.d.ts +123 -0
  375. package/shared/dashboard-contract.js +560 -0
  376. package/shared/dashboard-layout-store.d.ts +44 -0
  377. package/shared/dashboard-layout-store.js +281 -0
  378. package/shared/feedback-contract.d.ts +61 -0
  379. package/shared/feedback-contract.js +146 -0
  380. package/shared/galaxy-artifact-links.d.ts +30 -0
  381. package/shared/galaxy-artifact-links.js +166 -0
  382. package/shared/galaxy-credentials.d.ts +26 -0
  383. package/shared/galaxy-credentials.js +71 -0
  384. package/shared/galaxy-destructive.d.ts +21 -0
  385. package/shared/galaxy-destructive.js +269 -0
  386. package/shared/galaxy-guidance.d.ts +2 -0
  387. package/shared/galaxy-guidance.js +53 -0
  388. package/shared/galaxy-live-contract.d.ts +92 -0
  389. package/shared/galaxy-live-contract.js +180 -0
  390. package/shared/galaxy-page-cells.d.ts +2 -0
  391. package/shared/galaxy-page-cells.js +22 -0
  392. package/shared/galaxy-tool-family.d.ts +5 -0
  393. package/shared/galaxy-tool-family.js +27 -0
  394. package/shared/galaxy-url.d.ts +1 -0
  395. package/shared/galaxy-url.js +48 -0
  396. package/shared/gtn.d.ts +31 -0
  397. package/shared/gtn.js +253 -0
  398. package/shared/handled-prompt.d.ts +3 -0
  399. package/shared/handled-prompt.js +26 -0
  400. package/shared/known-provider.d.ts +11 -0
  401. package/shared/known-provider.js +89 -0
  402. package/shared/lesson-hint-marker.d.ts +7 -0
  403. package/shared/lesson-hint-marker.js +32 -0
  404. package/shared/lesson-rules.d.ts +150 -0
  405. package/shared/lesson-rules.js +203 -0
  406. package/shared/malformed-object-ids.d.ts +1 -0
  407. package/shared/malformed-object-ids.js +37 -0
  408. package/shared/markdown-sections.d.ts +10 -0
  409. package/shared/markdown-sections.js +118 -0
  410. package/shared/notebook-fences.d.ts +12 -0
  411. package/shared/notebook-fences.js +53 -0
  412. package/shared/observation-contract.d.ts +91 -0
  413. package/shared/observation-contract.js +544 -0
  414. package/shared/orbit-config.d.ts +226 -0
  415. package/shared/orbit-config.js +189 -0
  416. package/shared/orbit-env.d.ts +13 -0
  417. package/shared/orbit-env.js +124 -0
  418. package/shared/orbit-shell-contract.d.ts +74 -0
  419. package/shared/orbit-shell-contract.js +30 -0
  420. package/shared/page-content-hash.d.ts +1 -0
  421. package/shared/page-content-hash.js +13 -0
  422. package/shared/pi-default-model.d.ts +7 -0
  423. package/shared/pi-default-model.js +41 -0
  424. package/shared/prompt-blocks.d.ts +87 -0
  425. package/shared/prompt-blocks.js +898 -0
  426. package/shared/provider-auth-caps.d.ts +22 -0
  427. package/shared/provider-auth-caps.js +57 -0
  428. package/shared/random.d.ts +2 -0
  429. package/shared/random.js +15 -0
  430. package/shared/record-excerpt.d.ts +4 -0
  431. package/shared/record-excerpt.js +16 -0
  432. package/shared/redirect-guard.d.ts +36 -0
  433. package/shared/redirect-guard.js +235 -0
  434. package/shared/skills-pin.d.ts +8 -0
  435. package/shared/skills-pin.js +9 -0
  436. package/shared/skills-router.d.ts +17 -0
  437. package/shared/skills-router.js +63 -0
  438. package/shared/sra-import.d.ts +34 -0
  439. package/shared/sra-import.js +206 -0
  440. package/shared/state-dir.d.ts +21 -0
  441. package/shared/state-dir.js +240 -0
  442. package/shared/team-dispatch-contract.d.ts +28 -0
  443. package/shared/team-dispatch-contract.js +1 -0
  444. package/shared/truncate-middle.d.ts +11 -0
  445. package/shared/truncate-middle.js +68 -0
  446. package/shared/version-compare.d.ts +10 -0
  447. package/shared/version-compare.js +74 -0
  448. package/shared/whats-new.d.ts +31 -0
  449. package/shared/whats-new.js +83 -0
  450. package/shared/wsl.d.ts +10 -0
  451. package/shared/wsl.js +24 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Orbit <-> Galaxy-flavored-markdown content adapter. notebook.md is canonical.
3
+ *
4
+ * Push replaces each typed notebook fence Orbit keeps in the notebook body --
5
+ * `loom-invocation`, `loom-job`, and `loom-session` -- with a hidden carrier
6
+ * holding the literal block, base64-encoded. Galaxy has no renderer for these
7
+ * fence kinds, so a raw one shows up on the page as a "cell type is not
8
+ * available" error. The carrier is a CommonMark link-reference definition
9
+ * (`[loom-<kind>:v1]: #loom "<base64>"`): it renders to nothing and is preserved
10
+ * byte-for-byte on store, so pull restores the original fences exactly.
11
+ * (HTML comments do NOT work here -- Galaxy's page renderer escapes them to
12
+ * visible text rather than hiding them, verified live against 26.1.rc1. A
13
+ * reference definition is pure markdown, so it stays invisible.) base64 keeps
14
+ * the payload free of quotes and newlines, so the carrier is always one
15
+ * well-formed line. `loom-galaxy-page` binding blocks never reach this adapter;
16
+ * the sync helper strips them before push.
17
+ *
18
+ * Invocation and job blocks also get a visible ` ```galaxy ` directive
19
+ * (`invocation_outputs` / `job_parameters`) alongside the carrier when their id
20
+ * validates against the connected server; session blocks are a local ledger
21
+ * and get the carrier only. Pull strips the directives Orbit emitted (Orbit owns
22
+ * the projection under the loom-canonical model and regenerates them each
23
+ * push). A Orbit directive always sits immediately above a carrier with no blank
24
+ * line between, so pull strips only ```galaxy blocks in that position -- a
25
+ * ```galaxy fence a human wrote (or a co-author added on the Galaxy side)
26
+ * survives the round trip.
27
+ */
28
+
29
+ import { galaxyGet } from "./galaxy-api";
30
+ import {
31
+ NOTEBOOK_FENCE_READ_PREFIXES,
32
+ NOTEBOOK_FENCE_WRITE_PREFIX,
33
+ isNotebookFenceOpen,
34
+ } from "../../shared/notebook-fences.js";
35
+
36
+ const FENCE_CLOSE = "```";
37
+ const GALAXY_FENCE_OPEN = "```galaxy";
38
+
39
+ /** Notebook fence kinds that are carried through a Galaxy page push. */
40
+ const CARRIED_KINDS = ["invocation", "job", "session"] as const;
41
+ type CarriedKind = (typeof CARRIED_KINDS)[number];
42
+
43
+ // Anchored to a whole line (`m` flag): the carrier is always its own line, so
44
+ // this never decodes carrier-like syntax that appears inline in prose (e.g. a
45
+ // notebook documenting Orbit's own format). The `g` flag replaces every carrier.
46
+ // Tolerate trailing horizontal whitespace -- a storage round trip can append a
47
+ // space, and an unmatched carrier silently loses the block on pull.
48
+ // The carrier's label and anchor carry the product prefix too, so a page pushed
49
+ // by a newer (or older) client still decodes; the payload is the block verbatim,
50
+ // fence line included, so pull restores whatever prefix was pushed.
51
+ const CARRIER_PREFIX_ALT = NOTEBOOK_FENCE_READ_PREFIXES.join("|");
52
+ const CARRIER_KIND_ALT = CARRIED_KINDS.join("|");
53
+ const CARRIER_BODY = `\\[(?:${CARRIER_PREFIX_ALT})-(?:${CARRIER_KIND_ALT}):v1\\]: #(?:${CARRIER_PREFIX_ALT}) "([A-Za-z0-9+/=]+)"[ \\t]*`;
54
+ const CARRIER_RE = new RegExp(`^${CARRIER_BODY}$`, "gm");
55
+
56
+ /** base64 a typed block into a (render-invisible) link-reference carrier. */
57
+ function encodeCarrier(kind: CarriedKind, block: string): string {
58
+ const p = NOTEBOOK_FENCE_WRITE_PREFIX;
59
+ return `[${p}-${kind}:v1]: #${p} "${Buffer.from(block, "utf8").toString("base64")}"`;
60
+ }
61
+
62
+ function carriedKindOf(line: string): CarriedKind | null {
63
+ for (const kind of CARRIED_KINDS) {
64
+ if (isNotebookFenceOpen(line, kind)) return kind;
65
+ }
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * Push (pure, no network): typed notebook fences -> hidden base64 carriers,
71
+ * narrative untouched. The sync helper pushes via orbitToGalaxyMarkdownRich
72
+ * (which also emits validated directives); this plain form is kept for
73
+ * non-network callers and the round-trip tests.
74
+ */
75
+ export function orbitToGalaxyMarkdown(body: string): string {
76
+ const lines = body.split("\n");
77
+ const out: string[] = [];
78
+ let i = 0;
79
+ while (i < lines.length) {
80
+ const kind = carriedKindOf(lines[i]);
81
+ if (kind) {
82
+ let end = i + 1;
83
+ while (end < lines.length && lines[end].trim() !== FENCE_CLOSE) end++;
84
+ const block = lines.slice(i, end + 1).join("\n");
85
+ out.push(encodeCarrier(kind, block));
86
+ i = end + 1;
87
+ } else {
88
+ out.push(lines[i]);
89
+ i++;
90
+ }
91
+ }
92
+ return out.join("\n");
93
+ }
94
+
95
+ /** Pull: strip the ```galaxy directives Orbit emitted, then carriers -> original
96
+ * typed fences. Stripping runs first, while carriers are still single lines,
97
+ * so the "directive sits directly above a carrier" check is exact. */
98
+ export function galaxyMarkdownToOrbit(body: string): string {
99
+ const withoutOrbitDirectives = stripOrbitGalaxyDirectiveBlocks(body);
100
+ return withoutOrbitDirectives.replace(CARRIER_RE, (_m, b64: string) =>
101
+ Buffer.from(b64, "base64").toString("utf8"),
102
+ );
103
+ }
104
+
105
+ // Single-line carrier matcher. CARRIER_RE is global/multiline (stateful via
106
+ // lastIndex), so it's unsafe for a one-off .test(); this is the per-line form.
107
+ // Same trailing-whitespace tolerance as CARRIER_RE so the strip heuristic and
108
+ // the decoder agree on what counts as a carrier line.
109
+ const CARRIER_LINE_RE = new RegExp(`^${CARRIER_BODY}$`);
110
+
111
+ /**
112
+ * Remove only the ```galaxy directive blocks Orbit itself emitted.
113
+ * orbitToGalaxyMarkdownRich always writes the directive immediately above the
114
+ * block's carrier with no blank line between, so a ```galaxy block is Orbit's
115
+ * iff the line right after its closing fence is a carrier. Every other
116
+ * ```galaxy block was authored by a human and is preserved verbatim -- stripping
117
+ * those unconditionally was silent data loss on pull.
118
+ */
119
+ function stripOrbitGalaxyDirectiveBlocks(body: string): string {
120
+ const lines = body.split("\n");
121
+ const out: string[] = [];
122
+ let i = 0;
123
+ while (i < lines.length) {
124
+ if (lines[i].trim() === GALAXY_FENCE_OPEN) {
125
+ let end = i + 1;
126
+ while (end < lines.length && lines[end].trim() !== FENCE_CLOSE) end++;
127
+ // `end` is the closing fence (or EOF). Drop the block only when Orbit's
128
+ // carrier immediately follows it; otherwise fall through and keep it.
129
+ if (end + 1 < lines.length && CARRIER_LINE_RE.test(lines[end + 1])) {
130
+ i = end + 1;
131
+ continue;
132
+ }
133
+ }
134
+ out.push(lines[i]);
135
+ i++;
136
+ }
137
+ return out.join("\n");
138
+ }
139
+
140
+ /** Decides whether a Galaxy id is renderable on the connected server. */
141
+ export interface IdValidator {
142
+ isValid(id: string): Promise<boolean>;
143
+ }
144
+
145
+ export type InvocationValidator = IdValidator;
146
+ export type JobValidator = IdValidator;
147
+
148
+ /** One validator per directive-bearing block kind. */
149
+ export interface DirectiveValidators {
150
+ invocation: InvocationValidator;
151
+ job: JobValidator;
152
+ }
153
+
154
+ /**
155
+ * Real validators: a GET that resolves AND echoes back the same id means the id
156
+ * decodes and exists on the connected server (galaxyGet reads GALAXY_URL, not a
157
+ * block's own galaxy_server_url -- so an id from a different server validates as
158
+ * false and its directive is safely omitted, correct under the single-server
159
+ * push model).
160
+ *
161
+ * Two guards stop a malformed id from smuggling a directive onto the page:
162
+ * encoded ids are hex, so anything else is rejected before any network call (a
163
+ * value like "../histories" would otherwise dot-segment-normalize to a real
164
+ * endpoint, return 200, and pass); and the response id must equal the requested
165
+ * id, so a 200 for some *other* resource doesn't count. Both matter because
166
+ * pulled page content is untrusted -- a hostile carrier must not 400 the next
167
+ * push.
168
+ */
169
+ const ENCODED_ID_RE = /^[0-9a-fA-F]+$/;
170
+
171
+ function echoingIdValidator(collection: string): IdValidator {
172
+ return {
173
+ async isValid(id: string): Promise<boolean> {
174
+ if (!ENCODED_ID_RE.test(id)) return false;
175
+ try {
176
+ const res = await galaxyGet<{ id?: string }>(`/${collection}/${encodeURIComponent(id)}`);
177
+ return res?.id === id;
178
+ } catch {
179
+ return false;
180
+ }
181
+ },
182
+ };
183
+ }
184
+
185
+ export const galaxyInvocationValidator: InvocationValidator = echoingIdValidator("invocations");
186
+ export const galaxyJobValidator: JobValidator = echoingIdValidator("jobs");
187
+
188
+ export const galaxyDirectiveValidators: DirectiveValidators = {
189
+ invocation: galaxyInvocationValidator,
190
+ job: galaxyJobValidator,
191
+ };
192
+
193
+ const DIRECTIVES: Record<
194
+ keyof DirectiveValidators,
195
+ { idRe: RegExp; render: (id: string) => string }
196
+ > = {
197
+ invocation: {
198
+ idRe: /^invocation_id:\s*(.+)$/,
199
+ render: (id) => `invocation_outputs(invocation_id=${id})`,
200
+ },
201
+ job: {
202
+ idRe: /^job_id:\s*(.+)$/,
203
+ render: (id) => `job_parameters(job_id=${id})`,
204
+ },
205
+ };
206
+
207
+ /**
208
+ * Push with rich rendering: each typed block becomes a hidden carrier AND, for
209
+ * invocation and job blocks whose id validates, a visible directive. The
210
+ * directive is gated because Galaxy 400s the whole page on an undecodable id.
211
+ */
212
+ export async function orbitToGalaxyMarkdownRich(
213
+ body: string,
214
+ validators: DirectiveValidators,
215
+ ): Promise<string> {
216
+ const lines = body.split("\n");
217
+ const out: string[] = [];
218
+ let i = 0;
219
+ while (i < lines.length) {
220
+ const kind = carriedKindOf(lines[i]);
221
+ if (kind) {
222
+ const directive = kind === "session" ? null : DIRECTIVES[kind];
223
+ let end = i + 1;
224
+ let id: string | null = null;
225
+ while (end < lines.length && lines[end].trim() !== FENCE_CLOSE) {
226
+ const m = directive ? lines[end].match(directive.idRe) : null;
227
+ if (m) id = m[1].trim();
228
+ end++;
229
+ }
230
+ const block = lines.slice(i, end + 1).join("\n");
231
+ const carrier = encodeCarrier(kind, block);
232
+ // Emit the directive immediately before the carrier with NO extra blank
233
+ // line, so stripping the 3 fence lines on pull restores the carrier in
234
+ // the block's exact original position -- keeping the round trip identical.
235
+ if (directive && kind !== "session" && id && (await validators[kind].isValid(id))) {
236
+ out.push(GALAXY_FENCE_OPEN);
237
+ out.push(directive.render(id));
238
+ out.push(FENCE_CLOSE);
239
+ }
240
+ out.push(carrier);
241
+ i = end + 1;
242
+ } else {
243
+ out.push(lines[i]);
244
+ i++;
245
+ }
246
+ }
247
+ return out.join("\n");
248
+ }
@@ -0,0 +1,332 @@
1
+ /**
2
+ * What the brain layers on a galaxy-ops operation it does not own: policy, never behaviour.
3
+ *
4
+ * An operation does what Galaxy does; a policy decides whether this call should go out at all
5
+ * (`check`), what it waits behind or rewrites on the way (`around`), and what the model is told
6
+ * when Galaxy refuses it (`refused`). Keeping the two apart is what lets a bridging op be deleted
7
+ * when galaxy-ops ships the same operation without the brain losing what it adds.
8
+ *
9
+ * Policies see the tool's arguments as the model sent them: snake_case, after pi's validation.
10
+ */
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { malformedObjectIds } from "../../shared/malformed-object-ids.js";
13
+ import { sectionsHeaded } from "../../shared/markdown-sections.js";
14
+ import { pageContentHash } from "../../shared/page-content-hash.js";
15
+ import { ELISION_MARKER } from "../../shared/record-excerpt.js";
16
+ import { galaxyGet } from "./galaxy-api";
17
+ import { malformedIdsRefusal, pageBody } from "./galaxy-page-ops";
18
+ import { installedRecordStore, withRecordLock } from "./record-store-seam";
19
+
20
+ export type GalaxyOpArgs = Record<string, unknown>;
21
+
22
+ export interface GalaxyOpPolicy {
23
+ /** The brain's refusal before the operation runs, or undefined to let it run. */
24
+ check?(args: GalaxyOpArgs, call: { signal: AbortSignal }): Promise<string | undefined>;
25
+ /** Runs the call; `call` sends `args`, or the arguments it is given in their place. */
26
+ around?<T>(
27
+ call: (sent?: GalaxyOpArgs) => Promise<T>,
28
+ args: GalaxyOpArgs,
29
+ ctx: { signal: AbortSignal },
30
+ ): Promise<T>;
31
+ /** A replacement for Galaxy's refusal message, when the policy has something to add. */
32
+ refused?(message: string, args: GalaxyOpArgs): string | undefined;
33
+ }
34
+
35
+ type Row = Record<string, unknown>;
36
+
37
+ const isRow = (value: unknown): value is Row =>
38
+ !!value && typeof value === "object" && !Array.isArray(value);
39
+
40
+ // A lookup the deadline cut short is not a lookup that failed: failing open there would let the
41
+ // call run after the model was told its result is unknown.
42
+ function rethrowIfAborted(signal: AbortSignal): void {
43
+ if (signal.aborted) throw signal.reason;
44
+ }
45
+
46
+ /**
47
+ * `work`, given up on once `signal` aborts. The deadline only stops waiting for a call; a
48
+ * transport that ignores its signal leaves the call itself pending, and a lock held across it
49
+ * would never be released.
50
+ */
51
+ function untilAborted<T>(signal: AbortSignal, work: () => Promise<T>): Promise<T> {
52
+ if (signal.aborted) return Promise.reject(signal.reason);
53
+ return new Promise<T>((resolve, reject) => {
54
+ const abandon = () => reject(signal.reason);
55
+ signal.addEventListener("abort", abandon, { once: true });
56
+ work().then(
57
+ (value) => {
58
+ signal.removeEventListener("abort", abandon);
59
+ resolve(value);
60
+ },
61
+ (error: unknown) => {
62
+ signal.removeEventListener("abort", abandon);
63
+ reject(error);
64
+ },
65
+ );
66
+ });
67
+ }
68
+
69
+ // ── run_tool: input keys Galaxy would not read ───────────────────────────────────────────────────
70
+
71
+ /**
72
+ * Whether Galaxy's legacy tool state reads `key` for these declared inputs: a parameter by its
73
+ * name, a repeat's instance as `name_N|`, a conditional or section member as `name|`, the way
74
+ * Galaxy's `_populate_state_legacy` builds its keys.
75
+ */
76
+ function reads(declared: unknown, key: string): boolean {
77
+ return (Array.isArray(declared) ? declared : []).filter(isRow).some((p) => {
78
+ const name = String(p.name ?? "");
79
+ if (!name) return false;
80
+ if (p.type === "repeat" || p.type === "upload_dataset") {
81
+ const instance = key.match(/^(.+?)_\d+\|(.+)$/);
82
+ return instance?.[1] === name && reads(p.inputs, instance[2]);
83
+ }
84
+ if (p.type === "conditional") {
85
+ const test = isRow(p.test_param) ? p.test_param.name : undefined;
86
+ if (key === test) return true;
87
+ const rest = key.startsWith(`${name}|`) ? key.slice(name.length + 1) : undefined;
88
+ return (
89
+ rest !== undefined &&
90
+ (rest === test ||
91
+ (Array.isArray(p.cases) ? p.cases : []).some((c) => isRow(c) && reads(c.inputs, rest)))
92
+ );
93
+ }
94
+ if (p.type === "section") {
95
+ return key.startsWith(`${name}|`) && reads(p.inputs, key.slice(name.length + 1));
96
+ }
97
+ return key === name;
98
+ });
99
+ }
100
+
101
+ /** The keys Galaxy reads for these declared inputs, a repeat shown by its first instance. */
102
+ function keysOf(declared: unknown, prefix = ""): string[] {
103
+ return (Array.isArray(declared) ? declared : []).filter(isRow).flatMap((p) => {
104
+ const key = `${prefix}${String(p.name)}`;
105
+ if (p.type === "repeat" || p.type === "upload_dataset") return keysOf(p.inputs, `${key}_0|`);
106
+ if (p.type === "conditional") {
107
+ const test = isRow(p.test_param) ? String(p.test_param.name) : "";
108
+ const cases = (Array.isArray(p.cases) ? p.cases : [])
109
+ .filter(isRow)
110
+ .flatMap((c) => keysOf(c.inputs, `${key}|`));
111
+ return [`${key}|${test}`, ...new Set(cases)];
112
+ }
113
+ return p.type === "section" ? keysOf(p.inputs, `${key}|`) : [key];
114
+ });
115
+ }
116
+
117
+ /**
118
+ * A refusal for run_tool input keys the tool does not declare. Galaxy drops a key it does not
119
+ * read without a word and runs the tool on its defaults, so a misspelt parameter becomes a job
120
+ * that answers a different question. Anything this cannot establish -- a failed lookup, a schema
121
+ * for another tool or version, a tool with no declared inputs -- is left for Galaxy to decide.
122
+ */
123
+ export async function unreadInputs(
124
+ args: GalaxyOpArgs,
125
+ { signal }: { signal: AbortSignal },
126
+ ): Promise<string | undefined> {
127
+ const { tool_id: toolId, tool_version: version, inputs } = args;
128
+ if (!isRow(inputs) || typeof toolId !== "string" || !toolId) return undefined;
129
+ const pinned = typeof version === "string" && version ? version : undefined;
130
+ let schema: unknown;
131
+ try {
132
+ schema = await galaxyGet(
133
+ `/tools/${encodeURIComponent(toolId)}?io_details=true${pinned ? `&tool_version=${encodeURIComponent(pinned)}` : ""}`,
134
+ signal,
135
+ );
136
+ } catch {
137
+ rethrowIfAborted(signal);
138
+ return undefined;
139
+ }
140
+ if (!isRow(schema) || !Array.isArray(schema.inputs) || schema.inputs.length === 0) {
141
+ return undefined;
142
+ }
143
+ // Galaxy expands a short id and serves its newest version when the one asked for is missing;
144
+ // a schema for another tool or version says nothing about this call.
145
+ const id = String(schema.id ?? "");
146
+ if (!(id === toolId || id.startsWith(`${toolId}/`))) return undefined;
147
+ if (pinned && schema.version !== pinned) return undefined;
148
+ const unread = Object.keys(inputs).filter(
149
+ (key) =>
150
+ !key.startsWith("__") && !key.endsWith("|__identifier__") && !reads(schema.inputs, key),
151
+ );
152
+ if (unread.length === 0) return undefined;
153
+ const list = (keys: string[]) => keys.map((k) => JSON.stringify(k)).join(", ");
154
+ return (
155
+ `Refused: ${toolId} has no input at ${list(unread)}, so Galaxy would drop ` +
156
+ `${unread.length > 1 ? "them" : "it"} and run the tool without saying so. The keys it ` +
157
+ `reads are ${list(keysOf(schema.inputs))}. A repeat takes one key prefix per instance ` +
158
+ `(\`name_0|\`, \`name_1|\`), a conditional or section member is \`name|member\`, and a ` +
159
+ `parameter that takes several datasets takes them under its own key as {"values": [...]}.`
160
+ );
161
+ }
162
+
163
+ // ── pages: what the model was shown, and section edits against the page as it is now ────────────
164
+
165
+ /**
166
+ * Page bodies this session's model was shown, keyed by page and the content_hash it saw with
167
+ * them. Enough to tell whether a section the model is rewriting moved since it read the page.
168
+ */
169
+ const shown = new Map<string, string>();
170
+ const SHOWN_KEPT = 20;
171
+ const shownKey = (pageId: string, hash: string) => JSON.stringify([pageId, hash]);
172
+
173
+ function remember(pageId: string, body: string, claimed: unknown): void {
174
+ const hash = pageContentHash(body);
175
+ // A body that does not hash to what the model was told is not what it saw.
176
+ if (typeof claimed === "string" && claimed !== hash) return;
177
+ const key = shownKey(pageId, hash);
178
+ shown.delete(key);
179
+ shown.set(key, body);
180
+ if (shown.size > SHOWN_KEPT) shown.delete(shown.keys().next().value!);
181
+ }
182
+
183
+ /** Forget every page body; a new session's model has been shown none. */
184
+ export function resetShownPages(): void {
185
+ shown.clear();
186
+ }
187
+
188
+ /** Keep the page a successful call answered with as what the model was shown. */
189
+ function shownPage<T>(env: T, args: GalaxyOpArgs): T {
190
+ const { success, data } = (env ?? {}) as { success?: unknown; data?: unknown };
191
+ if (
192
+ success === true &&
193
+ isRow(data) &&
194
+ typeof args.page_id === "string" &&
195
+ (data.content_editor != null || data.content != null)
196
+ ) {
197
+ remember(args.page_id, pageBody(data as Parameters<typeof pageBody>[0]), data.content_hash);
198
+ }
199
+ return env;
200
+ }
201
+
202
+ /**
203
+ * A section edit's arguments against the page as it is now. Orbit writes into the record page
204
+ * itself (the poller's job blocks, the session's own lines), so a hash the model read before one
205
+ * of those writes no longer matches. When the model's read is known and the sections it replaces
206
+ * are unchanged since, the edit is just as right against the current page, and is sent with the
207
+ * current hash. Anything else goes as given, and the bridge refuses a stale hash. A hash the
208
+ * model did not send is never supplied.
209
+ */
210
+ async function againstCurrent(args: GalaxyOpArgs, signal: AbortSignal): Promise<GalaxyOpArgs> {
211
+ const { expect_hash: read, section_heading: heading, page_id: pageId } = args;
212
+ if (typeof read !== "string" || typeof heading !== "string" || typeof pageId !== "string") {
213
+ return args;
214
+ }
215
+ if (args.content != null) return args;
216
+ const base = shown.get(shownKey(pageId, read));
217
+ if (base === undefined) return args;
218
+ let current: string;
219
+ try {
220
+ const page = await galaxyGet<Parameters<typeof pageBody>[0] | null>(
221
+ `/pages/${encodeURIComponent(pageId)}`,
222
+ signal,
223
+ );
224
+ current = pageBody(page ?? {});
225
+ } catch {
226
+ rethrowIfAborted(signal);
227
+ return args;
228
+ }
229
+ const now = pageContentHash(current);
230
+ if (now === read) return args;
231
+ const same =
232
+ JSON.stringify(sectionsHeaded(base, heading)) ===
233
+ JSON.stringify(sectionsHeaded(current, heading));
234
+ return same ? { ...args, expect_hash: now } : args;
235
+ }
236
+
237
+ const HEADING_LINE = /^#{1,6}\s+\S/;
238
+
239
+ /** A refusal for a section edit that would leave its text without a heading on the page. */
240
+ function headingless(args: GalaxyOpArgs): string | undefined {
241
+ if (args.section_heading == null) return undefined;
242
+ const heading = String(args.section_heading);
243
+ // No heading line on a page holds a newline, so such a heading never matches and the edit
244
+ // would land at the end of the page.
245
+ if (heading.includes("\n")) {
246
+ return (
247
+ `Refused: section_heading is one line, the heading line exactly as the page writes it ` +
248
+ `(such as "## Results"). Everything under it goes in section_content.`
249
+ );
250
+ }
251
+ if (!HEADING_LINE.test(heading)) {
252
+ return (
253
+ `Refused: section_heading is the heading line itself, exactly as the page writes it ` +
254
+ `(such as ${JSON.stringify(`## ${heading.trim()}`)}), not the bare title. A line the page ` +
255
+ `does not hold as a heading adds the text at the end of the page under no heading.`
256
+ );
257
+ }
258
+ // Leaves the pair refusal to the bridge, which says what is missing.
259
+ if (args.section_content == null) return undefined;
260
+ // Only blank lines are skipped: an indented heading line is not a heading to markdown, so the
261
+ // section would merge into the one above it.
262
+ const first = String(args.section_content)
263
+ .replace(/^(?:[ \t]*\r?\n)+/, "")
264
+ .split("\n")[0];
265
+ if (HEADING_LINE.test(first)) return undefined;
266
+ return (
267
+ `Refused: section_content replaces the whole section, its heading line included, so it ` +
268
+ `starts with ${JSON.stringify(heading)}. Without that line the page loses the heading.`
269
+ );
270
+ }
271
+
272
+ /**
273
+ * Keyed by operation name. These are the brain's own checks; Galaxy's server validation stays
274
+ * the backstop for anything they do not cover.
275
+ */
276
+ export const GALAXY_OP_POLICY: Record<string, GalaxyOpPolicy> = {
277
+ run_tool: { check: unreadInputs },
278
+ create_page: {
279
+ check: async (args) => {
280
+ const found = malformedObjectIds(typeof args.content === "string" ? args.content : null);
281
+ return found.length > 0 ? malformedIdsRefusal(found) : undefined;
282
+ },
283
+ },
284
+ get_page: {
285
+ around: async (call, args) => shownPage(await call(), args),
286
+ },
287
+ update_page: {
288
+ check: async (args) => {
289
+ // Orbit shows the model a head-and-tail excerpt of the record; content copied from it
290
+ // would replace the middle of the page with the marker.
291
+ if (typeof args.content === "string" && args.content.includes(ELISION_MARKER)) {
292
+ return (
293
+ `Refused: this content still holds the record excerpt's elision marker ` +
294
+ `(${ELISION_MARKER}), so writing it would delete the part of the page the excerpt ` +
295
+ `left out. Rewrite the section you mean with section_heading and section_content instead.`
296
+ );
297
+ }
298
+ // The excerpt cuts by length, so one section can straddle the cut.
299
+ if (
300
+ typeof args.section_content === "string" &&
301
+ args.section_content.includes(ELISION_MARKER)
302
+ ) {
303
+ return (
304
+ `Refused: this section_content still holds the record excerpt's elision marker ` +
305
+ `(${ELISION_MARKER}), so writing it would delete the part of the section the excerpt ` +
306
+ `left out. Read the page with get_page and rewrite the section from what it holds.`
307
+ );
308
+ }
309
+ return headingless(args);
310
+ },
311
+ around: async (call, args, { signal }) => {
312
+ const run = async () => {
313
+ const sent = await againstCurrent(args, signal);
314
+ return shownPage(await call(sent === args ? undefined : sent), args);
315
+ };
316
+ // The bridge reads the page and then writes it. On the record page the poller writes
317
+ // under this lock, so holding it closes that window; a file record has no page id. The
318
+ // lock ends with the deadline, not with a request that may never come back.
319
+ const store = installedRecordStore();
320
+ return store?.kind === "page" && store.pageId !== undefined && store.pageId === args.page_id
321
+ ? withRecordLock(store.key, () => untilAborted(signal, run))
322
+ : run();
323
+ },
324
+ },
325
+ };
326
+
327
+ /** The policy's session state: a new session forgets the pages the last one was shown. */
328
+ export function registerGalaxyOpPolicy(pi: ExtensionAPI): void {
329
+ pi.on("session_start", () => {
330
+ resetShownPages();
331
+ });
332
+ }