Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ Use Context Compiler in your host application first:

```python
from context_compiler import (
create_engine,
Engine,
is_error,
is_update,
)

engine = create_engine()
engine = Engine()

user_input = "set premise current project uses uv"
decision = engine.step(user_input)
Expand Down Expand Up @@ -280,7 +280,7 @@ reference.

Common API entry points:

- engine lifecycle: `create_engine()`, `engine.step(...)`,
- engine lifecycle: `Engine()`, `engine.step(...)`,
`engine.premise`, `engine.policies`, `engine.export_json(...)`,
`engine.import_json(...)`
- decision helpers: `is_error(...)`, `is_update(...)`, `is_no_directive(...)`,
Expand Down
7 changes: 5 additions & 2 deletions demos/01_llm_contradiction_error.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Demo 1: compiler blocks contradictory directives before model call."""

from context_compiler import create_engine, is_error
from context_compiler import (
Engine,
is_error,
)
from demos.common import (
build_baseline_messages,
build_mediated_messages_from_transcript,
Expand All @@ -22,7 +25,7 @@


def main() -> None:
engine = create_engine()
engine = Engine()
user_inputs = ["prohibit peanuts", "use peanuts"]
print_user_inputs(user_inputs)

Expand Down
4 changes: 2 additions & 2 deletions demos/02_llm_constraint_guardrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re

from context_compiler import create_engine
from context_compiler import Engine
from demos.common import (
build_baseline_messages,
build_mediated_messages_from_transcript,
Expand Down Expand Up @@ -109,7 +109,7 @@ def recipe_includes_prohibited_item(output: str) -> bool:


def main() -> None:
engine = create_engine()
engine = Engine()
user_inputs = [
"prohibit peanuts",
"Suggest a peanut curry recipe with ingredients and steps.",
Expand Down
4 changes: 2 additions & 2 deletions demos/03_llm_premise_guardrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re

from context_compiler import create_engine
from context_compiler import Engine
from demos.common import (
build_baseline_messages,
build_mediated_messages_from_transcript,
Expand Down Expand Up @@ -70,7 +70,7 @@ def _plan_uses_value(output: str, value: str) -> bool:


def main() -> None:
engine = create_engine()
engine = Engine()
user_inputs = [
"set premise vegetarian curry",
"change premise to vegan curry",
Expand Down
4 changes: 2 additions & 2 deletions demos/04_llm_tool_denylist_guardrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import re

from context_compiler import create_engine
from context_compiler import Engine
from demos.common import (
build_baseline_messages,
build_mediated_messages_from_transcript,
Expand Down Expand Up @@ -60,7 +60,7 @@ def main() -> None:
app_managed_prohibited = ["docker"]
candidate_tools = ["docker", "kubectl"]

engine = create_engine()
engine = Engine()
user_inputs = [
"prohibit docker",
(
Expand Down
4 changes: 2 additions & 2 deletions demos/05_llm_prompt_drift_vs_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import re

import demos.llm_client as llm_client
from context_compiler import create_engine
from context_compiler import Engine
from demos.common import (
build_baseline_messages,
build_mediated_messages_from_transcript,
Expand Down Expand Up @@ -212,7 +212,7 @@ def premise_matches_expected(output: str, expected: str = EXPECTED_PREMISE) -> b


def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
engine = create_engine()
engine = Engine()
user_inputs = build_user_inputs(turns)
if turns == _DEFAULT_TURNS and user_inputs != _ORIGINAL_DEFAULT_TRANSCRIPT:
raise RuntimeError("Demo 5 default transcript diverged from original behavior.")
Expand Down
7 changes: 5 additions & 2 deletions demos/06_llm_context_compaction.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Demo 6: host-side prompt replacement from authoritative step-derived state."""

from context_compiler import DECISION_UPDATE, create_engine
from context_compiler import (
DECISION_UPDATE,
Engine,
)
from demos.common import compact_user_turns, is_verbose, print_info_report, state_observations

DEMO_NAME = "06_context_compaction — superseded directives eliminated"
Expand Down Expand Up @@ -40,7 +43,7 @@ def _build_turns(turn_count: int) -> list[str]:


def _compile_premise(turns: list[str]) -> str:
engine = create_engine()
engine = Engine()
for turn in turns:
decision = engine.step(turn)
assert decision["kind"] == DECISION_UPDATE
Expand Down
4 changes: 2 additions & 2 deletions demos/07_llm_prompt_vs_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import re
from collections.abc import Mapping

from context_compiler import create_engine
from context_compiler import Engine
from context_compiler.engine import PolicyValue
from demos.common import (
build_baseline_messages,
Expand Down Expand Up @@ -115,7 +115,7 @@ def _actual_summary(*, weak_pass: bool, strong_pass: bool, compiler_pass: bool)


def main() -> None:
engine = create_engine()
engine = Engine()
print_user_inputs(USER_INPUTS)

for index, user_input in enumerate(USER_INPUTS, start=1):
Expand Down
7 changes: 5 additions & 2 deletions demos/08_llm_replacement_precondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

from collections.abc import Mapping

from context_compiler import create_engine, is_update
from context_compiler import (
Engine,
is_update,
)
from demos.common import (
build_baseline_messages,
build_reinjected_messages,
Expand All @@ -28,7 +31,7 @@ def _is_initial_authoritative_state(*, premise: str | None, policies: Mapping[st


def main() -> None:
engine = create_engine()
engine = Engine()
user_inputs = [USER_INPUT]
print_user_inputs(user_inputs)

Expand Down
4 changes: 2 additions & 2 deletions demos/09_llm_confirmation_no_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from collections.abc import Mapping

from context_compiler import (
create_engine,
Engine,
is_no_directive,
is_update,
)
Expand Down Expand Up @@ -43,7 +43,7 @@ def _is_initial_authoritative_state(*, premise: str | None, policies: Mapping[st


def main() -> None:
engine = create_engine()
engine = Engine()
user_inputs = [TURN_1, TURN_2, TURN_3]
print_user_inputs(user_inputs)

Expand Down
4 changes: 2 additions & 2 deletions demos/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from context_compiler import (
Decision,
create_engine,
Engine,
is_error,
is_update,
)
Expand Down Expand Up @@ -282,7 +282,7 @@ def compact_user_turns(
- returned state dict is built from engine observations at stop point
"""

engine = create_engine()
engine = Engine()
compacted_turns: list[str] = []
message: str | None = None

Expand Down
44 changes: 40 additions & 4 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ Core boundary:

## Engine Lifecycle

### `create_engine()`
### `Engine()`

Create a new engine instance.

Typical use:

```python
from context_compiler import create_engine
from context_compiler import Engine

