From: "Michael R. Crusoe" <crusoe@debian.org>
Date: Thu, 20 Dec 2018 05:19:19 -0800
Subject: Disable --provance until python3-prov issue is resolved

Forwarded: not-needed
Last-Update: 2026-01-24
---
 cwltool/argparser.py           |  58 +--
 setup.py                       |   2 +-
 tests/test_main_parsed_args.py |  19 -
 tests/test_provenance.py       | 845 -----------------------------------------
 4 files changed, 2 insertions(+), 922 deletions(-)

--- cwltool.orig/cwltool/argparser.py
+++ cwltool/cwltool/argparser.py
@@ -396,61 +396,7 @@
         dest="move_outputs",
     )
 
-    provgroup = parser.add_argument_group("provenance recording")
-    provgroup.add_argument(
-        "--provenance",
-        help="Save provenance to specified folder as a "
-        "Research Object that captures and aggregates "
-        "workflow execution and data products.",
-        type=str,
-    )
-    provgroup.add_argument(
-        "--enable-user-provenance",
-        default=False,
-        action="store_true",
-        help="Record user account info as part of --provenance.",
-        dest="user_provenance",
-    )
-    provgroup.add_argument(
-        "--disable-user-provenance",
-        default=False,
-        action="store_false",
-        help="Do not record user account info in --provenance.",
-        dest="user_provenance",
-    )
-    provgroup.add_argument(
-        "--enable-host-provenance",
-        default=False,
-        action="store_true",
-        help="Record host info as part of --provenance.",
-        dest="host_provenance",
-    )
-    provgroup.add_argument(
-        "--disable-host-provenance",
-        default=False,
-        action="store_false",
-        help="Do not record host info in --provenance.",
-        dest="host_provenance",
-    )
-    provgroup.add_argument(
-        "--orcid",
-        help="Record user ORCID identifier as part of "
-        "--provenance, e.g. https://orcid.org/0000-0002-1825-0097 "
-        "or 0000-0002-1825-0097. Alternatively the environment variable "
-        "ORCID may be set.",
-        dest="orcid",
-        default=os.environ.get("ORCID", ""),
-        type=str,
-    )
-    provgroup.add_argument(
-        "--full-name",
-        help="Record full name of user as part of --provenance, "
-        "e.g. `Josiah Carberry`. You may need to use shell quotes to preserve "
-        "spaces. Also set by the CWL_FULL_NAME environment variable.",
-        dest="cwl_full_name",
-        default=os.environ.get("CWL_FULL_NAME", ""),
-        type=str,
-    )
+    parser.add_argument("--provenance", help=argparse.SUPPRESS)
 
     strictgroup = parser.add_mutually_exclusive_group()
     strictgroup.add_argument(
--- cwltool.orig/setup.py
+++ cwltool/setup.py
@@ -152,7 +152,7 @@
         "ruamel.yaml >= 0.16, < 0.20",
         "rdflib >= 4.2.2, < 7.6.0",
         "schema-salad >= 8.9, < 9",
-        "prov == 1.5.1",
+        "prov >= 1.5.1",
         "mypy-extensions",
         "psutil >= 5.6.6",
         "coloredlogs",
--- cwltool.orig/tests/test_main_parsed_args.py
+++ cwltool/tests/test_main_parsed_args.py
@@ -19,22 +19,3 @@
         assert main(args=parsed_args, stdout=stdout, stderr=stderr) == 0
     except SystemExit as err:
         assert err.code == 0
-
-
-def test_main_parsed_args_provenance(tmp_path: Path) -> None:
-    """Affirm that main can be called with parsed args only, requesting provenance."""
-    stdout = io.StringIO()
-    stderr = io.StringIO()
-
-    prov_folder = tmp_path / "provenance"  # will be created if necessary
-
-    unparsed_args = ["--provenance", str(prov_folder), get_data("tests/echo.cwl"), "--inp", "Hello"]
-    parsed_args = arg_parser().parse_args(unparsed_args)
-
-    try:
-        assert main(args=parsed_args, stdout=stdout, stderr=stderr) == 0
-    except SystemExit as err:
-        assert err.code == 0
-
-    manifest_file = prov_folder / "metadata" / "manifest.json"
-    assert manifest_file.is_file(), f"Can't find RO-Crate manifest {manifest_file}"
--- cwltool.orig/tests/test_provenance.py
+++ cwltool/tests/test_provenance.py
@@ -8,16 +8,11 @@
 from typing import IO, Any, cast
 
 import arcp
-import bagit
 import pytest
 from rdflib import Graph, Namespace, URIRef
 from rdflib.namespace import DC, DCTERMS, RDF
 from rdflib.term import Literal
 
-import cwltool.cwlprov as provenance
-from cwltool.cwlprov import provenance_constants
-from cwltool.cwlprov.ro import ResearchObject
-from cwltool.cwlprov.writablebagfile import close_ro, write_bag_file
 from cwltool.main import main
 from cwltool.stdfsaccess import StdFsAccess
 
@@ -36,847 +31,3 @@
 
 
 TEST_ORCID = "https://orcid.org/0000-0003-4862-3349"
-
-
-def cwltool(tmp_path: Path, *args: Any, with_orcid: bool = False) -> Path:
-    prov_folder = tmp_path / "provenance"
-    prov_folder.mkdir()
-    new_args = [
-        "--enable-user-provenance",
-        "--enable-host-provenance",
-        "--provenance",
-        str(prov_folder),
-    ]
-    if with_orcid:
-        new_args.extend(["--orcid", TEST_ORCID])
-    new_args.extend(args)
-    # Run within a temporary directory to not pollute git checkout
-    tmp_dir = tmp_path / "cwltool-run"
-    tmp_dir.mkdir()
-    with working_directory(tmp_dir):
-        status = main(new_args)
-        assert status == 0, f"Failed: cwltool.main({args})"
-    return prov_folder
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_hello_workflow(tmp_path: Path, with_orcid: bool) -> None:
-    check_provenance(
-        cwltool(
-            tmp_path,
-            get_data("tests/wf/hello-workflow.cwl"),
-            "--usermessage",
-            "Hello workflow",
-            with_orcid=with_orcid,
-        ),
-        with_orcid=with_orcid,
-    )
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_hello_single_tool(tmp_path: Path, with_orcid: bool) -> None:
-    check_provenance(
-        cwltool(
-            tmp_path,
-            get_data("tests/wf/hello_single_tool.cwl"),
-            "--message",
-            "Hello tool",
-            with_orcid=with_orcid,
-        ),
-        single_tool=True,
-        with_orcid=with_orcid,
-    )
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_revsort_workflow(tmp_path: Path, with_orcid: bool) -> None:
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/revsort.cwl"),
-        get_data("tests/wf/revsort-job.json"),
-        with_orcid=with_orcid,
-    )
-    check_output_object(folder)
-    check_provenance(folder, with_orcid=with_orcid)
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_revsort_workflow_shortcut(tmp_path: Path, with_orcid: bool) -> None:
-    """Confirm that using 'cwl:tool' shortcut still snapshots the CWL files."""
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/revsort-job-shortcut.json"),
-        with_orcid=with_orcid,
-    )
-    check_output_object(folder)
-    check_provenance(folder, with_orcid=with_orcid)
-    assert not (folder / "snapshot" / "revsort-job-shortcut.json").exists()
-    assert len(list((folder / "snapshot").iterdir())) == 4
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_nested_workflow(tmp_path: Path, with_orcid: bool) -> None:
-    check_provenance(
-        cwltool(
-            tmp_path,
-            get_data("tests/wf/nested.cwl"),
-            with_orcid=with_orcid,
-        ),
-        nested=True,
-        with_orcid=with_orcid,
-    )
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_secondary_files_implicit(tmp_path: Path, with_orcid: bool) -> None:
-    file1 = tmp_path / "foo1.txt"
-    file1idx = tmp_path / "foo1.txt.idx"
-
-    with open(str(file1), "w", encoding="ascii") as f:
-        f.write("foo")
-    with open(str(file1idx), "w", encoding="ascii") as f:
-        f.write("bar")
-
-    # secondary will be picked up by .idx
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/sec-wf.cwl"),
-        "--file1",
-        str(file1),
-        with_orcid=with_orcid,
-    )
-    check_provenance(folder, secondary_files=True, with_orcid=with_orcid)
-    check_secondary_files(folder)
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_secondary_files_explicit(tmp_path: Path, with_orcid: bool) -> None:
-    # Deliberately do NOT have common basename or extension
-    file1dir = tmp_path / "foo"
-    file1dir.mkdir()
-    file1 = file1dir / "foo"
-    file1idxdir = tmp_path / "bar"
-    file1idxdir.mkdir()
-    file1idx = file1idxdir / "bar"
-
-    with open(file1, "w", encoding="ascii") as f:
-        f.write("foo")
-    with open(file1idx, "w", encoding="ascii") as f:
-        f.write("bar")
-
-    # explicit secondaryFiles
-    job = {
-        "file1": {
-            "class": "File",
-            "path": str(file1),
-            "basename": "foo1.txt",
-            "secondaryFiles": [
-                {
-                    "class": "File",
-                    "path": str(file1idx),
-                    "basename": "foo1.txt.idx",
-                }
-            ],
-        }
-    }
-
-    jobJson = tmp_path / "job.json"
-    with open(jobJson, "wb") as fp:
-        j = json.dumps(job, ensure_ascii=True)
-        fp.write(j.encode("ascii"))
-
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/sec-wf.cwl"),
-        str(jobJson),
-        with_orcid=with_orcid,
-    )
-    check_provenance(folder, secondary_files=True, with_orcid=with_orcid)
-    check_secondary_files(folder)
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_secondary_files_output(tmp_path: Path, with_orcid: bool) -> None:
-    # secondary will be picked up by .idx
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/sec-wf-out.cwl"),
-        with_orcid=with_orcid,
-    )
-    check_provenance(folder, secondary_files=True, with_orcid=with_orcid)
-    # Skipped, not the same secondary files as above
-    # self.check_secondary_files()
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_directory_workflow(tmp_path: Path, with_orcid: bool) -> None:
-    dir2 = tmp_path / "dir2"
-    dir2.mkdir()
-    sha1 = {
-        # Expected hashes of ASCII letters (no linefeed)
-        # as returned from:
-        # for x in a b c ; do echo -n $x | sha1sum ; done
-        "a": "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
-        "b": "e9d71f5ee7c92d6dc9e92ffdad17b8bd49418f98",
-        "c": "84a516841ba77a5b4648de2cd0dfcb30ea46dbb4",
-    }
-    for x in "abc":
-        # Make test files with predictable hashes
-        with open(dir2 / x, "w", encoding="ascii") as f:
-            f.write(x)
-
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/directory.cwl"),
-        "--dir",
-        str(dir2),
-        with_orcid=with_orcid,
-    )
-    check_provenance(folder, directory=True, with_orcid=with_orcid)
-
-    # Output should include ls stdout of filenames a b c on each line
-    file_list = (
-        folder
-        / "data"
-        / "3c"
-        / "3ca69e8d6c234a469d16ac28a4a658c92267c423"
-        # checksum as returned from:
-        # echo -e "a\nb\nc" | sha1sum
-        # 3ca69e8d6c234a469d16ac28a4a658c92267c423  -
-    )
-    assert file_list.is_file()
-
-    # Input files should be captured by hash value,
-    # even if they were inside a class: Directory
-    for letter, l_hash in sha1.items():
-        prefix = l_hash[:2]  # first 2 letters
-        p = folder / "data" / prefix / l_hash
-        assert p.is_file(), f"Could not find {letter} as {p}"
-
-
-@needs_docker
-@pytest.mark.parametrize("with_orcid", [True, False])
-def test_no_data_files(tmp_path: Path, with_orcid: bool) -> None:
-    folder = cwltool(
-        tmp_path,
-        get_data("tests/wf/conditional_step_no_inputs.cwl"),
-        with_orcid=with_orcid,
-    )
-    check_bagit(folder)
-
-
-def check_output_object(base_path: Path) -> None:
-    output_obj = base_path / "workflow" / "primary-output.json"
-    compare_checksum = "sha1$b9214658cc453331b62c2282b772a5c063dbd284"
-    compare_location = "../data/b9/b9214658cc453331b62c2282b772a5c063dbd284"
-    with open(output_obj) as fp:
-        out_json = json.load(fp)
-    f1 = out_json["sorted_output"]
-    assert f1["checksum"] == compare_checksum
-    assert f1["location"] == compare_location
-
-
-def check_secondary_files(base_path: Path) -> None:
-    foo_data = (
-        base_path
-        / "data"
-        / "0b"
-        / "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
-        # checksum as returned from:
-        # $ echo -n foo | sha1sum
-        # 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33  -
-    )
-    bar_data = base_path / "data" / "62" / "62cdb7020ff920e5aa642c3d4066950dd1f01f4d"
-    assert foo_data.is_file(), "Did not capture file.txt 'foo'"
-    assert bar_data.is_file(), "Did not capture secondary file.txt.idx 'bar"
-
-    primary_job = base_path / "workflow" / "primary-job.json"
-    with open(primary_job) as fp:
-        job_json = json.load(fp)
-    # TODO: Verify secondaryFile in primary-job.json
-    f1 = job_json["file1"]
-    assert f1["location"] == "../data/0b/0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
-    assert f1["basename"] == "foo1.txt"
-
-    secondaries = f1["secondaryFiles"]
-    assert secondaries
-    f1idx = secondaries[0]
-    assert f1idx["location"] == "../data/62/62cdb7020ff920e5aa642c3d4066950dd1f01f4d"
-    assert f1idx["basename"], "foo1.txt.idx"
-
-
-def check_provenance(
-    base_path: Path,
-    nested: bool = False,
-    single_tool: bool = False,
-    directory: bool = False,
-    secondary_files: bool = False,
-    with_orcid: bool = False,
-) -> None:
-    check_folders(base_path)
-    check_bagit(base_path)
-    check_ro(base_path, nested=nested)
-    check_prov(
-        base_path,
-        nested=nested,
-        single_tool=single_tool,
-        directory=directory,
-        secondary_files=secondary_files,
-        with_orcid=with_orcid,
-    )
-
-
-def check_folders(base_path: Path) -> None:
-    required_folders = [
-        "data",
-        "snapshot",
-        "workflow",
-        "metadata",
-        os.path.join("metadata", "provenance"),
-    ]
-
-    for folder in required_folders:
-        assert (base_path / folder).is_dir()
-
-
-def check_bagit(base_path: Path) -> None:
-    # check bagit structure
-    required_files = [
-        "bagit.txt",
-        "bag-info.txt",
-        "manifest-sha1.txt",
-        "tagmanifest-sha1.txt",
-        "tagmanifest-sha256.txt",
-    ]
-
-    for basename in required_files:
-        assert (base_path / basename).is_file()
-
-    bag = bagit.Bag(str(base_path))
-    assert bag.has_oxum()
-    (only_manifest, only_fs) = bag.compare_manifests_with_fs()
-    assert not list(only_manifest), "Some files only in manifest"
-    assert not list(only_fs), "Some files only on file system"
-    missing_tagfiles = bag.missing_optional_tagfiles()
-    assert not list(missing_tagfiles), "Some files only in tagmanifest"
-    bag.validate()
-    # TODO: Check other bag-info attributes
-    assert arcp.is_arcp_uri(cast(str, bag.info.get("External-Identifier")))
-
-
-def find_arcp(base_path: Path) -> str:
-    # First try to find External-Identifier
-    bag = bagit.Bag(str(base_path))
-    ext_id = cast(str, bag.info.get("External-Identifier"))
-    if arcp.is_arcp_uri(ext_id):
-        return ext_id
-    raise Exception("Can't find External-Identifier")
-
-
-def _arcp2file(base_path: Path, uri: str) -> Path:
-    parsed = arcp.parse_arcp(uri)
-    # arcp URIs, ensure they are local to our RO
-    assert (
-        parsed.uuid == arcp.parse_arcp(find_arcp(base_path)).uuid
-    ), "arcp URI must be local to the research object"
-
-    path = parsed.path[1:]  # Strip first /
-    return base_path / Path(path)
-
-
-def check_ro(base_path: Path, nested: bool = False) -> None:
-    manifest_file = base_path / "metadata" / "manifest.json"
-    assert manifest_file.is_file(), f"Can't find {manifest_file}"
-    arcp_root = find_arcp(base_path)
-    base = urllib.parse.urljoin(arcp_root, "metadata/manifest.json")
-    g = Graph()
-
-    # Avoid resolving JSON-LD context https://w3id.org/bundle/context
-    # so this test works offline
-    context = Path(get_data("tests/bundle-context.jsonld")).as_uri()
-    with open(manifest_file, encoding="UTF-8") as fh:
-        jsonld = fh.read()
-        # replace with file:/// URI
-        jsonld = jsonld.replace("https://w3id.org/bundle/context", context)
-    g.parse(data=jsonld, format="json-ld", publicID=base)
-    if os.environ.get("DEBUG"):
-        print("Parsed manifest:\n\n")
-        g.serialize(cast(IO[bytes], sys.stdout), format="ttl")
-    _ro = None
-
-    for _ro in g.subjects(ORE.isDescribedBy, URIRef(base)):
-        break
-    assert _ro is not None, "Can't find RO with ore:isDescribedBy"
-
-    profile = None
-    for dc in g.objects(_ro, DCTERMS.conformsTo):
-        profile = dc
-        break
-    assert profile is not None, "Can't find profile with dct:conformsTo"
-    assert profile == URIRef(
-        provenance_constants.CWLPROV_VERSION
-    ), f"Unexpected cwlprov version {profile}"
-
-    paths = []
-    externals = []
-    for aggregate in g.objects(_ro, ORE.aggregates):
-        if not arcp.is_arcp_uri(cast(str, aggregate)):
-            externals.append(aggregate)
-            # Won't check external URIs existence here
-            # TODO: Check they are not relative!
-            continue
-        lfile = _arcp2file(base_path, cast(str, aggregate))
-        paths.append(os.path.relpath(lfile, base_path))
-        assert os.path.isfile(lfile), f"Can't find aggregated {lfile}"
-
-    assert paths, "Didn't find any arcp aggregates"
-    assert externals, "Didn't find any data URIs"
-
-    for ext in ["provn", "xml", "json", "jsonld", "nt", "ttl"]:
-        f = "metadata/provenance/primary.cwlprov.%s" % ext
-        assert f in paths, "provenance file missing " + f
-
-    for f in [
-        "workflow/primary-job.json",
-        "workflow/packed.cwl",
-        "workflow/primary-output.json",
-    ]:
-        assert f in paths, "workflow file missing " + f
-    # Can't test snapshot/ files directly as their name varies
-
-    # TODO: check urn:hash::sha1 thingies
-    # TODO: Check OA annotations
-
-    packed = urllib.parse.urljoin(arcp_root, "/workflow/packed.cwl")
-    primary_job = urllib.parse.urljoin(arcp_root, "/workflow/primary-job.json")
-    primary_prov_nt = urllib.parse.urljoin(arcp_root, "/metadata/provenance/primary.cwlprov.nt")
-    uuid = arcp.parse_arcp(arcp_root).uuid
-
-    highlights = set(g.subjects(OA.motivatedBy, OA.highlighting))
-    assert highlights, "Didn't find highlights"
-    for h in highlights:
-        assert (h, OA.hasTarget, URIRef(packed)) in g
-
-    describes = set(g.subjects(OA.motivatedBy, OA.describing))
-    for d in describes:
-        assert (d, OA.hasBody, URIRef(arcp_root)) in g
-        assert (d, OA.hasTarget, URIRef(uuid.urn)) in g
-
-    linked = set(g.subjects(OA.motivatedBy, OA.linking))
-    for link in linked:
-        assert (link, OA.hasBody, URIRef(packed)) in g
-        assert (link, OA.hasBody, URIRef(primary_job)) in g
-        assert (link, OA.hasTarget, URIRef(uuid.urn)) in g
-
-    has_provenance = set(g.subjects(OA.hasBody, URIRef(primary_prov_nt)))
-    for p in has_provenance:
-        assert (p, OA.hasTarget, URIRef(uuid.urn)) in g
-        assert (p, OA.motivatedBy, PROV.has_provenance) in g
-        # Check all prov elements are listed
-        formats = set()
-        for prov in g.objects(p, OA.hasBody):
-            assert (
-                prov,
-                DCTERMS.conformsTo,
-                URIRef(provenance_constants.CWLPROV_VERSION),
-            ) in g
-            # NOTE: DC.format is a Namespace method and does not resolve like other terms
-            formats.update(set(g.objects(prov, DC["format"])))
-        assert formats, "Could not find media types"
-        expected = {
-            Literal(f)
-            for f in (
-                "application/json",
-                "application/ld+json",
-                "application/n-triples",
-                'text/provenance-notation; charset="UTF-8"',
-                'text/turtle; charset="UTF-8"',
-                "application/xml",
-            )
-        }
-        assert formats == expected, "Did not match expected PROV media types"
-
-    if nested:
-        # Check for additional PROVs
-        # Let's try to find the other wf run ID
-        otherRuns = set()
-        for p in g.subjects(OA.motivatedBy, PROV.has_provenance):
-            if (p, OA.hasTarget, URIRef(uuid.urn)) in g:
-                continue
-            otherRuns.update(set(g.objects(p, OA.hasTarget)))
-        assert otherRuns, "Could not find nested workflow run prov annotations"
-
-
-def check_prov(
-    base_path: Path,
-    nested: bool = False,
-    single_tool: bool = False,
-    directory: bool = False,
-    secondary_files: bool = False,
-    with_orcid: bool = False,
-) -> None:
-    prov_file = base_path / "metadata" / "provenance" / "primary.cwlprov.nt"
-    assert prov_file.is_file(), f"Can't find {prov_file}"
-    arcp_root = find_arcp(base_path)
-    # Note: We don't need to include metadata/provnance in base URI
-    # as .nt always use absolute URIs
-    g = Graph()
-    with open(prov_file, "rb") as f:
-        g.parse(file=f, format="nt", publicID=arcp_root)
-    if os.environ.get("DEBUG"):
-        print("Parsed %s:\n\n" % prov_file)
-        g.serialize(cast(IO[bytes], sys.stdout), format="ttl")
-    runs = set(g.subjects(RDF.type, WFPROV.WorkflowRun))
-
-    # main workflow run URI (as urn:uuid:) should correspond to arcp uuid part
-    uuid = arcp.parse_arcp(arcp_root).uuid
-    main_run = URIRef(uuid.urn)
-    assert main_run in runs, f"Can't find run {main_run} in {runs}"
-    # TODO: we should not need to parse arcp, but follow
-    # the has_provenance annotations in manifest.json instead
-
-    # run should have been started by a wf engine
-    engines = set(g.subjects(RDF.type, WFPROV.WorkflowEngine))
-    assert engines, "Could not find WorkflowEngine"
-    assert len(engines) == 1, "Found too many WorkflowEngines: %s" % engines
-    engine = engines.pop()
-
-    assert (
-        main_run,
-        PROV.wasAssociatedWith,
-        engine,
-    ) in g, "Wf run not associated with wf engine"
-    assert (
-        engine,
-        RDF.type,
-        PROV.SoftwareAgent,
-    ) in g, "Engine not declared as SoftwareAgent"
-
-    # run should be associated to the user
-    accounts = set(g.subjects(RDF.type, FOAF.OnlineAccount))
-    assert len(accounts) == 1
-    account = accounts.pop()
-    people = set(g.subjects(RDF.type, SCHEMA.Person))
-    assert len(people) == 1, "Can't find associated person in workflow run"
-    person = people.pop()
-    if with_orcid:
-        assert person == URIRef(TEST_ORCID)
-    else:
-        account_names = set(g.objects(account, FOAF.accountName))
-        assert len(account_names) == 1
-        account_name = cast(Literal, account_names.pop())
-        machine_user = provenance._whoami()[0]
-        assert account_name.value == machine_user
-
-    # find the random UUID assigned to cwltool
-    tool_agents = set(g.subjects(RDF.type, PROV.SoftwareAgent))
-    n_all_agents = 2 + len(tool_agents)
-    agents = set(g.subjects(RDF.type, PROV.Agent))
-    assert (
-        len(agents) == n_all_agents
-    ), "There should be 1 agent per tool (engine), 1 user agent, and 1 cwltool agent"
-    agents.remove(person)
-    agents.remove(engine)  # the main tool
-    remain_agents = agents - tool_agents
-    assert len(remain_agents) == 1
-    assert (
-        account,
-        PROV.actedOnBehalfOf,
-        person,
-    ) in g, "Association of cwltool agent acting for user is missing"
-
-    if single_tool:
-        activities = set(g.subjects(RDF.type, PROV.Activity))
-        assert len(activities) == 1, "Too many activities: %s" % activities
-        # single tool exec, there should be no other activities
-        # than the tool run
-        # (NOTE: the WorkflowEngine is also activity, but not declared explicitly)
-    else:
-        # Check all process runs were started by the main worklow
-        stepActivities = set(g.subjects(RDF.type, WFPROV.ProcessRun))
-        # Although semantically a WorkflowEngine is also a ProcessRun,
-        # we don't declare that,
-        # thus only the step activities should be in this set.
-        assert main_run not in stepActivities
-        assert stepActivities, "No steps executed in workflow"
-        for step in stepActivities:
-            # Let's check it was started by the main_run. Unfortunately, unlike PROV-N
-            # in PROV-O RDF we have to check through the n-ary qualifiedStart relation
-            starts = set(g.objects(step, PROV.qualifiedStart))
-            assert starts, "Could not find qualifiedStart of step %s" % step
-            assert len(starts) == 1, "Too many qualifiedStart for step %s" % step
-            start = starts.pop()
-            assert (
-                start,
-                PROV.hadActivity,
-                main_run,
-            ) in g, "Step activity not started by main activity"
-            # Tip: Any nested workflow step executions should not be in this prov file,
-            # but in separate file
-    if nested:
-        # Find some cwlprov.nt the nested workflow is described in
-        prov_ids = set(g.objects(predicate=PROV.has_provenance))
-        # FIXME: The above is a bit naive and does not check the subject is
-        # one of the steps -- OK for now as this is the only case of prov:has_provenance
-        assert prov_ids, "Could not find prov:has_provenance from nested workflow"
-
-        nt_uris = [uri for uri in prov_ids if uri.endswith("cwlprov.nt")]
-        # TODO: Look up manifest conformsTo and content-type rather than assuming magic filename
-        assert nt_uris, "Could not find *.cwlprov.nt"
-        # Load into new graph
-        g2 = Graph()
-        nt_uri = nt_uris.pop()
-        with open(_arcp2file(base_path, nt_uri), "rb") as f:
-            g2.parse(file=f, format="nt", publicID=nt_uri)
-        # TODO: Check g2 statements that it's the same UUID activity inside
-        # as in the outer step
-    if directory:
-        directories = set(g.subjects(RDF.type, RO.Folder))
-        assert directories
-
-        for d in directories:
-            assert (d, RDF.type, PROV.Dictionary) in g
-            assert (d, RDF.type, PROV.Collection) in g
-            assert (d, RDF.type, PROV.Entity) in g
-            assert len(list(g.objects(d, CWLPROV.basename))) == 1
-
-            files = set()
-            for entry in g.objects(d, PROV.hadDictionaryMember):
-                assert (entry, RDF.type, PROV.KeyEntityPair) in g
-                # We don't check what that filename is here
-                assert set(g.objects(entry, PROV.pairKey))
-
-                # RO:Folder aspect
-                assert set(g.objects(entry, RO.entryName))
-                assert (d, ORE.aggregates, entry) in g
-                assert (entry, RDF.type, RO.FolderEntry) in g
-                assert (entry, RDF.type, ORE.Proxy) in g
-                assert (entry, ORE.proxyIn, d) in g
-                assert (entry, ORE.proxyIn, d) in g
-
-                # Which file?
-                entities = set(g.objects(entry, PROV.pairEntity))
-                assert entities
-                ef = entities.pop()
-                files.add(ef)
-                assert (entry, ORE.proxyFor, ef) in g
-                assert (ef, RDF.type, PROV.Entity) in g
-
-            if not files:
-                assert (d, RDF.type, PROV.EmptyCollection) in g
-                assert (d, RDF.type, PROV.EmptyDictionary) in g
-    if secondary_files:
-        derivations = set(g.subjects(RDF.type, CWLPROV.SecondaryFile))
-        assert derivations
-        for der in derivations:
-            sec = set(g.subjects(PROV.qualifiedDerivation, der)).pop()
-            prim = set(g.objects(der, PROV.entity)).pop()
-
-            # UUID specializes a hash checksum
-            assert set(g.objects(sec, PROV.specializationOf))
-            # extensions etc.
-            sec_basename = set(g.objects(sec, CWLPROV.basename)).pop()
-            sec_nameroot = set(g.objects(sec, CWLPROV.nameroot)).pop()
-            sec_nameext = set(g.objects(sec, CWLPROV.nameext)).pop()
-            assert str(sec_basename) == f"{sec_nameroot}{sec_nameext}"
-            # TODO: Check hash data file exist in RO
-
-            # The primary entity should have the same, but different values
-            assert set(g.objects(prim, PROV.specializationOf))
-            prim_basename = set(g.objects(prim, CWLPROV.basename)).pop()
-            prim_nameroot = set(g.objects(prim, CWLPROV.nameroot)).pop()
-            prim_nameext = set(g.objects(prim, CWLPROV.nameext)).pop()
-            assert str(prim_basename) == f"{prim_nameroot}{prim_nameext}"
-
-
-@pytest.fixture
-def research_object(tmp_path: Path) -> Generator[ResearchObject, None, None]:
-    re_ob = ResearchObject(StdFsAccess(str(tmp_path / "ro")), temp_prefix_ro=str(tmp_path / "tmp"))
-    yield re_ob
-    close_ro(re_ob)
-
-
-def test_absolute_path_fails(research_object: ResearchObject) -> None:
-    with pytest.raises(ValueError):
-        write_bag_file(research_object, "/absolute/path/fails")
-
-
-def test_climboutfails(research_object: ResearchObject) -> None:
-    with pytest.raises(ValueError):
-        write_bag_file(research_object, "../../outside-ro")
-
-
-def test_writable_string(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "file.txt") as fh:
-        assert fh.writable()
-        fh.write("Hello\n")
-
-    sha1 = os.path.join(research_object.folder, "tagmanifest-sha1.txt")
-    assert os.path.isfile(sha1)
-
-    with open(sha1, encoding="UTF-8") as sha_file:
-        stripped_sha = sha_file.readline().strip()
-    assert stripped_sha.endswith("file.txt")
-    # stain@biggie:~/src/cwltool$ echo Hello | sha1sum
-    # 1d229271928d3f9e2bb0375bd6ce5db6c6d348d9  -
-    assert stripped_sha.startswith("1d229271928d3f9e2bb0375bd6ce5db6c6d348d9")
-
-    sha256 = os.path.join(research_object.folder, "tagmanifest-sha256.txt")
-    assert os.path.isfile(sha256)
-
-    with open(sha256, encoding="UTF-8") as sha_file:
-        stripped_sha = sha_file.readline().strip()
-
-    assert stripped_sha.endswith("file.txt")
-    # stain@biggie:~/src/cwltool$ echo Hello | sha256sum
-    # 66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18  -
-    assert stripped_sha.startswith(
-        "66a045b452102c59d840ec097d59d9467e13a3f34f6494e539ffd32c1bb35f18"
-    )
-
-    sha512 = os.path.join(research_object.folder, "tagmanifest-sha512.txt")
-    assert os.path.isfile(sha512)
-
-
-def test_writable_unicode_string(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "file.txt") as fh:
-        assert fh.writable()
-        fh.write("Here is a snowman: \u2603 \n")
-
-
-def test_writable_bytes(research_object: ResearchObject) -> None:
-    string = "Here is a snowman: \u2603 \n".encode()
-    with write_bag_file(research_object, "file.txt", encoding=None) as fh:
-        fh.write(string)  # type: ignore
-
-
-def test_data(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "data/file.txt") as fh:
-        assert fh.writable()
-        fh.write("Hello\n")
-
-    # Because this is under data/ it should add to manifest
-    # rather than tagmanifest
-    sha1 = os.path.join(research_object.folder, "manifest-sha1.txt")
-    assert os.path.isfile(sha1)
-    with open(sha1, encoding="UTF-8") as fh2:
-        stripped_sha = fh2.readline().strip()
-        assert stripped_sha.endswith("data/file.txt")
-
-
-def test_not_seekable(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "file.txt") as fh:
-        assert not fh.seekable()
-        with pytest.raises(OSError):
-            fh.seek(0)
-
-
-def test_not_readable(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "file.txt") as fh:
-        assert not fh.readable()
-        with pytest.raises(OSError):
-            fh.read()
-
-
-def test_truncate_fails(research_object: ResearchObject) -> None:
-    with write_bag_file(research_object, "file.txt") as fh:
-        fh.write("Hello there")
-        fh.truncate()  # OK as we're always at end
-        # Will fail because the checksum can't rewind
-        with pytest.raises(OSError):
-            fh.truncate(0)
-
-
-mod_validness = [
-    # Taken from "Some sample ORCID iDs" on
-    # https://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
-    ("0000-0002-1825-0097", True),
-    ("0000-0001-5109-3700", True),
-    ("0000-0002-1694-233X", True),
-    # dashes optional
-    ("0000000218250097", True),
-    ("0000000151093700", True),
-    ("000000021694233X", True),
-    # do not fail on missing digits
-    ("0002-1694-233X", True),
-    # Swap check-digits around to force error
-    ("0000-0002-1825-009X", False),
-    ("0000-0001-5109-3707", False),
-    ("0000-0002-1694-2330", False),
-]
-
-
-@pytest.mark.parametrize("mod11,valid", mod_validness)
-def test_check_mod_11_2(mod11: str, valid: bool) -> None:
-    assert provenance._check_mod_11_2(mod11) == valid
-
-
-orcid_uris = [
-    # https://orcid.org/ (Expected form)
-    ("https://orcid.org/0000-0002-1694-233X", "https://orcid.org/0000-0002-1694-233X"),
-    # orcid.org
-    ("http://orcid.org/0000-0002-1694-233X", "https://orcid.org/0000-0002-1694-233X"),
-    # just the number
-    ("0000-0002-1825-0097", "https://orcid.org/0000-0002-1825-0097"),
-    # lower-case X is OK (and fixed)
-    ("https://orcid.org/0000-0002-1694-233x", "https://orcid.org/0000-0002-1694-233X"),
-    # upper-case ORCID.ORG is OK.. (and fixed)
-    ("https://ORCID.ORG/0000-0002-1694-233X", "https://orcid.org/0000-0002-1694-233X"),
-]
-
-
-@pytest.mark.parametrize("orcid,expected", orcid_uris)
-def test_valid_orcid(orcid: str, expected: str) -> None:
-    assert provenance._valid_orcid(orcid) == expected
-
-
-invalid_orcids = [
-    # missing digit fails (even if checksum is correct)
-    "0002-1694-2332",
-    # Wrong checkdigit fails
-    "https://orcid.org/0000-0002-1694-2332",
-    "0000-0002-1694-2332",
-    # Missing dashes fails (although that's OK for checksum)
-    "https://orcid.org/000000021694233X",
-    "000000021694233X",
-    # Wrong hostname fails
-    "https://example.org/0000-0002-1694-233X",
-    # Wrong protocol fails
-    "ftp://orcid.org/0000-0002-1694-233X",
-    # Trying to be clever fails (no URL parsing!)
-    "https://orcid.org:443/0000-0002-1694-233X",
-    "http://orcid.org:80/0000-0002-1694-233X",
-    # Empty string is not really valid
-    "",
-]
-
-
-@pytest.mark.parametrize("orcid", invalid_orcids)
-def test_invalid_orcid(orcid: str) -> None:
-    with pytest.raises(ValueError):
-        provenance._valid_orcid(orcid)
-
-
-def test_whoami() -> None:
-    username, fullname = provenance._whoami()
-    assert username and isinstance(username, str)
-    assert fullname and isinstance(fullname, str)
-
-
-def test_research_object() -> None:
-    # TODO: Test ResearchObject methods
-    pass
-
-
-def test_research_object_picklability(research_object: ResearchObject) -> None:
-    """Research object may need to be pickled (for Toil)."""
-    assert pickle.dumps(research_object) is not None
--- cwltool.orig/cwltool/job.py
+++ cwltool/cwltool/job.py
@@ -21,7 +21,6 @@
 from typing import IO, TYPE_CHECKING, Optional, TextIO, Union, cast
 
 import psutil
-from prov.model import PROV
 from schema_salad.sourceline import SourceLine
 from schema_salad.utils import json_dump, json_dumps
 
@@ -48,10 +47,6 @@
 )
 
 if TYPE_CHECKING:
-    from .cwlprov.provenance_profile import (
-        ProvenanceProfile,  # pylint: disable=unused-import
-    )
-
     CollectOutputsType = Union[
         Callable[[str, int], CWLObjectType], functools.partial[CWLObjectType]
     ]
@@ -145,8 +140,6 @@
         }
         self.stagedir: str | None = None
         self.inplace_update = False
-        self.prov_obj: ProvenanceProfile | None = None
-        self.parent_wf: ProvenanceProfile | None = None
         self.timelimit: int | None = None
         self.networkaccess: bool = False
         self.mpi_procs: int | None = None
@@ -265,22 +258,6 @@
             " > %s" % os.path.join(self.base_path_logs, self.stdout) if self.stdout else "",
             " 2> %s" % os.path.join(self.base_path_logs, self.stderr) if self.stderr else "",
         )
-        if self.joborder is not None and runtimeContext.research_obj is not None:
-            job_order = self.joborder
-            if (
-                runtimeContext.process_run_id is not None
-                and runtimeContext.prov_obj is not None
-                and isinstance(job_order, (list, dict))
-            ):
-                runtimeContext.prov_obj.used_artefacts(
-                    job_order, runtimeContext.process_run_id, str(self.name)
-                )
-            else:
-                _logger.warning(
-                    "research_obj set but one of process_run_id "
-                    "or prov_obj is missing from runtimeContext: "
-                    "{}".format(runtimeContext)
-                )
         outputs: CWLObjectType = {}
         try:
             stdin_path = None
@@ -401,18 +378,6 @@
                 "Exception while running job: %s.", str(err), exc_info=runtimeContext.debug
             )
             processStatus = "permanentFail"
-        if (
-            runtimeContext.research_obj is not None
-            and self.prov_obj is not None
-            and runtimeContext.process_run_id is not None
-        ):
-            # creating entities for the outputs produced by each step (in the provenance document)
-            self.prov_obj.record_process_end(
-                str(self.name),
-                runtimeContext.process_run_id,
-                outputs,
-                datetime.datetime.now(),
-            )
         if processStatus != "success":
             _logger.warning("[job %s] completed %s", self.name, processStatus)
         else:
@@ -763,7 +728,6 @@
                 os.makedirs(self.tmpdir)
 
         (docker_req, docker_is_req) = self.get_requirement("DockerRequirement")
-        self.prov_obj = runtimeContext.prov_obj
         img_id: str | None = None
         user_space_docker_cmd = runtimeContext.user_space_docker_cmd
         if docker_req is not None and user_space_docker_cmd:
@@ -800,27 +764,6 @@
                 if docker_req is not None and img_id is None and runtimeContext.use_container:
                     raise Exception("Docker image not available")
 
-                if (
-                    self.prov_obj is not None
-                    and img_id is not None
-                    and runtimeContext.process_run_id is not None
-                ):
-                    container_agent = self.prov_obj.document.agent(
-                        uuid.uuid4().urn,
-                        {
-                            "prov:type": PROV["SoftwareAgent"],
-                            "cwlprov:image": img_id,
-                            "prov:label": "Container execution of image %s" % img_id,
-                        },
-                    )
-                    # FIXME: img_id is not a sha256 id, it might just be "debian:8"
-                    # img_entity = document.entity("nih:sha-256;%s" % img_id,
-                    #                  {"prov:label": "Container image %s" % img_id} )
-                    # The image is the plan for this activity-agent association
-                    # document.wasAssociatedWith(process_run_ID, container_agent, img_entity)
-                    self.prov_obj.document.wasAssociatedWith(
-                        runtimeContext.process_run_id, container_agent
-                    )
             except Exception as err:
                 container = "Singularity" if runtimeContext.singularity else "Docker"
                 _logger.debug("%s error", container, exc_info=runtimeContext.debug)
--- cwltool.orig/cwltool/workflow.py
+++ cwltool/cwltool/workflow.py
@@ -15,8 +15,6 @@
 from . import command_line_tool, context, procgenerator
 from .checker import circular_dependency_checker, loop_checker, static_checker
 from .context import LoadingContext, RuntimeContext, getdefault
-from .cwlprov.provenance_profile import ProvenanceProfile
-from .cwlprov.writablebagfile import create_job
 from .errors import WorkflowException
 from .load_tool import load_tool
 from .loghandler import _logger
@@ -66,26 +64,6 @@
     ) -> None:
         """Initialize this Workflow."""
         super().__init__(toolpath_object, loadingContext)
-        self.provenance_object: ProvenanceProfile | None = None
-        if loadingContext.research_obj is not None:
-            run_uuid: UUID | None = None
-            is_main = not loadingContext.prov_obj  # Not yet set
-            if is_main:
-                run_uuid = loadingContext.research_obj.ro_uuid
-
-            self.provenance_object = loadingContext.research_obj.initialize_provenance(
-                full_name=loadingContext.cwl_full_name,
-                host_provenance=loadingContext.host_provenance,
-                user_provenance=loadingContext.user_provenance,
-                orcid=loadingContext.orcid,
-                run_uuid=run_uuid,
-                fsaccess=loadingContext.research_obj.fsaccess,
-            )  # inherit RO UUID for main wf run
-            # TODO: Is Workflow(..) only called when we are the main workflow?
-            self.parent_wf = self.provenance_object
-
-        # FIXME: Won't this overwrite prov_obj for nested workflows?
-        loadingContext.prov_obj = self.provenance_object
         loadingContext = loadingContext.copy()
         loadingContext.requirements = self.requirements
         loadingContext.hints = self.hints
@@ -95,7 +73,7 @@
         for index, step in enumerate(self.tool.get("steps", [])):
             try:
                 self.steps.append(
-                    self.make_workflow_step(step, index, loadingContext, loadingContext.prov_obj)
+                    self.make_workflow_step(step, index, loadingContext)
                 )
             except ValidationException as vexc:
                 if _logger.isEnabledFor(logging.DEBUG):
@@ -138,9 +116,8 @@
         toolpath_object: CommentedMap,
         pos: int,
         loadingContext: LoadingContext,
-        parentworkflowProv: ProvenanceProfile | None = None,
     ) -> "WorkflowStep":
-        return WorkflowStep(toolpath_object, pos, loadingContext, parentworkflowProv)
+        return WorkflowStep(toolpath_object, pos, loadingContext)
 
     def job(
         self,
@@ -150,12 +127,6 @@
     ) -> JobsGeneratorType:
         builder = self._init_job(job_order, runtimeContext)
 
-        if runtimeContext.research_obj is not None:
-            if runtimeContext.toplevel:
-                # Record primary-job.json
-                runtimeContext.research_obj.fsaccess = runtimeContext.make_fs_access("")
-                create_job(runtimeContext.research_obj, builder.job)
-
         job = WorkflowJob(self, runtimeContext)
         yield job
 
@@ -188,7 +159,6 @@
         toolpath_object: CommentedMap,
         pos: int,
         loadingContext: LoadingContext,
-        parentworkflowProv: ProvenanceProfile | None = None,
     ) -> None:
         """Initialize this WorkflowStep."""
         debug = loadingContext.debug
@@ -386,13 +356,6 @@
                     oparam["type"] = {"type": "array", "items": oparam["type"]}
             self.tool["inputs"] = inputparms
             self.tool["outputs"] = outputparms
-        self.prov_obj: ProvenanceProfile | None = None
-        if loadingContext.research_obj is not None:
-            self.prov_obj = parentworkflowProv
-            if self.embedded_tool.tool["class"] == "Workflow":
-                self.parent_wf = self.embedded_tool.parent_wf
-            else:
-                self.parent_wf = self.prov_obj
 
     def receive_output(
         self,
@@ -416,19 +379,6 @@
         runtimeContext: RuntimeContext,
     ) -> JobsGeneratorType:
         """Initialize sub-workflow as a step in the parent profile."""
-        if (
-            self.embedded_tool.tool["class"] == "Workflow"
-            and runtimeContext.research_obj
-            and self.prov_obj
-            and self.embedded_tool.provenance_object
-        ):
-            self.embedded_tool.parent_wf = self.prov_obj
-            process_name = self.tool["id"].split("#")[1]
-            self.prov_obj.start_process(
-                process_name,
-                datetime.datetime.now(),
-                self.embedded_tool.provenance_object.workflow_run_uri,
-            )
 
         step_input = {}
         for inp in self.tool["inputs"]:
--- cwltool.orig/cwltool/main.py
+++ cwltool/cwltool/main.py
@@ -40,14 +40,6 @@
 from . import CWL_CONTENT_TYPES, workflow
 from .argparser import arg_parser, generate_parser, get_default_args
 from .context import LoadingContext, RuntimeContext, getdefault
