docs: disambiguate the turn/loop primitive family#247
Conversation
Six verified factual errors in AGENTS.md / README / examples, plus the
"which one do I call" table the family never had.
Corrections (each checked against the installed @tangle-network/sandbox
0.10.5 d.ts, agent-runtime 0.79.3 d.ts, and this repo's source):
- `findCompletedTurn(turnId)` -> `findCompletedTurn(turnId, { sessionId })`.
`sessionId` is required; code written from the old doc does not compile.
- `_sessionStatus` / `_sessionResult` are `@internal` SDK plumbing. The
public polling surface is `box.session(id).status()` / `.result()`.
- `box.driveTurn` (SDK >= 0.10.5) and its shell wrapper `driveSandboxTurn`
(`/sandbox`, shipped and consumed) are now the primary autonomous recipe.
The docs still taught the hand-rolled dispatch+poll the export replaced --
exactly the failure invariant 6 exists to prevent.
- The browser gateway was misattributed. `box.mintScopedToken()` +
`SessionGatewayClient` (`@tangle-network/sandbox/session-gateway`,
WebSocket) is the browser leg; `box.streamPrompt` + `lastEventId` is the
server-side SSE reconnect. A browser never calls `streamPrompt`.
- The `/runtime` module row claimed the turn-loop was still a contribute-down
candidate. It already landed: `src/runtime/loop.ts` re-exports
agent-runtime's `runToolLoop` / `streamToolLoop` verbatim.
- The two eval rows in AGENTS.md and README prescribed three different
primitives for one caller and attributed none. Every primitive now carries
its owning package.
README peer table: `agent-integrations` was `>=0.32.0`, actual `>=0.44.0`;
added the four undocumented peers (sandbox, agent-interface, agent-knowledge,
agent-profile-materialize); corrected the "required by" column (`/tangle`
does not import agent-integrations, `/knowledge-loop` does not import
agent-runtime); noted that `driveSandboxTurn` needs sandbox >= 0.10.5, above
the declared `>=0.9.7` floor.
New in AGENTS.md: "Turn execution primitives -- which one, when" -- 15 rows
across sandbox / agent-runtime / agent-app with owner, behavior, and a
one-line USE WHEN, plus an explicit note on the four-way `runLoop` collision
(`runLoop` on agent-runtime/loops is a multi-round candidate kernel, not a
turn loop; `runToolLoop`/`streamToolLoop` on the root are; agent-app's
`runAppToolLoop`/`streamAppToolLoop` are 1:1 aliases of those; and
`routerToolLoop` is a third tool loop on the same /loops subpath).
Docs-only. Nothing deleted or renamed.
tangletools
left a comment
There was a problem hiding this comment.
✅ Auto-approved drewstone PR — 293d06b8
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.
tangletools · auto-approval · reason: drewstone_author · 2026-07-24T21:42:47Z
✅ No Blockers —
|
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 2 non-blocking findings — 293d06b8
Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision.
Full immutable report for this review: trace
Summary comment for this run: full summary
tangletools · 2026-07-24T21:46:38Z · immutable trace
Docs-only. Fixes six verified factual errors and adds the "which one do I call" table the turn/loop family never had. Nothing deleted, nothing renamed — every symbol an audit called dead turned out to have a live consumer.
What was wrong (each checked against ground truth, not memory)
Verified against the installed
@tangle-network/sandbox@0.10.5and@tangle-network/agent-runtime@0.79.3.d.ts, plus this repo's own source.findCompletedTurn(turnId)findCompletedTurn(turnId, { sessionId })—sessionIdis requiredsandbox/dist/sandbox-tksuLdrT.d.ts:1474_sessionStatus/_sessionResultpoll lifecycle@internal. Public API isbox.session(id).status()/.result()sandbox-tksuLdrT.d.ts:1515,1519(@internaltags) and:1403,247,266dispatchPrompt({detach:true})+ pollbox.driveTurn()does that pass, and agent-app already ships the wrapperdriveSandboxTurnsandbox-tksuLdrT.d.ts:1501; wrappersrc/sandbox/index.ts:2177→:2201 box.driveTurn(...)streamPrompt+lastEventIdreplay"box.mintScopedToken()+SessionGatewayClient(WebSocket).streamPrompt+lastEventId= server-side SSE reconnect; a browser never calls itsandbox-tksuLdrT.d.ts:697,1513;dist/session-gateway/index.d.ts:262,334src/runtime/loop.ts:28-31isexport { runToolLoop as runAppToolLoop, streamToolLoop as streamAppToolLoop }— agent-app holds zero loop logicsrc/runtime/loop.tsGrep note:
streamPromptwas never attributed to agent-runtime anywhere in this repo — that specific claim was wrong, and the real defect is attribution-by-adjacency (the transport table sat directly above "agent-runtimestays durability-free"). Fixed by labelling owners, not by deleting a sentence that didn't exist.README peer table (checked against
package.json)@tangle-network/agent-integrationswas>=0.32.0; actual is>=0.44.0.sandbox >=0.9.7,agent-interface >=0.15.0,agent-knowledge >=1.7.0,agent-profile-materialize >=0.6.0./tangledoes not import agent-integrations (structural only) and/knowledge-loopdoes not import agent-runtime.driveSandboxTurncallsbox.driveTurn, added in sandbox 0.10.5, above the declared>=0.9.7floor. A consumer on 0.9.7–0.10.4 satisfies the peer and gets a runtimeTypeError. Documented as "pin ≥ 0.10.5 yourself"; not bumped here — a peer bump forces lockfile churn across every consuming app and deserves its own PR with deploy verification.What's new
### Turn execution primitives — which one, whenin AGENTS.md, next to the transport section: 15 rows across@tangle-network/sandbox/agent-runtime/ agent-app, each with owner, what it does, and a one-line USE WHEN —box.streamPrompt,box.driveTurn,mintScopedToken+SessionGatewayClient,streamSandboxPrompt,runSandboxPrompt,driveSandboxTurn,createBufferedTurnTap,pumpBufferedTurn,createSandboxChatProducer,createChatTurnRoutes,runDetachedTurn,runAppToolLoop/streamAppToolLoop,runToolLoop/streamToolLoop,handleChatTurn,runLoop.The
runLoopname collision, called out explicitly — it is four-way, not three:runLoop—agent-runtime/loops. Multi-round, multi-candidate kernel: a driver plans N tasks per round, they run in N sandbox boxes, outputs fold throughdecide. Not a turn loop. Not on the package root.runToolLoop/streamToolLoop—agent-runtimeroot. The in-turn tool loop.runAppToolLoop/streamAppToolLoop— agent-app/runtime. Pure aliases of (2).routerToolLoop— a third tool loop, on the same/loopssubpath as (1) (router-client-Ak2IGuXq.d.ts:177, a positional-arg function unrelated torunToolLoop(opts)).The doc gives a reading test: rounds/candidates/driver → (1); tool calls folded into one turn → (2)/(3)/(4).
CLAUDE.mdis a symlink toAGENTS.md, so one edit covers both.Deliberately NOT done
runSandboxPromptwas dead; it is on gtm-agent's live cron path (cron.ts:312→ gtmsandbox/index.ts:3198→ agent-app). The original fleet grep missed it because ripgrep skips dot-directories by default and every product keeps server code insrc/lib/.server/.runLoop. A hard rename breaks three external repos at import. The additive-alias path is a separate agent-runtime PR.runAppToolLoop/streamAppToolLoop. Four products import the current names; two others already callstreamToolLoopdirectly. Both resolve to one function, so neither spelling is a bug — the doc now says so instead of leaving it to be "fixed" opportunistically.Verification
pnpm typecheck— clean (tsc --noEmit, no output).pnpm test— 193 files passed, 3143 tests passed, 0 failed, 0 skipped (74.7s). First run showed 139 failures from an unbuiltbetter-sqlite3native binding plus 2 files needingdist/; both are worktree setup, fixed bypnpm rebuild better-sqlite3+pnpm build, not by any change here.pnpm docs:genre-run, thenagent-docs --check→docs are fresh. Generation produced no diff, which is expected: agent-docs derives from source types, and this PR touches only prose.git merge-tree --write-tree origin/main HEAD→ merges clean.