docs: restructure the README around front doors, and read a binary outcome as 1 or 0 - #613
Conversation
A registered `binary` outcome reaches evidence as `true` or `false`. `computeEstimand` rejected that type, so a paired-mean-diff over a pass/fail field could not run without the caller re-encoding every row. `computeInterval` rejected it the same way. One shared reader now gives both interpreters the same reading: a boolean is 1 or 0, a finite number passes through, and every other type or a non-finite number rejects. A `NaN` outcome no longer reaches the mean.
…seal, and verify Each directory holds one runnable file and a README that answers when to use it, how to run it, and why it is built that way. Every expected output in a README is the output the file prints.
…aims The README carried 238 of 507 lines on one API family and 8 of 10 TypeScript blocks that did not compile. It now leads with one quickstart that the package verifier compiles against the packed build, then a table with one row per callable front door and a link to a runnable example for each. The Python install commands and version pins move to the optimizer guide that already held them. The engine list drops three names the package does not implement and no longer lists best-of twice. concepts.md states the five release decisions, not a ship/hold pair; its only TypeScript block now parses; and it defines the vocabulary the rest of the docs use. feature-guide.md drops a row naming a function that no longer exists.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 6afe903d
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-15T09:17:31Z
…s owned The exact-run contract lived only in the README, which named an `aiIdentity` field that exists nowhere in the source. The real type is `ExactExecutionComponentIdentity`, reduced to a snapshot that keeps id and version and replaces config with a digest.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — e647dc51
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-15T09:20:04Z
No gate in this package returns `model_ceiling` or `arch_ceiling`. Both are in the taxonomy and in the composition order, so a caller's gate can return either and every consumer must handle all five.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 5455340e
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-15T09:21:36Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 792e789d
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-15T09:23:12Z
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 792e789d
This PR was opened by the trusted drewstone account.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
This approval is provisional. It rests on the audit running. If the audit cannot run — for example the CLI bridge rejects it — this approval is dismissed rather than left standing, so an unrun check never reads as a passing one.
tangletools · auto-approval · reason: drewstone_author · 2026-08-15T09:28:27Z
|
Local proof on head
The one failure is
Two facts worth a reviewer's eye, both found while checking the old README's claims against source:
|
|
@tangletools review now |
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Coverage | 2 of 2 lenses (value, usefulness) |
| Concerns | 1 (1 low) |
| Heuristic | 0.0s |
| Duplication | 0.6s |
| Interrogation | 695.9s (2 bridge agents) |
| Total | 696.5s |
💰 Value — sound
Rewrites the README as a verified front-door index, adds 7 runnable offline examples for APIs that had none, and fixes computeEstimand/computeInterval to read boolean binary outcomes as 1/0 — all claims verified by execution.
- What it does: Three deltas. (1) README 507→190 lines: one compiling quickstart plus a 19-row 'Which Front Door' table (README.md:78-98) where each row links to a runnable example or owning doc; scripts/verify-package-exports.mjs:148 updates the quickstart-extraction regex from '## Evaluate An Agent' to '## Quickstart' so the pack-verification check keeps compiling it. (2) Seven new example directories (evaluate
- Goals it achieves: Make the README an accurate index of every callable entry point instead of a deep-dive on one API family; give surfaces with zero example coverage (/experiment seal+open, runExact, externalTextOptimizationMethod, runEquivalenceCheck/VERIFICATION_STRATEGIES, planCampaignRun, paired analyzeRuns) runnable proof; and unblock the sealed binary-outcome path — scripts/tb-gated-stop-ab.ts:353 registers va
- Assessment: Good on its merits and verified by execution: pnpm typecheck and pnpm typecheck:examples pass; all 7 examples run offline; printed outputs match their READMEs exactly, including the pinned seal digest 514cf827... in examples/sealed-experiment/README.md:30; 10/10 tests in tests/experiment/paired-binary-outcome.test.ts pass; GateDecision at src/campaign/types.ts:371 has exactly the five values conce
- Better / existing approach: none — this is the right approach. Searched for duplication before concluding: the base tree already had 17 example directories, but grepping c1b5c88 for analyzeRuns|runExact|sealExperiment|externalTextOptimizationMethod|planCampaignRun across examples/ matched only the two intake-adapter examples (customer-feedback-loop, customer-otel-traces), and both call analyzeRuns unpaired — the paired-lift
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 2
- Bridge warning: opencode/kimi-for-coding/k2p7: opencode: opencode error
🎯 Usefulness — sound
A docs/examples restructure whose one code fix (boolean outcome fields read as 1/0 in computeEstimand/computeInterval) unblocks the exact sealed-experiment shape a live script registers, is strictly tighter than the code it replaces (NaN/Infinity now reject), and is proven by a test file that mirror
- Integration: Fully reachable. readNumericOutcome (src/experiment/ast.ts:308) is called from both interpreters that read outcome fields — computeEstimand paired-mean-diff (ast.ts:346) and computeInterval cluster-bootstrap (ast.ts:433) — and through the sealed-experiment executor registered.estimate() (src/experiment/define.ts:498). The live consumer is scripts/tb-gated-stop-ab.ts, which registers kind:'binary'
- Fit with existing patterns: Fits the codebase's grain on every axis. The boolean reading is a documented semantic (risk difference), not a silent fallback: strings, null, absent fields, NaN, and Infinity all reject with a ValidationError naming the field and pair/cluster — matching the repo's fail-loud doctrine (CLAUDE.md 'No fallbacks'); notably the replaced code ACCEPTED NaN/Infinity since typeof NaN === 'number', so the n
- Real-world viability: Error paths are covered by tests, not just the happy path: rejection of string/null/NaN/Infinity/undefined outcome values with a precise message (paired-binary-outcome.test.ts:176-192), zero-diff semantics preserved when one arm never answered a pair (166-174), and boolean-read equality with hand-encoded 1/0 (160-164). The interval interpreter shares the same reading, so a cluster bootstrap over b
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🔎 Heuristic Signals
🟡 Cruft: console debug added examples/adapt-a-text-optimizer/index.ts
- console.log(
method: ${score.name})
What this audit checks
It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.
| Pass | What it asks |
|---|---|
| Heuristic | Vague title? Whitespace-only or cruft-bearing diff? (content signals only) |
| Duplication | Do added function/class names already exist elsewhere in the repo? |
| Value Audit | What does it do? What goal does it achieve? Is it good? Better architecture or already-exists? |
| Usefulness Audit | Does it integrate and fit? Will it hold up in real use and actually get used? |
Findings are concerns, not blocks — the human reviewer decides what to do with them.
What changed
The README carried 238 of its 507 lines on one API family (external text optimizers), and 8 of its 10 TypeScript blocks did not compile.
concepts.mddescribedselfImprove()as returning a ship/hold decision when the real type has five values, and its only TypeScript block was a parse error.README: 507 → 190 lines. One quickstart, then a table with one row per callable front door.
Eighteen rows, including the surfaces that had no README presence at all:
/experiment, analyst definitions, verification strategies, trace-repair, and trajectory-replay. Every row links to a runnable example or the doc that owns it.Examples: 7 new directories
Each holds one runnable file and a README that answers WHEN / HOW / WHY. Every expected output printed in a README is the output that file produces.
evaluate-a-changeplan-before-you-spendanalyze-existing-runssealed-experimentverify-without-an-answer-keycustom-trace-analystadapt-a-text-optimizerAll 7 typecheck under
pnpm typecheck:examplesand all 7 run offline.Fix:
computeEstimandrejected a binary outcomeA registered
binaryoutcome reaches evidence astrue/false.computeEstimandthrew on that type, so a paired-mean-diff over a pass/fail field could not run without the caller re-encoding every row — which is exactly the shapescripts/tb-gated-stop-ab.tsregisters (value: 'passed').computeIntervalrejected it the same way.One shared reader now gives both interpreters the same reading:
NaNpreviously passed thetypeof === 'number'check and silently poisoned the mean. It no longer can.tests/experiment/paired-binary-outcome.test.tsruns the gated-stop runner's exact spec shape end to end: seal → verify → admit → estimate → interval → decide, on boolean rows. It asserts the risk difference (9/16), that hand-encoded 1/0 rows give an identical result, that zero-diff semantics survive a missing arm, and that five bad value types reject. 10 of 10 tests fail without the fix.Docs
AutoResearch,Meta Harness, andBest-of-N, none of which this package implements, and listed best-of twice. The real recipes areengine,sequential,adaptive-sequential,best-of,vote,omni.concepts.md: the fiveGateDecisionvalues with what each one tells you to do next; three new front-door rows; a vocabulary section covering the terms the docs use and never defined (case, surface, dispatch, campaign, cell, receipt, cost ledger, provenance, train/selection/final cases, seal, estimand, funnel, certification); the judge-calibration statistics as a table instead of a 66-word sentence of unglossed symbols.feature-guide.md: dropped a row namingrunPromptEvolution, which does not exist.verify-package-exports.mjsfollows the renamed quickstart heading, so the packed-build check keeps running.Proof
pnpm typecheckpnpm typecheck:examplespnpm buildpnpm verify:packagepnpm testThe single failure is
tests/contract-self-improve.test.ts > threads rationale + diff + durable provenance. It is a pre-existing flake: it fails intermittently on cleanorigin/maintoo (fails run 1, passes run 2, same checkout), and it has no import path tocomputeEstimand. Not introduced here, not fixed here.