@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,1482 @@
1
+ # Galaxy Apply Rules DSL Research
2
+
3
+ ## Context
4
+
5
+ The Apply Rules tool (`__APPLY_RULES__`) is Galaxy's most powerful collection manipulation tool. It processes collection metadata as tabular data and applies transformation rules to filter, reorganize, nest, flatten, and modify collections. This document provides comprehensive documentation of the rules DSL (Domain-Specific Language).
6
+
7
+ **Key principle:** Rules transform collection metadata (identifiers, indices, tags) as tabular data, then map columns back to create new collection structures.
8
+
9
+ ## Rules DSL Architecture
10
+
11
+ ### Core Concepts
12
+
13
+ **Data Model:**
14
+ ```
15
+ data: [[cell values]] # 2D array of strings (tabular data)
16
+ sources: [source objects] # Metadata for each row (identifiers, indices, tags)
17
+ ```
18
+
19
+ **Execution Flow:**
20
+ 1. Collection metadata extracted to tabular format
21
+ 2. Rules applied sequentially to transform data
22
+ 3. Mapping operations convert transformed data to new collection
23
+
24
+ **Example:**
25
+ ```
26
+ Input collection: list [i1, i2]
27
+
28
+ Initial state:
29
+ data: [["value1"], ["value2"]]
30
+ sources: [
31
+ {"identifiers": ["i1"], "indices": [0]},
32
+ {"identifiers": ["i2"], "indices": [1]}
33
+ ]
34
+
35
+ After rules:
36
+ data: [["value1", "i1"], ["value2", "i2"]] # Added identifier column
37
+
38
+ After mapping:
39
+ Output collection: list [i1, i2]
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Rule Operations
45
+
46
+ Rules are applied **sequentially** in the order specified. Each rule transforms the data table.
47
+
48
+ ### 1. Column Addition Rules
49
+
50
+ #### add_column_basename
51
+
52
+ **Purpose:** Extract basename from file paths
53
+
54
+ **Parameters:**
55
+ - `target_column` (int): Column containing paths
56
+
57
+ **Example:**
58
+ ```yaml
59
+ rules:
60
+ - type: add_column_basename
61
+ target_column: 0
62
+ ```
63
+
64
+ **Transformation:**
65
+ ```
66
+ Input: [["/path/to/moo.txt"], ["moo.txt"]]
67
+ Output: [["/path/to/moo.txt", "moo.txt"], ["moo.txt", "moo.txt"]]
68
+ ```
69
+
70
+ **Use cases:**
71
+ - Extract filenames from full paths
72
+ - Create identifiers from uploaded file paths
73
+ - Normalize identifiers across different upload methods
74
+
75
+ ---
76
+
77
+ #### add_column_regex
78
+
79
+ **Purpose:** Capture regex groups or perform replacements
80
+
81
+ **Parameters:**
82
+ - `target_column` (int): Column to process
83
+ - `expression` (string): Regular expression pattern
84
+ - `replacement` (string, optional): Replacement template with `\1`, `\2` for groups
85
+ - `group_count` (int, optional): Number of groups to capture as separate columns
86
+ - `allow_unmatched` (bool, default: false): If false, errors on unmatched rows
87
+
88
+ **Mode 1: Simple capture (default)**
89
+ ```yaml
90
+ rules:
91
+ - type: add_column_regex
92
+ target_column: 0
93
+ expression: '(o)+'
94
+ ```
95
+ ```
96
+ Input: [["foo"], ["cow"]]
97
+ Output: [["foo", "oo"], ["cow", "o"]]
98
+ ```
99
+
100
+ **Mode 2: Replacement**
101
+ ```yaml
102
+ rules:
103
+ - type: add_column_regex
104
+ target_column: 0
105
+ expression: '(o+)'
106
+ replacement: 'the os \1'
107
+ ```
108
+ ```
109
+ Input: [["foo"], ["cow"]]
110
+ Output: [["foo", "the os oo"], ["cow", "the os o"]]
111
+ ```
112
+
113
+ **Mode 3: Multiple groups**
114
+ ```yaml
115
+ rules:
116
+ - type: add_column_regex
117
+ target_column: 0
118
+ expression: '.*(o)(o)'
119
+ group_count: 2
120
+ ```
121
+ ```
122
+ Input: [["foo"], ["boo"]]
123
+ Output: [["foo", "o", "o"], ["boo", "o", "o"]]
124
+ ```
125
+
126
+ **Mode 4: Allow unmatched**
127
+ ```yaml
128
+ rules:
129
+ - type: add_column_regex
130
+ target_column: 0
131
+ expression: '(o)+'
132
+ allow_unmatched: true
133
+ ```
134
+ ```
135
+ Input: [["foo"], ["cow"], ["cat"]]
136
+ Output: [["foo", "oo"], ["cow", "o"], ["cat", ""]]
137
+ ```
138
+
139
+ **Use cases:**
140
+ - Extract sample names from filenames (e.g., `sample_(\w+)_R1.fastq`)
141
+ - Parse structured identifiers (e.g., `TCGA-(\w+)-(\d+)`)
142
+ - Clean up identifiers (remove prefixes/suffixes)
143
+ - Extract metadata embedded in filenames
144
+
145
+ **Common patterns:**
146
+ ```yaml
147
+ # Extract sample ID from "sample_123_R1.fastq"
148
+ expression: 'sample_(\w+)_R\d'
149
+
150
+ # Extract prefix before underscore
151
+ expression: '([^_]+)_.*'
152
+
153
+ # Extract everything before last dot
154
+ expression: '(.+)\.[^.]+$'
155
+ ```
156
+
157
+ ---
158
+
159
+ #### add_column_substr
160
+
161
+ **Purpose:** Extract or remove fixed-length substrings
162
+
163
+ **Parameters:**
164
+ - `target_column` (int): Column to process
165
+ - `substr_type` (enum): Operation type
166
+ - `keep_prefix`: Keep first N characters
167
+ - `keep_suffix`: Keep last N characters
168
+ - `drop_prefix`: Remove first N characters
169
+ - `drop_suffix`: Remove last N characters
170
+ - `length` (int): Number of characters
171
+
172
+ **Examples:**
173
+ ```yaml
174
+ # Keep first 2 characters
175
+ rules:
176
+ - type: add_column_substr
177
+ target_column: 0
178
+ substr_type: keep_prefix
179
+ length: 2
180
+ ```
181
+ ```
182
+ Input: [["foo"], ["cow"], ["ba"], ["d"]]
183
+ Output: [["foo", "fo"], ["cow", "co"], ["ba", "ba"], ["d", "d"]]
184
+ ```
185
+
186
+ ```yaml
187
+ # Drop last 2 characters
188
+ rules:
189
+ - type: add_column_substr
190
+ target_column: 0
191
+ substr_type: drop_suffix
192
+ length: 2
193
+ ```
194
+ ```
195
+ Input: [["foo"], ["cow"], ["ba"], ["d"]]
196
+ Output: [["foo", "f"], ["cow", "c"], ["ba", ""], ["d", ""]]
197
+ ```
198
+
199
+ **Use cases:**
200
+ - Remove common prefixes/suffixes
201
+ - Extract barcodes from fixed positions
202
+ - Truncate long identifiers
203
+
204
+ ---
205
+
206
+ #### add_column_rownum
207
+
208
+ **Purpose:** Add sequential row numbers
209
+
210
+ **Parameters:**
211
+ - `start` (int): Starting number (0 or 1)
212
+
213
+ **Example:**
214
+ ```yaml
215
+ rules:
216
+ - type: add_column_rownum
217
+ start: 1
218
+ ```
219
+ ```
220
+ Input: [["foo"], ["cow"], ["ba"], ["d"]]
221
+ Output: [["foo", "1"], ["cow", "2"], ["ba", "3"], ["d", "4"]]
222
+ ```
223
+
224
+ **Use cases:**
225
+ - Create numerical identifiers
226
+ - Track original row order after sorting
227
+ - Generate replicate numbers
228
+
229
+ ---
230
+
231
+ #### add_column_value
232
+
233
+ **Purpose:** Add constant value to all rows
234
+
235
+ **Parameters:**
236
+ - `value` (string): Constant value
237
+
238
+ **Example:**
239
+ ```yaml
240
+ rules:
241
+ - type: add_column_value
242
+ value: "control"
243
+ ```
244
+ ```
245
+ Input: [["foo"], ["cow"]]
246
+ Output: [["foo", "control"], ["cow", "control"]]
247
+ ```
248
+
249
+ **Use cases:**
250
+ - Add condition labels (treatment/control)
251
+ - Add constant metadata
252
+ - Create separator columns for concatenation
253
+
254
+ ---
255
+
256
+ #### add_column_concatenate
257
+
258
+ **Purpose:** Combine two columns into one
259
+
260
+ **Parameters:**
261
+ - `target_column_0` (int): First column
262
+ - `target_column_1` (int): Second column
263
+
264
+ **Example:**
265
+ ```yaml
266
+ rules:
267
+ - type: add_column_concatenate
268
+ target_column_0: 0
269
+ target_column_1: 1
270
+ ```
271
+ ```
272
+ Input: [["sample", "001"], ["sample", "002"]]
273
+ Output: [["sample", "001", "sample001"], ["sample", "002", "sample002"]]
274
+ ```
275
+
276
+ **Use cases:**
277
+ - Combine sample ID + replicate number
278
+ - Build hierarchical identifiers
279
+ - Create unique identifiers from multiple parts
280
+
281
+ **Common pattern - add separator:**
282
+ ```yaml
283
+ rules:
284
+ - type: add_column_value
285
+ value: "_"
286
+ - type: add_column_concatenate
287
+ target_column_0: 0
288
+ target_column_1: 2 # The "_" column
289
+ - type: add_column_concatenate
290
+ target_column_0: 3
291
+ target_column_1: 1 # Result + second original column
292
+ ```
293
+
294
+ ---
295
+
296
+ #### add_column_metadata
297
+
298
+ **Purpose:** Extract metadata from source objects
299
+
300
+ **Parameters:**
301
+ - `value` (enum): Metadata type
302
+ - `identifier0`, `identifier1`, `identifier2`, ...
303
+ - `index0`, `index1`, `index2`, ...
304
+ - `tags`
305
+
306
+ **Identifier extraction:**
307
+ ```yaml
308
+ rules:
309
+ - type: add_column_metadata
310
+ value: identifier0 # Outermost identifier
311
+ ```
312
+ ```
313
+ Input: [["moo"], ["meow"], ["bark"]]
314
+ Sources: [{"identifiers": ["cow"]}, {"identifiers": ["cat"]}, {"identifiers": ["dog"]}]
315
+ Output: [["moo", "cow"], ["meow", "cat"], ["bark", "dog"]]
316
+ ```
317
+
318
+ **Multiple levels:**
319
+ ```yaml
320
+ rules:
321
+ - type: add_column_metadata
322
+ value: identifier0 # Outer identifier
323
+ - type: add_column_metadata
324
+ value: identifier1 # Inner identifier
325
+ ```
326
+ ```
327
+ Sources: [
328
+ {"identifiers": ["sample1", "forward"]},
329
+ {"identifiers": ["sample1", "reverse"]}
330
+ ]
331
+ Output: [["data", "sample1", "forward"], ["data", "sample1", "reverse"]]
332
+ ```
333
+
334
+ **Index extraction:**
335
+ ```yaml
336
+ rules:
337
+ - type: add_column_metadata
338
+ value: index0
339
+ - type: add_column_metadata
340
+ value: index1
341
+ ```
342
+ ```
343
+ Sources: [
344
+ {"indices": [0, 0]}, # First sample, forward
345
+ {"indices": [0, 1]}, # First sample, reverse
346
+ {"indices": [1, 0]}, # Second sample, forward
347
+ {"indices": [1, 1]} # Second sample, reverse
348
+ ]
349
+ Output: [
350
+ ["samp1for", "0", "0"],
351
+ ["samp1rev", "0", "1"],
352
+ ["samp2for", "1", "0"],
353
+ ["samp2rev", "1", "1"]
354
+ ]
355
+ ```
356
+
357
+ **Tags extraction:**
358
+ ```yaml
359
+ rules:
360
+ - type: add_column_metadata
361
+ value: tags
362
+ ```
363
+ ```
364
+ Sources: [
365
+ {"identifiers": ["cow"], "tags": ["farm"]},
366
+ {"identifiers": ["dog"], "tags": ["house", "firestation"]}
367
+ ]
368
+ Output: [["moo", "farm"], ["bark", "firestation,house"]] # Sorted, comma-joined
369
+ ```
370
+
371
+ **Use cases:**
372
+ - Access collection structure metadata
373
+ - Build identifiers from nested collections
374
+ - Use positional indices for numerical IDs
375
+ - Extract tags for grouping/filtering
376
+
377
+ ---
378
+
379
+ #### add_column_group_tag_value
380
+
381
+ **Purpose:** Extract specific group tag value
382
+
383
+ **Parameters:**
384
+ - `value` (string): Group tag name (e.g., "condition", "type")
385
+ - `default_value` (string): Value if tag not present
386
+
387
+ **Example:**
388
+ ```yaml
389
+ rules:
390
+ - type: add_column_group_tag_value
391
+ value: condition
392
+ default_value: 'control'
393
+ ```
394
+ ```
395
+ Sources: [
396
+ {"tags": ["group:condition:treated"]},
397
+ {"tags": ["group:condition:control"]},
398
+ {"tags": []} # No condition tag
399
+ ]
400
+ Output: [["data", "treated"], ["data", "control"], ["data", "control"]]
401
+ ```
402
+
403
+ **Multiple tags - first alphabetically wins:**
404
+ ```yaml
405
+ rules:
406
+ - type: add_column_group_tag_value
407
+ value: where
408
+ default_value: 'barn'
409
+ ```
410
+ ```
411
+ Sources: [
412
+ {"tags": ["group:where:house", "group:where:firestation"]}
413
+ ]
414
+ Output: [["data", "firestation"]] # "firestation" < "house" alphabetically
415
+ ```
416
+
417
+ **Use cases:**
418
+ - Group samples by experimental condition
419
+ - Extract sample type (single-end/paired-end)
420
+ - Use tags for nested collection organization
421
+
422
+ ---
423
+
424
+ #### add_column_from_sample_sheet_index
425
+
426
+ **Purpose:** Retrieve values from sample sheet columns
427
+
428
+ **Parameters:**
429
+ - `value` (int): Sample sheet column index
430
+
431
+ **Example:**
432
+ ```yaml
433
+ rules:
434
+ - type: add_column_from_sample_sheet_index
435
+ value: 0
436
+ - type: add_column_from_sample_sheet_index
437
+ value: 1
438
+ ```
439
+ ```
440
+ Sources: [
441
+ {"columns": [0, 1]},
442
+ {"columns": [2, 3]}
443
+ ]
444
+ Output: [["moo", 0, 1], ["cow", 2, 3]]
445
+ ```
446
+
447
+ **Use cases:**
448
+ - Extract metadata from uploaded sample sheets
449
+ - Access additional columns beyond identifiers
450
+ - Incorporate external metadata
451
+
452
+ ---
453
+
454
+ ### 2. Filter Rules
455
+
456
+ Filters **remove rows** from the data table based on conditions.
457
+
458
+ #### add_filter_regex
459
+
460
+ **Purpose:** Keep/remove rows matching pattern
461
+
462
+ **Parameters:**
463
+ - `target_column` (int): Column to test
464
+ - `expression` (string): Regular expression
465
+ - `invert` (bool, default: false): If true, keep non-matching rows
466
+
467
+ **Keep matching:**
468
+ ```yaml
469
+ rules:
470
+ - type: add_filter_regex
471
+ target_column: 0
472
+ expression: '(a+)'
473
+ invert: false
474
+ ```
475
+ ```
476
+ Input: [["a", "b", "c"], ["e", "f", "g"]]
477
+ Output: [["a", "b", "c"]]
478
+ ```
479
+
480
+ **Remove matching:**
481
+ ```yaml
482
+ rules:
483
+ - type: add_filter_regex
484
+ target_column: 2
485
+ expression: '(c+)'
486
+ invert: true
487
+ ```
488
+ ```
489
+ Input: [["a", "b", "c"], ["e", "f", "g"]]
490
+ Output: [["e", "f", "g"]]
491
+ ```
492
+
493
+ **Use cases:**
494
+ - Filter by sample name pattern
495
+ - Remove control samples
496
+ - Select specific file types
497
+
498
+ ---
499
+
500
+ #### add_filter_count
501
+
502
+ **Purpose:** Keep/remove first or last N rows
503
+
504
+ **Parameters:**
505
+ - `count` (int): Number of rows
506
+ - `which` (enum): `first` or `last`
507
+ - `invert` (bool, default: false): If true, reverse filter
508
+
509
+ **Remove first row:**
510
+ ```yaml
511
+ rules:
512
+ - type: add_filter_count
513
+ count: 1
514
+ which: first
515
+ invert: false # Remove first, keep rest
516
+ ```
517
+ ```
518
+ Input: [["a", "b", "c"], ["e", "f", "g"], ["h", "i", "j"]]
519
+ Output: [["e", "f", "g"], ["h", "i", "j"]]
520
+ ```
521
+
522
+ **Keep only last row:**
523
+ ```yaml
524
+ rules:
525
+ - type: add_filter_count
526
+ count: 1
527
+ which: last
528
+ invert: true # Remove all but last
529
+ ```
530
+ ```
531
+ Input: [["a", "b", "c"], ["e", "f", "g"], ["h", "i", "j"]]
532
+ Output: [["h", "i", "j"]]
533
+ ```
534
+
535
+ **Use cases:**
536
+ - Remove header rows
537
+ - Skip first N samples
538
+ - Select specific replicates
539
+
540
+ ---
541
+
542
+ #### add_filter_empty
543
+
544
+ **Purpose:** Remove rows with empty cells
545
+
546
+ **Parameters:**
547
+ - `target_column` (int): Column to check
548
+ - `invert` (bool, default: false): If true, keep only empty
549
+
550
+ **Remove empty:**
551
+ ```yaml
552
+ rules:
553
+ - type: add_filter_empty
554
+ target_column: 0
555
+ invert: false
556
+ ```
557
+ ```
558
+ Input: [["", "b", "c"], ["a", "b", "c"]]
559
+ Output: [["a", "b", "c"]]
560
+ ```
561
+
562
+ **Use cases:**
563
+ - Remove rows with missing identifiers
564
+ - Clean up sparse data
565
+ - Filter failed extractions
566
+
567
+ ---
568
+
569
+ #### add_filter_matches
570
+
571
+ **Purpose:** Exact value matching (case-sensitive)
572
+
573
+ **Parameters:**
574
+ - `value` (string): Exact value to match
575
+ - `target_column` (int): Column to check
576
+ - `invert` (bool, default: false): If true, keep non-matching
577
+
578
+ **Example:**
579
+ ```yaml
580
+ rules:
581
+ - type: add_filter_matches
582
+ value: "a"
583
+ target_column: 0
584
+ invert: false
585
+ ```
586
+ ```
587
+ Input: [["a", "b", "c"], ["e", "f", "g"], ["h", "i", "j"]]
588
+ Output: [["a", "b", "c"]]
589
+ ```
590
+
591
+ **Important:** Exact match only, no partial matches:
592
+ ```yaml
593
+ rules:
594
+ - type: add_filter_matches
595
+ value: "a"
596
+ target_column: 1
597
+ ```
598
+ ```
599
+ Input: [["a ", "b", "c"]] # Note space after "a"
600
+ Output: [] # No match - "a " != "a"
601
+ ```
602
+
603
+ **Use cases:**
604
+ - Filter by specific sample ID
605
+ - Select exact condition matches
606
+ - Boolean filtering (match "true"/"false")
607
+
608
+ ---
609
+
610
+ #### add_filter_compare
611
+
612
+ **Purpose:** Numeric comparisons
613
+
614
+ **Parameters:**
615
+ - `target_column` (int): Column with numeric values
616
+ - `value` (number): Comparison value
617
+ - `compare_type` (enum):
618
+ - `less_than`
619
+ - `less_than_equal`
620
+ - `greater_than`
621
+ - `greater_than_equal`
622
+
623
+ **Example:**
624
+ ```yaml
625
+ rules:
626
+ - type: add_filter_compare
627
+ target_column: 0
628
+ value: 13
629
+ compare_type: less_than
630
+ ```
631
+ ```
632
+ Input: [["1", "moo"], ["10", "cow"], ["13", "rat"], ["20", "dog"]]
633
+ Output: [["1", "moo"], ["10", "cow"]]
634
+ ```
635
+
636
+ **Use cases:**
637
+ - Filter by quality scores
638
+ - Select samples by replicate number
639
+ - Threshold-based filtering
640
+
641
+ ---
642
+
643
+ ### 3. Structural Rules
644
+
645
+ #### remove_columns
646
+
647
+ **Purpose:** Delete specified columns
648
+
649
+ **Parameters:**
650
+ - `target_columns` (list[int]): Column indices to remove
651
+
652
+ **Example:**
653
+ ```yaml
654
+ rules:
655
+ - type: remove_columns
656
+ target_columns: [0, 1]
657
+ ```
658
+ ```
659
+ Input: [["a", "b", "c"], ["e", "f", "g"]]
660
+ Output: [["c"], ["g"]]
661
+ ```
662
+
663
+ **Use cases:**
664
+ - Clean up intermediate columns
665
+ - Remove temporary concatenation columns
666
+ - Keep only final identifier columns
667
+
668
+ ---
669
+
670
+ #### sort
671
+
672
+ **Purpose:** Sort rows by column value
673
+
674
+ **Parameters:**
675
+ - `target_column` (int): Column to sort by
676
+ - `numeric` (bool): If true, numeric sort; if false, alphabetic
677
+
678
+ **Alphabetic sort:**
679
+ ```yaml
680
+ rules:
681
+ - type: sort
682
+ numeric: false
683
+ target_column: 0
684
+ ```
685
+ ```
686
+ Input: [["moo", "cow"], ["meow", "cat"], ["bark", "dog"]]
687
+ Output: [["bark", "dog"], ["meow", "cat"], ["moo", "cow"]]
688
+ ```
689
+
690
+ **Note:** Case-sensitive, uppercase sorts before lowercase
691
+ ```
692
+ Input: [["Dog"], ["cat"], ["cow"]]
693
+ Output: [["Dog"], ["cat"], ["cow"]] # "Dog" < "cat" < "cow"
694
+ ```
695
+
696
+ **Use cases:**
697
+ - Alphabetize samples
698
+ - Order by numerical IDs
699
+ - Group similar identifiers together
700
+
701
+ ---
702
+
703
+ #### swap_columns
704
+
705
+ **Purpose:** Exchange two column positions
706
+
707
+ **Parameters:**
708
+ - `target_column_0` (int): First column
709
+ - `target_column_1` (int): Second column
710
+
711
+ **Example:**
712
+ ```yaml
713
+ rules:
714
+ - type: swap_columns
715
+ target_column_0: 0
716
+ target_column_1: 1
717
+ ```
718
+ ```
719
+ Input: [["moo", "cow"], ["meow", "cat"]]
720
+ Output: [["cow", "moo"], ["cat", "meow"]]
721
+ ```
722
+
723
+ **Use cases:**
724
+ - Reorder identifier columns for mapping
725
+ - Fix column order mistakes
726
+ - Prepare for specific mapping requirements
727
+
728
+ ---
729
+
730
+ #### split_columns
731
+
732
+ **Purpose:** Create Cartesian product of column groups (split rows)
733
+
734
+ **Parameters:**
735
+ - `target_columns_0` (list[int]): First column group
736
+ - `target_columns_1` (list[int]): Second column group
737
+
738
+ **Example:**
739
+ ```yaml
740
+ rules:
741
+ - type: split_columns
742
+ target_columns_0: [0]
743
+ target_columns_1: [1]
744
+ ```
745
+ ```
746
+ Input: [["moo", "cow", "A"], ["meow", "cat", "B"]]
747
+ Output: [
748
+ ["moo", "A"],
749
+ ["cow", "A"],
750
+ ["meow", "B"],
751
+ ["cat", "B"]
752
+ ]
753
+ ```
754
+
755
+ **How it works:**
756
+ - For each row, creates N×M new rows where:
757
+ - N = number of columns in group 0
758
+ - M = number of columns in group 1
759
+ - Each new row contains one value from group 0 + one value from group 1 + all other columns
760
+
761
+ **Use cases:**
762
+ - Split paired-end data into forward/reverse
763
+ - Expand multiple samples per row
764
+ - Create all combinations for comparisons
765
+
766
+ ---
767
+
768
+ ## Mapping Operations
769
+
770
+ Mapping operations define how transformed data columns become collection structure. These are the **final step** that converts tabular data back to collections.
771
+
772
+ ### Available Mapping Types
773
+
774
+ #### list_identifiers
775
+
776
+ **Purpose:** Create list structure with specified nesting levels
777
+
778
+ **Parameters:**
779
+ - `columns` (list[int]): Column indices for identifiers
780
+
781
+ **Single column = simple list:**
782
+ ```yaml
783
+ mapping:
784
+ - type: list_identifiers
785
+ columns: [0]
786
+ ```
787
+ ```
788
+ Data: [["sample1"], ["sample2"]]
789
+ Result: list [sample1, sample2]
790
+ ```
791
+
792
+ **Two columns = nested list:list:**
793
+ ```yaml
794
+ mapping:
795
+ - type: list_identifiers
796
+ columns: [0, 1]
797
+ ```
798
+ ```
799
+ Data: [["group1", "s1"], ["group1", "s2"], ["group2", "s3"]]
800
+ Result: list:list [
801
+ group1 → [s1, s2],
802
+ group2 → [s3]
803
+ ]
804
+ ```
805
+
806
+ **Three columns = list:list:list:**
807
+ ```yaml
808
+ mapping:
809
+ - type: list_identifiers
810
+ columns: [0, 1, 2]
811
+ ```
812
+
813
+ **Nesting logic:**
814
+ - Column 0 = outermost identifier
815
+ - Column 1 = next level identifier
816
+ - Column 2 = innermost identifier
817
+ - Groups rows by matching outer identifiers
818
+
819
+ ---
820
+
821
+ #### paired_identifier
822
+
823
+ **Purpose:** Add paired collection level
824
+
825
+ **Parameters:**
826
+ - `columns` (list[int]): Single column with paired identifier
827
+
828
+ **Simple paired:**
829
+ ```yaml
830
+ mapping:
831
+ - type: paired_identifier
832
+ columns: [0]
833
+ ```
834
+ ```
835
+ Data: [["forward"], ["reverse"]]
836
+ Result: paired {forward, reverse}
837
+ ```
838
+
839
+ **Combined with list:**
840
+ ```yaml
841
+ mapping:
842
+ - type: list_identifiers
843
+ columns: [0]
844
+ - type: paired_identifier
845
+ columns: [1]
846
+ ```
847
+ ```
848
+ Data: [
849
+ ["sample1", "forward"],
850
+ ["sample1", "reverse"],
851
+ ["sample2", "forward"],
852
+ ["sample2", "reverse"]
853
+ ]
854
+ Result: list:paired [
855
+ sample1 → {forward, reverse},
856
+ sample2 → {forward, reverse}
857
+ ]
858
+ ```
859
+
860
+ ---
861
+
862
+ #### tags
863
+
864
+ **Purpose:** Apply tags to collection elements
865
+
866
+ **Parameters:**
867
+ - `columns` (list[int]): Columns containing tag values
868
+
869
+ **Example:**
870
+ ```yaml
871
+ mapping:
872
+ - type: list_identifiers
873
+ columns: [0]
874
+ - type: tags
875
+ columns: [1]
876
+ ```
877
+ ```
878
+ Data: [["sample1", "replicate1"], ["sample2", "replicate2"]]
879
+ Result: list with tags [
880
+ sample1 (tags: ["replicate1"]),
881
+ sample2 (tags: ["replicate2"])
882
+ ]
883
+ ```
884
+
885
+ ---
886
+
887
+ #### group_tags
888
+
889
+ **Purpose:** Apply group tags (format: `group:name:value`)
890
+
891
+ **Parameters:**
892
+ - `columns` (list[int]): Columns containing group tag values
893
+
894
+ **Example:**
895
+ ```yaml
896
+ mapping:
897
+ - type: list_identifiers
898
+ columns: [1, 0] # Group by column 1, element ID column 0
899
+ - type: group_tags
900
+ columns: [1] # Apply as group tag
901
+ ```
902
+ ```
903
+ Data: [["s1", "treated"], ["s2", "control"]]
904
+ Result: list:list with group tags [
905
+ treated → [s1 (tags: ["group:treated"])],
906
+ control → [s2 (tags: ["group:control"])]
907
+ ]
908
+ ```
909
+
910
+ ---
911
+
912
+ ## Complete Example: list:record to list:paired
913
+
914
+ This example demonstrates complex transformation combining multiple rule types:
915
+
916
+ **Goal:** Convert `list:record` collection where records have "mother" and "child" elements into `list:paired` with "forward" and "reverse".
917
+
918
+ ```yaml
919
+ rules:
920
+ - type: add_column_metadata
921
+ value: identifier0 # Sample identifier
922
+ - type: add_column_metadata
923
+ value: identifier1 # Record type (mother/father/child)
924
+ - type: add_column_regex
925
+ target_column: 2
926
+ expression: 'mother'
927
+ replacement: 'forward'
928
+ allow_unmatched: true # Leaves others as ""
929
+ - type: add_column_regex
930
+ target_column: 2
931
+ expression: 'child'
932
+ replacement: 'reverse'
933
+ allow_unmatched: true
934
+ - type: add_column_concatenate
935
+ target_column_0: 3 # Result of first regex
936
+ target_column_1: 4 # Result of second regex
937
+ - type: add_filter_empty
938
+ target_column: 5 # Remove rows that didn't match (father)
939
+ invert: false
940
+ - type: remove_columns
941
+ target_columns: [2, 3, 4] # Clean up intermediate columns
942
+
943
+ mapping:
944
+ - type: list_identifiers
945
+ columns: [1, 2] # Sample ID, then forward/reverse
946
+ ```
947
+
948
+ **Transformation steps:**
949
+
950
+ ```
951
+ Initial:
952
+ data: [["el1"], ["el2"], ["el3"]]
953
+ sources: [
954
+ {"identifiers": ["samp1", "mother"]},
955
+ {"identifiers": ["samp1", "father"]},
956
+ {"identifiers": ["samp1", "child"]}
957
+ ]
958
+
959
+ After add_column_metadata (identifier0, identifier1):
960
+ [["el1", "samp1", "mother"],
961
+ ["el2", "samp1", "father"],
962
+ ["el3", "samp1", "child"]]
963
+
964
+ After first regex (mother → forward):
965
+ [["el1", "samp1", "mother", "forward"],
966
+ ["el2", "samp1", "father", ""],
967
+ ["el3", "samp1", "child", ""]]
968
+
969
+ After second regex (child → reverse):
970
+ [["el1", "samp1", "mother", "forward", ""],
971
+ ["el2", "samp1", "father", "", ""],
972
+ ["el3", "samp1", "child", "", "reverse"]]
973
+
974
+ After concatenate (cols 3+4):
975
+ [["el1", "samp1", "mother", "forward", "", "forward"],
976
+ ["el2", "samp1", "father", "", "", ""],
977
+ ["el3", "samp1", "child", "", "reverse", "reverse"]]
978
+
979
+ After filter empty (col 5):
980
+ [["el1", "samp1", "mother", "forward", "", "forward"],
981
+ ["el3", "samp1", "child", "", "reverse", "reverse"]]
982
+
983
+ After remove_columns [2, 3, 4]:
984
+ [["el1", "samp1", "forward"],
985
+ ["el3", "samp1", "reverse"]]
986
+
987
+ Final mapping with list_identifiers [1, 2]:
988
+ Result: list:paired [
989
+ samp1 → {forward, reverse}
990
+ ]
991
+ ```
992
+
993
+ ---
994
+
995
+ ## Rule Composition Patterns
996
+
997
+ ### Pattern 1: Extract and Flatten
998
+
999
+ **Goal:** Flatten `list:paired` → `list` with combined identifiers
1000
+
1001
+ ```yaml
1002
+ rules:
1003
+ - type: add_column_metadata
1004
+ value: identifier0 # Outer ID
1005
+ - type: add_column_metadata
1006
+ value: identifier1 # Pair ID (forward/reverse)
1007
+ - type: add_column_concatenate
1008
+ target_column_0: 1
1009
+ target_column_1: 2 # Combine them
1010
+
1011
+ mapping:
1012
+ - type: list_identifiers
1013
+ columns: [3] # Use concatenated column
1014
+ ```
1015
+
1016
+ ---
1017
+
1018
+ ### Pattern 2: Group by Tag
1019
+
1020
+ **Goal:** Reorganize by tag value into nested structure
1021
+
1022
+ ```yaml
1023
+ rules:
1024
+ - type: add_column_metadata
1025
+ value: identifier0
1026
+ - type: add_column_group_tag_value
1027
+ value: condition # Extract "condition" tag
1028
+ default_value: "unassigned"
1029
+
1030
+ mapping:
1031
+ - type: list_identifiers
1032
+ columns: [1, 0] # Group by condition, then sample ID
1033
+ - type: group_tags
1034
+ columns: [1] # Apply as group tags
1035
+ ```
1036
+
1037
+ ---
1038
+
1039
+ ### Pattern 3: Filter and Sort
1040
+
1041
+ **Goal:** Select subset and alphabetize
1042
+
1043
+ ```yaml
1044
+ rules:
1045
+ - type: add_column_metadata
1046
+ value: identifier0
1047
+ - type: add_filter_regex
1048
+ target_column: 0
1049
+ expression: '^control_' # Only controls
1050
+ invert: false
1051
+ - type: sort
1052
+ numeric: false
1053
+ target_column: 0
1054
+
1055
+ mapping:
1056
+ - type: list_identifiers
1057
+ columns: [0]
1058
+ ```
1059
+
1060
+ ---
1061
+
1062
+ ### Pattern 4: Parse Filename Structure
1063
+
1064
+ **Goal:** Extract sample info from "sample_123_R1.fastq.gz" format
1065
+
1066
+ ```yaml
1067
+ rules:
1068
+ - type: add_column_metadata
1069
+ value: identifier0 # Original filename
1070
+ - type: add_column_regex
1071
+ target_column: 0
1072
+ expression: 'sample_(\w+)_R(\d)'
1073
+ group_count: 2 # Sample ID and read number
1074
+ - type: add_column_value
1075
+ value: "_R"
1076
+ - type: add_column_concatenate
1077
+ target_column_0: 3
1078
+ target_column_1: 2 # "_R" + "1" = "_R1"
1079
+ - type: add_column_concatenate
1080
+ target_column_0: 1
1081
+ target_column_1: 4 # "123" + "_R1" = "123_R1"
1082
+ - type: remove_columns
1083
+ target_columns: [0, 2, 3, 4] # Keep only final identifier
1084
+
1085
+ mapping:
1086
+ - type: list_identifiers
1087
+ columns: [0]
1088
+ ```
1089
+
1090
+ ---
1091
+
1092
+ ### Pattern 5: Create Paired from Separate Lists
1093
+
1094
+ **Goal:** Combine separate forward/reverse lists into paired
1095
+
1096
+ **Assumption:** Files named like `sample1_R1.fastq`, `sample1_R2.fastq`
1097
+
1098
+ ```yaml
1099
+ rules:
1100
+ - type: add_column_metadata
1101
+ value: identifier0
1102
+ - type: add_column_regex
1103
+ target_column: 0
1104
+ expression: '(.+)_R([12])'
1105
+ group_count: 2 # Sample name and read number
1106
+ - type: add_column_regex
1107
+ target_column: 2
1108
+ expression: '1'
1109
+ replacement: 'forward'
1110
+ allow_unmatched: true
1111
+ - type: add_column_regex
1112
+ target_column: 2
1113
+ expression: '2'
1114
+ replacement: 'reverse'
1115
+ allow_unmatched: true
1116
+ - type: add_column_concatenate
1117
+ target_column_0: 3
1118
+ target_column_1: 4
1119
+ - type: sort
1120
+ numeric: false
1121
+ target_column: 1 # Ensure pairs adjacent
1122
+ - type: remove_columns
1123
+ target_columns: [0, 2, 3, 4]
1124
+
1125
+ mapping:
1126
+ - type: list_identifiers
1127
+ columns: [0] # Sample ID
1128
+ - type: paired_identifier
1129
+ columns: [1] # forward/reverse
1130
+ ```
1131
+
1132
+ ---
1133
+
1134
+ ## Best Practices
1135
+
1136
+ ### 1. Plan Column Layout
1137
+
1138
+ Before writing rules, sketch the transformations:
1139
+ ```
1140
+ Col 0: Original identifier
1141
+ Col 1: Extracted sample ID (regex)
1142
+ Col 2: Extracted replicate (regex)
1143
+ Col 3: Separator "_"
1144
+ Col 4: Concatenate 1+3+2
1145
+ Col 5: Final identifier after cleanup
1146
+ ```
1147
+
1148
+ ### 2. Test Incrementally
1149
+
1150
+ Add rules one at a time and verify output:
1151
+ - Start with metadata extraction
1152
+ - Add one transformation
1153
+ - Check result
1154
+ - Continue
1155
+
1156
+ ### 3. Use allow_unmatched Carefully
1157
+
1158
+ Only use when genuinely optional:
1159
+ ```yaml
1160
+ # BAD - silently fails to extract
1161
+ - type: add_column_regex
1162
+ expression: 'wrong_pattern'
1163
+ allow_unmatched: true
1164
+
1165
+ # GOOD - errors if pattern doesn't match
1166
+ - type: add_column_regex
1167
+ expression: 'expected_pattern'
1168
+ allow_unmatched: false
1169
+ ```
1170
+
1171
+ ### 4. Remove Intermediate Columns
1172
+
1173
+ Clean up before mapping:
1174
+ ```yaml
1175
+ rules:
1176
+ - type: add_column_metadata
1177
+ value: identifier0
1178
+ # ... many transformations ...
1179
+ - type: remove_columns
1180
+ target_columns: [0, 2, 3] # Remove temp columns
1181
+
1182
+ mapping:
1183
+ - type: list_identifiers
1184
+ columns: [0] # Only final column remains
1185
+ ```
1186
+
1187
+ ### 5. Validate with Filters
1188
+
1189
+ Use filters to ensure data quality:
1190
+ ```yaml
1191
+ rules:
1192
+ - type: add_column_regex
1193
+ expression: 'pattern'
1194
+ allow_unmatched: false # Errors if doesn't match
1195
+ - type: add_filter_empty
1196
+ target_column: 1
1197
+ invert: false # Remove any that became empty
1198
+ ```
1199
+
1200
+ ### 6. Document Complex Rules
1201
+
1202
+ Add comments explaining logic:
1203
+ ```yaml
1204
+ rules:
1205
+ # Extract sample ID from filename "sample_123_R1.fastq"
1206
+ - type: add_column_regex
1207
+ target_column: 0
1208
+ expression: 'sample_(\w+)_R\d'
1209
+
1210
+ # Remove original filename column
1211
+ - type: remove_columns
1212
+ target_columns: [0]
1213
+ ```
1214
+
1215
+ ---
1216
+
1217
+ ## Common Pitfalls
1218
+
1219
+ ### Pitfall 1: Column Indices Shift
1220
+
1221
+ **Problem:** After removing columns, indices change
1222
+
1223
+ ```yaml
1224
+ # WRONG
1225
+ rules:
1226
+ - type: remove_columns
1227
+ target_columns: [0]
1228
+ - type: add_column_regex
1229
+ target_column: 1 # This is now wrong! Column 1 became 0
1230
+ ```
1231
+
1232
+ **Solution:** Remove columns last, or recalculate indices
1233
+
1234
+ ### Pitfall 2: Forgetting Invert Logic
1235
+
1236
+ **Problem:** Confusion about filter invert
1237
+
1238
+ ```yaml
1239
+ # Keep matching rows (default behavior)
1240
+ - type: add_filter_regex
1241
+ expression: 'sample_'
1242
+ invert: false # FALSE means "keep matching"
1243
+
1244
+ # Remove matching rows (keep non-matching)
1245
+ - type: add_filter_regex
1246
+ expression: 'control_'
1247
+ invert: true # TRUE means "remove matching" = keep non-matching
1248
+ ```
1249
+
1250
+ **Clearer thinking:** `invert: false` = "keep matches", `invert: true` = "remove matches" (keep non-matching)
1251
+
1252
+ ### Pitfall 3: Regex Escaping
1253
+
1254
+ **Problem:** Special regex characters not escaped
1255
+
1256
+ ```yaml
1257
+ # WRONG - . matches any character
1258
+ expression: 'file.fastq'
1259
+
1260
+ # RIGHT
1261
+ expression: 'file\.fastq'
1262
+
1263
+ # For literal parentheses
1264
+ expression: '\(sample\)'
1265
+ ```
1266
+
1267
+ ### Pitfall 4: Character Classes vs Alternation for Sequential IDs
1268
+
1269
+ **Problem:** Character classes match single characters, not multi-digit suffixes
1270
+
1271
+ ```yaml
1272
+ # WRONG - [90] matches a single char (9 or 0) at one position
1273
+ # Matches SRR22376029 but NOT SRR22376030 (different digit boundary)
1274
+ expression: 'SRR2237602[90]'
1275
+
1276
+ # RIGHT - alternation matches full strings
1277
+ expression: 'SRR22376029|SRR22376030'
1278
+ ```
1279
+
1280
+ **Why it fails:** `SRR2237602[90]` looks for prefix `SRR2237602` followed by one character that is `9` or `0`. It matches `SRR22376029` (prefix `SRR2237602` + `9`), but `SRR22376030` splits as `SRR2237603` + `0` — the prefix doesn't end at the same boundary. Use explicit alternation for sequential accession IDs.
1281
+
1282
+ ### Pitfall 5: Case Sensitivity
1283
+
1284
+ **Problem:** Filters are case-sensitive
1285
+
1286
+ ```yaml
1287
+ # Doesn't match "Sample1"
1288
+ - type: add_filter_matches
1289
+ value: "sample1"
1290
+ target_column: 0
1291
+ ```
1292
+
1293
+ **Solution:** Use regex with case-insensitive flag or normalize case first
1294
+
1295
+ ### Pitfall 6: Empty Sources After Filtering
1296
+
1297
+ **Problem:** All rows filtered out
1298
+
1299
+ ```yaml
1300
+ rules:
1301
+ - type: add_filter_regex
1302
+ expression: 'nonexistent'
1303
+ invert: false
1304
+ # Result: Empty collection!
1305
+ ```
1306
+
1307
+ **Solution:** Test filters carefully, use `allow_unmatched: true` when appropriate
1308
+
1309
+ ---
1310
+
1311
+ ## Use Case Examples
1312
+
1313
+ ### Use Case 1: Standard Paired-End RNA-seq
1314
+
1315
+ **Files:** `sample1_R1.fastq.gz`, `sample1_R2.fastq.gz`, `sample2_R1.fastq.gz`, `sample2_R2.fastq.gz`
1316
+
1317
+ **Goal:** Create `list:paired` collection
1318
+
1319
+ ```yaml
1320
+ rules:
1321
+ - type: add_column_metadata
1322
+ value: identifier0
1323
+ - type: add_column_regex
1324
+ target_column: 0
1325
+ expression: '(.+)_R([12])\.fastq\.gz'
1326
+ group_count: 2
1327
+ - type: add_column_regex
1328
+ target_column: 2
1329
+ expression: '1'
1330
+ replacement: 'forward'
1331
+ allow_unmatched: true
1332
+ - type: add_column_regex
1333
+ target_column: 2
1334
+ expression: '2'
1335
+ replacement: 'reverse'
1336
+ allow_unmatched: true
1337
+ - type: add_column_concatenate
1338
+ target_column_0: 3
1339
+ target_column_1: 4
1340
+ - type: sort
1341
+ target_column: 1
1342
+ numeric: false
1343
+ - type: remove_columns
1344
+ target_columns: [0, 2, 3, 4]
1345
+
1346
+ mapping:
1347
+ - type: list_identifiers
1348
+ columns: [0]
1349
+ - type: paired_identifier
1350
+ columns: [1]
1351
+ ```
1352
+
1353
+ ---
1354
+
1355
+ ### Use Case 2: Remove Control Samples
1356
+
1357
+ **Goal:** Filter out samples starting with "control_"
1358
+
1359
+ ```yaml
1360
+ rules:
1361
+ - type: add_column_metadata
1362
+ value: identifier0
1363
+ - type: add_filter_regex
1364
+ target_column: 0
1365
+ expression: '^control_'
1366
+ invert: true # Remove matches = keep non-controls
1367
+
1368
+ mapping:
1369
+ - type: list_identifiers
1370
+ columns: [0]
1371
+ ```
1372
+
1373
+ ---
1374
+
1375
+ ### Use Case 3: Group by Treatment Condition
1376
+
1377
+ **Goal:** Reorganize by "group:condition:*" tag into nested list
1378
+
1379
+ ```yaml
1380
+ rules:
1381
+ - type: add_column_metadata
1382
+ value: identifier0
1383
+ - type: add_column_group_tag_value
1384
+ value: condition
1385
+ default_value: 'unassigned'
1386
+
1387
+ mapping:
1388
+ - type: list_identifiers
1389
+ columns: [1, 0] # Group by condition, then sample
1390
+ - type: group_tags
1391
+ columns: [1]
1392
+ ```
1393
+
1394
+ ---
1395
+
1396
+ ### Use Case 4: Select Top N by Quality Score
1397
+
1398
+ **Assumption:** Quality score in sample name like "sample_123_q95"
1399
+
1400
+ **Goal:** Keep only samples with quality >= 90
1401
+
1402
+ ```yaml
1403
+ rules:
1404
+ - type: add_column_metadata
1405
+ value: identifier0
1406
+ - type: add_column_regex
1407
+ target_column: 0
1408
+ expression: 'sample_\w+_q(\d+)'
1409
+ - type: add_filter_compare
1410
+ target_column: 1
1411
+ value: 90
1412
+ compare_type: greater_than_equal
1413
+ - type: remove_columns
1414
+ target_columns: [1]
1415
+
1416
+ mapping:
1417
+ - type: list_identifiers
1418
+ columns: [0]
1419
+ ```
1420
+
1421
+ ---
1422
+
1423
+ ### Use Case 5: Replicate Structure
1424
+
1425
+ **Files:** `treatment_rep1`, `treatment_rep2`, `control_rep1`, `control_rep2`
1426
+
1427
+ **Goal:** Create `list:list` [treatment → [rep1, rep2], control → [rep1, rep2]]
1428
+
1429
+ ```yaml
1430
+ rules:
1431
+ - type: add_column_metadata
1432
+ value: identifier0
1433
+ - type: add_column_regex
1434
+ target_column: 0
1435
+ expression: '(.+)_rep(\d+)'
1436
+ group_count: 2
1437
+ - type: sort
1438
+ target_column: 1
1439
+ numeric: false
1440
+ - type: remove_columns
1441
+ target_columns: [0]
1442
+
1443
+ mapping:
1444
+ - type: list_identifiers
1445
+ columns: [0, 1] # Condition, then replicate
1446
+ ```
1447
+
1448
+ ---
1449
+
1450
+ ## Summary
1451
+
1452
+ The Apply Rules DSL is a powerful, composable system for collection transformation:
1453
+
1454
+ **Key Principles:**
1455
+ 1. **Tabular transformation** - Collections → table → transform → collection
1456
+ 2. **Sequential rules** - Applied in order, each builds on previous
1457
+ 3. **Column-based operations** - All transformations work on columns
1458
+ 4. **Flexible mapping** - Final step determines output structure
1459
+
1460
+ **When to Use:**
1461
+ - Complex identifier parsing
1462
+ - Conditional filtering
1463
+ - Structure reorganization
1464
+ - Tag-based grouping
1465
+ - Operations beyond simple collection tools
1466
+
1467
+ **When Not to Use:**
1468
+ - Simple operations (use dedicated tools instead)
1469
+ - If pattern unclear (prototype with simpler tools first)
1470
+ - One-off transformations (no reusability needed)
1471
+
1472
+ **Power:** Apply Rules can perform ANY collection transformation expressible as tabular operations, making it the most flexible tool in Galaxy's collection toolkit.
1473
+
1474
+ ---
1475
+
1476
+ ## Additional Resources
1477
+
1478
+ - **Tool Catalog:** `references/tools.md` for all collection tools
1479
+ - **API Guide:** `references/api-patterns.md` for programmatic usage
1480
+ - **Test Examples:** `references/test-patterns.md` for real test patterns
1481
+ - **PR #5819:** https://github.com/galaxyproject/galaxy/pull/5819
1482
+ - **DSL Spec:** `lib/galaxy/util/rules_dsl_spec.yml` in Galaxy source