项目文件夹

文件
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

102 行
4.7 KiB
Markdown

# Prompt evals
A tiny A/B harness for one question: **does this guidance sentence actually
change behavior?** `AGENTS.md` is loaded into every agent, so every line there
has a cost. A sentence earns its place only if it measurably fixes a mistake an
undirected agent makes — otherwise it's noise.
## How it works
Each **case** seeds an isolated sandbox with files, hands the agent a realistic
task (e.g. "apply this PR-review feedback"), and judges the result against a
rubric. We run every **candidate** guidance string — including an empty
`baseline` — and compare pass rates:
- `baseline` should **reproduce the mistake** (low pass rate). If it doesn't,
the case isn't testing anything.
- A candidate **earns its place** if it lifts the pass rate to ~100%.
- Among candidates that work, the **shortest** wins. That's the line we add.
The agent runs via the `claude` CLI in a throwaway `/tmp` sandbox (so it sees no
`AGENTS.md` except the guidance we inject through `--append-system-prompt`). A
fresh `claude` instance acts as the LLM judge.
## Findings: comment hygiene
The `pr-review-comments` case seeds a config field that already carries a
change-narration comment (`// bumped from 5000 to 8000 …`) and asks the agent to
bump the value again. An undirected agent reliably keeps narrating the history
instead of deleting a comment that only ever described a past change.
Pass rate by guidance, on both a small and a frontier agent model (judge:
Sonnet 4.6):
| candidate | guidance injected | Haiku 4.5 | Opus 4.8 |
| --- | --- | ---: | ---: |
| baseline | _(none)_ | 0–13% | 0% |
| describe-now | "Comments describe the code as it is, not how it changed." | 0% | 0% |
| why-not-what | "Comments explain why the code is the way it is; they never narrate what changed." | 13% | — |
| no-history | "Never write comments that reference the PR, the review, or a previous version of the code." | 25% | — |
| drop-tombstones | "Code comments describe the current code, never its history. When you edit a line, remove any nearby comment that just narrates a past change." | 75% | 67% |
| **delete-stale** | **"When you change code, delete any comment that only records its history."** | 50% | **~94%** |
(Haiku at n=8; Opus `baseline`/`delete-stale` confirmed at n=6 then n=10 →
0/16 and 15/16.)
Three things fell out of this:
1. **Telling the model how to _write_ comments doesn't make it _remove_ a stale
one.** The "write good comments" phrasings (`describe-now`, `why-not-what`,
`no-history`) sit in the noise around baseline on both models — the agent
reads them as advice for new comments, not a mandate to clean up the
existing one. Only guidance that explicitly says to _delete_ history comments
moves the needle.
2. **The best phrasing is model-dependent.** The terse one-liner `delete-stale`
is near-perfect on Opus (~94%) but only halfway on Haiku; the wordier
`drop-tombstones` is the reverse (75% Haiku, 67% Opus). Extra words help a
small model and distract a frontier one. We optimize for the model our agents
actually run on (Opus), so the one-liner wins — and it's the shorter line.
3. **The _add_ habit barely reproduces on modern models.** Earlier, weaker cases
(write fresh code; apply a clean rename) passed ~100% at baseline — the agents
almost never _add_ a change-narration comment unprompted. The habit only
surfaces under mimicry, when stale history comments already exist to copy.
`delete-stale` earned its line in the root `AGENTS.md`; the other phrasings did
not.
## Running
Requires the `claude` CLI on PATH, authenticated. Node 22+ runs the TypeScript
directly — no install step.
```bash
cd evals
pnpm eval # all cases, all candidates, 3 trials
TRIALS=5 node src/cli.ts # more trials = tighter signal
node src/cli.ts pr-review-comments # one case
CANDIDATES=baseline,describe-now node src/cli.ts # subset of candidates
AGENT_MODEL=claude-haiku-4-5 node src/cli.ts # pin the agent model
```
Results are printed and written to `results/latest.md`.
## Adding a case
Drop a file in `src/cases/` exporting an `EvalCase` and register it in
`src/cases/index.ts`. A good case has a `task` that tempts the mistake and a
`rubric` the judge can apply mechanically. Confirm `baseline` fails before
trusting any candidate that passes.
## Layout
```
src/
types.ts EvalCase / Candidate / Verdict
agent.ts runs the agent in a sandbox, with/without guidance
judge.ts scores an artifact against a rubric (LLM judge)
runner.ts baseline-vs-candidates A/B for one case
candidates.ts the guidance phrasings under test
cases/ the scenarios
cli.ts entry point
```