feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces - #190

Merged
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop
Jun 7, 2026
Merged

feat: eval substrate (search-bench + generate-eval) + unify the executor/driver surfaces#190
drewstone merged 7 commits into
mainfrom
feat/research-stateful-loop

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

Two threads, both landed green (tsc 0 · biome clean · 676/676 tests).

1. The eval substrate — measure provider × harness × model on fresh, non-trainable tasks

The neutral-measurement layer the RSI runtime needs (grounding) and that sells as data (docs/eval-substrate.md is the north star + measurement non-negotiables).

  • bench/src/search-bench/ — coding-harness × web-search comparison: per-arm AgentProfile builders (native / provider-MCP+native-disabled / off), deterministic oracles (exact-identifier checks, no LLM judge), a runner over the unified executor (sandbox + cli-bridge backends), and a rigorous exporter (methodology + all tasks defined + per-task matrix + paired sign-test + CSV + gist).
  • 21 web-verified discriminating tasks (tasks-fresh.ts) where GPT-4.1 fails 90% parametrically (search-correctable headroom) — generated + adversarially verified, not hand-authored.
  • bench/src/generate-eval/ — the data engine as a skill + certifier + kernel loop: an agent authors a task; the runtime certifies it (grounding gate = reference must execute+pass against the real pinned target; discrimination gate = a no-tools baseline must fail). Soundness guaranteed, production budget-bounded, exhaustion loud. skills/generate-eval/SKILL.md is portable to any agent/stack.

Honest first result (shipped as data, not marketing): on these 21 tasks, you.com is at correctness parity with the harness's native search (opencode 71/67/67, p=1.0; claude-code 65/66) and markedly more token-efficient (−36%/−61% input tokens vs opencode's page-dumping webfetch). The substrate's value is reporting where each provider wins/ties/loses, continuously.

2. Unify the executor / driver surfaces (no aliases — aggressive)

Collapsed the sprawl the survey mapped (six parallel surfaces) onto one vocabulary and one port:

  • Executor / ExecutorFactory / ExecutorResult (was LeafExecutor* — the literature-standard term; the supervision-tree "leaf" role is now a docstring).
  • createDriver / DriverDecision (was createDynamicDriver — "dynamic" distinguished it from static drivers that no longer exist); dynamic.tsdriver.ts.
  • SandboxClient (was LoopSandboxClient — no longer the loop's port name; it's the box-shaped structural contract).
  • createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) — the ONE built-in: the backend is serializable data (a profile/experiment-config/journal can name it), not an import choice. The per-backend factories are internal case-arms; the registry feeds from the same bodies; BYO agents implement Executor directly (the port stays open).
  • inlineSandboxClient(factory) — the ONE pseudo-box adapter: any non-box Executor drives runLoop without re-faking a box. The three duplicated shims (router-executor.ts, generate-eval's bridge client, search-bench's bridge POST) now share it.
  • Renamed across 241 sites / 47 files; all docs, the adoption skill, and examples propagated so no map disagrees with the code.

3. Process hygiene

CLAUDE.md decluttered to the timeless contract — a top-of-file rule (pointers, not state: no gate numbers / run ids / session status; those live in .evolve/current.json + memory/) and the code-map fixed to the unified names.

Test plan

  • pnpm run typecheck (src) + tsc --noEmit (bench): 0 errors. pnpm run lint: clean. pnpm test: 66 files / 676 tests pass.
  • search-bench + generate-eval proven live end-to-end (real sandbox + cli-bridge); see docs/eval-substrate.md.
  • Merges clean into main.

