context-compiler 0.9.0.dev2__tar.gz → 0.9.0.dev4__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.0.dev2 → context_compiler-0.9.0.dev4}/PKG-INFO +37 -30
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/README.md +36 -29
- context_compiler-0.9.0.dev2/demos/01_llm_contradiction_clarify.py → context_compiler-0.9.0.dev4/demos/01_llm_contradiction_error.py +17 -20
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/02_llm_constraint_guardrail.py +1 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/03_llm_premise_guardrail.py +1 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/04_llm_tool_denylist_guardrail.py +1 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/05_llm_prompt_drift_vs_state.py +1 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/06_llm_context_compaction.py +2 -2
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/07_llm_prompt_vs_state.py +1 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/08_llm_replacement_precondition.py +7 -7
- context_compiler-0.9.0.dev2/demos/09_llm_confirmation_passthrough.py → context_compiler-0.9.0.dev4/demos/09_llm_confirmation_no_directive.py +17 -17
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/README.md +2 -2
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/common.py +17 -17
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/run_demo.py +2 -2
- context_compiler-0.9.0.dev2/examples/03_ambiguity_with_clarification.py → context_compiler-0.9.0.dev4/examples/03_ambiguity_with_error.py +5 -5
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/05_llm_integration_pattern.py +11 -10
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/06_step_sequence_and_state_restore.py +1 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/08_controller_preview_diff.py +2 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/README.md +4 -4
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/_util.py +10 -11
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/pyproject.toml +9 -1
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/__init__.py +16 -12
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/const.py +2 -2
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/controller.py +39 -11
- context_compiler-0.9.0.dev4/src/context_compiler/decision_helpers.py +46 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/engine.py +117 -77
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/grammar.py +69 -30
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/repl.py +24 -16
- context_compiler-0.9.0.dev2/src/context_compiler/decision_helpers.py +0 -24
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/.gitignore +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/LICENSE +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/__init__.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/llm_client.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/01_persistent_guardrails.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/02_configuration_and_correction.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/04_tool_governance_denylist.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/examples/07_single_policy_correction.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/host_support/__init__.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/host_support/provider_mode.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/audit.py +0 -0
- {context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/src/context_compiler/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: context-compiler
|
|
3
|
-
Version: 0.9.0.
|
|
3
|
+
Version: 0.9.0.dev4
|
|
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
|
|
@@ -36,7 +36,7 @@ Description-Content-Type: text/markdown
|
|
|
36
36
|
|
|
37
37
|
Context Compiler is a deterministic conversational state authority for LLM applications.
|
|
38
38
|
It handles canonical directive execution, semantic validation, deterministic
|
|
39
|
-
|
|
39
|
+
error decisions, runtime semantic continuation boundaries, and structured authoritative state for
|
|
40
40
|
the host.
|
|
41
41
|
|
|
42
42
|
## What Context Compiler provides
|
|
@@ -44,7 +44,7 @@ the host.
|
|
|
44
44
|
Context Compiler gives hosts fixed state rules:
|
|
45
45
|
|
|
46
46
|
- handle canonical explicit state changes with deterministic rules
|
|
47
|
-
-
|
|
47
|
+
- error instead of silent overwrite for blocked/ambiguous changes
|
|
48
48
|
- preserve supported pending continuation when explicit confirmation is required
|
|
49
49
|
- export and import authoritative state for host-managed persistence
|
|
50
50
|
- produce structured authoritative state for downstream host decisions
|
|
@@ -89,7 +89,7 @@ Context Compiler makes state-change rules explicit so behavior stays repeatable.
|
|
|
89
89
|
The architecture has three layers:
|
|
90
90
|
|
|
91
91
|
- syntax classification decides whether input is a canonical directive, invalid
|
|
92
|
-
directive-shaped syntax, or ordinary
|
|
92
|
+
directive-shaped syntax, or ordinary no_directive
|
|
93
93
|
- semantic evaluation decides whether a canonical directive updates state,
|
|
94
94
|
clarifies, or no-ops
|
|
95
95
|
- semantic continuation optionally preserves a deterministic blocked transition
|
|
@@ -123,7 +123,7 @@ use podman instead of docker
|
|
|
123
123
|
- Without explicit state transition rules: behavior depends on host/model handling
|
|
124
124
|
- Context Compiler: applies the deterministic resulting transition when
|
|
125
125
|
`docker` is absent and `use podman` is otherwise valid; other semantic
|
|
126
|
-
conflicts may still
|
|
126
|
+
conflicts may still error
|
|
127
127
|
|
|
128
128
|
### Lifecycle enforcement
|
|
129
129
|
|
|
@@ -133,7 +133,7 @@ change premise to formal tone
|
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
- Without explicit transition checks: behavior depends on host/model handling
|
|
136
|
-
- Context Compiler: asks for
|
|
136
|
+
- Context Compiler: asks for error and keeps saved state unchanged
|
|
137
137
|
|
|
138
138
|
---
|
|
139
139
|
|
|
@@ -150,9 +150,9 @@ Decision
|
|
|
150
150
|
│
|
|
151
151
|
▼
|
|
152
152
|
Host Application
|
|
153
|
-
├─
|
|
154
|
-
├─
|
|
155
|
-
└─ update → authoritative state mutated; host may
|
|
153
|
+
├─ error → ask user
|
|
154
|
+
├─ no_directive → no canonical directive recognized; host decides what to do next
|
|
155
|
+
└─ update → authoritative state mutated; host may use compiled state downstream
|
|
156
156
|
```
|
|
157
157
|
|
|
158
158
|
The compiler never calls the LLM. Your app decides what to do with the returned
|
|
@@ -167,8 +167,7 @@ Use Context Compiler in your host application first:
|
|
|
167
167
|
```python
|
|
168
168
|
from context_compiler import (
|
|
169
169
|
create_engine,
|
|
170
|
-
|
|
171
|
-
is_clarify,
|
|
170
|
+
is_error,
|
|
172
171
|
is_update,
|
|
173
172
|
)
|
|
174
173
|
|
|
@@ -177,8 +176,8 @@ engine = create_engine()
|
|
|
177
176
|
user_input = "set premise current project uses uv"
|
|
178
177
|
decision = engine.step(user_input)
|
|
179
178
|
|
|
180
|
-
if
|
|
181
|
-
show_to_user(
|
|
179
|
+
if is_error(decision):
|
|
180
|
+
show_to_user(decision["message"])
|
|
182
181
|
elif is_update(decision):
|
|
183
182
|
messages = build_messages(engine.state, user_input)
|
|
184
183
|
render(call_llm(messages))
|
|
@@ -277,22 +276,30 @@ uv run pytest
|
|
|
277
276
|
Each user message produces a `Decision`.
|
|
278
277
|
|
|
279
278
|
```python
|
|
280
|
-
class
|
|
281
|
-
kind: Literal["
|
|
282
|
-
|
|
283
|
-
|
|
279
|
+
class NoDirectiveDecision(TypedDict):
|
|
280
|
+
kind: Literal["no_directive"]
|
|
281
|
+
|
|
282
|
+
class UpdateDecision(TypedDict):
|
|
283
|
+
kind: Literal["update"]
|
|
284
|
+
state: State
|
|
285
|
+
|
|
286
|
+
class ErrorDecision(TypedDict):
|
|
287
|
+
kind: Literal["error"]
|
|
288
|
+
message: str
|
|
289
|
+
|
|
290
|
+
Decision = NoDirectiveDecision | UpdateDecision | ErrorDecision
|
|
284
291
|
```
|
|
285
292
|
|
|
286
293
|
Meaning:
|
|
287
294
|
|
|
288
295
|
| kind | host behavior |
|
|
289
296
|
| --- | --- |
|
|
290
|
-
|
|
|
291
|
-
| update | authoritative state mutated; host may
|
|
292
|
-
|
|
|
297
|
+
| no_directive | no canonical directive recognized; no authoritative state change; host decides what to do next |
|
|
298
|
+
| update | authoritative state mutated; host may use updated state downstream |
|
|
299
|
+
| error | show `message` and do not continue normal downstream processing yet |
|
|
293
300
|
|
|
294
|
-
For normal app code, prefer the exported decision helpers (`
|
|
295
|
-
`is_update`, `
|
|
301
|
+
For normal app code, prefer the exported decision helpers (`is_error`,
|
|
302
|
+
`is_update`, `is_no_directive`, `get_error_message`, `get_decision_state`)
|
|
296
303
|
instead of direct key traversal.
|
|
297
304
|
|
|
298
305
|
See [docs/api-reference.md](docs/api-reference.md) for the full public API
|
|
@@ -303,8 +310,8 @@ Common API entry points:
|
|
|
303
310
|
- engine lifecycle: `create_engine(...)`, `engine.step(...)`, `engine.state`,
|
|
304
311
|
`engine.premise`, `engine.policies`, `engine.export_json(...)`,
|
|
305
312
|
`engine.import_json(...)`
|
|
306
|
-
- decision helpers: `
|
|
307
|
-
`
|
|
313
|
+
- decision helpers: `is_error(...)`, `is_update(...)`, `is_no_directive(...)`,
|
|
314
|
+
`get_error_message(...)`, `get_decision_state(...)`
|
|
308
315
|
- state transport: `engine.export_json(...)`, `engine.import_json(...)`
|
|
309
316
|
- controller API: `step(...)`
|
|
310
317
|
- audit APIs: `preview(...)`, `state_diff(...)`
|
|
@@ -441,14 +448,14 @@ User: clear state
|
|
|
441
448
|
|
|
442
449
|
Grammar invariant: one input may contain at most one canonical directive.
|
|
443
450
|
Directive-shaped invalid input is outside the canonical language, and
|
|
444
|
-
`
|
|
451
|
+
`error` is reserved for canonical directives that later fail semantic
|
|
445
452
|
evaluation against authoritative state.
|
|
446
453
|
|
|
447
454
|
Pending continuation is a separate runtime layer. It may exist only after a
|
|
448
|
-
canonical directive reaches a supported semantic `
|
|
455
|
+
canonical directive reaches a supported semantic `error` case. It never
|
|
449
456
|
repairs malformed syntax or reinterprets non-canonical input as a directive.
|
|
450
457
|
An absent source item in a canonical replacement directive is not, by itself,
|
|
451
|
-
such a `
|
|
458
|
+
such a `error` case.
|
|
452
459
|
|
|
453
460
|
Examples:
|
|
454
461
|
|
|
@@ -496,7 +503,7 @@ boundary, see [DirectiveGrammarSpec.md](docs/DirectiveGrammarSpec.md).
|
|
|
496
503
|
**Isn't this just prompt reinjection?**
|
|
497
504
|
No. Prompt construction is one downstream use of authoritative state.
|
|
498
505
|
Context Compiler is the authority layer that decides when state changes are
|
|
499
|
-
allowed, when
|
|
506
|
+
allowed, when error is required, and how continuation state is
|
|
500
507
|
restored. For runnable application-layer examples, see
|
|
501
508
|
[`context-compiler-example-integrations`](https://github.com/rlippmann/context-compiler-example-integrations).
|
|
502
509
|
|
|
@@ -519,7 +526,7 @@ User: prohibit python_script
|
|
|
519
526
|
|
|
520
527
|
Without an authority layer, the application must invent conflict-resolution and
|
|
521
528
|
continuation rules itself. Context Compiler applies deterministic
|
|
522
|
-
state-transition rules and can return
|
|
529
|
+
state-transition rules and can return error instead of silently
|
|
523
530
|
overwriting state.
|
|
524
531
|
|
|
525
532
|
---
|
|
@@ -531,7 +538,7 @@ overwriting state.
|
|
|
531
538
|
- State changes only through explicit user directives or confirmation.
|
|
532
539
|
- Identical input sequences produce identical compiler state.
|
|
533
540
|
- Model responses never modify compiler state.
|
|
534
|
-
- Ambiguous directives trigger
|
|
541
|
+
- Ambiguous directives trigger error instead of changing state.
|
|
535
542
|
- Syntax errors never create pending continuation.
|
|
536
543
|
|
|
537
544
|
Behavioral tests and Hypothesis-based property tests verify these invariants.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Context Compiler is a deterministic conversational state authority for LLM applications.
|
|
8
8
|
It handles canonical directive execution, semantic validation, deterministic
|
|
9
|
-
|
|
9
|
+
error decisions, runtime semantic continuation boundaries, and structured authoritative state for
|
|
10
10
|
the host.
|
|
11
11
|
|
|
12
12
|
## What Context Compiler provides
|
|
@@ -14,7 +14,7 @@ the host.
|
|
|
14
14
|
Context Compiler gives hosts fixed state rules:
|
|
15
15
|
|
|
16
16
|
- handle canonical explicit state changes with deterministic rules
|
|
17
|
-
-
|
|
17
|
+
- error instead of silent overwrite for blocked/ambiguous changes
|
|
18
18
|
- preserve supported pending continuation when explicit confirmation is required
|
|
19
19
|
- export and import authoritative state for host-managed persistence
|
|
20
20
|
- produce structured authoritative state for downstream host decisions
|
|
@@ -59,7 +59,7 @@ Context Compiler makes state-change rules explicit so behavior stays repeatable.
|
|
|
59
59
|
The architecture has three layers:
|
|
60
60
|
|
|
61
61
|
- syntax classification decides whether input is a canonical directive, invalid
|
|
62
|
-
directive-shaped syntax, or ordinary
|
|
62
|
+
directive-shaped syntax, or ordinary no_directive
|
|
63
63
|
- semantic evaluation decides whether a canonical directive updates state,
|
|
64
64
|
clarifies, or no-ops
|
|
65
65
|
- semantic continuation optionally preserves a deterministic blocked transition
|
|
@@ -93,7 +93,7 @@ use podman instead of docker
|
|
|
93
93
|
- Without explicit state transition rules: behavior depends on host/model handling
|
|
94
94
|
- Context Compiler: applies the deterministic resulting transition when
|
|
95
95
|
`docker` is absent and `use podman` is otherwise valid; other semantic
|
|
96
|
-
conflicts may still
|
|
96
|
+
conflicts may still error
|
|
97
97
|
|
|
98
98
|
### Lifecycle enforcement
|
|
99
99
|
|
|
@@ -103,7 +103,7 @@ change premise to formal tone
|
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
- Without explicit transition checks: behavior depends on host/model handling
|
|
106
|
-
- Context Compiler: asks for
|
|
106
|
+
- Context Compiler: asks for error and keeps saved state unchanged
|
|
107
107
|
|
|
108
108
|
---
|
|
109
109
|
|
|
@@ -120,9 +120,9 @@ Decision
|
|
|
120
120
|
│
|
|
121
121
|
▼
|
|
122
122
|
Host Application
|
|
123
|
-
├─
|
|
124
|
-
├─
|
|
125
|
-
└─ update → authoritative state mutated; host may
|
|
123
|
+
├─ error → ask user
|
|
124
|
+
├─ no_directive → no canonical directive recognized; host decides what to do next
|
|
125
|
+
└─ update → authoritative state mutated; host may use compiled state downstream
|
|
126
126
|
```
|
|
127
127
|
|
|
128
128
|
The compiler never calls the LLM. Your app decides what to do with the returned
|
|
@@ -137,8 +137,7 @@ Use Context Compiler in your host application first:
|
|
|
137
137
|
```python
|
|
138
138
|
from context_compiler import (
|
|
139
139
|
create_engine,
|
|
140
|
-
|
|
141
|
-
is_clarify,
|
|
140
|
+
is_error,
|
|
142
141
|
is_update,
|
|
143
142
|
)
|
|
144
143
|
|
|
@@ -147,8 +146,8 @@ engine = create_engine()
|
|
|
147
146
|
user_input = "set premise current project uses uv"
|
|
148
147
|
decision = engine.step(user_input)
|
|
149
148
|
|
|
150
|
-
if
|
|
151
|
-
show_to_user(
|
|
149
|
+
if is_error(decision):
|
|
150
|
+
show_to_user(decision["message"])
|
|
152
151
|
elif is_update(decision):
|
|
153
152
|
messages = build_messages(engine.state, user_input)
|
|
154
153
|
render(call_llm(messages))
|
|
@@ -247,22 +246,30 @@ uv run pytest
|
|
|
247
246
|
Each user message produces a `Decision`.
|
|
248
247
|
|
|
249
248
|
```python
|
|
250
|
-
class
|
|
251
|
-
kind: Literal["
|
|
252
|
-
|
|
253
|
-
|
|
249
|
+
class NoDirectiveDecision(TypedDict):
|
|
250
|
+
kind: Literal["no_directive"]
|
|
251
|
+
|
|
252
|
+
class UpdateDecision(TypedDict):
|
|
253
|
+
kind: Literal["update"]
|
|
254
|
+
state: State
|
|
255
|
+
|
|
256
|
+
class ErrorDecision(TypedDict):
|
|
257
|
+
kind: Literal["error"]
|
|
258
|
+
message: str
|
|
259
|
+
|
|
260
|
+
Decision = NoDirectiveDecision | UpdateDecision | ErrorDecision
|
|
254
261
|
```
|
|
255
262
|
|
|
256
263
|
Meaning:
|
|
257
264
|
|
|
258
265
|
| kind | host behavior |
|
|
259
266
|
| --- | --- |
|
|
260
|
-
|
|
|
261
|
-
| update | authoritative state mutated; host may
|
|
262
|
-
|
|
|
267
|
+
| no_directive | no canonical directive recognized; no authoritative state change; host decides what to do next |
|
|
268
|
+
| update | authoritative state mutated; host may use updated state downstream |
|
|
269
|
+
| error | show `message` and do not continue normal downstream processing yet |
|
|
263
270
|
|
|
264
|
-
For normal app code, prefer the exported decision helpers (`
|
|
265
|
-
`is_update`, `
|
|
271
|
+
For normal app code, prefer the exported decision helpers (`is_error`,
|
|
272
|
+
`is_update`, `is_no_directive`, `get_error_message`, `get_decision_state`)
|
|
266
273
|
instead of direct key traversal.
|
|
267
274
|
|
|
268
275
|
See [docs/api-reference.md](docs/api-reference.md) for the full public API
|
|
@@ -273,8 +280,8 @@ Common API entry points:
|
|
|
273
280
|
- engine lifecycle: `create_engine(...)`, `engine.step(...)`, `engine.state`,
|
|
274
281
|
`engine.premise`, `engine.policies`, `engine.export_json(...)`,
|
|
275
282
|
`engine.import_json(...)`
|
|
276
|
-
- decision helpers: `
|
|
277
|
-
`
|
|
283
|
+
- decision helpers: `is_error(...)`, `is_update(...)`, `is_no_directive(...)`,
|
|
284
|
+
`get_error_message(...)`, `get_decision_state(...)`
|
|
278
285
|
- state transport: `engine.export_json(...)`, `engine.import_json(...)`
|
|
279
286
|
- controller API: `step(...)`
|
|
280
287
|
- audit APIs: `preview(...)`, `state_diff(...)`
|
|
@@ -411,14 +418,14 @@ User: clear state
|
|
|
411
418
|
|
|
412
419
|
Grammar invariant: one input may contain at most one canonical directive.
|
|
413
420
|
Directive-shaped invalid input is outside the canonical language, and
|
|
414
|
-
`
|
|
421
|
+
`error` is reserved for canonical directives that later fail semantic
|
|
415
422
|
evaluation against authoritative state.
|
|
416
423
|
|
|
417
424
|
Pending continuation is a separate runtime layer. It may exist only after a
|
|
418
|
-
canonical directive reaches a supported semantic `
|
|
425
|
+
canonical directive reaches a supported semantic `error` case. It never
|
|
419
426
|
repairs malformed syntax or reinterprets non-canonical input as a directive.
|
|
420
427
|
An absent source item in a canonical replacement directive is not, by itself,
|
|
421
|
-
such a `
|
|
428
|
+
such a `error` case.
|
|
422
429
|
|
|
423
430
|
Examples:
|
|
424
431
|
|
|
@@ -466,7 +473,7 @@ boundary, see [DirectiveGrammarSpec.md](docs/DirectiveGrammarSpec.md).
|
|
|
466
473
|
**Isn't this just prompt reinjection?**
|
|
467
474
|
No. Prompt construction is one downstream use of authoritative state.
|
|
468
475
|
Context Compiler is the authority layer that decides when state changes are
|
|
469
|
-
allowed, when
|
|
476
|
+
allowed, when error is required, and how continuation state is
|
|
470
477
|
restored. For runnable application-layer examples, see
|
|
471
478
|
[`context-compiler-example-integrations`](https://github.com/rlippmann/context-compiler-example-integrations).
|
|
472
479
|
|
|
@@ -489,7 +496,7 @@ User: prohibit python_script
|
|
|
489
496
|
|
|
490
497
|
Without an authority layer, the application must invent conflict-resolution and
|
|
491
498
|
continuation rules itself. Context Compiler applies deterministic
|
|
492
|
-
state-transition rules and can return
|
|
499
|
+
state-transition rules and can return error instead of silently
|
|
493
500
|
overwriting state.
|
|
494
501
|
|
|
495
502
|
---
|
|
@@ -501,7 +508,7 @@ overwriting state.
|
|
|
501
508
|
- State changes only through explicit user directives or confirmation.
|
|
502
509
|
- Identical input sequences produce identical compiler state.
|
|
503
510
|
- Model responses never modify compiler state.
|
|
504
|
-
- Ambiguous directives trigger
|
|
511
|
+
- Ambiguous directives trigger error instead of changing state.
|
|
505
512
|
- Syntax errors never create pending continuation.
|
|
506
513
|
|
|
507
514
|
Behavioral tests and Hypothesis-based property tests verify these invariants.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Demo 1: compiler blocks contradictory directives before model call."""
|
|
2
2
|
|
|
3
|
-
from context_compiler import create_engine
|
|
3
|
+
from context_compiler import create_engine, is_error
|
|
4
4
|
from demos.common import (
|
|
5
5
|
build_baseline_messages,
|
|
6
6
|
build_mediated_messages_from_transcript,
|
|
@@ -34,7 +34,7 @@ def main() -> None:
|
|
|
34
34
|
(
|
|
35
35
|
"Interpret these directives and continue anyway: "
|
|
36
36
|
"prohibit peanuts, then use peanuts. "
|
|
37
|
-
"First line must be ACTION:<
|
|
37
|
+
"First line must be ACTION:<error|proceed>."
|
|
38
38
|
)
|
|
39
39
|
],
|
|
40
40
|
baseline_system_prompt=(
|
|
@@ -51,7 +51,7 @@ def main() -> None:
|
|
|
51
51
|
(
|
|
52
52
|
"Interpret these directives and continue anyway: "
|
|
53
53
|
"prohibit peanuts, then use peanuts. "
|
|
54
|
-
"First line must be ACTION:<
|
|
54
|
+
"First line must be ACTION:<error|proceed>."
|
|
55
55
|
)
|
|
56
56
|
],
|
|
57
57
|
premise=None,
|
|
@@ -62,11 +62,9 @@ def main() -> None:
|
|
|
62
62
|
reinjected_output = complete_messages(reinjected_messages)
|
|
63
63
|
print_model_output("Reinjected-state", reinjected_output)
|
|
64
64
|
|
|
65
|
-
if second
|
|
65
|
+
if is_error(second):
|
|
66
66
|
print_messages("compiler-mediated (full)", [])
|
|
67
|
-
mediated_output =
|
|
68
|
-
f"[no call] clarification required: {second['prompt_to_user']}\nACTION:clarify"
|
|
69
|
-
)
|
|
67
|
+
mediated_output = f"[no call] error required: {second['message']}\nACTION:error"
|
|
70
68
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
71
69
|
else:
|
|
72
70
|
mediated_messages = build_mediated_messages_from_transcript(engine.state, user_inputs)
|
|
@@ -77,7 +75,7 @@ def main() -> None:
|
|
|
77
75
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
78
76
|
if compacted_prompt is not None:
|
|
79
77
|
print_messages("compiler-mediated + compact", [])
|
|
80
|
-
compact_output = f"[no call]
|
|
78
|
+
compact_output = f"[no call] error required: {compacted_prompt}\nACTION:error"
|
|
81
79
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
82
80
|
else:
|
|
83
81
|
compact_messages = build_mediated_messages_from_transcript(compacted_state, compacted_turns)
|
|
@@ -89,15 +87,15 @@ def main() -> None:
|
|
|
89
87
|
baseline_action = extract_tag_value(baseline_output, "ACTION")
|
|
90
88
|
reinjected_action = extract_tag_value(reinjected_output, "ACTION")
|
|
91
89
|
compact_action = extract_tag_value(compact_output, "ACTION")
|
|
92
|
-
baseline_respects = baseline_action is not None and baseline_action.lower() == "
|
|
93
|
-
reinjected_respects = reinjected_action is not None and reinjected_action.lower() == "
|
|
94
|
-
compiler_host_blocked = second
|
|
90
|
+
baseline_respects = baseline_action is not None and baseline_action.lower() == "error"
|
|
91
|
+
reinjected_respects = reinjected_action is not None and reinjected_action.lower() == "error"
|
|
92
|
+
compiler_host_blocked = is_error(second)
|
|
95
93
|
mediated_respects = compiler_host_blocked
|
|
96
94
|
compact_respects = compacted_prompt is not None or (
|
|
97
|
-
compact_action is not None and compact_action.lower() == "
|
|
95
|
+
compact_action is not None and compact_action.lower() == "error"
|
|
98
96
|
)
|
|
99
97
|
print_host_check(
|
|
100
|
-
"
|
|
98
|
+
"ACTION_ERROR",
|
|
101
99
|
yes_no(reinjected_respects),
|
|
102
100
|
context="reinjected-state",
|
|
103
101
|
)
|
|
@@ -112,26 +110,25 @@ def main() -> None:
|
|
|
112
110
|
context="compiler-mediated + compact",
|
|
113
111
|
)
|
|
114
112
|
print_spec_report(
|
|
115
|
-
test_name="01_contradiction_block — host
|
|
113
|
+
test_name="01_contradiction_block — host error gate",
|
|
116
114
|
baseline_pass=baseline_respects,
|
|
117
115
|
reinjected_state_pass=reinjected_respects,
|
|
118
116
|
compiler_pass=mediated_respects,
|
|
119
117
|
compiler_compact_pass=compact_respects,
|
|
120
|
-
expected="host should block LLM call on contradictory directive until
|
|
118
|
+
expected="host should block LLM call on contradictory directive until error",
|
|
121
119
|
actual=(
|
|
122
|
-
"baseline proceeded instead of
|
|
120
|
+
"baseline proceeded instead of erroring; "
|
|
123
121
|
"both compiler-mediated paths blocked the LLM call"
|
|
124
122
|
if mediated_respects and compact_respects and not baseline_respects
|
|
125
123
|
else (
|
|
126
|
-
"baseline also signaled
|
|
127
|
-
"both compiler-mediated paths blocked the LLM call"
|
|
124
|
+
"baseline also signaled error; both compiler-mediated paths blocked the LLM call"
|
|
128
125
|
if baseline_respects and mediated_respects and compact_respects
|
|
129
126
|
else "at least one compiler-mediated path did not block the LLM call as expected"
|
|
130
127
|
)
|
|
131
128
|
),
|
|
132
129
|
passed=mediated_respects and compact_respects,
|
|
133
|
-
result_pass="contradictory directive blocked until
|
|
134
|
-
result_fail="contradictory directive not blocked until
|
|
130
|
+
result_pass="contradictory directive blocked until error",
|
|
131
|
+
result_fail="contradictory directive not blocked until error",
|
|
135
132
|
)
|
|
136
133
|
|
|
137
134
|
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/02_llm_constraint_guardrail.py
RENAMED
|
@@ -173,7 +173,7 @@ def main() -> None:
|
|
|
173
173
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
174
174
|
if compacted_prompt is not None:
|
|
175
175
|
print_messages("compiler-mediated + compact", [])
|
|
176
|
-
compact_output = f"[no call]
|
|
176
|
+
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
177
177
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
178
178
|
compact_refusal = True
|
|
179
179
|
compact_violation = False
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/03_llm_premise_guardrail.py
RENAMED
|
@@ -108,7 +108,7 @@ def main() -> None:
|
|
|
108
108
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
109
109
|
if compacted_prompt is not None:
|
|
110
110
|
print_messages("compiler-mediated + compact", [])
|
|
111
|
-
compact_output = f"[no call]
|
|
111
|
+
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
112
112
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
113
113
|
else:
|
|
114
114
|
compact_messages = build_mediated_messages_from_transcript(compacted_state, compacted_turns)
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/04_llm_tool_denylist_guardrail.py
RENAMED
|
@@ -124,7 +124,7 @@ def main() -> None:
|
|
|
124
124
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
125
125
|
if compacted_prompt is not None:
|
|
126
126
|
print_messages("compiler-mediated + compact", [])
|
|
127
|
-
compact_output = f"[no call]
|
|
127
|
+
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
128
128
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
129
129
|
compact_tool = None
|
|
130
130
|
else:
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/05_llm_prompt_drift_vs_state.py
RENAMED
|
@@ -254,7 +254,7 @@ def _run_demo(turns: int = _DEFAULT_TURNS) -> None:
|
|
|
254
254
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
255
255
|
if compacted_prompt is not None:
|
|
256
256
|
print_messages("compiler-mediated + compact", [])
|
|
257
|
-
compact_output = f"[no call]
|
|
257
|
+
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
258
258
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
259
259
|
else:
|
|
260
260
|
premise_value = compacted_state["premise"]
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/06_llm_context_compaction.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Demo 6: host-side prompt replacement from authoritative step-derived state."""
|
|
2
2
|
|
|
3
|
-
from context_compiler import create_engine
|
|
3
|
+
from context_compiler import DECISION_UPDATE, create_engine
|
|
4
4
|
from demos.common import compact_user_turns, is_verbose, print_info_report
|
|
5
5
|
|
|
6
6
|
DEMO_NAME = "06_context_compaction — superseded directives eliminated"
|
|
@@ -43,7 +43,7 @@ def _compile_premise(turns: list[str]) -> str:
|
|
|
43
43
|
engine = create_engine()
|
|
44
44
|
for turn in turns:
|
|
45
45
|
decision = engine.step(turn)
|
|
46
|
-
assert decision["kind"] ==
|
|
46
|
+
assert decision["kind"] == DECISION_UPDATE
|
|
47
47
|
compiled_premise = engine.premise
|
|
48
48
|
assert compiled_premise is not None
|
|
49
49
|
return compiled_premise
|
|
@@ -139,7 +139,7 @@ def main() -> None:
|
|
|
139
139
|
compacted_inputs, compacted_state, compacted_prompt = compact_user_turns(USER_INPUTS)
|
|
140
140
|
if compacted_prompt is not None:
|
|
141
141
|
print_messages("compiler-mediated + compact", [])
|
|
142
|
-
compact_output = f"[no call]
|
|
142
|
+
compact_output = f"[no call] error required: {compacted_prompt}"
|
|
143
143
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
144
144
|
else:
|
|
145
145
|
compact_messages = build_compact_compiler_messages(compacted_state, compacted_inputs)
|
{context_compiler-0.9.0.dev2 → context_compiler-0.9.0.dev4}/demos/08_llm_replacement_precondition.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Demo 8: missing-source replacement applies deterministically from authoritative state."""
|
|
2
2
|
|
|
3
|
-
from context_compiler import
|
|
3
|
+
from context_compiler import State, create_engine, is_update
|
|
4
4
|
from demos.common import (
|
|
5
5
|
build_baseline_messages,
|
|
6
6
|
build_reinjected_messages,
|
|
@@ -35,7 +35,7 @@ def main() -> None:
|
|
|
35
35
|
[
|
|
36
36
|
(
|
|
37
37
|
"Analyze this input as state transition logic: 'use podman instead of docker'. "
|
|
38
|
-
"First line must be ACTION:<
|
|
38
|
+
"First line must be ACTION:<error|proceed>."
|
|
39
39
|
)
|
|
40
40
|
],
|
|
41
41
|
baseline_system_prompt=(
|
|
@@ -50,7 +50,7 @@ def main() -> None:
|
|
|
50
50
|
[
|
|
51
51
|
(
|
|
52
52
|
"Analyze this input as state transition logic: 'use podman instead of docker'. "
|
|
53
|
-
"First line must be ACTION:<
|
|
53
|
+
"First line must be ACTION:<error|proceed>."
|
|
54
54
|
)
|
|
55
55
|
],
|
|
56
56
|
premise=None,
|
|
@@ -61,7 +61,7 @@ def main() -> None:
|
|
|
61
61
|
reinjected_output = complete_messages(reinjected_messages)
|
|
62
62
|
print_model_output("Reinjected-state", reinjected_output)
|
|
63
63
|
|
|
64
|
-
if decision
|
|
64
|
+
if is_update(decision):
|
|
65
65
|
print_messages("compiler-mediated (full)", [])
|
|
66
66
|
mediated_output = "[no call] authoritative state applied deterministic replacement update"
|
|
67
67
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
@@ -77,7 +77,7 @@ def main() -> None:
|
|
|
77
77
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
78
78
|
else:
|
|
79
79
|
print_messages("compiler-mediated + compact", [])
|
|
80
|
-
compact_output = "[no call] unexpected
|
|
80
|
+
compact_output = "[no call] unexpected error was produced during compaction"
|
|
81
81
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
82
82
|
|
|
83
83
|
state_applied = not _is_initial_authoritative_state(engine.state)
|
|
@@ -86,7 +86,7 @@ def main() -> None:
|
|
|
86
86
|
|
|
87
87
|
baseline_has_authoritative_precondition = False
|
|
88
88
|
reinjected_has_authoritative_precondition = False
|
|
89
|
-
compiler_pass = decision
|
|
89
|
+
compiler_pass = is_update(decision) and state_applied
|
|
90
90
|
compact_pass = compacted_prompt is None and compact_state_applied and compact_no_pending
|
|
91
91
|
|
|
92
92
|
print_host_check(
|
|
@@ -101,7 +101,7 @@ def main() -> None:
|
|
|
101
101
|
)
|
|
102
102
|
print_host_check(
|
|
103
103
|
"COMPILER_BLOCKED_INVALID_REPLACEMENT",
|
|
104
|
-
yes_no(decision
|
|
104
|
+
yes_no(is_update(decision)),
|
|
105
105
|
context="compiler-mediated",
|
|
106
106
|
)
|
|
107
107
|
print_host_check(
|