context-compiler 0.9.1__tar.gz → 0.9.2__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.
- {context_compiler-0.9.1 → context_compiler-0.9.2}/PKG-INFO +9 -7
- {context_compiler-0.9.1 → context_compiler-0.9.2}/README.md +8 -6
- {context_compiler-0.9.1 → context_compiler-0.9.2}/pyproject.toml +1 -1
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/engine.py +24 -20
- {context_compiler-0.9.1 → context_compiler-0.9.2}/.gitignore +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/LICENSE +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/01_llm_contradiction_error.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/02_llm_constraint_guardrail.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/03_llm_premise_guardrail.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/04_llm_tool_denylist_guardrail.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/05_llm_prompt_drift_vs_state.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/06_llm_context_compaction.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/07_llm_prompt_vs_state.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/08_llm_replacement_precondition.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/README.md +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/__init__.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/common.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/llm_client.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/run_demo.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/01_persistent_guardrails.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/02_configuration_and_correction.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/03_ambiguity_with_error.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/04_tool_governance_denylist.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/05_llm_integration_pattern.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/06_step_sequence_and_state_restore.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/07_single_policy_correction.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/08_apply_directive_decisions.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/README.md +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/_util.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/host_support/__init__.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/host_support/provider_mode.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/__init__.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/const.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/decision.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/grammar.py +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/py.typed +0 -0
- {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/repl.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: context-compiler
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.2
|
|
4
4
|
Summary: Deterministic conversational state engine for LLM applications.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rlippmann/context-compiler
|
|
6
6
|
Project-URL: Repository, https://github.com/rlippmann/context-compiler
|
|
@@ -27,9 +27,11 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
[](https://pypi.org/project/context-compiler/)
|
|
28
28
|
[](https://codecov.io/gh/rlippmann/context-compiler)
|
|
29
29
|
|
|
30
|
-
Context Compiler
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
Context Compiler maintains host-side working memory consisting of a premise and
|
|
31
|
+
policies, separate from the model's conversational context. The Engine applies
|
|
32
|
+
directives to that working memory so applications can maintain explicit state
|
|
33
|
+
across model interactions without relying on the model to remember or infer it.
|
|
34
|
+
It blocks invalid or conflicting changes and returns structured decisions.
|
|
33
35
|
|
|
34
36
|
Use it when saved context and policy rules need to shape what an application
|
|
35
37
|
does, not just what the model sees or says.
|
|
@@ -112,7 +114,7 @@ repair behavior.
|
|
|
112
114
|
|
|
113
115
|
## State Model
|
|
114
116
|
|
|
115
|
-
|
|
117
|
+
Working memory contains explicit user commitments:
|
|
116
118
|
|
|
117
119
|
| State | Meaning |
|
|
118
120
|
| --- | --- |
|
|
@@ -142,8 +144,8 @@ To replace an existing `use` policy:
|
|
|
142
144
|
use podman instead of docker
|
|
143
145
|
```
|
|
144
146
|
|
|
145
|
-
If `docker` is absent from
|
|
146
|
-
unchanged. It does not become plain `use podman`.
|
|
147
|
+
If `docker` is absent from working memory, the replacement fails and leaves
|
|
148
|
+
working memory unchanged. It does not become plain `use podman`.
|
|
147
149
|
|
|
148
150
|
To remove a policy or clear state:
|
|
149
151
|
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
[](https://pypi.org/project/context-compiler/)
|
|
6
6
|
[](https://codecov.io/gh/rlippmann/context-compiler)
|
|
7
7
|
|
|
8
|
-
Context Compiler
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Context Compiler maintains host-side working memory consisting of a premise and
|
|
9
|
+
policies, separate from the model's conversational context. The Engine applies
|
|
10
|
+
directives to that working memory so applications can maintain explicit state
|
|
11
|
+
across model interactions without relying on the model to remember or infer it.
|
|
12
|
+
It blocks invalid or conflicting changes and returns structured decisions.
|
|
11
13
|
|
|
12
14
|
Use it when saved context and policy rules need to shape what an application
|
|
13
15
|
does, not just what the model sees or says.
|
|
@@ -90,7 +92,7 @@ repair behavior.
|
|
|
90
92
|
|
|
91
93
|
## State Model
|
|
92
94
|
|
|
93
|
-
|
|
95
|
+
Working memory contains explicit user commitments:
|
|
94
96
|
|
|
95
97
|
| State | Meaning |
|
|
96
98
|
| --- | --- |
|
|
@@ -120,8 +122,8 @@ To replace an existing `use` policy:
|
|
|
120
122
|
use podman instead of docker
|
|
121
123
|
```
|
|
122
124
|
|
|
123
|
-
If `docker` is absent from
|
|
124
|
-
unchanged. It does not become plain `use podman`.
|
|
125
|
+
If `docker` is absent from working memory, the replacement fails and leaves
|
|
126
|
+
working memory unchanged. It does not become plain `use podman`.
|
|
125
127
|
|
|
126
128
|
To remove a policy or clear state:
|
|
127
129
|
|
|
@@ -27,8 +27,8 @@ from .grammar import CanonicalDirective, DirectiveKind, decompose_directive
|
|
|
27
27
|
PolicyValue = Literal["use", "prohibit"]
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
31
|
-
"""Versioned
|
|
30
|
+
class _WorkingMemory(TypedDict):
|
|
31
|
+
"""Versioned internal working memory."""
|
|
32
32
|
|
|
33
33
|
premise: str | None
|
|
34
34
|
policies: dict[str, PolicyValue]
|
|
@@ -37,7 +37,7 @@ class _State(TypedDict):
|
|
|
37
37
|
|
|
38
38
|
class _EvaluatedTransition(TypedDict):
|
|
39
39
|
decision: UpdateDecision | SemanticErrorDecision
|
|
40
|
-
next_state:
|
|
40
|
+
next_state: _WorkingMemory
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
_NO_DIRECTIVE = NoDirectiveDecision()
|
|
@@ -46,28 +46,28 @@ _NO_DIRECTIVE = NoDirectiveDecision()
|
|
|
46
46
|
class Engine:
|
|
47
47
|
"""Own the authoritative state and apply one directive transition at a time."""
|
|
48
48
|
|
|
49
|
-
__slots__ = ("
|
|
49
|
+
__slots__ = ("_working_memory",)
|
|
50
50
|
|
|
51
51
|
def __init__(self) -> None:
|
|
52
|
-
self.
|
|
52
|
+
self._working_memory: _WorkingMemory
|
|
53
53
|
self._replace_state(_initial_state())
|
|
54
54
|
|
|
55
55
|
@property
|
|
56
56
|
def premise(self) -> str | None:
|
|
57
57
|
"""Return the current premise from authoritative state."""
|
|
58
58
|
|
|
59
|
-
return self.
|
|
59
|
+
return self._working_memory[STATE_PREMISE]
|
|
60
60
|
|
|
61
61
|
@property
|
|
62
62
|
def policies(self) -> Mapping[str, PolicyValue]:
|
|
63
63
|
"""Return a defensive copy of the current policy mapping."""
|
|
64
64
|
|
|
65
|
-
return deepcopy(self.
|
|
65
|
+
return deepcopy(self._working_memory[STATE_POLICIES])
|
|
66
66
|
|
|
67
67
|
def export_json(self) -> str:
|
|
68
68
|
"""Serialize the current authoritative state to canonical JSON text."""
|
|
69
69
|
|
|
70
|
-
return json.dumps(self.
|
|
70
|
+
return json.dumps(self._working_memory, sort_keys=True, separators=(",", ":"))
|
|
71
71
|
|
|
72
72
|
def import_json(self, payload: str) -> None:
|
|
73
73
|
"""Replace authoritative state from previously exported JSON text.
|
|
@@ -100,12 +100,12 @@ class Engine:
|
|
|
100
100
|
) -> UpdateDecision | SemanticErrorDecision:
|
|
101
101
|
"""Evaluate and commit one canonical directive against authoritative state."""
|
|
102
102
|
|
|
103
|
-
evaluated = self._evaluate_directive_transition(self.
|
|
103
|
+
evaluated = self._evaluate_directive_transition(self._working_memory, directive)
|
|
104
104
|
self._replace_state(evaluated["next_state"])
|
|
105
105
|
return evaluated["decision"]
|
|
106
106
|
|
|
107
107
|
def _evaluate_directive_transition(
|
|
108
|
-
self, state:
|
|
108
|
+
self, state: _WorkingMemory, directive: CanonicalDirective
|
|
109
109
|
) -> _EvaluatedTransition:
|
|
110
110
|
error_decision = self._pre_mutation_error(directive, state=state)
|
|
111
111
|
if error_decision is not None:
|
|
@@ -117,13 +117,13 @@ class Engine:
|
|
|
117
117
|
"next_state": next_state,
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
def _replace_state(self, state:
|
|
121
|
-
self.
|
|
120
|
+
def _replace_state(self, state: _WorkingMemory) -> None:
|
|
121
|
+
self._working_memory = state
|
|
122
122
|
|
|
123
123
|
def _pre_mutation_error(
|
|
124
|
-
self, directive: CanonicalDirective, *, state:
|
|
124
|
+
self, directive: CanonicalDirective, *, state: _WorkingMemory | None = None
|
|
125
125
|
) -> SemanticErrorDecision | None:
|
|
126
|
-
candidate_state = self.
|
|
126
|
+
candidate_state = self._working_memory if state is None else state
|
|
127
127
|
# Single error path: all error outcomes are detected before any mutation.
|
|
128
128
|
if (
|
|
129
129
|
directive.kind is DirectiveKind.SET_PREMISE
|
|
@@ -203,7 +203,9 @@ class Engine:
|
|
|
203
203
|
|
|
204
204
|
return None
|
|
205
205
|
|
|
206
|
-
def _apply_directive(
|
|
206
|
+
def _apply_directive(
|
|
207
|
+
self, directive: CanonicalDirective, *, state: _WorkingMemory
|
|
208
|
+
) -> _WorkingMemory:
|
|
207
209
|
next_state = deepcopy(state)
|
|
208
210
|
|
|
209
211
|
if directive.kind is DirectiveKind.SET_PREMISE:
|
|
@@ -249,7 +251,9 @@ class Engine:
|
|
|
249
251
|
|
|
250
252
|
return _initial_state()
|
|
251
253
|
|
|
252
|
-
def _apply_replacement_explicit(
|
|
254
|
+
def _apply_replacement_explicit(
|
|
255
|
+
self, state: _WorkingMemory, new_item: str, old_item: str
|
|
256
|
+
) -> None:
|
|
253
257
|
new_key = _normalize_item(new_item)
|
|
254
258
|
old_key = _normalize_item(old_item)
|
|
255
259
|
|
|
@@ -260,7 +264,7 @@ class Engine:
|
|
|
260
264
|
state[STATE_POLICIES][new_key] = POLICY_USE
|
|
261
265
|
|
|
262
266
|
|
|
263
|
-
def _initial_state() ->
|
|
267
|
+
def _initial_state() -> _WorkingMemory:
|
|
264
268
|
return {
|
|
265
269
|
STATE_PREMISE: None,
|
|
266
270
|
STATE_POLICIES: {},
|
|
@@ -268,7 +272,7 @@ def _initial_state() -> _State:
|
|
|
268
272
|
}
|
|
269
273
|
|
|
270
274
|
|
|
271
|
-
def _load_state_json(payload: str) ->
|
|
275
|
+
def _load_state_json(payload: str) -> _WorkingMemory:
|
|
272
276
|
try:
|
|
273
277
|
raw = json.loads(payload)
|
|
274
278
|
except json.JSONDecodeError as exc:
|
|
@@ -277,7 +281,7 @@ def _load_state_json(payload: str) -> _State:
|
|
|
277
281
|
return _load_state_obj(raw)
|
|
278
282
|
|
|
279
283
|
|
|
280
|
-
def _load_state_obj(raw: object) ->
|
|
284
|
+
def _load_state_obj(raw: object) -> _WorkingMemory:
|
|
281
285
|
if not isinstance(raw, dict):
|
|
282
286
|
raise ValueError("Invalid state payload.")
|
|
283
287
|
|
|
@@ -379,5 +383,5 @@ def _repair_set_premise(value: str) -> CanonicalDirective:
|
|
|
379
383
|
)
|
|
380
384
|
|
|
381
385
|
|
|
382
|
-
def _update_decision(previous_state:
|
|
386
|
+
def _update_decision(previous_state: _WorkingMemory, next_state: _WorkingMemory) -> UpdateDecision:
|
|
383
387
|
return UpdateDecision(changed=previous_state != next_state)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.1 → context_compiler-0.9.2}/examples/02_configuration_and_correction.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.1 → context_compiler-0.9.2}/examples/06_step_sequence_and_state_restore.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|