Skip to content

Fix WfFormat 1.6 compatibility - #168

Merged
rafaelfsilva merged 5 commits into
mainfrom
fix/wfformat-1.6-compat
Oct 13, 2026
Merged

rafaelfsilva merged 5 commits into
mainfrom
fix/wfformat-1.6-compat

Conversation

@rafaelfsilva

Copy link
Copy Markdown
Member

Follow-up to #167. WfCommons wrote schemaVersion: "1.6", but most of its output failed the official WfFormat 1.6 validator, and it could not load many valid 1.6 instances.

What was broken

  • Wrong DAG metrics. compute_metrics built its graph with nodes keyed by task name and edges keyed by parent id, so numberOfLevels / minimumWidth / maximumWidth were wrong whenever name ≠ id. Every recipe-generated instance (0 of 23 tested) and every benchmark failed validation.
  • Crash on valid task IDs. IDs without _ID/_0 (e.g. ID0000001, or the : and / newly allowed in 1.6) raised ValueError in write_json, and in all translators.
  • Reader too strict. Instance required optional properties (description, createdAt, author, runtimeSystem, files, execution, machine cpu) and dropped data on round trip (energy/power keys, author details, timestamps).
  • Validator. Draft4Validator against a draft 2020-12 schema, no handling of spec-only instances, and a schema cached in the current working directory (a stale 1.5 copy rejected every 1.6 instance).
  • Parsers emitted invalid IDs and values (e.g. Pegasus coreCount: 0, unsanitized file names), and wfbench swapped time/num_chunks and corrupted arguments when renaming files.

Changes

  • Core (common/, wfinstances/instance.py, wfinstances/schema.py): metrics computed on an ID-keyed graph; integer byte totals; avgPowerInW; RFC 3339 timestamps; spec-only instances; all optional 1.6 properties accepted and round-tripped. SchemaValidator fetches the schema from the WfFormat release matching the version WfCommons writes (v1.6), caches it in ~/.cache/wfcommons, picks the validator from the schema's draft, and ports the upstream semantic checks.
  • wfchef: graph nodes keyed by task ID, task types derived from names.
  • Log parsers: ID/file sanitization, real start times and units, Pegasus core counts, RO-Crate counter and cycle fixes, Nextflow ms/d durations, machines emitted, keyword constructor arguments.
  • wfbench / translators: graph built from the workflow, IDs mapped to valid identifiers per target system (output unchanged for workflows whose IDs are already valid), clear error for tasks without a command, workflows without files, and the benchmark argument bugs.

Behavior changes

  • Instance now rejects what the official validator rejects (inconsistent metrics, duplicate IDs, dangling references, cycles).
  • Naive timestamps are written with the local timezone; tasks with no known start time no longer get a made-up executedAt; an empty command is omitted.
  • The first validation on a machine needs network access to fetch the schema (or pass schema_file).
  • Requires jsonschema>=4.18.

Testing

  • New unit tests for metrics, IDs, round trips, the validator, each log parser, and translator identifiers; recipe outputs are now checked against the validator.
  • Official validator, 0 errors / 0 warnings: all 10 recipes at 150–1000 tasks, recipe and synthetic benchmarks, and 297 of 298 local WfInstances files after a load/write round trip. The remaining file (nextflow/legacy/fetchngs-dirt02-001.json) is itself invalid (maximumWidth 19, actual 26) and needs regenerating in WfInstances.
  • CI on this branch: 133 passed on Python 3.11–3.14, including the Docker translator/logger tests.

Known limitations

  • Unknown extra fields (e.g. runName, repo in some Nextflow instances) are still dropped on round trip.
  • Makeflow quoting of # in task IDs is untested at runtime.
  • Swift/T still replaces task IDs and file names with generated ones.
  • Pegasus maxrss/ram_total (KB) and Makeflow resource-monitor (MB) unit conversions were not checked against real logs.

- Compute DAG level/width metrics on a task-ID-keyed graph, so that
  metrics are correct when task names differ from IDs (all recipe and
  benchmark outputs previously failed the WfFormat 1.6 validator), and
  writing no longer crashes on IDs without "_ID"/"_0" (e.g. "ID0000001",
  or IDs with ':' and '/').
- Emit integer byte totals only, gated on their own presence.
- Write avgPowerInW (not avgPowerInKWh), non-empty string arguments,
  coreCount >= 1, RFC 3339 timestamps, unique file IDs, and the command
  object only when set; support specification-only instances.
- Instance: accept every optional 1.6 property (description, createdAt,
  author, runtimeSystem, files, execution, machine cpu), keep tasks that
  have no execution entry, and round-trip energy, power, category,
  timestamps, author details, and unused machines.
- SchemaValidator: use the 1.6 schema shipped with the package instead
  of a copy cached in the working directory, pick the validator from the
  schema's draft (2020-12), report format issues as warnings, and port
  the upstream semantic checks.
- wfchef: key graph nodes by task ID and derive types from task names;
  compute task statistics before writing recipe files.
- Sanitize task and file IDs to the WfFormat character set (Makeflow
  commands such as g++, RO-Crate names, Pegasus/Snakemake/TaskVine file
  names), handle Makeflow "a->b" renames and variables, and give distinct
  files that share a name distinct IDs.
- Pegasus: use the job's cores profile (default 1) instead of 0, string
  arguments, kickstart start times, maxrss/ram_total in bytes, and the
  planner version and DAGMan start time instead of the YAML format
  version and creation time.
- RO-Crate: fix the doubling task counter, accept single input/output
  objects, and skip self-loops and cycles in inferred dependencies.
- Nextflow: parse "ms" and "d" durations correctly.
- Snakemake/TaskVine/Makeflow: real start times and makespans, unit
  conversions, None ignore list, quoted file names, exact name matching.
- Emit machines (task.machines), pass constructor arguments by keyword,
  and replace exit() calls with exceptions.
- Export the Snakemake, StreamFlow, and TaskVine parsers.
A task's executedAt is optional in WfFormat; tasks without a known start
time no longer get the time at which the Task object was created.
- Translators: build the task graph from the workflow instead of
  regenerating its JSON, raise a clear error for tasks without a command,
  and map task IDs and names (which may contain ':', '/', '#', '.', '-')
  to unique identifiers valid in each target system (Parsl, Snakemake,
  Nextflow, CWL/StreamFlow, Airflow, Pegasus, PyCOMPSs, Swift/T); output
  is unchanged for workflows whose IDs are already valid identifiers.
- Handle workflows without files (marker files keep the dependencies in
  Makeflow, Snakemake, and Nextflow), file IDs containing '/', and
  shell-unsafe --name values; replace Swift/T's exit(1) with an error.
- WorkflowBenchmark: pass time/num_chunks in the right order, rewrite only
  the input/output file arguments when renaming files, derive output
  file names from file-system-safe IDs, avoid a division by zero when the
  workflow has no runtimes, clear measured execution data, and look up
  per-type parameters by category or task name.
The schema is no longer versioned in this repository. SchemaValidator
fetches it from the WfFormat release that matches the schema version
written by WfCommons (tag v1.6), caches it in the user cache directory
(~/.cache/wfcommons), and ignores any wfcommons-schema.json file in the
working directory. Downloaded schema files are git-ignored.
@rafaelfsilva
rafaelfsilva merged commit 1a9fe00 into main Oct 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant