cwl-baseline-plugin 0.1.0__tar.gz

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.
Files changed (28) hide show
  1. cwl_baseline_plugin-0.1.0/.gitignore +40 -0
  2. cwl_baseline_plugin-0.1.0/CHANGELOG.md +52 -0
  3. cwl_baseline_plugin-0.1.0/LICENSE +201 -0
  4. cwl_baseline_plugin-0.1.0/NOTICE +4 -0
  5. cwl_baseline_plugin-0.1.0/PKG-INFO +340 -0
  6. cwl_baseline_plugin-0.1.0/README.md +310 -0
  7. cwl_baseline_plugin-0.1.0/docs/explanation/architecture.md +55 -0
  8. cwl_baseline_plugin-0.1.0/docs/explanation/compatibility.md +174 -0
  9. cwl_baseline_plugin-0.1.0/docs/explanation/index.md +22 -0
  10. cwl_baseline_plugin-0.1.0/docs/how-to/index.md +20 -0
  11. cwl_baseline_plugin-0.1.0/docs/how-to/install.md +48 -0
  12. cwl_baseline_plugin-0.1.0/docs/how-to/use-cli.md +60 -0
  13. cwl_baseline_plugin-0.1.0/docs/index.md +37 -0
  14. cwl_baseline_plugin-0.1.0/docs/reference/api.md +95 -0
  15. cwl_baseline_plugin-0.1.0/docs/reference/index.md +20 -0
  16. cwl_baseline_plugin-0.1.0/docs/tutorials/first-steps.md +50 -0
  17. cwl_baseline_plugin-0.1.0/docs/tutorials/index.md +20 -0
  18. cwl_baseline_plugin-0.1.0/pyproject.toml +169 -0
  19. cwl_baseline_plugin-0.1.0/src/cwl_baseline/__about__.py +17 -0
  20. cwl_baseline_plugin-0.1.0/src/cwl_baseline/__init__.py +28 -0
  21. cwl_baseline_plugin-0.1.0/src/cwl_baseline/compare.py +751 -0
  22. cwl_baseline_plugin-0.1.0/src/cwl_baseline/models.py +71 -0
  23. cwl_baseline_plugin-0.1.0/src/cwl_baseline/normalize.py +135 -0
  24. cwl_baseline_plugin-0.1.0/src/cwl_baseline/plugin.py +86 -0
  25. cwl_baseline_plugin-0.1.0/src/cwl_baseline/types.py +135 -0
  26. cwl_baseline_plugin-0.1.0/tests/conftest.py +61 -0
  27. cwl_baseline_plugin-0.1.0/tests/test_baseline.py +517 -0
  28. cwl_baseline_plugin-0.1.0/tests/test_plugin.py +135 -0
