Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
workflow_publication_bundle.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 """Validation: workflow publication bundle.
3 
4 Builds the top-level workflow manifest by assembling the emitted workflow
5 evidence artifacts into one reproducible, machine-checkable package. The bundle
6 preserves canonical workflow identity and contract-version fields across the
7 packaged evidence layers.
8 
9 Run with:
10  python benchmarks/density_matrix/workflow_evidence/workflow_publication_bundle.py
11 """
12 
13 from __future__ import annotations
14 
15 import argparse
16 import json
17 import sys
18 from pathlib import Path
19 
20 REPO_ROOT = Path(__file__).resolve().parents[3]
21 if str(REPO_ROOT) not in sys.path:
22  sys.path.insert(0, str(REPO_ROOT))
23 
24 from benchmarks.density_matrix.workflow_evidence.workflow_contract_validation import (
25  ARTIFACT_FILENAME as WORKFLOW_CONTRACT_ARTIFACT_FILENAME,
26  CONTRACT_VERSION,
27  DEFAULT_OUTPUT_DIR as WORKFLOW_EVIDENCE_OUTPUT_DIR,
28  REFERENCE_BACKEND,
29  WORKFLOW_ID,
30  build_software_metadata,
31  get_git_revision,
32  run_validation as run_workflow_contract_validation,
33  validate_artifact_bundle as validate_workflow_contract_artifact,
34 )
35 from benchmarks.density_matrix.workflow_evidence.end_to_end_trace_validation import (
36  ARTIFACT_FILENAME as END_TO_END_TRACE_ARTIFACT_FILENAME,
37  run_validation as run_end_to_end_trace_validation,
38  validate_artifact_bundle as validate_end_to_end_trace_artifact,
39 )
40 from benchmarks.density_matrix.workflow_evidence.matrix_baseline_validation import (
41  ARTIFACT_FILENAME as MATRIX_BASELINE_ARTIFACT_FILENAME,
42  run_validation as run_matrix_baseline_validation,
43  validate_artifact_bundle as validate_matrix_baseline_artifact,
44 )
45 from benchmarks.density_matrix.workflow_evidence.unsupported_workflow_validation import (
46  ARTIFACT_FILENAME as UNSUPPORTED_WORKFLOW_ARTIFACT_FILENAME,
47  run_validation as run_unsupported_workflow_validation,
48  validate_artifact_bundle as validate_unsupported_workflow_artifact,
49 )
50 from benchmarks.density_matrix.workflow_evidence.workflow_interpretation_validation import (
51  ARTIFACT_FILENAME as WORKFLOW_INTERPRETATION_ARTIFACT_FILENAME,
52  run_validation as run_workflow_interpretation_validation,
53  validate_artifact_bundle as validate_workflow_interpretation_artifact,
54 )
55 
56 SUITE_NAME = "workflow_publication_evidence"
57 ARTIFACT_FILENAME = "workflow_publication_bundle.json"
58 DEFAULT_OUTPUT_DIR = WORKFLOW_EVIDENCE_OUTPUT_DIR
59 WORKFLOW_CONTRACT_PATH = DEFAULT_OUTPUT_DIR / WORKFLOW_CONTRACT_ARTIFACT_FILENAME
60 END_TO_END_TRACE_PATH = DEFAULT_OUTPUT_DIR / END_TO_END_TRACE_ARTIFACT_FILENAME
61 MATRIX_BASELINE_PATH = DEFAULT_OUTPUT_DIR / MATRIX_BASELINE_ARTIFACT_FILENAME
62 UNSUPPORTED_WORKFLOW_PATH = DEFAULT_OUTPUT_DIR / UNSUPPORTED_WORKFLOW_ARTIFACT_FILENAME
63 WORKFLOW_INTERPRETATION_PATH = (
64  DEFAULT_OUTPUT_DIR / WORKFLOW_INTERPRETATION_ARTIFACT_FILENAME
65 )
66 BUNDLE_FIELDS = (
67  "suite_name",
68  "status",
69  "workflow_id",
70  "contract_version",
71  "backend",
72  "reference_backend",
73  "software",
74  "provenance",
75  "summary",
76  "artifacts",
77 )
78 REQUIRED_SEMANTIC_FLAGS = {
79  "workflow_contract_bundle": ("contract_sections_complete",),
80  "end_to_end_trace_bundle": (
81  "end_to_end_gate_completed",
82  "end_to_end_qubits_match_contract",
83  "trace_case_name_matches_contract",
84  "workflow_thresholds_match_contract",
85  ),
86  "matrix_baseline_bundle": (
87  "matrix_gate_completed",
88  "workflow_inventory_matches_contract",
89  "workflow_thresholds_match_contract",
90  "documented_10q_anchor_present",
91  ),
92  "unsupported_workflow_bundle": (
93  "unsupported_gate_completed",
94  "backend_incompatible_case_present",
95  ),
96  "workflow_interpretation_bundle": (
97  "mandatory_artifacts_complete",
98  "unsupported_evidence_negative_only",
99  "unsupported_case_field_alignment",
100  "main_workflow_claim_completed",
101  ),
102 }
103 
104 
105 def _load_json(path: Path):
106  return json.loads(path.read_text(encoding="utf-8"))
107 
108 
109 def _load_workflow_contract(path: Path = WORKFLOW_CONTRACT_PATH):
110  if path.exists():
111  artifact = _load_json(path)
112  validate_workflow_contract_artifact(artifact)
113  return artifact
114  _, artifact = run_workflow_contract_validation(verbose=False)
115  return artifact
116 
117 
118 def _load_end_to_end_trace(path: Path = END_TO_END_TRACE_PATH):
119  if path.exists():
120  artifact = _load_json(path)
121  validate_end_to_end_trace_artifact(artifact)
122  return artifact
123  _, _, _, artifact = run_end_to_end_trace_validation(verbose=False)
124  return artifact
125 
126 
127 def _load_matrix_baseline(path: Path = MATRIX_BASELINE_PATH):
128  if path.exists():
129  artifact = _load_json(path)
130  validate_matrix_baseline_artifact(artifact)
131  return artifact
132  _, _, _, artifact = run_matrix_baseline_validation(verbose=False)
133  return artifact
134 
135 
136 def _load_unsupported_workflow(path: Path = UNSUPPORTED_WORKFLOW_PATH):
137  if path.exists():
138  artifact = _load_json(path)
139  validate_unsupported_workflow_artifact(artifact)
140  return artifact
141  *_, artifact = run_unsupported_workflow_validation(verbose=False)
142  return artifact
143 
144 
145 def _load_workflow_interpretation(path: Path = WORKFLOW_INTERPRETATION_PATH):
146  if path.exists():
147  artifact = _load_json(path)
148  validate_workflow_interpretation_artifact(artifact)
149  return artifact
150  *_, artifact = run_workflow_interpretation_validation(verbose=False)
151  return artifact
152 
153 
154 def _write_artifact(path: Path, artifact) -> None:
155  path.parent.mkdir(parents=True, exist_ok=True)
156  path.write_text(json.dumps(artifact, indent=2) + "\n", encoding="utf-8")
157 
158 
160  *,
161  artifact_id,
162  artifact_class,
163  mandatory,
164  path,
165  status,
166  expected_statuses,
167  purpose,
168  generation_command,
169  summary,
170 ):
171  return {
172  "artifact_id": artifact_id,
173  "artifact_class": artifact_class,
174  "mandatory": mandatory,
175  "path": path,
176  "status": status,
177  "expected_statuses": list(expected_statuses),
178  "purpose": purpose,
179  "generation_command": generation_command,
180  "summary": dict(summary),
181  }
182 
183 
185  required_flags = REQUIRED_SEMANTIC_FLAGS.get(artifact["artifact_id"], ())
186  return all(artifact["summary"].get(flag, False) for flag in required_flags)
187 
188 
190  output_dir: Path,
191  *,
192  workflow_contract,
193  end_to_end_trace_bundle,
194  matrix_baseline_bundle,
195  unsupported_workflow_bundle,
196  workflow_interpretation_bundle,
197 ):
198  output_dir = Path(output_dir)
199  workflow_contract_command = (
200  f"python benchmarks/density_matrix/workflow_evidence/workflow_contract_validation.py "
201  f"--output-dir {output_dir}"
202  )
203  end_to_end_trace_command = (
204  f"python benchmarks/density_matrix/workflow_evidence/end_to_end_trace_validation.py "
205  f"--output-dir {output_dir}"
206  )
207  matrix_baseline_command = (
208  f"python benchmarks/density_matrix/workflow_evidence/matrix_baseline_validation.py "
209  f"--output-dir {output_dir}"
210  )
211  unsupported_workflow_command = (
212  f"python benchmarks/density_matrix/workflow_evidence/unsupported_workflow_validation.py "
213  f"--output-dir {output_dir}"
214  )
215  workflow_interpretation_command = (
216  f"python benchmarks/density_matrix/workflow_evidence/workflow_interpretation_validation.py "
217  f"--output-dir {output_dir}"
218  )
219  workflow_publication_command = (
220  f"python benchmarks/density_matrix/workflow_evidence/workflow_publication_bundle.py "
221  f"--output-dir {output_dir}"
222  )
223 
224  artifacts = [
226  artifact_id="workflow_contract_bundle",
227  artifact_class="canonical_workflow_contract_bundle",
228  mandatory=True,
229  path=WORKFLOW_CONTRACT_ARTIFACT_FILENAME,
230  status=workflow_contract["status"],
231  expected_statuses=["pass"],
232  purpose="Canonical workflow-contract artifact defining workflow identity, contract version, input/output sections, and boundary classes.",
233  generation_command=workflow_contract_command,
234  summary={
235  "workflow_id": workflow_contract["workflow_id"],
236  "contract_version": workflow_contract["contract_version"],
237  "contract_sections_complete": workflow_contract["summary"][
238  "contract_sections_complete"
239  ],
240  "absolute_energy_error": workflow_contract["thresholds"][
241  "absolute_energy_error"
242  ],
243  "required_workflow_qubits": workflow_contract["thresholds"][
244  "required_workflow_qubits"
245  ],
246  },
247  ),
249  artifact_id="end_to_end_trace_bundle",
250  artifact_class="end_to_end_trace_bundle",
251  mandatory=True,
252  path=END_TO_END_TRACE_ARTIFACT_FILENAME,
253  status=end_to_end_trace_bundle["status"],
254  expected_statuses=["pass"],
255  purpose="4q/6q end-to-end execution plus required bounded trace evidence.",
256  generation_command=end_to_end_trace_command,
257  summary={
258  "total_end_to_end_cases": end_to_end_trace_bundle["summary"][
259  "total_end_to_end_cases"
260  ],
261  "passed_end_to_end_cases": end_to_end_trace_bundle["summary"][
262  "passed_end_to_end_cases"
263  ],
264  "required_trace_completed": end_to_end_trace_bundle["summary"][
265  "required_trace_completed"
266  ],
267  "end_to_end_gate_completed": end_to_end_trace_bundle["summary"][
268  "end_to_end_gate_completed"
269  ],
270  "end_to_end_qubits_match_contract": end_to_end_trace_bundle["summary"][
271  "end_to_end_qubits_match_contract"
272  ],
273  "trace_case_name_matches_contract": end_to_end_trace_bundle["summary"][
274  "trace_case_name_matches_contract"
275  ],
276  "workflow_thresholds_match_contract": end_to_end_trace_bundle["summary"][
277  "workflow_thresholds_match_contract"
278  ],
279  "workflow_id": end_to_end_trace_bundle["workflow_id"],
280  "contract_version": end_to_end_trace_bundle["contract_version"],
281  },
282  ),
284  artifact_id="matrix_baseline_bundle",
285  artifact_class="matrix_baseline_bundle",
286  mandatory=True,
287  path=MATRIX_BASELINE_ARTIFACT_FILENAME,
288  status=matrix_baseline_bundle["status"],
289  expected_statuses=["pass"],
290  purpose="Fixed-parameter 4/6/8/10 matrix baseline with explicit 10-qubit anchor presence.",
291  generation_command=matrix_baseline_command,
292  summary={
293  "required_cases": matrix_baseline_bundle["summary"]["required_cases"],
294  "required_passed_cases": matrix_baseline_bundle["summary"][
295  "required_passed_cases"
296  ],
297  "documented_10q_anchor_present": matrix_baseline_bundle["summary"][
298  "documented_10q_anchor_present"
299  ],
300  "matrix_gate_completed": matrix_baseline_bundle["summary"][
301  "matrix_gate_completed"
302  ],
303  "workflow_inventory_matches_contract": matrix_baseline_bundle["summary"][
304  "workflow_inventory_matches_contract"
305  ],
306  "workflow_thresholds_match_contract": matrix_baseline_bundle["summary"][
307  "workflow_thresholds_match_contract"
308  ],
309  "workflow_id": matrix_baseline_bundle["workflow_id"],
310  "contract_version": matrix_baseline_bundle["contract_version"],
311  },
312  ),
314  artifact_id="unsupported_workflow_bundle",
315  artifact_class="unsupported_workflow_bundle",
316  mandatory=True,
317  path=UNSUPPORTED_WORKFLOW_ARTIFACT_FILENAME,
318  status=unsupported_workflow_bundle["status"],
319  expected_statuses=["pass"],
320  purpose="Deterministic unsupported/deferred workflow boundary evidence.",
321  generation_command=unsupported_workflow_command,
322  summary={
323  "unsupported_status_cases": unsupported_workflow_bundle["summary"][
324  "unsupported_status_cases"
325  ],
326  "backend_incompatible_case_present": unsupported_workflow_bundle["summary"][
327  "backend_incompatible_case_present"
328  ],
329  "unsupported_gate_completed": unsupported_workflow_bundle["summary"][
330  "unsupported_gate_completed"
331  ],
332  "workflow_id": unsupported_workflow_bundle["workflow_id"],
333  "contract_version": unsupported_workflow_bundle["contract_version"],
334  },
335  ),
337  artifact_id="workflow_interpretation_bundle",
338  artifact_class="interpretation_guardrail_bundle",
339  mandatory=True,
340  path=WORKFLOW_INTERPRETATION_ARTIFACT_FILENAME,
341  status=workflow_interpretation_bundle["status"],
342  expected_statuses=["pass"],
343  purpose="Interpretation guardrails preventing optional, unsupported, or incomplete evidence from inflating the main claim.",
344  generation_command=workflow_interpretation_command,
345  summary={
346  "mandatory_artifacts_complete": workflow_interpretation_bundle["summary"][
347  "mandatory_artifacts_complete"
348  ],
349  "optional_evidence_supplemental": workflow_interpretation_bundle["summary"][
350  "optional_evidence_supplemental"
351  ],
352  "unsupported_evidence_negative_only": workflow_interpretation_bundle["summary"][
353  "unsupported_evidence_negative_only"
354  ],
355  "unsupported_case_field_alignment": workflow_interpretation_bundle["summary"][
356  "unsupported_case_field_alignment"
357  ],
358  "main_workflow_claim_completed": workflow_interpretation_bundle["summary"][
359  "main_workflow_claim_completed"
360  ],
361  "workflow_id": workflow_interpretation_bundle["workflow_id"],
362  "contract_version": workflow_interpretation_bundle["contract_version"],
363  },
364  ),
365  ]
366 
367  mandatory_artifacts = [artifact for artifact in artifacts if artifact["mandatory"]]
368  present_count = 0
369  status_match_count = 0
370  identity_match_count = 0
371  semantic_match_count = 0
372  for artifact in mandatory_artifacts:
373  if (output_dir / artifact["path"]).exists():
374  present_count += 1
375  if artifact["status"] in artifact["expected_statuses"]:
376  status_match_count += 1
377  if artifact["summary"].get("workflow_id", WORKFLOW_ID) == WORKFLOW_ID and artifact[
378  "summary"
379  ].get("contract_version", CONTRACT_VERSION) == CONTRACT_VERSION:
380  identity_match_count += 1
381  if _artifact_semantics_complete(artifact):
382  semantic_match_count += 1
383 
384  bundle_status = (
385  "pass"
386  if present_count == len(mandatory_artifacts)
387  and status_match_count == len(mandatory_artifacts)
388  and identity_match_count == len(mandatory_artifacts)
389  and semantic_match_count == len(mandatory_artifacts)
390  else "fail"
391  )
392 
393  bundle = {
394  "suite_name": SUITE_NAME,
395  "status": bundle_status,
396  "workflow_id": WORKFLOW_ID,
397  "contract_version": CONTRACT_VERSION,
398  "backend": workflow_contract["backend"],
399  "reference_backend": workflow_contract["reference_backend"],
400  "software": build_software_metadata(),
401  "provenance": {
402  "generation_command": workflow_publication_command,
403  "working_directory": str(REPO_ROOT),
404  "git_revision": get_git_revision(),
405  "workflow_contract_path": str(WORKFLOW_CONTRACT_PATH),
406  "end_to_end_trace_path": str(END_TO_END_TRACE_PATH),
407  "matrix_baseline_path": str(MATRIX_BASELINE_PATH),
408  "unsupported_workflow_path": str(UNSUPPORTED_WORKFLOW_PATH),
409  "workflow_interpretation_path": str(WORKFLOW_INTERPRETATION_PATH),
410  },
411  "summary": {
412  "mandatory_artifact_count": len(mandatory_artifacts),
413  "present_artifact_count": present_count,
414  "status_match_count": status_match_count,
415  "workflow_identity_match_count": identity_match_count,
416  "semantic_match_count": semantic_match_count,
417  "missing_artifact_count": len(mandatory_artifacts) - present_count,
418  "mismatched_status_count": len(mandatory_artifacts) - status_match_count,
419  "mismatched_identity_count": len(mandatory_artifacts) - identity_match_count,
420  "mismatched_semantic_count": len(mandatory_artifacts)
421  - semantic_match_count,
422  },
423  "artifacts": artifacts,
424  }
425  validate_workflow_publication_bundle(bundle, output_dir)
426  return bundle
427 
428 
429 def validate_workflow_publication_bundle(bundle, bundle_dir: Path):
430  missing_fields = [field for field in BUNDLE_FIELDS if field not in bundle]
431  if missing_fields:
432  raise ValueError(
433  "Workflow publication bundle is missing required fields: {}".format(
434  ", ".join(missing_fields)
435  )
436  )
437 
438  if bundle["workflow_id"] != WORKFLOW_ID:
439  raise ValueError(
440  "Workflow publication bundle has unexpected workflow_id '{}'".format(
441  bundle["workflow_id"]
442  )
443  )
444  if bundle["contract_version"] != CONTRACT_VERSION:
445  raise ValueError(
446  "Workflow publication bundle has unexpected contract_version '{}'".format(
447  bundle["contract_version"]
448  )
449  )
450 
451  required_ids = {
452  "workflow_contract_bundle",
453  "end_to_end_trace_bundle",
454  "matrix_baseline_bundle",
455  "unsupported_workflow_bundle",
456  "workflow_interpretation_bundle",
457  }
458  artifact_ids = {artifact["artifact_id"] for artifact in bundle["artifacts"]}
459  if required_ids - artifact_ids:
460  raise ValueError(
461  "Workflow publication bundle is missing required artifact IDs: {}".format(
462  ", ".join(sorted(required_ids - artifact_ids))
463  )
464  )
465 
466  for artifact in bundle["artifacts"]:
467  artifact_path = bundle_dir / artifact["path"]
468  if artifact["mandatory"] and not artifact_path.exists():
469  raise ValueError(
470  "Workflow publication bundle is missing artifact file: {}".format(
471  artifact["path"]
472  )
473  )
474  if artifact["status"] not in artifact["expected_statuses"]:
475  raise ValueError(
476  "Workflow publication artifact {} has unexpected status {}".format(
477  artifact["artifact_id"], artifact["status"]
478  )
479  )
480  if artifact["summary"].get("workflow_id", WORKFLOW_ID) != bundle["workflow_id"]:
481  raise ValueError(
482  "Workflow publication artifact {} has mismatched workflow_id".format(
483  artifact["artifact_id"]
484  )
485  )
486  if artifact["summary"].get(
487  "contract_version", CONTRACT_VERSION
488  ) != bundle["contract_version"]:
489  raise ValueError(
490  "Workflow publication artifact {} has mismatched contract_version".format(
491  artifact["artifact_id"]
492  )
493  )
494  if not _artifact_semantics_complete(artifact):
495  raise ValueError(
496  "Workflow publication artifact {} is missing required semantic closure flags".format(
497  artifact["artifact_id"]
498  )
499  )
500 
501 
502 def write_workflow_publication_bundle(output_path: Path, bundle):
503  validate_workflow_publication_bundle(bundle, output_path.parent)
504  output_path.parent.mkdir(parents=True, exist_ok=True)
505  output_path.write_text(json.dumps(bundle, indent=2) + "\n", encoding="utf-8")
506 
507 
508 def run_validation(
509  *,
510  workflow_contract_path: Path = WORKFLOW_CONTRACT_PATH,
511  end_to_end_trace_path: Path = END_TO_END_TRACE_PATH,
512  matrix_baseline_path: Path = MATRIX_BASELINE_PATH,
513  unsupported_workflow_path: Path = UNSUPPORTED_WORKFLOW_PATH,
514  workflow_interpretation_path: Path = WORKFLOW_INTERPRETATION_PATH,
515  output_dir: Path = DEFAULT_OUTPUT_DIR,
516  verbose=False,
517 ):
518  output_dir = Path(output_dir)
519  output_dir.mkdir(parents=True, exist_ok=True)
520  workflow_contract = _load_workflow_contract(workflow_contract_path)
521  end_to_end_trace_bundle = _load_end_to_end_trace(end_to_end_trace_path)
522  matrix_baseline_bundle = _load_matrix_baseline(matrix_baseline_path)
523  unsupported_workflow_bundle = _load_unsupported_workflow(unsupported_workflow_path)
524  workflow_interpretation_bundle = _load_workflow_interpretation(
525  workflow_interpretation_path
526  )
527  _write_artifact(output_dir / WORKFLOW_CONTRACT_ARTIFACT_FILENAME, workflow_contract)
529  output_dir / END_TO_END_TRACE_ARTIFACT_FILENAME, end_to_end_trace_bundle
530  )
531  _write_artifact(output_dir / MATRIX_BASELINE_ARTIFACT_FILENAME, matrix_baseline_bundle)
533  output_dir / UNSUPPORTED_WORKFLOW_ARTIFACT_FILENAME,
534  unsupported_workflow_bundle,
535  )
537  output_dir / WORKFLOW_INTERPRETATION_ARTIFACT_FILENAME,
538  workflow_interpretation_bundle,
539  )
541  output_dir,
542  workflow_contract=workflow_contract,
543  end_to_end_trace_bundle=end_to_end_trace_bundle,
544  matrix_baseline_bundle=matrix_baseline_bundle,
545  unsupported_workflow_bundle=unsupported_workflow_bundle,
546  workflow_interpretation_bundle=workflow_interpretation_bundle,
547  )
548  if verbose:
549  print(
550  "{} [{}] present={}/{} status_match={}/{} identity_match={}/{}".format(
551  bundle["suite_name"],
552  bundle["status"],
553  bundle["summary"]["present_artifact_count"],
554  bundle["summary"]["mandatory_artifact_count"],
555  bundle["summary"]["status_match_count"],
556  bundle["summary"]["mandatory_artifact_count"],
557  bundle["summary"]["workflow_identity_match_count"],
558  bundle["summary"]["mandatory_artifact_count"],
559  )
560  )
561  return (
562  workflow_contract,
563  end_to_end_trace_bundle,
564  matrix_baseline_bundle,
565  unsupported_workflow_bundle,
566  workflow_interpretation_bundle,
567  bundle,
568  )
569 
570 
572  parser = argparse.ArgumentParser(description=__doc__)
573  parser.add_argument(
574  "--output-dir",
575  type=Path,
576  default=DEFAULT_OUTPUT_DIR,
577  help="Directory for the workflow-publication JSON artifact bundle.",
578  )
579  parser.add_argument(
580  "--workflow-contract-path",
581  type=Path,
582  default=WORKFLOW_CONTRACT_PATH,
583  help="Path to the canonical workflow-contract artifact.",
584  )
585  parser.add_argument(
586  "--end-to-end-trace-path",
587  type=Path,
588  default=END_TO_END_TRACE_PATH,
589  help="Path to the end-to-end trace bundle.",
590  )
591  parser.add_argument(
592  "--matrix-baseline-path",
593  type=Path,
594  default=MATRIX_BASELINE_PATH,
595  help="Path to the matrix-baseline bundle.",
596  )
597  parser.add_argument(
598  "--unsupported-workflow-path",
599  type=Path,
600  default=UNSUPPORTED_WORKFLOW_PATH,
601  help="Path to the unsupported-workflow bundle.",
602  )
603  parser.add_argument(
604  "--workflow-interpretation-path",
605  type=Path,
606  default=WORKFLOW_INTERPRETATION_PATH,
607  help="Path to the workflow-interpretation bundle.",
608  )
609  parser.add_argument(
610  "--quiet",
611  action="store_true",
612  help="Suppress summary output.",
613  )
614  return parser.parse_args()
615 
616 
617 def main():
618  args = parse_args()
619  *_, bundle = run_validation(
620  workflow_contract_path=args.workflow_contract_path,
621  end_to_end_trace_path=args.end_to_end_trace_path,
622  matrix_baseline_path=args.matrix_baseline_path,
623  unsupported_workflow_path=args.unsupported_workflow_path,
624  workflow_interpretation_path=args.workflow_interpretation_path,
625  output_dir=args.output_dir,
626  verbose=not args.quiet,
627  )
628  output_path = args.output_dir / ARTIFACT_FILENAME
629  write_workflow_publication_bundle(output_path, bundle)
630  print(
631  "Wrote {} with status {} ({}/{})".format(
632  output_path,
633  bundle["status"],
634  bundle["summary"]["present_artifact_count"],
635  bundle["summary"]["mandatory_artifact_count"],
636  )
637  )
638  if bundle["status"] != "pass":
639  raise SystemExit(1)
640 
641 
642 if __name__ == "__main__":
643  main()
def _build_artifact_entry(artifact_id, artifact_class, mandatory, path, status, expected_statuses, purpose, generation_command, summary)
def build_software_metadata()