Follow-up: Additional Workflow Operations (galaxy-tool-util)
Deferred from the initial normalized models plan. Implement after normalizedFormat2 and normalizedNative land and their declarative tests pass.
Expanded Models ✅
expandedFormat2(raw)— extendsNormalizedFormat2, resolves inline subworkflows recursively. External URL/@import resolution not yet wired (no test expectations require it).expandedNative(raw)— extendsNormalizedNativeWorkflow, resolves inline subworkflow references recursively.$graphmulti-document resolution already handled bynormalizedFormat2; expanded models go further by fetching/inlining external references (future).
New: packages/schema/src/workflow/normalized/expanded.ts
Expectation files
normalized_format2.ymlcontainstest_steps_without_run_unchanged(operation:expanded_format2) andtest_inline_subworkflow_expanded(operation:expanded_native) — both passing.
Conversion Operations ✅
toFormat2(native)— native → format2 conversiontoNative(format2)— format2 → native conversionensureFormat2(any)— polymorphic: accepts either format, returnsNormalizedFormat2ensureNative(any)— polymorphic: accepts either format, returnsNormalizedNativeWorkflow
New files:
packages/schema/src/workflow/normalized/toFormat2.ts— full native→format2 conversion with label map, step conversion (tool/subworkflow/pause), PJA→out conversion (all 7 action types), input_connections→in conversion, comments conversion (native→format2), anonymous output reference rewritingpackages/schema/src/workflow/normalized/toNative.ts— full format2→native conversion with ConversionContext (label registry + source resolution), input step building (type mapping), step dispatch (tool/subworkflow/pause), connection building with subworkflow input wiring, PJA building from out properties, workflow output wiring, comments conversion (format2→native)packages/schema/src/workflow/normalized/ensure.ts— format detection viaa_galaxy_workflow/class: GalaxyWorkflowand dispatchpackages/schema/src/workflow/normalized/comments.ts—flattenCommentData(native→format2) andunflattenCommentData(format2→native), port of gxformat2/_comment_helpers.pypackages/schema/src/workflow/normalized/labels.ts—resolveSourceReference,Labelsclass,UNLABELED_*prefixes,isUnlabeled/isAnonymousOutputLabelpredicates, port of gxformat2/_labels.py
Expectation files
to_format2.yml— 8 tests, all passingto_native.yml— 10 tests (+ 1 comments), all passingensure_format2.yml— 2 tests, all passingensure_native.yml— 2 tests, all passing
Changes to existing files
normalizedFormat2now passescommentsthrough on the result object (not in schema, but accessible via cast)normalizedNativenow passescommentsthrough similarly- Test runner: added
format_version→format-versiontoFIELD_ALIASES UNSUPPORTED_OPERATIONSemptied; all 6 operations now inOPERATIONSdispatch map
Implementation order (as executed)
- ✅ Shared utilities:
comments.ts,labels.ts - ✅
toFormat2(native → format2) - ✅
toNative(format2 → native) - ✅
ensureFormat2/ensureNative(polymorphic entry points) - ✅
expandedFormat2/expandedNative(inline-only expansion) - ✅ Wired into test runner + exports
Test results
- 61/61 declarative tests passing (0 skipped)
- Full suite: 4012 passed, 61 skipped (unrelated), 11 test files
- TypeScript: clean build (noEmit)
Resolved questions
_toSourcestrips/outputsuffix when output_name === “output” (matches Python)- Full PJA set implemented: Rename, Hide, DeleteIntermediates, ChangeDatatype, ColumnSet, TagDataset, RemoveTagDataset
- Comments conversion implemented in both directions using shared helpers ported from gxformat2/_comment_helpers.py
- Default positions generated as (10idx, 10idx) matching Python
- UUIDs not generated for to_native (tests don’t check them, Python generates random UUIDs)
Unresolved questions
- Expanded models: URL resolution / @import resolution not implemented (no test expectations, would need async resolver or callback pattern)
pick_valuestep type: partially handled in toFormat2 (falls through to tool handler) — no test expectations existGalaxyUserToolstep type: not handled (no test expectations)$graphdeduplication in toNative: Python supportsdeduplicate_subworkflowsoption — not implemented (no test expectations)
Integration with validate-workflow CLI
Once normalized + expanded models exist, validate-workflow could:
- Normalize before tool-state validation (catches malformed shorthands earlier)
- Report normalization warnings (e.g. deprecated input type aliases)
- Accept either format and convert via
ensure*for uniform validation