Skip to content

docs: restructure the README around front doors, and read a binary outcome as 1 or 0 - #613

Merged
drewstone merged 7 commits into
mainfrom
docs/restructure-operator-structure
Aug 15, 2026
Merged

docs: restructure the README around front doors, and read a binary outcome as 1 or 0#613
drewstone merged 7 commits into
mainfrom
docs/restructure-operator-structure

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

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.md described selfImprove() 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.

Column Content
When to call it The situation, in the reader's words
What you give it The inputs
What you get back The result

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.

Directory When to use it
evaluate-a-change You changed a surface and must know whether it helped
plan-before-you-spend The run costs money and you must see the grid first
analyze-existing-runs The runs already happened; no agent needs to run again
sealed-experiment The result must convince someone who does not trust you
verify-without-an-answer-key The work has no held-out test suite
custom-trace-analyst A batch failed and you need cited findings
adapt-a-text-optimizer Another package owns the search, you keep the scoring

All 7 typecheck under pnpm typecheck:examples and all 7 run offline.

Fix: computeEstimand rejected a binary outcome

A registered binary outcome reaches evidence as true/false. computeEstimand threw 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 shape scripts/tb-gated-stop-ab.ts registers (value: 'passed'). computeInterval rejected it the same way.

One shared reader now gives both interpreters the same reading:

  • a boolean reads as 1 or 0, so the mean of paired differences is the risk difference;
  • a finite number passes through;
  • every other type, and a non-finite number, rejects loudly.

NaN previously passed the typeof === 'number' check and silently poisoned the mean. It no longer can.

tests/experiment/paired-binary-outcome.test.ts runs 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

  • Python install commands and version pins deleted from the README; the optimizer guide already held them. Added the release-vs-source engine note there.
  • Engine list corrected: it named AutoResearch, Meta Harness, and Best-of-N, none of which this package implements, and listed best-of twice. The real recipes are engine, sequential, adaptive-sequential, best-of, vote, omni.
  • concepts.md: the five GateDecision values 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 naming runPromptEvolution, which does not exist.
  • verify-package-exports.mjs follows the renamed quickstart heading, so the packed-build check keeps running.

Proof

Check Result
pnpm typecheck clean
pnpm typecheck:examples clean
pnpm build clean
pnpm verify:package exit 0 — compiles the README quickstart against the packed build
README TypeScript blocks 2 of 2 compile (was 2 of 10)
New examples 7 of 7 typecheck, 7 of 7 run
Relative links across README, docs, examples 0 broken
pnpm test 5257 passed, 1 failed

The single failure is tests/contract-self-improve.test.ts > threads rationale + diff + durable provenance. It is a pre-existing flake: it fails intermittently on clean origin/main too (fails run 1, passes run 2, same checkout), and it has no import path to computeEstimand. Not introduced here, not fixed here.

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
tangletools previously approved these changes Aug 15, 2026

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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
tangletools previously approved these changes Aug 15, 2026

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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
tangletools previously approved these changes Aug 15, 2026

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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

@drewstone

Copy link
Copy Markdown
Contributor Author

Local proof on head 792e789, for the audit's reference.

Check Result
pnpm typecheck clean
pnpm typecheck:examples clean
pnpm build clean
pnpm verify:package exit 0 — compiles the README quickstart against the packed build
GitHub CI on 792e789 ci success, gepa-release success
README TypeScript blocks 2 of 2 compile (was 2 of 9)
New examples 7 of 7 typecheck, 7 of 7 run offline
Relative links across README, docs, examples 0 broken
pnpm test (--maxWorkers=4) 5257 passed, 1 failed

The one failure is tests/contract-self-improve.test.ts > threads rationale + diff + durable provenance. It is a pre-existing flake, not introduced here:

  • it fails on run 1 and passes on run 2 from the same clean origin/main checkout;
  • it has no import path to computeEstimand, the only source symbol this PR changes.

Two facts worth a reviewer's eye, both found while checking the old README's claims against source:

  1. aiIdentity — the old README required this field on analysts selected by runExact(). It exists nowhere in src/, tests/, or the git history of src/. The real type is ExactExecutionComponentIdentity. The claim is dropped, not carried forward.
  2. AutoResearch, Meta Harness, and Best-of-N — the old README listed these as GEPA recipes. None is implemented here, and the same sentence listed best-of twice. The real set is engine, sequential, adaptive-sequential, best-of, vote, omni.

@drewstone

Copy link
Copy Markdown
Contributor Author

@tangletools review now

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 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.

value-audit · 20260815T100525Z

@drewstone
drewstone merged commit 4fc1263 into main Aug 15, 2026
2 checks passed
@drewstone
drewstone deleted the docs/restructure-operator-structure branch August 15, 2026 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants