@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,210 @@
1
+ import { validateTeamSpec } from "./validate";
2
+ import { parseCriticResponse } from "./critic-parser";
3
+ import type { DispatchDeps, TeamResult, TeamSpec, TeamTurn } from "./types";
4
+
5
+ export interface DispatchOptions {
6
+ tokenCeiling?: number; // default 300_000
7
+ }
8
+
9
+ export type OnTurnUpdate = (snapshot: {
10
+ round: number;
11
+ max_rounds: number;
12
+ current_role: string;
13
+ turns: TeamTurn[];
14
+ }) => void;
15
+
16
+ const DEFAULT_TOKEN_CEILING = 300_000;
17
+
18
+ /**
19
+ * Run the two-role critic loop to completion.
20
+ * `deps.runRoleTurn` is injected so this function is unit-testable without
21
+ * a real Pi runtime.
22
+ */
23
+ export async function runTeamDispatch(
24
+ spec: TeamSpec,
25
+ deps: DispatchDeps,
26
+ signal: AbortSignal,
27
+ onTurn?: OnTurnUpdate,
28
+ options: DispatchOptions = {},
29
+ ): Promise<TeamResult> {
30
+ validateTeamSpec(spec);
31
+
32
+ const tokenCeiling = options.tokenCeiling ?? DEFAULT_TOKEN_CEILING;
33
+ const maxRounds = spec.max_rounds ?? 5;
34
+ const [proposer, critic] = spec.roles;
35
+ const transcript: TeamTurn[] = [];
36
+ let totalUsage = { input_tokens: 0, output_tokens: 0 };
37
+ let currentProposal = "";
38
+ let currentCritique: string | null = null;
39
+ let round = 0;
40
+
41
+ try {
42
+ for (round = 1; round <= maxRounds; round++) {
43
+ // --- Proposer turn ---
44
+ if (signal.aborted) return aborted(transcript, round, currentProposal, totalUsage);
45
+ const proposerInput = renderProposerInput(spec.description, currentCritique);
46
+ const proposerPreamble = buildPreamble(spec, proposer, "proposer");
47
+ const proposerResult = await deps.runRoleTurn(
48
+ proposer,
49
+ proposerPreamble,
50
+ proposerInput,
51
+ signal,
52
+ );
53
+ currentProposal = proposerResult.content;
54
+ transcript.push({
55
+ round,
56
+ role: proposer.name,
57
+ content: currentProposal,
58
+ });
59
+ totalUsage = add(totalUsage, proposerResult.usage);
60
+ onTurn?.({ round, max_rounds: maxRounds, current_role: proposer.name, turns: transcript });
61
+
62
+ if (exceedsCeiling(totalUsage, tokenCeiling)) {
63
+ return budgetExhausted(transcript, round, currentProposal, totalUsage);
64
+ }
65
+
66
+ // --- Critic turn ---
67
+ if (signal.aborted) return aborted(transcript, round, currentProposal, totalUsage);
68
+ const criticInput = renderCriticInput(spec.description, currentProposal);
69
+ const criticPreamble = buildPreamble(spec, critic, "critic");
70
+ const criticResult = await deps.runRoleTurn(critic, criticPreamble, criticInput, signal);
71
+ const verdict = parseCriticResponse(criticResult.content);
72
+ transcript.push({
73
+ round,
74
+ role: critic.name,
75
+ content: criticResult.content,
76
+ approved: verdict.approved,
77
+ });
78
+ totalUsage = add(totalUsage, criticResult.usage);
79
+ onTurn?.({ round, max_rounds: maxRounds, current_role: critic.name, turns: transcript });
80
+
81
+ if (verdict.approved) {
82
+ return {
83
+ converged: true,
84
+ rounds: round,
85
+ final_output: currentProposal,
86
+ transcript,
87
+ usage: totalUsage,
88
+ };
89
+ }
90
+ if (exceedsCeiling(totalUsage, tokenCeiling)) {
91
+ return budgetExhausted(transcript, round, currentProposal, totalUsage);
92
+ }
93
+ currentCritique = verdict.critique;
94
+ }
95
+
96
+ return {
97
+ converged: false,
98
+ rounds: maxRounds,
99
+ final_output: currentProposal,
100
+ transcript,
101
+ usage: totalUsage,
102
+ };
103
+ } catch (err) {
104
+ if (isAbortError(err) || signal.aborted) {
105
+ return aborted(transcript, round, currentProposal, totalUsage);
106
+ }
107
+ return {
108
+ converged: false,
109
+ rounds: round,
110
+ final_output: currentProposal,
111
+ transcript,
112
+ usage: totalUsage,
113
+ error: err instanceof Error ? err.message : String(err),
114
+ };
115
+ }
116
+ }
117
+
118
+ // --- helpers ------------------------------------------------------------
119
+
120
+ function renderProposerInput(description: string, priorCritique: string | null): string {
121
+ if (priorCritique === null) {
122
+ return `Team task: ${description}\n\nProduce your first proposal.`;
123
+ }
124
+ return (
125
+ `Team task: ${description}\n\n` +
126
+ `The critic raised the following issues with your previous proposal:\n${priorCritique}\n\n` +
127
+ `Produce a revised proposal that addresses them.`
128
+ );
129
+ }
130
+
131
+ function renderCriticInput(description: string, proposal: string): string {
132
+ return (
133
+ `Team task: ${description}\n\n` +
134
+ `Proposer output:\n${proposal}\n\n` +
135
+ `Critique the proposal. End your response with a JSON line of shape ` +
136
+ `{"approved": boolean, "critique": string}.`
137
+ );
138
+ }
139
+
140
+ function buildPreamble(
141
+ spec: TeamSpec,
142
+ role: { system_prompt: string },
143
+ kind: "proposer" | "critic",
144
+ ): string {
145
+ const teamContext =
146
+ `You are one role in a two-agent team collaborating on the task: "${spec.description}". ` +
147
+ `Respond only from your role's perspective.`;
148
+ const criticContract =
149
+ kind === "critic"
150
+ ? ` When you have finished critiquing, finish your response with a JSON line: ` +
151
+ `{"approved": boolean, "critique": "one paragraph"}.`
152
+ : "";
153
+ return `${teamContext}${criticContract}\n\n${role.system_prompt}`;
154
+ }
155
+
156
+ function add(
157
+ a: { input_tokens: number; output_tokens: number },
158
+ b: { input_tokens: number; output_tokens: number },
159
+ ) {
160
+ return {
161
+ input_tokens: a.input_tokens + b.input_tokens,
162
+ output_tokens: a.output_tokens + b.output_tokens,
163
+ };
164
+ }
165
+
166
+ function exceedsCeiling(
167
+ u: { input_tokens: number; output_tokens: number },
168
+ ceiling: number,
169
+ ): boolean {
170
+ return u.input_tokens + u.output_tokens > ceiling;
171
+ }
172
+
173
+ function aborted(
174
+ transcript: TeamTurn[],
175
+ round: number,
176
+ finalOutput: string,
177
+ usage: { input_tokens: number; output_tokens: number },
178
+ ): TeamResult {
179
+ return {
180
+ converged: false,
181
+ aborted: true,
182
+ rounds: round,
183
+ final_output: finalOutput,
184
+ transcript,
185
+ usage,
186
+ };
187
+ }
188
+
189
+ function budgetExhausted(
190
+ transcript: TeamTurn[],
191
+ round: number,
192
+ finalOutput: string,
193
+ usage: { input_tokens: number; output_tokens: number },
194
+ ): TeamResult {
195
+ return {
196
+ converged: false,
197
+ budget_exhausted: true,
198
+ rounds: round,
199
+ final_output: finalOutput,
200
+ transcript,
201
+ usage,
202
+ };
203
+ }
204
+
205
+ function isAbortError(err: unknown): boolean {
206
+ return (
207
+ err instanceof Error &&
208
+ (err.name === "AbortError" || err.message.toLowerCase().includes("abort"))
209
+ );
210
+ }
@@ -0,0 +1,22 @@
1
+ import { loadConfig } from "../config";
2
+ import { readEnv } from "../../../shared/orbit-env.js";
3
+
4
+ /**
5
+ * Whether the experimental team_dispatch tool is opted in.
6
+ *
7
+ * Resolution order (env wins so a developer can flip it for one session
8
+ * without touching ~/.orbit/config.json):
9
+ * 1. LOOM_TEAM_DISPATCH env var -- "1" -> on, "0" -> off (explicit
10
+ * override of an on-config), anything else -> defer to config.
11
+ * 2. config.experiments.teamDispatch -- boolean.
12
+ * 3. Default: off.
13
+ *
14
+ * Intended to be called once at extension boot, not in a hot path --
15
+ * each call hits loadConfig() / disk.
16
+ */
17
+ export function isTeamDispatchEnabled(): boolean {
18
+ const env = readEnv("TEAM_DISPATCH");
19
+ if (env === "1") return true;
20
+ if (env === "0") return false;
21
+ return loadConfig().experiments?.teamDispatch === true;
22
+ }
@@ -0,0 +1,187 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { Type } from "@sinclair/typebox";
3
+ import { Text } from "@earendil-works/pi-tui";
4
+ // pi 0.80 moved the global API to /compat. The extension loader aliases the
5
+ // root at runtime, but the typecheck resolves the published types, so import
6
+ // the real path.
7
+ import { completeSimple } from "@earendil-works/pi-ai/compat";
8
+ import type { Model } from "@earendil-works/pi-ai/compat";
9
+ import { runTeamDispatch } from "./dispatcher";
10
+ import { modelScriptRefusal } from "../model-script";
11
+ import { validateTeamSpec } from "./validate";
12
+ import type { DispatchDeps, RoleTurnResult, TeamSpec, RoleSpec } from "./types";
13
+ import { TEAM_DISPATCH_KIND } from "../../../shared/team-dispatch-contract.js";
14
+ import type { TeamDispatchDetails } from "../../../shared/team-dispatch-contract.js";
15
+
16
+ const RoleSchema = Type.Object({
17
+ name: Type.String({ minLength: 1 }),
18
+ system_prompt: Type.String({ minLength: 1 }),
19
+ model: Type.Optional(Type.String()),
20
+ });
21
+
22
+ const TeamSpecSchema = Type.Object({
23
+ description: Type.String({ minLength: 1 }),
24
+ roles: Type.Array(RoleSchema, { minItems: 2, maxItems: 2 }),
25
+ max_rounds: Type.Optional(Type.Integer({ minimum: 1, maximum: 20 })),
26
+ model: Type.Optional(Type.String()),
27
+ });
28
+
29
+ export function registerTeamTools(pi: ExtensionAPI): void {
30
+ pi.registerTool({
31
+ name: "team_dispatch",
32
+ label: "Dispatch specialist team",
33
+ description:
34
+ "Run a two-role critic loop (proposer → critic) to converge on a result. " +
35
+ "Use when the user asks for a 'team' to handle a bounded sub-task such as " +
36
+ "literature review or cross-checking findings. Each role is a pure-reasoning " +
37
+ "LLM call (no tools); gather any external data with your own tools first and " +
38
+ "include it in the `description`. Returns the converged result; persist useful " +
39
+ "output by editing notebook.md when the researcher wants it retained.",
40
+ parameters: TeamSpecSchema,
41
+ async execute(_toolCallId, params, signal, onUpdate, ctx) {
42
+ const spec = params as TeamSpec;
43
+ const scripted = modelScriptRefusal("team_dispatch");
44
+ if (scripted) return errorResult(new Error(scripted));
45
+
46
+ // 1. Spec validation (fail fast).
47
+ try {
48
+ validateTeamSpec(spec);
49
+ } catch (err) {
50
+ return errorResult(err);
51
+ }
52
+
53
+ // 2. Build the runRoleTurn binding over pi-ai.completeSimple.
54
+ const deps: DispatchDeps = {
55
+ runRoleTurn: async (
56
+ role: RoleSpec,
57
+ preamble,
58
+ userMessage,
59
+ runSignal,
60
+ ): Promise<RoleTurnResult> => {
61
+ const model = resolveModel(ctx, role.model ?? spec.model);
62
+ if (!model) {
63
+ throw new Error(
64
+ `No model available: neither role "${role.name}" nor the team spec nor the session provides one.`,
65
+ );
66
+ }
67
+ const msg = await completeSimple(
68
+ model,
69
+ {
70
+ systemPrompt: preamble,
71
+ messages: [{ role: "user", content: userMessage, timestamp: Date.now() }],
72
+ },
73
+ { signal: runSignal },
74
+ );
75
+ const content = extractText(msg);
76
+ // Count cache tokens too so the budget ceiling is honest on
77
+ // providers that charge for cache reads/writes (Anthropic).
78
+ const cacheRead = msg.usage.cacheRead ?? 0;
79
+ const cacheWrite = msg.usage.cacheWrite ?? 0;
80
+ return {
81
+ content,
82
+ usage: {
83
+ input_tokens: msg.usage.input + cacheRead + cacheWrite,
84
+ output_tokens: msg.usage.output,
85
+ },
86
+ };
87
+ },
88
+ };
89
+
90
+ // 3. Drive the loop; stream progress to the tool card.
91
+ const abort = signal ?? new AbortController().signal;
92
+ const result = await runTeamDispatch(spec, deps, abort, (snapshot) => {
93
+ const details: TeamDispatchDetails = {
94
+ kind: TEAM_DISPATCH_KIND,
95
+ spec: {
96
+ description: spec.description,
97
+ roles: spec.roles.map((r) => ({ name: r.name, model: r.model ?? spec.model })),
98
+ },
99
+ turns: snapshot.turns,
100
+ summary: `Round ${snapshot.round}/${snapshot.max_rounds} — ${snapshot.current_role} responding…`,
101
+ };
102
+ onUpdate?.({
103
+ content: [],
104
+ details,
105
+ });
106
+ });
107
+
108
+ // 4. Final tool-card summary.
109
+ const finalSummary = result.converged
110
+ ? `Team converged in ${result.rounds} round${result.rounds === 1 ? "" : "s"}`
111
+ : result.aborted
112
+ ? `Team aborted after ${result.rounds} round${result.rounds === 1 ? "" : "s"}`
113
+ : result.budget_exhausted
114
+ ? `Team halted on token budget after ${result.rounds} round${result.rounds === 1 ? "" : "s"}`
115
+ : result.error
116
+ ? `Team errored after ${result.rounds} round${result.rounds === 1 ? "" : "s"}: ${result.error}`
117
+ : `Team did not converge (${result.rounds}/${spec.max_rounds ?? 5} rounds — best-so-far returned)`;
118
+
119
+ const finalDetails: TeamDispatchDetails = {
120
+ kind: TEAM_DISPATCH_KIND,
121
+ spec: {
122
+ description: spec.description,
123
+ roles: spec.roles.map((r) => ({ name: r.name, model: r.model ?? spec.model })),
124
+ },
125
+ turns: result.transcript,
126
+ summary: finalSummary,
127
+ };
128
+ return {
129
+ content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }],
130
+ details: finalDetails,
131
+ };
132
+ },
133
+ renderResult: (result) => {
134
+ const d = result.details as { summary?: string } | undefined;
135
+ return new Text(d?.summary ?? "team_dispatch finished");
136
+ },
137
+ });
138
+ }
139
+
140
+ // --- helpers ------------------------------------------------------------
141
+
142
+ /**
143
+ * Resolve a Model<any> from a "provider:modelId" string, a bare Anthropic
144
+ * model id, or by falling back to the session model.
145
+ */
146
+ function resolveModel(
147
+ ctx: ExtensionContext,
148
+ modelSpec: string | undefined,
149
+ ): Model<any> | undefined {
150
+ if (modelSpec && modelSpec.trim().length > 0) {
151
+ const colon = modelSpec.indexOf(":");
152
+ const provider = colon >= 0 ? modelSpec.slice(0, colon) : "anthropic";
153
+ const modelId = colon >= 0 ? modelSpec.slice(colon + 1) : modelSpec;
154
+ const found = ctx.modelRegistry.find(provider, modelId);
155
+ if (!found) {
156
+ throw new Error(
157
+ `Unknown model "${modelSpec}" (provider="${provider}", modelId="${modelId}"). ` +
158
+ `Check ctx.modelRegistry, or omit the model field to use the session default.`,
159
+ );
160
+ }
161
+ return found;
162
+ }
163
+ return ctx.model;
164
+ }
165
+
166
+ /** Flatten an AssistantMessage's text chunks into a single string. */
167
+ function extractText(msg: { content: Array<{ type: string; text?: string }> }): string {
168
+ return msg.content
169
+ .filter((c) => c.type === "text" && typeof c.text === "string")
170
+ .map((c) => c.text as string)
171
+ .join("");
172
+ }
173
+
174
+ function errorResult(err: unknown) {
175
+ const message = err instanceof Error ? err.message : String(err);
176
+ const details: TeamDispatchDetails = {
177
+ kind: TEAM_DISPATCH_KIND,
178
+ error: message,
179
+ summary: `team_dispatch failed: ${message}`,
180
+ };
181
+ return {
182
+ content: [
183
+ { type: "text" as const, text: JSON.stringify({ ok: false, error: message }, null, 2) },
184
+ ],
185
+ details,
186
+ };
187
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Public types for the team_dispatch feature.
3
+ * See docs/superpowers/specs/2026-04-17-multi-agent-dispatch-design.md.
4
+ */
5
+
6
+ export interface TeamSpec {
7
+ description: string;
8
+ roles: RoleSpec[];
9
+ max_rounds?: number;
10
+ model?: string;
11
+ }
12
+
13
+ export interface RoleSpec {
14
+ name: string;
15
+ system_prompt: string;
16
+ model?: string;
17
+ }
18
+
19
+ export interface TeamResult {
20
+ converged: boolean;
21
+ rounds: number;
22
+ final_output: string;
23
+ transcript: TeamTurn[];
24
+ usage: { input_tokens: number; output_tokens: number };
25
+ aborted?: boolean;
26
+ budget_exhausted?: boolean;
27
+ error?: string;
28
+ }
29
+
30
+ export interface TeamTurn {
31
+ round: number;
32
+ role: string;
33
+ content: string;
34
+ approved?: boolean;
35
+ }
36
+
37
+ /**
38
+ * Side-effect surface the dispatcher needs.
39
+ * Injected so the dispatcher is testable without a real LLM runtime.
40
+ *
41
+ * MVP: roles are pure-reasoning — each turn is a single LLM call with no
42
+ * tool access. Main agent pre-gathers any external data and includes it
43
+ * in TeamSpec.description before dispatching.
44
+ */
45
+ export interface DispatchDeps {
46
+ runRoleTurn: (
47
+ role: RoleSpec,
48
+ systemPreamble: string,
49
+ userMessage: string,
50
+ signal: AbortSignal,
51
+ ) => Promise<RoleTurnResult>;
52
+ }
53
+
54
+ export interface RoleTurnResult {
55
+ content: string;
56
+ usage: { input_tokens: number; output_tokens: number };
57
+ }
@@ -0,0 +1,42 @@
1
+ import type { TeamSpec } from "./types";
2
+
3
+ export class ValidationError extends Error {
4
+ constructor(message: string) {
5
+ super(message);
6
+ this.name = "ValidationError";
7
+ }
8
+ }
9
+
10
+ export function validateTeamSpec(spec: TeamSpec): void {
11
+ if (!spec.description || spec.description.trim().length === 0) {
12
+ throw new ValidationError("TeamSpec.description must be a non-empty string");
13
+ }
14
+
15
+ const roles = spec.roles;
16
+ if (!Array.isArray(roles) || roles.length < 2) {
17
+ throw new ValidationError("TeamSpec.roles must contain at least 2 roles");
18
+ }
19
+ if (roles.length > 2) {
20
+ throw new ValidationError(
21
+ "TeamSpec.roles contains more than 2 roles; >2 roles is not implemented in this MVP",
22
+ );
23
+ }
24
+
25
+ const seen = new Set<string>();
26
+ for (const role of roles) {
27
+ if (typeof role.name !== "string" || role.name.trim().length === 0) {
28
+ throw new ValidationError("Every RoleSpec must have a non-empty name");
29
+ }
30
+ if (seen.has(role.name)) {
31
+ throw new ValidationError(`RoleSpec.name must be unique; duplicate: "${role.name}"`);
32
+ }
33
+ seen.add(role.name);
34
+ }
35
+
36
+ const max = spec.max_rounds;
37
+ if (max !== undefined) {
38
+ if (!Number.isInteger(max) || max < 1 || max > 20) {
39
+ throw new ValidationError("TeamSpec.max_rounds must be an integer in [1, 20]");
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * /tester-id -- the get-or-set counterpart to buildTesterIdBlock (#189/#191).
3
+ *
4
+ * With no argument it prints the current tester ID; with an argument it sets it.
5
+ *
6
+ * Beta onboarding asks testers to put a `testerId` in ~/.orbit/config.json. That
7
+ * file is a credential store, so the agent's edit/write to it is floored by the
8
+ * exec-guard -- a hard deny on low-capability models and an unreachable
9
+ * read-then-edit on every tier once #194 landed (issue #222). This gives the
10
+ * user a deterministic, model-independent path that sets ONLY the testerId key.
11
+ *
12
+ * It deliberately reads/echoes ONLY the testerId field (a non-secret tester code
13
+ * like "orbit-007", which already passes #194 redaction), never any other config
14
+ * value, so it cannot become a way to surface the API keys that #183/#194 lock
15
+ * down.
16
+ */
17
+
18
+ import fs from "node:fs";
19
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
20
+ import { getConfigPath, loadConfig, saveConfig } from "./config.js";
21
+ import { readEnv } from "../../shared/orbit-env.js";
22
+
23
+ // Tester codes are opaque, non-secret strings (e.g. "orbit-007"). Constrain the
24
+ // shape so neither a fat-fingered user nor a pasted blob can smuggle a newline,
25
+ // JSON, or a giant value into the key: first char alphanumeric, then a few safe
26
+ // separators, capped length.
27
+ const TESTER_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
28
+
29
+ export type ValidateResult = { ok: true; id: string } | { ok: false; error: string };
30
+
31
+ export function validateTesterId(raw: string): ValidateResult {
32
+ const id = (raw ?? "").trim();
33
+ if (!id) {
34
+ return { ok: false, error: "Usage: /tester-id <id> (e.g. /tester-id orbit-007)" };
35
+ }
36
+ if (!TESTER_ID_RE.test(id)) {
37
+ return {
38
+ ok: false,
39
+ error:
40
+ "Tester ID must be 1-64 characters: letters, digits, and . _ - only, " +
41
+ "starting with a letter or digit (e.g. orbit-007).",
42
+ };
43
+ }
44
+ return { ok: true, id };
45
+ }
46
+
47
+ /**
48
+ * The currently-effective tester ID and where it came from. Mirrors
49
+ * buildTesterIdBlock's precedence (config wins over the env override). Reads
50
+ * ONLY testerId -- never another config field.
51
+ */
52
+ export function getCurrentTesterId(): { id: string; source: "config" | "env" } | null {
53
+ const fromConfig = loadConfig().testerId;
54
+ if (fromConfig) return { id: fromConfig, source: "config" };
55
+ const fromEnv = readEnv("TESTER_ID");
56
+ if (fromEnv) return { id: fromEnv, source: "env" };
57
+ return null;
58
+ }
59
+
60
+ /**
61
+ * Set ONLY the testerId key. Loads the full config so existing fields (API keys
62
+ * included) ride straight back to disk unchanged, mutates the single key, and
63
+ * persists via the shared atomic writer. No other field is read out, returned,
64
+ * or echoed.
65
+ *
66
+ * Fails closed: loadConfig() silently returns {} when an existing config can't
67
+ * be read or parsed, so writing that back would wipe the user's stored API
68
+ * keys. We refuse rather than clobber -- a genuinely absent file is still fine
69
+ * to create. A save failure is rewrapped in a fixed message so the raw error
70
+ * (whatever it carries) can never be surfaced through this command.
71
+ */
72
+ export function setTesterId(id: string): void {
73
+ const configPath = getConfigPath();
74
+ if (fs.existsSync(configPath)) {
75
+ try {
76
+ JSON.parse(fs.readFileSync(configPath, "utf-8"));
77
+ } catch (err) {
78
+ throw new Error(
79
+ "~/.orbit/config.json couldn't be read, so it wasn't changed -- fix or remove the file and try again.",
80
+ { cause: err },
81
+ );
82
+ }
83
+ }
84
+ const cfg = loadConfig();
85
+ cfg.testerId = id;
86
+ try {
87
+ saveConfig(cfg);
88
+ } catch (err) {
89
+ throw new Error(
90
+ "Couldn't write ~/.orbit/config.json -- check file permissions and free space, then try again.",
91
+ { cause: err },
92
+ );
93
+ }
94
+ }
95
+
96
+ export function registerTesterIdCommand(pi: ExtensionAPI): void {
97
+ pi.registerCommand("tester-id", {
98
+ description:
99
+ "Show or set your Orbit beta tester ID (writes only testerId to ~/.orbit/config.json).",
100
+ handler: async (args: string | undefined, ctx: ExtensionContext) => {
101
+ const raw = (args ?? "").trim();
102
+
103
+ if (!raw) {
104
+ const current = getCurrentTesterId();
105
+ if (!current) {
106
+ ctx.ui.notify(
107
+ "No tester ID set. Set one with /tester-id <id> (e.g. /tester-id orbit-007).",
108
+ "info",
109
+ );
110
+ return;
111
+ }
112
+ const suffix = current.source === "env" ? " (from LOOM_TESTER_ID)" : "";
113
+ ctx.ui.notify(`Tester ID: ${current.id}${suffix}`, "info");
114
+ return;
115
+ }
116
+
117
+ const result = validateTesterId(raw);
118
+ if (!result.ok) {
119
+ ctx.ui.notify(result.error, "error");
120
+ return;
121
+ }
122
+ try {
123
+ setTesterId(result.id);
124
+ } catch (err) {
125
+ // setTesterId only throws messages it authored -- never a raw error
126
+ // that could carry config contents -- so showing it is safe.
127
+ ctx.ui.notify(err instanceof Error ? err.message : "Failed to save tester ID.", "error");
128
+ return;
129
+ }
130
+ ctx.ui.notify(`Tester ID set to ${result.id}.`, "info");
131
+ },
132
+ });
133
+ }