From d0a4369fe21113e983d1f502b9622a79a9ae0c46 Mon Sep 17 00:00:00 2001 From: Robert Lippmann Date: Tue, 8 Sep 2026 09:15:53 -0400 Subject: [PATCH 1/3] refactor: rename internal state abstraction --- README.md | 8 +++++--- src/context_compiler/engine.py | 30 +++++++++++++++++------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 85d83cd..084e74b 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,11 @@ [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/) [![codecov](https://codecov.io/gh/rlippmann/context-compiler/branch/main/graph/badge.svg)](https://codecov.io/gh/rlippmann/context-compiler) -Context Compiler helps LLM applications keep explicit premise and policy rules -stable across turns. It blocks invalid or conflicting changes and returns -structured decisions. +Context Compiler keeps a host-side working memory of premise and policy rules, +separate from the model's conversational context. The Engine applies +directives to that working memory so applications can carry explicit state +across model interactions without relying on the model to remember or infer +it. It blocks invalid or conflicting changes and returns structured decisions. Use it when saved context and policy rules need to shape what an application does, not just what the model sees or says. diff --git a/src/context_compiler/engine.py b/src/context_compiler/engine.py index 7a439c9..62923df 100644 --- a/src/context_compiler/engine.py +++ b/src/context_compiler/engine.py @@ -27,8 +27,8 @@ PolicyValue = Literal["use", "prohibit"] -class _State(TypedDict): - """Versioned authoritative state.""" +class _WorkingMemory(TypedDict): + """Versioned internal working memory.""" premise: str | None policies: dict[str, PolicyValue] @@ -37,7 +37,7 @@ class _State(TypedDict): class _EvaluatedTransition(TypedDict): decision: UpdateDecision | SemanticErrorDecision - next_state: _State + next_state: _WorkingMemory _NO_DIRECTIVE = NoDirectiveDecision() @@ -49,7 +49,7 @@ class Engine: __slots__ = ("_state",) def __init__(self) -> None: - self._state: _State + self._state: _WorkingMemory self._replace_state(_initial_state()) @property @@ -105,7 +105,7 @@ def apply_directive( return evaluated["decision"] def _evaluate_directive_transition( - self, state: _State, directive: CanonicalDirective + self, state: _WorkingMemory, directive: CanonicalDirective ) -> _EvaluatedTransition: error_decision = self._pre_mutation_error(directive, state=state) if error_decision is not None: @@ -117,11 +117,11 @@ def _evaluate_directive_transition( "next_state": next_state, } - def _replace_state(self, state: _State) -> None: + def _replace_state(self, state: _WorkingMemory) -> None: self._state = state def _pre_mutation_error( - self, directive: CanonicalDirective, *, state: _State | None = None + self, directive: CanonicalDirective, *, state: _WorkingMemory | None = None ) -> SemanticErrorDecision | None: candidate_state = self._state if state is None else state # Single error path: all error outcomes are detected before any mutation. @@ -203,7 +203,9 @@ def _pre_mutation_error( return None - def _apply_directive(self, directive: CanonicalDirective, *, state: _State) -> _State: + def _apply_directive( + self, directive: CanonicalDirective, *, state: _WorkingMemory + ) -> _WorkingMemory: next_state = deepcopy(state) if directive.kind is DirectiveKind.SET_PREMISE: @@ -249,7 +251,9 @@ def _apply_directive(self, directive: CanonicalDirective, *, state: _State) -> _ return _initial_state() - def _apply_replacement_explicit(self, state: _State, new_item: str, old_item: str) -> None: + def _apply_replacement_explicit( + self, state: _WorkingMemory, new_item: str, old_item: str + ) -> None: new_key = _normalize_item(new_item) old_key = _normalize_item(old_item) @@ -260,7 +264,7 @@ def _apply_replacement_explicit(self, state: _State, new_item: str, old_item: st state[STATE_POLICIES][new_key] = POLICY_USE -def _initial_state() -> _State: +def _initial_state() -> _WorkingMemory: return { STATE_PREMISE: None, STATE_POLICIES: {}, @@ -268,7 +272,7 @@ def _initial_state() -> _State: } -def _load_state_json(payload: str) -> _State: +def _load_state_json(payload: str) -> _WorkingMemory: try: raw = json.loads(payload) except json.JSONDecodeError as exc: @@ -277,7 +281,7 @@ def _load_state_json(payload: str) -> _State: return _load_state_obj(raw) -def _load_state_obj(raw: object) -> _State: +def _load_state_obj(raw: object) -> _WorkingMemory: if not isinstance(raw, dict): raise ValueError("Invalid state payload.") @@ -379,5 +383,5 @@ def _repair_set_premise(value: str) -> CanonicalDirective: ) -def _update_decision(previous_state: _State, next_state: _State) -> UpdateDecision: +def _update_decision(previous_state: _WorkingMemory, next_state: _WorkingMemory) -> UpdateDecision: return UpdateDecision(changed=previous_state != next_state) From beeff6f5777af1e27d9578611ed47ef4d77df418 Mon Sep 17 00:00:00 2001 From: Robert Lippmann Date: Tue, 8 Sep 2026 09:19:52 -0400 Subject: [PATCH 2/3] docs: clarify working memory terminology --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 084e74b..5c7511b 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/) [![codecov](https://codecov.io/gh/rlippmann/context-compiler/branch/main/graph/badge.svg)](https://codecov.io/gh/rlippmann/context-compiler) -Context Compiler keeps a host-side working memory of premise and policy rules, -separate from the model's conversational context. The Engine applies -directives to that working memory so applications can carry explicit state -across model interactions without relying on the model to remember or infer -it. It blocks invalid or conflicting changes and returns structured decisions. +Context Compiler keeps host-side working memory consisting of a premise and +policies, separate from the model's conversational context. The Engine applies +directives to that working memory so applications can maintain explicit state +across model interactions without relying on the model to remember or infer it. +It blocks invalid or conflicting changes and returns structured decisions. Use it when saved context and policy rules need to shape what an application does, not just what the model sees or says. @@ -92,7 +92,7 @@ repair behavior. ## State Model -The engine stores explicit user commitments as saved state: +Working memory contains explicit user commitments: | State | Meaning | | --- | --- | From ddc0735b12b871960e5ed6b6d3315e0a1cdbc1c5 Mon Sep 17 00:00:00 2001 From: Robert Lippmann Date: Tue, 8 Sep 2026 09:22:49 -0400 Subject: [PATCH 3/3] docs: align working memory wording --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c7511b..6534b98 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/) [![codecov](https://codecov.io/gh/rlippmann/context-compiler/branch/main/graph/badge.svg)](https://codecov.io/gh/rlippmann/context-compiler) -Context Compiler keeps host-side working memory consisting of a premise and +Context Compiler maintains host-side working memory consisting of a premise and policies, separate from the model's conversational context. The Engine applies directives to that working memory so applications can maintain explicit state across model interactions without relying on the model to remember or infer it. @@ -122,8 +122,8 @@ To replace an existing `use` policy: use podman instead of docker ``` -If `docker` is absent from saved state, the replacement fails and leaves state -unchanged. It does not become plain `use podman`. +If `docker` is absent from working memory, the replacement fails and leaves +working memory unchanged. It does not become plain `use podman`. To remove a policy or clear state: