@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,735 @@
1
+ /**
2
+ * The approval and attempt registry's schema (design v3 §3), its canonical
3
+ * JSON form, and the parser that is the only way a document from disk or a
4
+ * Page carrier becomes a `Registry`.
5
+ *
6
+ * Deliberately free of anything harness-specific: no pi, no extension state,
7
+ * no environment. The same module has to serve a standalone MCP process later.
8
+ * `tests/registry-no-pi-imports.test.ts` enforces that over the import graph.
9
+ *
10
+ * The parser builds fresh objects field by field rather than casting what it
11
+ * was given. Unknown keys are dropped, so nothing an import smuggles in gets
12
+ * re-signed with this session's key and read back later as its own state.
13
+ */
14
+
15
+ import { createHash } from "crypto";
16
+ import { isUlid } from "./ulid";
17
+
18
+ // ─────────────────────────────────────────────────────────────────────────────
19
+ // Types (v3 §3, names kept exactly)
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+
22
+ /** A ULID, the same format capture already writes as `attempt_id`. */
23
+ export type AttemptId = string;
24
+
25
+ /** A notebook step anchor, or the literal capture uses for "no step". */
26
+ export type StepAnchor = string;
27
+
28
+ export const CURRENT_REGISTRY_VERSION = 3;
29
+
30
+ export interface Registry {
31
+ version: 3;
32
+ revision: number;
33
+ writer_token: string;
34
+ /** HMAC(session_key, canonical registry without this field). */
35
+ session_sig: string;
36
+ analysis_id: string;
37
+ server_url: string;
38
+ attempts: Record<AttemptId, Attempt>;
39
+ exceptions: Exception[];
40
+ supervision: { active_at_shutdown: AttemptId[]; last_reconcile_at?: string };
41
+ /**
42
+ * Not in v3 §3, which says server-mismatched imports are "quarantined"
43
+ * without saying where. Kept out of `attempts` so nothing that reads
44
+ * attempts can act on them, and persisted so the quarantine survives a save.
45
+ */
46
+ quarantine?: Record<AttemptId, Attempt>;
47
+ }
48
+
49
+ export type AttemptKind = "workflow" | "tool" | "udt" | "upload" | "rerun";
50
+
51
+ export interface Attempt {
52
+ attempt_id: AttemptId;
53
+ kind: AttemptKind;
54
+ binding: { step_anchor: StepAnchor | "unattributed"; bound_at: string };
55
+ server_url: string;
56
+ history_id: string;
57
+
58
+ approval?: {
59
+ proposal_id: string;
60
+ /** sha256(canonical Spec) */
61
+ spec_revision: string;
62
+ spec_snapshot: Spec;
63
+ status: "live" | "restored" | "revoked";
64
+ by: "user" | "restored";
65
+ at: string;
66
+ };
67
+
68
+ reservation?: {
69
+ dispatch_id: string;
70
+ reserved_at: string;
71
+ state: "reserved" | "submitted" | "submission_unknown" | "released";
72
+ };
73
+
74
+ submission?: {
75
+ invocation_id?: string;
76
+ job_id?: string;
77
+ dataset_id?: string;
78
+ submitted_at: string;
79
+ submitted_by: "harness" | "agent" | "unknown" | "pre-existing";
80
+ server_verified: boolean;
81
+ check: {
82
+ /**
83
+ * `conformant_by_reconcile`: the run Galaxy reports was re-checked against
84
+ * the frozen Spec in this session. Never written for a by-construction
85
+ * submission, and never carried across an import.
86
+ */
87
+ outcome:
88
+ | "conformant_by_construction"
89
+ | "conformant_by_reconcile"
90
+ | "unchecked"
91
+ | "mismatch"
92
+ | "unverified";
93
+ diff?: Diff[];
94
+ mode: "off" | "warn" | "deny";
95
+ };
96
+ request_digest: string;
97
+ dispatch_recheck: { definition_digest_ok: boolean; template_digest_ok: boolean; at: string };
98
+ };
99
+
100
+ provenance?: {
101
+ ref: { kind: "dataset" | "file"; id: string };
102
+ digest: string;
103
+ enrichment: "pending" | "complete" | "unavailable";
104
+ authority: "established" | "historical";
105
+ };
106
+
107
+ evaluation?: {
108
+ execution: "success" | "failed" | "unknown";
109
+ conformity: "conformant" | "nonconformant" | "unverified" | "excepted";
110
+ /** `attested`: the user vouched for a result no code checked; never reported as `pass`. */
111
+ predicate_result: "pass" | "fail" | "unevaluable" | "attested";
112
+ assertions: Record<string, "pass" | "fail" | "inconclusive" | "excepted">;
113
+ integrity: "ok" | "unverified_identity" | "render_contradiction" | "effective_contradiction";
114
+ authority: "established" | "historical";
115
+ evaluated_at: string;
116
+ };
117
+ /** Derived (v3 §7). Recomputed on every write; never taken from input. */
118
+ handoff_eligible: boolean;
119
+ rerun_of?: AttemptId[];
120
+ }
121
+
122
+ export interface Spec {
123
+ target: {
124
+ kind: "workflow" | "tool" | "udt";
125
+ workflow_id?: string;
126
+ tool_id?: string;
127
+ tool_uuid?: string;
128
+ /** Always resolved at approval, never "unpinned". */
129
+ version: string;
130
+ definition_digest?: string;
131
+ };
132
+ server_url: string;
133
+ history_id: string;
134
+ inputs: Array<{ slot: string; src: "hda" | "hdca" | "ldda"; id: string; required: boolean }>;
135
+ overrides: Array<{ param: string; value: unknown; rationale: string }>;
136
+ template_ref: { digest: string; fetched_at: string; version: string };
137
+ predicate: Predicate;
138
+ assertions: Array<{ id: string; definition_digest: string; definition: unknown }>;
139
+ }
140
+
141
+ export type Predicate =
142
+ | { kind: "exists_with_ext"; ext: string; min_count?: number }
143
+ | { kind: "count_eq"; ext?: string; count: number }
144
+ | { kind: "assertions_pass"; ids: string[] }
145
+ | { kind: "manual" };
146
+
147
+ export interface Exception {
148
+ id: string;
149
+ attempt_id: AttemptId;
150
+ spec_revision: string;
151
+ scope: "submission_check" | "evidence_gate" | "manual_attestation";
152
+ /** evidence_gate only: the one assertion this waives. */
153
+ assertion_id?: string;
154
+ by: "user" | "restored";
155
+ at: string;
156
+ reason: string;
157
+ }
158
+
159
+ export type Diff = { path: string; approved: unknown; observed: unknown };
160
+
161
+ // ─────────────────────────────────────────────────────────────────────────────
162
+ // Canonical JSON and digests
163
+ // ─────────────────────────────────────────────────────────────────────────────
164
+
165
+ /**
166
+ * JSON with object keys sorted at every level and `undefined` members dropped.
167
+ * The one serialisation everything here hashes or signs, so two processes that
168
+ * hold the same value always agree on its digest. Throws on anything JSON
169
+ * can't represent faithfully rather than letting it coerce to `null` or `{}`.
170
+ */
171
+ export function canonicalJson(value: unknown): string {
172
+ if (value === null) return "null";
173
+ switch (typeof value) {
174
+ case "string":
175
+ case "boolean":
176
+ return JSON.stringify(value);
177
+ case "number":
178
+ if (!Number.isFinite(value)) throw new TypeError(`canonicalJson: non-finite number`);
179
+ return JSON.stringify(value);
180
+ case "object": {
181
+ if (Array.isArray(value)) {
182
+ return `[${value.map((v) => canonicalJson(v)).join(",")}]`;
183
+ }
184
+ const proto = Object.getPrototypeOf(value);
185
+ if (proto !== Object.prototype && proto !== null) {
186
+ throw new TypeError(`canonicalJson: not a plain object`);
187
+ }
188
+ const rec = value as Record<string, unknown>;
189
+ const parts: string[] = [];
190
+ for (const key of Object.keys(rec).sort()) {
191
+ if (rec[key] === undefined) continue;
192
+ parts.push(`${JSON.stringify(key)}:${canonicalJson(rec[key])}`);
193
+ }
194
+ return `{${parts.join(",")}}`;
195
+ }
196
+ default:
197
+ throw new TypeError(`canonicalJson: cannot serialise a ${typeof value}`);
198
+ }
199
+ }
200
+
201
+ export function sha256Hex(text: string): string {
202
+ return createHash("sha256").update(text, "utf-8").digest("hex");
203
+ }
204
+
205
+ /** `spec_revision`: sha256 of the canonical Spec (v3 §5). */
206
+ export function specRevision(spec: Spec): string {
207
+ return sha256Hex(canonicalJson(spec));
208
+ }
209
+
210
+ export const DIGEST_RE = /^[0-9a-f]{64}$/;
211
+
212
+ // ─────────────────────────────────────────────────────────────────────────────
213
+ // Strict parsing
214
+ // ─────────────────────────────────────────────────────────────────────────────
215
+
216
+ export class RegistryFormatError extends Error {
217
+ constructor(message: string) {
218
+ super(message);
219
+ this.name = "RegistryFormatError";
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Throw if any JSON object in `text` repeats a key. `JSON.parse` silently keeps
225
+ * the last one, which would let a file carry two different attempts under one
226
+ * id and have us sign whichever happened to come second. Assumes `text` has
227
+ * already parsed as JSON.
228
+ */
229
+ export function assertNoDuplicateKeys(text: string): void {
230
+ const stack: Array<Set<string> | null> = [];
231
+ let expectKey = false;
232
+ let i = 0;
233
+ while (i < text.length) {
234
+ const c = text[i];
235
+ if (c === '"') {
236
+ let j = i + 1;
237
+ while (j < text.length && text[j] !== '"') j += text[j] === "\\" ? 2 : 1;
238
+ const top = stack[stack.length - 1];
239
+ if (top && expectKey) {
240
+ const key = JSON.parse(text.slice(i, j + 1)) as string;
241
+ if (top.has(key)) throw new RegistryFormatError(`duplicate key "${key}"`);
242
+ top.add(key);
243
+ expectKey = false;
244
+ }
245
+ i = j + 1;
246
+ continue;
247
+ }
248
+ if (c === "{") {
249
+ stack.push(new Set());
250
+ expectKey = true;
251
+ } else if (c === "[") {
252
+ stack.push(null);
253
+ } else if (c === "}" || c === "]") {
254
+ stack.pop();
255
+ } else if (c === ",") {
256
+ expectKey = stack[stack.length - 1] != null;
257
+ }
258
+ i++;
259
+ }
260
+ }
261
+
262
+ const MAX_STRING = 4096;
263
+
264
+ function fail(path: string, what: string): never {
265
+ throw new RegistryFormatError(`${path}: ${what}`);
266
+ }
267
+
268
+ function rec(v: unknown, path: string): Record<string, unknown> {
269
+ if (v === null || typeof v !== "object" || Array.isArray(v)) fail(path, "expected an object");
270
+ return v as Record<string, unknown>;
271
+ }
272
+
273
+ function arr(v: unknown, path: string): unknown[] {
274
+ if (!Array.isArray(v)) fail(path, "expected an array");
275
+ return v;
276
+ }
277
+
278
+ function str(v: unknown, path: string): string {
279
+ if (typeof v !== "string") fail(path, "expected a string");
280
+ if (v.length > MAX_STRING) fail(path, "string too long");
281
+ return v;
282
+ }
283
+
284
+ function optStr(v: unknown, path: string): string | undefined {
285
+ return v === undefined ? undefined : str(v, path);
286
+ }
287
+
288
+ function bool(v: unknown, path: string): boolean {
289
+ if (typeof v !== "boolean") fail(path, "expected a boolean");
290
+ return v;
291
+ }
292
+
293
+ /**
294
+ * Ceiling on `registry.revision`. Every write adds one, so a file claiming a
295
+ * revision near MAX_SAFE_INTEGER would push the next write past it, and every
296
+ * write after that would fail validation -- a registry nobody can record into.
297
+ * 2^48 is far beyond any real session's writes.
298
+ */
299
+ export const MAX_REGISTRY_REVISION = 2 ** 48;
300
+
301
+ function count(v: unknown, path: string): number {
302
+ if (typeof v !== "number" || !Number.isSafeInteger(v) || v < 0) {
303
+ fail(path, "expected a non-negative integer");
304
+ }
305
+ return v;
306
+ }
307
+
308
+ function revisionCount(v: unknown): number {
309
+ const n = count(v, "registry.revision");
310
+ if (n > MAX_REGISTRY_REVISION) fail("registry.revision", "is too large to keep incrementing");
311
+ return n;
312
+ }
313
+
314
+ function oneOf<T extends string>(v: unknown, allowed: readonly T[], path: string): T {
315
+ if (typeof v !== "string" || !(allowed as readonly string[]).includes(v)) {
316
+ fail(path, `expected one of ${allowed.join(", ")}`);
317
+ }
318
+ return v as T;
319
+ }
320
+
321
+ /**
322
+ * A string that becomes an object key somewhere. `__proto__` as a key is
323
+ * silently swallowed by plain-object assignment, so a result recorded under it
324
+ * would vanish; refuse it outright.
325
+ */
326
+ function keyStr(v: unknown, path: string): string {
327
+ const s = str(v, path);
328
+ if (s === "__proto__") fail(path, "reserved key");
329
+ return s;
330
+ }
331
+
332
+ function attemptId(v: unknown, path: string): AttemptId {
333
+ const s = str(v, path);
334
+ if (!isUlid(s)) fail(path, "not an attempt id");
335
+ return s;
336
+ }
337
+
338
+ function digest(v: unknown, path: string): string {
339
+ const s = str(v, path);
340
+ if (!DIGEST_RE.test(s)) fail(path, "not a sha256 hex digest");
341
+ return s;
342
+ }
343
+
344
+ /** Any JSON value, re-serialised to prove it is one. */
345
+ function jsonValue(v: unknown, path: string): unknown {
346
+ try {
347
+ return JSON.parse(canonicalJson(v));
348
+ } catch {
349
+ fail(path, "not a JSON value");
350
+ }
351
+ }
352
+
353
+ function parsePredicate(v: unknown, path: string): Predicate {
354
+ const o = rec(v, path);
355
+ const kind = oneOf(o.kind, ["exists_with_ext", "count_eq", "assertions_pass", "manual"], path);
356
+ switch (kind) {
357
+ case "exists_with_ext": {
358
+ const p: Predicate = { kind, ext: str(o.ext, `${path}.ext`) };
359
+ if (o.min_count !== undefined) p.min_count = count(o.min_count, `${path}.min_count`);
360
+ return p;
361
+ }
362
+ case "count_eq": {
363
+ const p: Predicate = { kind, count: count(o.count, `${path}.count`) };
364
+ if (o.ext !== undefined) p.ext = str(o.ext, `${path}.ext`);
365
+ return p;
366
+ }
367
+ case "assertions_pass": {
368
+ const ids = arr(o.ids, `${path}.ids`).map((x, i) => str(x, `${path}.ids[${i}]`));
369
+ // v3 §7: never vacuous.
370
+ if (ids.length === 0) fail(`${path}.ids`, "assertions_pass needs at least one id");
371
+ return { kind, ids };
372
+ }
373
+ case "manual":
374
+ return { kind };
375
+ }
376
+ }
377
+
378
+ export function parseSpec(v: unknown, path = "spec"): Spec {
379
+ const o = rec(v, path);
380
+ const t = rec(o.target, `${path}.target`);
381
+ const version = str(t.version, `${path}.target.version`);
382
+ if (version === "" || version === "unpinned") {
383
+ fail(`${path}.target.version`, "a Spec's version is always resolved");
384
+ }
385
+ const target: Spec["target"] = {
386
+ kind: oneOf(t.kind, ["workflow", "tool", "udt"], `${path}.target.kind`),
387
+ version,
388
+ };
389
+ if (t.workflow_id !== undefined)
390
+ target.workflow_id = str(t.workflow_id, `${path}.target.workflow_id`);
391
+ if (t.tool_id !== undefined) target.tool_id = str(t.tool_id, `${path}.target.tool_id`);
392
+ if (t.tool_uuid !== undefined) target.tool_uuid = str(t.tool_uuid, `${path}.target.tool_uuid`);
393
+ if (t.definition_digest !== undefined) {
394
+ target.definition_digest = digest(t.definition_digest, `${path}.target.definition_digest`);
395
+ }
396
+ const tr = rec(o.template_ref, `${path}.template_ref`);
397
+ const assertions = arr(o.assertions, `${path}.assertions`).map((a, i) => {
398
+ const ap = `${path}.assertions[${i}]`;
399
+ const ao = rec(a, ap);
400
+ return {
401
+ id: keyStr(ao.id, `${ap}.id`),
402
+ definition_digest: digest(ao.definition_digest, `${ap}.definition_digest`),
403
+ definition: jsonValue(ao.definition, `${ap}.definition`),
404
+ };
405
+ });
406
+ const predicate = parsePredicate(o.predicate, `${path}.predicate`);
407
+ if (predicate.kind === "assertions_pass") {
408
+ const known = new Set(assertions.map((a) => a.id));
409
+ for (const id of predicate.ids) {
410
+ if (!known.has(id)) fail(`${path}.predicate.ids`, `"${id}" is not a frozen assertion`);
411
+ }
412
+ }
413
+ return {
414
+ target,
415
+ server_url: str(o.server_url, `${path}.server_url`),
416
+ history_id: str(o.history_id, `${path}.history_id`),
417
+ inputs: arr(o.inputs, `${path}.inputs`).map((x, i) => {
418
+ const ip = `${path}.inputs[${i}]`;
419
+ const io = rec(x, ip);
420
+ return {
421
+ slot: str(io.slot, `${ip}.slot`),
422
+ src: oneOf(io.src, ["hda", "hdca", "ldda"], `${ip}.src`),
423
+ id: str(io.id, `${ip}.id`),
424
+ required: bool(io.required, `${ip}.required`),
425
+ };
426
+ }),
427
+ overrides: arr(o.overrides, `${path}.overrides`).map((x, i) => {
428
+ const op = `${path}.overrides[${i}]`;
429
+ const oo = rec(x, op);
430
+ return {
431
+ param: str(oo.param, `${op}.param`),
432
+ value: jsonValue(oo.value, `${op}.value`),
433
+ rationale: str(oo.rationale, `${op}.rationale`),
434
+ };
435
+ }),
436
+ template_ref: {
437
+ digest: digest(tr.digest, `${path}.template_ref.digest`),
438
+ fetched_at: str(tr.fetched_at, `${path}.template_ref.fetched_at`),
439
+ version: str(tr.version, `${path}.template_ref.version`),
440
+ },
441
+ predicate,
442
+ assertions,
443
+ };
444
+ }
445
+
446
+ function parseAttempt(v: unknown, path: string): Attempt {
447
+ const o = rec(v, path);
448
+ const b = rec(o.binding, `${path}.binding`);
449
+ const attempt: Attempt = {
450
+ attempt_id: attemptId(o.attempt_id, `${path}.attempt_id`),
451
+ kind: oneOf(o.kind, ["workflow", "tool", "udt", "upload", "rerun"], `${path}.kind`),
452
+ binding: {
453
+ step_anchor: str(b.step_anchor, `${path}.binding.step_anchor`),
454
+ bound_at: str(b.bound_at, `${path}.binding.bound_at`),
455
+ },
456
+ server_url: str(o.server_url, `${path}.server_url`),
457
+ history_id: str(o.history_id, `${path}.history_id`),
458
+ // Derived; whatever the input said is irrelevant. The store recomputes it.
459
+ handoff_eligible: false,
460
+ };
461
+
462
+ if (o.approval !== undefined) {
463
+ const p = `${path}.approval`;
464
+ const a = rec(o.approval, p);
465
+ attempt.approval = {
466
+ proposal_id: str(a.proposal_id, `${p}.proposal_id`),
467
+ spec_revision: digest(a.spec_revision, `${p}.spec_revision`),
468
+ spec_snapshot: parseSpec(a.spec_snapshot, `${p}.spec_snapshot`),
469
+ status: oneOf(a.status, ["live", "restored", "revoked"], `${p}.status`),
470
+ by: oneOf(a.by, ["user", "restored"], `${p}.by`),
471
+ at: str(a.at, `${p}.at`),
472
+ };
473
+ // Coherence, not authentication: a revision that doesn't hash the snapshot
474
+ // it sits beside was edited by hand, and there is no telling which half.
475
+ if (specRevision(attempt.approval.spec_snapshot) !== attempt.approval.spec_revision) {
476
+ fail(`${p}.spec_revision`, "does not match spec_snapshot");
477
+ }
478
+ }
479
+
480
+ if (o.reservation !== undefined) {
481
+ const p = `${path}.reservation`;
482
+ const r = rec(o.reservation, p);
483
+ attempt.reservation = {
484
+ dispatch_id: str(r.dispatch_id, `${p}.dispatch_id`),
485
+ reserved_at: str(r.reserved_at, `${p}.reserved_at`),
486
+ state: oneOf(
487
+ r.state,
488
+ ["reserved", "submitted", "submission_unknown", "released"],
489
+ `${p}.state`,
490
+ ),
491
+ };
492
+ }
493
+
494
+ if (o.submission !== undefined) {
495
+ const p = `${path}.submission`;
496
+ const s = rec(o.submission, p);
497
+ const c = rec(s.check, `${p}.check`);
498
+ const d = rec(s.dispatch_recheck, `${p}.dispatch_recheck`);
499
+ const check: NonNullable<Attempt["submission"]>["check"] = {
500
+ outcome: oneOf(
501
+ c.outcome,
502
+ [
503
+ "conformant_by_construction",
504
+ "conformant_by_reconcile",
505
+ "unchecked",
506
+ "mismatch",
507
+ "unverified",
508
+ ],
509
+ `${p}.check.outcome`,
510
+ ),
511
+ mode: oneOf(c.mode, ["off", "warn", "deny"], `${p}.check.mode`),
512
+ };
513
+ if (c.diff !== undefined) {
514
+ check.diff = arr(c.diff, `${p}.check.diff`).map((x, i) => {
515
+ const dp = `${p}.check.diff[${i}]`;
516
+ const dobj = rec(x, dp);
517
+ return {
518
+ path: str(dobj.path, `${dp}.path`),
519
+ approved: jsonValue(dobj.approved, `${dp}.approved`),
520
+ observed: jsonValue(dobj.observed, `${dp}.observed`),
521
+ };
522
+ });
523
+ }
524
+ attempt.submission = {
525
+ invocation_id: optStr(s.invocation_id, `${p}.invocation_id`),
526
+ job_id: optStr(s.job_id, `${p}.job_id`),
527
+ dataset_id: optStr(s.dataset_id, `${p}.dataset_id`),
528
+ submitted_at: str(s.submitted_at, `${p}.submitted_at`),
529
+ submitted_by: oneOf(
530
+ s.submitted_by,
531
+ ["harness", "agent", "unknown", "pre-existing"],
532
+ `${p}.submitted_by`,
533
+ ),
534
+ server_verified: bool(s.server_verified, `${p}.server_verified`),
535
+ check,
536
+ request_digest: str(s.request_digest, `${p}.request_digest`),
537
+ dispatch_recheck: {
538
+ definition_digest_ok: bool(
539
+ d.definition_digest_ok,
540
+ `${p}.dispatch_recheck.definition_digest_ok`,
541
+ ),
542
+ template_digest_ok: bool(d.template_digest_ok, `${p}.dispatch_recheck.template_digest_ok`),
543
+ at: str(d.at, `${p}.dispatch_recheck.at`),
544
+ },
545
+ };
546
+ for (const k of ["invocation_id", "job_id", "dataset_id"] as const) {
547
+ if (attempt.submission[k] === undefined) delete attempt.submission[k];
548
+ }
549
+ }
550
+
551
+ if (o.provenance !== undefined) {
552
+ const p = `${path}.provenance`;
553
+ const pv = rec(o.provenance, p);
554
+ const ref = rec(pv.ref, `${p}.ref`);
555
+ attempt.provenance = {
556
+ ref: {
557
+ kind: oneOf(ref.kind, ["dataset", "file"], `${p}.ref.kind`),
558
+ id: str(ref.id, `${p}.ref.id`),
559
+ },
560
+ digest: str(pv.digest, `${p}.digest`),
561
+ enrichment: oneOf(pv.enrichment, ["pending", "complete", "unavailable"], `${p}.enrichment`),
562
+ authority: oneOf(pv.authority, ["established", "historical"], `${p}.authority`),
563
+ };
564
+ }
565
+
566
+ if (o.evaluation !== undefined) {
567
+ const p = `${path}.evaluation`;
568
+ const e = rec(o.evaluation, p);
569
+ const assertions: Record<string, "pass" | "fail" | "inconclusive" | "excepted"> = {};
570
+ for (const [k, val] of Object.entries(rec(e.assertions, `${p}.assertions`))) {
571
+ assertions[keyStr(k, `${p}.assertions key`)] = oneOf(
572
+ val,
573
+ ["pass", "fail", "inconclusive", "excepted"],
574
+ `${p}.assertions.${k}`,
575
+ );
576
+ }
577
+ attempt.evaluation = {
578
+ execution: oneOf(e.execution, ["success", "failed", "unknown"], `${p}.execution`),
579
+ conformity: oneOf(
580
+ e.conformity,
581
+ ["conformant", "nonconformant", "unverified", "excepted"],
582
+ `${p}.conformity`,
583
+ ),
584
+ predicate_result: oneOf(
585
+ e.predicate_result,
586
+ ["pass", "fail", "unevaluable", "attested"],
587
+ `${p}.predicate_result`,
588
+ ),
589
+ assertions,
590
+ integrity: oneOf(
591
+ e.integrity,
592
+ ["ok", "unverified_identity", "render_contradiction", "effective_contradiction"],
593
+ `${p}.integrity`,
594
+ ),
595
+ authority: oneOf(e.authority, ["established", "historical"], `${p}.authority`),
596
+ evaluated_at: str(e.evaluated_at, `${p}.evaluated_at`),
597
+ };
598
+ }
599
+
600
+ if (o.rerun_of !== undefined) {
601
+ attempt.rerun_of = arr(o.rerun_of, `${path}.rerun_of`).map((x, i) =>
602
+ attemptId(x, `${path}.rerun_of[${i}]`),
603
+ );
604
+ }
605
+ return attempt;
606
+ }
607
+
608
+ function parseException(v: unknown, path: string): Exception {
609
+ const o = rec(v, path);
610
+ const x: Exception = {
611
+ id: str(o.id, `${path}.id`),
612
+ attempt_id: attemptId(o.attempt_id, `${path}.attempt_id`),
613
+ spec_revision: digest(o.spec_revision, `${path}.spec_revision`),
614
+ scope: oneOf(
615
+ o.scope,
616
+ ["submission_check", "evidence_gate", "manual_attestation"],
617
+ `${path}.scope`,
618
+ ),
619
+ by: oneOf(o.by, ["user", "restored"], `${path}.by`),
620
+ at: str(o.at, `${path}.at`),
621
+ reason: str(o.reason, `${path}.reason`),
622
+ };
623
+ if (o.assertion_id !== undefined) {
624
+ if (x.scope !== "evidence_gate")
625
+ fail(`${path}.assertion_id`, "only an evidence_gate names one");
626
+ x.assertion_id = keyStr(o.assertion_id, `${path}.assertion_id`);
627
+ }
628
+ return x;
629
+ }
630
+
631
+ function parseAttemptMap(v: unknown, path: string, seen: Set<string>): Record<AttemptId, Attempt> {
632
+ const out: Record<AttemptId, Attempt> = {};
633
+ for (const [key, value] of Object.entries(rec(v, path))) {
634
+ const attempt = parseAttempt(value, `${path}.${key}`);
635
+ if (attempt.attempt_id !== key) fail(`${path}.${key}`, "keyed under a different id");
636
+ if (seen.has(key)) fail(`${path}.${key}`, "duplicate attempt id");
637
+ seen.add(key);
638
+ out[key] = attempt;
639
+ }
640
+ return out;
641
+ }
642
+
643
+ /**
644
+ * Parse a current-version registry document. Throws `RegistryFormatError` on
645
+ * anything malformed; returns a fresh object holding only known fields.
646
+ */
647
+ export function parseRegistry(v: unknown): Registry {
648
+ const o = rec(v, "registry");
649
+ if (o.version !== CURRENT_REGISTRY_VERSION) fail("registry.version", "expected 3");
650
+ const seen = new Set<string>();
651
+ const attempts = parseAttemptMap(o.attempts, "registry.attempts", seen);
652
+ const quarantine =
653
+ o.quarantine === undefined
654
+ ? undefined
655
+ : parseAttemptMap(o.quarantine, "registry.quarantine", seen);
656
+ const exceptions = arr(o.exceptions, "registry.exceptions").map((x, i) =>
657
+ parseException(x, `registry.exceptions[${i}]`),
658
+ );
659
+ const exceptionIds = new Set<string>();
660
+ for (const ex of exceptions) {
661
+ if (exceptionIds.has(ex.id)) fail("registry.exceptions", `duplicate exception id "${ex.id}"`);
662
+ exceptionIds.add(ex.id);
663
+ }
664
+ const sup = rec(o.supervision, "registry.supervision");
665
+ const supervision: Registry["supervision"] = {
666
+ active_at_shutdown: arr(sup.active_at_shutdown, "registry.supervision.active_at_shutdown").map(
667
+ (x, i) => attemptId(x, `registry.supervision.active_at_shutdown[${i}]`),
668
+ ),
669
+ };
670
+ if (sup.last_reconcile_at !== undefined) {
671
+ supervision.last_reconcile_at = str(
672
+ sup.last_reconcile_at,
673
+ "registry.supervision.last_reconcile_at",
674
+ );
675
+ }
676
+ const registry: Registry = {
677
+ version: CURRENT_REGISTRY_VERSION,
678
+ revision: revisionCount(o.revision),
679
+ writer_token: str(o.writer_token, "registry.writer_token"),
680
+ session_sig: str(o.session_sig, "registry.session_sig"),
681
+ analysis_id: str(o.analysis_id, "registry.analysis_id"),
682
+ server_url: str(o.server_url, "registry.server_url"),
683
+ attempts,
684
+ exceptions,
685
+ supervision,
686
+ };
687
+ if (quarantine !== undefined) registry.quarantine = quarantine;
688
+ return registry;
689
+ }
690
+
691
+ // ─────────────────────────────────────────────────────────────────────────────
692
+ // Migrations
693
+ // ─────────────────────────────────────────────────────────────────────────────
694
+
695
+ /**
696
+ * Upgrades keyed by the version they read: `MIGRATIONS[3]` would turn a v3
697
+ * document into v4. Empty while v3 is the only version. A migrated document is
698
+ * always an import -- its signature was over the old shape -- so a migration
699
+ * never has to preserve anything the import rule downgrades anyway.
700
+ */
701
+ export const MIGRATIONS: Readonly<
702
+ Record<number, (doc: Record<string, unknown>) => Record<string, unknown>>
703
+ > = {};
704
+
705
+ /** Bring a parsed document up to the current version, or throw. */
706
+ export function migrateToCurrent(
707
+ doc: unknown,
708
+ migrations: Readonly<
709
+ Record<number, (d: Record<string, unknown>) => Record<string, unknown>>
710
+ > = MIGRATIONS,
711
+ ): unknown {
712
+ let current = rec(doc, "registry");
713
+ for (let steps = 0; steps < 64; steps++) {
714
+ const version = current.version;
715
+ if (version === CURRENT_REGISTRY_VERSION) return current;
716
+ if (typeof version !== "number" || !Number.isSafeInteger(version)) {
717
+ fail("registry.version", "missing or not an integer");
718
+ }
719
+ if (version > CURRENT_REGISTRY_VERSION) {
720
+ fail("registry.version", `written by a newer Orbit (version ${version})`);
721
+ }
722
+ const step = migrations[version];
723
+ if (!step) fail("registry.version", `no migration from version ${version}`);
724
+ current = rec(step(current), "registry");
725
+ if (current.version === version) fail("registry.version", "migration did not advance");
726
+ }
727
+ fail("registry.version", "migration chain too long");
728
+ }
729
+
730
+ /** Normalise a Galaxy server url for comparison: scheme defaulted, no trailing slash, lowercase. */
731
+ export function normalizeServerUrl(url: string): string {
732
+ const trimmed = url.trim().replace(/\/+$/, "").toLowerCase();
733
+ if (trimmed === "") return "";
734
+ return /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
735
+ }