…un env passthrough
research-gate.mts: off-sandbox research-bench leaderboard (model x web-search-provider x multi-shot) over the router -- provider-pinned /v1/search + web_fetch, then answer. Deep-cleaned onto the kernel primitives (routerChatWithUsage, runPool, appendRunRecord, adapter.judge); deleted the reinvented pool/corpus/sandbox backends. 424 -> 259 lines.
experiment.ts: sandboxAgentRun gains an optional env passthrough (merged onto OPENAI_*), letting a caller pin the in-box agent search provider (TANGLE_SEARCH_DEFAULT_PROVIDER). rsi.ts forwards SEARCH / EXA_API_KEY to the box via it.
Verified: tsc clean; SimpleQA you-arm reproduces 2/2 through the cleaned worker.
…l-loop
# Conflicts:
#	bench/src/research-gate.mts
…boxClient
No aliases, hard rename across src/bench/tests (241 sites, 47 files):
- LeafExecutor → Executor, LeafExecutorFactory → ExecutorFactory,
LeafResult → ExecutorResult (the literature-standard executor vocabulary;
the supervision-tree 'leaf' role moves to the docstring)
- createDynamicDriver → createDriver, CreateDynamicDriverOptions →
CreateDriverOptions, DynamicDecision → DriverDecision ('dynamic'
distinguished it from static drivers that no longer exist)
- LoopSandboxClient → SandboxClient (no longer the loop's port name; it is
the box-shaped structural contract for the sandbox substrate: lineage,
fs artifacts, capabilities, MCP delegation, in-process clients)
- src/runtime/dynamic.ts → src/runtime/driver.ts
… + one pseudo-box adapter
Collapses per-backend executor factories into a single config-driven entrypoint;
the backend becomes serializable DATA (a profile/experiment-config/journal can
NAME it) instead of an import choice.
- createExecutor({ backend: 'router'|'bridge'|'cli'|'sandbox', …seam }) is the
ONE public built-in; routerInline/sandbox/cli become internal case-arms; the
registry (Supervisor's resolve-by-harness path) feeds from the same bodies.
- bridgeExecutor: the cli-bridge harness turn (model = harness selector,
agent_profile = the arm's native-disable/MCP) — implemented ONCE, in src/.
- inlineSandboxClient(factory): the ONE pseudo-box adapter — any non-box Executor
drives runLoop without re-faking a box. Replaces the shims each call site grew.
- generate-eval migrated onto it (deletes its bespoke bridge SandboxClient).
router-executor.ts + search-bench/bridge.ts migrate next (same pattern).
The port stays OPEN: BYO agents implement Executor and never pass through here.
…ied executor
Delete the last two pseudo-box / raw-fetch duplicates:
- router-executor.ts: a BYO Executor over runResearchShot wrapped by
inlineSandboxClient — owns only the research-shot specifics, no hand-rolled
create/streamPrompt/delete box shell.
- search-bench/bridge.ts: the cell scorer's bridge POST+usage-parse becomes a
createExecutor({backend:'bridge'}) call; it keeps only oracle scoring +
citation extraction. Same backend the loop path uses, one implementation.
- generate-eval run loop: per-round gate verdicts now logged (an exhaust says
WHY — malformed JSON vs grounding vs discrimination).
…name
- CLAUDE.md: add the top-of-file rule (pointers, not state — no gate numbers,
run ids, or session/generation status; those live in .evolve/current.json +
memory/). Replace the embedded science-state paragraph with a pointer; fix
the code-map to the unified names (driver.ts, Executor, createExecutor,
inlineSandboxClient, SandboxClient).
- Propagate the executor/driver rename across all docs, the adoption skill,
and examples so no map disagrees with the code (anti-staleness law).
@drewstone
drewstone merged commit 7bd250c into mainJun 7, 2026
1 check passed
drewstone added a commit that referenced this pull request Jun 9, 2026
…() analyst (#204)
Stops hand-rolling. Brings the Supervisor depth/breadth drivers forward (the
general agentic primitive, d5aa85a) and makes them truly canonical: the depth
STEERER is now agent-eval's observe() (makeFinding + ChatClient + the
derived_from_judge firewall), not a hand-rolled chat call. The worker runs through
the keystone (createSupervisor + Scope + Agent.act + scope.spawn shots), metered by
the conserved budget pool (equal-k by construction), journaled.
This is the loop system we built, end to end — depth (continue over one artifact,
observe()-steered) vs breadth (parallel best-of), over the live EOPS gym. The
+13.4pp branch hand-rolled its analyst; this is the first run with the REAL
analyst. Fixed the executor-rename drift (LeafExecutor→Executor etc, #190).
Smoke (n=2, deepseek-v4-pro) runs clean through the Supervisor; full n in flight.
Replaces the throwaway flat-loop eops-gate prototype for the science.
Sign up for freeto 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.

1 participant

@drewstone