context-compiler 0.7.0__tar.gz → 0.7.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 (249) hide show
  1. {context_compiler-0.7.0 → context_compiler-0.7.2}/PKG-INFO +82 -39
  2. {context_compiler-0.7.0 → context_compiler-0.7.2}/README.md +81 -38
  3. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/01_llm_contradiction_clarify.py +25 -0
  4. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/02_llm_constraint_guardrail.py +38 -0
  5. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/03_llm_premise_guardrail.py +26 -1
  6. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/04_llm_tool_denylist_guardrail.py +37 -9
  7. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/05_llm_prompt_drift_vs_state.py +27 -1
  8. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/07_llm_prompt_vs_state.py +21 -1
  9. context_compiler-0.7.2/demos/08_llm_replacement_precondition.py +137 -0
  10. context_compiler-0.7.2/demos/09_llm_pending_clarification.py +167 -0
  11. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/README.md +66 -8
  12. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/common.py +50 -0
  13. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/llm_client.py +87 -0
  14. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/run_demo.py +64 -8
  15. context_compiler-0.7.2/docs/demos-results.md +157 -0
  16. context_compiler-0.7.2/docs/llm-preprocessor.md +116 -0
  17. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/README.md +10 -10
  18. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/README.md +6 -5
  19. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm/README.md +15 -8
  20. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/README.md +4 -3
  21. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/openwebui/README.md +22 -13
  22. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/openwebui/open_webui_pipe.py +44 -22
  23. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/openwebui/open_webui_pipe_with_preprocessor.py +39 -20
  24. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/README.md +36 -5
  25. {context_compiler-0.7.0 → context_compiler-0.7.2}/pyproject.toml +1 -1
  26. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/observability.py +1 -1
  27. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_demo_01_04_behavior.py +30 -6
  28. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_demo_05_prompt_contract.py +5 -4
  29. context_compiler-0.7.2/tests/test_demo_08_09_behavior.py +162 -0
  30. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_llm_client.py +116 -0
  31. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_openwebui_pipe.py +206 -0
  32. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_openwebui_preprocessor_pipe.py +199 -0
  33. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_run_demo.py +175 -2
  34. {context_compiler-0.7.0 → context_compiler-0.7.2}/uv.lock +1 -1
  35. context_compiler-0.7.0/docs/demos-results.md +0 -67
  36. context_compiler-0.7.0/docs/llm-preprocessor.md +0 -66
  37. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  38. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  39. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/pull_request_template.md +0 -0
  40. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/workflows/ci.yml +0 -0
  41. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/workflows/publish-pypi.yml +0 -0
  42. {context_compiler-0.7.0 → context_compiler-0.7.2}/.github/workflows/stress-tests.yml +0 -0
  43. {context_compiler-0.7.0 → context_compiler-0.7.2}/.gitignore +0 -0
  44. {context_compiler-0.7.0 → context_compiler-0.7.2}/.pre-commit-config.yaml +0 -0
  45. {context_compiler-0.7.0 → context_compiler-0.7.2}/AGENTS.md +0 -0
  46. {context_compiler-0.7.0 → context_compiler-0.7.2}/CODE_OF_CONDUCT.md +0 -0
  47. {context_compiler-0.7.0 → context_compiler-0.7.2}/CONTRIBUTING.md +0 -0
  48. {context_compiler-0.7.0 → context_compiler-0.7.2}/LICENSE +0 -0
  49. {context_compiler-0.7.0 → context_compiler-0.7.2}/SECURITY.md +0 -0
  50. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/06_llm_context_compaction.py +0 -0
  51. {context_compiler-0.7.0 → context_compiler-0.7.2}/demos/__init__.py +0 -0
  52. {context_compiler-0.7.0 → context_compiler-0.7.2}/docs/DescriptionAndMilestones.md +0 -0
  53. {context_compiler-0.7.0 → context_compiler-0.7.2}/docs/DesignPhilosophy.md +0 -0
  54. {context_compiler-0.7.0 → context_compiler-0.7.2}/docs/DirectiveGrammarSpec.md +0 -0
  55. {context_compiler-0.7.0 → context_compiler-0.7.2}/docs/README.md +0 -0
  56. {context_compiler-0.7.0 → context_compiler-0.7.2}/docs/multi-engine.md +0 -0
  57. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/litellm_proxy_additional_findings.md +0 -0
  58. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/litellm_proxy_behavioral_comparisons.md +0 -0
  59. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/README.md +0 -0
  60. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/RUBRIC.md +0 -0
  61. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/manifest.json +0 -0
  62. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/swe-bench.py +0 -0
  63. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-12453.json +0 -0
  64. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-13158.json +0 -0
  65. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-13964.json +0 -0
  66. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-15252.json +0 -0
  67. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/matplotlib__matplotlib-23299.json +0 -0
  68. {context_compiler-0.7.0 → context_compiler-0.7.2}/evals/swe-bench/tasks/psf__requests-1963.json +0 -0
  69. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/01_persistent_guardrails.py +0 -0
  70. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/02_configuration_and_correction.py +0 -0
  71. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/03_ambiguity_with_clarification.py +0 -0
  72. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/04_tool_governance_denylist.py +0 -0
  73. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/05_llm_integration_pattern.py +0 -0
  74. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/06_transcript_replay.py +0 -0
  75. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/07_single_policy_correction.py +0 -0
  76. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/_util.py +0 -0
  77. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm/basic.py +0 -0
  78. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm/with_preprocessor.py +0 -0
  79. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/config.example.yaml +0 -0
  80. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/context_compiler_precall_hook.py +0 -0
  81. {context_compiler-0.7.0 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/context_compiler_precall_hook_with_preprocessor.py +0 -0
  82. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/__init__.py +0 -0
  83. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/__init__.py +0 -0
  84. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/constants.py +0 -0
  85. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/heuristic_preprocessor.py +0 -0
  86. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/output_validation.py +0 -0
  87. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/prompt_utils.py +0 -0
  88. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/prompts/default.txt +0 -0
  89. {context_compiler-0.7.0 → context_compiler-0.7.2}/experimental/preprocessor/prompts/llama.txt +0 -0
  90. {context_compiler-0.7.0 → context_compiler-0.7.2}/host_support/__init__.py +0 -0
  91. {context_compiler-0.7.0 → context_compiler-0.7.2}/host_support/confirmation.py +0 -0
  92. {context_compiler-0.7.0 → context_compiler-0.7.2}/host_support/provider_mode.py +0 -0
  93. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/__init__.py +0 -0
  94. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/const.py +0 -0
  95. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/controller.py +0 -0
  96. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/decision_constants.py +0 -0
  97. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/engine.py +0 -0
  98. {context_compiler-0.7.0 → context_compiler-0.7.2}/src/context_compiler/repl.py +0 -0
  99. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/README.md +0 -0
  100. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/api/public-api-v1.json +0 -0
  101. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/001_import_checkpoint_non_object_rejected.json +0 -0
  102. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/002_import_checkpoint_unsupported_version_rejected.json +0 -0
  103. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/003_import_checkpoint_invalid_pending_shape_rejected.json +0 -0
  104. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/004_import_checkpoint_invalid_replacement_shape_rejected.json +0 -0
  105. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/005_import_checkpoint_invalid_authoritative_state_rejected_atomically.json +0 -0
  106. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/006_import_checkpoint_pending_null_clears_existing_pending.json +0 -0
  107. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/007_import_checkpoint_pending_absent_clears_existing_pending.json +0 -0
  108. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/001_export_json_canonical_sorted_compact.json +0 -0
  109. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/002_import_json_invalid_json_rejected.json +0 -0
  110. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/003_import_json_non_object_rejected.json +0 -0
  111. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/004_import_json_unsupported_version_rejected.json +0 -0
  112. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/005_import_json_empty_normalized_policy_key_rejected_atomically.json +0 -0
  113. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/006_import_json_valid_normalized_policy_key_accepted.json +0 -0
  114. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/001_set_premise_update.json +0 -0
  115. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/002_use_item_normalization.json +0 -0
  116. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/003_conflict_prohibit_clarify.json +0 -0
  117. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/004_remove_policy_missing_idempotent_update.json +0 -0
  118. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/005_exact_prefix_passthrough_leading_space.json +0 -0
  119. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/006_near_miss_set_premise_to.json +0 -0
  120. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/007_near_miss_change_premise_missing_to.json +0 -0
  121. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/008_replace_missing_source_clarify_prompt.json +0 -0
  122. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/009_pending_affirmative_normalized_token.json +0 -0
  123. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/010_pending_negative_normalized_token.json +0 -0
  124. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/011_pending_unmatched_reuses_prompt.json +0 -0
  125. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/012_clear_premise_populated_update.json +0 -0
  126. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/013_clear_premise_already_null_update.json +0 -0
  127. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/014_reset_policies_populated_update.json +0 -0
  128. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/015_reset_policies_already_empty_update.json +0 -0
  129. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/016_clear_state_populated_update.json +0 -0
  130. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/017_clear_state_already_empty_update.json +0 -0
  131. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/018_pending_affirmative_punctuation_token.json +0 -0
  132. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/step/019_pending_negative_punctuation_token.json +0 -0
  133. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/001_user_only_replay_state.json +0 -0
  134. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/002_non_string_user_content_ignored.json +0 -0
  135. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/003_stops_at_first_clarify_later_yes.json +0 -0
  136. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/004_stops_at_first_clarify_later_no.json +0 -0
  137. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/controller/preview_clarify_no_mutation.json +0 -0
  138. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/controller/preview_idempotent_no_mutation.json +0 -0
  139. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/README.md +0 -0
  140. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/contradiction_clarify.json +0 -0
  141. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_no.json +0 -0
  142. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_unmatched.json +0 -0
  143. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_yes.json +0 -0
  144. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/premise_lifecycle.json +0 -0
  145. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/replacement_clarify.json +0 -0
  146. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/contradiction_clarify.json +0 -0
  147. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_no.json +0 -0
  148. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_unmatched.json +0 -0
  149. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_yes.json +0 -0
  150. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/premise_lifecycle.json +0 -0
  151. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/replacement_clarify.json +0 -0
  152. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/admin-alias-remove-policies-unknown.json +0 -0
  153. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/admin-alias-reset-policy-unknown.json +0 -0
  154. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/ambiguous-directive-adjacent.json +0 -0
  155. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-bracket-wrapper.json +0 -0
  156. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-case-normalized-use-docker.json +0 -0
  157. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-clear-state-period.json +0 -0
  158. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-clear-state.json +0 -0
  159. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-paren-wrapper.json +0 -0
  160. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-prohibit-peanuts.json +0 -0
  161. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-quoted-payload-use-docker.json +0 -0
  162. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-reset-policies-bang.json +0 -0
  163. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-whitespace-collapsed-use-docker.json +0 -0
  164. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/fenced-code-block-directive-unknown.json +0 -0
  165. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/inline-prose-code-directive-unknown.json +0 -0
  166. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/list-prefix-directive-unknown.json +0 -0
  167. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/malformed-replacement-instead-docker-unknown.json +0 -0
  168. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/meta-prefix-directive-unknown.json +0 -0
  169. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/mixed-directive-task-unknown.json +0 -0
  170. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/mixed-intent-unknown.json +0 -0
  171. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/modal-please-clear-state-unknown.json +0 -0
  172. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/multiline-multi-directive-unknown.json +0 -0
  173. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/natural-language-dont-use-unknown.json +0 -0
  174. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-change-premise-missing-to-unknown.json +0 -0
  175. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-change-premise-to-empty-unknown.json +0 -0
  176. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-prohibit-empty-unknown.json +0 -0
  177. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-remove-policy-empty-unknown.json +0 -0
  178. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-set-premise-empty-unknown.json +0 -0
  179. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-set-premise-to-unknown.json +0 -0
  180. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-empty-unknown.json +0 -0
  181. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-instead-of-missing-new-item-unknown.json +0 -0
  182. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-instead-of-missing-old-item-unknown.json +0 -0
  183. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/nested-wrapper-clear-state-unknown.json +0 -0
  184. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/ordinary-non-directive.json +0 -0
  185. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-fenced-code-rejected.json +0 -0
  186. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-inline-prose-code-rejected.json +0 -0
  187. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-mixed-directive-task-rejected.json +0 -0
  188. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-multiline-rejected.json +0 -0
  189. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-question-form-rejected.json +0 -0
  190. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-quoted-payload-locked.json +0 -0
  191. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-reported-speech-rejected.json +0 -0
  192. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-safe-canonical-use-docker.json +0 -0
  193. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-safe-canonicalization-use-docker.json +0 -0
  194. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/public-api-v1.json +0 -0
  195. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/question-can-you-use-docker-unknown.json +0 -0
  196. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/question-use-docker-unknown.json +0 -0
  197. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-backtick-unknown.json +0 -0
  198. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-single-unknown.json +0 -0
  199. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-unknown.json +0 -0
  200. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-reported-unknown.json +0 -0
  201. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/reported-speech-docs-say-unknown.json +0 -0
  202. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/sentence-adjacent-directive-unknown.json +0 -0
  203. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/unsupported-alias-unknown.json +0 -0
  204. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-invalid-json-shape-unknown.json +0 -0
  205. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-json-text-unknown.json +0 -0
  206. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-sentinel-unknown.json +0 -0
  207. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-text-unknown.json +0 -0
  208. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-multi-candidate-directive-unknown.json +0 -0
  209. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-sentinel-no-directive.json +0 -0
  210. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-allow-safe-directive.json +0 -0
  211. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-block-change-premise-rewrite.json +0 -0
  212. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-block-set-premise-rewrite.json +0 -0
  213. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-structured-json-directive.json +0 -0
  214. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_04_grammar_edge_cases.py +0 -0
  215. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_04_llm_tool_governance.py +0 -0
  216. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_07_llm_prompt_engineering_comparison.py +0 -0
  217. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_api_contract_fixture.py +0 -0
  218. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_controller.py +0 -0
  219. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_decision_constants.py +0 -0
  220. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_demo_07_output_clarity.py +0 -0
  221. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_demo_compaction.py +0 -0
  222. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_demo_oracle_properties.py +0 -0
  223. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_engine.py +0 -0
  224. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_example_integrations_imports.py +0 -0
  225. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_examples.py +0 -0
  226. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_examples_behavior.py +0 -0
  227. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_examples_smoke.py +0 -0
  228. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_fixtures.py +0 -0
  229. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_host_confirmation.py +0 -0
  230. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_host_observability.py +0 -0
  231. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_litellm_checkpoint_integration.py +0 -0
  232. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_litellm_integration_error_paths.py +0 -0
  233. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_litellm_preprocessor_model_config.py +0 -0
  234. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_llm_demos.py +0 -0
  235. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_precompiler_prompt_utils.py +0 -0
  236. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_api_contract_fixture.py +0 -0
  237. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_conformance.py +0 -0
  238. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_heuristic.py +0 -0
  239. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_heuristic_properties.py +0 -0
  240. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_output_validation.py +0 -0
  241. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_preprocessor_validator_properties.py +0 -0
  242. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_properties.py +0 -0
  243. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_provider_helper.py +0 -0
  244. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_repl.py +0 -0
  245. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_repl_coverage.py +0 -0
  246. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_repl_properties.py +0 -0
  247. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_smoke.py +0 -0
  248. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_structured_regression.py +0 -0
  249. {context_compiler-0.7.0 → context_compiler-0.7.2}/tests/test_transcript_replay.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: context-compiler
3
- Version: 0.7.0
3
+ Version: 0.7.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
@@ -34,22 +34,59 @@ Provides-Extra: litellm-proxy
34
34
  Requires-Dist: litellm[proxy]>=1.0.0; extra == 'litellm-proxy'
35
35
  Description-Content-Type: text/markdown
36
36
 
37
-
38
37
  # Context Compiler
39
38
 
40
39
  [![PyPI version](https://img.shields.io/pypi/v/context-compiler)](https://pypi.org/project/context-compiler/)
41
40
  [![Python versions](https://img.shields.io/pypi/pyversions/context-compiler)](https://pypi.org/project/context-compiler/)
42
41
  [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/)
43
42
 
44
- Context Compiler lets users set rules and corrections that actually stick.
45
- It helps applications keep explicit user instructions consistent across turns.
46
- It stores premise and policy rules outside the model, so corrections do not drift or conflict over time.
43
+ Some behaviors require explicit host-side state machinery.
44
+
45
+ Context Compiler is a deterministic host-side state layer for LLM applications.
46
+ It handles explicit state transitions for premise and policies so that mutation
47
+ rules are fixed and repeatable.
48
+
49
+ ## What prompting and reinjection can do
50
+
51
+ Prompting and reinjection are useful. In many real systems, reinjecting saved
52
+ state text is enough to keep instructions and policies persistent across turns.
53
+
54
+ Context Compiler adds host-owned transition rules for behaviors that plain text
55
+ reinjection does not implement by itself: replace `X` only if `X` exists, block
56
+ conflicting changes and ask for confirmation, and restore saved state plus
57
+ pending confirmations from checkpoints.
58
+
59
+ ## What prompting cannot do by itself
60
+
61
+ Prompt text (including reinjected state text) helps, but it does not give your
62
+ app controlled rules for when state can change. By itself, it does not provide:
63
+
64
+ - rules your app controls for state changes
65
+ - replacement precondition checks (`use X instead of Y` when `Y` may be absent)
66
+ - confirmation flows that must complete before anything else changes
67
+ - clear decisions about when a change is blocked
68
+ - reliable checkpoint restore for both saved state and pending confirmation flow
69
+
70
+ ## What Context Compiler provides
71
+
72
+ Context Compiler provides fixed host-side state machinery:
73
+
74
+ - deterministic directive handling for explicit user state changes
75
+ - clarification instead of silent overwrite for blocked/ambiguous changes
76
+ - pending confirmation flows that must resolve before anything else changes
77
+ - checkpoint export/import for restoring saved state and pending confirmation flow
78
+ - structured saved state that the host can pass to the model
47
79
 
48
- LLMs are good at conversation, but bad at consistently following long-term rules and corrections. Constraints drift, corrections conflict, and long chats can become inconsistent.
80
+ The model generates responses. The compiler owns state transitions.
49
81
 
50
- The model writes responses. The compiler stores premise and policy rules.
82
+ ## How the compiler metaphor works
51
83
 
52
- Context Compiler is a deterministic control layer for LLM applications. It processes explicit user instructions before model calls so applications can reliably enforce premise and policy constraints.
84
+ Context Compiler treats important instructions as structured state instead of
85
+ temporary prompt text.
86
+
87
+ Like a compiler, it parses input, validates it, applies fixed rules, and
88
+ produces a stable representation the host can use. It is not source-code
89
+ compilation and not a reasoning model.
53
90
 
54
91
  ## Does it work?
55
92
 
@@ -59,7 +96,13 @@ Yes, on the current scored demo set.
59
96
  - Scored checks (**6 demos per model**; Demo 6 excluded): baseline **26 / 42**, compiler **42 / 42**, compiler+compact **42 / 42**.
60
97
  - Across tested models, compiler-mediated paths pass all scored scenarios; baseline behavior is model-dependent.
61
98
 
62
- [Full results and demo output](demos/README.md)
99
+ Interpretation guide:
100
+ - Demos `01`-`05` and `07` focus on persistence and policy-following behavior.
101
+ - Demos `08`/`09` focus on rules for when state is allowed to change.
102
+ - Demos `08`/`09` show what prompt text does not implement by itself.
103
+ - Plain reinjection can produce plausible responses, but it does not check whether replacement is allowed or wait for confirmation before saving changes.
104
+
105
+ → [Full results and demo output](demos/README.md)
63
106
  Canonical matrix: [docs/demos-results.md](docs/demos-results.md)
64
107
 
65
108
  ## Quickstart
@@ -74,9 +117,9 @@ context-compiler --json < input.txt
74
117
  `context-compiler` launches the interactive REPL.
75
118
 
76
119
  `--with-preprocessor` enables the experimental preprocessor before each REPL turn
77
- (heuristic + validation only). Near-miss inputs are not rewritten and are
78
- passed through to the engine, which continues to return clarify behavior for
79
- those forms.
120
+ (simple rule-based checks plus conservative validation). For near-miss inputs,
121
+ the preprocessor does not rewrite the text. It passes the input to the engine,
122
+ and the engine can return `clarify`.
80
123
 
81
124
  `--json` enables machine-readable NDJSON output for non-interactive usage
82
125
  (one complete JSON object per processed input line).
@@ -88,7 +131,7 @@ Preload options keep saved rules separate from in-progress confirmation state:
88
131
  continuation checkpoint (saved state + pending confirmation state).
89
132
 
90
133
  REPL commands (controller layer, not engine directives):
91
- - `state` shows current authoritative state.
134
+ - `state` shows current saved state.
92
135
  - `preview <input>` runs deterministic dry-run without mutating live state.
93
136
  - `step <input>` is an explicit alias of normal bare-input step behavior.
94
137
 
@@ -139,27 +182,25 @@ uv run pytest
139
182
 
140
183
  ---
141
184
 
142
- ## Why “Compiler”?
143
-
144
- Context Compiler treats explicit user directives as inputs to a fixed, repeatable process.
145
-
146
- Instead of relying on the LLM to remember constraints across a conversation, user instructions are compiled into structured state before the model runs.
147
-
148
- The idea is similar to a traditional compiler: user directives are translated into a structured representation that the rest of the system can rely on.
149
-
150
- ---
151
-
152
185
  ## FAQ
153
186
 
154
187
  **Is this just prompt reinjection?**
155
- Partly. Hosts still pass state to models as context. The difference is that
156
- state is maintained by a deterministic engine with explicit update rules,
157
- clarification behavior, and inspectable checkpoints.
188
+ Reinjection helps with persistence, and it remains useful. Context Compiler
189
+ handles a different problem: rules for when state is allowed to change.
190
+
191
+ Examples:
192
+ - replacement semantics (`use X instead of Y`) when `Y` may not exist
193
+ - contradiction detection before applying a mutation
194
+ - lifecycle enforcement (for example, you cannot change an unset premise)
195
+ - pending clarification flows that must be resolved before other mutations
196
+
197
+ In short: reinjection carries state forward; Context Compiler decides when your
198
+ app should change state.
158
199
 
159
200
  **Isn’t this just prompt engineering?**
160
201
  It complements prompt engineering, but solves a different problem. Prompting
161
- shapes model behavior; Context Compiler provides a deterministic state layer
162
- that updates only through explicit directives.
202
+ shapes model behavior. Context Compiler enforces state rules and updates state
203
+ only through explicit directives.
163
204
 
164
205
  ---
165
206
 
@@ -179,36 +220,38 @@ Later in the conversation:
179
220
  User: how should I make this curry?
180
221
  ```
181
222
 
182
- Your app sends the saved state to the model so the rule still applies on later turns.
223
+ Your host sends the saved policy state with this later request, so the model is
224
+ constrained by explicit state (`peanuts: prohibit`) instead of relying on memory
225
+ of earlier conversation text.
183
226
 
184
227
  ---
185
228
 
186
229
  ## Deterministic behavior (examples)
187
230
 
188
- LLMs interpret intent. Context Compiler enforces it.
231
+ Context Compiler makes mutation rules explicit so behavior stays repeatable.
189
232
 
190
233
  **Explicit directive**
191
234
  ```text
192
235
  set premise concise replies
193
236
  ```
194
237
  - Base model: silently accepts / rewrites
195
- - Context Compiler: applies a deterministic state update
238
+ - Context Compiler: applies a repeatable state update
196
239
 
197
240
  **State-dependent operation**
198
241
  ```text
199
242
  clear state
200
243
  use podman instead of docker
201
244
  ```
202
- - Base model: generic explanation
203
- - Context Compiler: rejects (“No exact policy found for 'docker'…”)
245
+ - Without explicit state transition rules: behavior depends on host/model handling
246
+ - Context Compiler: returns `clarify` before changing state
204
247
 
205
248
  **Lifecycle enforcement**
206
249
  ```text
207
250
  clear state
208
251
  change premise to formal tone
209
252
  ```
210
- - Base model: conversational rewrite guidance
211
- - Context Compiler: clarifies (“No premise exists yet…”)
253
+ - Without explicit transition checks: behavior depends on host/model handling
254
+ - Context Compiler: asks for clarification and keeps saved state unchanged
212
255
 
213
256
  ---
214
257
 
@@ -227,7 +270,7 @@ Decision
227
270
  Host Application
228
271
  ├─ clarify → ask user
229
272
  ├─ passthrough → call LLM
230
- └─ update → call LLM with compiled state
273
+ └─ update → authoritative state mutated; host may call LLM with compiled state
231
274
  ```
232
275
 
233
276
  The compiler owns state updates and never calls the LLM.
@@ -251,7 +294,7 @@ Meaning:
251
294
  | kind | host behavior |
252
295
  |:-----------:|-----------------------------------------------|
253
296
  | passthrough | forward user input to LLM |
254
- | update | forward input with updated state |
297
+ | update | authoritative state mutated; host may call LLM with updated state |
255
298
  | clarify | show `prompt_to_user` and do not call the LLM |
256
299
 
257
300
  ---
@@ -315,7 +358,7 @@ The internal structure of the state is intentionally opaque to host applications
315
358
  - `export_json()` / `import_json()` transport **authoritative state only**
316
359
  - checkpoint APIs transport **serialized continuation**:
317
360
  - authoritative state
318
- - pending confirmation-required continuation state
361
+ - pending confirmation flow state
319
362
 
320
363
  Checkpoint object shape:
321
364
 
@@ -357,7 +400,7 @@ When to use checkpoint APIs:
357
400
 
358
401
  - stateless host/integration boundaries where engine instances are short-lived.
359
402
  - resume after interruption without losing pending clarification flow.
360
- - preserve confirmation-required continuation state (`pending`) across process/request boundaries.
403
+ - preserve pending confirmation flow state (`pending`) across process/request boundaries.
361
404
 
362
405
  ---
363
406
 
@@ -1,19 +1,56 @@
1
-
2
1
  # Context Compiler
3
2
 
4
3
  [![PyPI version](https://img.shields.io/pypi/v/context-compiler)](https://pypi.org/project/context-compiler/)
5
4
  [![Python versions](https://img.shields.io/pypi/pyversions/context-compiler)](https://pypi.org/project/context-compiler/)
6
5
  [![License](https://img.shields.io/pypi/l/context-compiler)](https://pypi.org/project/context-compiler/)
7
6
 
8
- Context Compiler lets users set rules and corrections that actually stick.
9
- It helps applications keep explicit user instructions consistent across turns.
10
- It stores premise and policy rules outside the model, so corrections do not drift or conflict over time.
7
+ Some behaviors require explicit host-side state machinery.
8
+
9
+ Context Compiler is a deterministic host-side state layer for LLM applications.
10
+ It handles explicit state transitions for premise and policies so that mutation
11
+ rules are fixed and repeatable.
12
+
13
+ ## What prompting and reinjection can do
14
+
15
+ Prompting and reinjection are useful. In many real systems, reinjecting saved
16
+ state text is enough to keep instructions and policies persistent across turns.
17
+
18
+ Context Compiler adds host-owned transition rules for behaviors that plain text
19
+ reinjection does not implement by itself: replace `X` only if `X` exists, block
20
+ conflicting changes and ask for confirmation, and restore saved state plus
21
+ pending confirmations from checkpoints.
22
+
23
+ ## What prompting cannot do by itself
24
+
25
+ Prompt text (including reinjected state text) helps, but it does not give your
26
+ app controlled rules for when state can change. By itself, it does not provide:
27
+
28
+ - rules your app controls for state changes
29
+ - replacement precondition checks (`use X instead of Y` when `Y` may be absent)
30
+ - confirmation flows that must complete before anything else changes
31
+ - clear decisions about when a change is blocked
32
+ - reliable checkpoint restore for both saved state and pending confirmation flow
33
+
34
+ ## What Context Compiler provides
35
+
36
+ Context Compiler provides fixed host-side state machinery:
37
+
38
+ - deterministic directive handling for explicit user state changes
39
+ - clarification instead of silent overwrite for blocked/ambiguous changes
40
+ - pending confirmation flows that must resolve before anything else changes
41
+ - checkpoint export/import for restoring saved state and pending confirmation flow
42
+ - structured saved state that the host can pass to the model
11
43
 
12
- LLMs are good at conversation, but bad at consistently following long-term rules and corrections. Constraints drift, corrections conflict, and long chats can become inconsistent.
44
+ The model generates responses. The compiler owns state transitions.
13
45
 
14
- The model writes responses. The compiler stores premise and policy rules.
46
+ ## How the compiler metaphor works
15
47
 
16
- Context Compiler is a deterministic control layer for LLM applications. It processes explicit user instructions before model calls so applications can reliably enforce premise and policy constraints.
48
+ Context Compiler treats important instructions as structured state instead of
49
+ temporary prompt text.
50
+
51
+ Like a compiler, it parses input, validates it, applies fixed rules, and
52
+ produces a stable representation the host can use. It is not source-code
53
+ compilation and not a reasoning model.
17
54
 
18
55
  ## Does it work?
19
56
 
@@ -23,7 +60,13 @@ Yes, on the current scored demo set.
23
60
  - Scored checks (**6 demos per model**; Demo 6 excluded): baseline **26 / 42**, compiler **42 / 42**, compiler+compact **42 / 42**.
24
61
  - Across tested models, compiler-mediated paths pass all scored scenarios; baseline behavior is model-dependent.
25
62
 
26
- [Full results and demo output](demos/README.md)
63
+ Interpretation guide:
64
+ - Demos `01`-`05` and `07` focus on persistence and policy-following behavior.
65
+ - Demos `08`/`09` focus on rules for when state is allowed to change.
66
+ - Demos `08`/`09` show what prompt text does not implement by itself.
67
+ - Plain reinjection can produce plausible responses, but it does not check whether replacement is allowed or wait for confirmation before saving changes.
68
+
69
+ → [Full results and demo output](demos/README.md)
27
70
  Canonical matrix: [docs/demos-results.md](docs/demos-results.md)
28
71
 
29
72
  ## Quickstart
@@ -38,9 +81,9 @@ context-compiler --json < input.txt
38
81
  `context-compiler` launches the interactive REPL.
39
82
 
40
83
  `--with-preprocessor` enables the experimental preprocessor before each REPL turn
41
- (heuristic + validation only). Near-miss inputs are not rewritten and are
42
- passed through to the engine, which continues to return clarify behavior for
43
- those forms.
84
+ (simple rule-based checks plus conservative validation). For near-miss inputs,
85
+ the preprocessor does not rewrite the text. It passes the input to the engine,
86
+ and the engine can return `clarify`.
44
87
 
45
88
  `--json` enables machine-readable NDJSON output for non-interactive usage
46
89
  (one complete JSON object per processed input line).
@@ -52,7 +95,7 @@ Preload options keep saved rules separate from in-progress confirmation state:
52
95
  continuation checkpoint (saved state + pending confirmation state).
53
96
 
54
97
  REPL commands (controller layer, not engine directives):
55
- - `state` shows current authoritative state.
98
+ - `state` shows current saved state.
56
99
  - `preview <input>` runs deterministic dry-run without mutating live state.
57
100
  - `step <input>` is an explicit alias of normal bare-input step behavior.
58
101
 
@@ -103,27 +146,25 @@ uv run pytest
103
146
 
104
147
  ---
105
148
 
106
- ## Why “Compiler”?
107
-
108
- Context Compiler treats explicit user directives as inputs to a fixed, repeatable process.
109
-
110
- Instead of relying on the LLM to remember constraints across a conversation, user instructions are compiled into structured state before the model runs.
111
-
112
- The idea is similar to a traditional compiler: user directives are translated into a structured representation that the rest of the system can rely on.
113
-
114
- ---
115
-
116
149
  ## FAQ
117
150
 
118
151
  **Is this just prompt reinjection?**
119
- Partly. Hosts still pass state to models as context. The difference is that
120
- state is maintained by a deterministic engine with explicit update rules,
121
- clarification behavior, and inspectable checkpoints.
152
+ Reinjection helps with persistence, and it remains useful. Context Compiler
153
+ handles a different problem: rules for when state is allowed to change.
154
+
155
+ Examples:
156
+ - replacement semantics (`use X instead of Y`) when `Y` may not exist
157
+ - contradiction detection before applying a mutation
158
+ - lifecycle enforcement (for example, you cannot change an unset premise)
159
+ - pending clarification flows that must be resolved before other mutations
160
+
161
+ In short: reinjection carries state forward; Context Compiler decides when your
162
+ app should change state.
122
163
 
123
164
  **Isn’t this just prompt engineering?**
124
165
  It complements prompt engineering, but solves a different problem. Prompting
125
- shapes model behavior; Context Compiler provides a deterministic state layer
126
- that updates only through explicit directives.
166
+ shapes model behavior. Context Compiler enforces state rules and updates state
167
+ only through explicit directives.
127
168
 
128
169
  ---
129
170
 
@@ -143,36 +184,38 @@ Later in the conversation:
143
184
  User: how should I make this curry?
144
185
  ```
145
186
 
146
- Your app sends the saved state to the model so the rule still applies on later turns.
187
+ Your host sends the saved policy state with this later request, so the model is
188
+ constrained by explicit state (`peanuts: prohibit`) instead of relying on memory
189
+ of earlier conversation text.
147
190
 
148
191
  ---
149
192
 
150
193
  ## Deterministic behavior (examples)
151
194
 
152
- LLMs interpret intent. Context Compiler enforces it.
195
+ Context Compiler makes mutation rules explicit so behavior stays repeatable.
153
196
 
154
197
  **Explicit directive**
155
198
  ```text
156
199
  set premise concise replies
157
200
  ```
158
201
  - Base model: silently accepts / rewrites
159
- - Context Compiler: applies a deterministic state update
202
+ - Context Compiler: applies a repeatable state update
160
203
 
161
204
  **State-dependent operation**
162
205
  ```text
163
206
  clear state
164
207
  use podman instead of docker
165
208
  ```
166
- - Base model: generic explanation
167
- - Context Compiler: rejects (“No exact policy found for 'docker'…”)
209
+ - Without explicit state transition rules: behavior depends on host/model handling
210
+ - Context Compiler: returns `clarify` before changing state
168
211
 
169
212
  **Lifecycle enforcement**
170
213
  ```text
171
214
  clear state
172
215
  change premise to formal tone
173
216
  ```
174
- - Base model: conversational rewrite guidance
175
- - Context Compiler: clarifies (“No premise exists yet…”)
217
+ - Without explicit transition checks: behavior depends on host/model handling
218
+ - Context Compiler: asks for clarification and keeps saved state unchanged
176
219
 
177
220
  ---
178
221
 
@@ -191,7 +234,7 @@ Decision
191
234
  Host Application
192
235
  ├─ clarify → ask user
193
236
  ├─ passthrough → call LLM
194
- └─ update → call LLM with compiled state
237
+ └─ update → authoritative state mutated; host may call LLM with compiled state
195
238
  ```
196
239
 
197
240
  The compiler owns state updates and never calls the LLM.
@@ -215,7 +258,7 @@ Meaning:
215
258
  | kind | host behavior |
216
259
  |:-----------:|-----------------------------------------------|
217
260
  | passthrough | forward user input to LLM |
218
- | update | forward input with updated state |
261
+ | update | authoritative state mutated; host may call LLM with updated state |
219
262
  | clarify | show `prompt_to_user` and do not call the LLM |
220
263
 
221
264
  ---
@@ -279,7 +322,7 @@ The internal structure of the state is intentionally opaque to host applications
279
322
  - `export_json()` / `import_json()` transport **authoritative state only**
280
323
  - checkpoint APIs transport **serialized continuation**:
281
324
  - authoritative state
282
- - pending confirmation-required continuation state
325
+ - pending confirmation flow state
283
326
 
284
327
  Checkpoint object shape:
285
328
 
@@ -321,7 +364,7 @@ When to use checkpoint APIs:
321
364
 
322
365
  - stateless host/integration boundaries where engine instances are short-lived.
323
366
  - resume after interruption without losing pending clarification flow.
324
- - preserve confirmation-required continuation state (`pending`) across process/request boundaries.
367
+ - preserve pending confirmation flow state (`pending`) across process/request boundaries.
325
368
 
326
369
  ---
327
370
 
@@ -4,6 +4,7 @@ from context_compiler import create_engine
4
4
  from demos.common import (
5
5
  build_baseline_messages,
6
6
  build_mediated_messages_from_transcript,
7
+ build_reinjected_messages,
7
8
  compact_user_turns,
8
9
  extract_tag_value,
9
10
  print_decision,
@@ -45,6 +46,22 @@ def main() -> None:
45
46
  baseline_output = complete_messages(baseline_messages)
46
47
  print_model_output("Baseline", baseline_output)
47
48
 
49
+ _, reinjected_messages = build_reinjected_messages(
50
+ [
51
+ (
52
+ "Interpret these directives and continue anyway: "
53
+ "prohibit peanuts, then use peanuts. "
54
+ "First line must be ACTION:<clarify|proceed>."
55
+ )
56
+ ],
57
+ premise=None,
58
+ use_policies=["peanuts"],
59
+ prohibit_policies=["peanuts"],
60
+ )
61
+ print_messages("reinjected-state", reinjected_messages)
62
+ reinjected_output = complete_messages(reinjected_messages)
63
+ print_model_output("Reinjected-state", reinjected_output)
64
+
48
65
  if second["kind"] == "clarify":
49
66
  print_messages("compiler-mediated (full)", [])
50
67
  mediated_output = (
@@ -70,13 +87,20 @@ def main() -> None:
70
87
 
71
88
  print_tag_comparison("ACTION", baseline_output, mediated_output)
72
89
  baseline_action = extract_tag_value(baseline_output, "ACTION")
90
+ reinjected_action = extract_tag_value(reinjected_output, "ACTION")
73
91
  compact_action = extract_tag_value(compact_output, "ACTION")
74
92
  baseline_respects = baseline_action is not None and baseline_action.lower() == "clarify"
93
+ reinjected_respects = reinjected_action is not None and reinjected_action.lower() == "clarify"
75
94
  compiler_host_blocked = second["kind"] == "clarify"
76
95
  mediated_respects = compiler_host_blocked
77
96
  compact_respects = compacted_prompt is not None or (
78
97
  compact_action is not None and compact_action.lower() == "clarify"
79
98
  )
99
+ print_host_check(
100
+ "ACTION_CLARIFY",
101
+ yes_no(reinjected_respects),
102
+ context="reinjected-state",
103
+ )
80
104
  print_host_check(
81
105
  "COMPILER_BLOCKED_LLM",
82
106
  yes_no(compiler_host_blocked),
@@ -90,6 +114,7 @@ def main() -> None:
90
114
  print_spec_report(
91
115
  test_name="01_contradiction_block — host clarification gate",
92
116
  baseline_pass=baseline_respects,
117
+ reinjected_state_pass=reinjected_respects,
93
118
  compiler_pass=mediated_respects,
94
119
  compiler_compact_pass=compact_respects,
95
120
  expected="host should block LLM call on contradictory directive until clarification",
@@ -6,6 +6,7 @@ from context_compiler import create_engine
6
6
  from demos.common import (
7
7
  build_baseline_messages,
8
8
  build_mediated_messages_from_transcript,
9
+ build_reinjected_messages,
9
10
  compact_user_turns,
10
11
  print_decision,
11
12
  print_host_check,
@@ -129,6 +130,24 @@ def main() -> None:
129
130
  context="baseline",
130
131
  )
131
132
 
133
+ _, reinjected_messages = build_reinjected_messages(
134
+ [user_inputs[1]],
135
+ premise=None,
136
+ use_policies=[],
137
+ prohibit_policies=["peanuts"],
138
+ extra_system_prompt=(
139
+ "If the user requests a prohibited item, refuse the literal request. "
140
+ "State briefly that the request conflicts with policy, then provide "
141
+ "the closest safe alternative recipe that excludes prohibited items."
142
+ ),
143
+ )
144
+ print_messages("reinjected-state", reinjected_messages)
145
+ reinjected_output = complete_messages(reinjected_messages)
146
+ print_model_output("Reinjected-state", reinjected_output)
147
+ reinjected_refusal = refusal_detected(reinjected_output)
148
+ reinjected_safe_alternative = safe_alternative_detected(reinjected_output)
149
+ reinjected_violation = recipe_includes_prohibited_item(reinjected_output)
150
+
132
151
  mediated_messages = build_mediated_messages_from_transcript(
133
152
  engine.state,
134
153
  user_inputs,
@@ -171,6 +190,21 @@ def main() -> None:
171
190
  if compacted_prompt is not None:
172
191
  compact_safe_alternative = True
173
192
 
193
+ print_host_check(
194
+ "REFUSAL_DETECTED",
195
+ yes_no(reinjected_refusal),
196
+ context="reinjected-state",
197
+ )
198
+ print_host_check(
199
+ "RECIPE_INCLUDES_PROHIBITED",
200
+ yes_no(reinjected_violation),
201
+ context="reinjected-state",
202
+ )
203
+ print_host_check(
204
+ "SAFE_ALTERNATIVE_DETECTED",
205
+ yes_no(reinjected_safe_alternative),
206
+ context="reinjected-state",
207
+ )
174
208
  print_host_check(
175
209
  "REFUSAL_DETECTED",
176
210
  yes_no(mediated_refusal),
@@ -202,12 +236,16 @@ def main() -> None:
202
236
  context="compiler-mediated + compact",
203
237
  )
204
238
  baseline_pass = not baseline_violation
239
+ reinjected_pass = (
240
+ reinjected_refusal or reinjected_safe_alternative
241
+ ) and not reinjected_violation
205
242
  compiler_pass = (mediated_refusal or mediated_safe_alternative) and not mediated_violation
206
243
  compact_pass = (compact_refusal or compact_safe_alternative) and not compact_violation
207
244
  passed = baseline_violation and compiler_pass and compact_pass
208
245
  print_spec_report(
209
246
  test_name="02_constraint_drift — persistent prohibition",
210
247
  baseline_pass=baseline_pass,
248
+ reinjected_state_pass=reinjected_pass,
211
249
  compiler_pass=compiler_pass,
212
250
  compiler_compact_pass=compact_pass,
213
251
  expected=(
@@ -6,6 +6,7 @@ from context_compiler import create_engine
6
6
  from demos.common import (
7
7
  build_baseline_messages,
8
8
  build_mediated_messages_from_transcript,
9
+ build_reinjected_messages,
9
10
  compact_user_turns,
10
11
  extract_tag_value,
11
12
  print_decision,
@@ -89,6 +90,16 @@ def main() -> None:
89
90
  baseline_output = complete_messages(baseline_messages)
90
91
  print_model_output("Baseline", baseline_output)
91
92
 
93
+ _, reinjected_messages = build_reinjected_messages(
94
+ [user_inputs[0], user_inputs[1], user_inputs[2]],
95
+ premise="vegan curry",
96
+ use_policies=[],
97
+ prohibit_policies=[],
98
+ )
99
+ print_messages("reinjected-state", reinjected_messages)
100
+ reinjected_output = complete_messages(reinjected_messages)
101
+ print_model_output("Reinjected-state", reinjected_output)
102
+
92
103
  mediated_messages = build_mediated_messages_from_transcript(engine.state, user_inputs)
93
104
  print_messages("compiler-mediated (full)", mediated_messages)
94
105
  mediated_output = complete_messages(mediated_messages)
@@ -108,15 +119,19 @@ def main() -> None:
108
119
  print_tag_comparison("PREMISE", baseline_output, mediated_output)
109
120
 
110
121
  baseline_premise = extract_tag_value(baseline_output, "PREMISE")
122
+ reinjected_premise = extract_tag_value(reinjected_output, "PREMISE")
111
123
  mediated_premise = extract_tag_value(mediated_output, "PREMISE")
112
124
  compact_premise = extract_tag_value(compact_output, "PREMISE")
113
125
  baseline_uses_vegan = _plan_uses_value(baseline_output, "vegan")
114
126
  baseline_uses_vegetarian = _plan_uses_value(baseline_output, "vegetarian")
127
+ reinjected_uses_vegan = _plan_uses_value(reinjected_output, "vegan")
128
+ reinjected_uses_vegetarian = _plan_uses_value(reinjected_output, "vegetarian")
115
129
  mediated_uses_vegan = _plan_uses_value(mediated_output, "vegan")
116
130
  mediated_uses_vegetarian = _plan_uses_value(mediated_output, "vegetarian")
117
131
  compact_uses_vegan = _plan_uses_value(compact_output, "vegan")
118
132
  compact_uses_vegetarian = _plan_uses_value(compact_output, "vegetarian")
119
133
  baseline_respects = not baseline_uses_vegetarian
134
+ reinjected_respects = not reinjected_uses_vegetarian
120
135
  mediated_respects = not mediated_uses_vegetarian
121
136
  compact_respects = compacted_prompt is None and not compact_uses_vegetarian
122
137
  print_host_check(
@@ -128,6 +143,15 @@ def main() -> None:
128
143
  ),
129
144
  context="baseline",
130
145
  )
146
+ print_host_check(
147
+ "PLAN_VALUES",
148
+ (
149
+ f"vegan={yes_no(reinjected_uses_vegan)}, "
150
+ f"vegetarian={yes_no(reinjected_uses_vegetarian)}, "
151
+ f"premise_tag={reinjected_premise or 'MISSING'}"
152
+ ),
153
+ context="reinjected-state",
154
+ )
131
155
  print_host_check(
132
156
  "PLAN_VALUES",
133
157
  (
@@ -149,6 +173,7 @@ def main() -> None:
149
173
  print_spec_report(
150
174
  test_name="03_explicit_premise_change — stale value removed",
151
175
  baseline_pass=baseline_respects,
176
+ reinjected_state_pass=reinjected_respects,
152
177
  compiler_pass=mediated_respects,
153
178
  compiler_compact_pass=compact_respects,
154
179
  expected="explicit premise change should remove the stale vegetarian value",
@@ -157,7 +182,7 @@ def main() -> None:
157
182
  "both compiler-mediated paths used vegan value"
158
183
  if mediated_respects and compact_respects and baseline_uses_vegetarian
159
184
  else (
160
- "all three paths used vegan value"
185
+ "all four paths used vegan value"
161
186
  if baseline_respects and mediated_respects and compact_respects
162
187
  else (
163
188
  "at least one compiler-mediated path included stale vegetarian value"