Skip to content

Commit f96c836

Browse files
authored
Merge pull request #4 from weijt606/v0.1.3
feat: v0.1.3 — ph new, --template, upgrade/uninstall, consolidate templates
2 parents 54f5547 + 420e3fe commit f96c836

33 files changed

Lines changed: 543 additions & 282 deletions

File tree

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [0.1.3] - 2026-04-08
8+
9+
### Added
10+
- `ph new <dir>` scaffold command — generates starter `harness.py`, `test_cases.json`, and `evaluate.py`
11+
- `--template` option for `ph init` — one-command workspace setup from 5 bundled templates
12+
- `ph upgrade` command — check and upgrade PolyHarness via pip
13+
- `ph uninstall` command — clean removal with confirmation prompt
14+
- 7 new tests for `ph new` and `--template` features (128 total)
15+
16+
### Changed
17+
- Consolidated `examples/` into `src/polyharness/templates/` — single source of truth, shipped with package
18+
- Redesigned README "Initialize Workspace" section: Option A (bundled template) + Option B (`ph new` scaffold)
19+
- Updated CLI Reference tables in both READMEs
20+
21+
### Removed
22+
- `examples/` directory (replaced by bundled templates)
23+
724
## [0.1.0] - 2026-04-04
825

926
### Added

README.md

Lines changed: 98 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ You want to tune it for your specific tasks — without manually tweaking prompt
7575

7676
```bash
7777
pip install polyharness
78-
ph init --agent claude-code --task-dir ./my_tasks
78+
ph init --agent claude-code --template text-classification
7979
ph run
8080
ph apply
8181
```
@@ -131,25 +131,96 @@ This auto-detects which agent backends (Claude Code, Codex, etc.) are installed
131131

132132
### 3. Initialize a workspace
133133

134+
`ph init` sets up two things:
135+
136+
1. **Who optimizes** (`--agent`) — which AI does the thinking: a CLI tool like `claude-code`, or an API like `api` / `openai`.
137+
2. **What to optimize** (`--template` or `--base-harness` + `--task-dir`) — your harness code, test cases, and evaluation script. These three are always needed for `ph run` to work.
138+
139+
#### Option A: Use a bundled template (recommended for first run)
140+
141+
PolyHarness ships with ready-to-run templates. One command sets up everything:
142+
143+
```bash
144+
ph init --agent api --template text-classification
145+
```
146+
147+
This copies a complete set of harness + tasks + evaluate script into the workspace automatically:
148+
149+
```
150+
.ph_workspace/
151+
├── base_harness/
152+
│ └── harness.py # starting code to optimize
153+
├── tasks/
154+
│ └── test_cases.json # test inputs + expected outputs
155+
├── evaluate.py # scoring script
156+
└── config.yaml # auto-generated
157+
```
158+
159+
That's it — skip to [step 4](#4-run-the-optimization-loop).
160+
161+
> Available templates: `text-classification`, `math-word-problems`, `code-generation`, `rag-qa`, `api-calling`.
162+
163+
#### Option B: Use your own project
164+
165+
You need three files: `harness.py` (code to optimize), `tasks/test_cases.json` (test data), and `evaluate.py` (scoring script). Generate them all with one command:
166+
167+
```bash
168+
ph new my-project
169+
```
170+
171+
This creates:
172+
173+
```
174+
my-project/
175+
├── base_harness/
176+
│ └── harness.py # ← edit: your starting logic
177+
├── tasks/
178+
│ └── test_cases.json # ← edit: your test inputs + expected outputs
179+
└── evaluate.py # ← edit if needed: scoring logic
180+
```
181+
182+
Edit the generated files for your task. For example, if you're building a text classifier:
183+
184+
```python
185+
# my-project/base_harness/harness.py
186+
def solve(input_data: str) -> str:
187+
# A simple starting point — the agent will improve this
188+
if "good" in input_data.lower():
189+
return "positive"
190+
return "negative"
191+
```
192+
193+
```json
194+
// my-project/tasks/test_cases.json
195+
[
196+
{"input": "This product is good", "expected": "positive"},
197+
{"input": "Terrible experience", "expected": "negative"},
198+
{"input": "The meeting is at 3pm", "expected": "neutral"}
199+
]
200+
```
201+
202+
> `evaluate.py` works out of the box — it calls `harness.solve(case["input"])`, compares with `case["expected"]`, and reports accuracy. Only edit it if your scoring needs custom logic.
203+
204+
Then initialize:
205+
134206
```bash
135207
ph init \
136208
--agent claude-code \
137-
--base-harness ./my_harness/ \
138-
--task-dir ./my_tasks/ \
139-
--eval-script ./evaluate.py
209+
--base-harness ./my-project/base_harness \
210+
--task-dir ./my-project
140211
```
141212

