From 7b287612c4e5af419df21d3c411bdaef060b3c96 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:00:51 +0300 Subject: [PATCH 01/29] Add versioned machine output contract helpers --- src/process_as_code/output_contract.py | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/process_as_code/output_contract.py diff --git a/src/process_as_code/output_contract.py b/src/process_as_code/output_contract.py new file mode 100644 index 0000000..b0b1c9a --- /dev/null +++ b/src/process_as_code/output_contract.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +import json +from importlib.resources import files +from typing import Any + + +OUTPUT_FORMAT_VERSION = "1.0" + +_OUTPUT_FORMATS = { + "semantic-diff": "process-as-code.semantic-diff", + "impact": "process-as-code.impact", +} + +_OUTPUT_SCHEMA_FILES = { + "semantic-diff": "semantic-diff-v1.schema.json", + "impact": "impact-v1.schema.json", +} + +_RESOURCE_ROOT = files("process_as_code").joinpath("resources/output-schemas") + + +def output_kinds() -> tuple[str, ...]: + """Return stable machine-output contract kinds exposed by the CLI.""" + return tuple(_OUTPUT_FORMATS) + + +def output_metadata(kind: str) -> dict[str, str]: + """Return the compatibility metadata for one machine-readable output kind.""" + try: + format_name = _OUTPUT_FORMATS[kind] + except KeyError as exc: + raise ValueError(f"unknown output contract kind '{kind}'") from exc + return {"format": format_name, "version": OUTPUT_FORMAT_VERSION} + + +def attach_output_contract(kind: str, payload: dict[str, Any]) -> dict[str, Any]: + """Attach additive output metadata without changing existing payload keys.""" + if "output" in payload: + raise ValueError("machine-readable payload already contains reserved 'output' metadata") + return {"output": output_metadata(kind), **payload} + + +def output_schema_text(kind: str) -> str: + """Return a bundled JSON Schema for a machine-readable output contract.""" + try: + filename = _OUTPUT_SCHEMA_FILES[kind] + except KeyError as exc: + raise ValueError(f"unknown output contract kind '{kind}'") from exc + return _RESOURCE_ROOT.joinpath(filename).read_text(encoding="utf-8") + + +def output_schema_dict(kind: str) -> dict[str, Any]: + """Return a bundled machine-output JSON Schema as a mapping.""" + data = json.loads(output_schema_text(kind)) + if not isinstance(data, dict): + raise ValueError(f"bundled output schema '{kind}' must be a JSON object") + return data From eccdada4cf9bad4e2cd4f2498f1f523136f692ce Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:23 +0300 Subject: [PATCH 02/29] Add machine output JSON Schemas --- schemas/outputs/semantic-diff-v1.schema.json | 77 ++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 schemas/outputs/semantic-diff-v1.schema.json diff --git a/schemas/outputs/semantic-diff-v1.schema.json b/schemas/outputs/semantic-diff-v1.schema.json new file mode 100644 index 0000000..f3e5b1e --- /dev/null +++ b/schemas/outputs/semantic-diff-v1.schema.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", + "title": "Process as Code semantic diff output v1", + "type": "object", + "required": ["output", "process", "sections", "analysis"], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.semantic-diff"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + }, + "process": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/value_change"} + }, + "sections": { + "type": "object", + "required": ["steps", "roles", "systems", "objects", "interfaces", "controls", "risks", "evidence", "artifacts"], + "properties": { + "steps": {"$ref": "#/$defs/entity_diff"}, + "roles": {"$ref": "#/$defs/entity_diff"}, + "systems": {"$ref": "#/$defs/entity_diff"}, + "objects": {"$ref": "#/$defs/entity_diff"}, + "interfaces": {"$ref": "#/$defs/entity_diff"}, + "controls": {"$ref": "#/$defs/entity_diff"}, + "risks": {"$ref": "#/$defs/entity_diff"}, + "evidence": {"$ref": "#/$defs/entity_diff"}, + "artifacts": {"$ref": "#/$defs/entity_diff"} + }, + "additionalProperties": true + }, + "analysis": { + "type": "object", + "required": ["variants", "pain_points", "data_flows"], + "properties": { + "variants": {"$ref": "#/$defs/entity_diff"}, + "pain_points": {"$ref": "#/$defs/entity_diff"}, + "data_flows": {"$ref": "#/$defs/entity_diff"} + }, + "additionalProperties": true + } + }, + "$defs": { + "value_change": { + "type": "object", + "required": ["old", "new"], + "properties": { + "old": {}, + "new": {} + }, + "additionalProperties": true + }, + "field_changes": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/value_change"} + }, + "entity_diff": { + "type": "object", + "required": ["added", "removed", "changed"], + "properties": { + "added": {"type": "array", "items": {"type": "string"}}, + "removed": {"type": "array", "items": {"type": "string"}}, + "changed": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/field_changes"} + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true +} From 1d76f0418b6d294101938b34438252782741880d Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:24 +0300 Subject: [PATCH 03/29] Add machine output JSON Schemas --- schemas/outputs/impact-v1.schema.json | 84 +++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 schemas/outputs/impact-v1.schema.json diff --git a/schemas/outputs/impact-v1.schema.json b/schemas/outputs/impact-v1.schema.json new file mode 100644 index 0000000..fe87e61 --- /dev/null +++ b/schemas/outputs/impact-v1.schema.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/impact-v1.schema.json", + "title": "Process as Code change impact output v1", + "type": "object", + "required": [ + "output", + "changed_steps", + "analysis_changes", + "analysis_affected_steps", + "affected", + "risk_flags", + "recommended_tests", + "resolved_artifacts", + "semantic_diff" + ], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.impact"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + }, + "changed_steps": {"type": "array", "items": {"type": "string"}}, + "analysis_changes": { + "type": "object", + "required": ["variants", "pain_points", "data_flows"], + "properties": { + "variants": {"type": "array", "items": {"type": "string"}}, + "pain_points": {"type": "array", "items": {"type": "string"}}, + "data_flows": {"type": "array", "items": {"type": "string"}} + }, + "additionalProperties": true + }, + "analysis_affected_steps": {"type": "array", "items": {"type": "string"}}, + "affected": { + "type": "object", + "required": ["roles", "systems", "objects", "interfaces", "controls", "risks", "evidence", "artifacts", "subprocesses"], + "additionalProperties": { + "type": "array", + "items": {"type": "string"} + } + }, + "risk_flags": {"type": "array", "items": {"type": "string"}}, + "recommended_tests": { + "type": "array", + "items": { + "type": "object", + "required": ["id", "step", "type", "scenario"], + "properties": { + "id": {"type": "string"}, + "step": {"type": "string"}, + "type": {"type": "string"}, + "scenario": {"type": "string"} + }, + "additionalProperties": true + } + }, + "resolved_artifacts": { + "type": "array", + "items": {"type": "object"} + }, + "semantic_diff": { + "type": "object", + "required": ["output", "process", "sections", "analysis"], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.semantic-diff"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true +} From bd2ab31e1ad844ce46d0ac89723f3207fbd012d8 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:27 +0300 Subject: [PATCH 04/29] Add machine output JSON Schemas --- .../semantic-diff-v1.schema.json | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json diff --git a/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json b/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json new file mode 100644 index 0000000..f3e5b1e --- /dev/null +++ b/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", + "title": "Process as Code semantic diff output v1", + "type": "object", + "required": ["output", "process", "sections", "analysis"], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.semantic-diff"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + }, + "process": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/value_change"} + }, + "sections": { + "type": "object", + "required": ["steps", "roles", "systems", "objects", "interfaces", "controls", "risks", "evidence", "artifacts"], + "properties": { + "steps": {"$ref": "#/$defs/entity_diff"}, + "roles": {"$ref": "#/$defs/entity_diff"}, + "systems": {"$ref": "#/$defs/entity_diff"}, + "objects": {"$ref": "#/$defs/entity_diff"}, + "interfaces": {"$ref": "#/$defs/entity_diff"}, + "controls": {"$ref": "#/$defs/entity_diff"}, + "risks": {"$ref": "#/$defs/entity_diff"}, + "evidence": {"$ref": "#/$defs/entity_diff"}, + "artifacts": {"$ref": "#/$defs/entity_diff"} + }, + "additionalProperties": true + }, + "analysis": { + "type": "object", + "required": ["variants", "pain_points", "data_flows"], + "properties": { + "variants": {"$ref": "#/$defs/entity_diff"}, + "pain_points": {"$ref": "#/$defs/entity_diff"}, + "data_flows": {"$ref": "#/$defs/entity_diff"} + }, + "additionalProperties": true + } + }, + "$defs": { + "value_change": { + "type": "object", + "required": ["old", "new"], + "properties": { + "old": {}, + "new": {} + }, + "additionalProperties": true + }, + "field_changes": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/value_change"} + }, + "entity_diff": { + "type": "object", + "required": ["added", "removed", "changed"], + "properties": { + "added": {"type": "array", "items": {"type": "string"}}, + "removed": {"type": "array", "items": {"type": "string"}}, + "changed": { + "type": "object", + "additionalProperties": {"$ref": "#/$defs/field_changes"} + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true +} From 26d6176e405e445442f9c3534ebdcc86314416aa Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:29 +0300 Subject: [PATCH 05/29] Add machine output JSON Schemas --- .../output-schemas/impact-v1.schema.json | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/process_as_code/resources/output-schemas/impact-v1.schema.json diff --git a/src/process_as_code/resources/output-schemas/impact-v1.schema.json b/src/process_as_code/resources/output-schemas/impact-v1.schema.json new file mode 100644 index 0000000..fe87e61 --- /dev/null +++ b/src/process_as_code/resources/output-schemas/impact-v1.schema.json @@ -0,0 +1,84 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/impact-v1.schema.json", + "title": "Process as Code change impact output v1", + "type": "object", + "required": [ + "output", + "changed_steps", + "analysis_changes", + "analysis_affected_steps", + "affected", + "risk_flags", + "recommended_tests", + "resolved_artifacts", + "semantic_diff" + ], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.impact"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + }, + "changed_steps": {"type": "array", "items": {"type": "string"}}, + "analysis_changes": { + "type": "object", + "required": ["variants", "pain_points", "data_flows"], + "properties": { + "variants": {"type": "array", "items": {"type": "string"}}, + "pain_points": {"type": "array", "items": {"type": "string"}}, + "data_flows": {"type": "array", "items": {"type": "string"}} + }, + "additionalProperties": true + }, + "analysis_affected_steps": {"type": "array", "items": {"type": "string"}}, + "affected": { + "type": "object", + "required": ["roles", "systems", "objects", "interfaces", "controls", "risks", "evidence", "artifacts", "subprocesses"], + "additionalProperties": { + "type": "array", + "items": {"type": "string"} + } + }, + "risk_flags": {"type": "array", "items": {"type": "string"}}, + "recommended_tests": { + "type": "array", + "items": { + "type": "object", + "required": ["id", "step", "type", "scenario"], + "properties": { + "id": {"type": "string"}, + "step": {"type": "string"}, + "type": {"type": "string"}, + "scenario": {"type": "string"} + }, + "additionalProperties": true + } + }, + "resolved_artifacts": { + "type": "array", + "items": {"type": "object"} + }, + "semantic_diff": { + "type": "object", + "required": ["output", "process", "sections", "analysis"], + "properties": { + "output": { + "type": "object", + "required": ["format", "version"], + "properties": { + "format": {"const": "process-as-code.semantic-diff"}, + "version": {"const": "1.0"} + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true +} From 7aa49e0b0b24fc5300273308725f9046a894961d Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:50 +0300 Subject: [PATCH 06/29] Version semantic diff machine output --- src/process_as_code/diff.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/process_as_code/diff.py b/src/process_as_code/diff.py index b2eca92..2e9b32b 100644 --- a/src/process_as_code/diff.py +++ b/src/process_as_code/diff.py @@ -2,6 +2,8 @@ from typing import Any +from .output_contract import attach_output_contract + SECTIONS = ("steps", "roles", "systems", "objects", "interfaces", "controls", "risks", "evidence", "artifacts") ANALYSIS_SECTIONS = ("variants", "pain_points", "data_flows") @@ -45,7 +47,7 @@ def semantic_diff(old: dict[str, Any], new: dict[str, Any]) -> dict[str, Any]: new_analysis = new.get("analysis", {}) if isinstance(new.get("analysis"), dict) else {} for section in ANALYSIS_SECTIONS: result["analysis"][section] = _diff_items(old_analysis.get(section), new_analysis.get(section)) - return result + return attach_output_contract("semantic-diff", result) def diff_markdown(diff: dict[str, Any]) -> str: From b93f55b2e9856084a1a3b5352091574b18de1fe7 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:01:52 +0300 Subject: [PATCH 07/29] Version impact machine output --- src/process_as_code/impact.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/process_as_code/impact.py b/src/process_as_code/impact.py index cf1e550..3889cb3 100644 --- a/src/process_as_code/impact.py +++ b/src/process_as_code/impact.py @@ -4,6 +4,7 @@ from typing import Any from .diff import semantic_diff +from .output_contract import attach_output_contract from .refs import resolve_artifacts from .testgen import generate_test_scope @@ -121,7 +122,7 @@ def impact_analysis(old: dict[str, Any], new: dict[str, Any], *, base_dir: str | affected_artifacts = affected["artifacts"] resolved = [r for r in resolved_all if r.get("id") in affected_artifacts] - return { + return attach_output_contract("impact", { "changed_steps": sorted(changed_steps), "analysis_changes": analysis_changes, "analysis_affected_steps": sorted(analysis_affected_steps), @@ -130,7 +131,7 @@ def impact_analysis(old: dict[str, Any], new: dict[str, Any], *, base_dir: str | "recommended_tests": tests, "resolved_artifacts": resolved, "semantic_diff": diff, - } + }) def impact_markdown(result: dict[str, Any]) -> str: lines = ["# Process change impact", "", "## Changed steps", ""] From b40d9e685efe4406ee54740ab11509b3cb84cf4f Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:02:19 +0300 Subject: [PATCH 08/29] Expose machine output schemas in CLI --- src/process_as_code/cli.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/process_as_code/cli.py b/src/process_as_code/cli.py index 6329352..bd365aa 100644 --- a/src/process_as_code/cli.py +++ b/src/process_as_code/cli.py @@ -16,6 +16,7 @@ from .jsonld import to_jsonld from .migrate import migrate_process from .observed import compare_observed, load_event_traces, observed_markdown +from .output_contract import output_kinds, output_schema_text from .policy import evaluate_policy, policy_markdown from .process_tests import affected_process_tests, run_process_tests from .raci import extract_raci, raci_markdown @@ -61,6 +62,10 @@ def build_parser() -> argparse.ArgumentParser: if name == "jsonld": cmd.add_argument("--base-uri") + output_schema = sub.add_parser("output-schema", help="print a bundled machine-output JSON Schema") + output_schema.add_argument("kind", choices=output_kinds()) + output_schema.add_argument("-o", "--output") + diff = sub.add_parser("diff", help="semantic diff between two process versions") diff.add_argument("old") diff.add_argument("new") @@ -160,6 +165,9 @@ def main(argv: list[str] | None = None) -> int: return 0 return 1 + if args.command == "output-schema": + _write(output_schema_text(args.kind), args.output) + return 0 if args.command == "diff": change = semantic_diff(load_process(args.old), load_process(args.new)) _write(dump_json(change) if args.json else diff_markdown(change), args.output) From d20cf1b8d5bc0decf3c60fef18b6a3fb096d0faa Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:02:21 +0300 Subject: [PATCH 09/29] Bundle and test machine output schemas --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b54941e..12557b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ Repository = "https://github.com/dkharlanau/process-as-code" Issues = "https://github.com/dkharlanau/process-as-code/issues" [project.optional-dependencies] -dev = ["pytest>=8.0"] +dev = ["pytest>=8.0", "jsonschema>=4.23"] mcp = ["mcp>=2,<3"] [project.scripts] @@ -43,4 +43,4 @@ package-dir = {"" = "src"} where = ["src"] [tool.setuptools.package-data] -process_as_code = ["resources/*.json"] +process_as_code = ["resources/*.json", "resources/output-schemas/*.json"] From b33ffcfbb81d57f66cd5258b6697aaa1d1fe68e4 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:02:34 +0300 Subject: [PATCH 10/29] Add machine output contract tests --- tests/test_output_contracts.py | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tests/test_output_contracts.py diff --git a/tests/test_output_contracts.py b/tests/test_output_contracts.py new file mode 100644 index 0000000..c349478 --- /dev/null +++ b/tests/test_output_contracts.py @@ -0,0 +1,69 @@ +from __future__ import annotations + +import json +from pathlib import Path + +from jsonschema import Draft202012Validator + +from process_as_code.cli import main +from process_as_code.diff import semantic_diff +from process_as_code.impact import impact_analysis +from process_as_code.io import load_process +from process_as_code.output_contract import ( + OUTPUT_FORMAT_VERSION, + output_metadata, + output_schema_dict, + output_schema_text, +) + + +ROOT = Path(__file__).resolve().parents[1] +OLD = ROOT / "examples/customer-creation.process.yaml" +NEW = ROOT / "examples/changes/customer-creation-v2.process.yaml" + +SCHEMAS = { + "semantic-diff": "semantic-diff-v1.schema.json", + "impact": "impact-v1.schema.json", +} + + +def test_semantic_diff_has_stable_output_contract() -> None: + result = semantic_diff(load_process(OLD), load_process(NEW)) + + assert result["output"] == { + "format": "process-as-code.semantic-diff", + "version": "1.0", + } + assert {"process", "sections", "analysis"} <= set(result) + Draft202012Validator(output_schema_dict("semantic-diff")).validate(result) + + +def test_impact_has_stable_output_contract_and_tagged_nested_diff() -> None: + result = impact_analysis(load_process(OLD), load_process(NEW)) + + assert result["output"] == { + "format": "process-as-code.impact", + "version": "1.0", + } + assert {"changed_steps", "affected", "risk_flags", "recommended_tests", "semantic_diff"} <= set(result) + assert result["semantic_diff"]["output"]["format"] == "process-as-code.semantic-diff" + Draft202012Validator(output_schema_dict("impact")).validate(result) + + +def test_output_schema_source_and_package_copies_match() -> None: + for kind, filename in SCHEMAS.items(): + source = (ROOT / "schemas" / "outputs" / filename).read_text(encoding="utf-8") + assert output_schema_text(kind) == source + parsed = json.loads(source) + assert parsed["properties"]["output"]["properties"]["version"]["const"] == OUTPUT_FORMAT_VERSION + + +def test_output_contract_metadata_is_explicit() -> None: + assert output_metadata("semantic-diff")["format"] != output_metadata("impact")["format"] + assert output_metadata("impact")["version"] == OUTPUT_FORMAT_VERSION + + +def test_cli_exports_bundled_output_schema(tmp_path: Path) -> None: + target = tmp_path / "impact.schema.json" + assert main(["output-schema", "impact", "-o", str(target)]) == 0 + assert target.read_text(encoding="utf-8") == output_schema_text("impact") From 732b445c5cb5c5e1024f32e6c2938263ddff7984 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:03:14 +0300 Subject: [PATCH 11/29] Add stable schema URIs to output metadata --- src/process_as_code/output_contract.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/process_as_code/output_contract.py b/src/process_as_code/output_contract.py index b0b1c9a..f1e9863 100644 --- a/src/process_as_code/output_contract.py +++ b/src/process_as_code/output_contract.py @@ -17,6 +17,11 @@ "impact": "impact-v1.schema.json", } +_OUTPUT_SCHEMA_URLS = { + "semantic-diff": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", + "impact": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json", +} + _RESOURCE_ROOT = files("process_as_code").joinpath("resources/output-schemas") @@ -31,7 +36,11 @@ def output_metadata(kind: str) -> dict[str, str]: format_name = _OUTPUT_FORMATS[kind] except KeyError as exc: raise ValueError(f"unknown output contract kind '{kind}'") from exc - return {"format": format_name, "version": OUTPUT_FORMAT_VERSION} + return { + "format": format_name, + "version": OUTPUT_FORMAT_VERSION, + "schema": _OUTPUT_SCHEMA_URLS[kind], + } def attach_output_contract(kind: str, payload: dict[str, Any]) -> dict[str, Any]: From 54bae6295ad51915ed8a7dfc66b2fe8fe9bf043f Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:03:16 +0300 Subject: [PATCH 12/29] Publish self-describing output schema metadata --- schemas/outputs/semantic-diff-v1.schema.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/schemas/outputs/semantic-diff-v1.schema.json b/schemas/outputs/semantic-diff-v1.schema.json index f3e5b1e..4696371 100644 --- a/schemas/outputs/semantic-diff-v1.schema.json +++ b/schemas/outputs/semantic-diff-v1.schema.json @@ -1,16 +1,17 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", + "$id": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", "title": "Process as Code semantic diff output v1", "type": "object", "required": ["output", "process", "sections", "analysis"], "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.semantic-diff"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json"} }, "additionalProperties": true }, From 8a3bae46877739ea216c4671c1a4ba3b7c6671d0 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:03:19 +0300 Subject: [PATCH 13/29] Publish self-describing output schema metadata --- schemas/outputs/impact-v1.schema.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/schemas/outputs/impact-v1.schema.json b/schemas/outputs/impact-v1.schema.json index fe87e61..674db1f 100644 --- a/schemas/outputs/impact-v1.schema.json +++ b/schemas/outputs/impact-v1.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/impact-v1.schema.json", + "$id": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json", "title": "Process as Code change impact output v1", "type": "object", "required": [ @@ -17,10 +17,11 @@ "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.impact"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json"} }, "additionalProperties": true }, @@ -69,10 +70,11 @@ "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.semantic-diff"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json"} }, "additionalProperties": true } From a1a8f228ae33a7470512f143e01e52b872a14db9 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:03:21 +0300 Subject: [PATCH 14/29] Publish self-describing output schema metadata --- .../resources/output-schemas/semantic-diff-v1.schema.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json b/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json index f3e5b1e..4696371 100644 --- a/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json +++ b/src/process_as_code/resources/output-schemas/semantic-diff-v1.schema.json @@ -1,16 +1,17 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", + "$id": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", "title": "Process as Code semantic diff output v1", "type": "object", "required": ["output", "process", "sections", "analysis"], "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.semantic-diff"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json"} }, "additionalProperties": true }, From 18309066c7d0817609cba0196f69192f17586820 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:03:23 +0300 Subject: [PATCH 15/29] Publish self-describing output schema metadata --- .../resources/output-schemas/impact-v1.schema.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/process_as_code/resources/output-schemas/impact-v1.schema.json b/src/process_as_code/resources/output-schemas/impact-v1.schema.json index fe87e61..674db1f 100644 --- a/src/process_as_code/resources/output-schemas/impact-v1.schema.json +++ b/src/process_as_code/resources/output-schemas/impact-v1.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/dkharlanau/process-as-code/schemas/outputs/impact-v1.schema.json", + "$id": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json", "title": "Process as Code change impact output v1", "type": "object", "required": [ @@ -17,10 +17,11 @@ "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.impact"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json"} }, "additionalProperties": true }, @@ -69,10 +70,11 @@ "properties": { "output": { "type": "object", - "required": ["format", "version"], + "required": ["format", "version", "schema"], "properties": { "format": {"const": "process-as-code.semantic-diff"}, - "version": {"const": "1.0"} + "version": {"const": "1.0"}, + "schema": {"const": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json"} }, "additionalProperties": true } From 284d085e1fe740ccba79adeb1a6766dbc710664b Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:05 +0300 Subject: [PATCH 16/29] Test self-describing output metadata --- tests/test_output_contracts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_output_contracts.py b/tests/test_output_contracts.py index c349478..5245354 100644 --- a/tests/test_output_contracts.py +++ b/tests/test_output_contracts.py @@ -33,6 +33,7 @@ def test_semantic_diff_has_stable_output_contract() -> None: assert result["output"] == { "format": "process-as-code.semantic-diff", "version": "1.0", + "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json", } assert {"process", "sections", "analysis"} <= set(result) Draft202012Validator(output_schema_dict("semantic-diff")).validate(result) @@ -44,6 +45,7 @@ def test_impact_has_stable_output_contract_and_tagged_nested_diff() -> None: assert result["output"] == { "format": "process-as-code.impact", "version": "1.0", + "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json", } assert {"changed_steps", "affected", "risk_flags", "recommended_tests", "semantic_diff"} <= set(result) assert result["semantic_diff"]["output"]["format"] == "process-as-code.semantic-diff" From a80529cc09daade2a21c4e411b9b9a13e141731a Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:07 +0300 Subject: [PATCH 17/29] Document versioned machine output contracts --- docs/machine-output-contracts.md | 82 ++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 docs/machine-output-contracts.md diff --git a/docs/machine-output-contracts.md b/docs/machine-output-contracts.md new file mode 100644 index 0000000..42948f9 --- /dev/null +++ b/docs/machine-output-contracts.md @@ -0,0 +1,82 @@ +# Machine-readable output contracts + +Process as Code exposes deterministic JSON for automation. The first versioned output contracts cover: + +- `process-code diff OLD NEW --json` +- `process-code impact OLD NEW --json` + +These JSON documents are used by CI pipelines, repository tooling, agent integrations and other as-code tools. Their structure therefore needs an explicit compatibility boundary. + +## Output metadata + +Each versioned JSON document contains an `output` object: + +```json +{ + "output": { + "format": "process-as-code.semantic-diff", + "version": "1.0", + "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json" + }, + "process": {}, + "sections": {}, + "analysis": {} +} +``` + +The impact report uses `process-as-code.impact` and its own schema URI. Its nested `semantic_diff` object keeps the semantic-diff metadata as well. + +The output contract version is independent from: + +- the Process Contract version such as `0.2`; +- the Python package version such as `0.2.0`. + +## Compatibility rule + +Version `1.0` follows these rules: + +1. Existing documented fields keep their meaning and type. +2. New optional fields may be added. +3. Consumers should ignore fields they do not understand. +4. Removing, renaming or changing the type of an existing documented field requires a new major output contract. +5. Machine output stays deterministic. It does not include timestamps, random IDs or environment-specific values unless a command explicitly models them as business data. + +This policy lets a CI consumer depend on fields such as `sections.steps.changed` or `affected.interfaces` without depending on the internal Python implementation. + +## JSON Schemas + +The schemas are stored in: + +- `schemas/outputs/semantic-diff-v1.schema.json` +- `schemas/outputs/impact-v1.schema.json` + +They are bundled in the Python package and published with the project site. + +Retrieve the bundled copies without network access: + +```bash +process-code output-schema semantic-diff -o semantic-diff.schema.json +process-code output-schema impact -o impact.schema.json +``` + +## Consumer pattern + +A consumer should check the metadata before reading the payload: + +```python +result = json.loads(payload) + +output = result["output"] +if output["format"] != "process-as-code.impact": + raise ValueError("unexpected Process as Code output") +if output["version"] != "1.0": + raise ValueError("unsupported impact contract version") + +interfaces = result["affected"]["interfaces"] +``` + +For validation, use the schema from `output.schema` or a bundled copy retrieved with `process-code output-schema`. + +## Scope + +The first contract boundary is intentionally focused on semantic change control: diff and impact. Other JSON-producing commands can adopt the same pattern when their payloads become integration surfaces with external consumers. From 9a8d5882373bb1694499e5257ac960140c66fb05 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:32 +0300 Subject: [PATCH 18/29] Expose machine output contracts in README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ad5be7..ef10612 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ The source-tree schema is [`schemas/process.schema.json`](schemas/process.schema | Capability | Command | | --- | --- | | Bundled JSON Schema | `process-code schema` | +| Versioned machine-output schemas | `process-code output-schema` | | Contract validation | `process-code validate` | | v0.1 -> v0.2 migration | `process-code migrate` | | Mermaid | `process-code mermaid` | @@ -321,7 +322,7 @@ The deterministic graph keeps stable links across process, steps, systems, inter ## Status -`0.2.0` alpha reference implementation. The specification is intentionally explicit but not frozen until 1.0. See [`PRODUCT_BACKLOG.md`](PRODUCT_BACKLOG.md), [`ROADMAP.md`](ROADMAP.md), the [problem-oriented guides](docs/guides/README.md), and the public conformance suite. +`0.2.0` alpha reference implementation. The specification is intentionally explicit but not frozen until 1.0. See [`PRODUCT_BACKLOG.md`](PRODUCT_BACKLOG.md), [`ROADMAP.md`](ROADMAP.md), the [machine-readable output contracts](docs/machine-output-contracts.md), the [problem-oriented guides](docs/guides/README.md), and the public conformance suite. MIT License. From c0d02f820ae80ed1385a8eca933dfc640b7dcdc4 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:34 +0300 Subject: [PATCH 19/29] Document output schema CLI --- docs/cli.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/cli.md b/docs/cli.md index fcdb7c0..c122afa 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -10,6 +10,7 @@ Core authoring and review: - `docs FILE` - `raci FILE` - `diff OLD NEW [--json]` +- `output-schema {semantic-diff,impact} [-o FILE]` - `diff-visual OLD NEW` - `impact OLD NEW [--resolve-external]` - `policy FILE --policy POLICY [--old OLD]` @@ -32,4 +33,6 @@ Adoption and AI tooling: - `adapter-import ADAPTER SOURCE` - `mcp --root ROOT` +`diff --json` and `impact --json` use versioned machine-output contracts with bundled JSON Schemas. See [Machine-readable output contracts](machine-output-contracts.md). + Commands that support `--json` emit deterministic machine-readable output suitable for CI/agents. The CLI returns non-zero for validation, policy, test or import validation failures. From 683aa536f07e1bf61f857ffcdb24607fdcb512cc Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:36 +0300 Subject: [PATCH 20/29] Record versioned machine output contracts --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e261c7f..e583b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - BPMN supported-subset import and richer export with lanes and parallel gateways. - Process governance policy gates. - GitHub Action PR validation, semantic impact and marker-based PR comment reporting, including shallow-checkout support and deleted-contract status. +- Versioned machine-readable contracts and bundled JSON Schemas for semantic diff and impact output. - Portable/transitive external artifact resolver with GitHub and JSON Pointer support. - External artifact security hardening: local-reference sandboxing against traversal/symlink escapes, validated GitHub URI components and bounded network payloads. - MCP v2 process-context server. From 7984569b5c2241a89011ed9a149425572c4e2e68 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:38 +0300 Subject: [PATCH 21/29] Track machine output contracts in roadmap --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index b4a46fc..7bad28a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -43,6 +43,7 @@ For product strategy and acceptance criteria, see [PRODUCT_BACKLOG.md](PRODUCT_B - [x] zero-backend browser playground - [x] adapter framework + BPMN/CSV reference adapters - [x] provider-neutral AI-assisted drafting bundle +- [x] versioned JSON output contracts for semantic diff and impact ## 1.0 — stable contract From 4dc39677a3b009202e31534625cf3639aea43254 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:41 +0300 Subject: [PATCH 22/29] Publish machine output schemas on Pages --- .github/workflows/pages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 7bac8ea..6433925 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -35,6 +35,8 @@ jobs: cp docs/product.html _site/index.html cp docs/agent-manifest.json _site/agent-manifest.json cp -R web/playground _site/playground + mkdir -p _site/schemas/outputs + cp schemas/outputs/*.json _site/schemas/outputs/ touch _site/.nojekyll - name: Detect Pages availability id: pages From c05ded3b7b6a08ba18553fc850cd4c8acae41a55 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:04:43 +0300 Subject: [PATCH 23/29] Smoke test bundled output schemas --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b7925f..aea3ad4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,12 +101,18 @@ jobs: cd /tmp printf '%s\n' 'Create and approve a customer request, then replicate it to the target system.' > process-description.txt /tmp/pac-wheel/bin/process-code schema -o process.schema.json + /tmp/pac-wheel/bin/process-code output-schema semantic-diff -o semantic-diff.schema.json + /tmp/pac-wheel/bin/process-code output-schema impact -o impact.schema.json /tmp/pac-wheel/bin/process-code draft-context process-description.txt --json -o draft-context.json /tmp/pac-wheel/bin/python - <<'PY' import json schema = json.load(open('/tmp/process.schema.json', encoding='utf-8')) + diff_schema = json.load(open('/tmp/semantic-diff.schema.json', encoding='utf-8')) + impact_schema = json.load(open('/tmp/impact.schema.json', encoding='utf-8')) draft = json.load(open('/tmp/draft-context.json', encoding='utf-8')) assert schema['title'] == 'Process as Code contract v0.2' + assert diff_schema['properties']['output']['properties']['format']['const'] == 'process-as-code.semantic-diff' + assert impact_schema['properties']['output']['properties']['format']['const'] == 'process-as-code.impact' assert draft['schema']['title'] == schema['title'] assert draft['schema_source'].startswith('package:') PY From 0438ac5567a22665816836a92674bae0d60988f0 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:05:59 +0300 Subject: [PATCH 24/29] Test public JSON CLI contract metadata --- tests/test_output_contracts.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_output_contracts.py b/tests/test_output_contracts.py index 5245354..4a32780 100644 --- a/tests/test_output_contracts.py +++ b/tests/test_output_contracts.py @@ -69,3 +69,17 @@ def test_cli_exports_bundled_output_schema(tmp_path: Path) -> None: target = tmp_path / "impact.schema.json" assert main(["output-schema", "impact", "-o", str(target)]) == 0 assert target.read_text(encoding="utf-8") == output_schema_text("impact") + + +def test_cli_diff_and_impact_json_keep_contract_metadata(tmp_path: Path) -> None: + diff_target = tmp_path / "diff.json" + impact_target = tmp_path / "impact.json" + + assert main(["diff", str(OLD), str(NEW), "--json", "-o", str(diff_target)]) == 0 + assert main(["impact", str(OLD), str(NEW), "--json", "-o", str(impact_target)]) == 0 + + diff_payload = json.loads(diff_target.read_text(encoding="utf-8")) + impact_payload = json.loads(impact_target.read_text(encoding="utf-8")) + assert diff_payload["output"]["format"] == "process-as-code.semantic-diff" + assert impact_payload["output"]["format"] == "process-as-code.impact" + assert impact_payload["semantic_diff"]["output"] == diff_payload["output"] From e9d840c717d9a0dc05dd029b4bb56115564a6a4e Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:06:32 +0300 Subject: [PATCH 25/29] Advertise versioned outputs to agents --- docs/agent-manifest.json | 93 ++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/docs/agent-manifest.json b/docs/agent-manifest.json index c71c572..5423b68 100644 --- a/docs/agent-manifest.json +++ b/docs/agent-manifest.json @@ -4,20 +4,87 @@ "purpose": "Govern business process change as a versioned contract with semantic diff, impact analysis, policy, generated views, and bounded agent context.", "human_url": "https://dkharlanau.github.io/process-as-code/", "repository": "https://github.com/dkharlanau/process-as-code", - "boundaries": ["not a workflow engine", "not a replacement for full BPMN modeling suites", "do not invent process semantics or ownership", "validate contracts before diff/impact/policy"], - "capabilities": ["validate process contracts", "semantic and visual diff", "change impact analysis", "policy gates", "Mermaid/BPMN/RACI/docs generation", "test-scope generation", "searchable catalog", "external-reference resolution", "MCP process context", "JSON-LD export"], + "boundaries": [ + "not a workflow engine", + "not a replacement for full BPMN modeling suites", + "do not invent process semantics or ownership", + "validate contracts before diff/impact/policy" + ], + "capabilities": [ + "validate process contracts", + "semantic and visual diff", + "change impact analysis", + "policy gates", + "Mermaid/BPMN/RACI/docs generation", + "test-scope generation", + "searchable catalog", + "external-reference resolution", + "MCP process context", + "JSON-LD export", + "versioned diff/impact JSON contracts" + ], "entrypoints": [ - {"type":"cli","command":"process-code validate --strict"}, - {"type":"cli","command":"process-code diff "}, - {"type":"cli","command":"process-code impact "}, - {"type":"cli","command":"process-code policy --policy "}, - {"type":"cli","command":"process-code mcp"} + { + "type": "cli", + "command": "process-code validate --strict" + }, + { + "type": "cli", + "command": "process-code diff " + }, + { + "type": "cli", + "command": "process-code impact " + }, + { + "type": "cli", + "command": "process-code output-schema impact" + }, + { + "type": "cli", + "command": "process-code policy --policy " + }, + { + "type": "cli", + "command": "process-code mcp" + } + ], + "safe_agent_loop": [ + "read process contract and manifest", + "validate", + "inspect semantic diff for changes", + "calculate impact/policy before proposing edits", + "respect step-level agent.exposable/executable/allowed_actions", + "return generated evidence and affected scope" ], - "safe_agent_loop": ["read process contract and manifest", "validate", "inspect semantic diff for changes", "calculate impact/policy before proposing edits", "respect step-level agent.exposable/executable/allowed_actions", "return generated evidence and affected scope"], "related": [ - {"product":"interface-as-code","relationship":"operational contracts referenced by process steps through sandboxed artifact resolution"}, - {"product":"mapping-as-code","relationship":"mapping artifacts resolved for traceability without transform evaluation"}, - {"product":"reconciliation-as-code","relationship":"assurance controls or evidence linked to process and cutover gates"}, - {"product":"decision-tables-as-code","relationship":"governed decision tables referenced by stable ID; Process as Code does not execute them"} - ] + { + "product": "interface-as-code", + "relationship": "operational contracts referenced by process steps through sandboxed artifact resolution" + }, + { + "product": "mapping-as-code", + "relationship": "mapping artifacts resolved for traceability without transform evaluation" + }, + { + "product": "reconciliation-as-code", + "relationship": "assurance controls or evidence linked to process and cutover gates" + }, + { + "product": "decision-tables-as-code", + "relationship": "governed decision tables referenced by stable ID; Process as Code does not execute them" + } + ], + "machine_outputs": { + "semantic_diff": { + "format": "process-as-code.semantic-diff", + "version": "1.0", + "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json" + }, + "impact": { + "format": "process-as-code.impact", + "version": "1.0", + "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json" + } + } } From f9d590c2cf6fdbd103807c0f02578f4f3df65f0b Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:06:34 +0300 Subject: [PATCH 26/29] Expose output contracts on product page --- docs/product.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/product.html b/docs/product.html index 20beb87..89b1f60 100644 --- a/docs/product.html +++ b/docs/product.html @@ -10,5 +10,5 @@ process-code policy examples/customer-creation.process.yaml \ --policy examples/policy.yaml

