feat(supervise): delegate(intent) over supervise() — generic delegation verb, cost rides through (+ docs freshness fix)#355
Merged
Conversation
Add delegate(intent, opts) — the one generic delegation verb, a thin front door over supervise(). It hands the INTENT to a default authoring supervisor (router-brained, harness null, systemPrompt = supervisorInstructions()) which AUTHORS and spawns whatever worker the intent needs over the conserved-budget pool. No hardcoded coder/researcher profile; the supervisor writes its own. Returns supervise()'s SupervisedResult unchanged, so spentTotal (iterations, tokens, usd, ms) rides straight back — the cost channel delegate_code lacks. Add the delegate MCP tool (createDelegateHandler) as the agent-facing generic replacement for delegate_code/delegate_research: it routes to delegate(), takes the supervisor substrate (router/backend/deliverable) injected at server construction (like coderDelegate), and returns the delivered output WITH its spentTotal synchronously. Purely additive — delegate_code/delegate_research/composeProductionAgentProfile/ detachedSessionDelegate/coderProfile are all untouched. Reuses supervise(), the authoring skill, the conserved-budget pool, DeliverableSpec; no hand-rolled driver, spawn loop, or equal-k. Exports: delegate/DelegateOptions/defaultDelegateBudget from runtime barrel (/loops, next to supervise); the delegate tool + types from the mcp barrel. Regenerated docs/api/ for the new symbols.
…rsion pin + platform entryPoint) The no-winner variant of SupervisedResult lacked a spentTotal field even though real conserved compute is spent before a run fails — so a failed delegation reported its cost as absent (and the delegate MCP tool fabricated a zero). Add spentTotal as a required field on the no-winner variant and compute it off the same journal the winner path reads (spentFromJournal), DRY'd into one noWinner() builder over the two no-winner exit points. The delegate MCP tool now returns the real result.spentTotal on no-winner; the fabricated zeroSpend constant is removed. This is delegate()'s whole point: the cost rides back on BOTH paths. Docs freshness gate (pnpm docs:check) was red on main from #352: the canonical-api version pin read 0.70.0 while package.json is 0.70.1, and the restored ./platform export had no typedoc entryPoint. Bump the pin to 0.70.1, register src/platform/index.ts in typedoc.json, regenerate docs/api/ (adds platform.md + the new delegate symbols). Add examples/delegate/e2e-delegate-real.ts: a router-brained supervisor authors + spawns a worker (no hardcoded coder profile), the worker does real filesystem work, the deliverable gate reads disk, and result.spentTotal carries the real conserved cost on both winner and no-winner paths.
tangletools
approved these changes
Jun 22, 2026
tangletools
left a comment
Contributor
There was a problem hiding this comment.
✅ Auto-approved PR — bad18b92
Blanket team auto-approval is enabled for this reviewer service.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: blanket_auto_approve · 2026-06-22T08:19:56Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
delegate(intent, opts)— the one generic delegation verb — as a thin front door oversupervise(), plus the agent-facingdelegateMCP tool. You hand it an INTENT (the outcome you want); a default authoring supervisor (router-brained,harness: null,systemPrompt = supervisorInstructions()) AUTHORS and spawns whatever worker that intent needs over the conserved-budget pool. No hardcoded coder/researcher profile — the supervisor writes its own. It returnssupervise()'sSupervisedResultunchanged, sospentTotal(iterations / tokens / usd / ms) rides straight back — the cost channeldelegate_codelacks.Design
delegate()(src/runtime/supervise/delegate.ts): builds the default authoring-supervisor profile and callssupervise(). Reuses the conserved-budget pool, the completion oracle (DeliverableSpec), the coordination toolbox, and equal-compute accounting — no hand-rolled driver, spawn loop, or equal-k.delegateMCP tool (src/mcp/tools/delegate.ts): the generic agent-facing replacement fordelegate_code/delegate_research. The supervisor substrate (router/backend/deliverable) is injected at server construction (exactly asdelegate_codeinjects itsCoderDelegate); the agent supplies only the intent. Synchronous: returns the delivered output WITH itsspentTotal.delegate/DelegateOptions/defaultDelegateBudgetfrom the runtime barrel (/loops, next tosupervise); the delegate tool + types from the mcp barrel.Purely additive.
delegate_code/delegate_research/composeProductionAgentProfile/detachedSessionDelegate/coderProfileare all untouched.The no-winner cost fix (the binding correctness fix)
The
no-winnervariant ofSupervisedResulthad nospentTotalfield — but real conserved compute is spent before a run fails. So a failed delegation reported its cost as absent, and the delegate MCP tool fabricated a zero (spentTotal: zeroSpend). That defeats delegate()'s whole point: the caller learns the cost.spentTotal: Spendis now a required field on the no-winner variant, computed off the same journal the winner path reads (spentFromJournal), DRY'd into onenoWinner()builder over the two no-winner exit points.result.spentTotalon no-winner; the fabricatedzeroSpendconstant is removed.spentFromJournal's conserved-pool sum already captures — the right number.Cost now rides back on both the winner and no-winner paths. Covered by new unit tests in
tests/loops/delegate.test.ts,tests/mcp/delegate.test.ts, andtests/loops/supervise.test.ts(no-winnerspentTotalis well-formed and non-negative).Docs freshness fix (the red CI on the last push)
pnpm docs:checkwas red on main, pre-existing from #352, not introduced here:docs/canonical-api.mdversion pin read0.70.0whilepackage.jsonis0.70.1→ bumped../platformexport restored in feat(platform): restore ./platform export (0.70.1) #352 had no typedoc entryPoint → registeredsrc/platform/index.tsintypedoc.json, regenerateddocs/api/(addsplatform.md+ the new delegate symbols).pnpm docs:checknow passes.E2E (real router, proof the cost rides through)
examples/delegate/e2e-delegate-real.ts: a router-brained supervisor authors + spawns a worker (no hardcoded coder profile), the worker does real filesystem work via a grantedwrite_filetool, and the deliverable gate reads disk (ground truth). Run against the live Tangle router (deepseek-v4-flash):Proven live: the supervisor authored + spawned a worker (no
coderProfile); the worker did real work —out.txtcontaininghelloon disk; andresult.spentTotalcarries real conserved cost ($0.013, 35k tokens) on the no-winner path — the exact field this PR adds.The
no-winner(notwinner) outcome is asupervise()brain/completion-gate behavior, not adelegate()defect:delegate()returnssupervise()'s result unchanged. The supervisor brain node (deepseek-v4-flash) failed to settle a winner after spawning; the worker's deliverable was met on disk regardless. A stronger brain model settles a winner when the router's tool-call path is healthy (it was intermittently returning 500s on the stronger models during the run). The delegate()-scoped claim — routing + cost-passthrough — is proven.Verification
pnpm docs:check: passes