142-
This copies your harness code, test cases, and evaluation script into an isolated **optimization workspace** (by default `.ph_workspace` in the current directory, or the folder specified by `--workspace`).
143-
144-
#### What you need to prepare
213+
| Flag | What to pass | Required? |
214+
|------|-------------|:---------:|
215+
| `--agent` | Who optimizes: `claude-code`, `codex`, `api`, `openai`, etc. | Yes (default `api`) |
216+
| `--base-harness` | Directory with your starting harness code (at least `harness.py`) | Yes* |
217+
| `--task-dir` | Directory with `tasks/test_cases.json` and optionally `evaluate.py` | Yes* |
218+
| `--eval-script` | Path to `evaluate.py`, if it lives outside `--task-dir` | Only if not in task-dir |
219+
| `--workspace` | Where to create the workspace (default `.ph_workspace`) | No |
145220

146-
| Item | What it is | Example |
147-
|------|-----------|---------|
148-
| **base-harness/** | A directory with your starting harness code. Must contain at least one entry file (default: `harness.py`). This is the code PolyHarness will iteratively optimize. | A Python file with a `classify(text)` or `solve(question)` function |
149-
| **tasks/** | A directory with `test_cases.json` — a JSON array of test inputs and expected outputs. Each item should have an `"input"` and `"expected"` field. | `[{"input": "2+3", "expected": "5"}, ...]` |
150-
| **evaluate.py** | A script that runs the harness against each task and outputs a JSON score. Must print `{"overall_score": 0.85, "task_scores": {...}}` to stdout. | See any `examples/*/evaluate.py` for a working template |
221+
\* Technically optional at `init` time, but `ph run` will fail without harness code and test data.
151222

152-
> **Tip:** If you're unsure about the format, start with one of the bundled `examples/` directories — each one is a complete, working template you can copy and adapt.
223+
`ph init` copies everything into an isolated **optimization workspace** — your original code is never modified.
153224

154225
**Configure Your Agent**
155226

@@ -190,14 +261,9 @@ ph clean --keep-best # remove candidates to free disk space
190261
### Try it now (no API key needed)
191262

192263
```bash
193-
cd examples/math-word-problems
194-
195-
ph init --agent local \
196-
--base-harness ./base_harness \
197-
--task-dir . \
198-
--workspace .ph_workspace
199-
200-
ph log --workspace .ph_workspace
264+
ph init --agent local --template math-word-problems
265+
ph run --max-iterations 5
266+
ph log
201267

202268
# Search Tree
203269
# └── iter_0 0.3500
@@ -277,10 +343,8 @@ When you run `ph init --agent claude-code`, PolyHarness automatically generates
277343
If you're running a local model (Ollama, vLLM, LM Studio, or any OpenAI-compatible server), use the `openai` backend:
278344

279345
```bash
280-
# 1. Initialize
281-
ph init --agent openai \
282-
--base-harness ./my_harness/ \
283-
--task-dir ./my_tasks/
346+
# 1. Initialize (use a template, or --base-harness + --task-dir for your own project)
347+
ph init --agent openai --template text-classification
284348

285349
# 2. Configure your local endpoint
286350
ph config set proposer.model llama3.3
@@ -388,6 +452,7 @@ python -m polyharness --version
388452
| Command | Description |
389453
|---------|-------------|
390454
| `ph doctor` | Detect installed agents and environment status |
455+
| `ph new [dir]` | Scaffold a new harness project (generates harness.py + tasks + evaluate.py) |
391456
| `ph init` | Initialize workspace with auto-copy of harness, tasks, eval script |
392457
| `ph run` | Start the optimization search loop |
393458
| `ph status` | Progress table with elapsed time, improvement rate, and delta |
@@ -403,6 +468,8 @@ python -m polyharness --version
403468
| `ph clean` | Remove candidate dirs to free disk space (`--keep-best`, `-y`) |
404469
| `ph config show` | Display the current workspace configuration |
405470
| `ph config set K V` | Modify a config value via dot-notation (with validation) |
471+
| `ph upgrade` | Upgrade PolyHarness to the latest version |
472+
| `ph uninstall` | Uninstall PolyHarness from the current environment (`-y` to skip confirm) |
406473

407474
### Global flags
408475

@@ -440,8 +507,7 @@ The score trajectories below are measured from the bundled examples using the cu
440507
### Text Classification (sentiment analysis)
441508
442509
```bash
443-
cd examples/text-classification
444-
ph init --agent local --base-harness ./base_harness --task-dir .
510+
ph init --agent local --template text-classification
445511
ph run --max-iterations 3
446512
447513
# iter_0: 0.65 → iter_1: 1.00 ★ (naive word list → expanded lexicon)
@@ -450,8 +516,7 @@ ph run --max-iterations 3
450516
### Math Word Problems (numerical reasoning)
451517

452518
```bash
453-
cd examples/math-word-problems
454-
ph init --agent local --base-harness ./base_harness --task-dir .
519+
ph init --agent local --template math-word-problems
455520
ph run --max-iterations 5
456521

457522
# iter_0: 0.35 → iter_1: 0.50 → iter_2: 0.65 → iter_3: 0.90 ★
@@ -461,8 +526,7 @@ ph run --max-iterations 5
461526
### Code Generation (function synthesis)
462527

463528
```bash
464-
cd examples/code-generation
465-
ph init --agent local --base-harness ./base_harness --task-dir .
529+
ph init --agent local --template code-generation
466530
ph run --max-iterations 5
467531

468532
# iter_0: 0.27 → iter_1: 0.50 → iter_2: 0.68 → iter_3: 0.95 ★
@@ -472,8 +536,7 @@ ph run --max-iterations 5
472536
### API Calling (endpoint routing + parameter extraction)
473537

474538
```bash
475-
cd examples/api-calling
476-
ph init --agent local --base-harness ./base_harness --task-dir .
539+
ph init --agent local --template api-calling
477540
ph run --max-iterations 5
478541

479542
# iter_0: 0.19 → iter_1: 0.55 → iter_2: 0.77 → iter_3: 0.87 ★
@@ -483,8 +546,7 @@ ph run --max-iterations 5
483546
### RAG Question Answering (retrieval + answer extraction)
484547

485548
```bash
486-
cd examples/rag-qa
487-
ph init --agent local --base-harness ./base_harness --task-dir .
549+
ph init --agent local --template rag-qa
488550
ph run --max-iterations 5
489551

490552
# iter_0: 0.51 → iter_1: 0.79 ★
@@ -519,14 +581,7 @@ bin/
519581
├── ph.mjs # npm wrapper
520582
└── postinstall.mjs # npm postinstall
521583
522-
examples/
523-
├── text-classification/ # 20 test cases
524-
├── math-word-problems/ # 20 test cases
525-
├── code-generation/ # 20 tasks × 3 inputs
526-
├── api-calling/ # 20 test cases
527-
└── rag-qa/ # 20 QA pairs + 10-doc knowledge base
528-
529-
tests/ # 121 tests (pytest)
584+
tests/ # 128 tests (pytest)
530585
```
531586

532587
## Local Development

0 commit comments

Comments
 (0)