Metadata-Version: 2.4
Name: agent-prompt-engineering
Version: 0.1.0
Summary: Deterministic data->prompt builder + cognition chains + optional grammar gate — the shared base of the chaincompiler ecosystem.
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: rulecatcher
Requires-Dist: agent-skilltree>=0.2.1

---
name: prompt-engineering
description: The Prompt Engineering System — a deterministic prompt builder. Give it a payload (a "block": attributes + methods + a render sequence) and it produces the SAME prompt every time. Compose blocks into stored "prompt templates". Use it to make system prompts, personas, rule blocks, few-shot blocks, or any prompt. No model call, no randomness.
when_to_use: Building or reusing prompts/personas/templates programmatically; you want the same spec to render the same prompt every time; making a new prompt template (folder of blocks).
---

# Prompt Engineering System

A skill (this `SKILL.md` + the code beside it) that turns **data → a prompt**, deterministically. The
model decides *what* spec to write; this engine guarantees *how* it renders — same inputs, same output,
every time. That reliability is the point: an agent reads this skill and uses it to make prompts/personas
the same way each time.

## Vocabulary

- **block** — one payload (`values` + `methods` + a `template_sequence`) that renders to a chunk of prompt
- **prompt template** — a stored, ordered set of blocks (a folder under `templates/`) that renders to one
  full prompt

There is **no baked-in structure and no "levels."** You bring your own via blocks and templates.

## Use it (the package `prompt_engineering`)

```python
# pip install -e .  (or add this skill dir to sys.path for in-place use)
from prompt_engineering import render, render_template, list_templates

# 1) render a single block from a payload
render({
  "values": {"role": "Worldsmith", "domain": "otters"},
  "methods": [
    {"name": "format_title", "func": "return f'# {self.role}'", "add_to_sequence": True},
    {"name": "format_intro", "func": "return f'You are the {self.role} of {self.domain}.'", "add_to_sequence": True},
  ],
})  # → "# Worldsmith\n\nYou are the Worldsmith of otters."   (same payload → same prompt, always)

# 2) render a stored prompt template (its blocks, joined in order)
list_templates()              # ['five_level', 'simple_agent']
render_template("five_level") # → one prompt with WORLD/EGREGORE/DEITY/PROGENITOR/AGENT sections
```

Or from the shell (see `scripts/` below): `python scripts/make_prompt.py --template five_level`.

> **Naming tip:** name block methods `format_*` so they don't shadow the `values` they read
> (a method `duty` would overwrite the value `duty`; `format_duty` reading `self.duty` is correct).

## Add a prompt template — DROP A FOLDER

```
templates/
  {template_name}/
    template.json   # {name, description, blocks: ["block1.json", "block2.json", ...]}
    {block}.json    # the block payloads (any structure you want)
```

Create the folder, write `template.json`, drop in the block payloads. Nothing in the engine changes.
`list_templates()` / `render_template(name)` pick it up by convention.

## Resource files (referenced by relative path)

- `prompt_engineering/prompt_engine.py` — the API: `render`, `render_file`, `list_templates`, `load_template`,
  `render_template`, `render_template_blocks`
- `prompt_engineering/template_mixins.py` — the engine internals (add attributes/methods from data; run a sequence)
- `examples/` — single-block payloads for different **prompt block types** (system, persona, rules,
  few-shot, constraints, output-format) and full personas — read these to learn the block format
- `templates/five_level/` — the 5-level model **as a prompt template** (an example, not a default)
- `templates/simple_agent/` — a one-block template (proves the add-by-folder mechanic)
- `prompt_engineering/cognition.py` — the cognition-chain stack (attention chain / chain-of-reasoning / skill chain) on
  the engine, + `validate_chain` (a shallow no-dep broken-detector)
- `prompt_engineering/gate.py` — the REAL gate: `gate(text, exemplars)` LEARNS the grammar from exemplar chains (you don't
  hand-write the error rules) → violations + fixes + the `orthogonal`/`syntax_break` (steerable/fatal) verdict
- **`rulecatcher`** — the grammar learner/linter the gate runs on; now an installed dependency (D3, un-vendored)
- `prompt_engineering/persona.py` — `make_persona(spec)` / `make_persona_file(path)`: generate a full persona prompt
  (block types + a cognition DSL block) from a small spec
- `examples/persona_*.json` — example persona systems (debugger, socratic, code-reviewer) with reasoning DSLs
- `scripts/make_prompt.py` — render a block/template from the command line
- `scripts/make_persona.py` — generate a persona prompt from a spec file
- `scripts/new_template_skill.py` — scaffold a NEW skill package for a prompt template
- `test_prompt_engine.py` · `test_cognition.py` · `test_persona.py` · `test_gate.py` — run to verify (all NO-API)

## Cognition chains & personas (the ACCC/CORCC/SCCC stack, rebuilt right)

`prompt_engineering/cognition.py` is the clean version of the old `*CC` "compiler-compilers": an **attention chain**, a
**chain-of-reasoning**, and a **skill chain** are just prompt templates composed on this engine (a CoR
*nests* an AC = block-nesting). **Rendering never touches a grammar engine or a DB.**

The **gate is a separate, optional layer** (`prompt_engineering/gate.py`, on the **`rulecatcher`** package). You don't
hand-write the error rules: `gate(text, exemplars)` LEARNS the grammar from the template's exemplar chains
(`next_kind` = shape, `next_token` = vocabulary), then lints a candidate → violations + fixes + the
`orthogonal` (in the language, wrong slot → **steerable**) vs `syntax_break` (foreign → **fatal**) verdict.
`rulecatcher` is an installed dependency (D3), so the real gate runs everywhere it's installed.
(`validate_chain` remains a shallow no-dep fallback.)

```python
from prompt_engineering import render_cor, gate, make_persona

render_cor("Debugger", ["Symptom", "Repro", "Hypothesis"], "Localize", "the root cause")  # a CoR persona
gate("[Goal] ⇒ [Repro] ⇒ |Localize|",                                                     # learn from exemplars, then lint:
     exemplars=["[Symptom] ⇒ [Repro] ⇒ |Localize|", "[Symptom] ⇒ [Bisect] ⇒ |RootCause|"])
# → {ok: False, verdict: 'orthogonal', violations: [{found:'Goal', candidates:['Symptom'], ...}]}

make_persona({                                   # a whole persona with a complex reasoning DSL, in one call
  "name": "Ada", "role": "a senior debugger",
  "reasoning": {"foci": ["Symptom", "Repro", "Bisect"], "held": "RootCause", "decision": "the minimal fix"},
  "rules": ["Reproduce before theorizing."], "output": "A markdown report.",
})
```

## Why deterministic matters

`render` runs the `template_sequence` in order and joins the non-empty results — pure composition, no
model call. That's what lets an agent rely on it to produce prompts consistently across runs.
