executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
iterative-prompt-refinementImplements systematic prompt evolution through baseline generation, structured evaluation against rubrics, targeted revision, and regression validation to continuously improve prompt quality.
Independent GitHub snapshot · Automated classification · Original documentation governs
Implements systematic prompt evolution through a continuous improvement loop: baseline generation → structured evaluation against rubrics → targeted revision → regression validation. This skill makes the model design and implement automated prompt testing pipelines that measure prompt quality improvements with statistical rigor and prevent regressions during iterative development.
Use this skill when:
Avoid this skill for:
from dataclasses import dataclass, field
from typing import Callable
import json
from pathlib import Path
@dataclass
class TestCase:
"""A single test case for prompt evaluation."""
input_text: str
expected_output: str | None = None # Optional ground truth
expected_fields: dict | None = None # If structured output, required fields
@dataclass
class RubricDimension:
"""A single scoring dimension in the evaluation rubric."""
name: str
weight: float # Must sum to 1.0 across all dimensions
max_score: int = 5
description: str = ""
@dataclass
class PromptVersion:
"""A versioned prompt with its performance metrics."""
version_id: str
prompt_template: str
test_cases: list[TestCase]
rubric: list[RubricDimension]
scores: dict[str, float] = field(default_factory=dict)
case_scores: list[dict] = field(default_factory=list)
class PromptRefinementEngine:
"""Manages prompt versions, evaluation, and A/B comparison."""
def __init__(self, llm_client: Any, rubric: list[RubricDimension]) -> None:
self._llm = llm_client
self._rubric = rubric
self._versions: dict[str, PromptVersion] = {}
def add_version(
self,
version_id: str,
prompt_template: str,
test_cases: list[TestCase]
) -> None:
"""Register a new prompt version for evaluation."""
total_weight = sum(d.weight for d in self._rubric)
assert abs(total_weight - 1.0) < 0.01, f"Rubric weights must sum to 1.0, got {total_weight}"
self._versions[version_id] = PromptVersion(
version_id=version_id,
prompt_template=prompt_template,
test_cases=test_cases,
rubric=self._rubric
)
def evaluate_version(self, version_id: str) -> dict[str, float]:
"""Run full evaluation of a prompt version against the rubric."""
if version_id not in self._versions:
raise ValueError(f"Unknown version: {version_id}")
version = self._versions[version_id]
case_scores = []
for i, tc in enumerate(version.test_cases):
response = self._llm.generate(version.prompt_template.format(input_text=tc.input_text))
output = response.choices[0].message.content
# Score each rubric dimension
dimension_scores: dict[str, float] = {}
for dim in version.rubric:
score = self._score_dimension(dim.name, tc, output)
dimension_scores[dim.name] = score
case_score = sum(
dim.weight * dimension_scores[dim.name] / dim.max_score
for dim in version.rubric
)
case_scores.append({
"case_index": i,
"input": tc.input_text[:100],
"total_score": round(case_score, 3),
"dimension_scores": {k: round(v / dim.max_score, 3)
for k, v in dimension_scores.items()},
})
# Aggregate scores
aggregate = {}
for dim in version.rubric:
avg = sum(cs["dimension_scores"].get(dim.name, 0) for cs in case_scores) / len(case_scores)
aggregate[dim.name] = round(avg * dim.weight * dim.max_score, 3)
total = sum(aggregate.values())
version.scores = aggregate
version.case_scores = case_scores
return {"total": round(total, 3), **aggregate}
def _score_dimension(self, dimension_name: str, tc: TestCase, output: str) -> float:
"""Score a single rubric dimension for one test case. Uses LLM-as-judge."""
prompt = f"""Evaluate the following output on the '{dimension_name}' dimension (1-5 scale).
Criteria for this dimension: {self._get_dimension_criteria(dimension_name)}
Input: {tc.input_text[:500]}
Expected: {tc.expected_output or 'N/A'}
Actual Output: {output}
Score only a number 1-5. Return nothing else.
"""
response = self._llm.generate(prompt)
try:
score = int(response.choices[0].message.content.strip())
return max(1, min(5, score))
except ValueError:
return 3 # Default neutral score on parse failure
def _get_dimension_criteria(self, dimension_name: str) -> str:
"""Return the scoring criteria for a given rubric dimension."""
criteria = {
"correctness": "1=Completely wrong or irrelevant, 3=Partially correct with errors, 5=Factually accurate and on-topic",
"completeness": "1=Major aspects missing, 3=Most aspects covered, 5=All relevant aspects included without omission",
"tone": "1=Inappropriate tone for context, 3=Adequate but inconsistent, 5=Perfectly matched tone throughout",
"format": "1=No structure or formatting, 3=Roughly follows format with errors, 5=Flawlessly follows required format",
}
return criteria.get(dimension_name, "Score based on overall quality (1-5)")
def compare_versions(self, v1_id: str, v2_id: str) -> dict:
"""Compare two prompt versions with statistical significance testing."""
if v1_id not in self._versions or v2_id not in self._versions:
raise ValueError("Both versions must exist")
v1 = self._versions[v1_id]
v2 = self._versions[v2_id]
assert len(v1.test_cases) == len(v2.test_cases), "Test suites must match"
# Paired comparison per test case
differences = []
for i in range(len(v1.test_cases)):
s1 = v1.case_scores[i]["total_score"] if v1.case_scores else 0
s2 = v2.case_scores[i]["total_score"] if v2.case_scores else 0
differences.append(s2 - s1)
mean_diff = sum(differences) / len(differences) if differences else 0
# Simple significance check (paired t-test approximation)
if len(differences) > 1:
variance = sum((d - mean_diff)**2 for d in differences) / (len(differences) - 1)
std_error = (variance / len(differences)) ** 0.5
t_statistic = mean_diff / std_error if std_error > 0 else 0
# Approximate: |t| > 2.0 suggests significance at ~95% for n>20
is_significant = abs(t_statistic) > 2.0
else:
t_statistic = mean_diff
is_significant = False
return {
"version_1": v1_id,
"version_2": v2_id,
"mean_improvement": round(mean_diff, 4),
"t_statistic": round(t_statistic, 4),
"is_significant": is_significant,
"n_test_cases": len(differences),
}
import difflib
from datetime import datetime
@dataclass
class PromptDiff:
"""Represents changes between two prompt versions."""
version_from: str
version_to: str
additions: list[str]
deletions: list[str]
timestamp: str
class PromptRollbackManager:
"""Manages prompt version history and rollback capabilities."""
def __init__(self) -> None:
self._history: list[PromptDiff] = []
self._snapshots: dict[str, str] = {} # version_id -> prompt_template
def record_change(
self,
from_version: str,
to_version: str,
template: str
) -> PromptDiff:
"""Record a change between prompt versions with diff analysis."""
if from_version not in self._snapshots:
raise ValueError(f"Cannot diff from unknown version: {from_version}")
old_template = self._snapshots[from_version]
# Compute line-level diff
old_lines = old_template.splitlines()
new_lines = template.splitlines()
differ = difflib.unified_diff(old_lines, new_lines)
additions = []
deletions = []
for line in differ:
if line.startswith("+") and not line.startswith("+++"):
additions.append(line[2:])
elif line.startswith("-") and not line.startswith("---"):
deletions.append(line[2:])
diff = PromptDiff(
version_from=from_version,
version_to=to_version,
additions=additions,
deletions=deletions,
timestamp=datetime.now().isoformat(),
)
self._history.append(diff)
self._snapshots[to_version] = template
return diff
def rollback_to(self, target_version: str) -> str | None:
"""Rollback to a specific prompt version by ID."""
if target_version not in self._snapshots:
return None
return self._snapshots[target_version]
from typing import Protocol
class PromptEvaluator(Protocol):
"""Protocol for evaluating a prompt output."""
def evaluate(self, input_text: str, expected: str, actual: str) -> dict[str, float]: ...
class PromptRegressionTester:
"""Runs regression tests across multiple prompt versions."""
def __init__(self, evaluator: PromptEvaluator) -> None:
self._evaluator = evaluator
self._regression_threshold = 0.1 # Max allowed score drop
def run_regression(
self,
test_cases: list[dict[str, str]],
baseline_results: dict[str, float],
new_results: dict[str, float],
) -> dict:
"""Compare new results against baseline to detect regressions."""
regressed = []
improved = []
for case_id in baseline_results:
old_score = baseline_results[case_id]
new_score = new_results.get(case_id, 0)
delta = new_score - old_score
if delta < -self._regression_threshold:
regressed.append({
"case_id": case_id,
"old_score": round(old_score, 3),
"new_score": round(new_score, 3),
"delta": round(delta, 3),
})
elif delta > self._regression_threshold:
improved.append({
"case_id": case_id,
"old_score": round(old_score, 3),
"new_score": round(new_score, 3),
"delta": round(delta, 3),
})
return {
"total_cases": len(baseline_results),
"regressed": len(regressed),
"improved": len(improved),
"unchanged": len(baseline_results) - len(regressed) - len(improved),
"regressed_cases": regressed,
"improved_cases": improved,
}
# BAD — No regression testing
new_prompt = "You are an expert assistant. Answer questions accurately."
response = llm.generate(new_prompt.format(question="What is 2+2?"))
# What if it broke the tone? No one knows without systematic comparison.
# GOOD — Regression-tested change
test_suite = [
{"id": "math_01", "input": "What is 2+2?", "expected": "4"},
{"id": "tone_01", "input": "Tell me a joke", "expected": "..."},
]
baseline = engine.evaluate_version("v3")
engine.add_version("v4", improved_template, test_suite)
new_results = engine.evaluate_version("v4")
regression_report = tester.run_regression(test_suite, baseline, new_results)
assert regression_report["regressed"] == 0, "Regression detected!"
from dataclasses import dataclass, field
from enum import Enum
class HypothesisStatus(Enum):
PENDING = "pending"
TESTING = "testing"
VALIDATED = "validated"
REJECTED = "rejected"
@dataclass
class ImprovementHypothesis:
"""Tracks a hypothesis about how to improve a prompt."""
id: str
description: str # e.g., "Adding examples improves correctness by ~15%"
target_dimension: str
predicted_improvement: float # Expected improvement in score (0-1)
status: HypothesisStatus = HypothesisStatus.PENDING
actual_improvement: float | None = None
class HypothesisManager:
"""Manages prompt improvement hypotheses and tracks validation."""
def __init__(self, engine: PromptRefinementEngine) -> None:
self._engine = engine
self._hypotheses: dict[str, ImprovementHypothesis] = {}
def add_hypothesis(self, hypothesis: ImprovementHypothesis) -> str:
"""Register a new improvement hypothesis."""
self._hypotheses[hypothesis.id] = hypothesis
return hypothesis.id
def validate_hypothesis(
self,
hypothesis_id: str,
baseline_version: str,
test_version: str
) -> ImprovementHypothesis:
"""Run A/B test and update hypothesis with actual results."""
if hypothesis_id not in self._hypotheses:
raise ValueError(f"Unknown hypothesis: {hypothesis_id}")
comp = self._engine.compare_versions(baseline_version, test_version)
actual = comp["mean_improvement"]
h = self._hypotheses[hypothesis_id]
h.actual_improvement = actual
h.status = (
HypothesisStatus.VALIDATED
if comp["is_significant"] and actual > 0
else HypothesisStatus.REJECTED
)
return h
def get_active_hypotheses(self) -> list[ImprovementHypothesis]:
"""Return hypotheses that still need validation."""
return [h for h in self._hypotheses.values()
if h.status == HypothesisStatus.PENDING]
code-philosophy (5 Laws of Elegant Defense): parse don't validate at rubric boundary, fail fast on regression detectionWhen this skill is active, deliver:
| Skill | Purpose |
|---|---|
prompt-chaining | Each step in a chain can be individually refined with this pattern |
evaluation-monitoring | Production monitoring complements development-time refinement |
structured-output-enforcement | Ensures prompt outputs are valid before evaluation |
📖 skill(local cache): prompt-chaining, evaluation-monitoring, structured-output-enforcement