Designed for coexistence

Process as Code complements BPMN editors, modeling suites, and process-mining tools. It adds a Git-native contract and review layer around the process instead of trying to become another authoring suite.

Not a workflow engine and not a replacement for full BPMN modeling. Use it where process intent has to participate in version control, CI, impact analysis, and agent context.
-
Agent entry point

Governed process context for agents.

The process contract can expose selected steps and allowed actions. MCP and drafting-context commands make the same reviewed process available to agents without turning documentation into an unrestricted tool surface.

DISCOVER

Manifest + schema

agent-manifest.json describes the product surface; the bundled schema defines the process contract.

INSPECT

Diff before acting

Agents can explain current flow and change impact before proposing modifications.

BOUND

Expose allowed actions

Step-level agent metadata distinguishes explainable context from executable capability.

+
Agent entry point

Governed process context for agents.

The process contract can expose selected steps and allowed actions. MCP and drafting-context commands make the same reviewed process available to agents without turning documentation into an unrestricted tool surface.

DISCOVER

Manifest + schemas

agent-manifest.json describes the product surface. The process schema defines input, while versioned output schemas define diff and impact JSON for automation.

INSPECT

Diff before acting

Agents can explain current flow and change impact before proposing modifications.

BOUND

Expose allowed actions

Step-level agent metadata distinguishes explainable context from executable capability.

Put process change where teams can review it.

Start with one process that changes often, version the intent, and let the catalog and impact views come from that source.

Process as Code · part of the Enterprise Transformation Toolkit by Dzmitryi Kharlanau.
From 12e034e0a70afb5743b8d83cf2a86c0617d583d5 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:06:57 +0300 Subject: [PATCH 27/29] Document machine output contract layer --- docs/architecture.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/architecture.md b/docs/architecture.md index cf2d91a..dbeb645 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -24,6 +24,8 @@ YAML/JSON contract The v0.2 JSON Schema describes syntax; Python validation enforces graph and cross-reference invariants. Stable IDs are the semantic backbone for diff, impact, tests, external links and knowledge-graph export. +Semantic diff and impact also expose versioned machine-output contracts. Their JSON payloads carry explicit format/version/schema metadata while preserving the existing top-level data fields. This separates external automation compatibility from internal Python implementation changes. + Graph validation deliberately separates **reachability** from **liveness**. Forward traversal identifies what execution can enter. Reachable edge-less steps define the terminal set. A reverse traversal then determines which reachable steps can eventually reach a terminal. Strongly connected components identify trapped retry/rework cycles that have no terminating path without treating every intentional loop as an error. The validator remains a static contract analyzer: a liveness-clean graph means the declared model contains a terminating path from every reachable branch, not that external workers or systems are guaranteed to complete it. From 8e081425f4f30582adb8e25f656e842cbf97c5f5 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:07:17 +0300 Subject: [PATCH 28/29] Keep impact module formatting consistent --- src/process_as_code/impact.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/process_as_code/impact.py b/src/process_as_code/impact.py index 3889cb3..d3b66fb 100644 --- a/src/process_as_code/impact.py +++ b/src/process_as_code/impact.py @@ -133,6 +133,7 @@ def impact_analysis(old: dict[str, Any], new: dict[str, Any], *, base_dir: str | "semantic_diff": diff, }) + def impact_markdown(result: dict[str, Any]) -> str: lines = ["# Process change impact", "", "## Changed steps", ""] lines += [f"- `{step}`" for step in result["changed_steps"]] or ["No step-level changes."] From e51747ec393f57484fcfe9e44235c4ea68451b30 Mon Sep 17 00:00:00 2001 From: Dzmitryi Kharlanau Date: Tue, 6 Oct 2026 09:08:54 +0300 Subject: [PATCH 29/29] Keep agent manifest diff focused --- docs/agent-manifest.json | 98 ++++++++-------------------------------- 1 file changed, 18 insertions(+), 80 deletions(-) diff --git a/docs/agent-manifest.json b/docs/agent-manifest.json index 5423b68..3d82e91 100644 --- a/docs/agent-manifest.json +++ b/docs/agent-manifest.json @@ -4,87 +4,25 @@ "purpose": "Govern business process change as a versioned contract with semantic diff, impact analysis, policy, generated views, and bounded agent context.", "human_url": "https://dkharlanau.github.io/process-as-code/", "repository": "https://github.com/dkharlanau/process-as-code", - "boundaries": [ - "not a workflow engine", - "not a replacement for full BPMN modeling suites", - "do not invent process semantics or ownership", - "validate contracts before diff/impact/policy" - ], - "capabilities": [ - "validate process contracts", - "semantic and visual diff", - "change impact analysis", - "policy gates", - "Mermaid/BPMN/RACI/docs generation", - "test-scope generation", - "searchable catalog", - "external-reference resolution", - "MCP process context", - "JSON-LD export", - "versioned diff/impact JSON contracts" - ], + "boundaries": ["not a workflow engine", "not a replacement for full BPMN modeling suites", "do not invent process semantics or ownership", "validate contracts before diff/impact/policy"], + "capabilities": ["validate process contracts", "semantic and visual diff", "change impact analysis", "policy gates", "Mermaid/BPMN/RACI/docs generation", "test-scope generation", "searchable catalog", "external-reference resolution", "MCP process context", "JSON-LD export", "versioned diff/impact JSON contracts"], "entrypoints": [ - { - "type": "cli", - "command": "process-code validate --strict" - }, - { - "type": "cli", - "command": "process-code diff " - }, - { - "type": "cli", - "command": "process-code impact " - }, - { - "type": "cli", - "command": "process-code output-schema impact" - }, - { - "type": "cli", - "command": "process-code policy --policy " - }, - { - "type": "cli", - "command": "process-code mcp" - } - ], - "safe_agent_loop": [ - "read process contract and manifest", - "validate", - "inspect semantic diff for changes", - "calculate impact/policy before proposing edits", - "respect step-level agent.exposable/executable/allowed_actions", - "return generated evidence and affected scope" - ], - "related": [ - { - "product": "interface-as-code", - "relationship": "operational contracts referenced by process steps through sandboxed artifact resolution" - }, - { - "product": "mapping-as-code", - "relationship": "mapping artifacts resolved for traceability without transform evaluation" - }, - { - "product": "reconciliation-as-code", - "relationship": "assurance controls or evidence linked to process and cutover gates" - }, - { - "product": "decision-tables-as-code", - "relationship": "governed decision tables referenced by stable ID; Process as Code does not execute them" - } + {"type":"cli","command":"process-code validate --strict"}, + {"type":"cli","command":"process-code diff "}, + {"type":"cli","command":"process-code impact "}, + {"type":"cli","command":"process-code output-schema impact"}, + {"type":"cli","command":"process-code policy --policy "}, + {"type":"cli","command":"process-code mcp"} ], + "safe_agent_loop": ["read process contract and manifest", "validate", "inspect semantic diff for changes", "calculate impact/policy before proposing edits", "respect step-level agent.exposable/executable/allowed_actions", "return generated evidence and affected scope"], "machine_outputs": { - "semantic_diff": { - "format": "process-as-code.semantic-diff", - "version": "1.0", - "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json" - }, - "impact": { - "format": "process-as-code.impact", - "version": "1.0", - "schema": "https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json" - } - } + "semantic_diff": {"format":"process-as-code.semantic-diff","version":"1.0","schema":"https://dkharlanau.github.io/process-as-code/schemas/outputs/semantic-diff-v1.schema.json"}, + "impact": {"format":"process-as-code.impact","version":"1.0","schema":"https://dkharlanau.github.io/process-as-code/schemas/outputs/impact-v1.schema.json"} + }, + "related": [ + {"product":"interface-as-code","relationship":"operational contracts referenced by process steps through sandboxed artifact resolution"}, + {"product":"mapping-as-code","relationship":"mapping artifacts resolved for traceability without transform evaluation"}, + {"product":"reconciliation-as-code","relationship":"assurance controls or evidence linked to process and cutover gates"}, + {"product":"decision-tables-as-code","relationship":"governed decision tables referenced by stable ID; Process as Code does not execute them"} + ] }