procheiron 0.1.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.
- procheiron-0.1.0/.gitignore +7 -0
- procheiron-0.1.0/CODE_OF_CONDUCT.md +8 -0
- procheiron-0.1.0/CONTRIBUTING.md +30 -0
- procheiron-0.1.0/LICENSE +21 -0
- procheiron-0.1.0/PKG-INFO +114 -0
- procheiron-0.1.0/README.md +85 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/config.yaml +29 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/lib/procheiron_lock.py +47 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/lib/procheiron_paths.py +60 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/lib/procheiron_patterns.py +87 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/lib/procheiron_resolve.py +191 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/lib/procheiron_schema.py +248 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/policy/policy_data.json +133 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/policy/procheiron.rego +144 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/policy/procheiron_policy.py +162 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/policy/procheiron_test.rego +85 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/profiles/meridian/lint.json +44 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/profiles/meridian/profile.md +98 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/profiles/meridian/retrieval.md +85 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/adapter_manifest.schema.json +27 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/audit_event.schema.json +71 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/config.schema.json +46 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/manifest.schema.json +40 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/memory_record.schema.json +135 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/profile_lint.schema.json +34 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/required_tokens.json +32 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/severity_map.json +53 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/source_record.schema.json +47 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/schemas/supersession.schema.json +34 -0
- procheiron-0.1.0/conformance/generic-vault/.procheiron/validators/validate_procheiron2.py +723 -0
- procheiron-0.1.0/conformance/generic-vault/console/ACTIVE_PROJECTS.md +42 -0
- procheiron-0.1.0/conformance/generic-vault/console/AGENT_BOOT.md +128 -0
- procheiron-0.1.0/conformance/generic-vault/console/AGENT_REGISTRY.md +52 -0
- procheiron-0.1.0/conformance/generic-vault/console/BLOCKERS.md +46 -0
- procheiron-0.1.0/conformance/generic-vault/console/DECISIONS.md +62 -0
- procheiron-0.1.0/conformance/generic-vault/console/PRECEDENCE.md +87 -0
- procheiron-0.1.0/conformance/generic-vault/console/PROCHEIRON.md +62 -0
- procheiron-0.1.0/conformance/generic-vault/console/RETRIEVAL_POLICY.md +107 -0
- procheiron-0.1.0/conformance/generic-vault/console/SELF_ACTION_POLICY.md +415 -0
- procheiron-0.1.0/conformance/generic-vault/console/SOURCE_OF_TRUTH.md +54 -0
- procheiron-0.1.0/conformance/generic-vault/knowledge/wiki/DESIGN_PRINCIPLES.md +30 -0
- procheiron-0.1.0/conformance/generic-vault/memory/README.md +60 -0
- procheiron-0.1.0/conformance/generic-vault/memory/SCHEMA.md +117 -0
- procheiron-0.1.0/conformance/generic-vault/memory/VALIDATION.md +33 -0
- procheiron-0.1.0/conformance/generic-vault/memory/index/audit.jsonl +8 -0
- procheiron-0.1.0/conformance/generic-vault/memory/index/memories.jsonl +8 -0
- procheiron-0.1.0/conformance/generic-vault/memory/index/supersessions.jsonl +1 -0
- procheiron-0.1.0/conformance/generic-vault/runtime/state/STATE.json +10 -0
- procheiron-0.1.0/conformance/generic-vault/sources/MATERIAL_STANDARDS.md +65 -0
- procheiron-0.1.0/conformance/generic-vault/studio/STUDIO_GOVERNANCE.md +28 -0
- procheiron-0.1.0/conformance/manifest.json +27 -0
- procheiron-0.1.0/conformance/minimal-vault/.procheiron/config.yaml +6 -0
- procheiron-0.1.0/conformance/minimal-vault/console/CONSOLE.md +79 -0
- procheiron-0.1.0/conformance/minimal-vault/memory/SCHEMA.md +82 -0
- procheiron-0.1.0/conformance/minimal-vault/memory/index/audit.jsonl +4 -0
- procheiron-0.1.0/conformance/minimal-vault/memory/index/memories.jsonl +4 -0
- procheiron-0.1.0/conformance/minimal-vault/memory_promote.py +477 -0
- procheiron-0.1.0/conformance/minimal-vault/memory_propose.py +271 -0
- procheiron-0.1.0/conformance/minimal-vault/procheiron_schema.py +248 -0
- procheiron-0.1.0/conformance/minimal-vault/schemas/memory_record.schema.json +135 -0
- procheiron-0.1.0/conformance/minimal-vault/validate_minimal.py +170 -0
- procheiron-0.1.0/conformance/run_conformance.py +203 -0
- procheiron-0.1.0/examples/minimal-adopter/CONSOLE.md +79 -0
- procheiron-0.1.0/examples/minimal-adopter/README.md +103 -0
- procheiron-0.1.0/examples/minimal-adopter/SCHEMA.md +82 -0
- procheiron-0.1.0/examples/minimal-adopter/memory_promote.py +477 -0
- procheiron-0.1.0/examples/minimal-adopter/memory_propose.py +271 -0
- procheiron-0.1.0/examples/minimal-adopter/procheiron_schema.py +248 -0
- procheiron-0.1.0/examples/minimal-adopter/schemas/memory_record.schema.json +135 -0
- procheiron-0.1.0/examples/minimal-adopter/validate_minimal.py +170 -0
- procheiron-0.1.0/init/PORTING_GUIDE.md +258 -0
- procheiron-0.1.0/init/procheiron_init.py +326 -0
- procheiron-0.1.0/pyproject.toml +18 -0
- procheiron-0.1.0/spec/README.md +27 -0
- procheiron-0.1.0/spec/boundary.md +52 -0
- procheiron-0.1.0/spec/conformance.md +191 -0
- procheiron-0.1.0/spec/control-plane.md +115 -0
- procheiron-0.1.0/spec/governance.md +133 -0
- procheiron-0.1.0/spec/memory-commons.md +122 -0
- procheiron-0.1.0/src/procheiron/__init__.py +3 -0
- procheiron-0.1.0/src/procheiron/cli.py +158 -0
- procheiron-0.1.0/src/procheiron/data/adopter/memory_promote.py +477 -0
- procheiron-0.1.0/src/procheiron/data/adopter/memory_propose.py +271 -0
- procheiron-0.1.0/src/procheiron/data/adopter/procheiron_schema.py +248 -0
- procheiron-0.1.0/src/procheiron/data/adopter/schemas/memory_record.schema.json +135 -0
- procheiron-0.1.0/src/procheiron/data/adopter/validate_minimal.py +170 -0
- procheiron-0.1.0/src/procheiron/data/policy/policy_data.json +133 -0
- procheiron-0.1.0/src/procheiron/data/policy/procheiron.rego +144 -0
- procheiron-0.1.0/src/procheiron/data/policy/procheiron_test.rego +85 -0
- procheiron-0.1.0/src/procheiron/data/schemas/adapter_manifest.schema.json +27 -0
- procheiron-0.1.0/src/procheiron/data/schemas/audit_event.schema.json +71 -0
- procheiron-0.1.0/src/procheiron/data/schemas/config.schema.json +46 -0
- procheiron-0.1.0/src/procheiron/data/schemas/manifest.schema.json +40 -0
- procheiron-0.1.0/src/procheiron/data/schemas/memory_record.schema.json +135 -0
- procheiron-0.1.0/src/procheiron/data/schemas/profile_lint.schema.json +34 -0
- procheiron-0.1.0/src/procheiron/data/schemas/required_tokens.json +32 -0
- procheiron-0.1.0/src/procheiron/data/schemas/severity_map.json +53 -0
- procheiron-0.1.0/src/procheiron/data/schemas/source_record.schema.json +47 -0
- procheiron-0.1.0/src/procheiron/data/schemas/supersession.schema.json +34 -0
- procheiron-0.1.0/src/procheiron/init.py +325 -0
- procheiron-0.1.0/src/procheiron/lock.py +47 -0
- procheiron-0.1.0/src/procheiron/paths.py +60 -0
- procheiron-0.1.0/src/procheiron/patterns.py +87 -0
- procheiron-0.1.0/src/procheiron/policy.py +162 -0
- procheiron-0.1.0/src/procheiron/resolve.py +191 -0
- procheiron-0.1.0/src/procheiron/schema.py +248 -0
- procheiron-0.1.0/src/procheiron/validate.py +729 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
This project follows the [Contributor Covenant](https://www.contributor-covenant.org/) v2.1.
|
|
4
|
+
|
|
5
|
+
Be respectful, assume good faith, and focus on the work. Harassment or abusive behavior is not tolerated.
|
|
6
|
+
Report concerns by opening a confidential issue or contacting the maintainers.
|
|
7
|
+
|
|
8
|
+
The full Contributor Covenant text applies; see https://www.contributor-covenant.org/version/2/1/code_of_conduct/.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Contributing to Procheiron
|
|
2
|
+
|
|
3
|
+
Procheiron is a spec + reference implementation for governed agent memory. Contributions are welcome,
|
|
4
|
+
with one rule that comes from the project's own subject matter: **claims trail proofs.**
|
|
5
|
+
|
|
6
|
+
## Ground rules
|
|
7
|
+
|
|
8
|
+
1. **Every behavioral claim must be backed by the conformance suite.** If you change governance behavior,
|
|
9
|
+
add or update a fixture in `conformance/` and make `run_conformance.py` green. A PR that changes
|
|
10
|
+
behavior without a fixture will be asked for one.
|
|
11
|
+
2. **Zero runtime dependencies.** Anything a deployment runs at runtime must be standard-library Python.
|
|
12
|
+
Dev/CI-only tools (jsonschema, opa) are fine but must never be required to run the validator, init, or
|
|
13
|
+
the minimal adopter.
|
|
14
|
+
3. **No secrets, ever.** No real credentials, tokens, identities, or private deployment content in any
|
|
15
|
+
fixture, example, or test. Secret-*shaped* strings used to test detection must be generated at runtime,
|
|
16
|
+
not committed (see `run_conformance.py`).
|
|
17
|
+
4. **Portable Core, specific Profile.** Keep deployment-specific detail (paths, identities, ladder/gate
|
|
18
|
+
tables, executor bindings) in profiles/examples — not in the normative spec. See `spec/boundary.md`.
|
|
19
|
+
5. **Number honestly.** This is v0.1. v1.0 is earned only when a second *real* deployment passes
|
|
20
|
+
conformance — not by a fixture pass, a single deployment, or authority approval alone.
|
|
21
|
+
|
|
22
|
+
## How to propose a change
|
|
23
|
+
|
|
24
|
+
- Open an issue describing the behavior and why.
|
|
25
|
+
- For spec changes, edit `spec/` and update `conformance.md` (the MUST-list) together.
|
|
26
|
+
- Run `python3 conformance/run_conformance.py` and include the output in your PR.
|
|
27
|
+
|
|
28
|
+
## What's most wanted right now
|
|
29
|
+
|
|
30
|
+
See the Roadmap in `README.md` — the standalone, `--root`-relative MCP server is the top item.
|
procheiron-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Procheiron contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: procheiron
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Governance and provenance layer for agent memory.
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Procheiron contributors
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Python: >=3.9
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Procheiron
|
|
31
|
+
|
|
32
|
+
**A governance and provenance layer for agent memory.** Not a memory engine — the trust layer that
|
|
33
|
+
sits on top of one.
|
|
34
|
+
|
|
35
|
+
Memory engines (supermemory, mempalace, agentmemory, a vector DB, or plain files) answer *"what does my
|
|
36
|
+
agent remember?"* Procheiron answers a different question: **"can a *different* agent trust this memory,
|
|
37
|
+
and prove who wrote it, who reviewed it, and who authorized it?"** It is built for the case a single-agent
|
|
38
|
+
memory store ignores — **multiple agents sharing one governed source of truth.**
|
|
39
|
+
|
|
40
|
+
Status: **v0.1 draft, pre-release.** Conformance passes at fixture level (a second, fully fictional
|
|
41
|
+
deployment validates against the same Core). Honest scope discipline: nothing here claims more than the
|
|
42
|
+
conformance suite proves.
|
|
43
|
+
|
|
44
|
+
## Why this exists
|
|
45
|
+
|
|
46
|
+
Give an agent keys and it will use them. Give several agents a shared memory and, without governance, any
|
|
47
|
+
one of them can write a "fact" the others will trust — no record of who, no independent review, no way to
|
|
48
|
+
supersede it cleanly. Procheiron makes the trustworthy path the easy one:
|
|
49
|
+
|
|
50
|
+
- **Provenance-first lifecycle** — every memory is `draft → candidate → validated → active → superseded`.
|
|
51
|
+
An `active` (trusted) record requires independent review by an actor that is *not* its author.
|
|
52
|
+
- **Authority, not vibes** — who may promote, review, or authorize is policy, checked by a validator and a
|
|
53
|
+
policy engine, not a prompt asking nicely.
|
|
54
|
+
- **Provable, replayable** — a conformance suite checks that a deployment obeys the spec; a fictional
|
|
55
|
+
reference deployment (`conformance/generic-vault/`) proves the same Core governs a vault it has never
|
|
56
|
+
seen.
|
|
57
|
+
|
|
58
|
+
## What's in this repo
|
|
59
|
+
|
|
60
|
+
| Path | What it is |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `spec/` | The v0.1 specification: `governance.md`, `memory-commons.md`, `control-plane.md`, the normative `conformance.md` MUST-list, and the Core/Profile `boundary.md`. |
|
|
63
|
+
| `conformance/` | `run_conformance.py` + fixtures. `generic-vault/` is a complete fictional deployment ("Meridian Atelier"); `minimal-vault/` is the 5-file minimal adopter. Run it to prove conformance. |
|
|
64
|
+
| `examples/minimal-adopter/` | The smallest compliant deployment — a memory commons with provenance + independent review, no heavyweight governance ladder. |
|
|
65
|
+
| `init/` | `procheiron_init.py` scaffolds a new deployment; `PORTING_GUIDE.md` is the step-by-step. |
|
|
66
|
+
|
|
67
|
+
## Quick start
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Install (zero runtime dependencies — stdlib-only Python):
|
|
71
|
+
pipx install procheiron # or: pip install procheiron
|
|
72
|
+
|
|
73
|
+
# Scaffold a governed memory commons and validate it:
|
|
74
|
+
procheiron init ./my-commons
|
|
75
|
+
procheiron validate ./my-commons
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
From a source checkout (no install required):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Prove the spec holds against the bundled fixtures:
|
|
82
|
+
python3 conformance/run_conformance.py
|
|
83
|
+
|
|
84
|
+
# Scaffold via the init script directly:
|
|
85
|
+
python3 init/procheiron_init.py --root ./my-commons
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Design choices worth knowing
|
|
89
|
+
|
|
90
|
+
- **Zero runtime dependencies.** Every tool a live deployment runs is standard-library Python. (`jsonschema`,
|
|
91
|
+
`opa` etc. are used only for development/CI cross-checks, never required at runtime.) Adopt it without
|
|
92
|
+
taking on a dependency tree.
|
|
93
|
+
- **Bring your own memory engine.** Procheiron governs records and their lifecycle; it does **not** do
|
|
94
|
+
embeddings or retrieval and never will (that is the engine's job). Point it at any store.
|
|
95
|
+
- **Core vs Profile.** The spec is portable Core. Deployment-specific bindings (identities, paths, a git
|
|
96
|
+
preservation executor, a full L0–L9 authority ladder) live in a *profile* — see `boundary.md`.
|
|
97
|
+
|
|
98
|
+
## Not in scope (by design)
|
|
99
|
+
|
|
100
|
+
No vector/retrieval engine. No recall benchmarks — that is the memory engine's axis, not ours. No claim of
|
|
101
|
+
"production-replicable" until a second *real* deployment passes conformance (fixture-level proof is what
|
|
102
|
+
exists today, and the README says exactly that).
|
|
103
|
+
|
|
104
|
+
## Roadmap (next, post first-deployment feedback)
|
|
105
|
+
|
|
106
|
+
1. **Standalone MCP server** — `memory.search/get/propose/promote` + `boot_context`, the "any agent has the
|
|
107
|
+
context on hand" integration. (A working version exists but is currently coupled to its origin
|
|
108
|
+
deployment's layout; the port to a `--root`-relative standalone server is the top item.)
|
|
109
|
+
2. ~~PyPI / `pipx` packaging and a one-command `procheiron init`.~~ **Shipped in v0.1** — `pip install procheiron`, `procheiron init`, `procheiron validate`.
|
|
110
|
+
3. A reference integration: Procheiron governing a third-party memory engine end to end.
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
MIT — see `LICENSE`.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Procheiron
|
|
2
|
+
|
|
3
|
+
**A governance and provenance layer for agent memory.** Not a memory engine — the trust layer that
|
|
4
|
+
sits on top of one.
|
|
5
|
+
|
|
6
|
+
Memory engines (supermemory, mempalace, agentmemory, a vector DB, or plain files) answer *"what does my
|
|
7
|
+
agent remember?"* Procheiron answers a different question: **"can a *different* agent trust this memory,
|
|
8
|
+
and prove who wrote it, who reviewed it, and who authorized it?"** It is built for the case a single-agent
|
|
9
|
+
memory store ignores — **multiple agents sharing one governed source of truth.**
|
|
10
|
+
|
|
11
|
+
Status: **v0.1 draft, pre-release.** Conformance passes at fixture level (a second, fully fictional
|
|
12
|
+
deployment validates against the same Core). Honest scope discipline: nothing here claims more than the
|
|
13
|
+
conformance suite proves.
|
|
14
|
+
|
|
15
|
+
## Why this exists
|
|
16
|
+
|
|
17
|
+
Give an agent keys and it will use them. Give several agents a shared memory and, without governance, any
|
|
18
|
+
one of them can write a "fact" the others will trust — no record of who, no independent review, no way to
|
|
19
|
+
supersede it cleanly. Procheiron makes the trustworthy path the easy one:
|
|
20
|
+
|
|
21
|
+
- **Provenance-first lifecycle** — every memory is `draft → candidate → validated → active → superseded`.
|
|
22
|
+
An `active` (trusted) record requires independent review by an actor that is *not* its author.
|
|
23
|
+
- **Authority, not vibes** — who may promote, review, or authorize is policy, checked by a validator and a
|
|
24
|
+
policy engine, not a prompt asking nicely.
|
|
25
|
+
- **Provable, replayable** — a conformance suite checks that a deployment obeys the spec; a fictional
|
|
26
|
+
reference deployment (`conformance/generic-vault/`) proves the same Core governs a vault it has never
|
|
27
|
+
seen.
|
|
28
|
+
|
|
29
|
+
## What's in this repo
|
|
30
|
+
|
|
31
|
+
| Path | What it is |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `spec/` | The v0.1 specification: `governance.md`, `memory-commons.md`, `control-plane.md`, the normative `conformance.md` MUST-list, and the Core/Profile `boundary.md`. |
|
|
34
|
+
| `conformance/` | `run_conformance.py` + fixtures. `generic-vault/` is a complete fictional deployment ("Meridian Atelier"); `minimal-vault/` is the 5-file minimal adopter. Run it to prove conformance. |
|
|
35
|
+
| `examples/minimal-adopter/` | The smallest compliant deployment — a memory commons with provenance + independent review, no heavyweight governance ladder. |
|
|
36
|
+
| `init/` | `procheiron_init.py` scaffolds a new deployment; `PORTING_GUIDE.md` is the step-by-step. |
|
|
37
|
+
|
|
38
|
+
## Quick start
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Install (zero runtime dependencies — stdlib-only Python):
|
|
42
|
+
pipx install procheiron # or: pip install procheiron
|
|
43
|
+
|
|
44
|
+
# Scaffold a governed memory commons and validate it:
|
|
45
|
+
procheiron init ./my-commons
|
|
46
|
+
procheiron validate ./my-commons
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
From a source checkout (no install required):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Prove the spec holds against the bundled fixtures:
|
|
53
|
+
python3 conformance/run_conformance.py
|
|
54
|
+
|
|
55
|
+
# Scaffold via the init script directly:
|
|
56
|
+
python3 init/procheiron_init.py --root ./my-commons
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Design choices worth knowing
|
|
60
|
+
|
|
61
|
+
- **Zero runtime dependencies.** Every tool a live deployment runs is standard-library Python. (`jsonschema`,
|
|
62
|
+
`opa` etc. are used only for development/CI cross-checks, never required at runtime.) Adopt it without
|
|
63
|
+
taking on a dependency tree.
|
|
64
|
+
- **Bring your own memory engine.** Procheiron governs records and their lifecycle; it does **not** do
|
|
65
|
+
embeddings or retrieval and never will (that is the engine's job). Point it at any store.
|
|
66
|
+
- **Core vs Profile.** The spec is portable Core. Deployment-specific bindings (identities, paths, a git
|
|
67
|
+
preservation executor, a full L0–L9 authority ladder) live in a *profile* — see `boundary.md`.
|
|
68
|
+
|
|
69
|
+
## Not in scope (by design)
|
|
70
|
+
|
|
71
|
+
No vector/retrieval engine. No recall benchmarks — that is the memory engine's axis, not ours. No claim of
|
|
72
|
+
"production-replicable" until a second *real* deployment passes conformance (fixture-level proof is what
|
|
73
|
+
exists today, and the README says exactly that).
|
|
74
|
+
|
|
75
|
+
## Roadmap (next, post first-deployment feedback)
|
|
76
|
+
|
|
77
|
+
1. **Standalone MCP server** — `memory.search/get/propose/promote` + `boot_context`, the "any agent has the
|
|
78
|
+
context on hand" integration. (A working version exists but is currently coupled to its origin
|
|
79
|
+
deployment's layout; the port to a `--root`-relative standalone server is the top item.)
|
|
80
|
+
2. ~~PyPI / `pipx` packaging and a one-command `procheiron init`.~~ **Shipped in v0.1** — `pip install procheiron`, `procheiron init`, `procheiron validate`.
|
|
81
|
+
3. A reference integration: Procheiron governing a third-party memory engine end to end.
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT — see `LICENSE`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
version: 0.1
|
|
2
|
+
profile: meridian
|
|
3
|
+
root: .
|
|
4
|
+
paths:
|
|
5
|
+
console: console
|
|
6
|
+
memory: memory
|
|
7
|
+
sources: sources
|
|
8
|
+
wiki: knowledge
|
|
9
|
+
outputs: outputs
|
|
10
|
+
adapters: adapters
|
|
11
|
+
legacy_governance: studio
|
|
12
|
+
workspace: workspace
|
|
13
|
+
runtime_root: runtime/procheiron
|
|
14
|
+
runtime_state: runtime/state/STATE.json
|
|
15
|
+
scripts: scripts
|
|
16
|
+
policy_defaults:
|
|
17
|
+
local_first: true
|
|
18
|
+
human_visible: true
|
|
19
|
+
raw_sources_immutable: true
|
|
20
|
+
derived_memory_rebuildable: true
|
|
21
|
+
provenance_required: true
|
|
22
|
+
temporal_by_default: true
|
|
23
|
+
no_runtime_lock_in: true
|
|
24
|
+
no_external_actions_by_default: true
|
|
25
|
+
no_hooks_phase_1_2: true
|
|
26
|
+
no_cron_changes_phase_1_2: true
|
|
27
|
+
no_package_installs_phase_1_2: true
|
|
28
|
+
agents_may_propose_not_promote: true
|
|
29
|
+
secrets_allowed: false
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Single-writer advisory lock for the Procheiron memory indexes (roadmap 3.6).
|
|
3
|
+
|
|
4
|
+
STAGED ARTIFACT — installs to .procheiron/lib/procheiron_lock.py under the
|
|
5
|
+
Phase-3 adoption authorization, shared by memory_promote.py and memory_propose.py
|
|
6
|
+
so there is one lock implementation, no drift. Stdlib-only.
|
|
7
|
+
|
|
8
|
+
Discipline: O_CREAT|O_EXCL create (no auto-steal), age-surfaced contention,
|
|
9
|
+
unlink on exit (including SystemExit). Extracted verbatim-in-behavior from the
|
|
10
|
+
Lock already living in the live memory_promote.py.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import datetime as dt
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LockHeld(SystemExit):
|
|
21
|
+
"""Raised (as SystemExit, so a CLI exits cleanly) when the lock is held."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Lock:
|
|
25
|
+
def __init__(self, root: Path) -> None:
|
|
26
|
+
lock_dir = Path(root) / ".procheiron" / "locks"
|
|
27
|
+
lock_dir.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
self.path = lock_dir / "memory_index.lock"
|
|
29
|
+
|
|
30
|
+
def __enter__(self) -> "Lock":
|
|
31
|
+
try:
|
|
32
|
+
fd = os.open(str(self.path), os.O_CREAT | os.O_EXCL | os.O_WRONLY)
|
|
33
|
+
except FileExistsError:
|
|
34
|
+
age = dt.datetime.now().timestamp() - self.path.stat().st_mtime
|
|
35
|
+
raise LockHeld(
|
|
36
|
+
f"memory index lock held ({self.path}, {int(age)}s old); "
|
|
37
|
+
"retry or remove a stale lock manually"
|
|
38
|
+
)
|
|
39
|
+
os.write(fd, f"{os.getpid()} {dt.datetime.now(dt.timezone.utc).isoformat()}\n".encode())
|
|
40
|
+
os.close(fd)
|
|
41
|
+
return self
|
|
42
|
+
|
|
43
|
+
def __exit__(self, *_exc: Any) -> None:
|
|
44
|
+
try:
|
|
45
|
+
self.path.unlink()
|
|
46
|
+
except FileNotFoundError:
|
|
47
|
+
pass
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Source-path normalization for Procheiron memory records.
|
|
3
|
+
|
|
4
|
+
Converts machine-absolute provenance paths into self-describing, portable
|
|
5
|
+
forms so records survive a deployment move (the data-plane weld from the
|
|
6
|
+
2026-06-10/11 audits):
|
|
7
|
+
|
|
8
|
+
- a path under the deployment root becomes root-relative
|
|
9
|
+
- a path under any absolute `paths.<key>` from config.yaml becomes
|
|
10
|
+
`{paths.<key>}/<rest>` (longest prefix wins)
|
|
11
|
+
- any other absolute path is returned unchanged and reported by the caller
|
|
12
|
+
|
|
13
|
+
Used by memory_propose.py (normalize at write time) and migrate_records.py
|
|
14
|
+
(repair existing records). Stdlib-only.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Optional, Tuple
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def normalize_source_path(cfg: Any, raw: str) -> Tuple[str, bool]:
|
|
24
|
+
"""Return (normalized_path, changed). Non-absolute input passes through."""
|
|
25
|
+
if not raw or not raw.startswith('/'):
|
|
26
|
+
return raw, False
|
|
27
|
+
# Collapse `..`/`.` segments BEFORE prefix matching so a path like
|
|
28
|
+
# `/v/memory/../secret/x` does not falsely tokenize under {paths.memory}
|
|
29
|
+
# (review finding L-4). normpath is lexical only — it never touches disk
|
|
30
|
+
# or resolves symlinks, so it cannot leak filesystem state.
|
|
31
|
+
raw = os.path.normpath(raw)
|
|
32
|
+
candidate = Path(raw)
|
|
33
|
+
best_key: Optional[str] = None
|
|
34
|
+
best_len = -1
|
|
35
|
+
for key, value in cfg.paths.items():
|
|
36
|
+
base = Path(str(value))
|
|
37
|
+
if not base.is_absolute():
|
|
38
|
+
continue
|
|
39
|
+
try:
|
|
40
|
+
rest = candidate.relative_to(base)
|
|
41
|
+
except ValueError:
|
|
42
|
+
continue
|
|
43
|
+
if len(str(base)) > best_len:
|
|
44
|
+
best_key, best_len = key, len(str(base))
|
|
45
|
+
best_rest = rest
|
|
46
|
+
root = Path(str(cfg.root))
|
|
47
|
+
try:
|
|
48
|
+
root_rest = candidate.relative_to(root)
|
|
49
|
+
root_len = len(str(root))
|
|
50
|
+
except ValueError:
|
|
51
|
+
root_rest, root_len = None, -1
|
|
52
|
+
|
|
53
|
+
if root_rest is not None and root_len >= best_len:
|
|
54
|
+
return root_rest.as_posix(), True
|
|
55
|
+
if best_key is not None:
|
|
56
|
+
rest_str = best_rest.as_posix()
|
|
57
|
+
if rest_str == '.':
|
|
58
|
+
return '{paths.%s}' % best_key, True
|
|
59
|
+
return '{paths.%s}/%s' % (best_key, rest_str), True
|
|
60
|
+
return raw, False
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Shared Procheiron secret-pattern registry.
|
|
3
|
+
|
|
4
|
+
Single source of truth for secret detection across the validator
|
|
5
|
+
(validate_procheiron2.py), the candidate-append helper (memory_propose.py),
|
|
6
|
+
and the promotion gate (memory_promote.py). Reunified 2026-06-11 per the
|
|
7
|
+
A-to-Z audit finding that the v2 validator had regressed to 3 patterns
|
|
8
|
+
(AKIA dropped) while memory_propose carried 11 unshared.
|
|
9
|
+
|
|
10
|
+
Stdlib-only. Importing this module must never require third-party packages.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
import unicodedata
|
|
16
|
+
from typing import List, Tuple
|
|
17
|
+
|
|
18
|
+
# (label, compiled pattern). Labels are stable identifiers used in reports.
|
|
19
|
+
SECRET_PATTERNS: List[Tuple[str, "re.Pattern[str]"]] = [
|
|
20
|
+
("openai_style_key", re.compile(r"\bsk-[A-Za-z0-9_\-]{16,}\b")),
|
|
21
|
+
("stripe_key", re.compile(r"\bsk_(live|test)_[A-Za-z0-9]{16,}\b")),
|
|
22
|
+
("github_token", re.compile(r"\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}\b")),
|
|
23
|
+
("github_fine_grained", re.compile(r"\bgithub_pat_[A-Za-z0-9_]{20,}\b")),
|
|
24
|
+
("google_api_key", re.compile(r"\bAIza[0-9A-Za-z_\-]{30,}\b")),
|
|
25
|
+
("slack_token", re.compile(r"\bxox[baprs]-[A-Za-z0-9\-]{10,}\b")),
|
|
26
|
+
("aws_access_key_id", re.compile(r"\bAKIA[0-9A-Z]{16}\b")),
|
|
27
|
+
("jwt", re.compile(r"\beyJ[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,}\.")),
|
|
28
|
+
("bearer_token", re.compile(r"(?i)\bbearer\s+[A-Za-z0-9\-_\.=]{16,}")),
|
|
29
|
+
(
|
|
30
|
+
"credential_assignment",
|
|
31
|
+
re.compile(r"(?i)[\"']?(password|passwd|api[_-]?key|secret|token)[\"']?\s*[:=]\s*[\"']?\S{12,}"),
|
|
32
|
+
),
|
|
33
|
+
("private_key_block", re.compile(r"-----BEGIN [A-Z ]*PRIVATE KEY-----")),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_ZERO_WIDTH = {"", "", "", "", ""}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def normalize_for_scan(text: str) -> str:
|
|
41
|
+
"""NFKC-normalize and strip zero-width/format chars before secret scanning.
|
|
42
|
+
|
|
43
|
+
Defeats the common evasions: a zero-width space inside a key, a fullwidth
|
|
44
|
+
colon in `password:`, an NBSP in a token. Without this, the regexes run on
|
|
45
|
+
the raw bytes and a single invisible character hides a live credential
|
|
46
|
+
(review finding L-1). We strip Unicode Cf (format) chars and the explicit
|
|
47
|
+
zero-width set, then NFKC-fold width/compatibility variants.
|
|
48
|
+
"""
|
|
49
|
+
if not text:
|
|
50
|
+
return ""
|
|
51
|
+
out = []
|
|
52
|
+
for ch in text:
|
|
53
|
+
if ch in _ZERO_WIDTH:
|
|
54
|
+
continue
|
|
55
|
+
if unicodedata.category(ch) == "Cf":
|
|
56
|
+
continue
|
|
57
|
+
out.append(ch)
|
|
58
|
+
return unicodedata.normalize("NFKC", "".join(out))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def scan_text(text: str) -> List[Tuple[int, str]]:
|
|
62
|
+
"""Return (line_number, label) findings for every secret-pattern hit.
|
|
63
|
+
|
|
64
|
+
Each line is scanned both raw and normalized, so an evaded credential is
|
|
65
|
+
still caught while line numbers stay meaningful.
|
|
66
|
+
"""
|
|
67
|
+
findings: List[Tuple[int, str]] = []
|
|
68
|
+
for lineno, line in enumerate(text.splitlines(), 1):
|
|
69
|
+
norm = normalize_for_scan(line)
|
|
70
|
+
for label, pattern in SECRET_PATTERNS:
|
|
71
|
+
if pattern.search(line) or (norm != line and pattern.search(norm)):
|
|
72
|
+
findings.append((lineno, label))
|
|
73
|
+
return findings
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def first_match_label(text: str) -> str | None:
|
|
77
|
+
"""Return the label of the first matching pattern, or None.
|
|
78
|
+
|
|
79
|
+
Scans both the raw and normalized forms so zero-width / homoglyph evasions
|
|
80
|
+
do not slip a live secret past the guard.
|
|
81
|
+
"""
|
|
82
|
+
raw = text or ""
|
|
83
|
+
norm = normalize_for_scan(raw)
|
|
84
|
+
for label, pattern in SECRET_PATTERNS:
|
|
85
|
+
if pattern.search(raw) or (norm != raw and pattern.search(norm)):
|
|
86
|
+
return label
|
|
87
|
+
return None
|