pgc-runtime 5.0.0__tar.gz → 7.0.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 (39) hide show
  1. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/NOTICE +1 -1
  2. {pgc_runtime-5.0.0/pgc_runtime.egg-info → pgc_runtime-7.0.0}/PKG-INFO +14 -18
  3. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/README.md +12 -14
  4. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0/pgc_runtime.egg-info}/PKG-INFO +14 -18
  5. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pgc_runtime.egg-info/SOURCES.txt +0 -1
  6. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pgc_runtime.egg-info/requires.txt +0 -3
  7. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pyproject.toml +2 -5
  8. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/api.py +6 -3
  9. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/boot.py +3 -3
  10. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/cli.py +0 -75
  11. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/conformance.py +34 -2
  12. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/coordinator.py +1 -1
  13. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/ct_execute.py +3 -12
  14. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/ct_executor.py +89 -116
  15. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/dispatcher.py +198 -87
  16. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/evidence.py +23 -7
  17. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/examine/__init__.py +1 -1
  18. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/examine/parser.py +3 -4
  19. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/__init__.py +1 -1
  20. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/defaults.py +1 -1
  21. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/memory.py +40 -23
  22. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/scheduler.py +29 -11
  23. pgc_runtime-5.0.0/runtime/trace_viz.py +0 -233
  24. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/LICENSE +0 -0
  25. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/MANIFEST.in +0 -0
  26. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pgc_runtime.egg-info/dependency_links.txt +0 -0
  27. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pgc_runtime.egg-info/entry_points.txt +0 -0
  28. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/pgc_runtime.egg-info/top_level.txt +0 -0
  29. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/__init__.py +0 -0
  30. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/ct_errors.py +0 -0
  31. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/examine/cli.py +0 -0
  32. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/examine/reporter.py +0 -0
  33. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/client.py +0 -0
  34. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/coordinator.py +0 -0
  35. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/store.py +0 -0
  36. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/federation/worker.py +0 -0
  37. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/loader.py +0 -0
  38. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/runtime/replay.py +0 -0
  39. {pgc_runtime-5.0.0 → pgc_runtime-7.0.0}/setup.cfg +0 -0
@@ -1,4 +1,4 @@
1
- PGS — Protocol-Governed Systems
1
+ PGC — Protocol-Governed Computing
2
2
  Copyright 2026 Bhash Ganti aka Bachi
3
3
 
4
4
  This project introduces a protocol-first execution model in which:
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pgc-runtime
3
- Version: 5.0.0
3
+ Version: 7.0.0
4
4
  Summary: PGC protocol runtime — executes a sealed snapshot as governed DAG traversal and emits traces (import package: runtime)
5
5
  Author-email: Bhash Ganti <bachipeachy@gmail.com>
6
6
  License-Expression: Apache-2.0
7
7
  Project-URL: Homepage, https://omnibachi.org/
8
8
  Project-URL: Repository, https://github.com/protocol-governed-computing/protocol_runtime
9
- Project-URL: Standard, https://doi.org/10.5281/zenodo.22150616
9
+ Project-URL: Standard, https://doi.org/10.5281/zenodo.22150615
10
10
  Keywords: protocol-governed-computing,pgc,protocol,runtime,workflow,execution
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
@@ -22,8 +22,6 @@ License-File: LICENSE
22
22
  License-File: NOTICE
23
23
  Provides-Extra: reference
24
24
  Requires-Dist: pgc-governance>=2.0.0; extra == "reference"
25
- Provides-Extra: render
26
- Requires-Dist: pgc-inspector>=5.0.0; extra == "render"
27
25
  Dynamic: license-file
28
26
 
29
27
  # protocol_runtime
@@ -85,9 +83,7 @@ the data root:
85
83
 