-from .cwlprov.ro import ResearchObject  # , WritableBagFile
-from .cwlprov.writablebagfile import (  # change this later
-    WritableBagFile,
-    close_ro,
-    create_job,
-    open_log_file_for_activity,
-    packed_workflow,
-)
 from .cwlrdf import printdot, printrdf
 from .errors import (
     ArgumentException,
@@ -677,37 +669,6 @@
         return with_msecs
 
 
-ProvOut = Union[io.TextIOWrapper, WritableBagFile]
-
-
-def setup_provenance(
-    args: argparse.Namespace,
-    runtimeContext: RuntimeContext,
-    argsl: list[str] | None = None,
-) -> tuple[ProvOut, "logging.StreamHandler[ProvOut]"]:
-    if not args.compute_checksum:
-        _logger.error("--provenance incompatible with --no-compute-checksum")
-        raise ArgumentException()
-    ro = ResearchObject(
-        getdefault(runtimeContext.make_fs_access, StdFsAccess)(""),
-        temp_prefix_ro=args.tmpdir_prefix,
-        orcid=args.orcid,
-        full_name=args.cwl_full_name,
-    )
-    runtimeContext.research_obj = ro
-    log_file_io = open_log_file_for_activity(ro, ro.engine_uuid)
-    prov_log_handler = logging.StreamHandler(log_file_io)
-
-    prov_log_handler.setFormatter(ProvLogFormatter())
-    _logger.addHandler(prov_log_handler)
-    _logger.debug("[provenance] Logging to %s", log_file_io)
-    if argsl is not None:
-        # Log cwltool command line options to provenance file
-        _logger.info("[cwltool] %s %s", sys.argv[0], " ".join(argsl))
-    _logger.debug("[cwltool] Arguments: %s", args)
-    return log_file_io, prov_log_handler
-
-
 def setup_loadingContext(
     loadingContext: LoadingContext | None,
     runtimeContext: RuntimeContext,
@@ -725,7 +686,6 @@
         enable_dev=args.enable_dev,
         doc_cache=args.doc_cache,
     )
-    loadingContext.research_obj = runtimeContext.research_obj
     loadingContext.disable_js_validation = args.disable_js_validation or (not args.do_validate)
     loadingContext.construct_tool_object = getdefault(
         loadingContext.construct_tool_object, workflow.default_make_tool
@@ -971,7 +931,6 @@
 
     _logger.removeHandler(defaultStreamHandler)
     workflowobj = None
-    prov_log_handler: logging.StreamHandler[ProvOut] | None = None
     global docker_exe
 
     user_agent = "cwltool"
@@ -1055,20 +1014,8 @@
 
         setup_schema(args, custom_schema_callback)
 
-        prov_log_stream: io.TextIOWrapper | WritableBagFile | None = None
-        if args.provenance:
-            try:
-                prov_log_stream, prov_log_handler = setup_provenance(args, runtimeContext, argsl)
-            except ArgumentException:
-                return 1
-
         loadingContext = setup_loadingContext(loadingContext, runtimeContext, args)
 
-        if loadingContext.research_obj:
-            # early forward parameters required for a single command line tool
-            runtimeContext.prov_host = loadingContext.host_provenance
-            runtimeContext.prov_user = loadingContext.user_provenance
-
         uri, tool_file_uri = resolve_tool_uri(
             args.workflow,
             resolver=loadingContext.resolver,
@@ -1112,10 +1059,6 @@
                 print(print_pack(loadingContext, uri), file=stdout)
                 return 0
 
-            if args.provenance and runtimeContext.research_obj:
-                # Can't really be combined with args.pack at same time
-                packed_workflow(runtimeContext.research_obj, print_pack(loadingContext, uri))
-
             if args.print_pre:
                 json_dump(
                     processobj,
@@ -1320,29 +1263,6 @@
                 return 0
 
             if out is not None:
-                if runtimeContext.research_obj is not None:
-                    create_job(runtimeContext.research_obj, out, True)
-
-                    def remove_at_id(doc: CWLObjectType) -> None:
-                        for key in list(doc.keys()):
-                            if key == "@id":
-                                del doc[key]
-                            else:
-                                value = doc[key]
-                                if isinstance(value, MutableMapping):
-                                    remove_at_id(value)
-                                elif isinstance(value, MutableSequence):
-                                    for entry in value:
-                                        if isinstance(entry, MutableMapping):
-                                            remove_at_id(entry)
-
-                    remove_at_id(out)
-                    visit_class(
-                        out,
-                        ("File",),
-                        functools.partial(add_sizes, runtimeContext.make_fs_access("")),
-                    )
-
                 def loc_to_path(obj: CWLObjectType) -> None:
                     for field in ("path", "nameext", "nameroot", "dirname"):
                         if field in obj:
@@ -1397,36 +1317,6 @@
             return 1
 
     finally:
-        if (
-            args
-            and runtimeContext
-            and runtimeContext.research_obj
-            and workflowobj
-            and loadingContext
-        ):
-            research_obj = runtimeContext.research_obj
-            if loadingContext.loader is not None:
-                research_obj.generate_snapshot(
-                    prov_deps(cast(CWLObjectType, processobj), loadingContext.loader, uri)
-                )
-            else:
-                _logger.warning(
-                    "Unable to generate provenance snapshot "
-                    " due to missing loadingContext.loader."
-                )
-            if prov_log_handler is not None:
-                # Stop logging so we won't half-log adding ourself to RO
-                _logger.debug("[provenance] Closing provenance log file %s", prov_log_handler)
-                _logger.removeHandler(prov_log_handler)
-                # Ensure last log lines are written out
-                prov_log_handler.flush()
-                # Underlying WritableBagFile will add the tagfile to the manifest
-                if prov_log_stream:
-                    prov_log_stream.close()
-                # Why not use prov_log_handler.stream ? That is not part of the
-                # public API for logging.StreamHandler
-                prov_log_handler.close()
-            close_ro(research_obj, args.provenance)
         _logger.removeHandler(err_handler)
         _logger.addHandler(defaultStreamHandler)
 
--- cwltool.orig/cwltool/builder.py
+++ cwltool/cwltool/builder.py
@@ -156,7 +156,6 @@
         self.cwlVersion = cwlVersion
 
         self.pathmapper: Optional["PathMapper"] = None
-        self.prov_obj: Optional["ProvenanceProfile"] = None
         self.find_default_container: Callable[[], str] | None = None
         self.container_engine = container_engine
 
--- cwltool.orig/cwltool/command_line_tool.py
+++ cwltool/cwltool/command_line_tool.py
@@ -77,11 +77,6 @@
     visit_class,
 )
 
-if TYPE_CHECKING:
-    from .cwlprov.provenance_profile import (
-        ProvenanceProfile,  # pylint: disable=unused-import
-    )
-
 
 class PathCheckingMode(Enum):
     """
@@ -168,7 +163,6 @@
         self.outdir = outdir
         self.tmpdir = tmpdir
         self.script = script
-        self.prov_obj: Optional["ProvenanceProfile"] = None
 
     def run(
         self,
@@ -219,7 +213,6 @@
             self.requirements,
             self.hints,
         )
-        job.prov_obj = runtimeContext.prov_obj
         yield job
 
 
@@ -327,7 +320,6 @@
         self.output_callback = output_callback
         self.cachebuilder = cachebuilder
         self.outdir = jobcache
-        self.prov_obj: ProvenanceProfile | None = None
 
     def run(
         self,
@@ -403,7 +395,6 @@
     def __init__(self, toolpath_object: CommentedMap, loadingContext: LoadingContext) -> None:
         """Initialize this CommandLineTool."""
         super().__init__(toolpath_object, loadingContext)
-        self.prov_obj = loadingContext.prov_obj
         self.path_check_mode: PathCheckingMode = (
             PathCheckingMode.RELAXED
             if loadingContext.relax_path_checks
@@ -973,7 +964,6 @@
             self.hints,
             jobname,
         )
-        j.prov_obj = self.prov_obj
 
         j.successCodes = self.tool.get("successCodes", [])
         j.temporaryFailCodes = self.tool.get("temporaryFailCodes", [])
--- cwltool.orig/cwltool/context.py
+++ cwltool/cwltool/context.py
@@ -23,8 +23,6 @@
     from cwl_utils.parser.cwl_v1_2 import LoadingOptions
 
     from .builder import Builder
-    from .cwlprov.provenance_profile import ProvenanceProfile
-    from .cwlprov.ro import ResearchObject
     from .mutation import MutationManager
     from .process import Process
     from .secrets import SecretStore
@@ -93,12 +91,10 @@
         self.resolver: ResolverType | None = None
         self.fetcher_constructor: FetcherCallableType | None = None
         self.construct_tool_object = default_make_tool
-        self.research_obj: ResearchObject | None = None
         self.orcid: str = ""
         self.cwl_full_name: str = ""
         self.host_provenance: bool = False
         self.user_provenance: bool = False
-        self.prov_obj: Optional["ProvenanceProfile"] = None
         self.do_update: bool | None = None
         self.jobdefaults: CommentedMap | None = None
         self.doc_cache: bool = True
@@ -181,13 +177,11 @@
         self.cidfile_prefix: str | None = None
 
         self.workflow_eval_lock: Union[threading.Condition, None] = None
-        self.research_obj: ResearchObject | None = None
         self.orcid: str = ""
         self.cwl_full_name: str = ""
         self.process_run_id: str | None = None
         self.prov_host: bool = False
         self.prov_user: bool = False
-        self.prov_obj: ProvenanceProfile | None = None
         self.mpi_config: MpiConfig = MpiConfig()
         self.default_stdout: IO[bytes] | TextIO | None = None
         self.default_stderr: IO[bytes] | TextIO | None = None
--- cwltool.orig/cwltool/executors.py
+++ cwltool/cwltool/executors.py
@@ -160,21 +160,6 @@
             cleanIntermediate(output_dirs)
 
         if self.final_output and self.final_status:
-            if (
-                runtime_context.research_obj is not None
-                and isinstance(process, (JobBase, Process, WorkflowJobStep, WorkflowJob))
-                and process.parent_wf
-            ):
-                process_run_id: str | None = None
-                name = "primary"
-                process.parent_wf.generate_output_prov(self.final_output[0], process_run_id, name)
-                process.parent_wf.document.wasEndedBy(
-                    process.parent_wf.workflow_run_uri,
-                    None,
-                    process.parent_wf.engine_uuid,
-                    datetime.datetime.now(),
-                )
-                process.parent_wf.finalize_prov_profile(name=None)
             return (self.final_output[0], self.final_status[0])
         return (None, "permanentFail")
 
@@ -192,22 +177,6 @@
     ) -> None:
         process_run_id: str | None = None
 
-        # define provenance profile for single commandline tool
-        if not isinstance(process, Workflow) and runtime_context.research_obj is not None:
-            process.provenance_object = runtime_context.research_obj.initialize_provenance(
-                full_name=runtime_context.cwl_full_name,
-                # following are only set from main when directly command line tool
-                # when nested in a workflow, they should be disabled since they would
-                # already have been provided/initialized by the parent workflow prov-obj
-                host_provenance=runtime_context.prov_host,
-                user_provenance=runtime_context.prov_user,
-                orcid=runtime_context.orcid,
-                # single tool execution, so RO UUID = wf UUID = tool UUID
-                run_uuid=runtime_context.research_obj.ro_uuid,
-                fsaccess=runtime_context.make_fs_access(""),
-            )
-            process.parent_wf = process.provenance_object
-
         jobiter = process.job(job_order_object, self.output_callback, runtime_context)
 
         try:
@@ -217,23 +186,6 @@
                         job.builder = runtime_context.builder
                     if job.outdir is not None:
                         self.output_dirs.add(job.outdir)
-                    if runtime_context.research_obj is not None:
-                        if not isinstance(process, Workflow):
-                            prov_obj = process.provenance_object
-                        else:
-                            prov_obj = job.prov_obj
-                        if prov_obj:
-                            runtime_context.prov_obj = prov_obj
-                            prov_obj.fsaccess = runtime_context.make_fs_access("")
-                            prov_obj.evaluate(
-                                process,
-                                job,
-                                job_order_object,
-                                runtime_context.research_obj,
-                            )
-                            process_run_id = prov_obj.record_process_start(process, job)
-                            runtime_context = runtime_context.copy()
-                        runtime_context.process_run_id = process_run_id
                     if runtime_context.validate_only is True:
                         if isinstance(job, WorkflowJob):
                             name = job.tool.lc.filename
--- cwltool.orig/cwltool/workflow_job.py
+++ cwltool/cwltool/workflow_job.py
@@ -33,7 +33,6 @@
 )
 
 if TYPE_CHECKING:
-    from .cwlprov.provenance_profile import ProvenanceProfile
     from .workflow import Workflow, WorkflowStep
 
 
@@ -49,8 +48,6 @@
         self.iterable: JobsGeneratorType | None = None
         self.completed = False
         self.name = uniquename("step %s" % shortname(self.id))
-        self.prov_obj = step.prov_obj
-        self.parent_wf = step.parent_wf
 
     def job(
         self,
@@ -474,12 +471,7 @@
     def __init__(self, workflow: "Workflow", runtimeContext: RuntimeContext) -> None:
         """Initialize this WorkflowJob."""
         self.workflow = workflow
-        self.prov_obj: ProvenanceProfile | None = None
-        self.parent_wf: ProvenanceProfile | None = None
         self.tool = workflow.tool
-        if runtimeContext.research_obj is not None:
-            self.prov_obj = workflow.provenance_object
-            self.parent_wf = workflow.parent_wf
         self.steps = [WorkflowJobStep(s) for s in workflow.steps]
         self.state: dict[str, WorkflowStateItem | None] = {}
         self.processStatus = ""
@@ -520,22 +512,6 @@
         except WorkflowException as err:
             _logger.error("[%s] Cannot collect workflow output: %s", self.name, str(err))
             self.processStatus = "permanentFail"
-        if (
-            self.prov_obj
-            and self.parent_wf
-            and self.prov_obj.workflow_run_uri != self.parent_wf.workflow_run_uri
-        ):
-            process_run_id: str | None = None
-            self.prov_obj.generate_output_prov(wo or {}, process_run_id, self.name)
-            self.prov_obj.document.wasEndedBy(
-                self.prov_obj.workflow_run_uri,
-                None,
-                self.prov_obj.engine_uuid,
-                datetime.datetime.now(),
-            )
-            prov_ids = self.prov_obj.finalize_prov_profile(self.name)
-            # Tell parent to associate our provenance files with our wf run
-            self.parent_wf.activity_has_provenance(self.prov_obj.workflow_run_uri, prov_ids)
 
         _logger.info("[%s] completed %s", self.name, self.processStatus)
         if _logger.isEnabledFor(logging.DEBUG):
--- cwltool.orig/cwltool/process.py
+++ cwltool/cwltool/process.py
@@ -536,8 +536,6 @@
         """Build a Process object from the provided dictionary."""
         super().__init__()
         self.metadata: CWLObjectType = getdefault(loadingContext.metadata, {})
-        self.provenance_object: Optional["ProvenanceProfile"] = None
-        self.parent_wf: Optional["ProvenanceProfile"] = None
         global SCHEMA_FILE, SCHEMA_DIR, SCHEMA_ANY  # pylint: disable=global-statement
         if SCHEMA_FILE is None or SCHEMA_ANY is None or SCHEMA_DIR is None:
             get_schema("v1.0")
