@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,15 @@
|
|
|
1
|
+
// Set by the bash sandbox layer when the OS sandbox is actually live for bash
|
|
2
|
+
// (false on unsupported platforms or a failed init). Lives in exec-guard, the
|
|
3
|
+
// lower layer, so the gate can query it without importing upward into the sandbox
|
|
4
|
+
// module. Layer 1 (write confinement) does NOT relax anything off this flag; it is
|
|
5
|
+
// kept here as the seam a future sound auto-allow (contained, recoverable
|
|
6
|
+
// unknown-bash) will read.
|
|
7
|
+
let sandboxActive = false;
|
|
8
|
+
|
|
9
|
+
export function setSandboxActive(active: boolean): void {
|
|
10
|
+
sandboxActive = active;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isSandboxActive(): boolean {
|
|
14
|
+
return sandboxActive;
|
|
15
|
+
}
|
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { WORKSPACE_STATE_DIR_NAMES } from "../workspace-state-dir";
|
|
4
|
+
import { piAgentDir } from "../agent-dir";
|
|
5
|
+
|
|
6
|
+
// Directories under $HOME that hold credentials/secrets.
|
|
7
|
+
const SENSITIVE_HOME_DIRS = [
|
|
8
|
+
".ssh",
|
|
9
|
+
".aws",
|
|
10
|
+
".gnupg",
|
|
11
|
+
".config/gcloud",
|
|
12
|
+
".kube",
|
|
13
|
+
".docker",
|
|
14
|
+
"Library/Keychains",
|
|
15
|
+
];
|
|
16
|
+
// Exact files under $HOME.
|
|
17
|
+
// Both brain config locations: a newer release may have copied the config
|
|
18
|
+
// into ~/.orbit, and this one reads it from there when it exists.
|
|
19
|
+
//
|
|
20
|
+
// The observation files are here for the same reason config.json is. The
|
|
21
|
+
// token store holds the retract tokens the intake route accepts as proof of
|
|
22
|
+
// ownership, and the outbox holds the install token that ties rows together --
|
|
23
|
+
// neither belongs in a model request. The sent log carries neither token, but
|
|
24
|
+
// it is the user's record of what they reported and is read through
|
|
25
|
+
// /observations, not by the agent.
|
|
26
|
+
const SENSITIVE_HOME_FILES = [
|
|
27
|
+
".netrc",
|
|
28
|
+
".loom/config.json",
|
|
29
|
+
".orbit/config.json",
|
|
30
|
+
".loom/observations-tokens.json",
|
|
31
|
+
".orbit/observations-tokens.json",
|
|
32
|
+
".loom/observations-outbox.jsonl",
|
|
33
|
+
".orbit/observations-outbox.jsonl",
|
|
34
|
+
".loom/observations-sent.jsonl",
|
|
35
|
+
".orbit/observations-sent.jsonl",
|
|
36
|
+
".pgpass",
|
|
37
|
+
".npmrc",
|
|
38
|
+
];
|
|
39
|
+
// Files inside pi's agent dir that hold live credentials. auth.json is pi's
|
|
40
|
+
// CredentialStore -- an api-key `key`, or an OAuth access+refresh pair; mcp.json
|
|
41
|
+
// and galaxy-profiles.json carry Galaxy keys. These want the floor more than
|
|
42
|
+
// the config.json entries above, not less: those are safeStorage blobs, but pi
|
|
43
|
+
// reads these directly and refreshes auth.json in place (app/src/main/
|
|
44
|
+
// oauth-handler.ts), so Orbit cannot encrypt them and this is the only
|
|
45
|
+
// protection they get. Listed separately from SENSITIVE_HOME_FILES because the
|
|
46
|
+
// whole directory relocates with PI_CODING_AGENT_DIR and is then not under
|
|
47
|
+
// $HOME at all. models.json holds the env var NAME rather than the secret, and
|
|
48
|
+
// models-store.json is a refreshed provider catalog, so both stay readable.
|
|
49
|
+
const AGENT_DIR_CREDENTIAL_FILES = ["auth.json", "mcp.json", "galaxy-profiles.json"];
|
|
50
|
+
// Basename / extension patterns sensitive anywhere.
|
|
51
|
+
const SENSITIVE_BASENAME =
|
|
52
|
+
/^(\.env(\..+)?|id_rsa|id_ed25519|id_ecdsa|.*\.pem|.*\.key|.*\.keychain(-db)?|credentials)$/i;
|
|
53
|
+
|
|
54
|
+
function within(abs: string, dir: string): boolean {
|
|
55
|
+
const rel = path.relative(dir, abs);
|
|
56
|
+
return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `within`, case-folded. Only the credential-store lists use it.
|
|
61
|
+
*
|
|
62
|
+
* macOS is case-insensitive and its realpath does not normalize case, so
|
|
63
|
+
* `Library/Keychains` and `library/keychains` name one directory that an
|
|
64
|
+
* exact-case list only half-covers -- `library/keychains/user.kb` walked
|
|
65
|
+
* straight past this check. Folding can over-match a literally lowercase
|
|
66
|
+
* `library/keychains` on Linux, which errs toward refusing a read, and that is
|
|
67
|
+
* the safe direction for a list whose whole purpose is credential stores.
|
|
68
|
+
*
|
|
69
|
+
* Deliberately NOT used by the write-protection carve-out below: there a match
|
|
70
|
+
* means "this is an analysis workspace, so allow the write", and folding would
|
|
71
|
+
* widen an exemption rather than a refusal.
|
|
72
|
+
*/
|
|
73
|
+
function withinFolded(abs: string, dir: string): boolean {
|
|
74
|
+
return within(abs.toLowerCase(), dir.toLowerCase());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Dedicated credential stores: the home-relative dirs and exact files above
|
|
78
|
+
// that exist solely to hold secrets. The agent has no legitimate reason to read
|
|
79
|
+
// their CONTENTS, so reads are denied for every model tier (not just downgraded
|
|
80
|
+
// to an ask). This is the floor that closes #183 -- ~/.orbit/config.json is a
|
|
81
|
+
// store. The basename patterns (.env, *.pem, *.key, ...) are deliberately NOT
|
|
82
|
+
// stores: those can be project fixtures, so they keep the ask/deny-by-tier path.
|
|
83
|
+
// `agentDir` is injected so tests can relocate the store the same way
|
|
84
|
+
// PI_CODING_AGENT_DIR does in a real run; the default resolves it exactly as
|
|
85
|
+
// the rest of Orbit does.
|
|
86
|
+
export function isCredentialStore(
|
|
87
|
+
absPath: string,
|
|
88
|
+
home: string,
|
|
89
|
+
agentDir: string = piAgentDir(),
|
|
90
|
+
): boolean {
|
|
91
|
+
const norm = path.normalize(absPath);
|
|
92
|
+
for (const d of SENSITIVE_HOME_DIRS) if (withinFolded(norm, path.join(home, d))) return true;
|
|
93
|
+
// Also as realpaths: callers compare resolved targets, so a config.json that
|
|
94
|
+
// is itself a symlink into the workspace would otherwise read as a plain
|
|
95
|
+
// workspace file.
|
|
96
|
+
return credentialFileCandidates(home, agentDir).has(norm.toLowerCase());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface CandidateSnapshot {
|
|
100
|
+
candidates: Set<string>;
|
|
101
|
+
watched: Map<string, DirSignature>;
|
|
102
|
+
// Each symlink the walk followed, signed as the link itself.
|
|
103
|
+
links: Map<string, DirSignature>;
|
|
104
|
+
// False while any watched dir changed too recently to trust; see
|
|
105
|
+
// RACY_WINDOW_MS.
|
|
106
|
+
settled: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface DirSignature {
|
|
110
|
+
key: string;
|
|
111
|
+
changedAt: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const candidateCache = new Map<string, CandidateSnapshot>();
|
|
115
|
+
const CANDIDATE_CACHE_LIMIT = 16;
|
|
116
|
+
|
|
117
|
+
// A change in the same timestamp tick as one a snapshot already saw leaves the
|
|
118
|
+
// stamps unchanged (Linux stamps from a coarse jiffy clock, HFS+ to the
|
|
119
|
+
// second), so a snapshot taken within this long of a watched dir changing is
|
|
120
|
+
// rebuilt on the next call instead of trusted. The same window catches a
|
|
121
|
+
// change that lands in a resolved dir between resolving it and statting it.
|
|
122
|
+
// Same idea as git's racy-index check.
|
|
123
|
+
const RACY_WINDOW_MS = 1000;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Every spelling of every credential file, lexical and resolved, lowercased.
|
|
127
|
+
*
|
|
128
|
+
* Every file read and every directory listing entry on the web surface comes
|
|
129
|
+
* through here, and resolving each file costs one or two realpath walks --
|
|
130
|
+
* slow enough on Windows to matter -- so the set is cached per (home,
|
|
131
|
+
* agentDir). The cache is keyed on an lstat of every directory whose entries
|
|
132
|
+
* the resolution depended on: each one a candidate's parent is walked through
|
|
133
|
+
* component by component, including the dir that holds each symlink along the
|
|
134
|
+
* way and every dir that link's target passes through in turn (see
|
|
135
|
+
* watchResolution). What a candidate resolves to can only change when an
|
|
136
|
+
* entry in one of those dirs is created, removed, renamed or replaced, and
|
|
137
|
+
* each of those rewrites that dir -- so a symlink planted at
|
|
138
|
+
* `~/.orbit/config.json`, a renamed ancestor relinked to its old name, or a
|
|
139
|
+
* link halfway down the chain re-pointed somewhere else all show up on the
|
|
140
|
+
* very next call. ctime is in the signature because mtime alone can be put
|
|
141
|
+
* back with `touch -r`, and no ordinary file call can set ctime.
|
|
142
|
+
*
|
|
143
|
+
* A settled snapshot never re-checks its own age, so a clock set backwards
|
|
144
|
+
* far enough to reproduce an old mtime:ctime:ino tuple would go unnoticed.
|
|
145
|
+
* That's accepted: whoever can roll back the clock is outside what this
|
|
146
|
+
* guards against, and the racy window is only about time moving forward.
|
|
147
|
+
*/
|
|
148
|
+
function credentialFileCandidates(home: string, agentDir: string): Set<string> {
|
|
149
|
+
// No home: the lexical relative paths, exactly as before. They resolve
|
|
150
|
+
// against the cwd, so there's nothing stable to cache them under.
|
|
151
|
+
if (!home) {
|
|
152
|
+
const lexical = SENSITIVE_HOME_FILES.map((f) => path.join(home, f));
|
|
153
|
+
const resolvedParents = new Map<string, ResolvedDir>();
|
|
154
|
+
for (const f of AGENT_DIR_CREDENTIAL_FILES) {
|
|
155
|
+
const p = path.join(agentDir, f);
|
|
156
|
+
lexical.push(...withRealpath(p, resolvedParents, isSymlink(p)));
|
|
157
|
+
}
|
|
158
|
+
return new Set(lexical.map((c) => c.toLowerCase()));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Keyed on the absolute dirs: PI_CODING_AGENT_DIR may be relative, and a
|
|
162
|
+
// snapshot of a relative dir would outlive a chdir. The candidates keep the
|
|
163
|
+
// spellings as given too, since on Windows resolving a drive-less home
|
|
164
|
+
// prepends the cwd's drive and callers may still pass the drive-less form.
|
|
165
|
+
const absHome = path.resolve(home);
|
|
166
|
+
const absAgentDir = path.resolve(agentDir);
|
|
167
|
+
const key = JSON.stringify([absHome, absAgentDir]);
|
|
168
|
+
const cached = candidateCache.get(key);
|
|
169
|
+
if (cached?.settled && signaturesMatch(cached.watched) && signaturesMatch(cached.links)) {
|
|
170
|
+
return cached.candidates;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const builtAt = Date.now();
|
|
174
|
+
const files = [
|
|
175
|
+
...SENSITIVE_HOME_FILES.map((f) => path.join(home, f)),
|
|
176
|
+
...AGENT_DIR_CREDENTIAL_FILES.map((f) => path.join(agentDir, f)),
|
|
177
|
+
];
|
|
178
|
+
const candidates = new Set<string>();
|
|
179
|
+
if (absHome !== home) for (const f of SENSITIVE_HOME_FILES) addFolded(candidates, absHome, f);
|
|
180
|
+
if (absAgentDir !== agentDir) {
|
|
181
|
+
for (const f of AGENT_DIR_CREDENTIAL_FILES) addFolded(candidates, absAgentDir, f);
|
|
182
|
+
}
|
|
183
|
+
// Walk (and so sign) every dir BEFORE realpath resolves it, so a change
|
|
184
|
+
// that lands mid-build leaves a stale signature behind and forces the next
|
|
185
|
+
// call to rebuild.
|
|
186
|
+
const walk: WalkState = { watched: new Map(), links: new Map(), targets: new Map() };
|
|
187
|
+
const parents = new Map<string, Walk>();
|
|
188
|
+
for (const f of files) {
|
|
189
|
+
const dir = path.dirname(f);
|
|
190
|
+
if (!parents.has(dir)) parents.set(dir, watchResolution(dir, walk));
|
|
191
|
+
}
|
|
192
|
+
const { watched, links } = walk;
|
|
193
|
+
const resolvedParents = new Map<string, ResolvedDir>();
|
|
194
|
+
let sawLink = false;
|
|
195
|
+
for (const f of files) {
|
|
196
|
+
const link = isSymlink(f);
|
|
197
|
+
if (link) sawLink = true;
|
|
198
|
+
for (const c of withRealpath(f, resolvedParents, link, parents)) {
|
|
199
|
+
candidates.add(c.toLowerCase());
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// realpath decides the spellings, since that's what callers compare against;
|
|
203
|
+
// the walk only decides what to watch. If it disagrees with fs.realpathSync
|
|
204
|
+
// -- a race, or some platform quirk the walk doesn't model -- the watched
|
|
205
|
+
// set may be the wrong one, so don't trust it.
|
|
206
|
+
//
|
|
207
|
+
//
|
|
208
|
+
// The native one is compared too, except that an 8.3 short name the walk
|
|
209
|
+
// kept (`RUNNER~1`) may come back expanded: which long name it stands for is
|
|
210
|
+
// an entry in a dir the walk already signed, so it can't change unseen, and
|
|
211
|
+
// without this every home under a short-name tmpdir rebuilt on every call.
|
|
212
|
+
// A subst or mapped drive coming back as its target is still a mismatch,
|
|
213
|
+
// since the drive mapping is in no dir the walk can sign.
|
|
214
|
+
let walksAgree = true;
|
|
215
|
+
for (const [dir, w] of parents) {
|
|
216
|
+
const r = resolvedParents.get(dir);
|
|
217
|
+
if (!w.complete || w.real !== (r?.js ?? null)) walksAgree = false;
|
|
218
|
+
else if (!sameButShortNames(w.real, r?.native ?? null)) walksAgree = false;
|
|
219
|
+
}
|
|
220
|
+
// A credential file that is itself a symlink resolves through its target's
|
|
221
|
+
// dirs, and a dangling one starts resolving the moment its target is
|
|
222
|
+
// created, so that snapshot is never trusted: rare enough that paying the
|
|
223
|
+
// full walk on every call is fine.
|
|
224
|
+
const settled =
|
|
225
|
+
walksAgree &&
|
|
226
|
+
!sawLink &&
|
|
227
|
+
[...watched.values()].every((sig) => sig.changedAt < builtAt - RACY_WINDOW_MS);
|
|
228
|
+
|
|
229
|
+
if (candidateCache.size >= CANDIDATE_CACHE_LIMIT && !candidateCache.has(key)) {
|
|
230
|
+
candidateCache.clear();
|
|
231
|
+
}
|
|
232
|
+
candidateCache.set(key, { candidates, watched, links, settled });
|
|
233
|
+
return candidates;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Case-folded equality, letting a component the walk kept as an 8.3 short
|
|
237
|
+
// name (`~` and a digit) stand for whatever long name sits in that position.
|
|
238
|
+
function sameButShortNames(walked: string | null, native: string | null): boolean {
|
|
239
|
+
if (walked === null || native === null) return walked === native;
|
|
240
|
+
const a = walked.toLowerCase();
|
|
241
|
+
const b = native.toLowerCase();
|
|
242
|
+
if (a === b) return true;
|
|
243
|
+
if (process.platform !== "win32") return false;
|
|
244
|
+
const as = a.split(path.sep);
|
|
245
|
+
const bs = b.split(path.sep);
|
|
246
|
+
if (as.length !== bs.length || as[0] !== bs[0]) return false;
|
|
247
|
+
return as.every((c, i) => c === bs[i] || /~\d/.test(c));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function addFolded(set: Set<string>, dir: string, file: string): void {
|
|
251
|
+
set.add(path.join(dir, file).toLowerCase());
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
interface Walk {
|
|
255
|
+
// False when the walk hit something it can't promise to notice changing.
|
|
256
|
+
complete: boolean;
|
|
257
|
+
// Where the dir resolved to, or null when it doesn't exist (yet).
|
|
258
|
+
real: string | null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
interface WalkState {
|
|
262
|
+
// Every dir whose entries a resolution read. Only dirs go in here.
|
|
263
|
+
watched: Map<string, DirSignature>;
|
|
264
|
+
links: Map<string, DirSignature>;
|
|
265
|
+
// readlink results, so links shared by several credential dirs (macOS's
|
|
266
|
+
// /var, say) are read once per build.
|
|
267
|
+
targets: Map<string, string>;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// At least what any of our kernels allows in one lookup (Linux 40, macOS 32).
|
|
271
|
+
// A chain realpath gives up on but the walk finishes just disagrees with it,
|
|
272
|
+
// which leaves the snapshot untrusted.
|
|
273
|
+
const MAX_LINK_HOPS = 40;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Resolve `dir` the way realpath does -- one component at a time with lstat,
|
|
277
|
+
* splicing a symlink's target in ahead of whatever is left -- and sign every
|
|
278
|
+
* directory whose entries that depended on: every dir walked through, which
|
|
279
|
+
* includes the one holding each link and every dir the link's target passes
|
|
280
|
+
* through. Each link is signed as well, since a Windows junction can be
|
|
281
|
+
* re-pointed in place without touching the dir it sits in.
|
|
282
|
+
*
|
|
283
|
+
* A missing component is fine wherever it turns up -- in the path as written
|
|
284
|
+
* or in a dangling link's target: the walk stops in the dir it would appear
|
|
285
|
+
* in, that dir is already signed, and creating the entry rewrites it.
|
|
286
|
+
* Anything else that stops the walk (an unreadable dir or link, a file where
|
|
287
|
+
* a dir should be, too many hops) means the dirs a later resolution
|
|
288
|
+
* would depend on aren't known, so the walk reports itself incomplete and the
|
|
289
|
+
* snapshot is rebuilt on every call.
|
|
290
|
+
*
|
|
291
|
+
* So does a link target containing `..`. The kernel applies it to the dir the
|
|
292
|
+
* preceding link really points into; fs.realpathSync drops it textually, so
|
|
293
|
+
* the two land in different places and depend on different dirs. Neither
|
|
294
|
+
* answer can be watched for both, so both realpaths are just redone each call.
|
|
295
|
+
*/
|
|
296
|
+
function watchResolution(dir: string, state: WalkState): Walk {
|
|
297
|
+
const incomplete = { complete: false, real: null };
|
|
298
|
+
const abs = path.resolve(dir);
|
|
299
|
+
let cur = path.parse(abs).root;
|
|
300
|
+
if (!state.watched.has(cur)) state.watched.set(cur, dirSignature(cur));
|
|
301
|
+
// A stack: the next component is at the end.
|
|
302
|
+
const pending = components(abs.slice(cur.length)).reverse();
|
|
303
|
+
let hops = 0;
|
|
304
|
+
while (pending.length > 0) {
|
|
305
|
+
const next = path.join(cur, pending.pop()!);
|
|
306
|
+
if (state.watched.has(next)) {
|
|
307
|
+
cur = next;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
let target = state.targets.get(next);
|
|
311
|
+
if (target === undefined) {
|
|
312
|
+
let st: fs.Stats;
|
|
313
|
+
try {
|
|
314
|
+
st = fs.lstatSync(next);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
return { complete: (err as NodeJS.ErrnoException).code === "ENOENT", real: null };
|
|
317
|
+
}
|
|
318
|
+
if (!st.isSymbolicLink()) {
|
|
319
|
+
if (!st.isDirectory()) return incomplete;
|
|
320
|
+
state.watched.set(next, signatureOf(st));
|
|
321
|
+
cur = next;
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
state.links.set(next, signatureOf(st));
|
|
325
|
+
try {
|
|
326
|
+
target = fs.readlinkSync(next);
|
|
327
|
+
} catch {
|
|
328
|
+
return incomplete;
|
|
329
|
+
}
|
|
330
|
+
state.targets.set(next, target);
|
|
331
|
+
}
|
|
332
|
+
if (++hops > MAX_LINK_HOPS) return incomplete;
|
|
333
|
+
// Split on both separators: on POSIX a backslash is just a name
|
|
334
|
+
// character, and calling it one only errs toward incomplete.
|
|
335
|
+
if (target.split(/[\\/]/).includes("..")) return incomplete;
|
|
336
|
+
const resolved = path.resolve(cur, target);
|
|
337
|
+
cur = path.parse(resolved).root;
|
|
338
|
+
if (!state.watched.has(cur)) state.watched.set(cur, dirSignature(cur));
|
|
339
|
+
const parts = components(resolved.slice(cur.length));
|
|
340
|
+
for (let i = parts.length - 1; i >= 0; i--) pending.push(parts[i]);
|
|
341
|
+
}
|
|
342
|
+
return { complete: true, real: cur };
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function components(rel: string): string[] {
|
|
346
|
+
return rel.split(path.sep).filter(Boolean);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function isSymlink(p: string): boolean {
|
|
350
|
+
try {
|
|
351
|
+
return fs.lstatSync(p).isSymbolicLink();
|
|
352
|
+
} catch {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function dirSignature(dir: string): DirSignature {
|
|
358
|
+
try {
|
|
359
|
+
return signatureOf(fs.lstatSync(dir));
|
|
360
|
+
} catch {
|
|
361
|
+
return { key: "absent", changedAt: -Infinity };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function signatureOf(st: fs.Stats): DirSignature {
|
|
366
|
+
return {
|
|
367
|
+
key: `${st.mtimeMs}:${st.ctimeMs}:${st.ino}`,
|
|
368
|
+
// max, so a future mtime set by hand keeps the snapshot untrusted too.
|
|
369
|
+
changedAt: Math.max(st.mtimeMs, st.ctimeMs),
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function signaturesMatch(watched: Map<string, DirSignature>): boolean {
|
|
374
|
+
for (const [dir, sig] of watched) if (dirSignature(dir).key !== sig.key) return false;
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// A dir resolved both ways: fs.realpathSync is what the exec-guard's jail
|
|
379
|
+
// hands us, and the native one (what fs.promises.realpath gives the web files
|
|
380
|
+
// surface) can differ from it: a `..` in a link target anywhere, and on
|
|
381
|
+
// Windows an expanded 8.3 short name or a subst or mapped drive's target.
|
|
382
|
+
interface ResolvedDir {
|
|
383
|
+
js: string | null;
|
|
384
|
+
native: string | null;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// A path both as written and as resolved, since callers hand us realpaths. Only
|
|
388
|
+
// a file that is itself a symlink needs its own realpath; anything else
|
|
389
|
+
// resolves through its parent, which is resolved once per directory and shared
|
|
390
|
+
// through `resolvedParents`. That also covers a file that doesn't exist yet.
|
|
391
|
+
function withRealpath(
|
|
392
|
+
p: string,
|
|
393
|
+
resolvedParents: Map<string, ResolvedDir>,
|
|
394
|
+
isLink: boolean,
|
|
395
|
+
walks?: Map<string, Walk>,
|
|
396
|
+
): string[] {
|
|
397
|
+
const out = [p];
|
|
398
|
+
if (isLink) {
|
|
399
|
+
const own = resolveBothWays(p);
|
|
400
|
+
if (own.js !== null || own.native !== null) {
|
|
401
|
+
for (const r of [own.js, own.native]) if (r !== null) out.push(r);
|
|
402
|
+
return out;
|
|
403
|
+
}
|
|
404
|
+
/* dangling -- the parent-resolved spelling is still worth having */
|
|
405
|
+
}
|
|
406
|
+
const dir = path.dirname(p);
|
|
407
|
+
let realDir = resolvedParents.get(dir);
|
|
408
|
+
if (!realDir) {
|
|
409
|
+
realDir = resolveBothWays(dir, walks?.get(dir));
|
|
410
|
+
resolvedParents.set(dir, realDir);
|
|
411
|
+
}
|
|
412
|
+
for (const r of [realDir.js, realDir.native]) {
|
|
413
|
+
if (r !== null) out.push(path.join(r, path.basename(p)));
|
|
414
|
+
}
|
|
415
|
+
return out;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Both realpaths of `p`. A completed walk that agrees with fs.realpathSync has
|
|
420
|
+
* just done what the kernel does -- it only completes when no link target has
|
|
421
|
+
* a `..` in it, the one place the two part ways -- so off Windows the native
|
|
422
|
+
* call is skipped then. On Windows the native one can still differ (an 8.3
|
|
423
|
+
* short name comes back expanded, a subst or mapped drive as its target), and
|
|
424
|
+
* callers that resolved natively hand us that spelling, so it always runs there.
|
|
425
|
+
*/
|
|
426
|
+
function resolveBothWays(p: string, walk?: Walk): ResolvedDir {
|
|
427
|
+
const attempt = (resolve: (p: string) => string): string | null => {
|
|
428
|
+
try {
|
|
429
|
+
return resolve(p);
|
|
430
|
+
} catch {
|
|
431
|
+
/* nothing on disk yet -- the lexical path is all there is */
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const js = attempt(fs.realpathSync);
|
|
436
|
+
if (process.platform !== "win32" && walk?.complete && walk.real === js) {
|
|
437
|
+
return { js, native: js };
|
|
438
|
+
}
|
|
439
|
+
return { js, native: attempt(fs.realpathSync.native) };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export function isSensitivePath(absPath: string, home: string, agentDir?: string): boolean {
|
|
443
|
+
if (isCredentialStore(absPath, home, agentDir)) return true;
|
|
444
|
+
if (SENSITIVE_BASENAME.test(path.basename(path.normalize(absPath)))) return true;
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Case-folded path-segment membership. macOS HFS+ is case-insensitive and
|
|
449
|
+
// realpath does not normalize case there, so `.Git` / `.LOOM` would otherwise
|
|
450
|
+
// dodge the check. Folding may over-match a literal `.Git` dir on case-sensitive
|
|
451
|
+
// Linux, but that errs toward protection.
|
|
452
|
+
function hasSegment(p: string, name: string): boolean {
|
|
453
|
+
return p.split(path.sep).some((s) => s.toLowerCase() === name);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Write targets gated even inside the workspace jail. A file under `.git`
|
|
457
|
+
// (hooks run on the next git operation; config can redirect hooksPath) or under
|
|
458
|
+
// a state dir (`.loom` or `.orbit` -- Orbit's own session state) should never be
|
|
459
|
+
// written by the model silently -- it uses git commands for repo ops, not the
|
|
460
|
+
// write tool.
|
|
461
|
+
//
|
|
462
|
+
// `home` enables the one carve-out we need: Orbit files analyses under
|
|
463
|
+
// $HOME/.loom/analyses/<name>/ (and, after the rename, $HOME/.orbit/analyses),
|
|
464
|
+
// so those workspaces sit under a state-dir segment yet are the agent's actual
|
|
465
|
+
// work product, not Orbit state. Writes there are allowed -- but a *nested*
|
|
466
|
+
// `.git`/`.loom`/`.orbit` inside an analysis (a real repo's hooks, or the
|
|
467
|
+
// per-workspace state dir) stays protected. Everything else with a `.git` or
|
|
468
|
+
// state-dir segment -- Orbit's home state, some other repo's .git, a
|
|
469
|
+
// per-workspace state dir outside the analyses tree, or a path whose cwd
|
|
470
|
+
// happens to sit inside one -- stays gated. `.git` is never carved out: a
|
|
471
|
+
// workspace is never legitimately inside one. Pass home="" for the plain
|
|
472
|
+
// absolute check (callers without a home / the unit tests).
|
|
473
|
+
export function isProtectedWritePath(absPath: string, home = ""): boolean {
|
|
474
|
+
if (hasSegment(path.normalize(absPath), ".git")) return true;
|
|
475
|
+
return isOrbitStatePath(absPath, home);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// The harness-owned record: the signed registry and frozen templates under
|
|
479
|
+
// `<state dir>/state/`, and the per-attempt provenance under
|
|
480
|
+
// `<state dir>/provenance/`. Nothing the model does needs to write either, and
|
|
481
|
+
// an approval it could write itself would not be consent, so these are a
|
|
482
|
+
// floor for the file tools -- denied, not asked about -- where the rest of the
|
|
483
|
+
// state dir only prompts.
|
|
484
|
+
const RECORD_STORE_DIRS = new Set(["state", "provenance"]);
|
|
485
|
+
|
|
486
|
+
export function isRecordStorePath(absPath: string): boolean {
|
|
487
|
+
const segments = path.normalize(absPath).split(path.sep);
|
|
488
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
489
|
+
if (!(WORKSPACE_STATE_DIR_NAMES as readonly string[]).includes(segments[i].toLowerCase())) {
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (RECORD_STORE_DIRS.has(segments[i + 1].toLowerCase())) return true;
|
|
493
|
+
}
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Both spellings are state in every workspace, whichever one it actually uses:
|
|
498
|
+
// a `.loom` workspace must not leave a sibling `.orbit` writable, or the other
|
|
499
|
+
// way round.
|
|
500
|
+
function hasStateSegment(p: string): boolean {
|
|
501
|
+
return WORKSPACE_STATE_DIR_NAMES.some((name) => hasSegment(p, name));
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Orbit's own state: a path with a state-dir segment that is NOT the analyses
|
|
505
|
+
// tree Orbit hands the agent as a workspace. Split out of isProtectedWritePath
|
|
506
|
+
// so the bash classifier can reuse exactly this carve-out without also
|
|
507
|
+
// inheriting the `.git` rule -- a `.git` write through bash is an ordinary
|
|
508
|
+
// unrecognized command, not a catastrophic one. (home is compared
|
|
509
|
+
// un-realpath'd, matching isSensitivePath; pass home="" for the plain absolute
|
|
510
|
+
// check.)
|
|
511
|
+
export function isOrbitStatePath(absPath: string, home = ""): boolean {
|
|
512
|
+
const norm = path.normalize(absPath);
|
|
513
|
+
if (!hasStateSegment(norm)) return false;
|
|
514
|
+
// A home that itself sits under a state dir gets no carve-out: the segment
|
|
515
|
+
// above it is state no matter which analyses tree the path is in.
|
|
516
|
+
if (home && !hasStateSegment(path.normalize(home))) {
|
|
517
|
+
for (const name of WORKSPACE_STATE_DIR_NAMES) {
|
|
518
|
+
const analyses = path.join(home, name, "analyses");
|
|
519
|
+
if (within(norm, analyses) && !hasStateSegment(path.relative(analyses, norm))) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type Decision = "allow" | "ask" | "deny";
|
|
2
|
+
export type ModelTier = "trusted" | "weak";
|
|
3
|
+
|
|
4
|
+
export interface GuardianConfig {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
dangerouslyBypassPermissions: boolean;
|
|
7
|
+
trustedWorkspaces: string[];
|
|
8
|
+
extraWorkspaceRoots: string[];
|
|
9
|
+
consentAcknowledged: { version: string; at: string } | null;
|
|
10
|
+
/** Opt-in: run allowed bash inside an OS sandbox (confines bash writes + network). */
|
|
11
|
+
sandbox: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface PathResolver {
|
|
15
|
+
/** Realpath the target (resolving the deepest existing ancestor for not-yet-existing
|
|
16
|
+
* targets) and report whether it lands inside any allowed root. */
|
|
17
|
+
contains(targetPath: string): { resolved: string; inside: boolean };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface PolicyRequest {
|
|
21
|
+
toolName: string;
|
|
22
|
+
toolInput: Record<string, unknown>;
|
|
23
|
+
modelTier: ModelTier;
|
|
24
|
+
config: GuardianConfig;
|
|
25
|
+
interactive: boolean;
|
|
26
|
+
cwd: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface PolicyDeps {
|
|
30
|
+
resolver: PathResolver;
|
|
31
|
+
home: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface PolicyResult {
|
|
35
|
+
decision: Decision;
|
|
36
|
+
// e.g. "bypass", "bash:safe", "bash:catastrophic", "write:in-jail", "read:sensitive",
|
|
37
|
+
// "galaxy:destructive", "default:ask"
|
|
38
|
+
category: string;
|
|
39
|
+
reason: string; // human-facing
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const CONSENT_VERSION = "1";
|