Skip to content

Forward visible output policy to sandbox stream#152

Merged
shekohex merged 1 commit into
mainfrom
fix/forward-visible-output-policy
Jun 29, 2026
Merged

Forward visible output policy to sandbox stream#152
shekohex merged 1 commit into
mainfrom
fix/forward-visible-output-policy

Conversation

@shekohex

Copy link
Copy Markdown
Contributor

Summary

  • expose requireVisibleAssistantOutput on StreamSandboxPromptOptions
  • forward the option into box.streamPrompt() so sidecar visible-output enforcement can be enabled by product shells
  • add seam coverage in src/sandbox/index.test.ts

Validation

  • corepack pnpm@10.33.4 -C /home/coder/project/agent-app exec vitest run src/sandbox/index.test.ts
  • corepack pnpm@10.33.4 -C /home/coder/project/agent-app exec tsc --noEmit
  • NODE_OPTIONS='--max-old-space-size=8192' corepack pnpm@10.33.4 -C /home/coder/project/agent-app build

Review Guide

  • src/sandbox/index.ts: option is pass-through only; no default behavior change.
  • src/sandbox/index.test.ts: asserts the seam reaches the sandbox SDK call.

Release note

  • GTM can drop its package patch after a patch release containing this seam.

Refs tangle-network/gtm-agent#386

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 1 (1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 155.4s (2 bridge agents)
Total 155.4s

💰 Value — sound

Adds one optional pass-through field on the existing streamSandboxPrompt seam so product shells can enable the substrate's visible-output enforcement without patching the package; minimal, in-grain, correctly tested.

  • What it does: Exposes requireVisibleAssistantOutput?: boolean on StreamSandboxPromptOptions (src/sandbox/index.ts:1507) and conditionally forwards it into box.streamPrompt({...}) at src/sandbox/index.ts:1546-1548, using the same !== undefined ? {…} spread idiom as signal/timeoutMs immediately above. The option is pure pass-through — agent-app adds no default, no logic, no transformation; the target
  • Goals it achieves: Let product shells (the PR body names gtm-agent, which currently carries a package patch per tangle-network/gtm-agent#386) enable the substrate sidecar's require-visible-assistant-output policy through the agent-app seam instead of monkey-patching the framework. The win is removing a downstream patch and giving every agent-app consumer a typed knob for a policy the substrate already enforces.
  • Assessment: Good change on its merits. It satisfies the engine/shell rule in AGENTS.md: the capability (visible-output enforcement) lives in the ENGINE (@tangle-network/sandbox) and this shell only forwards it as a typed parameter — no domain value baked, no logic reimplemented, no product import. It is additive and non-breaking (new optional field on an existing interface, no new subpath needed). It follow
  • Better / existing approach: none — this is the right approach. I checked for a generic escape hatch (rg passthrough|streamPromptOptions|rawOptions|sdkOptions|forwardOptions in src/) and found none; every option on this seam is explicit, so a generic passthrough field would fight the grain and lose type safety / discoverability for a trivial savings. I also confirmed no existing equivalent in agent-app (rg `requireVisibleAs
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 2
  • Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content

🎯 Usefulness — sound-with-nits

A minimal, in-grain pass-through that exposes an SDK-level visible-output enforcement knob on the streaming sandbox seam, with an imminent caller (gtm-agent) already patching the package for it.

  • Integration: Reachable and correctly wired. New field on StreamSandboxPromptOptions (src/sandbox/index.ts:1507) is forwarded into box.streamPrompt via the same conditional-spread used for timeoutMs/signal (src/sandbox/index.ts:1546-1548). streamSandboxPrompt is exported through the root barrel (src/index.ts:23) and the ./sandbox subpath (package.json:96). The option type also flows to runSandboxPrompt (src/san
  • Fit with existing patterns: Matches the established pattern exactly. The codebase separates pure SDK pass-through options (sessionId, executionId, lastEventId, signal, timeoutMs) from locally-consumed options (disallowQuestions, used at src/sandbox/index.ts:1563). This PR places requireVisibleAssistantOutput in the pass-through bucket, using the identical ...(x !== undefined ? { x } : {}) guard. Visible-output enforcement
  • Real-world viability: Holds up. Pure pass-through means robustness is the SDK's responsibility; the conditional spread guarantees omitting the option changes no default behavior (the omit-path test at src/sandbox/index.test.ts:467-476 still passes unchanged). The new assertion (src/sandbox/index.test.ts:464) proves the value reaches the SDK call object. Error/concurrency paths in the generator (severed-stream detection
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 driveSandboxTurn does not forward the new option to box.prompt [integration] ``

driveSandboxTurn (src/sandbox/index.ts:1749) accepts StreamSandboxPromptOptions (so the new field is now part of its type) but its box.prompt call (src/sandbox/index.ts:1770-1776) only forwards sessionId/executionId/timeoutMs/signal — not requireVisibleAssistantOutput. A detached cron/mission caller that sets the option would have it silently ignored on the non-streaming path. Likely fine in practice (visible-output enforcement is most meaningful on a streamed turn), and out of this PR's scope,


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260629T015905Z

@tangletools

Copy link
Copy Markdown

✅ No Blockers — c89ea3f2

Review health 100/100 · Reviewer score 95/100 · Confidence 65/100 · 0 findings (none)

deepseek: Correctness 95 · Security 95 · Testing 95 · Architecture 95

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision.

No findings.


tangletools · 2026-06-29T01:59:13Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Clean — c89ea3f2

Full multi-shot audit completed 1/1 planned shots over 2 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-06-29T01:59:13Z · immutable trace

@shekohex shekohex merged commit 27b4072 into main Jun 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants