context-compiler 0.9.0.dev9__tar.gz → 0.9.0.dev10__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.dev9 → context_compiler-0.9.0.dev10}/PKG-INFO +6 -7
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/README.md +5 -6
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/08_llm_replacement_precondition.py +24 -24
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/09_llm_confirmation_no_directive.py +24 -27
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/pyproject.toml +1 -1
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/engine.py +1 -1
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/grammar.py +95 -38
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/.gitignore +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/LICENSE +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/01_llm_contradiction_error.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/02_llm_constraint_guardrail.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/03_llm_premise_guardrail.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/04_llm_tool_denylist_guardrail.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/05_llm_prompt_drift_vs_state.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/06_llm_context_compaction.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/07_llm_prompt_vs_state.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/README.md +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/__init__.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/common.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/llm_client.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/run_demo.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/01_persistent_guardrails.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/02_configuration_and_correction.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/03_ambiguity_with_error.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/04_tool_governance_denylist.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/05_llm_integration_pattern.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/06_step_sequence_and_state_restore.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/07_single_policy_correction.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/README.md +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/_util.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/host_support/__init__.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/host_support/provider_mode.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/__init__.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/const.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/decision_helpers.py +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/py.typed +0 -0
- {context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/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.0.
|
|
3
|
+
Version: 0.9.0.dev10
|
|
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
|
|
@@ -414,10 +414,9 @@ Replacement:
|
|
|
414
414
|
User: use podman instead of docker
|
|
415
415
|
```
|
|
416
416
|
|
|
417
|
-
If `docker` is absent from saved state, that
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
semantically valid.
|
|
417
|
+
If `docker` is absent from saved state, that is a semantic `error`.
|
|
418
|
+
Canonical replacement requires an active existing source `use` policy and
|
|
419
|
+
does not degrade to plain `use podman`.
|
|
421
420
|
|
|
422
421
|
Removal and reset:
|
|
423
422
|
|
|
@@ -435,8 +434,8 @@ evaluation against authoritative state.
|
|
|
435
434
|
Pending continuation is a separate runtime layer. It may exist only after a
|
|
436
435
|
canonical directive reaches a supported semantic `error` case. It never
|
|
437
436
|
repairs malformed syntax or reinterprets non-canonical input as a directive.
|
|
438
|
-
An absent source item in a canonical replacement directive is
|
|
439
|
-
|
|
437
|
+
An absent source item in a canonical replacement directive is itself a
|
|
438
|
+
semantic `error` case and does not authorize degradation to plain `use`.
|
|
440
439
|
|
|
441
440
|
Examples:
|
|
442
441
|
|
|
@@ -392,10 +392,9 @@ Replacement:
|
|
|
392
392
|
User: use podman instead of docker
|
|
393
393
|
```
|
|
394
394
|
|
|
395
|
-
If `docker` is absent from saved state, that
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
semantically valid.
|
|
395
|
+
If `docker` is absent from saved state, that is a semantic `error`.
|
|
396
|
+
Canonical replacement requires an active existing source `use` policy and
|
|
397
|
+
does not degrade to plain `use podman`.
|
|
399
398
|
|
|
400
399
|
Removal and reset:
|
|
401
400
|
|
|
@@ -413,8 +412,8 @@ evaluation against authoritative state.
|
|
|
413
412
|
Pending continuation is a separate runtime layer. It may exist only after a
|
|
414
413
|
canonical directive reaches a supported semantic `error` case. It never
|
|
415
414
|
repairs malformed syntax or reinterprets non-canonical input as a directive.
|
|
416
|
-
An absent source item in a canonical replacement directive is
|
|
417
|
-
|
|
415
|
+
An absent source item in a canonical replacement directive is itself a
|
|
416
|
+
semantic `error` case and does not authorize degradation to plain `use`.
|
|
418
417
|
|
|
419
418
|
Examples:
|
|
420
419
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"""Demo 8: missing-source replacement
|
|
1
|
+
"""Demo 8: missing-source replacement fails without mutating authoritative state."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
|
|
5
5
|
from context_compiler import (
|
|
6
6
|
Engine,
|
|
7
|
-
|
|
7
|
+
is_error,
|
|
8
8
|
)
|
|
9
9
|
from demos.common import (
|
|
10
10
|
build_baseline_messages,
|
|
@@ -22,7 +22,7 @@ from demos.common import (
|
|
|
22
22
|
)
|
|
23
23
|
from demos.llm_client import complete_messages
|
|
24
24
|
|
|
25
|
-
DEMO_NAME = "08_replacement_precondition — missing-source replacement
|
|
25
|
+
DEMO_NAME = "08_replacement_precondition — missing-source replacement requires active source"
|
|
26
26
|
USER_INPUT = "use podman instead of docker"
|
|
27
27
|
|
|
28
28
|
|
|
@@ -69,38 +69,38 @@ def main() -> None:
|
|
|
69
69
|
reinjected_output = complete_messages(reinjected_messages)
|
|
70
70
|
print_model_output("Reinjected-state", reinjected_output)
|
|
71
71
|
|
|
72
|
-
if
|
|
72
|
+
if is_error(decision):
|
|
73
73
|
print_messages("compiler-mediated (full)", [])
|
|
74
|
-
mediated_output = "[no call] authoritative state
|
|
74
|
+
mediated_output = "[no call] authoritative state blocked replacement without source use"
|
|
75
75
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
76
76
|
else:
|
|
77
77
|
print_messages("compiler-mediated (full)", [])
|
|
78
|
-
mediated_output = "[no call] expected
|
|
78
|
+
mediated_output = "[no call] expected semantic replacement error was not produced"
|
|
79
79
|
print_model_output("Compiler-mediated (full)", mediated_output)
|
|
80
80
|
|
|
81
81
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
82
|
-
if compacted_prompt is None:
|
|
82
|
+
if compacted_prompt is not None:
|
|
83
83
|
print_messages("compiler-mediated + compact", [])
|
|
84
|
-
compact_output = "[no call]
|
|
84
|
+
compact_output = "[no call] unexpected error was produced during compaction"
|
|
85
85
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
86
86
|
else:
|
|
87
87
|
print_messages("compiler-mediated + compact", [])
|
|
88
|
-
compact_output = "[no call]
|
|
88
|
+
compact_output = "[no call] compaction preserved replacement error without state mutation"
|
|
89
89
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
90
90
|
|
|
91
91
|
premise, policies = observe_engine(engine)
|
|
92
92
|
compacted_premise, compacted_policies = state_observations(compacted_state)
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
state_preserved = _is_initial_authoritative_state(premise=premise, policies=policies)
|
|
94
|
+
compact_state_preserved = _is_initial_authoritative_state(
|
|
95
95
|
premise=compacted_premise,
|
|
96
96
|
policies=compacted_policies,
|
|
97
97
|
)
|
|
98
|
-
|
|
98
|
+
compact_error_preserved = compacted_prompt is not None
|
|
99
99
|
|
|
100
100
|
baseline_has_authoritative_precondition = False
|
|
101
101
|
reinjected_has_authoritative_precondition = False
|
|
102
|
-
compiler_pass =
|
|
103
|
-
compact_pass =
|
|
102
|
+
compiler_pass = is_error(decision) and state_preserved
|
|
103
|
+
compact_pass = compact_error_preserved and compact_state_preserved
|
|
104
104
|
|
|
105
105
|
print_host_check(
|
|
106
106
|
"BASELINE_AUTHORITATIVE_PRECONDITION",
|
|
@@ -114,12 +114,12 @@ def main() -> None:
|
|
|
114
114
|
)
|
|
115
115
|
print_host_check(
|
|
116
116
|
"COMPILER_BLOCKED_INVALID_REPLACEMENT",
|
|
117
|
-
yes_no(
|
|
117
|
+
yes_no(is_error(decision)),
|
|
118
118
|
context="compiler-mediated",
|
|
119
119
|
)
|
|
120
120
|
print_host_check(
|
|
121
|
-
"
|
|
122
|
-
yes_no(
|
|
121
|
+
"COMPILER_STATE_PRESERVED",
|
|
122
|
+
yes_no(state_preserved),
|
|
123
123
|
context="compiler-mediated",
|
|
124
124
|
)
|
|
125
125
|
|
|
@@ -130,18 +130,18 @@ def main() -> None:
|
|
|
130
130
|
compiler_pass=compiler_pass,
|
|
131
131
|
compiler_compact_pass=compact_pass,
|
|
132
132
|
expected=(
|
|
133
|
-
"missing-source replacement should
|
|
134
|
-
"
|
|
133
|
+
"missing-source replacement should return semantic error without mutating "
|
|
134
|
+
"authoritative state"
|
|
135
135
|
),
|
|
136
136
|
actual=(
|
|
137
|
-
"compiler
|
|
138
|
-
"still lack authoritative state enforcement"
|
|
137
|
+
"compiler blocked missing-source replacement without mutating state; baseline and "
|
|
138
|
+
"reinjected paths still lack authoritative state enforcement"
|
|
139
139
|
if compiler_pass and compact_pass
|
|
140
|
-
else "compiler did not consistently
|
|
140
|
+
else "compiler did not consistently enforce the replacement source precondition"
|
|
141
141
|
),
|
|
142
142
|
passed=compiler_pass and compact_pass,
|
|
143
|
-
result_pass="missing-source replacement
|
|
144
|
-
result_fail="missing-source replacement
|
|
143
|
+
result_pass="missing-source replacement was rejected without mutation",
|
|
144
|
+
result_fail="missing-source replacement was not rejected correctly",
|
|
145
145
|
)
|
|
146
146
|
|
|
147
147
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
"""Demo 9: confirmation-style
|
|
1
|
+
"""Demo 9: replacement errors do not create confirmation-style followup state."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
|
|
5
5
|
from context_compiler import (
|
|
6
6
|
Engine,
|
|
7
|
+
is_error,
|
|
7
8
|
is_no_directive,
|
|
8
|
-
is_update,
|
|
9
9
|
)
|
|
10
10
|
from demos.common import (
|
|
11
11
|
build_baseline_messages,
|
|
@@ -24,8 +24,7 @@ from demos.common import (
|
|
|
24
24
|
from demos.llm_client import complete_messages
|
|
25
25
|
|
|
26
26
|
DEMO_NAME = (
|
|
27
|
-
"09_confirmation_no_directive_boundary — "
|
|
28
|
-
"missing-source replacement does not create a confirmation state"
|
|
27
|
+
"09_confirmation_no_directive_boundary — replacement errors do not create a confirmation state"
|
|
29
28
|
)
|
|
30
29
|
TURN_1 = "use podman instead of docker"
|
|
31
30
|
TURN_2 = "maybe"
|
|
@@ -34,10 +33,6 @@ INITIAL_PREMISE: str | None = None
|
|
|
34
33
|
INITIAL_POLICIES: dict[str, str] = {}
|
|
35
34
|
|
|
36
35
|
|
|
37
|
-
def _has_podman_use(policies: Mapping[str, str]) -> bool:
|
|
38
|
-
return policies.get("podman") == "use"
|
|
39
|
-
|
|
40
|
-
|
|
41
36
|
def _is_initial_authoritative_state(*, premise: str | None, policies: Mapping[str, str]) -> bool:
|
|
42
37
|
return premise == INITIAL_PREMISE and dict(policies) == INITIAL_POLICIES
|
|
43
38
|
|
|
@@ -50,12 +45,17 @@ def main() -> None:
|
|
|
50
45
|
first = engine.step(TURN_1)
|
|
51
46
|
premise, policies = observe_engine(engine)
|
|
52
47
|
print_decision("turn 1", first, premise=premise, policies=policies)
|
|
53
|
-
|
|
48
|
+
state_preserved_after_first = _is_initial_authoritative_state(
|
|
49
|
+
premise=premise, policies=policies
|
|
50
|
+
)
|
|
54
51
|
|
|
55
52
|
second = engine.step(TURN_2)
|
|
56
53
|
premise, policies = observe_engine(engine)
|
|
57
54
|
print_decision("turn 2", second, premise=premise, policies=policies)
|
|
58
|
-
state_preserved_after_second =
|
|
55
|
+
state_preserved_after_second = _is_initial_authoritative_state(
|
|
56
|
+
premise=premise,
|
|
57
|
+
policies=policies,
|
|
58
|
+
)
|
|
59
59
|
|
|
60
60
|
third = engine.step(TURN_3)
|
|
61
61
|
premise, policies = observe_engine(engine)
|
|
@@ -96,7 +96,7 @@ def main() -> None:
|
|
|
96
96
|
compacted_turns, compacted_state, compacted_prompt = compact_user_turns(user_inputs)
|
|
97
97
|
if compacted_prompt is not None:
|
|
98
98
|
print_messages("compiler-mediated + compact", [])
|
|
99
|
-
compact_output = f"[no call] error
|
|
99
|
+
compact_output = f"[no call] replacement error preserved: {compacted_prompt}"
|
|
100
100
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
101
101
|
else:
|
|
102
102
|
print_messages("compiler-mediated + compact", [])
|
|
@@ -105,32 +105,30 @@ def main() -> None:
|
|
|
105
105
|
)
|
|
106
106
|
print_model_output("Compiler-mediated + compact", compact_output)
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
deterministic_initial_error = is_error(first) and state_preserved_after_first
|
|
109
109
|
unrelated_followup_no_directive = is_no_directive(second) and state_preserved_after_second
|
|
110
110
|
confirmation_token_not_consumed = is_no_directive(third)
|
|
111
111
|
premise, policies = observe_engine(engine)
|
|
112
|
-
deterministic_final_state =
|
|
112
|
+
deterministic_final_state = _is_initial_authoritative_state(premise=premise, policies=policies)
|
|
113
113
|
_, compacted_policies = state_observations(compacted_state)
|
|
114
114
|
|
|
115
115
|
baseline_has_confirmation_state_machine = False
|
|
116
116
|
reinjected_has_confirmation_state_machine = False
|
|
117
117
|
|
|
118
118
|
compiler_pass = (
|
|
119
|
-
|
|
119
|
+
deterministic_initial_error
|
|
120
120
|
and unrelated_followup_no_directive
|
|
121
121
|
and confirmation_token_not_consumed
|
|
122
122
|
and deterministic_final_state
|
|
123
123
|
)
|
|
124
124
|
|
|
125
125
|
compact_pass = (
|
|
126
|
-
compacted_prompt is None
|
|
127
|
-
and compacted_turns == [TURN_2, TURN_3]
|
|
128
|
-
and _has_podman_use(compacted_policies)
|
|
126
|
+
compacted_prompt is not None and compacted_turns == [TURN_1] and compacted_policies == {}
|
|
129
127
|
)
|
|
130
128
|
|
|
131
129
|
print_host_check(
|
|
132
|
-
"
|
|
133
|
-
yes_no(
|
|
130
|
+
"DETERMINISTIC_INITIAL_ERROR",
|
|
131
|
+
yes_no(deterministic_initial_error),
|
|
134
132
|
context="compiler-mediated",
|
|
135
133
|
)
|
|
136
134
|
print_host_check(
|
|
@@ -144,7 +142,7 @@ def main() -> None:
|
|
|
144
142
|
context="compiler-mediated",
|
|
145
143
|
)
|
|
146
144
|
print_host_check(
|
|
147
|
-
"
|
|
145
|
+
"FINAL_STATE_UNCHANGED",
|
|
148
146
|
yes_no(deterministic_final_state),
|
|
149
147
|
context="compiler-mediated",
|
|
150
148
|
)
|
|
@@ -156,19 +154,18 @@ def main() -> None:
|
|
|
156
154
|
compiler_pass=compiler_pass,
|
|
157
155
|
compiler_compact_pass=compact_pass,
|
|
158
156
|
expected=(
|
|
159
|
-
"
|
|
160
|
-
"
|
|
161
|
-
"no_directive"
|
|
157
|
+
"replacement error should not create an engine-owned confirmation state, "
|
|
158
|
+
"and later yes/no-style input should remain ordinary no_directive"
|
|
162
159
|
),
|
|
163
160
|
actual=(
|
|
164
|
-
"compiler
|
|
165
|
-
"
|
|
161
|
+
"compiler returned semantic error and treated later inputs as ordinary "
|
|
162
|
+
"no_directive without mutating state"
|
|
166
163
|
if compiler_pass and compact_pass
|
|
167
164
|
else "compiler did not consistently preserve the confirmation-no_directive boundary"
|
|
168
165
|
),
|
|
169
166
|
passed=compiler_pass and compact_pass,
|
|
170
|
-
result_pass="
|
|
171
|
-
result_fail="
|
|
167
|
+
result_pass="replacement error stayed outside engine-owned confirmation state",
|
|
168
|
+
result_fail="replacement error still behaved like engine-owned confirmation state",
|
|
172
169
|
)
|
|
173
170
|
|
|
174
171
|
|
|
@@ -176,7 +176,7 @@ class Engine:
|
|
|
176
176
|
f'"{new_item}" is currently prohibited.\n'
|
|
177
177
|
"Submit explicit directive(s) to remove it or use a different item."
|
|
178
178
|
)
|
|
179
|
-
if old_state
|
|
179
|
+
if old_state != POLICY_USE:
|
|
180
180
|
return _error(
|
|
181
181
|
f'"{old_item}" is not currently in use.\n'
|
|
182
182
|
"Replacement requires an active 'use' policy."
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/grammar.py
RENAMED
|
@@ -54,16 +54,31 @@ class InvalidDirectiveSyntax:
|
|
|
54
54
|
@dataclass(frozen=True, slots=True)
|
|
55
55
|
class _DirectiveSpec:
|
|
56
56
|
kind: DirectiveKind
|
|
57
|
+
canonical_start: str
|
|
57
58
|
operand_names: tuple[str, ...]
|
|
58
59
|
exact_text: str | None
|
|
59
60
|
renderer: Callable[[MappingProxyType[str, str]], str]
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
@dataclass(frozen=True, slots=True)
|
|
64
|
+
class DirectiveMetadata:
|
|
65
|
+
"""Describe one canonical directive family without exposing parser internals."""
|
|
66
|
+
|
|
67
|
+
kind: DirectiveKind
|
|
68
|
+
canonical_start: str
|
|
69
|
+
operand_names: tuple[str, ...]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
_SET_PREMISE_START = "set premise"
|
|
73
|
+
_CHANGE_PREMISE_START = "change premise to"
|
|
74
|
+
_USE_START = "use"
|
|
75
|
+
_PROHIBIT_START = "prohibit"
|
|
76
|
+
_REMOVE_POLICY_START = "remove policy"
|
|
77
|
+
_SET_PREMISE_PREFIX = f"{_SET_PREMISE_START} "
|
|
78
|
+
_CHANGE_PREMISE_PREFIX = f"{_CHANGE_PREMISE_START} "
|
|
79
|
+
_USE_PREFIX = f"{_USE_START} "
|
|
80
|
+
_PROHIBIT_PREFIX = f"{_PROHIBIT_START} "
|
|
81
|
+
_REMOVE_POLICY_PREFIX = f"{_REMOVE_POLICY_START} "
|
|
67
82
|
_CLEAR_PREMISE_TEXT = "clear premise"
|
|
68
83
|
_RESET_POLICIES_TEXT = "reset policies"
|
|
69
84
|
_CLEAR_STATE_TEXT = "clear state"
|
|
@@ -81,39 +96,6 @@ _REPLACE_RE = re.compile(
|
|
|
81
96
|
r"(?i)^use[ \t]+(?P<new_item>.*?)[ \t]+instead[ \t]+of[ \t]+(?P<old_item>.+)$"
|
|
82
97
|
)
|
|
83
98
|
|
|
84
|
-
_PREFIX_DIRECTIVE_STARTS: tuple[tuple[str, bool], ...] = (
|
|
85
|
-
(_CHANGE_PREMISE_PREFIX.removesuffix(" "), True),
|
|
86
|
-
(_SET_PREMISE_PREFIX.removesuffix(" "), True),
|
|
87
|
-
(_REMOVE_POLICY_PREFIX.removesuffix(" "), True),
|
|
88
|
-
(_PROHIBIT_PREFIX.removesuffix(" "), True),
|
|
89
|
-
(_USE_PREFIX.removesuffix(" "), True),
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
_EXACT_DIRECTIVE_STARTS: tuple[tuple[str, bool], ...] = (
|
|
93
|
-
(_RESET_POLICIES_TEXT, False),
|
|
94
|
-
(_CLEAR_PREMISE_TEXT, False),
|
|
95
|
-
(_CLEAR_STATE_TEXT, False),
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
_CANONICAL_DIRECTIVE_STARTS: tuple[tuple[str, bool], ...] = (
|
|
99
|
-
_PREFIX_DIRECTIVE_STARTS[0],
|
|
100
|
-
_PREFIX_DIRECTIVE_STARTS[1],
|
|
101
|
-
_PREFIX_DIRECTIVE_STARTS[2],
|
|
102
|
-
_EXACT_DIRECTIVE_STARTS[0],
|
|
103
|
-
_EXACT_DIRECTIVE_STARTS[1],
|
|
104
|
-
_EXACT_DIRECTIVE_STARTS[2],
|
|
105
|
-
_PREFIX_DIRECTIVE_STARTS[3],
|
|
106
|
-
_PREFIX_DIRECTIVE_STARTS[4],
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
_DIRECTIVE_FAMILY_STARTS: tuple[tuple[str, bool], ...] = (
|
|
110
|
-
(_CHANGE_PREMISE_FAMILY, True),
|
|
111
|
-
_PREFIX_DIRECTIVE_STARTS[1],
|
|
112
|
-
_PREFIX_DIRECTIVE_STARTS[2],
|
|
113
|
-
*_EXACT_DIRECTIVE_STARTS,
|
|
114
|
-
*_PREFIX_DIRECTIVE_STARTS[3:],
|
|
115
|
-
)
|
|
116
|
-
|
|
117
99
|
|
|
118
100
|
def _render_with_prefix(
|
|
119
101
|
prefix: str, operand_name: str
|
|
@@ -140,54 +122,63 @@ _DIRECTIVE_SPECS = MappingProxyType(
|
|
|
140
122
|
{
|
|
141
123
|
DirectiveKind.SET_PREMISE: _DirectiveSpec(
|
|
142
124
|
kind=DirectiveKind.SET_PREMISE,
|
|
125
|
+
canonical_start=_SET_PREMISE_START,
|
|
143
126
|
operand_names=("value",),
|
|
144
127
|
exact_text=None,
|
|
145
128
|
renderer=_render_with_prefix(_SET_PREMISE_PREFIX, "value"),
|
|
146
129
|
),
|
|
147
130
|
DirectiveKind.CHANGE_PREMISE: _DirectiveSpec(
|
|
148
131
|
kind=DirectiveKind.CHANGE_PREMISE,
|
|
132
|
+
canonical_start=_CHANGE_PREMISE_START,
|
|
149
133
|
operand_names=("value",),
|
|
150
134
|
exact_text=None,
|
|
151
135
|
renderer=_render_with_prefix(_CHANGE_PREMISE_PREFIX, "value"),
|
|
152
136
|
),
|
|
153
137
|
DirectiveKind.USE_ITEM: _DirectiveSpec(
|
|
154
138
|
kind=DirectiveKind.USE_ITEM,
|
|
139
|
+
canonical_start=_USE_START,
|
|
155
140
|
operand_names=("item",),
|
|
156
141
|
exact_text=None,
|
|
157
142
|
renderer=_render_with_prefix(_USE_PREFIX, "item"),
|
|
158
143
|
),
|
|
159
144
|
DirectiveKind.PROHIBIT_ITEM: _DirectiveSpec(
|
|
160
145
|
kind=DirectiveKind.PROHIBIT_ITEM,
|
|
146
|
+
canonical_start=_PROHIBIT_START,
|
|
161
147
|
operand_names=("item",),
|
|
162
148
|
exact_text=None,
|
|
163
149
|
renderer=_render_with_prefix(_PROHIBIT_PREFIX, "item"),
|
|
164
150
|
),
|
|
165
151
|
DirectiveKind.REMOVE_POLICY: _DirectiveSpec(
|
|
166
152
|
kind=DirectiveKind.REMOVE_POLICY,
|
|
153
|
+
canonical_start=_REMOVE_POLICY_START,
|
|
167
154
|
operand_names=("item",),
|
|
168
155
|
exact_text=None,
|
|
169
156
|
renderer=_render_with_prefix(_REMOVE_POLICY_PREFIX, "item"),
|
|
170
157
|
),
|
|
171
158
|
DirectiveKind.REPLACE_USE: _DirectiveSpec(
|
|
172
159
|
kind=DirectiveKind.REPLACE_USE,
|
|
160
|
+
canonical_start=_USE_START,
|
|
173
161
|
operand_names=("new_item", "old_item"),
|
|
174
162
|
exact_text=None,
|
|
175
163
|
renderer=_render_replace_use,
|
|
176
164
|
),
|
|
177
165
|
DirectiveKind.CLEAR_PREMISE: _DirectiveSpec(
|
|
178
166
|
kind=DirectiveKind.CLEAR_PREMISE,
|
|
167
|
+
canonical_start=_CLEAR_PREMISE_TEXT,
|
|
179
168
|
operand_names=(),
|
|
180
169
|
exact_text=_CLEAR_PREMISE_TEXT,
|
|
181
170
|
renderer=_render_exact(_CLEAR_PREMISE_TEXT),
|
|
182
171
|
),
|
|
183
172
|
DirectiveKind.RESET_POLICIES: _DirectiveSpec(
|
|
184
173
|
kind=DirectiveKind.RESET_POLICIES,
|
|
174
|
+
canonical_start=_RESET_POLICIES_TEXT,
|
|
185
175
|
operand_names=(),
|
|
186
176
|
exact_text=_RESET_POLICIES_TEXT,
|
|
187
177
|
renderer=_render_exact(_RESET_POLICIES_TEXT),
|
|
188
178
|
),
|
|
189
179
|
DirectiveKind.CLEAR_STATE: _DirectiveSpec(
|
|
190
180
|
kind=DirectiveKind.CLEAR_STATE,
|
|
181
|
+
canonical_start=_CLEAR_STATE_TEXT,
|
|
191
182
|
operand_names=(),
|
|
192
183
|
exact_text=_CLEAR_STATE_TEXT,
|
|
193
184
|
renderer=_render_exact(_CLEAR_STATE_TEXT),
|
|
@@ -196,6 +187,64 @@ _DIRECTIVE_SPECS = MappingProxyType(
|
|
|
196
187
|
)
|
|
197
188
|
|
|
198
189
|
|
|
190
|
+
def _starts_with_descriptor(spec: _DirectiveSpec) -> tuple[str, bool]:
|
|
191
|
+
return (spec.canonical_start, bool(spec.operand_names))
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _unique_start_descriptors(specs: tuple[_DirectiveSpec, ...]) -> tuple[tuple[str, bool], ...]:
|
|
195
|
+
descriptors: list[tuple[str, bool]] = []
|
|
196
|
+
seen: set[tuple[str, bool]] = set()
|
|
197
|
+
for spec in specs:
|
|
198
|
+
descriptor = _starts_with_descriptor(spec)
|
|
199
|
+
if descriptor not in seen:
|
|
200
|
+
seen.add(descriptor)
|
|
201
|
+
descriptors.append(descriptor)
|
|
202
|
+
return tuple(descriptors)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
_CANONICAL_START_ORDER = (
|
|
206
|
+
DirectiveKind.CHANGE_PREMISE,
|
|
207
|
+
DirectiveKind.SET_PREMISE,
|
|
208
|
+
DirectiveKind.REMOVE_POLICY,
|
|
209
|
+
DirectiveKind.RESET_POLICIES,
|
|
210
|
+
DirectiveKind.CLEAR_PREMISE,
|
|
211
|
+
DirectiveKind.CLEAR_STATE,
|
|
212
|
+
DirectiveKind.PROHIBIT_ITEM,
|
|
213
|
+
DirectiveKind.USE_ITEM,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
_CANONICAL_DIRECTIVE_STARTS = _unique_start_descriptors(
|
|
217
|
+
tuple(_DIRECTIVE_SPECS[kind] for kind in _CANONICAL_START_ORDER)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
_DIRECTIVE_FAMILY_STARTS = (
|
|
221
|
+
(_CHANGE_PREMISE_FAMILY, True),
|
|
222
|
+
*_unique_start_descriptors(
|
|
223
|
+
tuple(
|
|
224
|
+
_DIRECTIVE_SPECS[kind]
|
|
225
|
+
for kind in (
|
|
226
|
+
DirectiveKind.SET_PREMISE,
|
|
227
|
+
DirectiveKind.REMOVE_POLICY,
|
|
228
|
+
DirectiveKind.RESET_POLICIES,
|
|
229
|
+
DirectiveKind.CLEAR_PREMISE,
|
|
230
|
+
DirectiveKind.CLEAR_STATE,
|
|
231
|
+
DirectiveKind.PROHIBIT_ITEM,
|
|
232
|
+
DirectiveKind.USE_ITEM,
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
),
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
_PUBLIC_DIRECTIVE_METADATA = tuple(
|
|
239
|
+
DirectiveMetadata(
|
|
240
|
+
kind=spec.kind,
|
|
241
|
+
canonical_start=spec.canonical_start,
|
|
242
|
+
operand_names=spec.operand_names,
|
|
243
|
+
)
|
|
244
|
+
for spec in _DIRECTIVE_SPECS.values()
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
199
248
|
def _trim_ascii_whitespace(text: str) -> str:
|
|
200
249
|
return text.strip(_ASCII_WHITESPACE)
|
|
201
250
|
|
|
@@ -533,6 +582,12 @@ def decompose_directive(text: str) -> CanonicalDirective | InvalidDirectiveSynta
|
|
|
533
582
|
return _invalid_directive_syntax(DirectiveSyntaxFailure.MALFORMED_DIRECTIVE)
|
|
534
583
|
|
|
535
584
|
|
|
585
|
+
def get_directive_metadata() -> tuple[DirectiveMetadata, ...]:
|
|
586
|
+
"""Return immutable public directive metadata derived from internal specs."""
|
|
587
|
+
|
|
588
|
+
return _PUBLIC_DIRECTIVE_METADATA
|
|
589
|
+
|
|
590
|
+
|
|
536
591
|
def _render_directive(kind: DirectiveKind | str, /, **operands: str) -> str:
|
|
537
592
|
"""Produce canonical directive text from a semantic kind and operands."""
|
|
538
593
|
try:
|
|
@@ -572,7 +627,9 @@ def _render_directive(kind: DirectiveKind | str, /, **operands: str) -> str:
|
|
|
572
627
|
__all__ = [
|
|
573
628
|
"DirectiveKind",
|
|
574
629
|
"DirectiveSyntaxFailure",
|
|
630
|
+
"DirectiveMetadata",
|
|
575
631
|
"CanonicalDirective",
|
|
576
632
|
"InvalidDirectiveSyntax",
|
|
633
|
+
"get_directive_metadata",
|
|
577
634
|
"decompose_directive",
|
|
578
635
|
]
|
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/01_llm_contradiction_error.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/02_llm_constraint_guardrail.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/03_llm_premise_guardrail.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/04_llm_tool_denylist_guardrail.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/05_llm_prompt_drift_vs_state.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/06_llm_context_compaction.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/demos/07_llm_prompt_vs_state.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/01_persistent_guardrails.py
RENAMED
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/03_ambiguity_with_error.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/04_tool_governance_denylist.py
RENAMED
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/05_llm_integration_pattern.py
RENAMED
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/examples/07_single_policy_correction.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{context_compiler-0.9.0.dev9 → context_compiler-0.9.0.dev10}/src/context_compiler/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|