@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.
- package/CHANGELOG.md +123 -0
- package/LICENSE +21 -0
- package/README.md +760 -5
- package/bin/legacy-mcp-config.js +363 -0
- package/bin/orbit.js +810 -0
- package/bin/pi-extension-path.d.ts +4 -0
- package/bin/pi-extension-path.js +44 -0
- package/bin/provider-auth.d.ts +22 -0
- package/bin/provider-auth.js +77 -0
- package/bin/thinking-pref.js +38 -0
- package/bin/update-check.d.ts +15 -0
- package/bin/update-check.js +137 -0
- package/extensions/cli-update/index.ts +32 -0
- package/extensions/orbit/activity-hooks.ts +141 -0
- package/extensions/orbit/activity.ts +116 -0
- package/extensions/orbit/agent-dir.ts +11 -0
- package/extensions/orbit/auto-resume.ts +352 -0
- package/extensions/orbit/config.ts +3 -0
- package/extensions/orbit/confusables.ts +1 -0
- package/extensions/orbit/context.ts +957 -0
- package/extensions/orbit/dashboard-commands.ts +191 -0
- package/extensions/orbit/dashboard-store.ts +473 -0
- package/extensions/orbit/dashboard-tools.ts +1185 -0
- package/extensions/orbit/empty-completion.ts +99 -0
- package/extensions/orbit/evidence-gate.ts +1276 -0
- package/extensions/orbit/evidence-override-command.ts +294 -0
- package/extensions/orbit/exec-guard/bash-risk.ts +1408 -0
- package/extensions/orbit/exec-guard/gate.ts +181 -0
- package/extensions/orbit/exec-guard/guardian-config.ts +54 -0
- package/extensions/orbit/exec-guard/index.ts +1 -0
- package/extensions/orbit/exec-guard/model-tier.ts +36 -0
- package/extensions/orbit/exec-guard/path-jail.ts +54 -0
- package/extensions/orbit/exec-guard/policy.ts +342 -0
- package/extensions/orbit/exec-guard/runtime-state.ts +15 -0
- package/extensions/orbit/exec-guard/sensitive-read.ts +525 -0
- package/extensions/orbit/exec-guard/types.ts +42 -0
- package/extensions/orbit/execution-commands.ts +134 -0
- package/extensions/orbit/feedback-command.ts +81 -0
- package/extensions/orbit/feedback.ts +96 -0
- package/extensions/orbit/galaxy-api.test.ts +122 -0
- package/extensions/orbit/galaxy-api.ts +606 -0
- package/extensions/orbit/galaxy-artifact-link-guidance.ts +5 -0
- package/extensions/orbit/galaxy-destructive-gate.ts +113 -0
- package/extensions/orbit/galaxy-enrich.ts +1108 -0
- package/extensions/orbit/galaxy-failure.ts +101 -0
- package/extensions/orbit/galaxy-fixture.ts +126 -0
- package/extensions/orbit/galaxy-history-guard.ts +233 -0
- package/extensions/orbit/galaxy-job-block.ts +347 -0
- package/extensions/orbit/galaxy-job-ops.ts +288 -0
- package/extensions/orbit/galaxy-live-source.ts +929 -0
- package/extensions/orbit/galaxy-markdown-adapter.ts +248 -0
- package/extensions/orbit/galaxy-op-policy.ts +332 -0
- package/extensions/orbit/galaxy-ops-tools.ts +326 -0
- package/extensions/orbit/galaxy-output-store.ts +80 -0
- package/extensions/orbit/galaxy-output.ts +346 -0
- package/extensions/orbit/galaxy-page-binding.ts +222 -0
- package/extensions/orbit/galaxy-page-markdown-guidance.ts +15 -0
- package/extensions/orbit/galaxy-page-ops.ts +159 -0
- package/extensions/orbit/galaxy-page-sync.test.ts +417 -0
- package/extensions/orbit/galaxy-page-sync.ts +318 -0
- package/extensions/orbit/galaxy-pages-api.ts +203 -0
- package/extensions/orbit/galaxy-pages-sync.ts +409 -0
- package/extensions/orbit/galaxy-poll-guard.ts +189 -0
- package/extensions/orbit/galaxy-poller.ts +706 -0
- package/extensions/orbit/galaxy-provenance.ts +623 -0
- package/extensions/orbit/galaxy-reconcile.ts +956 -0
- package/extensions/orbit/galaxy-recovery.ts +176 -0
- package/extensions/orbit/galaxy-repeat-guard.ts +55 -0
- package/extensions/orbit/galaxy-submission-capture.ts +707 -0
- package/extensions/orbit/galaxy-submission.ts +502 -0
- package/extensions/orbit/galaxy-tool-source.ts +78 -0
- package/extensions/orbit/galaxy-tool-wrap.ts +234 -0
- package/extensions/orbit/galaxy-udt-block.ts +127 -0
- package/extensions/orbit/galaxy-upload-tus.ts +334 -0
- package/extensions/orbit/galaxy-upload.ts +300 -0
- package/extensions/orbit/galaxy-version-capture.ts +65 -0
- package/extensions/orbit/git.ts +173 -0
- package/extensions/orbit/harness-block-fields.ts +597 -0
- package/extensions/orbit/index.ts +593 -0
- package/extensions/orbit/init-gate.ts +284 -0
- package/extensions/orbit/instructions-command.ts +136 -0
- package/extensions/orbit/invocation-failure-hint.ts +57 -0
- package/extensions/orbit/iwc-plan-check.ts +94 -0
- package/extensions/orbit/lesson-command.ts +303 -0
- package/extensions/orbit/lesson-hint.ts +245 -0
- package/extensions/orbit/lesson-nudge.ts +106 -0
- package/extensions/orbit/lessons/compose.ts +177 -0
- package/extensions/orbit/lessons/counters.ts +120 -0
- package/extensions/orbit/lessons/enabled.ts +116 -0
- package/extensions/orbit/lessons/matcher.ts +346 -0
- package/extensions/orbit/lessons/paths.ts +286 -0
- package/extensions/orbit/lessons/pi-event-contract.ts +105 -0
- package/extensions/orbit/lessons/propose-replay.ts +103 -0
- package/extensions/orbit/lessons/propose-tool.ts +222 -0
- package/extensions/orbit/lessons/propose.ts +502 -0
- package/extensions/orbit/lessons/replay.ts +89 -0
- package/extensions/orbit/lessons/reproduction-index.ts +83 -0
- package/extensions/orbit/lessons/search-tool.ts +99 -0
- package/extensions/orbit/lessons/search.ts +136 -0
- package/extensions/orbit/lessons/store.ts +415 -0
- package/extensions/orbit/lessons/text.ts +36 -0
- package/extensions/orbit/lessons/types.ts +69 -0
- package/extensions/orbit/lessons/user-dir.ts +24 -0
- package/extensions/orbit/lessons/user-lesson.ts +88 -0
- package/extensions/orbit/lessons/wrapper.ts +61 -0
- package/extensions/orbit/lessons-command.ts +147 -0
- package/extensions/orbit/local-exec.ts +39 -0
- package/extensions/orbit/mcp-output.ts +179 -0
- package/extensions/orbit/mcp-servers.test.ts +24 -0
- package/extensions/orbit/mcp-servers.ts +25 -0
- package/extensions/orbit/model-script.ts +351 -0
- package/extensions/orbit/notebook-anchors.ts +342 -0
- package/extensions/orbit/notebook-writer.ts +863 -0
- package/extensions/orbit/observation-allowlists.ts +1109 -0
- package/extensions/orbit/observation-replay.ts +148 -0
- package/extensions/orbit/observation-triggers.ts +563 -0
- package/extensions/orbit/observation-ui.ts +175 -0
- package/extensions/orbit/observations-command.ts +421 -0
- package/extensions/orbit/observations-config.ts +200 -0
- package/extensions/orbit/observations.ts +1381 -0
- package/extensions/orbit/profiles.ts +270 -0
- package/extensions/orbit/progress-updates.ts +95 -0
- package/extensions/orbit/proposal-commands.ts +882 -0
- package/extensions/orbit/provenance-fs-file.ts +59 -0
- package/extensions/orbit/provenance-fs.ts +32 -0
- package/extensions/orbit/provenance-memory-fs.ts +59 -0
- package/extensions/orbit/record-store-file.ts +177 -0
- package/extensions/orbit/record-store-page.ts +77 -0
- package/extensions/orbit/record-store-seam.ts +47 -0
- package/extensions/orbit/record-store.ts +149 -0
- package/extensions/orbit/registry-carrier.ts +107 -0
- package/extensions/orbit/registry-eligibility.ts +95 -0
- package/extensions/orbit/registry-evaluation.ts +403 -0
- package/extensions/orbit/registry-evaluator.ts +519 -0
- package/extensions/orbit/registry-import.ts +91 -0
- package/extensions/orbit/registry-lock.ts +221 -0
- package/extensions/orbit/registry-memory-fs.ts +42 -0
- package/extensions/orbit/registry-page-carrier.ts +103 -0
- package/extensions/orbit/registry-proposal.ts +1348 -0
- package/extensions/orbit/registry-runtime.ts +234 -0
- package/extensions/orbit/registry-schema.ts +735 -0
- package/extensions/orbit/registry-submitter.ts +59 -0
- package/extensions/orbit/registry-templates.ts +346 -0
- package/extensions/orbit/registry.ts +476 -0
- package/extensions/orbit/sandbox/index.ts +120 -0
- package/extensions/orbit/sandbox/sandbox-bash.ts +93 -0
- package/extensions/orbit/sandbox/sandbox-config.ts +87 -0
- package/extensions/orbit/sandbox/sandbox-init-message.ts +28 -0
- package/extensions/orbit/secret-redaction.ts +247 -0
- package/extensions/orbit/session-index/cwd.ts +18 -0
- package/extensions/orbit/session-index/db.ts +56 -0
- package/extensions/orbit/session-index/indexer.ts +154 -0
- package/extensions/orbit/session-index/is-enabled.ts +17 -0
- package/extensions/orbit/session-index/parse.ts +254 -0
- package/extensions/orbit/session-index/query.ts +209 -0
- package/extensions/orbit/session-index/schema.ts +72 -0
- package/extensions/orbit/session-index/tools.ts +152 -0
- package/extensions/orbit/session-lifecycle.ts +321 -0
- package/extensions/orbit/skill-triggers.ts +159 -0
- package/extensions/orbit/skills-command.ts +48 -0
- package/extensions/orbit/skills-discovery.ts +435 -0
- package/extensions/orbit/skills.ts +84 -0
- package/extensions/orbit/sra-import-gate.ts +77 -0
- package/extensions/orbit/state.ts +265 -0
- package/extensions/orbit/submission-replay.ts +147 -0
- package/extensions/orbit/sync-command.ts +157 -0
- package/extensions/orbit/teams/critic-parser.ts +93 -0
- package/extensions/orbit/teams/dispatcher.ts +210 -0
- package/extensions/orbit/teams/is-enabled.ts +22 -0
- package/extensions/orbit/teams/tool.ts +187 -0
- package/extensions/orbit/teams/types.ts +57 -0
- package/extensions/orbit/teams/validate.ts +42 -0
- package/extensions/orbit/tester-id-command.ts +133 -0
- package/extensions/orbit/tools-sync.ts +279 -0
- package/extensions/orbit/tools.ts +1300 -0
- package/extensions/orbit/types.ts +41 -0
- package/extensions/orbit/ui-bridge.ts +55 -0
- package/extensions/orbit/ulid.ts +60 -0
- package/extensions/orbit/user-instructions.ts +388 -0
- package/extensions/orbit/vendor/skills/_catalog.json +68 -0
- package/extensions/orbit/vendor/skills/_manifest.json +1106 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/SKILL.md +112 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_provenance.json +218 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_required_tools.json +33 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/add.json +50 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-extract.json +51 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-next-step.json +42 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/list.json +32 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-tool-summary.schema.json +175 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/SKILL.md +82 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_provenance.json +133 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/galaxy-workflow-draft-format.md +135 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/SKILL.md +84 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_provenance.json +166 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_verify.json +29 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/SKILL.md +127 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_provenance.json +198 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/galaxy-data-flow-draft-contract.md +129 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/SKILL.md +73 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_provenance.json +160 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.md +43 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.yml +1250 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/nextflow-operators-to-galaxy-collection-recipes.md +98 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/SKILL.md +174 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_provenance.json +130 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_required_tools.json +18 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-revisions.json +48 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-search.json +95 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-versions.json +39 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/notes/component-tool-shed-search.md +230 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/schemas/galaxy-tool-discovery.schema.json +231 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/SKILL.md +93 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_provenance.json +201 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/_assembly.json +23 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/SKILL.md +79 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_provenance.json +125 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/skills/LICENSE +21 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/README.md +39 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/SKILL.md +892 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/api-patterns.md +927 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/apply-rules.md +1482 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/test-patterns.md +996 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/tools.md +609 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-data-libraries/SKILL.md +170 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/README.md +162 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/SKILL.md +99 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/README.md +119 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/tool-checking.md +419 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/workflow-testing.md +617 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/galaxy-integration.md +614 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/SKILL.md +144 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/average_col3.ipynb +68 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/extract_sample_metadata.ipynb +190 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/variant_annotation.ipynb +816 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/vcp_variant_map.ipynb +443 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/README.md +165 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/galaxy_tool_checker.py +521 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/SKILL.md +128 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/gotchas.md +135 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/history-access.md +132 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/SKILL.md +146 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/references/directives.yml +496 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/SKILL.md +245 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/01-minimal-echo.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/02-single-data-in-out.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/03-multiple-data-js.yml +28 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/04-select-integer-boolean.yml +41 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/05-resource-requirements.yml +25 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/06-biocontainer-tool.yml +38 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/07-inline-python-script.yml +56 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/08-configfile-script.yml +74 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/common-mistakes.md +76 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/schema-reference.md +155 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/templating.md +196 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/scripts/validate.py +109 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/README.md +71 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/SKILL.md +190 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/histology-staining.md +145 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/tissue-microarray-analysis.md +176 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/references/directives.md +415 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/SKILL.md +98 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/foundry.md +25 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/SKILL.md +74 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_provenance.json +71 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor-skills.ts +283 -0
- package/extensions/orbit/workspace-state-dir.ts +46 -0
- package/extensions/orbit-handoff/index.ts +73 -0
- package/extensions/orbit-handoff/orbit-launcher.ts +142 -0
- package/extensions/whats-new/index.ts +98 -0
- package/lessons/LICENSE +17 -0
- package/lessons/README.md +117 -0
- package/lessons/SCHEMA.md +187 -0
- package/lessons/build-snapshot.mjs +311 -0
- package/lessons/data/downloaded-file-is-not-what-its-extension-says.md +61 -0
- package/lessons/galaxy-api/403-history-is-a-hard-stop.md +57 -0
- package/lessons/galaxy-api/collection-into-single-dataset-input.md +61 -0
- package/lessons/galaxy-api/connectedvalue-in-command-line.md +62 -0
- package/lessons/galaxy-api/hid-is-not-an-id.md +59 -0
- package/lessons/galaxy-api/invoke-workflow-inputs-not-params.md +60 -0
- package/lessons/galaxy-api/repeat-param-pipe-keys.md +63 -0
- package/lessons/galaxy-api/run-tool-returns-on-submit.md +61 -0
- package/lessons/galaxy-tools/reference-index-not-on-server.md +62 -0
- package/lessons/log.md +42 -0
- package/lessons/reproduction/input-population-mismatch.md +59 -0
- package/lessons/reproduction/methods-text-vs-executed-parameters.md +62 -0
- package/lessons/snapshot.json +1004 -0
- package/lessons/stats/de-contrast-direction-and-sample-labels.md +63 -0
- package/lessons/stats/na-coerced-to-zero-in-filters.md +59 -0
- package/lessons/validate.mjs +1219 -0
- package/package.json +103 -5
- package/shared/agent-prompt.d.ts +8 -0
- package/shared/agent-prompt.js +15 -0
- package/shared/approval-prompt.d.ts +4 -0
- package/shared/approval-prompt.js +61 -0
- package/shared/brain-env.d.ts +14 -0
- package/shared/brain-env.js +108 -0
- package/shared/brain-exit.d.ts +20 -0
- package/shared/brain-exit.js +149 -0
- package/shared/capability-profile.d.ts +16 -0
- package/shared/capability-profile.js +75 -0
- package/shared/config-source.d.ts +13 -0
- package/shared/config-source.js +17 -0
- package/shared/confusables.d.ts +3 -0
- package/shared/confusables.js +93 -0
- package/shared/custom-provider.d.ts +45 -0
- package/shared/custom-provider.js +169 -0
- package/shared/dashboard-contract.d.ts +123 -0
- package/shared/dashboard-contract.js +560 -0
- package/shared/dashboard-layout-store.d.ts +44 -0
- package/shared/dashboard-layout-store.js +281 -0
- package/shared/feedback-contract.d.ts +61 -0
- package/shared/feedback-contract.js +146 -0
- package/shared/galaxy-artifact-links.d.ts +30 -0
- package/shared/galaxy-artifact-links.js +166 -0
- package/shared/galaxy-credentials.d.ts +26 -0
- package/shared/galaxy-credentials.js +71 -0
- package/shared/galaxy-destructive.d.ts +21 -0
- package/shared/galaxy-destructive.js +269 -0
- package/shared/galaxy-guidance.d.ts +2 -0
- package/shared/galaxy-guidance.js +53 -0
- package/shared/galaxy-live-contract.d.ts +92 -0
- package/shared/galaxy-live-contract.js +180 -0
- package/shared/galaxy-page-cells.d.ts +2 -0
- package/shared/galaxy-page-cells.js +22 -0
- package/shared/galaxy-tool-family.d.ts +5 -0
- package/shared/galaxy-tool-family.js +27 -0
- package/shared/galaxy-url.d.ts +1 -0
- package/shared/galaxy-url.js +48 -0
- package/shared/gtn.d.ts +31 -0
- package/shared/gtn.js +253 -0
- package/shared/handled-prompt.d.ts +3 -0
- package/shared/handled-prompt.js +26 -0
- package/shared/known-provider.d.ts +11 -0
- package/shared/known-provider.js +89 -0
- package/shared/lesson-hint-marker.d.ts +7 -0
- package/shared/lesson-hint-marker.js +32 -0
- package/shared/lesson-rules.d.ts +150 -0
- package/shared/lesson-rules.js +203 -0
- package/shared/malformed-object-ids.d.ts +1 -0
- package/shared/malformed-object-ids.js +37 -0
- package/shared/markdown-sections.d.ts +10 -0
- package/shared/markdown-sections.js +118 -0
- package/shared/notebook-fences.d.ts +12 -0
- package/shared/notebook-fences.js +53 -0
- package/shared/observation-contract.d.ts +91 -0
- package/shared/observation-contract.js +544 -0
- package/shared/orbit-config.d.ts +226 -0
- package/shared/orbit-config.js +189 -0
- package/shared/orbit-env.d.ts +13 -0
- package/shared/orbit-env.js +124 -0
- package/shared/orbit-shell-contract.d.ts +74 -0
- package/shared/orbit-shell-contract.js +30 -0
- package/shared/page-content-hash.d.ts +1 -0
- package/shared/page-content-hash.js +13 -0
- package/shared/pi-default-model.d.ts +7 -0
- package/shared/pi-default-model.js +41 -0
- package/shared/prompt-blocks.d.ts +87 -0
- package/shared/prompt-blocks.js +898 -0
- package/shared/provider-auth-caps.d.ts +22 -0
- package/shared/provider-auth-caps.js +57 -0
- package/shared/random.d.ts +2 -0
- package/shared/random.js +15 -0
- package/shared/record-excerpt.d.ts +4 -0
- package/shared/record-excerpt.js +16 -0
- package/shared/redirect-guard.d.ts +36 -0
- package/shared/redirect-guard.js +235 -0
- package/shared/skills-pin.d.ts +8 -0
- package/shared/skills-pin.js +9 -0
- package/shared/skills-router.d.ts +17 -0
- package/shared/skills-router.js +63 -0
- package/shared/sra-import.d.ts +34 -0
- package/shared/sra-import.js +206 -0
- package/shared/state-dir.d.ts +21 -0
- package/shared/state-dir.js +240 -0
- package/shared/team-dispatch-contract.d.ts +28 -0
- package/shared/team-dispatch-contract.js +1 -0
- package/shared/truncate-middle.d.ts +11 -0
- package/shared/truncate-middle.js +68 -0
- package/shared/version-compare.d.ts +10 -0
- package/shared/version-compare.js +74 -0
- package/shared/whats-new.d.ts +31 -0
- package/shared/whats-new.js +83 -0
- package/shared/wsl.d.ts +10 -0
- package/shared/wsl.js +24 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The registry's Page carrier (registry design v3 §9): the signed registry
|
|
3
|
+
* document, gzipped and base64'd into one CommonMark link-reference
|
|
4
|
+
* definition, `[loom-registry:v3]: #loom "<base64 gzip>"`. Same trick the
|
|
5
|
+
* typed-block carriers use (`galaxy-markdown-adapter.ts`): it renders to
|
|
6
|
+
* nothing on the Page and survives storage byte for byte.
|
|
7
|
+
*
|
|
8
|
+
* The carrier is unauthenticated on the wire. What it decodes to goes through
|
|
9
|
+
* `RegistryStore.ingestText`, where the session signature decides whether it
|
|
10
|
+
* is this session's own state (a continuation) or an import. Nothing here
|
|
11
|
+
* trusts it.
|
|
12
|
+
*
|
|
13
|
+
* Pi-free, like the rest of the trusted core.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { gunzipSync, gzipSync } from "zlib";
|
|
17
|
+
import {
|
|
18
|
+
NOTEBOOK_FENCE_READ_PREFIXES,
|
|
19
|
+
NOTEBOOK_FENCE_WRITE_PREFIX,
|
|
20
|
+
} from "../../shared/notebook-fences.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Past this many characters an encoded carrier is neither emitted nor read.
|
|
24
|
+
* Galaxy puts no length limit on page content (`TEXT` column, no
|
|
25
|
+
* `max_length` on the payload), and the proxy in front of a public server
|
|
26
|
+
* allows request bodies far larger, so the bound is ours: every push stores a
|
|
27
|
+
* full page revision, and a registry that big belongs in a history dataset,
|
|
28
|
+
* not in every revision of a Page. Measured on synthetic registries (one full
|
|
29
|
+
* tool approval with submission and evaluation per attempt, about 2 KB of JSON
|
|
30
|
+
* each; the facts themselves stay in `templates/`): 200 attempts encode to
|
|
31
|
+
* 13 KB and 1,000 to 56 KB. Real attempts vary more and compress less, but
|
|
32
|
+
* typical JSON still gzips several-fold, so a few hundred attempts sit well
|
|
33
|
+
* under the cap. Not measured against usegalaxy.eu itself; the round trip at
|
|
34
|
+
* the cap is a unit test.
|
|
35
|
+
*/
|
|
36
|
+
export const MAX_CARRIER_CHARS = 512 * 1024;
|
|
37
|
+
|
|
38
|
+
/** The decoded registry may not be larger than the store accepts anyway. */
|
|
39
|
+
export const MAX_CARRIER_DECODED_BYTES = 4 * 1024 * 1024;
|
|
40
|
+
|
|
41
|
+
const WRITE_PREFIX = NOTEBOOK_FENCE_WRITE_PREFIX;
|
|
42
|
+
const ALT = NOTEBOOK_FENCE_READ_PREFIXES.join("|");
|
|
43
|
+
// Whole line, so carrier-shaped text inside prose is never read as one.
|
|
44
|
+
const LINE = new RegExp(`^\\[(?:${ALT})-registry:v3\\]: #(?:${ALT}) "([A-Za-z0-9+/=]*)"[ \\t]*$`);
|
|
45
|
+
// Anything that looks like it means to be a registry carrier, valid or not.
|
|
46
|
+
const LOOKS_LIKE = new RegExp(`^\\s*\\[(?:${ALT})-registry:v\\d+\\]:`, "i");
|
|
47
|
+
|
|
48
|
+
export class CarrierTooLargeError extends Error {
|
|
49
|
+
constructor(chars: number) {
|
|
50
|
+
super(`the registry carrier would be ${chars} characters, over the ${MAX_CARRIER_CHARS} cap`);
|
|
51
|
+
this.name = "CarrierTooLargeError";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Encode a serialised registry as a carrier line. Throws past the cap. */
|
|
56
|
+
export function encodeRegistryCarrier(registryText: string): string {
|
|
57
|
+
const b64 = gzipSync(Buffer.from(registryText, "utf-8")).toString("base64");
|
|
58
|
+
const line = `[${WRITE_PREFIX}-registry:v3]: #${WRITE_PREFIX} "${b64}"`;
|
|
59
|
+
if (line.length > MAX_CARRIER_CHARS) throw new CarrierTooLargeError(line.length);
|
|
60
|
+
return line;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type CarrierExtraction =
|
|
64
|
+
| { kind: "none"; body: string }
|
|
65
|
+
| { kind: "found"; body: string; registryText: string }
|
|
66
|
+
| { kind: "rejected"; body: string; reason: string };
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Take the registry carrier out of pulled Page content. The body always comes
|
|
70
|
+
* back without any carrier-shaped line, so a carrier never lands in the
|
|
71
|
+
* notebook whatever happens to it. More than one carrier, an oversized one, or
|
|
72
|
+
* one that doesn't decode is rejected as a whole.
|
|
73
|
+
*/
|
|
74
|
+
export function extractRegistryCarrier(content: string): CarrierExtraction {
|
|
75
|
+
const kept: string[] = [];
|
|
76
|
+
const found: string[] = [];
|
|
77
|
+
let malformed = false;
|
|
78
|
+
for (const line of content.split("\n")) {
|
|
79
|
+
if (!LOOKS_LIKE.test(line)) {
|
|
80
|
+
kept.push(line);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const m = line.match(LINE);
|
|
84
|
+
if (!m) malformed = true;
|
|
85
|
+
else found.push(m[1]);
|
|
86
|
+
if (line.length > MAX_CARRIER_CHARS) malformed = true;
|
|
87
|
+
}
|
|
88
|
+
// Push puts the carrier after a blank line at the end; take that with it.
|
|
89
|
+
const removed = kept.length !== content.split("\n").length;
|
|
90
|
+
const body = removed ? kept.join("\n").replace(/\s+$/, "") + "\n" : content;
|
|
91
|
+
if (malformed) return { kind: "rejected", body, reason: "malformed or oversized carrier" };
|
|
92
|
+
if (found.length === 0) return { kind: "none", body };
|
|
93
|
+
if (found.length > 1) return { kind: "rejected", body, reason: `${found.length} carriers` };
|
|
94
|
+
if (found[0].length > MAX_CARRIER_CHARS) {
|
|
95
|
+
return { kind: "rejected", body, reason: "oversized carrier" };
|
|
96
|
+
}
|
|
97
|
+
let registryText: string;
|
|
98
|
+
try {
|
|
99
|
+
const raw = gunzipSync(Buffer.from(found[0], "base64"), {
|
|
100
|
+
maxOutputLength: MAX_CARRIER_DECODED_BYTES,
|
|
101
|
+
});
|
|
102
|
+
registryText = raw.toString("utf-8");
|
|
103
|
+
} catch (err) {
|
|
104
|
+
return { kind: "rejected", body, reason: `carrier doesn't decode: ${(err as Error).message}` };
|
|
105
|
+
}
|
|
106
|
+
return { kind: "found", body, registryText };
|
|
107
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `handoff_eligible` (registry design v3 §7) as a pure function of an attempt
|
|
3
|
+
* and the registry's exceptions.
|
|
4
|
+
*
|
|
5
|
+
* The formula is v3's. The checks after it are cross-checks against the facts
|
|
6
|
+
* the evaluation was supposed to be derived from, so an evaluation that claims
|
|
7
|
+
* more than the attempt supports -- a manual predicate "passed" with no user
|
|
8
|
+
* attestation, an `excepted` conformity with no user exception behind it,
|
|
9
|
+
* `integrity: ok` on a run Galaxy never confirmed -- fails closed instead of
|
|
10
|
+
* being believed. None of
|
|
11
|
+
* them can make an attempt eligible that the formula alone would not.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Attempt, Exception } from "./registry-schema";
|
|
15
|
+
|
|
16
|
+
export function computeHandoffEligible(
|
|
17
|
+
attempt: Attempt,
|
|
18
|
+
exceptions: readonly Exception[] = [],
|
|
19
|
+
): boolean {
|
|
20
|
+
const ev = attempt.evaluation;
|
|
21
|
+
const pv = attempt.provenance;
|
|
22
|
+
if (!ev || !pv) return false;
|
|
23
|
+
|
|
24
|
+
const formula =
|
|
25
|
+
ev.execution === "success" &&
|
|
26
|
+
(ev.conformity === "conformant" || ev.conformity === "excepted") &&
|
|
27
|
+
(ev.predicate_result === "pass" || ev.predicate_result === "attested") &&
|
|
28
|
+
ev.integrity === "ok" &&
|
|
29
|
+
ev.authority === "established" &&
|
|
30
|
+
pv.authority === "established";
|
|
31
|
+
if (!formula) return false;
|
|
32
|
+
|
|
33
|
+
// Integrity is `unverified_identity` while Galaxy hasn't confirmed the run.
|
|
34
|
+
if (!attempt.submission?.server_verified) return false;
|
|
35
|
+
|
|
36
|
+
// Every way past a check is a user exception for this attempt and, when there
|
|
37
|
+
// is an approval, its revision -- one scope per check, so attesting a result
|
|
38
|
+
// can't also excuse how it was submitted. An ungated attempt has no approval to
|
|
39
|
+
// match, which is why v3 §6 lets only an exception make it eligible.
|
|
40
|
+
const revision = attempt.approval?.spec_revision;
|
|
41
|
+
const userExcepted = (scope: Exception["scope"], assertionId?: string) =>
|
|
42
|
+
exceptions.some(
|
|
43
|
+
(x) =>
|
|
44
|
+
x.attempt_id === attempt.attempt_id &&
|
|
45
|
+
x.by === "user" &&
|
|
46
|
+
x.scope === scope &&
|
|
47
|
+
x.assertion_id === assertionId &&
|
|
48
|
+
(revision === undefined || x.spec_revision === revision),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (ev.conformity === "conformant") {
|
|
52
|
+
const outcome = attempt.submission.check.outcome;
|
|
53
|
+
if (outcome === "conformant_by_construction") {
|
|
54
|
+
// The harness built the request from a user approval in this session.
|
|
55
|
+
if (attempt.approval?.by !== "user") return false;
|
|
56
|
+
// A revoked approval no longer vouches for the run, even one it already submitted.
|
|
57
|
+
if (attempt.approval.status !== "live") return false;
|
|
58
|
+
} else if (outcome === "conformant_by_reconcile") {
|
|
59
|
+
// Galaxy's account of the run matched the frozen Spec when this session
|
|
60
|
+
// checked. That's an execution fact, not consent, so a restored approval
|
|
61
|
+
// is enough to check against -- but a revoked one still withdraws it.
|
|
62
|
+
if (!attempt.approval || attempt.approval.status === "revoked") return false;
|
|
63
|
+
} else {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
} else if (!userExcepted("submission_check")) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// What a person vouches for counts, but under its own label: a result no code
|
|
71
|
+
// checked is `attested`, never `pass`, and needs the attestation on record.
|
|
72
|
+
const attested = () => ev.predicate_result === "attested" && userExcepted("manual_attestation");
|
|
73
|
+
|
|
74
|
+
const spec = attempt.approval?.spec_snapshot;
|
|
75
|
+
if (!spec) {
|
|
76
|
+
// Ungated: there's no frozen predicate to hold the evaluation to, so the
|
|
77
|
+
// result has to be attested. Excusing how it was submitted doesn't excuse
|
|
78
|
+
// what came out.
|
|
79
|
+
return attested();
|
|
80
|
+
}
|
|
81
|
+
const predicate = spec.predicate;
|
|
82
|
+
if (predicate.kind === "manual") return attested();
|
|
83
|
+
// Only a manual predicate is the user's to vouch for; the rest are checked.
|
|
84
|
+
if (ev.predicate_result !== "pass") return false;
|
|
85
|
+
if (predicate.kind === "assertions_pass") {
|
|
86
|
+
if (predicate.ids.length === 0) return false;
|
|
87
|
+
// An excepted assertion is a failure the user chose to accept; it counts
|
|
88
|
+
// only with their evidence-gate exception naming that assertion.
|
|
89
|
+
const accepted = (id: string) =>
|
|
90
|
+
ev.assertions[id] === "pass" ||
|
|
91
|
+
(ev.assertions[id] === "excepted" && userExcepted("evidence_gate", id));
|
|
92
|
+
if (!predicate.ids.every(accepted)) return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evaluation half of the registry (design v3 §7): given an attempt and
|
|
3
|
+
* what Galaxy said about its run in this session, decide the four facts and
|
|
4
|
+
* what the submission check now says.
|
|
5
|
+
*
|
|
6
|
+
* Pure and pi-free, like the rest of the trusted core. The harness gathers the
|
|
7
|
+
* facts (`registry-evaluator.ts`) and writes the result through the store; this
|
|
8
|
+
* module only reads them. Nothing here takes a fact from the notebook.
|
|
9
|
+
*
|
|
10
|
+
* Fails toward "not shown". A fact that can't be read is `unknown` or
|
|
11
|
+
* `unevaluable`, and a comparison that can't be made exactly is `unverified`,
|
|
12
|
+
* never a match. A mismatch is only claimed when both sides were read and
|
|
13
|
+
* differ.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
canonicalJson,
|
|
18
|
+
sha256Hex,
|
|
19
|
+
type Attempt,
|
|
20
|
+
type Diff,
|
|
21
|
+
type Exception,
|
|
22
|
+
type Predicate,
|
|
23
|
+
type Spec,
|
|
24
|
+
} from "./registry-schema";
|
|
25
|
+
|
|
26
|
+
/** One dataset a job read or wrote, as Galaxy reported it. */
|
|
27
|
+
export interface RunDataset {
|
|
28
|
+
name: string;
|
|
29
|
+
id: string;
|
|
30
|
+
src?: string;
|
|
31
|
+
ext?: string;
|
|
32
|
+
state?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** One job of the run. Absent fields are ones Galaxy didn't give. */
|
|
36
|
+
export interface RunJob {
|
|
37
|
+
job_id: string;
|
|
38
|
+
tool_id?: string;
|
|
39
|
+
tool_version?: string;
|
|
40
|
+
state?: string;
|
|
41
|
+
params?: Record<string, unknown>;
|
|
42
|
+
inputs?: RunDataset[];
|
|
43
|
+
outputs?: RunDataset[];
|
|
44
|
+
/** Set when the job's details couldn't be fetched. */
|
|
45
|
+
unavailable?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* What the harness learned about one attempt's run from Galaxy, this session.
|
|
50
|
+
* Built only from Galaxy's answers; the notebook never contributes.
|
|
51
|
+
*/
|
|
52
|
+
export interface RunFacts {
|
|
53
|
+
kind: "invocation" | "job";
|
|
54
|
+
run_id: string;
|
|
55
|
+
/** Galaxy answered for exactly this id on this session's server. */
|
|
56
|
+
verified: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* `success`: done, and every job ok. `failed`: done, and something errored,
|
|
59
|
+
* was cancelled, or Galaxy failed it. `running`: Galaxy can still move it.
|
|
60
|
+
* `unknown`: couldn't tell, or done with nothing that succeeded.
|
|
61
|
+
*/
|
|
62
|
+
state: "success" | "failed" | "running" | "unknown";
|
|
63
|
+
history_id?: string;
|
|
64
|
+
jobs: RunJob[];
|
|
65
|
+
/** Invocation only: the workflow inputs Galaxy recorded, by step index. */
|
|
66
|
+
workflow_inputs?: Record<string, { id: string; src?: string }>;
|
|
67
|
+
/** `fixture` when the Tier-1 seam answered instead of a server. */
|
|
68
|
+
source: "galaxy" | "fixture";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type ConformityCheck =
|
|
72
|
+
| { outcome: "match" }
|
|
73
|
+
| { outcome: "mismatch"; diff: Diff[] }
|
|
74
|
+
| { outcome: "unverifiable"; reason: string };
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Walk a Galaxy flat parameter path (`queries_0|input2`) into a job's
|
|
78
|
+
* effective params. Galaxy hands top-level values back JSON-encoded as often
|
|
79
|
+
* as not, so a string that parses is read as what it encodes. Undefined when
|
|
80
|
+
* any step doesn't resolve.
|
|
81
|
+
*/
|
|
82
|
+
export function effectiveParam(params: Record<string, unknown>, path: string): unknown {
|
|
83
|
+
const decode = (v: unknown): unknown => {
|
|
84
|
+
if (typeof v !== "string") return v;
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(v);
|
|
87
|
+
} catch {
|
|
88
|
+
return v;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
let node: unknown = params;
|
|
92
|
+
for (const part of path.split("|")) {
|
|
93
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return undefined;
|
|
94
|
+
const rec = node as Record<string, unknown>;
|
|
95
|
+
if (Object.prototype.hasOwnProperty.call(rec, part)) {
|
|
96
|
+
node = decode(rec[part]);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// A repeat element: `queries_0` is `queries[0]`.
|
|
100
|
+
const m = part.match(/^(.+)_(\d+)$/);
|
|
101
|
+
if (!m || !Object.prototype.hasOwnProperty.call(rec, m[1])) return undefined;
|
|
102
|
+
const list = decode(rec[m[1]]);
|
|
103
|
+
if (!Array.isArray(list)) return undefined;
|
|
104
|
+
node = decode(list[Number(m[2])]);
|
|
105
|
+
if (node === undefined) return undefined;
|
|
106
|
+
}
|
|
107
|
+
return node;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether an observed value is the approved one. Galaxy stores scalars as
|
|
112
|
+
* strings and dataset parameters as `{src, id}`, so both of those are read
|
|
113
|
+
* through; anything else has to be canonically equal.
|
|
114
|
+
*/
|
|
115
|
+
export function sameValue(approved: unknown, observed: unknown): boolean | undefined {
|
|
116
|
+
if (observed === undefined) return undefined;
|
|
117
|
+
if (observed && typeof observed === "object" && !Array.isArray(observed)) {
|
|
118
|
+
const o = observed as Record<string, unknown>;
|
|
119
|
+
// `{values: [{src, id}]}` and `{src, id}` are how a data parameter comes back.
|
|
120
|
+
const values = Array.isArray(o.values) ? o.values : [o];
|
|
121
|
+
const ids = values
|
|
122
|
+
.map((v) => (v && typeof v === "object" ? (v as Record<string, unknown>).id : undefined))
|
|
123
|
+
.filter((id): id is string => typeof id === "string");
|
|
124
|
+
if (ids.length > 0 && (typeof approved === "string" || Array.isArray(approved))) {
|
|
125
|
+
const want = Array.isArray(approved) ? approved.map(String) : [approved];
|
|
126
|
+
return canonicalJson([...want].sort()) === canonicalJson([...ids].sort());
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (approved === null || typeof approved !== "object") {
|
|
130
|
+
if (observed === null || typeof observed !== "object") {
|
|
131
|
+
return String(approved) === String(observed);
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
return canonicalJson(approved) === canonicalJson(observed);
|
|
137
|
+
} catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Re-check the run Galaxy reports against the frozen Spec (the
|
|
144
|
+
* `conformant_by_reconcile` route). Tools and user-defined tools are compared
|
|
145
|
+
* job by job: tool id, version, every approved input and every override.
|
|
146
|
+
* Workflows can't be compared yet -- an invocation doesn't report the stored
|
|
147
|
+
* workflow or its version -- so they come back unverifiable.
|
|
148
|
+
*/
|
|
149
|
+
export function checkConformity(spec: Spec, facts: RunFacts): ConformityCheck {
|
|
150
|
+
if (!facts.verified) return { outcome: "unverifiable", reason: "run not verified on Galaxy" };
|
|
151
|
+
if (spec.target.kind === "workflow") {
|
|
152
|
+
return {
|
|
153
|
+
outcome: "unverifiable",
|
|
154
|
+
reason: "an invocation doesn't report which workflow version ran",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (facts.kind !== "job") {
|
|
158
|
+
return { outcome: "unverifiable", reason: "a tool approval recorded against an invocation" };
|
|
159
|
+
}
|
|
160
|
+
// Where it ran is part of what was approved: a matching job in some other
|
|
161
|
+
// history is some other run.
|
|
162
|
+
if (facts.history_id === undefined) {
|
|
163
|
+
return { outcome: "unverifiable", reason: "history not reported" };
|
|
164
|
+
}
|
|
165
|
+
if (facts.history_id !== spec.history_id) {
|
|
166
|
+
return {
|
|
167
|
+
outcome: "mismatch",
|
|
168
|
+
diff: [{ path: "history_id", approved: spec.history_id, observed: facts.history_id }],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// One job for a plain run, many when it mapped over. A job whose details
|
|
172
|
+
// never came could have run anything.
|
|
173
|
+
const jobs = facts.jobs;
|
|
174
|
+
if (jobs.length === 0) return { outcome: "unverifiable", reason: "no job details" };
|
|
175
|
+
if (jobs.some((j) => j.unavailable)) {
|
|
176
|
+
return { outcome: "unverifiable", reason: "some job details unavailable" };
|
|
177
|
+
}
|
|
178
|
+
const diff: Diff[] = [];
|
|
179
|
+
let unknown: string | null = null;
|
|
180
|
+
const wantTool = spec.target.kind === "udt" ? spec.target.tool_uuid : spec.target.tool_id;
|
|
181
|
+
|
|
182
|
+
for (const job of jobs) {
|
|
183
|
+
const at = (p: string) => `jobs.${job.job_id}.${p}`;
|
|
184
|
+
if (job.tool_id === undefined || wantTool === undefined) unknown ??= "tool id not reported";
|
|
185
|
+
else if (spec.target.kind === "tool" && job.tool_id !== wantTool) {
|
|
186
|
+
diff.push({ path: at("tool_id"), approved: wantTool, observed: job.tool_id });
|
|
187
|
+
}
|
|
188
|
+
if (spec.target.kind === "udt") {
|
|
189
|
+
// A user-defined tool's job reports a tool id Galaxy minted, not its
|
|
190
|
+
// uuid, so the target is only checked through the definition digest
|
|
191
|
+
// slice 3 re-checks at dispatch. Say so rather than calling it a match.
|
|
192
|
+
unknown ??= "a user-defined tool's job doesn't name its uuid";
|
|
193
|
+
}
|
|
194
|
+
if (job.tool_version === undefined) unknown ??= "tool version not reported";
|
|
195
|
+
else if (job.tool_version !== spec.target.version) {
|
|
196
|
+
diff.push({
|
|
197
|
+
path: at("tool_version"),
|
|
198
|
+
approved: spec.target.version,
|
|
199
|
+
observed: job.tool_version,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
for (const input of spec.inputs) {
|
|
203
|
+
if (input.src !== "hda") {
|
|
204
|
+
// A collection maps over: each job sees an element, not the collection.
|
|
205
|
+
unknown ??= `input ${input.slot} is a ${input.src}`;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const seen = job.inputs?.find((d) => d.name === input.slot);
|
|
209
|
+
if (!job.inputs) unknown ??= "job inputs not reported";
|
|
210
|
+
else if (!seen) unknown ??= `input ${input.slot} not reported`;
|
|
211
|
+
else if (seen.id !== input.id) {
|
|
212
|
+
diff.push({ path: at(`inputs.${input.slot}`), approved: input.id, observed: seen.id });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
for (const o of spec.overrides) {
|
|
216
|
+
if (!job.params) {
|
|
217
|
+
unknown ??= "job parameters not reported";
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const observed = effectiveParam(job.params, o.param);
|
|
221
|
+
const same = sameValue(o.value, observed);
|
|
222
|
+
if (same === undefined) unknown ??= `parameter ${o.param} not reported`;
|
|
223
|
+
else if (!same) diff.push({ path: at(`params.${o.param}`), approved: o.value, observed });
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (diff.length > 0) return { outcome: "mismatch", diff };
|
|
227
|
+
if (unknown) return { outcome: "unverifiable", reason: unknown };
|
|
228
|
+
return { outcome: "match" };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** This attempt's own outputs: datasets its jobs wrote. Never an older dataset. */
|
|
232
|
+
function outputsOf(facts: RunFacts): RunDataset[] {
|
|
233
|
+
const out = new Map<string, RunDataset>();
|
|
234
|
+
for (const job of facts.jobs) for (const d of job.outputs ?? []) out.set(d.id, d);
|
|
235
|
+
return [...out.values()];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* The predicate over this attempt's outputs. `manual` and `assertions_pass`
|
|
240
|
+
* are never evaluated here: a manual one is the user's call (attested through
|
|
241
|
+
* an exception), and assertions don't exist yet (#477).
|
|
242
|
+
*/
|
|
243
|
+
export function evaluatePredicate(
|
|
244
|
+
predicate: Predicate,
|
|
245
|
+
facts: RunFacts,
|
|
246
|
+
): "pass" | "fail" | "unevaluable" {
|
|
247
|
+
if (facts.state !== "success") return "unevaluable";
|
|
248
|
+
if (predicate.kind === "manual" || predicate.kind === "assertions_pass") return "unevaluable";
|
|
249
|
+
const outputs = outputsOf(facts);
|
|
250
|
+
if (facts.jobs.some((j) => !j.outputs)) return "unevaluable";
|
|
251
|
+
const matching = outputs.filter(
|
|
252
|
+
(d) => (predicate.ext === undefined || d.ext === predicate.ext) && d.state === "ok",
|
|
253
|
+
);
|
|
254
|
+
if (outputs.some((d) => d.ext === undefined && predicate.ext !== undefined)) {
|
|
255
|
+
return "unevaluable";
|
|
256
|
+
}
|
|
257
|
+
if (predicate.kind === "exists_with_ext") {
|
|
258
|
+
return matching.length >= (predicate.min_count ?? 1) ? "pass" : "fail";
|
|
259
|
+
}
|
|
260
|
+
return matching.length === predicate.count ? "pass" : "fail";
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** The `spec_revision` an exception on an attempt with no approval carries. */
|
|
264
|
+
export const NO_APPROVAL_REVISION = "0".repeat(64);
|
|
265
|
+
|
|
266
|
+
function userException(
|
|
267
|
+
attempt: Attempt,
|
|
268
|
+
exceptions: readonly Exception[],
|
|
269
|
+
scope: Exception["scope"],
|
|
270
|
+
): boolean {
|
|
271
|
+
const revision = attempt.approval?.spec_revision ?? NO_APPROVAL_REVISION;
|
|
272
|
+
return exceptions.some(
|
|
273
|
+
(x) =>
|
|
274
|
+
x.attempt_id === attempt.attempt_id &&
|
|
275
|
+
x.by === "user" &&
|
|
276
|
+
x.scope === scope &&
|
|
277
|
+
x.assertion_id === undefined &&
|
|
278
|
+
x.spec_revision === revision,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface EvaluationResult {
|
|
283
|
+
evaluation: NonNullable<Attempt["evaluation"]>;
|
|
284
|
+
provenance: NonNullable<Attempt["provenance"]>;
|
|
285
|
+
/** The submission's check and identity as this evaluation leaves them. */
|
|
286
|
+
check: NonNullable<Attempt["submission"]>["check"];
|
|
287
|
+
server_verified: boolean;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Evaluate one attempt that has a submission against facts gathered this
|
|
292
|
+
* session. The caller writes the result; `computeHandoffEligible` then derives
|
|
293
|
+
* the flag and cross-checks every claim here against the attempt.
|
|
294
|
+
*
|
|
295
|
+
* `factsRef` names where the facts are stored; the provenance digest is theirs.
|
|
296
|
+
*/
|
|
297
|
+
export function evaluateAttempt(
|
|
298
|
+
attempt: Attempt,
|
|
299
|
+
facts: RunFacts,
|
|
300
|
+
exceptions: readonly Exception[],
|
|
301
|
+
opts: {
|
|
302
|
+
now: string;
|
|
303
|
+
factsRef: string;
|
|
304
|
+
/**
|
|
305
|
+
* Whether the template the approval froze is in this registry's store and
|
|
306
|
+
* hashes to its name. A Spec that arrived without one -- in a carrier, say
|
|
307
|
+
* -- was never checked against anything, so a run matching it shows nothing.
|
|
308
|
+
*/
|
|
309
|
+
templateFrozen?: boolean;
|
|
310
|
+
},
|
|
311
|
+
): EvaluationResult {
|
|
312
|
+
const submission = attempt.submission;
|
|
313
|
+
if (!submission) throw new Error(`attempt ${attempt.attempt_id} has no submission`);
|
|
314
|
+
const execution: NonNullable<Attempt["evaluation"]>["execution"] =
|
|
315
|
+
facts.state === "success" ? "success" : facts.state === "failed" ? "failed" : "unknown";
|
|
316
|
+
|
|
317
|
+
// Fixture answers are not a server's word: they exercise the path in Tier-1
|
|
318
|
+
// without ever counting as established.
|
|
319
|
+
const established = facts.source === "galaxy" && facts.verified;
|
|
320
|
+
|
|
321
|
+
let check = { ...submission.check };
|
|
322
|
+
delete check.diff;
|
|
323
|
+
const spec = attempt.approval?.spec_snapshot;
|
|
324
|
+
if (check.outcome !== "conformant_by_construction" && spec && execution !== "unknown") {
|
|
325
|
+
const c = checkConformity(spec, facts);
|
|
326
|
+
const attemptHistory =
|
|
327
|
+
facts.history_id !== undefined && facts.history_id !== attempt.history_id
|
|
328
|
+
? [{ path: "attempt.history_id", approved: attempt.history_id, observed: facts.history_id }]
|
|
329
|
+
: [];
|
|
330
|
+
if (attemptHistory.length > 0) {
|
|
331
|
+
check = {
|
|
332
|
+
outcome: "mismatch",
|
|
333
|
+
mode: check.mode,
|
|
334
|
+
diff: [...attemptHistory, ...(c.outcome === "mismatch" ? c.diff : [])],
|
|
335
|
+
};
|
|
336
|
+
} else if (c.outcome === "match" && !opts.templateFrozen) {
|
|
337
|
+
check = { outcome: "unverified", mode: check.mode };
|
|
338
|
+
} else if (c.outcome === "match")
|
|
339
|
+
check = { outcome: "conformant_by_reconcile", mode: check.mode };
|
|
340
|
+
else if (c.outcome === "mismatch")
|
|
341
|
+
check = { outcome: "mismatch", mode: check.mode, diff: c.diff };
|
|
342
|
+
else check = { outcome: "unverified", mode: check.mode };
|
|
343
|
+
} else if (check.outcome === "conformant_by_construction" && spec && facts.verified) {
|
|
344
|
+
// Built from the Spec, but Galaxy may still have run something else (a
|
|
345
|
+
// version swapped under the request). A definite difference is an
|
|
346
|
+
// effective contradiction; anything less leaves construction standing.
|
|
347
|
+
const c = checkConformity(spec, facts);
|
|
348
|
+
if (c.outcome === "mismatch") {
|
|
349
|
+
check = { outcome: "conformant_by_construction", mode: check.mode, diff: c.diff };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const effectiveContradiction =
|
|
353
|
+
check.outcome === "conformant_by_construction" && (check.diff?.length ?? 0) > 0;
|
|
354
|
+
|
|
355
|
+
const conformity: NonNullable<Attempt["evaluation"]>["conformity"] = userException(
|
|
356
|
+
attempt,
|
|
357
|
+
exceptions,
|
|
358
|
+
"submission_check",
|
|
359
|
+
)
|
|
360
|
+
? "excepted"
|
|
361
|
+
: effectiveContradiction || check.outcome === "mismatch"
|
|
362
|
+
? "nonconformant"
|
|
363
|
+
: check.outcome === "conformant_by_construction" ||
|
|
364
|
+
check.outcome === "conformant_by_reconcile"
|
|
365
|
+
? "conformant"
|
|
366
|
+
: "unverified";
|
|
367
|
+
|
|
368
|
+
let predicate_result: NonNullable<Attempt["evaluation"]>["predicate_result"];
|
|
369
|
+
if (!spec || spec.predicate.kind === "manual") {
|
|
370
|
+
predicate_result =
|
|
371
|
+
execution === "success" && userException(attempt, exceptions, "manual_attestation")
|
|
372
|
+
? "attested"
|
|
373
|
+
: "unevaluable";
|
|
374
|
+
} else {
|
|
375
|
+
predicate_result = evaluatePredicate(spec.predicate, facts);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const integrity: NonNullable<Attempt["evaluation"]>["integrity"] = !facts.verified
|
|
379
|
+
? "unverified_identity"
|
|
380
|
+
: effectiveContradiction
|
|
381
|
+
? "effective_contradiction"
|
|
382
|
+
: "ok";
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
evaluation: {
|
|
386
|
+
execution,
|
|
387
|
+
conformity,
|
|
388
|
+
predicate_result,
|
|
389
|
+
assertions: {},
|
|
390
|
+
integrity,
|
|
391
|
+
authority: established ? "established" : "historical",
|
|
392
|
+
evaluated_at: opts.now,
|
|
393
|
+
},
|
|
394
|
+
provenance: {
|
|
395
|
+
ref: { kind: "file", id: opts.factsRef },
|
|
396
|
+
digest: sha256Hex(canonicalJson(facts)),
|
|
397
|
+
enrichment: facts.jobs.some((j) => j.unavailable) ? "unavailable" : "complete",
|
|
398
|
+
authority: established ? "established" : "historical",
|
|
399
|
+
},
|
|
400
|
+
check,
|
|
401
|
+
server_verified: facts.verified,
|
|
402
|
+
};
|
|
403
|
+
}
|