pgc-inspector 2.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 (38) hide show
  1. pgc_inspector-2.0.0/LICENSE +67 -0
  2. pgc_inspector-2.0.0/NOTICE +11 -0
  3. pgc_inspector-2.0.0/PKG-INFO +223 -0
  4. pgc_inspector-2.0.0/README.md +199 -0
  5. pgc_inspector-2.0.0/inspector/__init__.py +17 -0
  6. pgc_inspector-2.0.0/inspector/__main__.py +7 -0
  7. pgc_inspector-2.0.0/inspector/api.py +94 -0
  8. pgc_inspector-2.0.0/inspector/catalog.py +135 -0
  9. pgc_inspector-2.0.0/inspector/cli.py +265 -0
  10. pgc_inspector-2.0.0/inspector/graph.py +138 -0
  11. pgc_inspector-2.0.0/inspector/kinds.py +19 -0
  12. pgc_inspector-2.0.0/inspector/queries/__init__.py +8 -0
  13. pgc_inspector-2.0.0/inspector/queries/artifact_refs.py +40 -0
  14. pgc_inspector-2.0.0/inspector/queries/snapshot_validate.py +221 -0
  15. pgc_inspector-2.0.0/inspector/queries/topology_impact.py +39 -0
  16. pgc_inspector-2.0.0/inspector/reads/__init__.py +5 -0
  17. pgc_inspector-2.0.0/inspector/reads/artifact_indexed.py +22 -0
  18. pgc_inspector-2.0.0/inspector/reads/artifact_list.py +53 -0
  19. pgc_inspector-2.0.0/inspector/reads/artifact_show.py +30 -0
  20. pgc_inspector-2.0.0/inspector/reads/behavior_logic_list.py +29 -0
  21. pgc_inspector-2.0.0/inspector/reads/behavior_logic_show.py +36 -0
  22. pgc_inspector-2.0.0/inspector/reads/capability_surface.py +151 -0
  23. pgc_inspector-2.0.0/inspector/reads/catalog.py +42 -0
  24. pgc_inspector-2.0.0/inspector/reads/rule_set_list.py +84 -0
  25. pgc_inspector-2.0.0/inspector/reads/snapshot_summary.py +71 -0
  26. pgc_inspector-2.0.0/inspector/reads/snapshot_topology.py +37 -0
  27. pgc_inspector-2.0.0/inspector/reads/store_reads.py +112 -0
  28. pgc_inspector-2.0.0/inspector/reads/vocab_resolve.py +66 -0
  29. pgc_inspector-2.0.0/inspector/reads/vocab_search.py +41 -0
  30. pgc_inspector-2.0.0/inspector/registry.py +97 -0
  31. pgc_inspector-2.0.0/inspector/snapshot.py +175 -0
  32. pgc_inspector-2.0.0/pgc_inspector.egg-info/PKG-INFO +223 -0
  33. pgc_inspector-2.0.0/pgc_inspector.egg-info/SOURCES.txt +36 -0
  34. pgc_inspector-2.0.0/pgc_inspector.egg-info/dependency_links.txt +1 -0
  35. pgc_inspector-2.0.0/pgc_inspector.egg-info/entry_points.txt +2 -0
  36. pgc_inspector-2.0.0/pgc_inspector.egg-info/top_level.txt +1 -0
  37. pgc_inspector-2.0.0/pyproject.toml +42 -0
  38. pgc_inspector-2.0.0/setup.cfg +4 -0
