@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,265 @@
1
+ /**
2
+ * Session state — connection, notebook path, file watcher, listeners.
3
+ *
4
+ * The notebook (notebook.md in the session cwd, or the record store a shell
5
+ * installed) is the durable record. State here is just enough to wire the
6
+ * record watcher, track Galaxy connection, and route notebook changes to UI
7
+ * listeners.
8
+ */
9
+
10
+ import type { AnalystState } from "./types";
11
+ import { getDefaultNotebookPath } from "./notebook-writer";
12
+ import { commitFile, ensureGitRepo } from "./git";
13
+ import { appendActivityEvent, loadActivityLog, resetActivity } from "./activity";
14
+ import { installedRecordStore, recordStore } from "./record-store";
15
+ import * as path from "path";
16
+
17
+ // ─────────────────────────────────────────────────────────────────────────────
18
+ // Module state
19
+ // ─────────────────────────────────────────────────────────────────────────────
20
+
21
+ let state: AnalystState = {
22
+ currentHistoryId: null,
23
+ notebookPath: null,
24
+ notebookLoaded: false,
25
+ currentStepAnchor: null,
26
+ };
27
+
28
+ export function getState(): AnalystState {
29
+ return state;
30
+ }
31
+
32
+ // Notebook widget visibility mode:
33
+ // "auto" - not shown yet; auto-shows on the next notebook change (default)
34
+ // "open" - currently shown; stays in sync as the notebook changes
35
+ // "hidden" - user closed it via /notebook; stays closed (no auto-reopen)
36
+ // until they reopen it
37
+ type NotebookWidgetMode = "auto" | "open" | "hidden";
38
+ let notebookWidgetMode: NotebookWidgetMode = "auto";
39
+
40
+ export function getNotebookWidgetMode(): NotebookWidgetMode {
41
+ return notebookWidgetMode;
42
+ }
43
+
44
+ export function setNotebookWidgetMode(mode: NotebookWidgetMode): void {
45
+ notebookWidgetMode = mode;
46
+ }
47
+
48
+ export function resetState(): void {
49
+ stopWatchingNotebook();
50
+ notebookWidgetMode = "auto";
51
+ lastEmittedNotebookContent = null;
52
+ lastInspectedFingerprint = null;
53
+ state = {
54
+ currentHistoryId: null,
55
+ notebookPath: null,
56
+ notebookLoaded: false,
57
+ currentStepAnchor: null,
58
+ };
59
+ }
60
+
61
+ // ─────────────────────────────────────────────────────────────────────────────
62
+ // Notebook change listeners
63
+ // ─────────────────────────────────────────────────────────────────────────────
64
+
65
+ type NotebookChangeListener = (markdown: string) => void;
66
+ const notebookChangeListeners: NotebookChangeListener[] = [];
67
+
68
+ // Content last handed to listeners, plus the record version we last
69
+ // inspected. Both feed reemitNotebookIfChanged() so a re-sync
70
+ // trigger only emits when notebook.md actually changed.
71
+ let lastEmittedNotebookContent: string | null = null;
72
+ let lastInspectedFingerprint: string | null = null;
73
+
74
+ /** Register a callback that fires on every notebook write. Returns unsubscribe. */
75
+ export function onNotebookChange(listener: NotebookChangeListener): () => void {
76
+ notebookChangeListeners.push(listener);
77
+ return () => {
78
+ const idx = notebookChangeListeners.indexOf(listener);
79
+ if (idx >= 0) notebookChangeListeners.splice(idx, 1);
80
+ };
81
+ }
82
+
83
+ function notifyNotebookChange(markdown: string): void {
84
+ lastEmittedNotebookContent = markdown;
85
+ for (const listener of notebookChangeListeners) {
86
+ try {
87
+ listener(markdown);
88
+ } catch (err) {
89
+ // Isolate subscribers: one throwing listener must not starve the others
90
+ // or break the caller (e.g. the tool_execution_end hook, which is no
91
+ // longer wrapped the way the watcher path is). #253
92
+ console.error("notebook change listener failed:", err);
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Re-read the record and emit a change if its content differs from what was
99
+ * last emitted; returns whether it emitted.
100
+ *
101
+ * The chokidar watcher tracks a single file path and can miss a bash write
102
+ * that replaces the inode (an atomic temp-and-rename save, e.g. `sed -i` or an
103
+ * editor) or one that races its awaitWriteFinish window, leaving the Notebook
104
+ * panel stale until the next `/notebook`; under the page backend it is the only
105
+ * way an out-of-band page edit is seen at all. The tool_execution_end hook calls
106
+ * this after every tool so the panel re-syncs. The store's cheap version check
107
+ * skips the read when the record is untouched, and a content compare suppresses
108
+ * emits when nothing actually changed, so calling this on every tool end is not
109
+ * churn. #253
110
+ */
111
+ export async function reemitNotebookIfChanged(): Promise<boolean> {
112
+ const key = state.notebookPath;
113
+ if (!key) return false;
114
+ const store = recordStore(key);
115
+
116
+ const version = await store.stat();
117
+ // Missing/unreadable right now (e.g. mid-rename): the watcher and the next
118
+ // real write recover. Don't advance the fingerprint so the follow-up is seen.
119
+ if (!version || version === lastInspectedFingerprint) return false;
120
+
121
+ let content: string;
122
+ try {
123
+ ({ content } = await store.read());
124
+ } catch {
125
+ return false;
126
+ }
127
+ lastInspectedFingerprint = version;
128
+
129
+ // mtime/size moved but the bytes are identical (e.g. a rewrite) -> no churn.
130
+ if (content === lastEmittedNotebookContent) return false;
131
+
132
+ notifyNotebookChange(content);
133
+ return true;
134
+ }
135
+
136
+ // ─────────────────────────────────────────────────────────────────────────────
137
+ // Record watcher -- refresh UI + auto-commit on every notebook write
138
+ // ─────────────────────────────────────────────────────────────────────────────
139
+
140
+ let unsubscribeWatch: (() => void) | null = null;
141
+
142
+ function startWatchingNotebook(key: string, autoCommit = false): void {
143
+ stopWatchingNotebook();
144
+ const store = recordStore(key);
145
+ unsubscribeWatch = store.onChange((content) => {
146
+ notifyNotebookChange(content);
147
+ if (autoCommit && store.kind === "file") commitFile(key, "Notebook updated");
148
+ });
149
+ }
150
+
151
+ export function stopWatchingNotebook(): void {
152
+ unsubscribeWatch?.();
153
+ unsubscribeWatch = null;
154
+ }
155
+
156
+ // ─────────────────────────────────────────────────────────────────────────────
157
+ // Notebook path
158
+ // ─────────────────────────────────────────────────────────────────────────────
159
+
160
+ export function getNotebookPath(): string | null {
161
+ return state.notebookPath;
162
+ }
163
+
164
+ export function setNotebookPath(notebookFile: string | null): void {
165
+ state.notebookPath = notebookFile;
166
+ state.notebookLoaded = notebookFile !== null;
167
+ // Switching notebooks must not inherit the prior file's emit baselines, or a
168
+ // new notebook that shares the old one's content/fingerprint would be wrongly
169
+ // suppressed and leave the panel stale. #253
170
+ lastEmittedNotebookContent = null;
171
+ lastInspectedFingerprint = null;
172
+ if (notebookFile) {
173
+ startWatchingNotebook(notebookFile, false);
174
+ loadActivityLog(path.dirname(notebookFile));
175
+ } else {
176
+ stopWatchingNotebook();
177
+ resetActivity();
178
+ }
179
+ }
180
+
181
+ export function isNotebookLoaded(): boolean {
182
+ return state.notebookLoaded;
183
+ }
184
+
185
+ export function getDefaultPath(_title: string, directory: string): string {
186
+ return getDefaultNotebookPath(_title, directory);
187
+ }
188
+
189
+ /**
190
+ * Ensure every session has a record. On the desktop that is notebook.md in
191
+ * cwd, created empty if missing; under a shell that installed a record store
192
+ * it is whatever the shell bound. Attaches the watcher, hydrates the activity
193
+ * log, and emits the first notebook-change notification so the Notebook pane
194
+ * paints immediately. Idempotent; safe to call every session_start.
195
+ */
196
+ export async function initSessionArtifacts(cwd: string): Promise<void> {
197
+ const notebookPath = installedRecordStore()?.key ?? path.join(cwd, "notebook.md");
198
+ const sessionDir = cwd;
199
+ // Fresh session: Pi has cleared extension widgets, so reset the mode too.
200
+ notebookWidgetMode = "auto";
201
+ // New session may point at a different notebook.md; force the next re-sync
202
+ // check to re-inspect rather than trust a stale fingerprint. #253
203
+ lastInspectedFingerprint = null;
204
+
205
+ try {
206
+ const store = recordStore(notebookPath);
207
+ // Auto-commit needs a working tree; a page has none.
208
+ const autoCommit = store.kind === "file" ? ensureGitRepo(cwd) : false;
209
+
210
+ if ((await store.ensure()) && autoCommit) {
211
+ commitFile(notebookPath, "Initialize notebook");
212
+ }
213
+
214
+ state.notebookPath = notebookPath;
215
+ state.notebookLoaded = true;
216
+ startWatchingNotebook(notebookPath, autoCommit);
217
+ loadActivityLog(sessionDir);
218
+
219
+ notifyNotebookChange((await store.read()).content);
220
+
221
+ appendActivityEvent(sessionDir, {
222
+ timestamp: new Date().toISOString(),
223
+ kind: "session.started",
224
+ source: "session_bootstrap",
225
+ payload: { cwd },
226
+ });
227
+ } catch (err) {
228
+ console.error("initSessionArtifacts failed:", err);
229
+ }
230
+ }
231
+
232
+ // ─────────────────────────────────────────────────────────────────────────────
233
+ // Current Galaxy history
234
+ // ─────────────────────────────────────────────────────────────────────────────
235
+
236
+ export function setCurrentHistoryId(historyId: string | null): void {
237
+ state.currentHistoryId = historyId;
238
+ }
239
+
240
+ export function getCurrentHistoryId(): string | null {
241
+ return state.currentHistoryId;
242
+ }
243
+
244
+ // ─────────────────────────────────────────────────────────────────────────────
245
+ // Current plan step
246
+ // ─────────────────────────────────────────────────────────────────────────────
247
+
248
+ /**
249
+ * Point subsequent Galaxy submissions at a plan step, or clear the pointer.
250
+ *
251
+ * Set by /execute from the plan it parsed; cleared when the agent run that
252
+ * /execute started settles. It is deliberately in-memory and deliberately
253
+ * coarse: it says which step the agent was *asked* to work on, not which step
254
+ * a given submission belongs to. The submission hook reads it once, at
255
+ * dispatch, and carries the value forward with the attempt -- reading it again
256
+ * when the result lands would attribute a slow submission to whatever step was
257
+ * current by then.
258
+ */
259
+ export function setCurrentStepAnchor(anchor: string | null): void {
260
+ state.currentStepAnchor = anchor && anchor.trim().length > 0 ? anchor.trim() : null;
261
+ }
262
+
263
+ export function getCurrentStepAnchor(): string | null {
264
+ return state.currentStepAnchor;
265
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Replaying recorded submission results, for the Tier-1 evals.
3
+ *
4
+ * The capture hook fires on `tool_execution_end`, which needs a real tool
5
+ * call, which needs a model turn. The Tier-1 scenarios are deliberately
6
+ * model-free -- they exist to pin deterministic harness behavior without an
7
+ * API key or a flaky model in the loop -- so they need some way to hand the
8
+ * hook a result. This is it: `LOOM_SUBMISSION_REPLAY` names a JSONL file of
9
+ * recorded results, relative to the session directory, and each line is fed
10
+ * through the same start/end path a real submission takes.
11
+ *
12
+ * Off unless the env var is set, and nothing registers it otherwise -- the
13
+ * same shape as LOOM_TEAM_DISPATCH and LOOM_SESSION_INDEX. Two deliberate
14
+ * constraints, because this writes blocks that claim `submitted_by: harness`
15
+ * and `server_verified: true`:
16
+ *
17
+ * - the file must resolve inside the session directory, so the variable alone
18
+ * cannot point the replay at something elsewhere on the machine;
19
+ * - every replay writes a `submission.replay` row first, so a notebook
20
+ * produced this way is never silently indistinguishable from one produced
21
+ * by real submissions. If you are auditing a record and the activity log
22
+ * has that row in it, the provenance in that notebook was replayed.
23
+ *
24
+ * Each line: `{tool, args?, result, isError?, stepAnchor?}`. `tool` is the name the model would
25
+ * have called, read through the shell's Galaxy tool family the way a live call is, so a name no
26
+ * shell offers any more (the retired MCP spelling of run_tool) is refused rather than recorded.
27
+ */
28
+
29
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
30
+ import * as fs from "fs";
31
+ import * as path from "path";
32
+ import { readEnv } from "../../shared/orbit-env.js";
33
+ import { appendActivityEvent } from "./activity";
34
+ import { handleSubmissionResult, submissionToolName } from "./galaxy-submission-capture";
35
+ import { galaxyToolFamily } from "./galaxy-tool-source";
36
+ import { getNotebookPath, setCurrentStepAnchor } from "./state";
37
+
38
+ export interface ReplayEntry {
39
+ tool: string;
40
+ args?: Record<string, unknown>;
41
+ result?: unknown;
42
+ isError?: boolean;
43
+ /** Sets `state.currentStepAnchor` before this entry's dispatch. */
44
+ stepAnchor?: string | null;
45
+ }
46
+
47
+ export function isSubmissionReplayEnabled(): boolean {
48
+ return !!readEnv("SUBMISSION_REPLAY")?.trim();
49
+ }
50
+
51
+ /** Parse a replay file, skipping blank and malformed lines. */
52
+ export function parseReplayFile(raw: string): ReplayEntry[] {
53
+ const out: ReplayEntry[] = [];
54
+ for (const line of raw.split("\n")) {
55
+ if (!line.trim()) continue;
56
+ try {
57
+ const entry = JSON.parse(line) as ReplayEntry;
58
+ if (entry && typeof entry.tool === "string") out.push(entry);
59
+ } catch {
60
+ // Skip, same as the activity log's own hydrate.
61
+ }
62
+ }
63
+ return out;
64
+ }
65
+
66
+ /**
67
+ * Resolve the replay file inside `sessionDir`, or null if it escapes.
68
+ * Exported for the test that pins the containment.
69
+ *
70
+ * Both sides are realpath'd before comparing, so the check is about where the
71
+ * file actually is rather than how it is spelled: a lexical prefix test alone
72
+ * accepts `<session>/replay.jsonl` when that name is a symlink pointing
73
+ * somewhere else entirely. The session directory is realpath'd too, since on
74
+ * macOS a temp dir is reached through a `/var` -> `/private/var` symlink and
75
+ * comparing a resolved file against an unresolved root would reject every
76
+ * legitimate path.
77
+ */
78
+ export function resolveReplayPath(sessionDir: string, configured: string): string | null {
79
+ const real = (p: string): string => {
80
+ try {
81
+ return fs.realpathSync(p);
82
+ } catch {
83
+ return path.resolve(p);
84
+ }
85
+ };
86
+ const root = real(sessionDir);
87
+ const resolved = real(path.resolve(sessionDir, configured));
88
+ return resolved.startsWith(root + path.sep) ? resolved : null;
89
+ }
90
+
91
+ export function registerSubmissionReplay(pi: ExtensionAPI): void {
92
+ pi.on("session_start", async () => {
93
+ const configured = readEnv("SUBMISSION_REPLAY")?.trim();
94
+ if (!configured) return;
95
+
96
+ const notebookPath = getNotebookPath();
97
+ if (!notebookPath) return;
98
+ const sessionDir = path.dirname(notebookPath);
99
+
100
+ const file = resolveReplayPath(sessionDir, configured);
101
+ if (!file || !fs.existsSync(file)) return;
102
+
103
+ const entries = parseReplayFile(fs.readFileSync(file, "utf-8"));
104
+
105
+ appendActivityEvent(sessionDir, {
106
+ timestamp: new Date().toISOString(),
107
+ kind: "submission.replay",
108
+ source: "submission-replay",
109
+ payload: { file: path.relative(sessionDir, file), entries: entries.length },
110
+ });
111
+
112
+ const family = galaxyToolFamily();
113
+ for (const [index, entry] of entries.entries()) {
114
+ const toolName = submissionToolName(entry.tool, family);
115
+ if (!toolName) {
116
+ appendActivityEvent(sessionDir, {
117
+ timestamp: new Date().toISOString(),
118
+ kind: "submission.unparsed",
119
+ source: "submission-replay",
120
+ payload: {
121
+ tool: entry.tool,
122
+ step_anchor: entry.stepAnchor ?? null,
123
+ reason: `${entry.tool} is not a Galaxy submission tool this shell offers`,
124
+ },
125
+ });
126
+ continue;
127
+ }
128
+ // Set it for every entry, not just the ones that name one: leaving the
129
+ // previous entry's anchor in place made an entry with no `stepAnchor`
130
+ // inherit its predecessor's step instead of being unattributed.
131
+ setCurrentStepAnchor(entry.stepAnchor ?? null);
132
+ await handleSubmissionResult(
133
+ `replay-${index}`,
134
+ toolName,
135
+ entry.result,
136
+ entry.isError === true,
137
+ // Replay has no start event, so hand the dispatch details straight in
138
+ // rather than letting the hook fall back to "unattributed". `replayed`
139
+ // is what keeps the blocks from claiming a submission Orbit watched and
140
+ // a server that answered, neither of which happened here.
141
+ { args: entry.args ?? {}, stepAnchor: entry.stepAnchor ?? null, replayed: true },
142
+ );
143
+ }
144
+
145
+ setCurrentStepAnchor(null);
146
+ });
147
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * /sync command -- user-facing entry point to the three sync tools.
3
+ *
4
+ * Subcommands: status, push, pull, link. Same semantics as the
5
+ * notebook_*_galaxy tools (they share the underlying helpers in
6
+ * galaxy-pages-sync.ts); /sync just gives the user a direct way to invoke
7
+ * them from the chat without going through the agent.
8
+ */
9
+
10
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
+ import { getNotebookPath } from "./state";
12
+ import { readNotebook } from "./notebook-writer";
13
+ import { findGalaxyPageBlocks } from "./galaxy-page-binding";
14
+ import {
15
+ pushNotebookToGalaxy,
16
+ pullNotebookFromGalaxy,
17
+ linkGalaxyPage,
18
+ resumeGalaxyPage,
19
+ } from "./galaxy-pages-sync";
20
+
21
+ interface ParsedFlags {
22
+ positional: string[];
23
+ flags: Record<string, string | undefined>;
24
+ }
25
+
26
+ function parseFlags(input: string): ParsedFlags {
27
+ const tokens = input.match(/(?:--[a-z-]+(?:=(?:"[^"]*"|\S+))?|"[^"]*"|\S+)/gi) ?? [];
28
+ const positional: string[] = [];
29
+ const flags: Record<string, string | undefined> = {};
30
+ for (let i = 0; i < tokens.length; i++) {
31
+ const t = tokens[i];
32
+ if (t.startsWith("--")) {
33
+ const eq = t.indexOf("=");
34
+ if (eq >= 0) {
35
+ const k = t.slice(2, eq);
36
+ const v = t.slice(eq + 1).replace(/^"|"$/g, "");
37
+ flags[k] = v;
38
+ } else {
39
+ const k = t.slice(2);
40
+ const next = tokens[i + 1];
41
+ if (next && !next.startsWith("--")) {
42
+ flags[k] = next.replace(/^"|"$/g, "");
43
+ i++;
44
+ } else {
45
+ flags[k] = "";
46
+ }
47
+ }
48
+ } else {
49
+ positional.push(t.replace(/^"|"$/g, ""));
50
+ }
51
+ }
52
+ return { positional, flags };
53
+ }
54
+
55
+ export function registerSyncCommand(pi: ExtensionAPI): void {
56
+ pi.registerCommand("sync", {
57
+ description:
58
+ "Sync notebook.md with a Galaxy page. Subcommands: status | push [--history H --title T --slug S --annotation A] | pull | link <page_id> [--history H] | resume <page_id> [--history H]",
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ handler: async (args: string, ctx: any) => {
61
+ const trimmed = (args ?? "").trim();
62
+ const firstSpace = trimmed.indexOf(" ");
63
+ const subcommand = firstSpace === -1 ? trimmed || "status" : trimmed.slice(0, firstSpace);
64
+ const tail = firstSpace === -1 ? "" : trimmed.slice(firstSpace + 1);
65
+ const { positional, flags } = parseFlags(tail);
66
+
67
+ try {
68
+ if (subcommand === "status") {
69
+ const nbPath = getNotebookPath();
70
+ if (!nbPath) {
71
+ ctx.ui.notify("No active loom session; nothing to sync.", "warning");
72
+ return;
73
+ }
74
+ const content = await readNotebook(nbPath);
75
+ const binding = findGalaxyPageBlocks(content)[0];
76
+ if (!binding) {
77
+ ctx.ui.notify(
78
+ "Notebook is not bound to a Galaxy page. Use `/sync push --history <id>` to create one, or `/sync link <page_id>` to link an existing page.",
79
+ "info",
80
+ );
81
+ return;
82
+ }
83
+ ctx.ui.notify(
84
+ `Bound to ${binding.galaxyServerUrl} (page_id=${binding.pageId}, slug=${binding.pageSlug ?? "<none>"}, last_synced_revision=${binding.lastSyncedRevision ?? "<none>"})`,
85
+ "info",
86
+ );
87
+ return;
88
+ }
89
+
90
+ if (subcommand === "push") {
91
+ const result = await pushNotebookToGalaxy({
92
+ historyId: flags.history,
93
+ title: flags.title,
94
+ slug: flags.slug,
95
+ annotation: flags.annotation,
96
+ });
97
+ ctx.ui.notify(
98
+ `Pushed: ${result.action} page ${result.pageId} (revision ${result.latestRevisionId}).`,
99
+ "info",
100
+ );
101
+ return;
102
+ }
103
+
104
+ if (subcommand === "pull") {
105
+ const result = await pullNotebookFromGalaxy();
106
+ ctx.ui.notify(
107
+ `Pulled page ${result.pageId} (revision ${result.latestRevisionId}). Notebook updated.`,
108
+ "info",
109
+ );
110
+ return;
111
+ }
112
+
113
+ if (subcommand === "link") {
114
+ const pageId = positional[0];
115
+ if (!pageId) {
116
+ ctx.ui.notify("Usage: /sync link <page_id> [--history <id>]", "warning");
117
+ return;
118
+ }
119
+ const result = await linkGalaxyPage(pageId, {
120
+ historyId: flags.history,
121
+ });
122
+ ctx.ui.notify(
123
+ `Linked to page ${result.pageId} (revision ${result.latestRevisionId}).`,
124
+ "info",
125
+ );
126
+ return;
127
+ }
128
+
129
+ if (subcommand === "resume") {
130
+ const pageId = positional[0];
131
+ if (!pageId) {
132
+ ctx.ui.notify("Usage: /sync resume <page_id> [--history <id>]", "warning");
133
+ return;
134
+ }
135
+ const result = await resumeGalaxyPage(pageId, {
136
+ historyId: flags.history,
137
+ });
138
+ ctx.ui.notify(
139
+ `Resumed page ${result.pageId} (${result.action}, revision ${result.latestRevisionId}). Notebook updated.`,
140
+ "info",
141
+ );
142
+ return;
143
+ }
144
+
145
+ ctx.ui.notify(
146
+ `Unknown /sync subcommand: ${subcommand}. Use status, push, pull, link, or resume.`,
147
+ "warning",
148
+ );
149
+ } catch (e) {
150
+ ctx.ui.notify(
151
+ `/sync ${subcommand}: ${e instanceof Error ? e.message : String(e)}`,
152
+ "error",
153
+ );
154
+ }
155
+ },
156
+ });
157
+ }
@@ -0,0 +1,93 @@
1
+ export interface CriticVerdict {
2
+ approved: boolean;
3
+ critique: string;
4
+ }
5
+
6
+ /**
7
+ * Extract the last well-formed `{approved, critique}` JSON object from a
8
+ * critic response. Falls back to `{approved: false, critique: <input>}` if
9
+ * no valid object is found.
10
+ */
11
+ export function parseCriticResponse(text: string): CriticVerdict {
12
+ const matches = findJsonObjects(text);
13
+ for (let i = matches.length - 1; i >= 0; i--) {
14
+ const raw = matches[i];
15
+ try {
16
+ const parsed = JSON.parse(raw) as unknown;
17
+ if (isValidVerdict(parsed)) {
18
+ return { approved: parsed.approved, critique: parsed.critique };
19
+ }
20
+ } catch {
21
+ // try the next earlier candidate
22
+ }
23
+ }
24
+ return { approved: false, critique: text };
25
+ }
26
+
27
+ function isValidVerdict(v: unknown): v is CriticVerdict {
28
+ return (
29
+ typeof v === "object" &&
30
+ v !== null &&
31
+ "approved" in v &&
32
+ typeof (v as CriticVerdict).approved === "boolean" &&
33
+ "critique" in v &&
34
+ typeof (v as CriticVerdict).critique === "string"
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Scan `text` for substrings that start with `{` and are balanced with their
40
+ * closing `}`. Ignores braces inside double-quoted strings.
41
+ */
42
+ function findJsonObjects(text: string): string[] {
43
+ const out: string[] = [];
44
+ let i = 0;
45
+ while (i < text.length) {
46
+ if (text[i] !== "{") {
47
+ i++;
48
+ continue;
49
+ }
50
+ const end = scanBalancedBrace(text, i);
51
+ if (end < 0) {
52
+ i++;
53
+ continue;
54
+ }
55
+ out.push(text.slice(i, end + 1));
56
+ i = end + 1;
57
+ }
58
+ return out;
59
+ }
60
+
61
+ function scanBalancedBrace(text: string, start: number): number {
62
+ let depth = 0;
63
+ let inString = false;
64
+ let escaped = false;
65
+ for (let i = start; i < text.length; i++) {
66
+ const c = text[i];
67
+ if (escaped) {
68
+ escaped = false;
69
+ continue;
70
+ }
71
+ if (inString) {
72
+ if (c === "\\") {
73
+ escaped = true;
74
+ continue;
75
+ }
76
+ if (c === '"') {
77
+ inString = false;
78
+ continue;
79
+ }
80
+ continue;
81
+ }
82
+ if (c === '"') {
83
+ inString = true;
84
+ continue;
85
+ }
86
+ if (c === "{") depth++;
87
+ else if (c === "}") {
88
+ depth--;
89
+ if (depth === 0) return i;
90
+ }
91
+ }
92
+ return -1;
93
+ }