@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,181 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import { getNotebookPath } from "../state";
5
+ import { appendActivityEvent } from "../activity";
6
+ import { redactArgs } from "../activity-hooks";
7
+ import {
8
+ loadGuardianConfig,
9
+ resolveBypass,
10
+ trustWorkspace,
11
+ recordConsent,
12
+ } from "./guardian-config";
13
+ import { createPathResolver } from "./path-jail";
14
+ import { classifyModelTier } from "./model-tier";
15
+ import { decide } from "./policy";
16
+ import { CONSENT_VERSION, type PolicyResult } from "./types";
17
+ import { buildApprovalPrompt } from "../../../shared/approval-prompt.js";
18
+
19
+ // In-memory "allow for this session" set, keyed by tool + raw input signature.
20
+ const sessionAllow = new Set<string>();
21
+ function sig(toolName: string, input: Record<string, unknown>): string {
22
+ return toolName + ":" + JSON.stringify(input);
23
+ }
24
+
25
+ function audit(
26
+ toolName: string,
27
+ input: Record<string, unknown>,
28
+ result: PolicyResult,
29
+ outcome: string,
30
+ ): void {
31
+ const nb = getNotebookPath();
32
+ if (!nb) return;
33
+ appendActivityEvent(path.dirname(nb), {
34
+ timestamp: new Date().toISOString(),
35
+ kind: "guard.decision",
36
+ source: "exec-guard",
37
+ payload: {
38
+ toolName,
39
+ decision: result.decision,
40
+ category: result.category,
41
+ reason: result.reason,
42
+ outcome,
43
+ args: redactArgs(toolName, input),
44
+ },
45
+ });
46
+ }
47
+
48
+ // The state dir (.loom/.orbit) is deliberately not a root of its own. Under
49
+ // cwd it is already inside the jail; the only thing a separate root ever added
50
+ // was trust in wherever a symlinked state dir pointed, which the user never
51
+ // granted.
52
+ export function workspaceRoots(cwd: string, extra: string[]): string[] {
53
+ return [cwd, os.tmpdir(), ...extra];
54
+ }
55
+
56
+ export function registerExecGuard(pi: ExtensionAPI): void {
57
+ pi.on("tool_call", async (event, ctx) => {
58
+ const config = loadGuardianConfig();
59
+ if (!config.enabled) return; // gate fully disabled (advanced escape hatch)
60
+ // Fold the effective bypass back into the config the pure engine sees.
61
+ config.dangerouslyBypassPermissions = resolveBypass(config);
62
+
63
+ const input = event.input as Record<string, unknown>;
64
+ const cwd = ctx.cwd;
65
+ const resolver = createPathResolver(
66
+ workspaceRoots(cwd, config.extraWorkspaceRoots),
67
+ os.homedir(),
68
+ );
69
+
70
+ let result: PolicyResult;
71
+ try {
72
+ result = decide(
73
+ {
74
+ toolName: event.toolName,
75
+ toolInput: input,
76
+ modelTier: classifyModelTier(ctx.model),
77
+ config,
78
+ interactive: ctx.hasUI,
79
+ cwd,
80
+ },
81
+ { resolver, home: os.homedir() },
82
+ );
83
+ } catch {
84
+ const reason = "exec-guard internal error; failing closed";
85
+ audit(event.toolName, input, { decision: "deny", category: "error", reason }, "blocked");
86
+ return { block: true, reason };
87
+ }
88
+
89
+ if (result.decision === "allow") {
90
+ audit(event.toolName, input, result, "allowed");
91
+ return;
92
+ }
93
+ if (result.decision === "deny") {
94
+ audit(event.toolName, input, result, "blocked");
95
+ return { block: true, reason: result.reason };
96
+ }
97
+
98
+ // Destructive Galaxy op (#338): its own yes/no confirm, never cached and never
99
+ // offered "allow for session"/"trust workspace" -- every irreversible action
100
+ // re-prompts. Independent of the one-time local-exec consent disclosure (that's
101
+ // about shell execution; this is its own, more pointed prompt). The decision here
102
+ // is always "ask" -- the non-interactive case already denied above.
103
+ if (result.category === "galaxy:destructive") {
104
+ const proceed = await ctx.ui.confirm(
105
+ "Confirm destructive Galaxy operation",
106
+ `${ctx.model?.id ?? "The model"} wants to: ${result.reason}\n\nContinue?`,
107
+ {},
108
+ );
109
+ if (proceed) {
110
+ audit(event.toolName, input, result, "allowed:destructive-confirm");
111
+ return;
112
+ }
113
+ audit(event.toolName, input, result, "blocked:destructive-user");
114
+ return { block: true, reason: "Destructive Galaxy operation cancelled by user." };
115
+ }
116
+
117
+ // ask: session memory first.
118
+ if (sessionAllow.has(sig(event.toolName, input))) {
119
+ audit(event.toolName, input, result, "allowed:session");
120
+ return;
121
+ }
122
+
123
+ // One-time local-execution disclosure on the first gated action. Relies on
124
+ // the persisted flag (saveConfig is synchronous), so a failed save simply
125
+ // re-discloses rather than silently proceeding.
126
+ if (!config.consentAcknowledged) {
127
+ const ok = await ctx.ui.confirm(
128
+ "Orbit runs actions on your computer",
129
+ "Orbit can run shell commands and read/write files as you. Commands from the AI are gated, but no gate is perfect -- only use it in workspaces you trust. Continue?",
130
+ {},
131
+ );
132
+ if (!ok) {
133
+ audit(event.toolName, input, result, "blocked:consent-declined");
134
+ return { block: true, reason: "Local execution not consented." };
135
+ }
136
+ recordConsent(CONSENT_VERSION);
137
+ }
138
+
139
+ const modelName = ctx.model?.id ?? "the model";
140
+ // Heading and the thing being approved are separated by a blank line so a
141
+ // shell can render the command as a readable body instead of a headline.
142
+ // Lowercased to match the policy engine, which gates on the normalized
143
+ // name -- otherwise a "Bash" call would be gated as a command but prompted
144
+ // as a path, showing the user nothing of what they're approving.
145
+ const isBash = event.toolName.toLowerCase() === "bash";
146
+ const heading = isBash
147
+ ? `Allow ${modelName} to run this command?`
148
+ : `Allow ${modelName} to ${event.toolName} this path?`;
149
+ // File tools also arrive with the Anthropic `file_path` spelling and the policy
150
+ // layer gates both, so the prompt names every path the call carries: answering
151
+ // it while looking at one of two different targets is not consent.
152
+ const paths = [...new Set([input.path, input.file_path].filter((v) => typeof v === "string"))];
153
+ const detail = String(isBash ? (input.command ?? "") : paths.join(" + "));
154
+ const choice = await ctx.ui.select(
155
+ buildApprovalPrompt(heading, detail),
156
+ [
157
+ "Allow once",
158
+ "Allow for this session",
159
+ "Trust this workspace (stop asking for routine commands)",
160
+ "Deny",
161
+ ],
162
+ {},
163
+ );
164
+ if (choice === "Allow once") {
165
+ audit(event.toolName, input, result, "allowed:once");
166
+ return;
167
+ }
168
+ if (choice === "Allow for this session") {
169
+ sessionAllow.add(sig(event.toolName, input));
170
+ audit(event.toolName, input, result, "allowed:session");
171
+ return;
172
+ }
173
+ if (choice && choice.startsWith("Trust this workspace")) {
174
+ trustWorkspace(cwd);
175
+ audit(event.toolName, input, result, "allowed:trust-workspace");
176
+ return;
177
+ }
178
+ audit(event.toolName, input, result, "blocked:user");
179
+ return { block: true, reason: "Denied by user." };
180
+ });
181
+ }
@@ -0,0 +1,54 @@
1
+ import { loadConfig, saveConfig } from "../../../shared/orbit-config.js";
2
+ import type { GuardianConfig } from "./types";
3
+ import { readEnv } from "../../../shared/orbit-env.js";
4
+
5
+ export function loadGuardianConfig(): GuardianConfig {
6
+ const g = loadConfig().guardian ?? {};
7
+ return {
8
+ enabled: g.enabled !== false,
9
+ dangerouslyBypassPermissions: g.dangerouslyBypassPermissions === true,
10
+ trustedWorkspaces: g.trustedWorkspaces ?? [],
11
+ extraWorkspaceRoots: g.extraWorkspaceRoots ?? [],
12
+ consentAcknowledged: g.consentAcknowledged ?? null,
13
+ sandbox: g.sandbox === true,
14
+ };
15
+ }
16
+
17
+ /**
18
+ * Bypass is ON if (env flag OR config) AND NOT force-off. The agent can never
19
+ * flip the env or config: those are human-only channels (the gate makes
20
+ * writing ~/.orbit/config.json gated and editing guardian.* catastrophic).
21
+ */
22
+ export function resolveBypass(cfg: GuardianConfig): boolean {
23
+ if (readEnv("SAFE") === "1") return false;
24
+ if (readEnv("DANGEROUSLY_BYPASS_PERMISSIONS") === "1") return true;
25
+ return cfg.dangerouslyBypassPermissions === true;
26
+ }
27
+
28
+ /**
29
+ * The OS bash sandbox is opt-in: enabling it necessarily restricts bash network
30
+ * (ASRT cannot confine writes alone), so it's a deliberate user choice, not a
31
+ * default. On via LOOM_SANDBOX=1 or guardian.sandbox. Default off.
32
+ */
33
+ export function resolveSandbox(cfg: GuardianConfig): boolean {
34
+ if (readEnv("SANDBOX") === "1") return true;
35
+ return cfg.sandbox === true;
36
+ }
37
+
38
+ export function trustWorkspace(dir: string): void {
39
+ const cfg = loadConfig();
40
+ const g = cfg.guardian ?? {};
41
+ const set = new Set(g.trustedWorkspaces ?? []);
42
+ set.add(dir);
43
+ cfg.guardian = { ...g, trustedWorkspaces: [...set] };
44
+ saveConfig(cfg);
45
+ }
46
+
47
+ export function recordConsent(version: string): void {
48
+ const cfg = loadConfig();
49
+ cfg.guardian = {
50
+ ...(cfg.guardian ?? {}),
51
+ consentAcknowledged: { version, at: new Date().toISOString() },
52
+ };
53
+ saveConfig(cfg);
54
+ }
@@ -0,0 +1 @@
1
+ export { registerExecGuard } from "./gate";
@@ -0,0 +1,36 @@
1
+ import type { ModelTier } from "./types";
2
+
3
+ export interface TierInput {
4
+ id?: string;
5
+ provider?: string;
6
+ cost?: { input: number; output: number };
7
+ }
8
+
9
+ // Tokens that mark a model as weak/cheap regardless of cost. Matched as whole
10
+ // dash/dot-delimited tokens of the lowercased id (NOT substrings) so "mini"
11
+ // flags gpt-4o-mini but not gemini. Conservative: when unsure -> weak.
12
+ const WEAK_ID_MARKERS = ["haiku", "mini", "flash", "small", "lite", "8b", "7b", "1b", "3b", "nano"];
13
+
14
+ // Frontier id markers that are trusted even if a custom price table is wrong.
15
+ const TRUSTED_ID_MARKERS = [
16
+ "opus",
17
+ "sonnet",
18
+ "gpt-5",
19
+ "gpt-4.1",
20
+ "o1",
21
+ "o3",
22
+ "gemini-2.5-pro",
23
+ "gemini-1.5-pro",
24
+ ];
25
+
26
+ export function classifyModelTier(model: TierInput | undefined): ModelTier {
27
+ if (!model || !model.id) return "weak";
28
+ const id = model.id.toLowerCase();
29
+ const idTokens = id.split(/[^a-z0-9]+/);
30
+ if (idTokens.some((tok) => WEAK_ID_MARKERS.includes(tok))) return "weak";
31
+ if (TRUSTED_ID_MARKERS.some((m) => id.includes(m))) return "trusted";
32
+ // Fall back to price: frontier output pricing is well above cheap tiers.
33
+ // Threshold chosen so Haiku ($5 out) is weak and Sonnet ($15 out) is trusted.
34
+ const out = model.cost?.output ?? 0;
35
+ return out >= 10 ? "trusted" : "weak";
36
+ }
@@ -0,0 +1,54 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import type { PathResolver } from "./types";
4
+
5
+ // Expand a leading `~` or `$HOME`/`${HOME}` to the home dir. The shell does this
6
+ // in bash, and pi resolves `~` in its file tools, but `path.resolve` does not --
7
+ // so without this a `~/.aws/config` read resolves to `<cwd>/~/.aws/config` and
8
+ // dodges both the sensitive-read floor and the workspace jail.
9
+ export function expandHome(p: string, home: string): string {
10
+ if (!home) return p;
11
+ if (p === "~" || p === "~/") return home;
12
+ if (p.startsWith("~/")) return path.join(home, p.slice(2));
13
+ const m = p.match(/^\$\{?HOME\}?(?=\/|$)/);
14
+ if (m) return path.join(home, p.slice(m[0].length));
15
+ return p;
16
+ }
17
+
18
+ function realpathDeepest(target: string): string {
19
+ // realpath the longest existing prefix, then re-append the missing tail.
20
+ let cur = path.resolve(target);
21
+ const tail: string[] = [];
22
+ for (;;) {
23
+ try {
24
+ return path.join(fs.realpathSync(cur), ...tail.reverse());
25
+ } catch {
26
+ const parent = path.dirname(cur);
27
+ if (parent === cur) return path.resolve(target); // hit the root, nothing exists
28
+ tail.push(path.basename(cur));
29
+ cur = parent;
30
+ }
31
+ }
32
+ }
33
+
34
+ export function createPathResolver(roots: string[], home = ""): PathResolver {
35
+ const realRoots = roots
36
+ .map((r) => {
37
+ const expanded = expandHome(r, home);
38
+ try {
39
+ return fs.realpathSync(expanded);
40
+ } catch {
41
+ return path.resolve(expanded);
42
+ }
43
+ })
44
+ .filter(Boolean);
45
+ return {
46
+ contains(targetPath: string) {
47
+ const resolved = realpathDeepest(expandHome(targetPath, home));
48
+ const inside = realRoots.some(
49
+ (root) => resolved === root || resolved.startsWith(root + path.sep),
50
+ );
51
+ return { resolved, inside };
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,342 @@
1
+ import * as path from "path";
2
+ import { classifyBash } from "./bash-risk";
3
+ import { expandHome } from "./path-jail";
4
+ import {
5
+ isSensitivePath,
6
+ isCredentialStore,
7
+ isProtectedWritePath,
8
+ isOrbitStatePath,
9
+ isRecordStorePath,
10
+ } from "./sensitive-read";
11
+ import type { PolicyDeps, PolicyRequest, PolicyResult } from "./types";
12
+ import {
13
+ classifyGalaxyDestructive,
14
+ describeGalaxyDestructive,
15
+ isGalaxyDestructiveCurl,
16
+ } from "../../../shared/galaxy-destructive.js";
17
+ import type { GalaxyDestructiveOp } from "../../../shared/galaxy-destructive.js";
18
+
19
+ // A dedicated credential store's CONTENTS are never readable by the agent --
20
+ // denied for every tier, not downgraded to an ask. This is the floor that closes
21
+ // #183: a capable model that gets to read ~/.orbit/config.json echoes the keys
22
+ // straight into the provider's request logs. Approval can't override it.
23
+ function denyCredentialStore(p: string, home: string): PolicyResult {
24
+ return {
25
+ decision: "deny",
26
+ category: "read:credential-store",
27
+ reason: `access to credential store ${shown(p, home)} blocked for all models`,
28
+ };
29
+ }
30
+
31
+ // Reasons land in the activity log, and a path the classifier resolved is
32
+ // absolute; spelling the home dir as `~` keeps the username out of it.
33
+ // Compared as forward-slashed strings so the spelling is the same on every host.
34
+ function shown(p: string, home: string): string {
35
+ const fp = p.replace(/\\/g, "/");
36
+ const fh = home.replace(/\\/g, "/").replace(/\/+$/, "");
37
+ if (!fh) return p;
38
+ if (fp.toLowerCase() === fh.toLowerCase()) return "~";
39
+ return fp.toLowerCase().startsWith(fh.toLowerCase() + "/") ? `~/${fp.slice(fh.length + 1)}` : p;
40
+ }
41
+
42
+ const FILE_WRITE_TOOLS = new Set(["write", "edit"]);
43
+ // Tools that write a local file they're handed a path for. Readers that take a
44
+ // path (the local uploader) are left alone: reading the notebook is fine.
45
+ const LOCAL_WRITER_TOOL = /download/i;
46
+ // Parameter names those tools use for the destination.
47
+ const LOCAL_PATH_KEY = /^(?:file_?path|path|output_?path|dest(?:ination)?(?:_path)?|out_?file)$/i;
48
+ // The record files only the hooked file tools may write.
49
+ const RECORD_BASENAMES = new Set(["notebook.md", "activity.jsonl"]);
50
+ // Read-like pi tools that take an optional `path`. grep reads file CONTENTS, so
51
+ // `grep <pat> ~/.ssh/id_rsa` is a credential-leak vector; ls/find/glob enumerate
52
+ // names under a path. All face the sensitive-path floor AND the workspace jail --
53
+ // a read pointed outside the work dir prompts, same as a write. A path-less call
54
+ // (e.g. grep with just a pattern) searches the cwd and is allowed.
55
+ const FILE_READ_TOOLS = new Set(["read", "grep", "ls", "find", "glob"]);
56
+
57
+ function pick(toolInput: Record<string, unknown>, key: string): string | undefined {
58
+ const v = toolInput[key];
59
+ return typeof v === "string" ? v : undefined;
60
+ }
61
+
62
+ // pi declares its file tools with a `path` parameter, but every one of their
63
+ // renderers resolves `file_path ?? path` (dist/core/tools/{edit,write,read}.js):
64
+ // the Anthropic spelling arrives often enough that pi displays it. A floor must
65
+ // not assume one spelling, so both keys are collected and each check below runs
66
+ // across all of them -- a benign `path` cannot launder a sensitive `file_path`,
67
+ // and the path the human is asked about is one the tool could actually touch.
68
+ const PATH_KEYS = ["path", "file_path"];
69
+
70
+ interface PathTarget {
71
+ raw: string;
72
+ resolved: string;
73
+ inside: boolean;
74
+ }
75
+
76
+ function pathTargets(req: PolicyRequest, deps: PolicyDeps): PathTarget[] {
77
+ const out: PathTarget[] = [];
78
+ for (const key of PATH_KEYS) {
79
+ const raw = pick(req.toolInput, key);
80
+ if (!raw || out.some((t) => t.raw === raw)) continue;
81
+ out.push({ raw, ...deps.resolver.contains(raw) });
82
+ }
83
+ return out;
84
+ }
85
+
86
+ // Apply the weak-model + non-interactive modifiers to an `ask`.
87
+ function finalizeAsk(req: PolicyRequest, category: string, reason: string): PolicyResult {
88
+ if (req.modelTier === "weak") {
89
+ return { decision: "deny", category, reason: `${reason} (denied: low-capability model)` };
90
+ }
91
+ if (!req.interactive) {
92
+ return {
93
+ decision: "deny",
94
+ category,
95
+ reason: `${reason} (denied: no interactive session to approve)`,
96
+ };
97
+ }
98
+ return { decision: "ask", category, reason };
99
+ }
100
+
101
+ // A destructive, irreversible Galaxy operation (#338). Always confirm -- regardless of
102
+ // model tier, so it deliberately does NOT go through finalizeAsk (no weak->deny downgrade).
103
+ // A non-interactive session has no one to approve, so it denies rather than running silently.
104
+ function destructiveGalaxy(req: PolicyRequest, op: GalaxyDestructiveOp): PolicyResult {
105
+ const headline = describeGalaxyDestructive(op).headline;
106
+ if (!req.interactive) {
107
+ return {
108
+ decision: "deny",
109
+ category: "galaxy:destructive",
110
+ reason: `${headline} (denied: no interactive session to approve)`,
111
+ };
112
+ }
113
+ return { decision: "ask", category: "galaxy:destructive", reason: headline };
114
+ }
115
+
116
+ export function decide(req: PolicyRequest, deps: PolicyDeps): PolicyResult {
117
+ // 1. Bypass short-circuit (human-only; see guardian-config.resolveBypass).
118
+ if (req.config.dangerouslyBypassPermissions) {
119
+ return { decision: "allow", category: "bypass", reason: "permissions bypassed" };
120
+ }
121
+
122
+ // pi emits its built-in file tools lowercase ("bash"/"read"/"write"/"edit"); we
123
+ // normalize so a future capitalized or renamed emission can't slip past the jail
124
+ // into the "other -> allow" bucket. (Verified: pi has exactly write+edit, lowercase.)
125
+ const toolName = req.toolName.toLowerCase();
126
+
127
+ if (toolName === "bash") {
128
+ const command = pick(req.toolInput, "command") ?? "";
129
+ const c = classifyBash(command, deps.home, req.cwd);
130
+ if (c.kind === "catastrophic") {
131
+ return { decision: "deny", category: "bash:catastrophic", reason: c.reason };
132
+ }
133
+ // The classifier judges the command string; only this layer has a resolver.
134
+ // A write target that looks like ordinary work product in the analysis
135
+ // workspace but realpaths into Orbit's own state is still Orbit's own state.
136
+ for (const p of c.stateDirWriteTargets) {
137
+ if (isOrbitStatePath(deps.resolver.contains(p).resolved, deps.home)) {
138
+ return {
139
+ decision: "deny",
140
+ category: "bash:catastrophic",
141
+ reason: "write to the Orbit config directory",
142
+ };
143
+ }
144
+ }
145
+ // Sensitive-read floor: every content-read target, including inside a pipe or
146
+ // compound command (closes the `cat secret | tool` evasion). A dedicated
147
+ // credential store is denied for ALL tiers; any other sensitive path
148
+ // downgrades to an ask (deny for weak / non-interactive).
149
+ // Targets resolved after a cd go first, so the credential store a cd reached
150
+ // is denied even when the operand as typed is only basename-sensitive
151
+ // (`cd ~/.ssh && cat id_rsa`). A command with no cd has none, and keeps the
152
+ // single first-match pass it always had.
153
+ const cdReads = c.cdReadPaths.map((p) => ({ p, ...deps.resolver.contains(p) }));
154
+ for (const { p, resolved } of cdReads) {
155
+ if (isCredentialStore(resolved, deps.home)) return denyCredentialStore(p, deps.home);
156
+ }
157
+ for (const p of c.sensitiveReadPaths) {
158
+ const { resolved } = deps.resolver.contains(p);
159
+ if (isCredentialStore(resolved, deps.home)) return denyCredentialStore(p, deps.home);
160
+ if (isSensitivePath(resolved, deps.home)) {
161
+ return finalizeAsk(req, "read:sensitive", `read of sensitive path ${shown(p, deps.home)}`);
162
+ }
163
+ }
164
+ for (const { p, resolved } of cdReads) {
165
+ if (isSensitivePath(resolved, deps.home)) {
166
+ return finalizeAsk(req, "read:sensitive", `read of sensitive path ${shown(p, deps.home)}`);
167
+ }
168
+ }
169
+ // Workspace-jail floor: only confidently-parsed simple read commands, so a
170
+ // compound command's jail semantics stay unchanged (it falls to "unknown").
171
+ for (const p of c.readPaths) {
172
+ const { inside } = deps.resolver.contains(p);
173
+ if (!inside) {
174
+ return finalizeAsk(req, "read:escape", `read outside workspace: ${p}`);
175
+ }
176
+ }
177
+ if (c.kind === "safe") {
178
+ return { decision: "allow", category: "bash:safe", reason: c.reason };
179
+ }
180
+ // Destructive Galaxy API call via raw curl/wget (DELETE /api/histories/{id}). A
181
+ // guardrail, not a boundary -- routes the unknown command to the same destructive
182
+ // confirm as the tool path (asks even a weak model) instead of a generic "unknown" ask.
183
+ // Catastrophic pipes were already denied above, so they never reach here.
184
+ {
185
+ const op = isGalaxyDestructiveCurl(command);
186
+ if (op) return destructiveGalaxy(req, op);
187
+ }
188
+ // Unknown command. A trusted workspace relaxes by one notch only, and only
189
+ // for this category: trusted model ask->allow, weak model deny->ask (the
190
+ // human stays in the loop). It never lifts the catastrophic/jail/sensitive
191
+ // floor above, and it never covers a command run after a cd into Orbit's own
192
+ // state or a credential store -- trusting the workspace says nothing about
193
+ // those directories.
194
+ // Nor a line that names the analysis record or the registry: what an
195
+ // interpreter or script does with them is beyond this classifier, and the
196
+ // shell write forms it does model are denied above.
197
+ if (req.config.trustedWorkspaces.includes(req.cwd) && !c.guardedCwd && !c.namesRecord) {
198
+ if (req.modelTier === "trusted") {
199
+ return {
200
+ decision: "allow",
201
+ category: "bash:trusted-workspace",
202
+ reason: "unknown command in trusted workspace",
203
+ };
204
+ }
205
+ if (!req.interactive) {
206
+ return {
207
+ decision: "deny",
208
+ category: "bash:unknown",
209
+ reason: `${c.reason} (denied: no interactive session to approve)`,
210
+ };
211
+ }
212
+ return { decision: "ask", category: "bash:trusted-workspace", reason: c.reason };
213
+ }
214
+ // Unrecognized command in an untrusted workspace. Both tiers get a human
215
+ // approval prompt when interactive -- a weak model is no longer hard-denied
216
+ // here, so a user who explicitly chose local execution can approve routine
217
+ // local work (run a script it just wrote, a compound/redirected command)
218
+ // instead of being stuck (#232). Nothing is auto-allowed: the silent pass
219
+ // stays reserved for a trusted model in a trusted workspace (above), and the
220
+ // catastrophic / credential-store / sensitive-read / jail floors are all
221
+ // enforced before this point, so this branch only governs the residual
222
+ // "command we can't reason about" case. A headless session still denies --
223
+ // there is no one to approve.
224
+ if (!req.interactive) {
225
+ return {
226
+ decision: "deny",
227
+ category: "bash:unknown",
228
+ reason: `${c.reason} (denied: no interactive session to approve)`,
229
+ };
230
+ }
231
+ return { decision: "ask", category: "bash:unknown", reason: c.reason };
232
+ }
233
+
234
+ if (FILE_READ_TOOLS.has(toolName)) {
235
+ // Each floor sweeps every target before the next one runs, so the strictest
236
+ // verdict wins no matter which key carries the offending path.
237
+ const targets = pathTargets(req, deps);
238
+ for (const t of targets) {
239
+ if (isCredentialStore(t.resolved, deps.home)) return denyCredentialStore(t.raw, deps.home);
240
+ }
241
+ for (const t of targets) {
242
+ if (isSensitivePath(t.resolved, deps.home)) {
243
+ return finalizeAsk(req, "read:sensitive", `${req.toolName} of sensitive path ${t.raw}`);
244
+ }
245
+ }
246
+ // Out-of-workspace reads prompt. Sensitive paths are floored above.
247
+ for (const t of targets) {
248
+ if (!t.inside) {
249
+ return finalizeAsk(req, "read:escape", `${req.toolName} outside workspace: ${t.raw}`);
250
+ }
251
+ }
252
+ return { decision: "allow", category: "read:ok", reason: "non-sensitive read" };
253
+ }
254
+
255
+ if (FILE_WRITE_TOOLS.has(toolName)) {
256
+ const targets = pathTargets(req, deps);
257
+ if (targets.length === 0) {
258
+ return finalizeAsk(req, "write:no-path", "write with no resolvable path");
259
+ }
260
+ // Credential-shaped writes are floored regardless of jail membership, mirroring
261
+ // the read branch -- a secret dropped inside the workspace is still a secret.
262
+ for (const t of targets) {
263
+ if (isSensitivePath(t.resolved, deps.home)) {
264
+ return finalizeAsk(req, "write:sensitive", `write to sensitive path ${t.raw}`);
265
+ }
266
+ }
267
+ // Gated even inside the jail: a script under .git/hooks runs on the next git
268
+ // operation, and .loom/ is Orbit's own state -- these always prompt, regardless
269
+ // of being in the workspace. The lone carve-out is the $HOME/.loom/analyses
270
+ // tree (Orbit's default cwd), where the analysis's own files are work product;
271
+ // a .git/.loom/.orbit nested inside an analysis still gates. See
272
+ // isProtectedWritePath.
273
+ //
274
+ // The path as written is checked as well as the realpath: a state dir that
275
+ // is itself a symlink (onto a bigger disk, say) realpaths to somewhere with
276
+ // no state segment, and since it is also a jail root the write would
277
+ // otherwise pass silently.
278
+ // The registry and provenance are a floor, not an ask: approving the
279
+ // model's write to its own approval record would make the approval mean
280
+ // nothing.
281
+ for (const t of targets) {
282
+ const lexical = path.resolve(req.cwd, expandHome(t.raw, deps.home));
283
+ if (isRecordStorePath(t.resolved) || isRecordStorePath(lexical)) {
284
+ return {
285
+ decision: "deny",
286
+ category: "write:record-store",
287
+ reason: `write to Orbit's harness-owned record ${t.raw} (approvals, run evaluations, provenance) blocked for all models`,
288
+ };
289
+ }
290
+ }
291
+ for (const t of targets) {
292
+ const lexical = path.resolve(req.cwd, expandHome(t.raw, deps.home));
293
+ if (isProtectedWritePath(t.resolved, deps.home) || isProtectedWritePath(lexical, deps.home)) {
294
+ return finalizeAsk(req, "write:protected", `write to protected path ${t.raw}`);
295
+ }
296
+ }
297
+ for (const t of targets) {
298
+ if (!t.inside) {
299
+ return finalizeAsk(req, "write:escape", `write outside workspace: ${t.raw}`);
300
+ }
301
+ }
302
+ return { decision: "allow", category: "write:in-jail", reason: "write inside workspace" };
303
+ }
304
+
305
+ // A tool that writes a local file it is handed a path for -- download_dataset
306
+ // with `file_path` is the one that exists -- must not land
307
+ // on the analysis record or the harness-owned registry, any more than the
308
+ // shell may. Lexical and resolved both, as for the write tools.
309
+ for (const [key, value] of LOCAL_WRITER_TOOL.test(toolName)
310
+ ? Object.entries(req.toolInput)
311
+ : []) {
312
+ if (typeof value !== "string" || !LOCAL_PATH_KEY.test(key) || value.length === 0) continue;
313
+ const lexical = path.resolve(req.cwd, expandHome(value, deps.home));
314
+ const { resolved } = deps.resolver.contains(value);
315
+ const recordFile = [lexical, resolved].some((p) =>
316
+ RECORD_BASENAMES.has(path.basename(p).toLowerCase()),
317
+ );
318
+ if (recordFile || isRecordStorePath(lexical) || isRecordStorePath(resolved)) {
319
+ return {
320
+ decision: "deny",
321
+ category: "write:record-store",
322
+ reason: `${req.toolName} would write ${value}, part of the analysis record`,
323
+ };
324
+ }
325
+ }
326
+
327
+ // Destructive Galaxy operations (whole-history delete/purge) -- called directly or
328
+ // dispatched through the code-mode run_galaxy_tool envelope -- must be confirmed
329
+ // regardless of tier (#338). Non-destructive Galaxy/MCP tools fall through to the allow.
330
+ {
331
+ const op = classifyGalaxyDestructive(toolName, req.toolInput);
332
+ if (op) return destructiveGalaxy(req, op);
333
+ }
334
+
335
+ // Everything else is allowed: Galaxy/notebook tools, web fetchers, MCP. These are
336
+ // the remote/egress surface (notebook_push_to_galaxy, galaxy_upload_*/run_user_tool,
337
+ // skills_fetch's ~/.loom cache write) and are deliberately OUT of scope
338
+ // for the working-dir write-jail -- a local write boundary cannot and does not
339
+ // promise anything about data leaving the machine. Gating egress is separate future
340
+ // work; do not let this fallthrough be read as "confined".
341
+ return { decision: "allow", category: "other", reason: "non-local-execution tool" };
342
+ }