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.
Files changed (37) hide show
  1. {context_compiler-0.9.1 → context_compiler-0.9.2}/PKG-INFO +9 -7
  2. {context_compiler-0.9.1 → context_compiler-0.9.2}/README.md +8 -6
  3. {context_compiler-0.9.1 → context_compiler-0.9.2}/pyproject.toml +1 -1
  4. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/engine.py +24 -20
  5. {context_compiler-0.9.1 → context_compiler-0.9.2}/.gitignore +0 -0
  6. {context_compiler-0.9.1 → context_compiler-0.9.2}/LICENSE +0 -0
  7. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/01_llm_contradiction_error.py +0 -0
  8. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/02_llm_constraint_guardrail.py +0 -0
  9. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/03_llm_premise_guardrail.py +0 -0
  10. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/04_llm_tool_denylist_guardrail.py +0 -0
  11. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/05_llm_prompt_drift_vs_state.py +0 -0
  12. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/06_llm_context_compaction.py +0 -0
  13. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/07_llm_prompt_vs_state.py +0 -0
  14. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/08_llm_replacement_precondition.py +0 -0
  15. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/README.md +0 -0
  16. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/__init__.py +0 -0
  17. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/common.py +0 -0
  18. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/llm_client.py +0 -0
  19. {context_compiler-0.9.1 → context_compiler-0.9.2}/demos/run_demo.py +0 -0
  20. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/01_persistent_guardrails.py +0 -0
  21. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/02_configuration_and_correction.py +0 -0
  22. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/03_ambiguity_with_error.py +0 -0
  23. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/04_tool_governance_denylist.py +0 -0
  24. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/05_llm_integration_pattern.py +0 -0
  25. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/06_step_sequence_and_state_restore.py +0 -0
  26. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/07_single_policy_correction.py +0 -0
  27. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/08_apply_directive_decisions.py +0 -0
  28. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/README.md +0 -0
  29. {context_compiler-0.9.1 → context_compiler-0.9.2}/examples/_util.py +0 -0
  30. {context_compiler-0.9.1 → context_compiler-0.9.2}/host_support/__init__.py +0 -0
  31. {context_compiler-0.9.1 → context_compiler-0.9.2}/host_support/provider_mode.py +0 -0
  32. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/__init__.py +0 -0
  33. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/const.py +0 -0
  34. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/decision.py +0 -0
  35. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/grammar.py +0 -0
  36. {context_compiler-0.9.1 → context_compiler-0.9.2}/src/context_compiler/py.typed +0 -0
  37. {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.1
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
  [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/)
28
28
  [![codecov](https://codecov.io/gh/rlippmann/context-compiler/branch/main/graph/badge.svg)](https://codecov.io/gh/rlippmann/context-compiler)
29
29
 
30
- Context Compiler helps LLM applications keep explicit premise and policy rules
31
- stable across turns. It blocks invalid or conflicting changes and returns
32
- structured decisions.
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
- The engine stores explicit user commitments as saved state:
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 saved state, the replacement fails and leaves state
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
  [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/)
6
6
  [![codecov](https://codecov.io/gh/rlippmann/context-compiler/branch/main/graph/badge.svg)](https://codecov.io/gh/rlippmann/context-compiler)
7
7
 
8
- Context Compiler helps LLM applications keep explicit premise and policy rules
9
- stable across turns. It blocks invalid or conflicting changes and returns
10
- structured decisions.
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
- The engine stores explicit user commitments as saved state:
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 saved state, the replacement fails and leaves state
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
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "context-compiler"
7
- version = "0.9.1"
7
+ version = "0.9.2"
8
8
  description = "Deterministic conversational state engine for LLM applications."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -27,8 +27,8 @@ from .grammar import CanonicalDirective, DirectiveKind, decompose_directive
27
27
  PolicyValue = Literal["use", "prohibit"]
28
28
 
29
29
 
30
- class _State(TypedDict):
31
- """Versioned authoritative state."""
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: _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__ = ("_state",)
49
+ __slots__ = ("_working_memory",)
50
50
 
51
51
  def __init__(self) -> None:
52
- self._state: _State
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._state[STATE_PREMISE]
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._state[STATE_POLICIES])
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._state, sort_keys=True, separators=(",", ":"))
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._state, directive)
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: _State, directive: CanonicalDirective
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: _State) -> None:
121
- self._state = state
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: _State | None = None
124
+ self, directive: CanonicalDirective, *, state: _WorkingMemory | None = None
125
125
  ) -> SemanticErrorDecision | None:
126
- candidate_state = self._state if state is None else state
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(self, directive: CanonicalDirective, *, state: _State) -> _State:
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(self, state: _State, new_item: str, old_item: str) -> None:
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() -> _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) -> _State:
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) -> _State:
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: _State, next_state: _State) -> UpdateDecision:
386
+ def _update_decision(previous_state: _WorkingMemory, next_state: _WorkingMemory) -> UpdateDecision:
383
387
  return UpdateDecision(changed=previous_state != next_state)