@@ -0,0 +1,40 @@
1
+ # Copyright {{ copyright_year }} {{ author_name }}
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # Python
16
+ __pycache__/
17
+ *.py[cod]
18
+ *.egg-info/
19
+ .dist/
20
+ build/
21
+ dist/
22
+ .coverage
23
+ coverage.xml
24
+ .pytest_cache/
25
+ .mypy_cache/
26
+ .ruff_cache/
27
+
28
+ # Environments
29
+ .venv/
30
+
31
+ # MkDocs
32
+ site/
33
+
34
+ # Editors
35
+ .idea/
36
+ .vscode/
37
+ .DS_Store
38
+
39
+ .task
40
+ uv.lock
@@ -0,0 +1,52 @@
1
+ <!--
2
+ Copyright 2026 Transpiler-Mate
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ -->
16
+
17
+ # Changelog
18
+
19
+ All notable changes to this project will be documented in this file.
20
+
21
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
22
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
23
+
24
+ ## [Unreleased]
25
+
26
+ ### Added
27
+
28
+ ### Changed
29
+
30
+ ### Deprecated
31
+
32
+ ### Removed
33
+
34
+ ### Fixed
35
+
36
+ ### Security
37
+
38
+ ### Added
39
+
40
+ - Initial Hatch-based Python project scaffold.
41
+ - Diátaxis documentation structure.
42
+ - MkDocs configuration.
43
+ - Taskfile integration with Terradue remote task utilities.
44
+
45
+ ## [0.1.0] - 2026-01-01
46
+
47
+ ### Added
48
+
49
+ - Initial project release.
50
+
51
+ [Unreleased]: https://github.com/Transpiler-Mate/cwl-baseline-plugin/compare/0.1.0...HEAD
52
+ [0.1.0]: https://github.com/Transpiler-Mate/cwl-baseline-plugin/releases/tag/0.1.0
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Transpiler-Mate
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,4 @@
1
+ CWL Baseline Transpiler Mate Plugin
2
+ Copyright 2026 Transpiler-Mate
3
+
4
+ This product includes software developed by Transpiler-Mate.
@@ -0,0 +1,340 @@
1
+ Metadata-Version: 2.5
2
+ Name: cwl-baseline-plugin
3
+ Version: 0.1.0
4
+ Summary: CWL Baseline Transpiler Mate Plugin Transpiler-Mate Plugin.
5
+ Project-URL: Homepage, https://github.com/Transpiler-Mate/cwl-baseline-plugin
6
+ Project-URL: Documentation, https://Transpiler-Mate.github.io/cwl-baseline-plugin/
7
+ Project-URL: Repository, https://github.com/Transpiler-Mate/cwl-baseline-plugin
8
+ Project-URL: Issues, https://github.com/Transpiler-Mate/cwl-baseline-plugin/issues
9
+ Project-URL: Changelog, https://github.com/Transpiler-Mate/cwl-baseline-plugin/blob/main/CHANGELOG.md
10
+ Author-email: Transpiler-Mate <info@terradue.com>
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE
13
+ License-File: NOTICE
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: Implementation :: CPython
24
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: loguru==0.7.3
27
+ Requires-Dist: semver<4,>=3.0.4
28
+ Requires-Dist: transpiler-mate-api==1.0.0
29
+ Description-Content-Type: text/markdown
30
+
31
+ <!--
32
+ Copyright 2026 Transpiler-Mate
33
+
34
+ Licensed under the Apache License, Version 2.0 (the "License");
35
+ you may not use this file except in compliance with the License.
36
+ You may obtain a copy of the License at
37
+
38
+ http://www.apache.org/licenses/LICENSE-2.0
39
+
40
+ Unless required by applicable law or agreed to in writing, software
41
+ distributed under the License is distributed on an "AS IS" BASIS,
42
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
43
+ See the License for the specific language governing permissions and
44
+ limitations under the License.
45
+ -->
46
+
47
+ # CWL Baseline Transpiler Mate Plugin
48
+
49
+ [![PyPI - Version](https://img.shields.io/pypi/v/cwl-baseline-plugin.svg)](https://pypi.org/project/cwl-baseline-plugin)
50
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cwl-baseline-plugin.svg)](https://pypi.org/project/cwl-baseline-plugin)
51
+
52
+ A standalone plugin implementing the public `transpiler-mate-api` contract.
53
+ It compares every Process in two resolved CWL documents and produces an
54
+ explainable JSON baseline report with a minimum SemVer increment.
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ python -m pip install cwl-baseline-plugin
60
+ ```
61
+
62
+ For development, install your checkout of the API first if it has not yet been
63
+ published, then install this project:
64
+
65
+ ```bash
66
+ python -m pip install -e ../transpiler-mate-api
67
+ python -m pip install -e .
68
+ hatch run test:test
69
+ ```
70
+
71
+ Requires Python >=3.10, `transpiler-mate-api==1.0.0`, `semver>=3.0.4,<4`, and `loguru==0.7.3`.
72
+ The API supplies cwl-utils and Pydantic. The effective Python requirement also
73
+ depends on the selected versions of those dependencies.
74
+
75
+ ## Integrate with a transpiler-mate runtime
76
+
77
+ Exported plugin object: `cwl_baseline.baseline_plugin`.
78
+ Plugin name: `baseline`. Options model: `BaselineOptions`.
79
+
80
+ The package registers `baseline = "cwl_baseline.plugin:baseline_plugin"` in the
81
+ `transpiler_mate.plugins` entry-point group. Install it into the same environment
82
+ as the separately installed runtime. It provides no standalone `cwl_baseline`
83
+ executable. The runtime resolves the current CWL; the plugin resolves only the
84
+ previous release.
85
+
86
+ ```bash
87
+ transpiler-mate baseline examples/current.cwl \
88
+ --previous examples/previous.cwl --output baseline.json --check
89
+ ```
90
+
91
+ The host CLI resolves its input CWL into `context` and invokes:
92
+
93
+ ```python
94
+ from pathlib import Path
95
+ from transpiler_mate.api import TranspilerContext
96
+ from cwl_baseline import BaselineOptions, baseline_plugin
97
+
98
+
99
+ def execute_baseline(context: TranspilerContext) -> None:
100
+ baseline_plugin.execute(
101
+ context,
102
+ BaselineOptions(
103
+ previous="path-or-URI-to-previous-release.cwl",
104
+ output=Path("baseline.json"),
105
+ check=True,
106
+ ),
107
+ )
108
+ ```
109
+
110
+ Equivalent options payload for a runtime accepting JSON:
111
+
112
+ ```json
113
+ {
114
+ "previous": "path-or-URI-to-previous-release.cwl",
115
+ "output": "baseline.json",
116
+ "check": true
117
+ }
118
+ ```
119
+
120
+ | Option | Default | Meaning |
121
+ | --- | --- | --- |
122
+ | `previous` | required | Passed unchanged to `context.resolver.resolve()` |
123
+ | `output` | `baseline.json` | JSON destination; its parent directory must exist |
124
+ | `check` | `false` | Fail for unresolved review or insufficient declared version |
125
+ | `review_bump` | `null` | Explicitly classify review findings as `patch`, `minor`, or `major` |
126
+
127
+ `previous_context = context.resolver.resolve(options.previous)` supplies the
128
+ baseline. `context.document` supplies **all** current Processes, irrespective
129
+ of `context.process_id`. Both versions are read from
130
+ `context.metadata.software_version` on their respective contexts.
131
+
132
+ The highest applicable bump is applied **once to the previous release** using
133
+ `semver.Version.bump_major()`, `.bump_minor()`, or `.bump_patch()`. The third component is called *patch*.
134
+ Neither CWL document nor either metadata object is mutated.
135
+
136
+ ## Compatibility policy
137
+
138
+ The current implementation uses fixed static rules plus the global `review_bump`
139
+ classification. It does not yet support configurable per-rule policies. These
140
+ are plugin baselining assumptions, not versioning rules mandated by CWL.
141
+
142
+ Replacement requires AcceptedInputs(old) ⊆ AcceptedInputs(new) and
143
+ PossibleOutputs(new) ⊆ PossibleOutputs(old). Inputs are contravariant; outputs
144
+ are covariant. Thus `string` → `string | null` is minor for an input but major
145
+ for an output. Identical signatures do not prove compatible behavior.
146
+
147
+ See the [full compatibility policy](docs/explanation/compatibility.md) for the
148
+ implemented rules and their limitations.
149
+
150
+ Every Process exposed in `context.document` is treated as public. A Process
151
+ addition is minor; a removal or rename is major. This policy is intentionally
152
+ conservative for documents containing helper tools in their public mapping.
153
+
154
+ | Change | Minimum bump |
155
+ | --- | --- |
156
+ | Add Process | minor |
157
+ | Remove/rename Process | major |
158
+ | Add input that cannot be omitted | major |
159
+ | Add nullable/defaulted input | minor |
160
+ | Remove/rename input or output | major |
161
+ | Add output | minor; assumes consumers tolerate extra output keys |
162
+ | Widen accepted input values | minor |
163
+ | Narrow accepted input values | major |
164
+ | Widen possible output values | major |
165
+ | Narrow possible output values | patch, with behavioral review |
166
+ | Remove input omission capability | major |
167
+ | Change default | review; independently detect loss of omission capability |
168
+ | Add mandatory execution requirement | major; schema definitions handled separately |
169
+ | Change language version, existing execution requirement, or advisory hint | review |
170
+ | Change command, binding, expression, wiring, container, or step | review |
171
+ | Change `doc`, `label`, schema.org name/description | none |
172
+ | Change unknown extensions | review |
173
+
174
+ Type comparison is directional: old inputs must be assignable to new inputs;
175
+ new outputs must be assignable to old outputs. It covers primitives, CWL
176
+ numeric promotions, nullability, unions, enums, arrays, records, and named
177
+ schemas. Numeric promotion follows CWL type assignability; it does not claim
178
+ lossless numeric conversion. `Any` excludes null unless explicitly unioned
179
+ with null. Removed record fields are conservatively major for either direction.
180
+
181
+ Input omission is tracked separately: a serialized default or a nullable type
182
+ allows omission. Removing a default is major only when omission becomes invalid,
183
+ with a separate review finding for the default change. Adding or changing an
184
+ existing parameter's default also requires review.
185
+
186
+ Hints do not trigger the new mandatory requirement rule. Existing requirement
187
+ changes, including resource/network settings and container images, generally
188
+ receive residual behavioral review. Adding a new mandatory container requirement
189
+ is major. `SchemaDefRequirement` definitions are compared through parameter types;
190
+ unused schema changes require review.
191
+
192
+ File constraints include `format` and `secondaryFiles`. Literal format subset
193
+ relations can prove compatibility, but relationships between different format
194
+ IRIs may require ontology knowledge and are left for review. Secondary-file
195
+ expressions are also left for review. Existing optional secondary-file outputs
196
+ are not treated as required guarantees. Requiring a new secondary input file or
197
+ weakening a required secondary output guarantee is major; other literal changes
198
+ are minor. Compatible output-format narrowing has a patch floor without an
199
+ independent review flag in the current implementation.
200
+
201
+ Workflow steps are internal implementation details. They are matched by ID;
202
+ adding/removing one requires behavioral review rather than automatically
203
+ changing the public version. All residual changed DOM fields are reported,
204
+ including embedded `run` objects and unknown extension fields. Lists with
205
+ execution-significant order (arguments, source lists, etc.) retain their order.
206
+
207
+ ## Interpreting the report
208
+
209
+ ```json
210
+ {
211
+ "schema_version": "1.0",
212
+ "previous_version": "1.2.3",
213
+ "current_version": "1.2.3",
214
+ "minimum_bump": "major",
215
+ "minimum_version": "2.0.0",
216
+ "suggested_version": "2.0.0",
217
+ "review_required": false,
218
+ "review_bump": null,
219
+ "declared_version_sufficient": false,
220
+ "findings": []
221
+ }
222
+ ```
223
+
224
+ The abbreviated example omits findings. Real findings contain a stable rule
225
+ identifier, JSON-Pointer-style comparison path, category, minimum bump,
226
+ before/after values, presence flags, explanation, and review flag. Paths refer
227
+ to the normalized comparison model, not source-file line numbers.
228
+
229
+ - `minimum_bump` and `minimum_version` express the statically established floor.
230
+ - `suggested_version` is `null` while review remains unresolved. Otherwise it
231
+ is the minimum proposed release, not an instruction to downgrade a higher
232
+ already-declared version.
233
+ - A report without changes retains the previous release version.
234
+ - `declared_version_sufficient` is false while review is unresolved, even if the
235
+ current version is numerically high enough.
236
+ - The full report is written before `check=True` raises `PluginFailureError`.
237
+ - Missing/invalid SemVer metadata and prerelease baselines are domain errors.
238
+ Current development prereleases are accepted as input, but `1.3.0-dev.1`
239
+ does not satisfy a required final `1.3.0` release. Build metadata is handled
240
+ by the semver library.
241
+
242
+ After reviewing behavioral changes, classify them explicitly:
243
+
244
+ ```python
245
+ options = BaselineOptions(
246
+ previous="release.cwl",
247
+ output="baseline.json",
248
+ review_bump="patch", # All review findings have been assessed as compatible fixes.
249
+ check=True,
250
+ )
251
+ baseline_plugin.execute(context, options)
252
+ ```
253
+
254
+ `review_bump` applies to **all** review findings in this invocation. It cannot
255
+ reduce a proven major/minor requirement. Original per-finding review flags are
256
+ retained for auditing, while the report-level flag indicates unresolved review.
257
+ A global classification is not a per-rule waiver mechanism.
258
+
259
+ For library use without writing files:
260
+
261
+ ```python
262
+ from cwl_baseline import baseline
263
+
264
+ previous = context.resolver.resolve("release.cwl")
265
+ report = baseline(previous, context)
266
+ print(report.model_dump_json(indent=2))
267
+ ```
268
+
269
+ ## Normalization and boundaries
270
+
271
+ The plugin serializes the existing cwl-utils DOMs using
272
+ `save(relative_uris=False)`. It strips only the owning document's location from
273
+ CWL identity/reference fields, retaining scopes and external URIs. It does not
274
+ rewrite literal defaults, command arguments, expressions, or extension values.
275
+ Unambiguous short named-type references are recognized within a Process;
276
+ ambiguous/unresolved references produce review when their compatibility cannot
277
+ be established. Reachable named schemas are compared through their parameters;
278
+ changes to otherwise unused declarations are reported for review.
279
+
280
+ The runtime owns CWL parsing, import resolution, graph validation, and metadata
281
+ extraction. This plugin does not execute CWL, evaluate JavaScript, inspect image
282
+ contents, fetch format ontologies, or recursively fetch additional `run` URLs.
283
+ For reproducible baselines, the resolver must provide pinned dependency snapshots
284
+ in `document`. Changes behind an unchanged external reference that is absent
285
+ from the supplied DOMs cannot be detected. Inherited or externally defined
286
+ schemas not present in a Process's available declarations may require review.
287
+
288
+ Generated serializers may discard source spelling, comments, and explicit null
289
+ defaults. The comparison concerns the effective supplied DOM representation;
290
+ it cannot recover syntax that the parser discarded. Anonymous/generated **public Process** IDs
291
+ should be replaced with stable public IDs before baselining. Generated IDs of
292
+ anonymous inline tools are ignored; their enclosing step/run path identifies
293
+ them.
294
+
295
+ Static type compatibility does not prove scientific or behavioral equivalence.
296
+ A reviewed major release can still be necessary when output meanings or units
297
+ change without changing CWL types.
298
+
299
+ ## Tests and examples
300
+
301
+ `tests/` exercises parsed CWL DOMs, plugin resolution and error semantics,
302
+ variance, schema references, record/array changes, file constraints, source
303
+ relocation, ordered arguments, steps, and version aggregation. Test fixtures
304
+ use synthetic source URIs and disable link-existence checking only in their
305
+ fixture loader; production loading remains entirely with the host resolver.
306
+
307
+ `examples/previous.cwl`, `examples/current.cwl`, and
308
+ `examples/baseline.json` illustrate adding an optional input. Run `hatch run test:test` to execute the configured Python-version test matrix.
309
+
310
+ Upstream API: https://github.com/transpiler-mate/transpiler-mate-api
311
+ SemVer library: https://pypi.org/project/semver/
312
+
313
+ ## Documentation
314
+
315
+ Project documentation is published at: https://Transpiler-Mate.github.io/cwl-baseline-plugin/
316
+
317
+ ## Contribute
318
+
319
+ Submit a [Github issue](https://github.com/Transpiler-Mate/cwl-baseline-plugin/issues) if you have comments or suggestions.
320
+
321
+ ### Local quality checks
322
+
323
+ Install [Hatch](https://hatch.pypa.io/) and [Taskfiles](https://taskfile.dev/docs/guide) then install the Git hook:
324
+
325
+ ```console
326
+ task quality:pre-commit:install
327
+ ```
328
+
329
+ Every commit runs Ruff (including the configured McCabe complexity limit),
330
+ Ruff formatting, mypy, Bandit, and the pytest suite.
331
+
332
+ Run the complete hook explicitly with:
333
+
334
+ ```console
335
+ task quality:pre-commit:run
336
+ ```
337
+
338
+ ## License
339
+
340
+ [![Apache License, Version 2.0](https://img.shields.io/badge/license-Apache%20License%202.0-blue)](https://www.apache.org/licenses/LICENSE-2.0)