hs:bakeoff
Several candidate directions, undecidable by reasoning. Build a cheap probe for each, run every probe on the same input and the same mechanical metric, and let the numbers pick the winner. The asset isn't "pick the biggest number" — an LLM does that too. It's the part that refuses to crown a winner when the gap sits inside the measured noise. Trust reality, accept token cost — but only when justified.Nhiều hướng ứng viên, lập luận không tách được. Dựng một probe rẻ cho mỗi hướng, chạy mọi probe trên cùng một input và cùng một metric cơ học, rồi để số liệu chọn. Tài sản không phải "chọn số lớn nhất" — LLM cũng làm được. Nó là phần từ chối trao chiến thắng khi chênh lệch nằm trong vùng nhiễu đo được. Tin thực tế, chấp nhận tốn token — nhưng chỉ khi đáng.
When to useKhi nào dùng
✓ Reach for it when✓ Dùng khi
- ≥2 viable directions a mechanical metric can separate≥2 hướng khả thi mà một metric cơ học phân biệt được
- reasoning genuinely can't decide, and the choice is load-bearinglập luận thật sự không quyết được, và lựa chọn là load-bearing
- each candidate can be probed with a cheap throwaway stubmỗi ứng viên có thể probe bằng một stub rẻ, vứt-đi
✗ Won't do✗ Sẽ không làm
- bake-off a decision a minute of reasoning settles →
hs:predictbake-off một quyết định lập luận giải trong 1 phút →hs:predict - accept an LLM-scored "quality" metric — that's fake objectivitynhận metric "chất lượng" do LLM chấm — đó là giả-khách-quan
- invent a winner inside the noise band, or hide the losers' scoresbịa ra kẻ thắng trong vùng nhiễu, hay giấu điểm kẻ thua
How to run itCách chạy
Invoke it with the decision and the contenders — e.g. /hs:bakeoff cache layer --candidates redis,in-memory,sqlite --metric './bench.sh' --noise medium. Missing inputs are collected up front via one question.Gọi kèm quyết định và các ứng viên — ví dụ /hs:bakeoff lớp cache --candidates redis,in-memory,sqlite --metric './bench.sh' --noise medium. Thiếu input sẽ được hỏi gom một lần.
PreflightPreflight
bakeoff_rank.py preflight checks N∈[2,4], a safety-scan of the metric command, and the budget ceiling, plus a dry-run (one number, exit 0). Any fail → it refuses and falls back to hs:predict.bakeoff_rank.py preflight kiểm N∈[2,4], safety-scan lệnh metric, trần budget, cộng một dry-run (một số, exit 0). Thiếu bất kỳ → từ chối và lùi về hs:predict.
Fan-outToả nhánh
One isolated worktree per candidate (via hs:worktree), each holding a minimal throwaway probe that measures only the contested axis — never a full feature.Một worktree cách ly cho mỗi ứng viên (qua hs:worktree), mỗi cái chứa một probe vứt-đi tối thiểu đo chỉ trục đang tranh chấp — không phải feature đầy đủ.
MeasureĐo
Run the SAME metric on the SAME input in each worktree — trials per noise level (low 1 · medium 2 worse-of · high 3–5 median) — recording each value plus elapsed time and tokens.Chạy CÙNG metric trên CÙNG input ở mỗi worktree — số trial theo mức nhiễu (low 1 · medium 2 lấy-tệ-hơn · high 3–5 median) — ghi từng giá trị kèm thời gian và token.
RankXếp hạng
bakeoff_rank.py rank applies the noise band: exit 0 = a winner, 3 = tie within noise, 4 = insufficient trials.bakeoff_rank.py rank áp dải nhiễu: exit 0 = có kẻ thắng, 3 = hoà trong nhiễu, 4 = thiếu trial.
ReportBáo cáo
Print the full scoreboard — every candidate's score, spread, and any over-budget — losers never dropped. On a tie or insufficient trials, hand to a human; never invent a winner.In đầy đủ bảng điểm — điểm, spread, và over-budget của mọi ứng viên — không bỏ kẻ thua. Khi hoà hoặc thiếu trial, giao người; không bịa kẻ thắng.
CleanupDọn dẹp
Prune the candidate worktrees (hs:worktree remove), keep the winner's branch if useful, and return the winning direction to whoever called the bake-off.Xoá các worktree ứng viên (hs:worktree remove), giữ nhánh kẻ thắng nếu cần, và trả hướng thắng về cho người đã gọi bake-off.
Worked example: the refusal to pickVí dụ thật: từ chối chọn
Two cache designs, ~equal — it refuses to pickHai thiết kế cache, ~ngang nhau — nó từ chối chọn
Latency in ms, 3 trials each. Each design swings ±8ms run-to-run, but the gap between them is only 2ms. A human reading the table would "explain" why write-through wins; the script won't. The band widens to the measured noise (band = max(5%·rep, observed_spread)), so a 2ms gap inside 8ms of noise can't be a real win. real CLI
Độ trễ ms, 3 trial mỗi bên. Mỗi thiết kế dao động ±8ms giữa các lần, nhưng chênh lệch chỉ 2ms. Người đọc bảng sẽ "giải thích" vì sao write-through thắng; script thì không. Dải nhiễu tự nong theo nhiễu đo được (band = max(5%·rep, observed_spread)), nên gap 2ms trong 8ms nhiễu không thể là thắng thật. CLI thật
{
"direction": "lower",
"noise": "high",
"rel_band": 0.05,
"candidates": [
{
"candidate": "write-through",
"trials": [
100.0,
108.0,
104.0
],
"rep": 104.0,
"spread": 8.0,
"n": 3
},
{
"candidate": "write-back",
"trials": [
103.0,
111.0,
106.0
],
"rep": 106.0,
"spread": 8.0,
"n": 3
}
],
"ranking": [
"write-through",
"write-back"
],
"observed_spread_floor": 8.0,
"band": 8.0,
"gap": 2.0,
"verdict": "tie_within_noise",
"winner": null,
"rationale": "gap 2 <= band 8 (max of 5% relative and observed spread 8) -> tie within noise",
"schema": "artifact-bakeoff-verdict",
"run": "tie",
"actor": "user:hieubt@local",
"ts": "2026-06-15T10:42:22.758092+00:00",
"over_budget": []
}
exit: 3 (3 = tie_within_noise -> hand to human)
Exit 3 = tie_within_noise → hand to a human. Often this verdict is itself the signal: your metric doesn't discriminate. Knowing when you may not declare a winner is the thing an LLM won't do for you.Exit 3 = tie_within_noise → giao người. Thường chính verdict này là tín hiệu: metric của bạn không phân biệt được. Biết khi nào không được phép tuyên bố kẻ thắng mới là thứ LLM không tự làm cho bạn.
Gate-first — 4 conditions before a single token burnsCổng tiền-kiểm — 4 điều kiện trước khi đốt token đầu tiên
The first two are machine-checked by bakeoff_rank.py preflight (with a safety-scan reused from hs:loop); the last two are a judgment checklist you confirm. Miss any one → don't bake-off, fall back to hs:predict. A bad metric makes you pay N× cost for a number that only looks objective — the most dangerous failure of all.Hai điều đầu được máy kiểm bằng bakeoff_rank.py preflight (kèm safety-scan tái dùng từ hs:loop); hai điều cuối là checklist phán đoán bạn tự khẳng định. Thiếu bất kỳ → đừng bake-off, lùi về hs:predict. Metric tồi khiến bạn trả N lần chi phí cho một con số chỉ trông khách quan — failure nguy hiểm nhất.
{
"ok": false,
"reasons": [
"need 2..4 distinct candidates, got 1",
"metric command matches an unsafe pattern (rm -rf /, curl|sh, ...)",
"budget_seconds must be in (0, 600]"
]
}
exit: 2
Exit 2: it collects every reason at once — too few candidates, an unsafe metric command, a budget over the ceiling — so you fix them in one pass before any worktree is built.Exit 2: nó gom mọi lý do một lượt — quá ít ứng viên, lệnh metric nguy hiểm, budget vượt trần — để bạn sửa một lần trước khi dựng worktree.
When the numbers are clear, it commitsKhi số liệu rõ, nó chốt
Same metric, real separation: an indexed lookup at ~40ms against a full scan at ~95ms. Gap 55 ≫ band → a winner, exit 0. Every candidate's score, spread and trial count is reported — losers are never silently dropped — alongside the time/token each probe cost.Cùng metric, tách thật: tra cứu có index ~40ms so với quét toàn bộ ~95ms. Gap 55 ≫ band → có kẻ thắng, exit 0. Điểm, spread và số trial của MỌI ứng viên đều được báo — kẻ thua không bao giờ bị cắt lặng — kèm thời gian/token mỗi probe đã tốn.
{
"direction": "lower",
"noise": "high",
"rel_band": 0.05,
"candidates": [
{
"candidate": "sqlite-index",
"trials": [
40.0,
41.0,
40.0
],
"rep": 40.0,
"spread": 1.0,
"n": 3
},
{
"candidate": "full-scan",
"trials": [
95.0,
96.0,
94.0
],
"rep": 95.0,
"spread": 2.0,
"n": 3
}
],
"ranking": [
"sqlite-index",
"full-scan"
],
"observed_spread_floor": 2.0,
"band": 2.0,
"gap": 55.0,
"verdict": "winner",
"winner": "sqlite-index",
"rationale": "gap 55 > band 2 -> sqlite-index wins",
"schema": "artifact-bakeoff-verdict",
"run": "win",
"actor": "user:hieubt@local",
"ts": "2026-06-15T10:42:23.137241+00:00",
"over_budget": []
}
exit: 0 (0 = winner)
An escalation, not a default stepMột nhánh leo thang, không phải bước mặc định
Seven skills point here at the exact moment a linear path stalls and a metric exists — discover, plan (validate gate), research, triage, cook, problem-solving, predict. The trigger is always the same: ≥2 measurable directions, reasoning can't separate them, a cheap probe is possible. The verdict is a handoff artifact (artifact-bakeoff-verdict.json) — it blocks no stage; it just feeds the winning direction back to whoever asked.Bảy skill trỏ về đây đúng lúc đường tuyến tính tắc và có metric — discover, plan (cổng validate), research, triage, cook, problem-solving, predict. Câu kích hoạt luôn giống nhau: ≥2 hướng đo được, lập luận không tách được, probe rẻ khả thi. Verdict là handoff artifact (artifact-bakeoff-verdict.json) — không chặn stage nào; chỉ trả hướng thắng về cho người gọi.
bakeoff_rank.py refuses N∉[2,4] / an unsafe metric / an over-budget probe at preflight, and refuses to name a winner when gap ≤ band or trials fall below the noise minimum (low 1 / medium 2 / high 3). The score ledger is append-only JSONL under state/bakeoff/ with an actor and an aware-UTC timestamp on every line — re-derive any verdict, see exactly which candidate cost what. No t-tests, no p-values: at n≤5 they are pseudo-science.
bakeoff_rank.py từ chối N∉[2,4] / metric nguy hiểm / probe vượt budget ở preflight, và từ chối nêu kẻ thắng khi gap ≤ band hoặc số trial dưới mức tối thiểu theo nhiễu (low 1 / medium 2 / high 3). Sổ điểm là JSONL append-only dưới state/bakeoff/, mỗi dòng có actor và timestamp aware-UTC — kiểm lại mọi verdict, thấy đúng ứng viên nào tốn gì. Không t-test, không p-value: với n≤5 chúng là rởm-khoa-học.
FAQHỏi đáp
How is this different from hs:loop?Khác hs:loop chỗ nào?
hs:loop is the time axis — improving ONE solution over repeated iterations against a metric.bakeoff là trục so sánh — N ứng viên đo ở một thời điểm. hs:loop là trục thời gian — cải thiện MỘT giải pháp qua nhiều vòng theo một metric.Can the metric be an LLM "quality score"?Metric có thể là "điểm chất lượng" do LLM chấm?
hs:predict instead.Không — đó là giả-khách-quan. Metric phải là lệnh shell in một số và exit 0. Không có metric cơ học thì dùng hs:predict.Why does it sometimes refuse to pick a winner?Vì sao đôi khi nó từ chối chọn?
gap ≤ band (band = max(rel_band·rep, observed_spread)) or trials fall below the noise minimum. Often the tie is itself the signal: your metric doesn't discriminate the options.Khi gap ≤ band (band = max(rel_band·rep, observed_spread)) hoặc số trial dưới mức tối thiểu. Thường chính cái hoà là tín hiệu: metric của bạn không phân biệt được.Does the verdict block my pipeline?Verdict có chặn pipeline không?
artifact-bakeoff-verdict.json) is a handoff artifact, not a stage gate — it doesn't call gate_stage.py. It just feeds the winning direction back to the caller.Không. Verdict (artifact-bakeoff-verdict.json) là handoff artifact, không phải stage gate — không gọi gate_stage.py. Nó chỉ trả hướng thắng về cho người gọi.