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.
- pgc_inspector-2.0.0/LICENSE +67 -0
- pgc_inspector-2.0.0/NOTICE +11 -0
- pgc_inspector-2.0.0/PKG-INFO +223 -0
- pgc_inspector-2.0.0/README.md +199 -0
- pgc_inspector-2.0.0/inspector/__init__.py +17 -0
- pgc_inspector-2.0.0/inspector/__main__.py +7 -0
- pgc_inspector-2.0.0/inspector/api.py +94 -0
- pgc_inspector-2.0.0/inspector/catalog.py +135 -0
- pgc_inspector-2.0.0/inspector/cli.py +265 -0
- pgc_inspector-2.0.0/inspector/graph.py +138 -0
- pgc_inspector-2.0.0/inspector/kinds.py +19 -0
- pgc_inspector-2.0.0/inspector/queries/__init__.py +8 -0
- pgc_inspector-2.0.0/inspector/queries/artifact_refs.py +40 -0
- pgc_inspector-2.0.0/inspector/queries/snapshot_validate.py +221 -0
- pgc_inspector-2.0.0/inspector/queries/topology_impact.py +39 -0
- pgc_inspector-2.0.0/inspector/reads/__init__.py +5 -0
- pgc_inspector-2.0.0/inspector/reads/artifact_indexed.py +22 -0
- pgc_inspector-2.0.0/inspector/reads/artifact_list.py +53 -0
- pgc_inspector-2.0.0/inspector/reads/artifact_show.py +30 -0
- pgc_inspector-2.0.0/inspector/reads/behavior_logic_list.py +29 -0
- pgc_inspector-2.0.0/inspector/reads/behavior_logic_show.py +36 -0
- pgc_inspector-2.0.0/inspector/reads/capability_surface.py +151 -0
- pgc_inspector-2.0.0/inspector/reads/catalog.py +42 -0
- pgc_inspector-2.0.0/inspector/reads/rule_set_list.py +84 -0
- pgc_inspector-2.0.0/inspector/reads/snapshot_summary.py +71 -0
- pgc_inspector-2.0.0/inspector/reads/snapshot_topology.py +37 -0
- pgc_inspector-2.0.0/inspector/reads/store_reads.py +112 -0
- pgc_inspector-2.0.0/inspector/reads/vocab_resolve.py +66 -0
- pgc_inspector-2.0.0/inspector/reads/vocab_search.py +41 -0
- pgc_inspector-2.0.0/inspector/registry.py +97 -0
- pgc_inspector-2.0.0/inspector/snapshot.py +175 -0
- pgc_inspector-2.0.0/pgc_inspector.egg-info/PKG-INFO +223 -0
- pgc_inspector-2.0.0/pgc_inspector.egg-info/SOURCES.txt +36 -0
- pgc_inspector-2.0.0/pgc_inspector.egg-info/dependency_links.txt +1 -0
- pgc_inspector-2.0.0/pgc_inspector.egg-info/entry_points.txt +2 -0
- pgc_inspector-2.0.0/pgc_inspector.egg-info/top_level.txt +1 -0
- pgc_inspector-2.0.0/pyproject.toml +42 -0
- 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,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
|