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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Context Compiler Directive Drafter

Turn natural-language requests into candidate Context Compiler directives.
Turn user messages into candidate Context Compiler directives with a conservative validation boundary.

`context-compiler-directive-drafter` helps hosts translate user requests like:
`context-compiler-directive-drafter` helps hosts validate directive candidates such as:

> Please use Docker for container examples.
> use docker

into candidate directives, such as:
and reject nearby unsafe or non-canonical inputs such as:

> use docker
> Please use Docker for container examples.

This package drafts suggestions for the Context Compiler. Only `context-compiler` applies directives and updates state.

Expand All @@ -20,9 +20,9 @@ The drafter suggests candidate directives. context-compiler decides what to do w

Use this package when you want to:

- Translate user requests into safe, canonical directives.
- Validate and draft safe, canonical directives from user messages.
- Avoid accidental or unsafe state changes from ambiguous input.
- Add a conservative natural-language-to-directive step before applying changes.
- Add a conservative drafting step before applying changes.

## Installation

Expand All @@ -45,7 +45,7 @@ Draft and validate a candidate directive:
```python
from context_compiler_directive_drafter import preprocess_heuristic, parse_preprocessor_output

user_message = "Please use Docker for container examples."
user_message = "use docker"
result = preprocess_heuristic(user_message)

candidate = parse_preprocessor_output(
Expand Down Expand Up @@ -78,7 +78,7 @@ Public interface:

1. Run `preprocess_heuristic(message)`.
2. If a candidate exists, validate it with `parse_preprocessor_output(...)`.
3. If not valid, consider fallback drafting (e.g., LLM prompt).
3. If not valid, you may consider fallback drafting (e.g., an LLM prompt).
4. Always validate fallback output with `parse_preprocessor_output(..., source_input=message)`.
5. If validation yields a directive, pass it to `context-compiler`.
6. Otherwise, pass the original user input unchanged.
Expand All @@ -104,6 +104,8 @@ Use render_prompt(path, state) to load a template and fill it with the current c

The rendered prompt can be sent to an LLM to attempt directive drafting when heuristic drafting does not produce a result.

In `0.1.x`, the validated contract remains intentionally narrow: fallback output must still resolve to a canonical whole-message directive shape that passes `source_input` validation. Broader semantic rewriting is not part of the current package contract.

Any model output should still be validated with parse_preprocessor_output(...) or validate_preprocessor_output(...) before it is used.

## Current Limits
Expand All @@ -113,6 +115,7 @@ This package is intentionally conservative. It abstains when input is:
- Ambiguous, mixed-intent, or quoted.
- Embedded in prose, markdown, or code.
- Not matching a canonical directive form.
- A non-canonical natural-language paraphrase of a directive.

Boundary rules:

Expand Down
10 changes: 9 additions & 1 deletion src/context_compiler_directive_drafter/output_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@ def _contains_multiple_candidate_directives(text: str) -> bool:


def _is_safe_fallback_directive_rewrite(source_input: str, directive_output: str) -> bool:
"""Reject fallback rewrites that bypass strict whole-message boundaries."""
"""Allow only strict whole-message canonical fallback matches.

source_input validation is a boundary guard, not a second natural-language
parser. At the current 0.1 boundary, fallback output is accepted only when
the source is either the exact strict structured directive contract or a
whole-message canonical directive shape that normalizes to the same
directive. Unsafe wrappers, reported speech, mixed prose, and near-miss
canonicalizations remain rejected.
"""
source = re.sub(r"\s+", " ", source_input.strip().lower())
directive = re.sub(r"\s+", " ", directive_output.strip().lower())

Expand Down
22 changes: 16 additions & 6 deletions src/context_compiler_directive_drafter/prompts/default.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Default directive-drafter prompt.
# Use this prompt for most instruction-following models.
# Use this prompt for the strict 0.1.x canonical-only drafting boundary.

You convert the latest user message into a single Context Compiler directive, or `<NO_DIRECTIVE>`.

Expand Down Expand Up @@ -94,18 +94,19 @@ Replacement rules:

Conversion rules:

* For this prompt version, emit a directive only when the whole message already expresses one allowed directive form.
* Convert only clear, direct, explicit state-modification instructions into one canonical directive.
* Use the user’s original wording for `<value>` and `<item>` where possible.
* Do not expand meaning beyond what is explicitly stated.

Examples:
Message: don't use peanuts
Output: prohibit peanuts

Message: please use docker
Message: use docker
Output: use docker

Message: switch from docker to podman
Message: prohibit peanuts
Output: prohibit peanuts

Message: use podman instead of docker
Output: use podman instead of docker

Message: can you avoid peanuts?
Expand All @@ -114,6 +115,15 @@ Output: <NO_DIRECTIVE>
Message: I prefer concise replies
Output: <NO_DIRECTIVE>

Message: please use docker
Output: <NO_DIRECTIVE>

Message: don't use peanuts
Output: <NO_DIRECTIVE>

Message: switch from docker to podman
Output: <NO_DIRECTIVE>

Message: set premise to concise replies
Output: <NO_DIRECTIVE>

Expand Down
23 changes: 17 additions & 6 deletions src/context_compiler_directive_drafter/prompts/llama.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Directive-drafter prompt for Llama-family models.
# Use this when the model shows weaker adherence to strict output constraints.
# Use this for the strict 0.1.x canonical-only drafting boundary when the model
# needs extra output-shape reinforcement.

You convert the latest user message into a single Context Compiler directive, or `<NO_DIRECTIVE>`.

Expand Down Expand Up @@ -82,18 +83,19 @@ Replacement rules:

Conversion rules:

* For this prompt version, emit a directive only when the whole message already expresses one allowed directive form.
* Convert only clear, explicit state-modification instructions into one canonical directive.
* Use the user’s original wording for `<value>` and `<item>` where possible.
* Do not reinterpret or expand meaning beyond what is explicitly stated.

Examples:
Message: don't use peanuts
Output: prohibit peanuts

Message: please use docker
Message: use docker
Output: use docker

Message: switch from docker to podman
Message: prohibit peanuts
Output: prohibit peanuts

Message: use podman instead of docker
Output: use podman instead of docker

Message: can you avoid peanuts?
Expand All @@ -102,6 +104,15 @@ Output: <NO_DIRECTIVE>
Message: I prefer concise replies
Output: <NO_DIRECTIVE>

Message: please use docker
Output: <NO_DIRECTIVE>

Message: don't use peanuts
Output: <NO_DIRECTIVE>

Message: switch from docker to podman
Output: <NO_DIRECTIVE>

Message: set premise to concise replies
Output: <NO_DIRECTIVE>

Expand Down