@@ -0,0 +1,67 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ Copyright 2026 Bhash Ganti aka Bachi
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
18
+
19
+
20
+ ------------------------
21
+ FULL LICENSE TEXT BELOW
22
+ ------------------------
23
+
24
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
25
+
26
+ 1. Definitions.
27
+ "License" shall mean the terms and conditions for use, reproduction,
28
+ and distribution as defined by Sections 1 through 9 of this document.
29
+ "Licensor" shall mean the copyright owner.
30
+ "Legal Entity" shall mean the union of the acting entity and all other
31
+ entities that control, are controlled by, or are under common control.
32
+ "You" shall mean an individual or Legal Entity exercising permissions.
33
+ "Source" form shall mean the preferred form for making modifications.
34
+ "Object" form shall mean any form resulting from mechanical transformation.
35
+ "Work" shall mean the work of authorship.
36
+ "Derivative Works" shall mean any work based on the Work.
37
+ "Contribution" shall mean any work intentionally submitted.
38
+ "Contributor" shall mean Licensor and any individual submitting Contributions.
39
+
40
+ 2. Grant of Copyright License.
41
+ Each Contributor grants You a perpetual, worldwide, non-exclusive,
42
+ no-charge, royalty-free copyright license.
43
+
44
+ 3. Grant of Patent License.
45
+ Each Contributor grants a patent license to make, use, sell, etc.
46
+
47
+ 4. Redistribution.
48
+ You may reproduce and distribute copies provided that:
49
+ - You include a copy of this License
50
+ - You retain notices
51
+ - You state modifications
52
+ - You include NOTICE file if present
53
+
54
+ 5. Submission of Contributions.
55
+ Contributions are under this License unless stated otherwise.
56
+
57
+ 6. Trademarks.
58
+ This License does not grant trademark rights.
59
+
60
+ 7. Disclaimer of Warranty.
61
+ Provided "AS IS", without warranties.
62
+
63
+ 8. Limitation of Liability.
64
+ No liability for damages.
65
+
66
+ 9. Accepting Warranty or Additional Liability.
67
+ You may offer support/warranty on your own behalf only.
@@ -0,0 +1,11 @@
1
+ PGS — Protocol-Governed Systems
2
+ Copyright 2026 Bhash Ganti aka Bachi
3
+
4
+ This project introduces a protocol-first execution model in which:
5
+
6
+ - Behavior is declared in protocol artifacts
7
+ - Execution is performed by a deterministic runtime
8
+ - Capability implementations are bound at compile time
9
+ - Governance is enforced through invariants and assertions
10
+
11
+ Extensibility is achieved by declaration, not refactor.
@@ -0,0 +1,223 @@
1
+ Metadata-Version: 2.4
2
+ Name: pgc-inspector
3
+ Version: 2.0.0
4
+ Summary: PGC snapshot inspector — read-only query surface over compiled projections and sealed snapshots (command: si)
5
+ Author-email: Bhash Ganti <bachipeachy@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://omnibachi.org/
8
+ Project-URL: Repository, https://github.com/protocol-governed-computing/snapshot_inspector
9
+ Project-URL: Standard, https://doi.org/10.5281/zenodo.22150616
10
+ Keywords: protocol-governed-computing,pgc,inspection,snapshot,registry
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Software Development :: Debuggers
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ License-File: NOTICE
23
+ Dynamic: license-file
24
+
25
+ # snapshot_inspector
26
+
27
+ **Read-only inspection over assembled PGC snapshots.** A first-class toolchain component,
28
+ symmetric with the compiler, assembler, and runtime — each owns one phase of the snapshot
29
+ lifecycle:
30
+
31
+ ```
32
+ protocol_compiler source → compiled projections
33
+ snapshot_assembler projections → assembled snapshot
34
+ protocol_runtime snapshot → execution
35
+ snapshot_inspector snapshot → inspection (this repo)
36
+ ```
37
+
38
+ It reads the **assembled snapshot** (the final product) and answers inspection queries over it.
39
+ It never mutates and never executes.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install pgc-inspector
45
+ ```
46
+
47
+ Once installed:
48
+
49
+ ```bash
50
+ si --help
51
+ ```
52
+
53
+ ## Consumers
54
+
55
+ Inspection is consumer-neutral. `inspector.api.query(...)` serves:
56
+
57
+ - the **transport** `SNAPSHOT_READ` / `SNAPSHOT_QUERY` handlers (the Inspection Surface),
58
+ - the **`si` CLI**,
59
+ - **CI gates** (`validate` / `violations`),
60
+ - **change-management** dossiers (impact / refs / deps).
61
+
62
+ ## API
63
+
64
+ ```python
65
+ from inspector.api import query
66
+
67
+ status, payload = query(
68
+ "si.artifact.show",
69
+ {"artifact": "workload::WF_COLLATZ_CONJECTURE_V0"},
70
+ snapshot_root="/path/to/snapshot",
71
+ )
72
+ # status ∈ {"SUCCESS", "NOT_FOUND"}
73
+ ```
74
+
75
+ Callers pass an **Operation Identity**; the inspector resolves it internally (never an RPC of
76
+ projection functions). See `CLAUDE.md` for the architectural rules.
77
+
78
+ `operations(snapshot_root)` publishes the catalog — every operation with its handler kind,
79
+ category, parameters, summary and declared implementation. **It is read from the snapshot's
80
+ `inspection::` TI artifacts**, so a client's menu is what that snapshot offers, not what the code
81
+ privately believes. There is no second list anywhere.
82
+
83
+ ## Operations
84
+
85
+ | Operation | Kind | Params | |
86
+ |---|---|---|---|
87
+ | `si.snapshot.summary` | READ | — | identity, domains, counts by kind |
88
+ | `si.snapshot.topology` | READ | — | domain → subdomain → workflow map |
89
+ | `si.snapshot.validate` | QUERY | `strict?` | integrity + closure; every check reports `examined` |
90
+ | `si.artifact.list` | READ | `kind?` `domain?` | the artifact catalog |
91
+ | `si.artifact.show` | READ | `artifact` | the published canonical artifact |
92
+ | `si.artifact.indexed` | READ | `artifact` | index membership (absence is SUCCESS) |
93
+ | `si.artifact.refs` | QUERY | `artifact` `transitive?` | consumers and dependencies |
94
+ | `si.topology.impact` | QUERY | `artifact` | transitive consumer closure |
95
+ | `si.store.list` | READ | `domain?` | declared stores, owners, paths |
96
+ | `si.store.show` | READ | `store` | one store's declarations and bindings |
97
+ | `si.store.consumers` | READ | `store` | workflows and CCs reaching a store |
98
+ | `si.vocab.search` | READ | `term` | matching vocabulary identities |
99
+ | `si.vocab.resolve` | READ | `artifact` \| `address`+`domain` | identity ↔ per-domain address |
100
+ | `si.behavior_logic.list` | READ | — | workflows carrying a published graph |
101
+ | `si.behavior_logic.show` | READ | `wf` | one workflow's execution graph |
102
+ | `si.rule_set.list` | READ | `artifact?` | every artifact carrying a sealed rule set, and the rule identifiers it declares |
103
+ | `si.catalog` | READ | — | every operation this inspector answers |
104
+
105
+ A missing **required** parameter returns `NOT_FOUND` — a well-formed question the snapshot cannot
106
+ answer as posed. An **unregistered operation raises**: no snapshot could ever answer it.
107
+
108
+ ## Query classes
109
+
110
+ | Class | Meaning | Phase |
111
+ |---|---|---|
112
+ | `SNAPSHOT_READ` | project **published** snapshot material | 2a |
113
+ | `SNAPSHOT_QUERY` | **derive** a result by traversing/evaluating snapshot state | 2b |
114
+
115
+ ## CLI
116
+
117
+ ```bash
118
+ export PGC_SNAPSHOT_ROOT=../snapshot # or pass --snapshot PATH
119
+
120
+ si operations # the catalog
121
+ si snapshot summary
122
+ si artifact show workload::WF_COLLATZ_CONJECTURE_V0
123
+ si artifact refs capability_side_effects::CS_MUTABLE_JSON_V0 --transitive
124
+ si store consumers LICENSE_REGISTRY
125
+ si snapshot validate --strict # CI gate: exit 1 if invalid
126
+ si artifact list --kind RB --json
127
+ ```
128
+
129
+ Every command is **generated from the catalog** — registering an operation is the only way to add
130
+ one, so the CLI can never answer something the API cannot. Snapshot resolution: `--snapshot`, then
131
+ `$PGC_SNAPSHOT_ROOT`, then `./snapshot`. Exit codes: `0` SUCCESS, `1` NOT_FOUND (or an invalid
132
+ snapshot under `--strict`), `2` usage or snapshot error. Stdlib argparse — nothing to install.
133
+
134
+ ## Inspection Surface (browser)
135
+
136
+ ```bash
137
+ client/serve.sh # :8001 — needs an assembled snapshot
138
+ ```
139
+
140
+ One of two out-of-box reference implementations. Collatz demonstrates that a governed workflow
141
+ **executes**; this demonstrates what a governed snapshot **contains**.
142
+
143
+ The surface opens on a launcher listing every operation, grouped by category — fetched via
144
+ `si.catalog`, so the menu is exactly what the boundary can answer. Choosing an entry opens an
145
+ independent window: concurrent (several of the same operation with different parameters is the
146
+ point), movable, click-to-raise, individually closable. Nothing is ever disabled or queued behind
147
+ another window.
148
+
149
+ Every window's content arrives from one `POST /si` carrying an Operation Identity. The client
150
+ selects, fetches, formats, filters and navigates; it derives **no** PGC relationship. Clicking an
151
+ FQDN opens a new governed request for it — navigation, not a closure the browser worked out.
152
+
153
+ ## The `inspection::` tool domain
154
+
155
+ This repo also hosts the domain that declares the boundary: `registry/` (build config) and
156
+ `transport/` (32 TI/TE artifacts), compiled by `protocol_compiler/compile_domain.sh .` and
157
+ composed into the snapshot like any other domain. A **tool domain** declares capabilities *about*
158
+ a snapshot rather than within one; it consumes the assembled snapshot as the runtime does, which
159
+ makes it a peer of the runtime, not part of the normative platform.
160
+
161
+ **The contracts are the authority.** Each TI declares its operation's identity, kind, input
162
+ contract, presentation and — as a capability transform does — the `{module, callable}` that
163
+ answers it. `inspector.registry` holds implementations and no metadata; the operation set comes
164
+ from the snapshot.
165
+
166
+ `scripts/author_transport_contracts.py` is the authoring aid that writes the `.md` artifacts from
167
+ one complete declaration per operation. Nothing consults it at run time: delete it and the
168
+ inspector keeps working from the compiled contracts. Re-run it, then recompile the domain, after
169
+ changing any declaration.
170
+
171
+ ## Run (standalone)
172
+
173
+ ```bash
174
+ PYTHONPATH=. python3 -m inspector operations # CLI without installing
175
+ PYTHONPATH=. python3 -c "from inspector.api import query; \
176
+ print(query('si.artifact.show', {'artifact':'workload::WF_COLLATZ_CONJECTURE_V0'}, '../snapshot'))"
177
+
178
+ PYTHONPATH=. python3 scripts/testbed/test_inspector.py # behaviour contract
179
+ ```
180
+
181
+ ---
182
+
183
+ ## The package family
184
+
185
+ | Package | Repository | Role |
186
+ |---|---|---|
187
+ | `pgc-compiler` | `protocol_compiler` | declarations → compiled projections |
188
+ | `pgc-assembler` | `snapshot_assembler` | projections → sealed snapshot |
189
+ | `pgc-runtime` | `protocol_runtime` | snapshot → governed execution |
190
+ | `pgc-inspector` | `snapshot_inspector` | snapshot → read-only inspection |
191
+ | `pgc-transformation` | `transformation` | change request → protocol artifacts |
192
+ | `pgc-governance` | `software_governance` | the governance surface and its capability implementations |
193
+ | `pgc-workloads` | `conformance_workloads` | the workloads that make conformance observable |
194
+ | `pgc-domains` | `business_domains` | the business domain implementations the composed snapshot binds |
195
+
196
+ `pip install pgc` brings in the whole family.
197
+
198
+ **Installing the toolchain is one of two steps.** The compiler resolves the governance surface from
199
+ `PGC_PLATFORM_ROOT` — fail-hard, cwd-independent, zero inference — so the *declarations* come from a
200
+ repository you point at, never from a wheel. A registry inside a package would be a second governance
201
+ surface competing with the repository's, and a build could then be governed by a stale copy.
202
+
203
+ ```bash
204
+ git clone https://github.com/protocol-governed-computing/software_governance
205
+ export PGC_PLATFORM_ROOT=$PWD/software_governance
206
+ pgc # reports what is installed and whether the anchor resolves
207
+ ```
208
+
209
+ `PGC_BUILD_ROOT` (compiled output, keeping the governance repo read-only) and `PGC_DOMAIN_ROOTS`
210
+ (additional domains contributing their own `registry/structures`) are optional.
211
+
212
+ **Versioning.** Two schemes, and the published version follows the second.
213
+
214
+ - **Internal** — each repository's `VERSION` file, a monotonic composition ordinal. PGC versions the
215
+ composition rather than each repo: they release together and the governance closure forces lockstep,
216
+ so the ordinal names which composition a repo belongs to. Development happens on `dev/<N>` and each
217
+ cycle is tagged `release-<N>`. This is not published.
218
+ - **Public** — `PUBLIC_VERSION`, tagged on every component repository. The platform is at **`v2`**.
219
+
220
+ **The published version is the public one: `v2` is `2.0.0`.** The standard the packages implement is a
221
+ separate artifact on its own track and is not this number.
222
+
223
+ The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150616
@@ -0,0 +1,199 @@
1
+ # snapshot_inspector
2
+
3
+ **Read-only inspection over assembled PGC snapshots.** A first-class toolchain component,
4
+ symmetric with the compiler, assembler, and runtime — each owns one phase of the snapshot
5
+ lifecycle:
6
+
7
+ ```
8
+ protocol_compiler source → compiled projections
9
+ snapshot_assembler projections → assembled snapshot
10
+ protocol_runtime snapshot → execution
11
+ snapshot_inspector snapshot → inspection (this repo)
12
+ ```
13
+
14
+ It reads the **assembled snapshot** (the final product) and answers inspection queries over it.
15
+ It never mutates and never executes.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install pgc-inspector
21
+ ```
22
+
23
+ Once installed:
24
+
25
+ ```bash
26
+ si --help
27
+ ```
28
+
29
+ ## Consumers
30
+
31
+ Inspection is consumer-neutral. `inspector.api.query(...)` serves:
32
+
33
+ - the **transport** `SNAPSHOT_READ` / `SNAPSHOT_QUERY` handlers (the Inspection Surface),
34
+ - the **`si` CLI**,
35
+ - **CI gates** (`validate` / `violations`),
36
+ - **change-management** dossiers (impact / refs / deps).
37
+
38
+ ## API
39
+
40
+ ```python
41
+ from inspector.api import query
42
+
43
+ status, payload = query(
44
+ "si.artifact.show",
45
+ {"artifact": "workload::WF_COLLATZ_CONJECTURE_V0"},
46
+ snapshot_root="/path/to/snapshot",
47
+ )
48
+ # status ∈ {"SUCCESS", "NOT_FOUND"}
49
+ ```
50
+
51
+ Callers pass an **Operation Identity**; the inspector resolves it internally (never an RPC of
52
+ projection functions). See `CLAUDE.md` for the architectural rules.
53
+
54
+ `operations(snapshot_root)` publishes the catalog — every operation with its handler kind,
55
+ category, parameters, summary and declared implementation. **It is read from the snapshot's
56
+ `inspection::` TI artifacts**, so a client's menu is what that snapshot offers, not what the code
57
+ privately believes. There is no second list anywhere.
58
+
59
+ ## Operations
60
+
61
+ | Operation | Kind | Params | |
62
+ |---|---|---|---|
63
+ | `si.snapshot.summary` | READ | — | identity, domains, counts by kind |
64
+ | `si.snapshot.topology` | READ | — | domain → subdomain → workflow map |
65
+ | `si.snapshot.validate` | QUERY | `strict?` | integrity + closure; every check reports `examined` |
66
+ | `si.artifact.list` | READ | `kind?` `domain?` | the artifact catalog |
67
+ | `si.artifact.show` | READ | `artifact` | the published canonical artifact |
68
+ | `si.artifact.indexed` | READ | `artifact` | index membership (absence is SUCCESS) |
69
+ | `si.artifact.refs` | QUERY | `artifact` `transitive?` | consumers and dependencies |
70
+ | `si.topology.impact` | QUERY | `artifact` | transitive consumer closure |
71
+ | `si.store.list` | READ | `domain?` | declared stores, owners, paths |
72
+ | `si.store.show` | READ | `store` | one store's declarations and bindings |
73
+ | `si.store.consumers` | READ | `store` | workflows and CCs reaching a store |
74
+ | `si.vocab.search` | READ | `term` | matching vocabulary identities |
75
+ | `si.vocab.resolve` | READ | `artifact` \| `address`+`domain` | identity ↔ per-domain address |
76
+ | `si.behavior_logic.list` | READ | — | workflows carrying a published graph |
77
+ | `si.behavior_logic.show` | READ | `wf` | one workflow's execution graph |
78
+ | `si.rule_set.list` | READ | `artifact?` | every artifact carrying a sealed rule set, and the rule identifiers it declares |
79
+ | `si.catalog` | READ | — | every operation this inspector answers |
80
+
81
+ A missing **required** parameter returns `NOT_FOUND` — a well-formed question the snapshot cannot
82
+ answer as posed. An **unregistered operation raises**: no snapshot could ever answer it.
83
+
84
+ ## Query classes
85
+
86
+ | Class | Meaning | Phase |
87
+ |---|---|---|
88
+ | `SNAPSHOT_READ` | project **published** snapshot material | 2a |
89
+ | `SNAPSHOT_QUERY` | **derive** a result by traversing/evaluating snapshot state | 2b |
90
+
91
+ ## CLI
92
+
93
+ ```bash
94
+ export PGC_SNAPSHOT_ROOT=../snapshot # or pass --snapshot PATH
95
+
96
+ si operations # the catalog
97
+ si snapshot summary
98
+ si artifact show workload::WF_COLLATZ_CONJECTURE_V0
99
+ si artifact refs capability_side_effects::CS_MUTABLE_JSON_V0 --transitive
100
+ si store consumers LICENSE_REGISTRY
101
+ si snapshot validate --strict # CI gate: exit 1 if invalid
102
+ si artifact list --kind RB --json
103
+ ```
104
+
105
+ Every command is **generated from the catalog** — registering an operation is the only way to add
106
+ one, so the CLI can never answer something the API cannot. Snapshot resolution: `--snapshot`, then
107
+ `$PGC_SNAPSHOT_ROOT`, then `./snapshot`. Exit codes: `0` SUCCESS, `1` NOT_FOUND (or an invalid
108
+ snapshot under `--strict`), `2` usage or snapshot error. Stdlib argparse — nothing to install.
109
+
110
+ ## Inspection Surface (browser)
111
+
112
+ ```bash
113
+ client/serve.sh # :8001 — needs an assembled snapshot
114
+ ```
115
+
116
+ One of two out-of-box reference implementations. Collatz demonstrates that a governed workflow
117
+ **executes**; this demonstrates what a governed snapshot **contains**.
118
+
119
+ The surface opens on a launcher listing every operation, grouped by category — fetched via
120
+ `si.catalog`, so the menu is exactly what the boundary can answer. Choosing an entry opens an
121
+ independent window: concurrent (several of the same operation with different parameters is the
122
+ point), movable, click-to-raise, individually closable. Nothing is ever disabled or queued behind
123
+ another window.
124
+
125
+ Every window's content arrives from one `POST /si` carrying an Operation Identity. The client
126
+ selects, fetches, formats, filters and navigates; it derives **no** PGC relationship. Clicking an
127
+ FQDN opens a new governed request for it — navigation, not a closure the browser worked out.
128
+
129
+ ## The `inspection::` tool domain
130
+
131
+ This repo also hosts the domain that declares the boundary: `registry/` (build config) and
132
+ `transport/` (32 TI/TE artifacts), compiled by `protocol_compiler/compile_domain.sh .` and
133
+ composed into the snapshot like any other domain. A **tool domain** declares capabilities *about*
134
+ a snapshot rather than within one; it consumes the assembled snapshot as the runtime does, which
135
+ makes it a peer of the runtime, not part of the normative platform.
136
+
137
+ **The contracts are the authority.** Each TI declares its operation's identity, kind, input
138
+ contract, presentation and — as a capability transform does — the `{module, callable}` that
139
+ answers it. `inspector.registry` holds implementations and no metadata; the operation set comes
140
+ from the snapshot.
141
+
142
+ `scripts/author_transport_contracts.py` is the authoring aid that writes the `.md` artifacts from
143
+ one complete declaration per operation. Nothing consults it at run time: delete it and the
144
+ inspector keeps working from the compiled contracts. Re-run it, then recompile the domain, after
145
+ changing any declaration.
146
+
147
+ ## Run (standalone)
148
+
149
+ ```bash
150
+ PYTHONPATH=. python3 -m inspector operations # CLI without installing
151
+ PYTHONPATH=. python3 -c "from inspector.api import query; \
152
+ print(query('si.artifact.show', {'artifact':'workload::WF_COLLATZ_CONJECTURE_V0'}, '../snapshot'))"
153
+
154
+ PYTHONPATH=. python3 scripts/testbed/test_inspector.py # behaviour contract
155
+ ```
156
+
157
+ ---
158
+
159
+ ## The package family
160
+
161
+ | Package | Repository | Role |
162
+ |---|---|---|
163
+ | `pgc-compiler` | `protocol_compiler` | declarations → compiled projections |
164
+ | `pgc-assembler` | `snapshot_assembler` | projections → sealed snapshot |
165
+ | `pgc-runtime` | `protocol_runtime` | snapshot → governed execution |
166
+ | `pgc-inspector` | `snapshot_inspector` | snapshot → read-only inspection |
167
+ | `pgc-transformation` | `transformation` | change request → protocol artifacts |
168
+ | `pgc-governance` | `software_governance` | the governance surface and its capability implementations |
169
+ | `pgc-workloads` | `conformance_workloads` | the workloads that make conformance observable |
170
+ | `pgc-domains` | `business_domains` | the business domain implementations the composed snapshot binds |
171
+
172
+ `pip install pgc` brings in the whole family.
173
+
174
+ **Installing the toolchain is one of two steps.** The compiler resolves the governance surface from
175
+ `PGC_PLATFORM_ROOT` — fail-hard, cwd-independent, zero inference — so the *declarations* come from a
176
+ repository you point at, never from a wheel. A registry inside a package would be a second governance
177
+ surface competing with the repository's, and a build could then be governed by a stale copy.
178
+
179
+ ```bash
180
+ git clone https://github.com/protocol-governed-computing/software_governance
181
+ export PGC_PLATFORM_ROOT=$PWD/software_governance
182
+ pgc # reports what is installed and whether the anchor resolves
183
+ ```
184
+
185
+ `PGC_BUILD_ROOT` (compiled output, keeping the governance repo read-only) and `PGC_DOMAIN_ROOTS`
186
+ (additional domains contributing their own `registry/structures`) are optional.
187
+
188
+ **Versioning.** Two schemes, and the published version follows the second.
189
+
190
+ - **Internal** — each repository's `VERSION` file, a monotonic composition ordinal. PGC versions the
191
+ composition rather than each repo: they release together and the governance closure forces lockstep,
192
+ so the ordinal names which composition a repo belongs to. Development happens on `dev/<N>` and each
193
+ cycle is tagged `release-<N>`. This is not published.
194
+ - **Public** — `PUBLIC_VERSION`, tagged on every component repository. The platform is at **`v2`**.
195
+
196
+ **The published version is the public one: `v2` is `2.0.0`.** The standard the packages implement is a
197
+ separate artifact on its own track and is not this number.
198
+
199
+ The standard these packages implement is published separately: https://doi.org/10.5281/zenodo.22150616
@@ -0,0 +1,17 @@
1
+ """snapshot_inspector — read-only inspection over assembled PGC snapshots.
2
+
3
+ A first-class toolchain component, symmetric with the compiler / assembler / runtime — each
4
+ owns one phase of the snapshot lifecycle:
5
+
6
+ protocol_compiler source → compiled projections
7
+ snapshot_assembler projections → assembled snapshot
8
+ protocol_runtime snapshot → execution
9
+ snapshot_inspector snapshot → inspection (this repo)
10
+
11
+ CONSUMER-NEUTRAL: the transport SNAPSHOT_READ/SNAPSHOT_QUERY handlers are one consumer; a `si`
12
+ CLI, CI gates (validate/violations), and change-management dossiers are others. The API makes
13
+ no web/transport assumptions.
14
+
15
+ Inspection never mutates and never executes. Phase 2a projects PUBLISHED snapshot material;
16
+ Phase 2b derives governed queries (refs/deps/impact/validation) over it.
17
+ """
@@ -0,0 +1,7 @@
1
+ """`python -m inspector` → the `si` CLI, so the tool runs without being installed."""
2
+ import sys
3
+
4
+ from inspector.cli import main
5
+
6
+ if __name__ == "__main__":
7
+ sys.exit(main())
@@ -0,0 +1,94 @@
1
+ """inspector.api — the single programmatic entry point for snapshot inspection.
2
+
3
+ query(operation, params, snapshot_root) -> (status, payload)
4
+ operations(snapshot_root) -> the published catalog
5
+ operation_kind(operation, snapshot_root) -> the handler kind a boundary routes it by
6
+
7
+ `status` ∈ {"SUCCESS", "NOT_FOUND"}; raises on internal error. This mirrors
8
+ `runtime.api.run_workflow`'s `(status, surface)` so any boundary (e.g. the transport
9
+ SNAPSHOT_READ handler) can treat execution and inspection uniformly.
10
+
11
+ **The snapshot declares the operation set.** Every operation, its accepted parameters, its handler
12
+ kind and the implementation that answers it are read from the snapshot's compiled `inspection::` TI
13
+ artifacts (`inspector.catalog`); `inspector.registry` supplies implementations and declares no
14
+ metadata. So an inspector pointed at a snapshot answers exactly what that snapshot declares — two
15
+ snapshots may legitimately offer different operations, and neither is what the code privately
16
+ believes.
17
+
18
+ A missing REQUIRED parameter is NOT_FOUND, not a raise: the caller asked a well-formed question the
19
+ snapshot cannot answer as posed. An operation the snapshot does not declare raises, because no
20
+ amount of parameters would make it answerable here — that is a caller defect, not a result.
21
+ """
22
+ from __future__ import annotations
23
+
24
+ from pathlib import Path
25
+ from typing import Any
26
+
27
+ from inspector.catalog import load_catalog
28
+ from inspector.kinds import CATEGORIES
29
+ from inspector.snapshot import Snapshot
30
+
31
+
32
+ def _resolve(operation: str, snapshot: Snapshot):
33
+ catalog = load_catalog(snapshot)
34
+ op = catalog.get(operation)
35
+ if op is None:
36
+ raise KeyError(
37
+ f"snapshot at {snapshot.root} declares no inspection operation {operation!r}"
38
+ )
39
+ return op
40
+
41
+
42
+ def query(
43
+ operation: str,
44
+ params: dict[str, Any],
45
+ snapshot_root: str | Path,
46
+ ) -> tuple[str, dict[str, Any]]:
47
+ """Answer an inspection Operation Identity over the assembled snapshot at `snapshot_root`."""
48
+ snapshot = Snapshot(Path(snapshot_root))
49
+ op = _resolve(operation, snapshot)
50
+
51
+ params = params or {}
52
+ missing = [p for p in op.required if params.get(p) in (None, "")]
53
+ if missing:
54
+ return "NOT_FOUND", {
55
+ "operation": operation,
56
+ "reason": f"missing required parameter(s): {', '.join(missing)}",
57
+ "params": list(op.params),
58
+ }
59
+
60
+ return op.handler(snapshot, params)
61
+
62
+
63
+ def operation_kind(operation: str, snapshot_root: str | Path) -> str:
64
+ """The handler kind (`SNAPSHOT_READ` / `SNAPSHOT_QUERY`) a boundary routes this operation by."""
65
+ return _resolve(operation, Snapshot(Path(snapshot_root))).kind
66
+
67
+
68
+ def operations(snapshot_root: str | Path) -> list[dict[str, Any]]:
69
+ """The inspection catalog — every operation the snapshot declares, in category then identity order.
70
+
71
+ Published so a client's menu is what the SNAPSHOT offers. There is no second list: the CLI's
72
+ commands and the surface's launcher are both built from this, and this is built from the
73
+ compiled contracts.
74
+ """
75
+ snapshot = Snapshot(Path(snapshot_root))
76
+ return [
77
+ {
78
+ "operation": op.identity,
79
+ "kind": op.kind,
80
+ "category": op.category,
81
+ "label": op.label,
82
+ "params": list(op.params),
83
+ "required": list(op.required),
84
+ "flags": list(op.flags),
85
+ "summary": op.summary,
86
+ "implementation": op.implementation,
87
+ }
88
+ for op in load_catalog(snapshot).values()
89
+ ]
90
+
91
+
92
+ def categories() -> tuple[str, ...]:
93
+ """The catalog groupings, in presentation order."""
94
+ return CATEGORIES