pbuffer 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.
- pbuffer-0.1.0/LICENSE +21 -0
- pbuffer-0.1.0/PKG-INFO +77 -0
- pbuffer-0.1.0/README.md +63 -0
- pbuffer-0.1.0/pyproject.toml +26 -0
- pbuffer-0.1.0/setup.cfg +4 -0
- pbuffer-0.1.0/src/patternbuffer/__init__.py +317 -0
- pbuffer-0.1.0/src/patternbuffer/buffer.py +312 -0
- pbuffer-0.1.0/src/patternbuffer/classify.py +359 -0
- pbuffer-0.1.0/src/patternbuffer/codec.py +122 -0
- pbuffer-0.1.0/src/patternbuffer/dump.py +113 -0
- pbuffer-0.1.0/src/patternbuffer/identity.py +1271 -0
- pbuffer-0.1.0/src/patternbuffer/indexes.py +1642 -0
- pbuffer-0.1.0/src/patternbuffer/ingest.py +617 -0
- pbuffer-0.1.0/src/patternbuffer/mcp.py +303 -0
- pbuffer-0.1.0/src/patternbuffer/model.py +100 -0
- pbuffer-0.1.0/src/patternbuffer/porcelain.py +943 -0
- pbuffer-0.1.0/src/patternbuffer/project.py +436 -0
- pbuffer-0.1.0/src/patternbuffer/refer.py +256 -0
- pbuffer-0.1.0/src/patternbuffer/roles.py +77 -0
- pbuffer-0.1.0/src/patternbuffer/salience.py +170 -0
- pbuffer-0.1.0/src/patternbuffer/semantics.py +192 -0
- pbuffer-0.1.0/src/patternbuffer/testing.py +92 -0
- pbuffer-0.1.0/src/patternbuffer/thunks.py +245 -0
- pbuffer-0.1.0/src/patternbuffer/tmaint.py +122 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/PKG-INFO +77 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/SOURCES.txt +63 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/dependency_links.txt +1 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/entry_points.txt +2 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/requires.txt +6 -0
- pbuffer-0.1.0/src/pbuffer.egg-info/top_level.txt +1 -0
- pbuffer-0.1.0/tests/test_aka_correlation.py +245 -0
- pbuffer-0.1.0/tests/test_awareness_projection.py +132 -0
- pbuffer-0.1.0/tests/test_axis_heads.py +65 -0
- pbuffer-0.1.0/tests/test_bounded_reads.py +129 -0
- pbuffer-0.1.0/tests/test_buffer.py +151 -0
- pbuffer-0.1.0/tests/test_build_session.py +113 -0
- pbuffer-0.1.0/tests/test_classifier_event_safety.py +110 -0
- pbuffer-0.1.0/tests/test_confidence.py +169 -0
- pbuffer-0.1.0/tests/test_confidence_multiframe.py +178 -0
- pbuffer-0.1.0/tests/test_dump.py +72 -0
- pbuffer-0.1.0/tests/test_exact_decimal.py +254 -0
- pbuffer-0.1.0/tests/test_fidelity_audit.py +240 -0
- pbuffer-0.1.0/tests/test_fold.py +646 -0
- pbuffer-0.1.0/tests/test_fold_resolution.py +42 -0
- pbuffer-0.1.0/tests/test_grammar.py +316 -0
- pbuffer-0.1.0/tests/test_identity_containment_veto.py +69 -0
- pbuffer-0.1.0/tests/test_identity_recall.py +214 -0
- pbuffer-0.1.0/tests/test_identity_thunks.py +229 -0
- pbuffer-0.1.0/tests/test_individuation_v2.py +184 -0
- pbuffer-0.1.0/tests/test_ingest_frame_default.py +131 -0
- pbuffer-0.1.0/tests/test_ingest_hardening.py +282 -0
- pbuffer-0.1.0/tests/test_ingest_v2.py +556 -0
- pbuffer-0.1.0/tests/test_mcp_wrapper.py +419 -0
- pbuffer-0.1.0/tests/test_merge_verb.py +192 -0
- pbuffer-0.1.0/tests/test_path_temporal.py +85 -0
- pbuffer-0.1.0/tests/test_place_feature.py +150 -0
- pbuffer-0.1.0/tests/test_porcelain.py +475 -0
- pbuffer-0.1.0/tests/test_route.py +191 -0
- pbuffer-0.1.0/tests/test_scaffold.py +24 -0
- pbuffer-0.1.0/tests/test_shape_fix.py +371 -0
- pbuffer-0.1.0/tests/test_situation_lens.py +208 -0
- pbuffer-0.1.0/tests/test_triage_context.py +180 -0
- pbuffer-0.1.0/tests/test_who_knows.py +110 -0
- pbuffer-0.1.0/tests/test_world.py +634 -0
- pbuffer-0.1.0/tests/test_world_retrieval.py +382 -0
pbuffer-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 5000Stadia
|
|
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.
|
pbuffer-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pbuffer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A world-state database: an append-only log of everything true in a world - places, people, objects, knowledge, time. Deploy it under a game, AI agent, or real-world tracker for permanent, queryable world memory: current state, location, history, and who-knows-what, answered by deterministic queries instead of model calls.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
11
|
+
Provides-Extra: mcp
|
|
12
|
+
Requires-Dist: mcp<2,>=1.28; extra == "mcp"
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# pattern-buffer
|
|
16
|
+
|
|
17
|
+
[](https://github.com/5000Stadia/pattern-buffer/actions/workflows/ci.yml)
|
|
18
|
+
|
|
19
|
+
> A data structure that maps whatever world it's shown — real or fiction.
|
|
20
|
+
> The memory under the holodeck.
|
|
21
|
+
|
|
22
|
+
**A pattern buffer that never degrades.**
|
|
23
|
+
|
|
24
|
+
One append-only log of perspective-scoped, time-indexed assertions about entities; every other structure — current state, space, knowledge, history, the rendered world — is a disposable projection over it. Fiction simulation and real-world tracking are the same machine under one policy switch.
|
|
25
|
+
|
|
26
|
+
**A world-encapsulation framework, engine-independent by construction.** The substrate's only outside dependency is an injected model callable `(prompt, schema) -> json` — no host concept (players, turns, scenes, sessions) ever reaches inside it — so any engine sits on top: a game runtime, a household or job-site tracker, an agent's long-term memory. Fiction and tracking aren't two systems; they are two *instances* of one substrate, differing only in resolution policy and provenance discipline.
|
|
27
|
+
|
|
28
|
+
> A player places a pipe in a drawer in session 12 of a D&D campaign. Two hundred sessions pass without a mention. At retirement, the player opens the drawer — and the pipe is there, exactly as placed, with the original moment's full history behind it. No maintenance was ever performed. In this architecture, **silence is persistence**: state is folded from the log, never re-inferred and never kept alive by mention. The world remembers so the model doesn't have to.
|
|
29
|
+
|
|
30
|
+
**Status: pre-1.0; substrate validated, ingestion fidelity is the open
|
|
31
|
+
front.** The engine passes its 419-test invariant suite, and the chapter test
|
|
32
|
+
(ingest a complete noir mystery, delete the prose, interrogate the store
|
|
33
|
+
against a hand-authored answer key) has been graded across three full runs.
|
|
34
|
+
The substrate's invariants held in all of them — sealed containers stayed
|
|
35
|
+
sealed, contradictions were flagged and never merged, knowledge frames never
|
|
36
|
+
leaked, the two-time-axis fold answered late-revealed history correctly. Each
|
|
37
|
+
run also surfaced exactly one engine refinement at the fold (a working
|
|
38
|
+
assumption outholding evidence; a wrong inference outholding authored canon),
|
|
39
|
+
each fixed, tested, and generalized the same day — that progression is now
|
|
40
|
+
the **evidence-rank** rule. A registry-first ingestion pipeline
|
|
41
|
+
(whole-document scaffold → parallel compact-grammar extraction → audited
|
|
42
|
+
single commit) replaced serial prompt-iterated extraction after measurement
|
|
43
|
+
showed prose contracts fragment differently every round; identity and key
|
|
44
|
+
fragmentation died as failure classes, and pass-0 registry quality is where
|
|
45
|
+
the remaining extraction failures concentrate. Run 4, with its checkable
|
|
46
|
+
predictions, is in flight. Not yet installable from PyPI; the shipped example
|
|
47
|
+
world with a zero-API-key query tour lands once a verified run stamps it.
|
|
48
|
+
|
|
49
|
+
## What this is
|
|
50
|
+
|
|
51
|
+
A storage and retrieval substrate that lets a language model maintain a complete, queryable, durable model of a world — places, objects, people, relationships, histories, and unknowns — such that any state question is answered by a deterministic query, never by re-reading prose; the world accretes and is re-enterable; and the same engine serves authored fiction (a holodeck, a campaign, a mystery) and real-world tracking (a household, a job site, a vehicle), differing only in resolution policy and provenance discipline.
|
|
52
|
+
|
|
53
|
+
The buffer holds the pattern; materialization is re-entry; degradation is the failure we exist to prevent; the arch is how the operator steps outside the world to inspect it; and where nothing has been established, you don't get invented detail — **you see the grid.**
|
|
54
|
+
|
|
55
|
+
## Documents
|
|
56
|
+
|
|
57
|
+
- **[docs/WHITEPAPER.md](docs/WHITEPAPER.md)** — the canonical, comprehensive design reference. Principles, primitives, durability, frames, provenance, thunks, reference resolution, ingestion discipline, identity, the operation algebra, projection, both modes, embedding hazards, evaluation, and the decision record. Start here.
|
|
58
|
+
- **[docs/LEXICON.md](docs/LEXICON.md)** — the working vocabulary and its naming discipline.
|
|
59
|
+
- **[docs/ADOPTION.md](docs/ADOPTION.md)** — for agents (and humans) integrating the library: exact signatures, typed outcomes, the three-seam recipe, MUST/NEVER rules.
|
|
60
|
+
- **[docs/HOST-DISCIPLINE.md](docs/HOST-DISCIPLINE.md)** — the adopter's discipline brief: the seven categories every fact must be classified along to ingest with fidelity, and the structural retrieval strategies (the four correlation axes + the correlation sweep) to surface every relevant, related detail for any subject.
|
|
61
|
+
- **[docs/INGESTION-PLAYBOOK.md](docs/INGESTION-PLAYBOOK.md)** — evidence-based rules for deserializing narrative into a world: the extractor contract, feeding mechanics, what the gate guards, and measured ingestion baselines.
|
|
62
|
+
- **[docs/reference/assertion-world-model-original.md](docs/reference/assertion-world-model-original.md)** — the framework-agnostic design document this project was founded on, preserved verbatim for lineage.
|
|
63
|
+
|
|
64
|
+
## The road
|
|
65
|
+
|
|
66
|
+
1. ~~Recover and commit the *Last Honest Meter* eval seed (the chapter test's ground truth).~~ Done — v1-final, `evals/last_honest_meter/`.
|
|
67
|
+
2. ~~Engine spike: `PatternBuffer` + derived indexes + classifier + projector + resolver + `refer()` tier 1.~~ Done — `src/patternbuffer/`.
|
|
68
|
+
3. ~~The chapter test, runs 1–4~~: substrate validated; registry-first ingestion (INGEST-V2) landed; run 4 scored **22/33 (best graded run, all remaining failures extraction-class not shape-class)** — the substrate holds; ingestion fidelity (pass-0 registry quality) is the open score lever. Receipts: `evals/results/`.
|
|
69
|
+
4. ~~The shipped example world: `examples/anchor/`~~ — stamped (`STAMP.json`, run 4): a bible-verified noir mystery as a queryable database, with a zero-API-key scripted tour and 8 open truth-maintenance conflict flags shipped visibly (honesty is the product). Not yet packaged to PyPI.
|
|
70
|
+
5. ~~The messy-dialogue micro-eval (the honest bridge from fiction ingestion to tracking-mode ingestion).~~ Done — **10/10** on the reality-divergence battery (`evals/results/2026-06-12-micro-v1-final/`); tracking-mode ingestion validated against sloppy conversational fragments.
|
|
71
|
+
6. ~~The porcelain API + host integration.~~ Done — and proven in the strongest form. The frozen contract (`porcelain-v0.1`, additive-only): five load-bearing verbs — `ingest` (+`ingest_structured`) / `snapshot` / `ask` / `materialize` / `resolve`+`refer()` — over a fuller read-and-identity family (`state`, `where`, `aggregate`, `neighborhood`, `frame_diff`, `who_knows`, `correlate`, `route`, `entities`, `facts`, build sessions, `axis_heads`, …). The first *live* host, [Construct](https://github.com/5000Stadia/construct) (an interactive-fiction engine — `pattern` → `construct` loads it → `holonovel`), runs **entirely on this contract**: zero engine-internal reaches, its 800+-test suite green on the pure public surface. The engine-independent claim, demonstrated rather than asserted. (Intended primary host: [Kernos](https://github.com/5000Stadia/Kernos), adapter pattern.)
|
|
72
|
+
7. ~~The interactive-fiction milestone (thunk stability across sessions, frame-scoped NPCs, multi-path mystery, clocks, loop closure).~~ Met in the field — every item is exercised in [Construct](https://github.com/5000Stadia/construct)'s live suite (the first host runs entirely on the frozen porcelain). These are host-layer criteria, proven by the adopter, not a further engine deliverable.
|
|
73
|
+
8. ~~The MCP wrapper~~ — built: `pip install pbuffer[mcp]` → `patternbuffer-mcp --world w.world --world-id w:id` serves the frozen porcelain's **37 deterministic verbs** over stdio to any MCP client — read, query, and *build* a world with zero Python (the genuinely model-free subset; model-backed verbs are V1.1 via sampling). One server ↔ one world; a connected client is a fully **trusted world principal** — frame entitlement for untrusted consumers stays host-mediated. The framework-agnostic claim, proven by demonstration. Far field: the first host's V2 roadmap publicly assigns branch-worlds simulation and its curiosity loop to this engine — the two roadmaps meet in the middle.
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT
|
pbuffer-0.1.0/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# pattern-buffer
|
|
2
|
+
|
|
3
|
+
[](https://github.com/5000Stadia/pattern-buffer/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
> A data structure that maps whatever world it's shown — real or fiction.
|
|
6
|
+
> The memory under the holodeck.
|
|
7
|
+
|
|
8
|
+
**A pattern buffer that never degrades.**
|
|
9
|
+
|
|
10
|
+
One append-only log of perspective-scoped, time-indexed assertions about entities; every other structure — current state, space, knowledge, history, the rendered world — is a disposable projection over it. Fiction simulation and real-world tracking are the same machine under one policy switch.
|
|
11
|
+
|
|
12
|
+
**A world-encapsulation framework, engine-independent by construction.** The substrate's only outside dependency is an injected model callable `(prompt, schema) -> json` — no host concept (players, turns, scenes, sessions) ever reaches inside it — so any engine sits on top: a game runtime, a household or job-site tracker, an agent's long-term memory. Fiction and tracking aren't two systems; they are two *instances* of one substrate, differing only in resolution policy and provenance discipline.
|
|
13
|
+
|
|
14
|
+
> A player places a pipe in a drawer in session 12 of a D&D campaign. Two hundred sessions pass without a mention. At retirement, the player opens the drawer — and the pipe is there, exactly as placed, with the original moment's full history behind it. No maintenance was ever performed. In this architecture, **silence is persistence**: state is folded from the log, never re-inferred and never kept alive by mention. The world remembers so the model doesn't have to.
|
|
15
|
+
|
|
16
|
+
**Status: pre-1.0; substrate validated, ingestion fidelity is the open
|
|
17
|
+
front.** The engine passes its 419-test invariant suite, and the chapter test
|
|
18
|
+
(ingest a complete noir mystery, delete the prose, interrogate the store
|
|
19
|
+
against a hand-authored answer key) has been graded across three full runs.
|
|
20
|
+
The substrate's invariants held in all of them — sealed containers stayed
|
|
21
|
+
sealed, contradictions were flagged and never merged, knowledge frames never
|
|
22
|
+
leaked, the two-time-axis fold answered late-revealed history correctly. Each
|
|
23
|
+
run also surfaced exactly one engine refinement at the fold (a working
|
|
24
|
+
assumption outholding evidence; a wrong inference outholding authored canon),
|
|
25
|
+
each fixed, tested, and generalized the same day — that progression is now
|
|
26
|
+
the **evidence-rank** rule. A registry-first ingestion pipeline
|
|
27
|
+
(whole-document scaffold → parallel compact-grammar extraction → audited
|
|
28
|
+
single commit) replaced serial prompt-iterated extraction after measurement
|
|
29
|
+
showed prose contracts fragment differently every round; identity and key
|
|
30
|
+
fragmentation died as failure classes, and pass-0 registry quality is where
|
|
31
|
+
the remaining extraction failures concentrate. Run 4, with its checkable
|
|
32
|
+
predictions, is in flight. Not yet installable from PyPI; the shipped example
|
|
33
|
+
world with a zero-API-key query tour lands once a verified run stamps it.
|
|
34
|
+
|
|
35
|
+
## What this is
|
|
36
|
+
|
|
37
|
+
A storage and retrieval substrate that lets a language model maintain a complete, queryable, durable model of a world — places, objects, people, relationships, histories, and unknowns — such that any state question is answered by a deterministic query, never by re-reading prose; the world accretes and is re-enterable; and the same engine serves authored fiction (a holodeck, a campaign, a mystery) and real-world tracking (a household, a job site, a vehicle), differing only in resolution policy and provenance discipline.
|
|
38
|
+
|
|
39
|
+
The buffer holds the pattern; materialization is re-entry; degradation is the failure we exist to prevent; the arch is how the operator steps outside the world to inspect it; and where nothing has been established, you don't get invented detail — **you see the grid.**
|
|
40
|
+
|
|
41
|
+
## Documents
|
|
42
|
+
|
|
43
|
+
- **[docs/WHITEPAPER.md](docs/WHITEPAPER.md)** — the canonical, comprehensive design reference. Principles, primitives, durability, frames, provenance, thunks, reference resolution, ingestion discipline, identity, the operation algebra, projection, both modes, embedding hazards, evaluation, and the decision record. Start here.
|
|
44
|
+
- **[docs/LEXICON.md](docs/LEXICON.md)** — the working vocabulary and its naming discipline.
|
|
45
|
+
- **[docs/ADOPTION.md](docs/ADOPTION.md)** — for agents (and humans) integrating the library: exact signatures, typed outcomes, the three-seam recipe, MUST/NEVER rules.
|
|
46
|
+
- **[docs/HOST-DISCIPLINE.md](docs/HOST-DISCIPLINE.md)** — the adopter's discipline brief: the seven categories every fact must be classified along to ingest with fidelity, and the structural retrieval strategies (the four correlation axes + the correlation sweep) to surface every relevant, related detail for any subject.
|
|
47
|
+
- **[docs/INGESTION-PLAYBOOK.md](docs/INGESTION-PLAYBOOK.md)** — evidence-based rules for deserializing narrative into a world: the extractor contract, feeding mechanics, what the gate guards, and measured ingestion baselines.
|
|
48
|
+
- **[docs/reference/assertion-world-model-original.md](docs/reference/assertion-world-model-original.md)** — the framework-agnostic design document this project was founded on, preserved verbatim for lineage.
|
|
49
|
+
|
|
50
|
+
## The road
|
|
51
|
+
|
|
52
|
+
1. ~~Recover and commit the *Last Honest Meter* eval seed (the chapter test's ground truth).~~ Done — v1-final, `evals/last_honest_meter/`.
|
|
53
|
+
2. ~~Engine spike: `PatternBuffer` + derived indexes + classifier + projector + resolver + `refer()` tier 1.~~ Done — `src/patternbuffer/`.
|
|
54
|
+
3. ~~The chapter test, runs 1–4~~: substrate validated; registry-first ingestion (INGEST-V2) landed; run 4 scored **22/33 (best graded run, all remaining failures extraction-class not shape-class)** — the substrate holds; ingestion fidelity (pass-0 registry quality) is the open score lever. Receipts: `evals/results/`.
|
|
55
|
+
4. ~~The shipped example world: `examples/anchor/`~~ — stamped (`STAMP.json`, run 4): a bible-verified noir mystery as a queryable database, with a zero-API-key scripted tour and 8 open truth-maintenance conflict flags shipped visibly (honesty is the product). Not yet packaged to PyPI.
|
|
56
|
+
5. ~~The messy-dialogue micro-eval (the honest bridge from fiction ingestion to tracking-mode ingestion).~~ Done — **10/10** on the reality-divergence battery (`evals/results/2026-06-12-micro-v1-final/`); tracking-mode ingestion validated against sloppy conversational fragments.
|
|
57
|
+
6. ~~The porcelain API + host integration.~~ Done — and proven in the strongest form. The frozen contract (`porcelain-v0.1`, additive-only): five load-bearing verbs — `ingest` (+`ingest_structured`) / `snapshot` / `ask` / `materialize` / `resolve`+`refer()` — over a fuller read-and-identity family (`state`, `where`, `aggregate`, `neighborhood`, `frame_diff`, `who_knows`, `correlate`, `route`, `entities`, `facts`, build sessions, `axis_heads`, …). The first *live* host, [Construct](https://github.com/5000Stadia/construct) (an interactive-fiction engine — `pattern` → `construct` loads it → `holonovel`), runs **entirely on this contract**: zero engine-internal reaches, its 800+-test suite green on the pure public surface. The engine-independent claim, demonstrated rather than asserted. (Intended primary host: [Kernos](https://github.com/5000Stadia/Kernos), adapter pattern.)
|
|
58
|
+
7. ~~The interactive-fiction milestone (thunk stability across sessions, frame-scoped NPCs, multi-path mystery, clocks, loop closure).~~ Met in the field — every item is exercised in [Construct](https://github.com/5000Stadia/construct)'s live suite (the first host runs entirely on the frozen porcelain). These are host-layer criteria, proven by the adopter, not a further engine deliverable.
|
|
59
|
+
8. ~~The MCP wrapper~~ — built: `pip install pbuffer[mcp]` → `patternbuffer-mcp --world w.world --world-id w:id` serves the frozen porcelain's **37 deterministic verbs** over stdio to any MCP client — read, query, and *build* a world with zero Python (the genuinely model-free subset; model-backed verbs are V1.1 via sampling). One server ↔ one world; a connected client is a fully **trusted world principal** — frame entitlement for untrusted consumers stays host-mediated. The framework-agnostic claim, proven by demonstration. Far field: the first host's V2 roadmap publicly assigns branch-worlds simulation and its curiosity loop to this engine — the two roadmaps meet in the middle.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pbuffer"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A world-state database: an append-only log of everything true in a world - places, people, objects, knowledge, time. Deploy it under a game, AI agent, or real-world tracker for permanent, queryable world memory: current state, location, history, and who-knows-what, answered by deterministic queries instead of model calls."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
dependencies = []
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
dev = ["pytest>=8"]
|
|
16
|
+
mcp = ["mcp>=1.28,<2"]
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
patternbuffer-mcp = "patternbuffer.mcp:main"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.packages.find]
|
|
22
|
+
where = ["src"]
|
|
23
|
+
|
|
24
|
+
[tool.pytest.ini_options]
|
|
25
|
+
testpaths = ["tests"]
|
|
26
|
+
addopts = "-q"
|
pbuffer-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"""patternbuffer: an append-only world-state substrate.
|
|
2
|
+
|
|
3
|
+
One append-only log of perspective-scoped, time-indexed assertions per
|
|
4
|
+
world; every other structure — current state, space, knowledge, history,
|
|
5
|
+
the rendered world — is a disposable projection over it.
|
|
6
|
+
|
|
7
|
+
The engine is host-blind: its single outside dependency is an injected
|
|
8
|
+
model callable ``(prompt, schema) -> json``. See docs/WHITEPAPER.md.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import time
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, Callable
|
|
16
|
+
|
|
17
|
+
from patternbuffer.buffer import PatternBuffer
|
|
18
|
+
from patternbuffer.classify import Classifier
|
|
19
|
+
from patternbuffer.identity import IdentityRegistry
|
|
20
|
+
from patternbuffer.indexes import Indexes
|
|
21
|
+
from patternbuffer.ingest import Ingestor
|
|
22
|
+
from patternbuffer.model import ATTR_PREFIX, CANON, META_ATTRIBUTES
|
|
23
|
+
from patternbuffer.project import Materialization, Projector
|
|
24
|
+
from patternbuffer.refer import Refer, Resolution
|
|
25
|
+
from patternbuffer.roles import _make_engine_roles
|
|
26
|
+
from patternbuffer.salience import SalienceIndex
|
|
27
|
+
from patternbuffer.semantics import AttributeSemantics
|
|
28
|
+
from patternbuffer.thunks import (
|
|
29
|
+
INVENT_UNDER_CANON,
|
|
30
|
+
OBSERVE_OR_UNKNOWN,
|
|
31
|
+
POLICIES,
|
|
32
|
+
Resolver,
|
|
33
|
+
)
|
|
34
|
+
from patternbuffer.tmaint import TruthMaintenance
|
|
35
|
+
|
|
36
|
+
__version__ = "0.0.1"
|
|
37
|
+
|
|
38
|
+
STANCES = frozenset({"fiction", "reality", "hypothetical"}) # letter 026; fixed enum
|
|
39
|
+
__all__ = ["World", "Materialization", "Resolution", "__version__"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class World:
|
|
43
|
+
"""The named, individual unit: one PatternBuffer + its physics
|
|
44
|
+
(resolution policy, decay configuration) + derived indexes (§16).
|
|
45
|
+
|
|
46
|
+
``World("campaign.world", world_id="w:campaign", model=callable)`` is
|
|
47
|
+
the entire harness interface — a parameter, not a framework. Role
|
|
48
|
+
capabilities are minted here and nowhere else.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
path: str | Path,
|
|
54
|
+
world_id: str,
|
|
55
|
+
model: Callable[[str, dict], Any] | None = None,
|
|
56
|
+
policy: str = INVENT_UNDER_CANON,
|
|
57
|
+
clock: Callable[[], float] = time.time,
|
|
58
|
+
stance: str = "fiction",
|
|
59
|
+
title: str = "",
|
|
60
|
+
description: str = "",
|
|
61
|
+
attribute_default: Callable[[str], dict | None] | None = None,
|
|
62
|
+
) -> None:
|
|
63
|
+
if policy not in POLICIES:
|
|
64
|
+
raise ValueError(f"unknown policy {policy!r}")
|
|
65
|
+
if stance not in STANCES:
|
|
66
|
+
raise ValueError(f"unknown stance {stance!r} (fixed enum; letter 026)")
|
|
67
|
+
self.world_id = world_id
|
|
68
|
+
self.policy = policy
|
|
69
|
+
self.buffer = PatternBuffer(path, world_id)
|
|
70
|
+
self.semantics = AttributeSemantics(self.buffer)
|
|
71
|
+
roles = _make_engine_roles()
|
|
72
|
+
self.classifier = Classifier(self.buffer, model or _no_model, self.semantics)
|
|
73
|
+
self.registry = IdentityRegistry(self.buffer, roles["ingestor"], self.semantics)
|
|
74
|
+
self.indexes = Indexes(
|
|
75
|
+
self.buffer, self.classifier, self.registry.resolve, self.semantics
|
|
76
|
+
)
|
|
77
|
+
self.indexes.set_closure_provider(self.registry.closure)
|
|
78
|
+
self.indexes.set_correlation_provider(self.registry.correlation_set)
|
|
79
|
+
self.registry.set_kind_provider(lambda e: self.indexes.fold_key(e, "kind"))
|
|
80
|
+
self.salience_index = SalienceIndex(self.buffer, self.classifier, self.indexes)
|
|
81
|
+
self.indexes.set_salience_provider(self.salience_index.salience)
|
|
82
|
+
self.truth = TruthMaintenance(
|
|
83
|
+
self.buffer, self.classifier, self.indexes, roles["truth_maintenance"],
|
|
84
|
+
self.semantics,
|
|
85
|
+
)
|
|
86
|
+
# SHAPE-FIX-V1 retype wiring: retraction authority + rules-mode
|
|
87
|
+
# durability for the corrected kind row (the set_kind_provider idiom —
|
|
88
|
+
# truth/classifier post-date the registry).
|
|
89
|
+
self.registry.set_retract_provider(self.truth.retract)
|
|
90
|
+
self.registry.set_classify_provider(
|
|
91
|
+
lambda rows: self.classifier.classify_rows(rows, model=False)
|
|
92
|
+
)
|
|
93
|
+
# Win 4 (durable-contradiction veto, HD 089): the registry reads
|
|
94
|
+
# standing folds + durability verdicts through late-bound lookups.
|
|
95
|
+
self.registry.set_fold_provider(self.indexes.fold_key)
|
|
96
|
+
self.registry.set_durability_provider(self.classifier.durability)
|
|
97
|
+
self.resolver = Resolver(
|
|
98
|
+
self.buffer, self.classifier, self.indexes, roles["resolver"],
|
|
99
|
+
model or _no_model, policy,
|
|
100
|
+
)
|
|
101
|
+
self.projector = Projector(
|
|
102
|
+
self.buffer, self.classifier, self.indexes, self.semantics,
|
|
103
|
+
self.salience_index.salience,
|
|
104
|
+
)
|
|
105
|
+
self.ingestor = Ingestor(
|
|
106
|
+
self.buffer, self.classifier, self.registry, roles["ingestor"],
|
|
107
|
+
model, observe_mode=(policy == OBSERVE_OR_UNKNOWN), clock=clock,
|
|
108
|
+
resolver_role=roles["resolver"],
|
|
109
|
+
semantics=self.semantics,
|
|
110
|
+
attribute_default=attribute_default,
|
|
111
|
+
# Write-time containment-cycle gate (HD 002): the ancestor walk
|
|
112
|
+
# is the derived containment chain — locate folds the family.
|
|
113
|
+
containment_ancestors=lambda parent, frame, vf: set(
|
|
114
|
+
self.indexes.locate(parent, frame=frame, valid_as_of=vf)
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
self.refer = Refer(self.buffer, self.indexes, self.registry, model,
|
|
118
|
+
ingestor=self.ingestor)
|
|
119
|
+
# The World Charter (letter 026): a fresh world's genesis write
|
|
120
|
+
# asserts its self-description — stance is ontological stored
|
|
121
|
+
# truth (does this world claim to describe reality?), distinct
|
|
122
|
+
# from operational policy. Ordinary appends; amendable forever.
|
|
123
|
+
if self.buffer.head() == 0:
|
|
124
|
+
charter = [
|
|
125
|
+
{"entity": "world:self", "attribute": "kind", "value": "world",
|
|
126
|
+
"timeless": True},
|
|
127
|
+
{"entity": "world:self", "attribute": "stance", "value": stance,
|
|
128
|
+
"timeless": True},
|
|
129
|
+
]
|
|
130
|
+
if title:
|
|
131
|
+
charter.append({"entity": "world:self", "attribute": "title",
|
|
132
|
+
"value": title, "timeless": True})
|
|
133
|
+
if description:
|
|
134
|
+
charter.append({"entity": "world:self", "attribute": "description",
|
|
135
|
+
"value": description, "timeless": True})
|
|
136
|
+
self.ingestor.classify_inline = False
|
|
137
|
+
self.ingest_structured(charter)
|
|
138
|
+
self.ingestor.classify_inline = True
|
|
139
|
+
for row in self.buffer.all_rows():
|
|
140
|
+
self.classifier.set(row.id, "CONSTITUTIVE", 1.0)
|
|
141
|
+
|
|
142
|
+
# Reads (deterministic, no LLM — P7).
|
|
143
|
+
|
|
144
|
+
def locate(self, entity: str, **kw) -> list[str]:
|
|
145
|
+
return self.indexes.locate(entity, **kw)
|
|
146
|
+
|
|
147
|
+
def contents(self, container: str, **kw) -> list[str]:
|
|
148
|
+
return self.indexes.contents(container, **kw)
|
|
149
|
+
|
|
150
|
+
# PLACE-FEATURE-ABSTRACTION-V1 — the compositional axis (part_of).
|
|
151
|
+
def composition(self, entity: str, **kw) -> list[str]:
|
|
152
|
+
return self.indexes.composition(entity, **kw)
|
|
153
|
+
|
|
154
|
+
def features(self, place: str, **kw) -> list[str]:
|
|
155
|
+
return self.indexes.features(place, **kw)
|
|
156
|
+
|
|
157
|
+
# WHO-KNOWS-INVERSE-V1 — the computed "who knows X" read.
|
|
158
|
+
def who_knows(self, entity: str, attribute: str, value: Any = None, **kw) -> list[str]:
|
|
159
|
+
return self.indexes.who_knows(entity, attribute, value, **kw)
|
|
160
|
+
|
|
161
|
+
def state(self, entity: str, attribute: str, frame: str = CANON, **kw):
|
|
162
|
+
return self.indexes.fold_key(entity, attribute, frame, **kw)
|
|
163
|
+
|
|
164
|
+
# AKA-CORRELATION-V1 — the explicit, opt-in correlated identity surface.
|
|
165
|
+
def state_union(self, entity: str, attribute: str, frame: str = CANON, **kw):
|
|
166
|
+
return self.indexes.state_union(entity, attribute, frame, **kw)
|
|
167
|
+
|
|
168
|
+
def correlations(self, entity: str, **kw) -> list[str]:
|
|
169
|
+
return self.registry.correlations(entity, **kw)
|
|
170
|
+
|
|
171
|
+
def correlate(self, a: str, b: str, evidence: str, **kw) -> dict:
|
|
172
|
+
return self.registry.correlate(a, b, evidence, **kw)
|
|
173
|
+
|
|
174
|
+
def correlation_conflicts(self, **kw) -> list[dict]:
|
|
175
|
+
return self.registry.correlation_conflicts(**kw)
|
|
176
|
+
|
|
177
|
+
def path(self, a: str, b: str, **kw) -> list[str] | None:
|
|
178
|
+
return self.indexes.path(a, b, **kw)
|
|
179
|
+
|
|
180
|
+
def route(self, a: str, b: str, **kw) -> dict:
|
|
181
|
+
return self.indexes.route(a, b, **kw)
|
|
182
|
+
|
|
183
|
+
def salience(
|
|
184
|
+
self, entity: str, frame: str = CANON, as_of: float | None = None
|
|
185
|
+
) -> float:
|
|
186
|
+
return self.salience_index.salience(entity, frame, as_of)
|
|
187
|
+
|
|
188
|
+
def confidence(
|
|
189
|
+
self,
|
|
190
|
+
entity: str,
|
|
191
|
+
attribute: str,
|
|
192
|
+
frame: str | list[str] = CANON,
|
|
193
|
+
as_of: float | None = None,
|
|
194
|
+
asserted_as_of: int | None = None,
|
|
195
|
+
) -> dict:
|
|
196
|
+
return self.indexes.confidence(
|
|
197
|
+
entity, attribute, frame=frame, as_of=as_of,
|
|
198
|
+
asserted_as_of=asserted_as_of,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def neighborhood(self, entity: str, **kw) -> dict:
|
|
202
|
+
return self.indexes.neighborhood(entity, **kw)
|
|
203
|
+
|
|
204
|
+
def aggregate(self, container: str, member_attribute: str, op: str, **kw) -> dict:
|
|
205
|
+
return self.indexes.aggregate(container, member_attribute, op, **kw)
|
|
206
|
+
|
|
207
|
+
def fidelity_audit(self, frame: str = CANON, as_of: float | None = None) -> dict:
|
|
208
|
+
"""Structural ingestion-fidelity gaps, derived (INGESTION-FIDELITY-V1).
|
|
209
|
+
Read-only; run after a build's classification + `truth.scan()` (it never
|
|
210
|
+
classifies or scans). The engine surfaces gaps; the host joins arc/cast
|
|
211
|
+
severity and drives targeted re-extraction."""
|
|
212
|
+
from patternbuffer.classify import EVENT, STATE
|
|
213
|
+
|
|
214
|
+
collisions = self.registry.name_collisions(frame=frame, valid_as_of=as_of)
|
|
215
|
+
|
|
216
|
+
unstamped: list[dict] = []
|
|
217
|
+
entities: set[str] = set()
|
|
218
|
+
for row in self.buffer.visible(frame=frame):
|
|
219
|
+
if row.entity.startswith("a:") or row.entity.startswith(ATTR_PREFIX):
|
|
220
|
+
continue
|
|
221
|
+
eid = self.registry.resolve(row.entity)
|
|
222
|
+
if eid.startswith(("obj:", "person:")):
|
|
223
|
+
entities.add(eid)
|
|
224
|
+
# Meta/identity edges (same_as/distinct_from/aka/source…) are
|
|
225
|
+
# classified EVENT and carry no valid_from BY DESIGN — bookkeeping,
|
|
226
|
+
# never a spine fact; they are not an unstamped gap.
|
|
227
|
+
if row.attribute in META_ATTRIBUTES:
|
|
228
|
+
continue
|
|
229
|
+
if row.valid_from is None and self.classifier.get(row.id) is not None \
|
|
230
|
+
and self.classifier.durability(row.id) in (STATE, EVENT):
|
|
231
|
+
unstamped.append({"entity": eid, "attribute": row.attribute,
|
|
232
|
+
"assertion_id": row.id})
|
|
233
|
+
|
|
234
|
+
orphans = sorted(
|
|
235
|
+
e for e in entities
|
|
236
|
+
if not self.indexes.locate(e, frame=frame, valid_as_of=as_of)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
conflicts = [
|
|
240
|
+
{"entity": c.entity, "attribute": c.attribute, "frame": c.frame,
|
|
241
|
+
"kind": c.kind, "assertion_ids": list(c.assertion_ids)}
|
|
242
|
+
for c in self.truth.open_conflicts()
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
live = sum(1 for g in collisions if g["live"])
|
|
246
|
+
return {
|
|
247
|
+
"frame": frame,
|
|
248
|
+
"name_collisions": collisions,
|
|
249
|
+
"unstamped_timed": unstamped,
|
|
250
|
+
"orphan_entities": orphans,
|
|
251
|
+
"open_conflicts": conflicts,
|
|
252
|
+
"summary": {
|
|
253
|
+
"name_collisions": live, # live-fragmentation groups only
|
|
254
|
+
"name_collisions_total": len(collisions),
|
|
255
|
+
"unstamped_timed": len(unstamped),
|
|
256
|
+
"orphan_entities": len(orphans),
|
|
257
|
+
"open_conflicts": len(conflicts),
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
def materialize(self, scope, **kw) -> Materialization:
|
|
262
|
+
return self.projector.materialize(scope, **kw)
|
|
263
|
+
|
|
264
|
+
# Writes (each behind its role).
|
|
265
|
+
|
|
266
|
+
def ingest(self, text: str, context: str = "", frame: str | None = None,
|
|
267
|
+
classify: str = "inline", extract: str = "full",
|
|
268
|
+
cursor_authoritative: bool = False, pov: str | None = None) -> list:
|
|
269
|
+
return self.ingestor.ingest(text, context, frame=frame, classify=classify,
|
|
270
|
+
extract=extract,
|
|
271
|
+
cursor_authoritative=cursor_authoritative,
|
|
272
|
+
pov=pov)
|
|
273
|
+
|
|
274
|
+
def extract(self, text: str, context: str = "", extract: str = "full",
|
|
275
|
+
pov: str | None = None) -> list:
|
|
276
|
+
"""Read-only extraction (INGEST-LATENCY-V2): the host parallelizes these,
|
|
277
|
+
then ingest_structured()s the results serially. No write. `pov`
|
|
278
|
+
(SHAPE-FIX-V1 4c): the viewpoint entity id for deixis binding."""
|
|
279
|
+
return self.ingestor.extract(text, context, extract=extract, pov=pov)
|
|
280
|
+
|
|
281
|
+
def ingest_structured(self, items: list[dict], frame: str | None = None,
|
|
282
|
+
classify: str = "inline",
|
|
283
|
+
cursor_authoritative: bool = False) -> list:
|
|
284
|
+
return self.ingestor.ingest_structured(
|
|
285
|
+
items, frame=frame, classify=classify,
|
|
286
|
+
cursor_authoritative=cursor_authoritative)
|
|
287
|
+
|
|
288
|
+
def resolve(self, entity: str, aspect: str, frame: str = CANON, access=None):
|
|
289
|
+
return self.resolver.resolve(entity, aspect, frame, access)
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def porcelain(self):
|
|
293
|
+
"""The frozen host surface (PORCELAIN-V1). Lazy; import-local to
|
|
294
|
+
avoid circularity."""
|
|
295
|
+
if not hasattr(self, "_porcelain"):
|
|
296
|
+
from patternbuffer.porcelain import Porcelain
|
|
297
|
+
self._porcelain = Porcelain(self)
|
|
298
|
+
return self._porcelain
|
|
299
|
+
|
|
300
|
+
def charter(self) -> dict[str, Any]:
|
|
301
|
+
"""The world's self-description, read from world:self (letter 026)."""
|
|
302
|
+
out: dict[str, Any] = {}
|
|
303
|
+
for attr, result in self.indexes.current_state("world:self").items():
|
|
304
|
+
if result.winner is not None:
|
|
305
|
+
out[attr] = result.winner.value
|
|
306
|
+
return out
|
|
307
|
+
|
|
308
|
+
def close(self) -> None:
|
|
309
|
+
# An open build session never outlives the buffer: abort (restore the
|
|
310
|
+
# classify toggle, classify nothing) before closing (BUILD-SESSION-V1).
|
|
311
|
+
if hasattr(self, "_porcelain"):
|
|
312
|
+
self._porcelain.abort_build()
|
|
313
|
+
self.buffer.close()
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _no_model(prompt: str, schema: dict) -> Any:
|
|
317
|
+
raise RuntimeError("no model callable injected for this operation")
|