86
84
  ```
87
85
  <data-root>/traces/<domain>/<WF>/<TRACE_ID>/
88
- <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V1 event per line
89
- <TRACE_ID>.png the path the run took, drawn only on request (`run --behavior-logic`,
90
- or `behavior-logic <trace>`)
86
+ <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V0 event per line
91
87
 
92
88
  <data-root>/<domain>/<subdomain>/
93
89
  the stores the domain's runtime binding declares
@@ -113,7 +109,6 @@ the data root:
113
109
  | `coordinator` | serve as the coordinating node of a federated node group |
114
110
  | `worker` | serve as a worker node of a federated node group |
115
111
  | `examine` | read a completed trace: its path by node, contracts, results, events and errors |
116
- | `behavior-logic` | render a completed trace as a PNG: the path, each route's outcome, and why each node decided as far as the trace records it (drawn from the inspector's `si.execution.explain`; needs `pgc-runtime[render]`) |
117
112
 
118
113
  `PGC_SNAPSHOT_ROOT` overrides the snapshot location; `PGC_IMPL_ROOTS` is the colon-separated set of
119
114
  roots on `PYTHONPATH` for domain capability implementations.
@@ -172,7 +167,7 @@ Apache-2.0. See `LICENSE` and `NOTICE`.
172
167
  | `pgc-assembler` | `snapshot_assembler` | projections → sealed snapshot |
173
168
  | `pgc-runtime` | `protocol_runtime` | snapshot → governed execution |
174
169
  | `pgc-inspector` | `snapshot_inspector` | snapshot → read-only inspection |
175
- | `pgc-transformation` | `transformation` | change request → protocol artifacts |
170
+ | `pgc-transformation` | `transformation_compilers` | change request → protocol artifacts |
176
171
  | `pgc-governance` | `software_governance` | the governance surface and its capability implementations |
177
172
  | `pgc-workloads` | `conformance_workloads` | the workloads that make conformance observable |
178
173
  | `pgc-domains` | `business_domains` | the business domain implementations the composed snapshot binds |
@@ -204,15 +199,16 @@ assembler and the runtime alike.
204
199
  The full sequence, with the repositories it needs, is in
205
200
  [`pgc_install`](https://github.com/protocol-governed-computing/pgc_install).
206
201
 
207
- **Versioning.** Two schemes, and the published version follows the second.
202
+ **Versioning.** Two numbers name two different things.
208
203
 
209
- - **Internal** — each repository's `VERSION` file, a monotonic composition ordinal. PGC versions the
210
- composition rather than each repo: they release together and the governance closure forces lockstep,
211
- so the ordinal names which composition a repo belongs to. Development happens on `dev/<N>` and each
212
- cycle is tagged `release-<N>`. This is not published.
213
- - **Public** — `PUBLIC_VERSION`, tagged on every component repository. The platform is at **`v3`**.
204
+ - **Published** — this distribution's `version` in `pyproject.toml`. It moves on its own. A release
205
+ that changes this repository bumps it, and a release that leaves the repository unchanged keeps it.
206
+ - **Composition** — the public identity (`v6`, …) names one composition of the whole family.
207
+ `pgc_release` records which version of each distribution that composition holds, and `pgc_install`
208
+ pins exactly those versions.
214
209
 
215
- **The published version is the public one: `v4` is `4.0.0`.** The standard the packages implement is a
216
- separate artifact on its own track and is not this number.
210
+ Each repository's `VERSION` file holds the workspace's cycle ordinal, which names the `dev/<N>`
211
+ branch. It is development accounting, and it is never published. The standard the packages
212
+ implement is a separate artifact on its own track, and none of these numbers is its revision.
217
213
 
218
- The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150616
214
+ The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150615
@@ -57,9 +57,7 @@ the data root:
57
57
 
58
58
  ```
59
59
  <data-root>/traces/<domain>/<WF>/<TRACE_ID>/
60
- <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V1 event per line
61
- <TRACE_ID>.png the path the run took, drawn only on request (`run --behavior-logic`,
62
- or `behavior-logic <trace>`)
60
+ <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V0 event per line
63
61
 
64
62
  <data-root>/<domain>/<subdomain>/
65
63
  the stores the domain's runtime binding declares
@@ -85,7 +83,6 @@ the data root:
85
83
  | `coordinator` | serve as the coordinating node of a federated node group |
86
84
  | `worker` | serve as a worker node of a federated node group |
87
85
  | `examine` | read a completed trace: its path by node, contracts, results, events and errors |
88
- | `behavior-logic` | render a completed trace as a PNG: the path, each route's outcome, and why each node decided as far as the trace records it (drawn from the inspector's `si.execution.explain`; needs `pgc-runtime[render]`) |
89
86
 
