@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,347 @@
1
+ /**
2
+ * `loom-job` notebook blocks: the tool-run equivalent of `loom-invocation`.
3
+ *
4
+ * The background poller advances work by scanning the notebook for in-flight
5
+ * blocks, but it only ever knew about workflow invocations. A session driven
6
+ * with single Galaxy *tool* runs recorded nothing pollable, so every tick took
7
+ * the cheap early-return path, nothing advanced, no completion toast fired --
8
+ * and the analysis sat still until the user typed "status?" (#413).
9
+ *
10
+ * Deliberately a separate fence rather than a flag on InvocationYaml: an
11
+ * invocation id and a job id go to different Galaxy endpoints, and a job id
12
+ * parsed as an invocation would send the existing polling tools to
13
+ * /api/invocations/<job id> and fail. Separate types keep that mistake
14
+ * unrepresentable.
15
+ *
16
+ * Format matches loom-invocation: line-oriented and grep-friendly, so the
17
+ * blocks stay readable in a diff and survive hand edits.
18
+ *
19
+ * ```loom-job
20
+ * job_id: abc123
21
+ * galaxy_server_url: https://usegalaxy.org
22
+ * notebook_anchor: plan-1-step-3
23
+ * label: BWA alignment
24
+ * tool_id: bwa_mem
25
+ * submitted_at: 2026-08-12T15:30:00Z
26
+ * status: in_progress
27
+ * summary: ""
28
+ * ```
29
+ */
30
+
31
+ import { notebookFenceOpen, replaceNotebookBlocks } from "../../shared/notebook-fences.js";
32
+ import { appendBlock, isUnambiguousRange } from "./notebook-writer";
33
+ import {
34
+ blockLine,
35
+ isFoldableDuplicate,
36
+ scanFencedBlocks,
37
+ mergeHarnessFields,
38
+ parseHarnessFields,
39
+ renderHarnessFieldLines,
40
+ stripHarnessFields,
41
+ type HarnessBlockFields,
42
+ } from "./harness-block-fields";
43
+
44
+ export interface JobYaml extends HarnessBlockFields {
45
+ jobId: string;
46
+ galaxyServerUrl: string;
47
+ notebookAnchor: string;
48
+ label: string;
49
+ toolId?: string;
50
+ submittedAt: string;
51
+ status: "in_progress" | "completed" | "failed" | "cancelled" | "skipped";
52
+ summary?: string;
53
+ /**
54
+ * Whether Galaxy confirmed this job id exists at record time. `false` means
55
+ * the record tool asked and got no answer, not that the job is fake; the
56
+ * poller sets it true on its first successful poll. Absent means the block
57
+ * predates the field. Mirrors the same field on `InvocationYaml`.
58
+ */
59
+ serverVerified?: boolean;
60
+ /** Galaxy's raw job state at the last poll, kept for display and debugging. */
61
+ galaxyState?: string;
62
+ lastPolledAt?: string;
63
+ }
64
+
65
+ const JOB_FENCE_OPEN = notebookFenceOpen("job");
66
+ const JOB_FENCE_CLOSE = "```";
67
+
68
+ /**
69
+ * How each Galaxy job state (JobState in lib/galaxy/schema/schema.py) lands in
70
+ * the block. A state listed here stops the polling; anything absent -- known
71
+ * running states and any state Galaxy adds later -- leaves the block
72
+ * in_progress, which is the safe default: we keep watching rather than
73
+ * declaring an outcome we can't name.
74
+ *
75
+ * Two distinctions this table exists to make, both of which cost us a bug:
76
+ *
77
+ * Ending is not the same as failing. `deleted` and `stopped` are the user
78
+ * cancelling their own job, and `skipped` is a workflow conditional choosing
79
+ * not to run a step. Reporting those as failures sends the agent off to
80
+ * investigate a malfunction that never happened -- Galaxy's own workflow UI
81
+ * counts skipped alongside successful jobs.
82
+ *
83
+ * Ending is also not the same as heading for the exit. `deleting` and `stop`
84
+ * (the wire value of STOPPING) are transitional: Galaxy's job handler advances
85
+ * them to `deleted` and `stopped`. Treating them as terminal freezes the block
86
+ * on a state the job has already left, and because the poller only revisits
87
+ * in_progress blocks, nothing ever corrects it.
88
+ *
89
+ * `paused` is likewise not terminal: it resumes when its inputs arrive, or when
90
+ * the user resumes it explicitly.
91
+ */
92
+ const JOB_STATE_OUTCOME: Readonly<Record<string, Exclude<JobYaml["status"], "in_progress">>> = {
93
+ ok: "completed",
94
+ error: "failed",
95
+ failed: "failed",
96
+ deleted: "cancelled",
97
+ stopped: "cancelled",
98
+ skipped: "skipped",
99
+ };
100
+
101
+ /**
102
+ * Every status the block may carry. Parsing has to recognise all of them: a
103
+ * terminal status it doesn't know reads back as in_progress, so the poller
104
+ * picks the job up again, rewrites the same outcome, and re-announces it on
105
+ * every tick.
106
+ */
107
+ const JOB_STATUSES: readonly JobYaml["status"][] = [
108
+ "in_progress",
109
+ "completed",
110
+ "failed",
111
+ "cancelled",
112
+ "skipped",
113
+ ];
114
+
115
+ function isJobStatus(value: string | undefined): value is JobYaml["status"] {
116
+ return !!value && (JOB_STATUSES as readonly string[]).includes(value);
117
+ }
118
+
119
+ export function isTerminalJobState(state: string | undefined): boolean {
120
+ if (!state) return false;
121
+ return state.toLowerCase() in JOB_STATE_OUTCOME;
122
+ }
123
+
124
+ /** Map a Galaxy job state onto the block's coarse status. */
125
+ export function jobStatusFromGalaxyState(state: string | undefined): JobYaml["status"] {
126
+ if (!state) return "in_progress";
127
+ return JOB_STATE_OUTCOME[state.toLowerCase()] ?? "in_progress";
128
+ }
129
+
130
+ function escapeYaml(value: string): string {
131
+ // Same conservative rule the invocation block uses: quote anything that
132
+ // could be read as YAML structure, leave plain scalars alone.
133
+ if (value === "") return '""';
134
+ if (/^[\w .\-/]+$/.test(value)) return value;
135
+ return JSON.stringify(value);
136
+ }
137
+
138
+ function unescapeYaml(value: string): string {
139
+ const trimmed = value.trim();
140
+ if (trimmed.startsWith('"')) {
141
+ try {
142
+ return JSON.parse(trimmed) as string;
143
+ } catch {
144
+ return trimmed;
145
+ }
146
+ }
147
+ return trimmed;
148
+ }
149
+
150
+ /** Render a job as a `loom-job` fenced block, trailing newline included. */
151
+ export function renderJobYaml(job: JobYaml): string {
152
+ const lines: string[] = [
153
+ JOB_FENCE_OPEN,
154
+ blockLine("job_id", job.jobId, "jobId"),
155
+ blockLine("galaxy_server_url", job.galaxyServerUrl),
156
+ blockLine("notebook_anchor", job.notebookAnchor, "notebookAnchor"),
157
+ `label: ${escapeYaml(job.label)}`,
158
+ ];
159
+ if (job.toolId) lines.push(blockLine("tool_id", job.toolId, "toolId"));
160
+ lines.push(blockLine("submitted_at", job.submittedAt));
161
+ lines.push(`status: ${job.status}`);
162
+ lines.push(`summary: ${escapeYaml(job.summary ?? "")}`);
163
+ if (job.serverVerified !== undefined) lines.push(`server_verified: ${job.serverVerified}`);
164
+ if (job.galaxyState) lines.push(blockLine("galaxy_state", job.galaxyState));
165
+ if (job.lastPolledAt) lines.push(blockLine("last_polled_at", job.lastPolledAt));
166
+ lines.push(...renderHarnessFieldLines(job));
167
+ lines.push(JOB_FENCE_CLOSE);
168
+ return lines.join("\n") + "\n";
169
+ }
170
+
171
+ function parseBooleanField(raw: string | undefined): boolean | undefined {
172
+ if (raw === "true") return true;
173
+ if (raw === "false") return false;
174
+ return undefined;
175
+ }
176
+
177
+ /**
178
+ * The block's `key: value` lines, untouched. The upsert reads carry-forward
179
+ * provenance through here as well as the parser, because provenance has to
180
+ * survive a block the parser rejects -- see `upsertJobBlock`.
181
+ */
182
+ function rawJobFields(blockLines: string[]): Map<string, string> {
183
+ const map = new Map<string, string>();
184
+ for (const line of blockLines) {
185
+ const idx = line.indexOf(":");
186
+ if (idx === -1) continue;
187
+ map.set(line.slice(0, idx).trim(), line.slice(idx + 1).trim());
188
+ }
189
+ return map;
190
+ }
191
+
192
+ function parseJobBlock(blockLines: string[]): JobYaml | null {
193
+ const map = rawJobFields(blockLines);
194
+ const jobId = map.get("job_id");
195
+ if (!jobId) return null; // a block without an id is not pollable
196
+ const status = map.get("status");
197
+ return {
198
+ jobId,
199
+ galaxyServerUrl: map.get("galaxy_server_url") ?? "",
200
+ notebookAnchor: map.get("notebook_anchor") ?? "",
201
+ label: unescapeYaml(map.get("label") ?? ""),
202
+ toolId: map.get("tool_id") || undefined,
203
+ submittedAt: map.get("submitted_at") ?? "",
204
+ status: isJobStatus(status) ? status : "in_progress",
205
+ summary: unescapeYaml(map.get("summary") ?? "") || undefined,
206
+ // Absent or unreadable both mean "nobody has claimed this", which is the
207
+ // honest default for a flag about a server round trip.
208
+ serverVerified: parseBooleanField(map.get("server_verified")),
209
+ galaxyState: map.get("galaxy_state") || undefined,
210
+ lastPolledAt: map.get("last_polled_at") || undefined,
211
+ // `map` holds raw values (nothing here runs unescapeYaml), which is what
212
+ // the harness fields want: bare tokens and single-line JSON.
213
+ ...parseHarnessFields((key) => map.get(key)),
214
+ };
215
+ }
216
+
217
+ interface BlockRange {
218
+ jobId: string;
219
+ start: number;
220
+ end: number;
221
+ }
222
+
223
+ function findJobBlockRanges(content: string): BlockRange[] {
224
+ const lines = content.split("\n");
225
+ const ranges: BlockRange[] = [];
226
+ for (const range of scanFencedBlocks(lines, "job")) {
227
+ const parsed = parseJobBlock(lines.slice(range.start + 1, range.end));
228
+ if (parsed) ranges.push({ jobId: parsed.jobId, start: range.start, end: range.end });
229
+ }
230
+ return ranges;
231
+ }
232
+
233
+ /** Every parseable `loom-job` block in the notebook. Invalid blocks are skipped. */
234
+ export function findJobBlocks(content: string): JobYaml[] {
235
+ const lines = content.split("\n");
236
+ const result: JobYaml[] = [];
237
+ for (const range of scanFencedBlocks(lines, "job")) {
238
+ const parsed = parseJobBlock(lines.slice(range.start + 1, range.end));
239
+ if (parsed) result.push(parsed);
240
+ }
241
+ return result;
242
+ }
243
+
244
+ /**
245
+ * Find the first `loom-job` block physically carrying this id, and what it
246
+ * parses to. The invocation side's twin -- see `locateInvocationBlock` for why
247
+ * one physical block has to answer both questions.
248
+ */
249
+ export function locateJobBlock(
250
+ content: string,
251
+ jobId: string,
252
+ ): { present: boolean; record: JobYaml | null } {
253
+ const lines = content.split("\n");
254
+ const range = findJobBlockRanges(content).find((b) => b.jobId === jobId);
255
+ if (!range) return { present: false, record: null };
256
+ return { present: true, record: parseJobBlock(lines.slice(range.start + 1, range.end)) };
257
+ }
258
+
259
+ /**
260
+ * Upsert a `loom-job` block keyed by `job_id`: replace in place when the id is
261
+ * already present, otherwise append at the end.
262
+ *
263
+ * Harness-only fields on `job` are discarded; see `upsertInvocationBlock` in
264
+ * notebook-writer.ts for why. They are carried over from the block on disk,
265
+ * or supplied explicitly through `harness` by the auto-registration path.
266
+ */
267
+ export function upsertJobBlock(
268
+ content: string,
269
+ job: JobYaml,
270
+ harness?: HarnessBlockFields,
271
+ ): string {
272
+ const ranges = findJobBlockRanges(content);
273
+ const lines = content.split("\n");
274
+
275
+ // Only a range no unclosed fence precedes can be replaced -- see
276
+ // isUnambiguousRange. More than one can match when an older writer used the
277
+ // other fence prefix; foldable duplicates collapse into the rewritten block.
278
+ const matching = ranges.filter(
279
+ (b) => b.jobId === job.jobId && isUnambiguousRange(lines, b.start),
280
+ );
281
+ const existing = matching[0];
282
+ // Read off the block this write replaces, not a second scan of the file --
283
+ // see the same comment in `upsertInvocationBlock`.
284
+ const onDiskRaw = existing ? rawJobFields(lines.slice(existing.start + 1, existing.end)) : null;
285
+ const onDisk = parseHarnessFields((key) => onDiskRaw?.get(key));
286
+ const merged: JobYaml = {
287
+ ...stripHarnessFields(job),
288
+ ...mergeHarnessFields(onDisk, harness ?? {}),
289
+ };
290
+ const newBlock = renderJobYaml(merged).trimEnd().split("\n");
291
+
292
+ if (existing) {
293
+ const replaced = matching.filter(
294
+ (b) =>
295
+ b === existing ||
296
+ isFoldableDuplicate(
297
+ onDiskRaw?.get("attempt_id"),
298
+ rawJobFields(lines.slice(b.start + 1, b.end)).get("attempt_id"),
299
+ ),
300
+ );
301
+ return replaceNotebookBlocks(content, replaced, newBlock);
302
+ }
303
+
304
+ return appendBlock(content, newBlock);
305
+ }
306
+
307
+ /**
308
+ * What one poll learned. Deliberately not a whole JobYaml: `label`,
309
+ * `notebook_anchor` and `submitted_at` belong to whoever recorded the job, and
310
+ * writing back a copy captured before the Galaxy round trip would clobber an
311
+ * edit made in the meantime -- the same hazard the invocation poller documents.
312
+ */
313
+ export interface JobPollUpdate {
314
+ jobId: string;
315
+ /**
316
+ * The outcome this poll decided, or omitted for an update that isn't about
317
+ * the outcome at all -- a verification-only write, say. Omitting is not the
318
+ * same as passing the status the caller last saw: that copy predates whatever
319
+ * landed while we were talking to Galaxy, and writing it back would revert
320
+ * another writer's transition.
321
+ */
322
+ status?: JobYaml["status"];
323
+ galaxyState?: string;
324
+ lastPolledAt: string;
325
+ summary?: string;
326
+ /**
327
+ * True when this update came from a Galaxy round trip that answered, which is
328
+ * proof the id exists. Same rule as the invocation side: it clears a block
329
+ * recorded `server_verified: false` and leaves an unstamped one alone.
330
+ */
331
+ serverVerified?: boolean;
332
+ }
333
+
334
+ /** Apply a poll result to whichever block carries that job id. No-op if absent. */
335
+ export function applyJobPollUpdate(content: string, update: JobPollUpdate): string {
336
+ const current = findJobBlocks(content).find((j) => j.jobId === update.jobId);
337
+ if (!current) return content;
338
+ return upsertJobBlock(content, {
339
+ ...current,
340
+ status: update.status ?? current.status,
341
+ galaxyState: update.galaxyState ?? current.galaxyState,
342
+ lastPolledAt: update.lastPolledAt,
343
+ summary: update.summary ?? current.summary,
344
+ serverVerified:
345
+ update.serverVerified && current.serverVerified === false ? true : current.serverVerified,
346
+ });
347
+ }
@@ -0,0 +1,288 @@
1
+ /**
2
+ * The job reads Orbit's model needs that galaxy-ops 0.3.1 does not have, written as galaxy-ops
3
+ * operations so they run through the same wrapper as every other Galaxy tool: one envelope, the
4
+ * same failure kinds and deadline, Python-shaped failure wording from their `failure` contracts.
5
+ *
6
+ * `run_tool` answers with job ids, and the model polls them, but galaxy-ops' get_job_details only
7
+ * finds a job from the dataset it made. The bridge reads a job by its own id as well, and keeps
8
+ * the dataset route as galaxy-ops wrote it. list_jobs and get_job_logs have no galaxy-ops
9
+ * counterpart at all. They all go away when galaxy-ops ships the same operations.
10
+ */
11
+ import {
12
+ getJobDetailsOp,
13
+ GalaxyConnectionError,
14
+ GalaxyValidationError,
15
+ httpError,
16
+ type AnyOperation,
17
+ type GalaxyContext,
18
+ type GetJobDetailsResult,
19
+ type JobDetail,
20
+ type Operation,
21
+ } from "@galaxyproject/galaxy-ops";
22
+ import { isGalaxyEncodedId } from "./galaxy-api";
23
+ import type { GalaxyOpArgs } from "./galaxy-op-policy";
24
+ import type { GalaxyBridge } from "./galaxy-ops-tools";
25
+
26
+ /** A job id is a URL path segment; anything else could walk the URL to another endpoint. */
27
+ function encodedJobId(jobId: string): string {
28
+ if (!isGalaxyEncodedId(jobId)) {
29
+ throw new GalaxyValidationError(
30
+ `job_id '${jobId}' is not a Galaxy job id. Job ids are the hexadecimal strings run_tool and list_jobs return; pass one back exactly.`,
31
+ );
32
+ }
33
+ return jobId;
34
+ }
35
+
36
+ async function fetchJob(
37
+ ctx: GalaxyContext,
38
+ jobId: string,
39
+ full: boolean,
40
+ ): Promise<Record<string, unknown>> {
41
+ const { data, error, response } = await ctx.client.GET("/api/jobs/{job_id}", {
42
+ params: { path: { job_id: jobId }, ...(full ? { query: { full: true } } : {}) },
43
+ });
44
+ if (error || !data) throw httpError(response, error);
45
+ return data as Record<string, unknown>;
46
+ }
47
+
48
+ // The added and relaxed fields come from the operation's own zod fields, so they render, parse
49
+ // and laxen through galaxy-ops' zod like every other parameter. dataset_id stops being required
50
+ // because a job id alone is now enough.
51
+ const jobDetailsInput = {
52
+ ...getJobDetailsOp.input,
53
+ datasetId: getJobDetailsOp.input.datasetId.optional(),
54
+ jobId: getJobDetailsOp.input.datasetId
55
+ .describe("Galaxy job id, as run_tool returns it. Give job_id or dataset_id.")
56
+ .optional(),
57
+ };
58
+
59
+ /** The dataset route's shape on both routes, so the poll guard and parsers read one result. */
60
+ type JobDetailsOut = Omit<GetJobDetailsResult, "dataset_id"> & { dataset_id: string | null };
61
+
62
+ const byJob = (i: { jobId?: string }): i is { jobId: string } => i.jobId !== undefined;
63
+ const baseFailure = getJobDetailsOp.failure;
64
+
65
+ const getJobDetailsBridgeOp: Operation<typeof jobDetailsInput, JobDetailsOut> = {
66
+ ...getJobDetailsOp,
67
+ input: jobDetailsInput,
68
+ async run(i, ctx) {
69
+ if (byJob(i)) {
70
+ const jobId = encodedJobId(i.jobId);
71
+ const job = (await fetchJob(ctx, jobId, false)) as JobDetail;
72
+ return { job, dataset_id: null, job_id: jobId };
73
+ }
74
+ if (i.datasetId === undefined) {
75
+ throw new GalaxyValidationError("Give job_id (from run_tool) or dataset_id.");
76
+ }
77
+ return getJobDetailsOp.run({ datasetId: i.datasetId, historyId: i.historyId }, ctx);
78
+ },
79
+ project(out, i, facts) {
80
+ if (byJob(i)) return { message: `Retrieved job details for job '${out.job_id}'` };
81
+ return (
82
+ getJobDetailsOp.project?.(
83
+ out as GetJobDetailsResult,
84
+ { datasetId: out.dataset_id ?? "", historyId: i.historyId },
85
+ facts,
86
+ ) ?? {}
87
+ );
88
+ },
89
+ failure: baseFailure && {
90
+ shape: baseFailure.shape,
91
+ action: baseFailure.action,
92
+ context: (i) =>
93
+ byJob(i)
94
+ ? { job_id: i.jobId }
95
+ : (baseFailure.context?.({ datasetId: i.datasetId ?? "", historyId: i.historyId }) ?? {}),
96
+ // The base sentence names the dataset; on the job route there is none to name.
97
+ sentence: (text, status, i) =>
98
+ byJob(i)
99
+ ? undefined
100
+ : baseFailure.sentence?.(text, status, {
101
+ datasetId: i.datasetId ?? "",
102
+ historyId: i.historyId,
103
+ }),
104
+ },
105
+ };
106
+
107
+ export const getJobDetailsBridge: GalaxyBridge = {
108
+ op: getJobDetailsBridgeOp as unknown as AnyOperation,
109
+ note: "Pass job_id to read a job directly, or dataset_id to find the job that made a dataset.",
110
+ };
111
+
112
+ /** The model's snake_case keys under these operations' camelCase ones. */
113
+ const renamed =
114
+ (names: Record<string, string>) =>
115
+ (args: GalaxyOpArgs): GalaxyOpArgs =>
116
+ Object.fromEntries(Object.entries(args).map(([k, v]) => [names[k] ?? k, v]));
117
+
118
+ const JOB_ID_PARAMETER = {
119
+ type: "string",
120
+ description: "Galaxy job id, as run_tool or list_jobs returns it.",
121
+ } as const;
122
+
123
+ const LIST_JOBS_LIMIT = { default: 50, max: 500 } as const;
124
+
125
+ function wholeNumber(name: string, value: unknown, fallback: number, max?: number): number {
126
+ if (value === undefined || value === null) return fallback;
127
+ const ok =
128
+ typeof value === "number" &&
129
+ Number.isInteger(value) &&
130
+ value >= (max === undefined ? 0 : 1) &&
131
+ (max === undefined || value <= max);
132
+ if (!ok) {
133
+ const range = max === undefined ? "0 or greater" : `from 1 to ${max}`;
134
+ throw new GalaxyValidationError(`${name} must be a whole number ${range} (got ${value}).`);
135
+ }
136
+ return value;
137
+ }
138
+
139
+ interface ListJobsInput {
140
+ historyId?: unknown;
141
+ limit?: unknown;
142
+ offset?: unknown;
143
+ }
144
+
145
+ const listJobsOp = {
146
+ name: "list_jobs",
147
+ domain: "jobs",
148
+ summary:
149
+ "List the jobs in a history, newest first: each row's id, tool_id, state and create_time. Use it to find the job behind a step or to see what is still running; get_job_details and get_job_logs take a row's id.",
150
+ input: {},
151
+ readOnly: true,
152
+ async run(i: ListJobsInput, ctx: GalaxyContext): Promise<unknown[]> {
153
+ if (typeof i.historyId !== "string" || i.historyId === "") {
154
+ throw new GalaxyValidationError("list_jobs needs history_id.");
155
+ }
156
+ const limit = wholeNumber("limit", i.limit, LIST_JOBS_LIMIT.default, LIST_JOBS_LIMIT.max);
157
+ const offset = wholeNumber("offset", i.offset, 0);
158
+ const { data, error, response } = await ctx.client.GET("/api/jobs", {
159
+ params: {
160
+ query: {
161
+ history_id: i.historyId,
162
+ view: "collection",
163
+ order_by: "create_time",
164
+ // Galaxy sends no total, so one row past the page is how project knows another exists.
165
+ limit: limit + 1,
166
+ offset,
167
+ },
168
+ },
169
+ });
170
+ if (error || !data) throw httpError(response, error);
171
+ // A non-list here is not a job index at all; reading it as zero jobs would hide that.
172
+ if (!Array.isArray(data)) {
173
+ throw new GalaxyConnectionError("Galaxy's job index did not return a list");
174
+ }
175
+ return data as unknown[];
176
+ },
177
+ project: (rows: unknown[], i: ListJobsInput) => {
178
+ // run already refused anything these would throw on.
179
+ const limit = wholeNumber("limit", i.limit, LIST_JOBS_LIMIT.default, LIST_JOBS_LIMIT.max);
180
+ const offset = wholeNumber("offset", i.offset, 0);
181
+ const page = rows.slice(0, limit);
182
+ const hasNext = rows.length > limit;
183
+ const next = offset + page.length;
184
+ return {
185
+ data: page,
186
+ message: `Retrieved ${page.length} jobs for history '${String(i.historyId)}'`,
187
+ count: page.length,
188
+ pagination: {
189
+ // A lower bound: Galaxy's job index does not count the rest.
190
+ total_items: offset + rows.length,
191
+ returned_items: page.length,
192
+ limit,
193
+ offset,
194
+ has_next: hasNext,
195
+ has_previous: offset > 0,
196
+ next_offset: hasNext ? next : null,
197
+ previous_offset: offset > 0 ? Math.max(0, offset - limit) : null,
198
+ helper_text:
199
+ `Showing ${page.length} jobs from offset ${offset}. ` +
200
+ (hasNext ? `Use offset=${next} for the next page.` : "This is the last page."),
201
+ },
202
+ };
203
+ },
204
+ failure: {
205
+ shape: "raise-for-status",
206
+ action: "List jobs",
207
+ context: (i: ListJobsInput) => ({ history_id: i.historyId }),
208
+ },
209
+ };
210
+
211
+ export const listJobsBridge: GalaxyBridge = {
212
+ op: listJobsOp as unknown as AnyOperation,
213
+ parameters: {
214
+ type: "object",
215
+ properties: {
216
+ history_id: { type: "string", description: "Encoded id of the history whose jobs to list." },
217
+ limit: {
218
+ type: "integer",
219
+ minimum: 1,
220
+ maximum: LIST_JOBS_LIMIT.max,
221
+ default: LIST_JOBS_LIMIT.default,
222
+ description: `Most jobs to return (default ${LIST_JOBS_LIMIT.default}, at most ${LIST_JOBS_LIMIT.max}).`,
223
+ },
224
+ offset: {
225
+ type: "integer",
226
+ minimum: 0,
227
+ default: 0,
228
+ description: "Jobs to skip from the newest, for the next page (default 0).",
229
+ },
230
+ },
231
+ required: ["history_id"],
232
+ additionalProperties: false,
233
+ },
234
+ inputOf: renamed({ history_id: "historyId" }),
235
+ };
236
+
237
+ /** Every log a job can carry, as `GET /api/jobs/{id}?full=true` names them. */
238
+ const LOG_FIELDS = [
239
+ "state",
240
+ "exit_code",
241
+ "stdout",
242
+ "stderr",
243
+ "job_stdout",
244
+ "job_stderr",
245
+ "tool_stdout",
246
+ "tool_stderr",
247
+ ] as const;
248
+
249
+ interface JobLogsInput {
250
+ jobId?: unknown;
251
+ }
252
+
253
+ const getJobLogsOp = {
254
+ name: "get_job_logs",
255
+ domain: "jobs",
256
+ summary:
257
+ "Get a job's state, exit code and logs: stdout and stderr as the tool and as Galaxy's job runner wrote them. Read these to see why a job failed.",
258
+ input: {},
259
+ readOnly: true,
260
+ async run(i: JobLogsInput, ctx: GalaxyContext): Promise<Record<string, unknown>> {
261
+ if (typeof i.jobId !== "string") throw new GalaxyValidationError("get_job_logs needs job_id.");
262
+ const jobId = encodedJobId(i.jobId);
263
+ const job = await fetchJob(ctx, jobId, true);
264
+ // Only what the server sent: an absent log is not an empty one.
265
+ const out: Record<string, unknown> = { job_id: jobId };
266
+ for (const key of LOG_FIELDS) if (key in job) out[key] = job[key];
267
+ return out;
268
+ },
269
+ project: (_out: unknown, i: JobLogsInput) => ({
270
+ message: `Retrieved logs for job '${String(i.jobId)}'`,
271
+ }),
272
+ failure: {
273
+ shape: "raise-for-status",
274
+ action: "Get job logs",
275
+ context: (i: JobLogsInput) => ({ job_id: i.jobId }),
276
+ },
277
+ };
278
+
279
+ export const getJobLogsBridge: GalaxyBridge = {
280
+ op: getJobLogsOp as unknown as AnyOperation,
281
+ parameters: {
282
+ type: "object",
283
+ properties: { job_id: JOB_ID_PARAMETER },
284
+ required: ["job_id"],
285
+ additionalProperties: false,
286
+ },
287
+ inputOf: renamed({ job_id: "jobId" }),
288
+ };