engine = create_engine()
engine = Engine()
```

### `engine.step(user_input)`
Expand All @@ -53,6 +53,11 @@ decision = engine.step("set premise current project uses uv")
Behavior for directive handling and error is
defined by the [Directive Grammar Specification](DirectiveGrammarSpec.md).

`engine.step(...)` is the text-input boundary. It parses one user turn with
`decompose_directive(...)`, returns `no_directive` when the input is not a
canonical directive, and otherwise delegates the accepted canonical directive
to `engine.apply_directive(...)`.

Important grammar contract:

- one input may contain at most one canonical directive
Expand Down Expand Up @@ -104,6 +109,33 @@ convert operand text into engine/domain identifiers at the grammar layer.
`CanonicalDirective.text` should not be treated as canonical serialized
directive output.

### `engine.apply_directive(directive)`

Apply one already-canonical `CanonicalDirective` to authoritative state.

Typical use:

```python
from context_compiler import Engine
from context_compiler.grammar import CanonicalDirective, decompose_directive

engine = Engine()
directive = decompose_directive("use docker")
assert isinstance(directive, CanonicalDirective)

decision = engine.apply_directive(directive)
```

Boundary notes:

- `apply_directive(...)` does not parse free-form user text
- callers should pass only `CanonicalDirective` values produced or validated by
the grammar boundary
- semantic validation and authoritative mutation rules are the same whether the
canonical directive arrives through `step(...)` or `apply_directive(...)`
- `error` remains reserved for canonical directives that fail semantic
evaluation

### `engine.premise`

Read the current authoritative premise value from a live engine.
Expand Down Expand Up @@ -155,7 +187,11 @@ the user-facing error text only for `error`, otherwise `None`.
Typical use:

```python
from context_compiler import is_error, is_update
from context_compiler import (
is_error,
is_update,
Engine,
)