90
87
  `PGC_SNAPSHOT_ROOT` overrides the snapshot location; `PGC_IMPL_ROOTS` is the colon-separated set of
91
88
  roots on `PYTHONPATH` for domain capability implementations.
@@ -144,7 +141,7 @@ Apache-2.0. See `LICENSE` and `NOTICE`.
144
141
  | `pgc-assembler` | `snapshot_assembler` | projections → sealed snapshot |
145
142
  | `pgc-runtime` | `protocol_runtime` | snapshot → governed execution |
146
143
  | `pgc-inspector` | `snapshot_inspector` | snapshot → read-only inspection |
147
- | `pgc-transformation` | `transformation` | change request → protocol artifacts |
144
+ | `pgc-transformation` | `transformation_compilers` | change request → protocol artifacts |
148
145
  | `pgc-governance` | `software_governance` | the governance surface and its capability implementations |
149
146
  | `pgc-workloads` | `conformance_workloads` | the workloads that make conformance observable |
150
147
  | `pgc-domains` | `business_domains` | the business domain implementations the composed snapshot binds |
@@ -176,15 +173,16 @@ assembler and the runtime alike.
176
173
  The full sequence, with the repositories it needs, is in
177
174
  [`pgc_install`](https://github.com/protocol-governed-computing/pgc_install).
178
175
 
179
- **Versioning.** Two schemes, and the published version follows the second.
176
+ **Versioning.** Two numbers name two different things.
180
177
 
181
- - **Internal** — each repository's `VERSION` file, a monotonic composition ordinal. PGC versions the
182
- composition rather than each repo: they release together and the governance closure forces lockstep,
183
- so the ordinal names which composition a repo belongs to. Development happens on `dev/<N>` and each
184
- cycle is tagged `release-<N>`. This is not published.
185
- - **Public** — `PUBLIC_VERSION`, tagged on every component repository. The platform is at **`v3`**.
178
+ - **Published** — this distribution's `version` in `pyproject.toml`. It moves on its own. A release
179
+ that changes this repository bumps it, and a release that leaves the repository unchanged keeps it.
180
+ - **Composition** — the public identity (`v6`, …) names one composition of the whole family.
181
+ `pgc_release` records which version of each distribution that composition holds, and `pgc_install`
182
+ pins exactly those versions.
186
183
 
187
- **The published version is the public one: `v4` is `4.0.0`.** The standard the packages implement is a
188
- separate artifact on its own track and is not this number.
184
+ Each repository's `VERSION` file holds the workspace's cycle ordinal, which names the `dev/<N>`
185
+ branch. It is development accounting, and it is never published. The standard the packages
186
+ implement is a separate artifact on its own track, and none of these numbers is its revision.
189
187
 
190
- The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150616
188
+ The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150615
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pgc-runtime
3
- Version: 5.0.0
3
+ Version: 7.0.0
4
4
  Summary: PGC protocol runtime — executes a sealed snapshot as governed DAG traversal and emits traces (import package: runtime)
5
5
  Author-email: Bhash Ganti <bachipeachy@gmail.com>
6
6
  License-Expression: Apache-2.0
7
7
  Project-URL: Homepage, https://omnibachi.org/
8
8
  Project-URL: Repository, https://github.com/protocol-governed-computing/protocol_runtime
9
- Project-URL: Standard, https://doi.org/10.5281/zenodo.22150616
9
+ Project-URL: Standard, https://doi.org/10.5281/zenodo.22150615
10
10
  Keywords: protocol-governed-computing,pgc,protocol,runtime,workflow,execution
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
@@ -22,8 +22,6 @@ License-File: LICENSE
22
22
  License-File: NOTICE
23
23
  Provides-Extra: reference
24
24
  Requires-Dist: pgc-governance>=2.0.0; extra == "reference"
25
- Provides-Extra: render
26
- Requires-Dist: pgc-inspector>=5.0.0; extra == "render"
27
25
  Dynamic: license-file
28
26
 
29
27
  # protocol_runtime
@@ -85,9 +83,7 @@ the data root:
85
83
 
86
84
  ```
87
85
  <data-root>/traces/<domain>/<WF>/<TRACE_ID>/
88
- <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V1 event per line
89
- <TRACE_ID>.png the path the run took, drawn only on request (`run --behavior-logic`,
90
- or `behavior-logic <trace>`)
86
+ <TRACE_ID>.jsonl append-only execution log, one SCHEMA_TRACE_EVENT_V0 event per line
91
87
 
92
88
  <data-root>/<domain>/<subdomain>/
93
89
  the stores the domain's runtime binding declares
@@ -113,7 +109,6 @@ the data root:
113
109
  | `coordinator` | serve as the coordinating node of a federated node group |
114
110
  | `worker` | serve as a worker node of a federated node group |
115
111
  | `examine` | read a completed trace: its path by node, contracts, results, events and errors |
116
- | `behavior-logic` | render a completed trace as a PNG: the path, each route's outcome, and why each node decided as far as the trace records it (drawn from the inspector's `si.execution.explain`; needs `pgc-runtime[render]`) |
117
112
 
118
113
  `PGC_SNAPSHOT_ROOT` overrides the snapshot location; `PGC_IMPL_ROOTS` is the colon-separated set of
119
114
  roots on `PYTHONPATH` for domain capability implementations.
@@ -172,7 +167,7 @@ Apache-2.0. See `LICENSE` and `NOTICE`.
172
167
  | `pgc-assembler` | `snapshot_assembler` | projections → sealed snapshot |
173
168
  | `pgc-runtime` | `protocol_runtime` | snapshot → governed execution |
174
169
  | `pgc-inspector` | `snapshot_inspector` | snapshot → read-only inspection |
175
- | `pgc-transformation` | `transformation` | change request → protocol artifacts |
170
+ | `pgc-transformation` | `transformation_compilers` | change request → protocol artifacts |
176
171
  | `pgc-governance` | `software_governance` | the governance surface and its capability implementations |
177
172
  | `pgc-workloads` | `conformance_workloads` | the workloads that make conformance observable |
178
173
  | `pgc-domains` | `business_domains` | the business domain implementations the composed snapshot binds |
@@ -204,15 +199,16 @@ assembler and the runtime alike.
204
199
  The full sequence, with the repositories it needs, is in
205
200
  [`pgc_install`](https://github.com/protocol-governed-computing/pgc_install).
206
201
 
207
- **Versioning.** Two schemes, and the published version follows the second.
202
+ **Versioning.** Two numbers name two different things.
208
203
 
209
- - **Internal** — each repository's `VERSION` file, a monotonic composition ordinal. PGC versions the
210
- composition rather than each repo: they release together and the governance closure forces lockstep,
211
- so the ordinal names which composition a repo belongs to. Development happens on `dev/<N>` and each
212
- cycle is tagged `release-<N>`. This is not published.
213
- - **Public** — `PUBLIC_VERSION`, tagged on every component repository. The platform is at **`v3`**.
204
+ - **Published** — this distribution's `version` in `pyproject.toml`. It moves on its own. A release
205
+ that changes this repository bumps it, and a release that leaves the repository unchanged keeps it.
206
+ - **Composition** — the public identity (`v6`, …) names one composition of the whole family.
207
+ `pgc_release` records which version of each distribution that composition holds, and `pgc_install`
208
+ pins exactly those versions.
214
209
 
215
- **The published version is the public one: `v4` is `4.0.0`.** The standard the packages implement is a
216
- separate artifact on its own track and is not this number.
210
+ Each repository's `VERSION` file holds the workspace's cycle ordinal, which names the `dev/<N>`
211
+ branch. It is development accounting, and it is never published. The standard the packages
212
+ implement is a separate artifact on its own track, and none of these numbers is its revision.
217
213
 
218
- The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150616
214
+ The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150615
@@ -24,7 +24,6 @@ runtime/loader.py
24
24
  runtime/memory.py
25
25
  runtime/replay.py
26
26
  runtime/scheduler.py
27
- runtime/trace_viz.py
28
27
  runtime/examine/__init__.py
29
28
  runtime/examine/cli.py
30
29
  runtime/examine/parser.py
@@ -1,6 +1,3 @@
1
1
 
2
2
  [reference]
3
3
  pgc-governance>=2.0.0
4
-
5
- [render]
6
- pgc-inspector>=5.0.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pgc-runtime"
7
- version = "5.0.0"
7
+ version = "7.0.0"
8
8
  description = "PGC protocol runtime — executes a sealed snapshot as governed DAG traversal and emits traces (import package: runtime)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -32,9 +32,6 @@ dependencies = []
32
32
 
33
33
  [project.optional-dependencies]
34
34
  reference = ["pgc-governance>=2.0.0"]
35
- # The PNG projection (`--behavior-logic`, `behavior-logic`) draws the inspector's explanation of a
36
- # run. Execution never imports the inspector; only `runtime.trace_viz` does.
37
- render = ["pgc-inspector>=5.0.0"]
38
35
 
39
36
  [project.scripts]
40
37
  protocol_runtime = "runtime.cli:main"
@@ -42,7 +39,7 @@ protocol_runtime = "runtime.cli:main"
42
39
  [project.urls]
43
40
  Homepage = "https://omnibachi.org/"
44
41
  Repository = "https://github.com/protocol-governed-computing/protocol_runtime"
45
- Standard = "https://doi.org/10.5281/zenodo.22150616"
42
+ Standard = "https://doi.org/10.5281/zenodo.22150615"
46
43
 
47
44
  [tool.setuptools]
48
45
  include-package-data = false
@@ -16,7 +16,7 @@ from pathlib import Path
16
16
  from typing import Any
17
17
 
18
18
  from runtime.boot import BootedSnapshot, boot, default_snapshot_root
19
- from runtime.evidence import TraceWriter, make_trace_id
19
+ from runtime.evidence import RecordedRefusal, TraceWriter, make_trace_id
20
20
  from runtime.scheduler import run_wf
21
21
 
22
22
 
@@ -71,12 +71,15 @@ def run_workflow(
71
71
  try:
72
72
  status, surface = run_wf(wf_fqdn=wf_fqdn, payload=payload, pkg=pkg,
73
73
  writer=writer, data_root=str(data_root))
74
+ except RecordedRefusal:
75
+ # Recorded where it was determined; recording it again here would count it twice.
76
+ raise
74
77
  except Exception as exc:
75
78
  writer.error(str(exc))
76
79
  raise
77
80
  finally:
78
- # The JSONL is the evidence. A picture of the path is a view of it, drawn on request
79
- # (`run --behavior-logic`, or `behavior-logic <trace>`), never as a cost of every run.
81
+ # The JSONL is the evidence. A drawing of the path is a view of it, made by the inspector
82
+ # on request, never by the runtime and never as a cost of every run.
80
83
  writer.close()
81
84
 
82
85
  return RunResult(status=status, surface=surface or {}, trace_id=trace_id, trace_dir=trace_dir)
@@ -91,9 +91,9 @@ def boot(snapshot_root: str | Path | None = None) -> BootedSnapshot:
91
91
 
92
92
  # 2. ACCEPTANCE — all four conditions of `3b` §7, established from content.
93
93
  #
94
- # The runtime does not carry its own weaker copy of this. It previously recomputed the composite
95
- # over the manifest's RECORDED per-domain hashes, which detects a tampered manifest and not a
96
- # tampered constituent — and a snapshot with an edited projection booted and reported healthy.
94
+ # The runtime does not carry its own weaker copy of this. A composite over the manifest's RECORDED
95
+ # per-domain hashes detects a tampered manifest and not a tampered constituent: a snapshot with an
96
+ # edited projection would boot and report healthy.
97
97
  # `assembler.core.verify_snapshot` recomputes every constituent from its bytes; there is one
98
98
  # acceptance determination and both the assembler and the runtime reach it.
99
99
  #
@@ -4,7 +4,6 @@ cli.py — Token-native CLI entry point for the runtime.
4
4
  Commands:
5
5
  run — Execute a workflow against the tokenized snapshot.
6
6
  examine — Analyze a completed trace file and print a diagnostic report.
7
- behavior-logic — Render a completed trace, explained, over its workflow graph (PNG).
8
7
 
9
8
  Execution path (run):
10
9
  1. Load tokenized snapshot for the domain via loader.load_domain()
@@ -13,7 +12,6 @@ Execution path (run):
13
12
  3. Open TraceWriter at traces/<domain>/<wf_code>/<trace_id>/
14
13
  4. Drive workflow topology via scheduler.run_wf()
15
14
  5. Print result summary; exit 1 on non-SUCCESS
16
- 6. If --behavior-logic: render the explained run as a PNG (trace_viz, a client of the inspector)
17
15
 
18
16
  All runtime behavior comes from the compiled tokenized_snapshot.
19
17
  The CLI does not implement any domain logic.
@@ -72,14 +70,6 @@ def _build_parser() -> argparse.ArgumentParser:
72
70
  "Default: sibling ../snapshot",
73
71
  )
74
72
 
75
- # ── run: optional behavior-logic flag ────────────────────────
76
- run_p.add_argument(
77
- "--behavior-logic",
78
- action="store_true",
79
- dest="behavior_logic",
80
- help="Render execution-path PNG after run (requires graphviz)",
81
- )
82
-
83
73
  # ── replay ────────────────────────────────────────────────────
84
74
  rp_p = subs.add_parser(
85
75
  "replay",
@@ -136,23 +126,6 @@ def _build_parser() -> argparse.ArgumentParser:
136
126
  help="Path to a completed .jsonl trace file",
137
127
  )
138
128
 
139
- # ── behavior-logic ────────────────────────────────────────────
140
- bl_p = subs.add_parser(
141
- "behavior-logic",
142
- help="Render execution-path PNG from a completed trace file",
143
- )
144
- bl_p.add_argument(
145
- "trace_file",
146
- metavar="FILE",
147
- help="Path to a completed .jsonl trace file",
148
- )
149
- bl_p.add_argument(
150
- "--snapshot",
151
- metavar="PATH",
152
- help="Absolute path to the assembled snapshot the trace ran against "
153
- "(or set PGC_SNAPSHOT_ROOT; default: the sibling ../snapshot)",
154
- )
155
-
156
129
  return parser
157
130
 
158
131
 
@@ -208,12 +181,6 @@ def _handle_run(args: argparse.Namespace) -> None:
208
181
  print(f"[runtime] Trace dir: {trace_dir}")
209
182
  print()
210
183
 
211
- # Evidence projection: render execution-path PNG if requested
212
- trace_path = trace_dir / f"{trace_id}.jsonl"
213
- png_path = None
214
- if args.behavior_logic:
215
- png_path = _render_behavior_logic(snapshot_root, trace_path, trace_root=data_root)
216
-
217
184
  print("=" * 60)
218
185
  print("[runtime] Workflow Complete")
219
186
  print("=" * 60)
@@ -224,10 +191,6 @@ def _handle_run(args: argparse.Namespace) -> None:
224
191
  if surface:
225
192
  print("Output:")
226
193
  print(_format_surface(surface))
227
- if png_path:
228
- print(f"Graph: {png_path}")
229
- elif args.behavior_logic:
230
- print("Graph: (graphviz not available — PNG skipped)")
231
194
  print("=" * 60)
232
195
 
233
196
  if result_status not in ("SUCCESS", "ALREADY_EXISTS"):
@@ -341,27 +304,6 @@ def _health_line(snapshot_root: Path, booted) -> str:
341
304
  return f"[runtime] ✓ Snapshot healthy — {n} domain(s) resident and hash-verified{gov}. No issues."
342
305
 
343
306
 
344
- def _handle_behavior_logic(args: argparse.Namespace) -> None:
345
- trace_path = Path(args.trace_file)
346
- if not trace_path.exists():
347
- _fatal(f"Trace file not found: {args.trace_file}")
348
-
349
- snapshot_str = args.snapshot or os.environ.get("PGC_SNAPSHOT_ROOT")
350
- snapshot_root = Path(snapshot_str) if snapshot_str else default_snapshot_root()
351
- if not snapshot_root.is_absolute():
352
- _fatal(f"--snapshot must be an absolute path, got: {snapshot_str}")
353
-
354
- png_path = _render_behavior_logic(snapshot_root, trace_path)
355
- if png_path:
356
- print(f"[runtime] Execution path PNG: {png_path}")
357
- else:
358
- print(
359
- "[runtime] Behavior logic render skipped — graphviz (dot) not available.",
360
- file=sys.stderr,
361
- )
362
- sys.exit(1)
363
-
364
-
365
307
  def _handle_examine(args: argparse.Namespace) -> None:
366
308
  trace_path = Path(args.trace_file)
367
309
  if not trace_path.exists():
@@ -391,21 +333,6 @@ def _handle_examine(args: argparse.Namespace) -> None:
391
333
  # Utilities
392
334
  # ---------------------------------------------------------------------------
393
335
 
394
- def _render_behavior_logic(snapshot_root: Path, trace_path: Path,
395
- trace_root: Path | None = None) -> "Path | None":
396
- """Render the explained run as a PNG. Best-effort: a refusal is reported, never drawn around."""
397
- from runtime.trace_viz import render_trace_png
398
- try:
399
- return render_trace_png(snapshot_root, trace_path, trace_root=trace_root)
400
- except ModuleNotFoundError as exc:
401
- print(f"[runtime] Behavior logic render needs the snapshot inspector "
402
- f"(pgc-runtime[render]): {exc}", file=sys.stderr)
403
- return None
404
- except (FileNotFoundError, ValueError) as exc:
405
- print(f"[runtime] Behavior logic render error: {exc}", file=sys.stderr)
406
- return None
407
-
408
-
409
336
  def _load_payload(payload_path: str | None) -> dict:
410
337
  if not payload_path:
411
338
  return {}
@@ -500,8 +427,6 @@ def main() -> None:
500
427
  _handle_worker(args)
501
428
  elif args.command == "examine":
502
429
  _handle_examine(args)
503
- elif args.command == "behavior-logic":
504
- _handle_behavior_logic(args)
505
430
 
506
431
 
507
432
  if __name__ == "__main__":
@@ -6,7 +6,7 @@ the composition sealed it. This runs every case of one build and reports every t
6
6
  supplies as **proven** (every case ran and passed), **unproven** (no vector tests it) or **refused** (a
7
7
  case failed). It never reports success over nothing: a build with no vector is reported, by name, as
8
8
  unproven. The build is a domain's, or the platform's for the transforms the platform supplies.
9
- Governed by `conformance::CONSTITUTION_TEST_DATA_V2`.
9
+ Governed by `conformance::CONSTITUTION_TEST_DATA_V0`.
10
10
 
11
11
  What a build supplies and what it only carries is read from the capabilities its attestation records
12
12
  as imported, never from a transform's name: a carried copy is byte-identical to its supplier's, and the
@@ -27,7 +27,7 @@ from dataclasses import dataclass, field
27
27
  from pathlib import Path
28
28
  from typing import Any
29
29
 
30
- from runtime.ct_executor import CTArtifactNotFound, CTExecutor, CTExecutionError
30
+ from runtime.ct_executor import CTArtifactNotFound, CTExecutor, CTExecutionError, CTFault
31
31
 
32
32
  NONDETERMINISTIC_PURITY = "ct_impure"
33
33
  # Where a build's result is written, beside its compiled projections, so the assembler carries it into
@@ -201,6 +201,31 @@ def _resolve_outputs(ct_ir: dict[str, Any], vars_result: dict[str, Any]) -> dict
201
201
  return actual
202
202
 
203
203
 
204
+ def _undeclared_result(ct_ir: dict[str, Any], vars_result: dict[str, Any]) -> str | None:
205
+ """Say how a completed run's result differs from the outputs the transform declares, if it does.
206
+
207
+ A result read field by field carries exactly the outputs read from it: a key no output names is an
208
+ answer nothing declared, and a declared output it lacks is one the case could only compare against
209
+ the whole result. A result read as one output's value is that value, whatever it holds.
210
+ """
211
+ groups: dict[str, set[str]] = {}
212
+ for output_key, output_spec in (ct_ir.get("outputs") or {}).items():
213
+ groups.setdefault(output_spec.get("from"), set()).add(output_key)
214
+ for from_var, keys in sorted(groups.items(), key=lambda g: str(g[0])):
215
+ if from_var not in vars_result:
216
+ return f"no step produced {from_var!r}, which outputs {sorted(keys)} are read from"
217
+ source = vars_result[from_var]
218
+ if not isinstance(source, dict) or not keys & set(source):
219
+ if len(keys) == 1:
220
+ continue
221
+ return f"{from_var!r} carries none of the declared outputs {sorted(keys)}"
222
+ if set(source) != keys:
223
+ missing, extra = sorted(keys - set(source)), sorted(set(source) - keys)
224
+ return (f"{from_var!r} differs from the declared outputs"
225
+ f"{f' — lacks {missing}' if missing else ''}{f' — undeclared {extra}' if extra else ''}")
226
+ return None
227
+
228
+
204
229
  def _canonical(compiled: Path, kind_dir: str) -> list[dict[str, Any]]:
205
230
  folder = compiled / "canonical" / kind_dir
206
231
  return [json.loads(p.read_text()) for p in sorted(folder.glob("*.json"))] if folder.is_dir() else []
@@ -251,6 +276,10 @@ def _run_case(executor: CTExecutor, case: dict[str, Any]) -> CaseResult:
251
276
  # VIOLATION case by accident. A transform whose implementation is absent is refused and named,
252
277
  # which is a result; escaping as a crash names nothing and stops the other cases.
253
278
  return CaseResult(fqdn, False, f"implementation not present: {e}")
279
+ except CTFault as e:
280
+ # A fault is not the transform's judgement: it fails the case whatever the case expected,
281
+ # so a VIOLATION case is never passed by a transform that broke rather than refused.
282
+ return CaseResult(fqdn, False, f"fault, not a refusal: {e}")
254
283
  except CTExecutionError as e:
255
284
  # A refusal the case expected passes — unless it was the runner refusing a missing record,
256
285
  # which is a defect in the case, not the transform's judgement.
@@ -268,6 +297,9 @@ def _run_case(executor: CTExecutor, case: dict[str, Any]) -> CaseResult:
268
297
  if unused:
269
298
  return CaseResult(fqdn, False, f"recorded results no step used: {unused}")
270
299
 
300
+ undeclared = _undeclared_result(ct_ir, vars_result)
301
+ if undeclared:
302
+ return CaseResult(fqdn, False, f"result differs from the declared outputs: {undeclared}")
271
303
  actual = _resolve_outputs(ct_ir, vars_result)
272
304
  assertion_error = _assert_structural(actual, assertions) if assertions else None
273
305
  if assertion_error:
@@ -1,6 +1,6 @@
1
1
  """A coordinating party that runs several runtimes.
2
2
 
3
- `CONSTITUTION_EXECUTION_PLACEMENT_V1` authorizes `LOCAL_MULTI_WORKER`: more than one worker process
3
+ `CONSTITUTION_EXECUTION_PLACEMENT_V0` authorizes `LOCAL_MULTI_WORKER`: more than one worker process
4
4
  on one host, each drawing work from a coordinating party and executing a governed topology in its
5
5
  own process. This is that party.
6
6
 
@@ -6,8 +6,7 @@ Adapter between the dispatcher and CTExecutor.
6
6
 
7
7
  from typing import Any
8
8
 
9
- from runtime.ct_errors import StructuredError
10
- from runtime.ct_executor import CTExecutor
9
+ from runtime.ct_executor import CTExecutor, CTFault
11
10
 
12
11
  # Module-level executor singleton — avoids re-creating per call,
13
12
  # preserves federated IR directory cache and atom loading.
@@ -48,11 +47,7 @@ def execute_ct(ct_ir: dict[str, Any], inputs: dict[str, Any], observer=None, rec
48
47
  # ---- Output adaptation ----
49
48
  outputs = ct_ir.get("outputs")
50
49
  if not outputs:
51
- raise StructuredError(
52
- error_code="CT_EXECUTION_FAILED",
53
- node_category="CT",
54
- message="CT must declare at least one output",
55
- )
50
+ raise CTFault("CT must declare at least one output")
56
51
 
57
52
  # Build CT outputs by mapping from symbol table
58
53
  ct_outputs = {}
@@ -60,11 +55,7 @@ def execute_ct(ct_ir: dict[str, Any], inputs: dict[str, Any], observer=None, rec
60
55
  from_symbol = spec["from"]
61
56
 
62
57
  if from_symbol not in symbol_table:
63
- raise StructuredError(
64
- error_code="CT_EXECUTION_FAILED",
65
- node_category="CT",
66
- message=f"CT output symbol '{from_symbol}' was not produced by CT execution",
67
- )
58
+ raise CTFault(f"CT output symbol '{from_symbol}' was not produced by CT execution")
68
59
 
69
60
  symbol_value = symbol_table[from_symbol]
70
61