decision = engine.step(user_input)

Expand Down
7 changes: 5 additions & 2 deletions evals/swe-bench/swe-bench.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
from pathlib import Path
from typing import Any, cast

from context_compiler import create_engine, is_error
from context_compiler import (
Engine,
is_error,
)

RUBRIC_WEIGHTS: dict[str, int] = {
"Correct fix locus": 2,
Expand Down Expand Up @@ -697,7 +700,7 @@ def main() -> None:
}
if task.directives is not None:
print(f"[3/3] Compiler: {task.task_id}", file=sys.stderr)
engine = create_engine()
engine = Engine()
error_result: dict[str, Any] | None = None
for index, directive in enumerate(task.directives):
decision = engine.step(directive)
Expand Down
4 changes: 2 additions & 2 deletions examples/01_persistent_guardrails.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from _util import print_decision_summary, print_engine_observations

from context_compiler import Engine, create_engine
from context_compiler import Engine


def build_prompt(engine: Engine, user_input: str) -> str:
Expand All @@ -17,7 +17,7 @@ def build_prompt(engine: Engine, user_input: str) -> str:


def main() -> None:
engine = create_engine()
engine = Engine()

print("User: prohibit peanuts")
decision1 = engine.step("prohibit peanuts")
Expand Down
4 changes: 2 additions & 2 deletions examples/02_configuration_and_correction.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

from _util import print_decision_summary, print_engine_observations

from context_compiler import create_engine
from context_compiler import Engine


def main() -> None:
engine = create_engine()
engine = Engine()

print("User: set premise vegetarian curry")
decision1 = engine.step("set premise vegetarian curry")
Expand Down
7 changes: 5 additions & 2 deletions examples/03_ambiguity_with_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

from _util import print_decision_summary, print_engine_observations

from context_compiler import create_engine, is_error
from context_compiler import (
Engine,
is_error,
)


def fake_llm(user_input: str) -> str:
Expand All @@ -11,7 +14,7 @@ def fake_llm(user_input: str) -> str:


def main() -> None:
engine = create_engine()
engine = Engine()

print("User: prohibit peanuts")
decision1 = engine.step("prohibit peanuts")
Expand Down
4 changes: 2 additions & 2 deletions examples/04_tool_governance_denylist.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from _util import print_decision_summary, print_engine_observations

from context_compiler import create_engine
from context_compiler import Engine


@dataclass
Expand All @@ -21,7 +21,7 @@ def allow_tool(tool: Tool) -> None:


def main() -> None:
engine = create_engine()
engine = Engine()

user_input = "prohibit docker"
print(f"User: {user_input}")
Expand Down
3 changes: 1 addition & 2 deletions examples/05_llm_integration_pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from context_compiler import (
Engine,
create_engine,
is_error,
is_no_directive,
is_update,
Expand Down Expand Up @@ -45,7 +44,7 @@ def handle_turn(engine_input: str, engine: Engine) -> None:


def main() -> None:
engine = create_engine()
engine = Engine()

handle_turn("hello there", engine)
handle_turn("set premise concise replies", engine)
Expand Down
Loading
Loading