Write executable profiles through file API#150
Conversation
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 213.2s (2 bridge agents) |
| Total | 213.2s |
💰 Value — sound-with-nits
Routes workspace-relative executable profile files through the file-API batch with mode: 0o755 instead of the chunked exec path — a coherent, in-grain speedup; only nit is a duplicated executable-classification rule.
- What it does: In
writeProfileFilesToBox(src/sandbox/index.ts), removes the executable/bin-dir exclusion fromfileApiTarget()so workspace-relative executables are no longer forced onto the exec fallback. Adds aprofileFileMode()helper that returns0o755whenmount.executableis set OR the path matchesPROFILE_BIN_DIR_RE(abin/dir), elseundefined. The file-API batch payload (viaFileApi) no - Goals it achieves: Move the common case of reused executable profile files (e.g.
skills/run.sh,bin/tool) off the expensive transport. The exec path runs at 50/min with hand-rolled base64 chunking under a ~4 KiB proxy cap, multi-step mkdir/chunks/decode/mv/chmod; the file-API batch runs at 300/min, whole-file, auto-mkdir, mode-aware, with SDK-owned pacing+retry. Fewer exec round-trips during provisioning = faste - Assessment: Good change, in the grain of the existing two-path design. It extends the existing batch-vs-fallback partition by adding one optional field to the batch payload rather than introducing new machinery. The mode decision reuses the SAME predicate (
mount.executable ?? PROFILE_BIN_DIR_RE.test(mount.path)) and SAME constant the exec path already uses, so semantics stay consistent. The capability guard - Better / existing approach: No materially better architecture — this is the right spot and the right seam (extend the existing batch payload, keep the fallback). One small reuse opportunity exists: the codebase has no shared
isExecutableMount(mount)helper, and the 'is this mount executable' rule is now expressed twice — inprofileFileMode(src/sandbox/index.ts:756) and inline in the exec path (src/sandbox/index.ts:841-8 - 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
Routes executable workspace-relative profile files through the existing file-API batch path with mode: 0o755, preserving the exec fallback for unsupported paths; directly wired into the hot provisioning paths and covered by regression tests.
- Integration:
writeProfileFilesToBoxis called fromwriteDeferredFilesWithRuntimeAuthRefresh(src/sandbox/index.ts:1165,1172) andensureWorkspaceSandbox(src/sandbox/index.ts:1394), so every new/reused/resumed box that defers profile files exercises the new behavior. It is not dead surface. - Fit with existing patterns: It extends the established file-API-vs-exec partition already implemented in the same function (
fileApiTarget,box.fs.writeMany, exec fallback). The eligibility rules (workspace-relative, no../.sidecar, no bare~) and executable detection (PROFILE_BIN_DIR_RE,mount.executable) are reused from the existing exec path, so it does not compete with an established pattern. - Real-world viability: It holds up: capability-guarded for SDKs without
writeMany(src/sandbox/index.ts:775), preserves exec fallback for absolute/bare-~/../.sidecar paths, passespaceMs/maxRetriesthrough to the SDK, and fails loud with cause preserved for the auth-refresh wrapper. Tests cover mixed-corpus partitioning, reused executable writes, SDK rejection, and the no-writeManyfallback. - Model: opencode/kimi-for-coding/k2p7
- Bridge attempts: 2
- Bridge warning: opencode/zai-coding-plan/glm-5.2: bridge stream ended without value-audit content
💰 Value Audit
🟡 Executable-classification rule duplicated between file-API and exec paths [maintenance] ``
The predicate
mount.executable ?? PROFILE_BIN_DIR_RE.test(mount.path)now appears in the newprofileFileMode(src/sandbox/index.ts:756) AND inline in the exec fallback (src/sandbox/index.ts:841-842 asconst isBin = PROFILE_BIN_DIR_RE.test(path); const executable = mount.executable ?? isBin). Both must agree on what 'executable' means or the two transports will apply different policies. Extract a singleisExecutableMount(mount): boolean(e.g. nearPROFILE_BIN_DIR_REat :553) and have `p
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.
❌ Needs Work —
|
| opencode-kimi | glm | deepseek | aggregate | |
|---|---|---|---|---|
| Readiness | 60 | 0 | 67 | 0 |
| Confidence | 65 | 65 | 65 | 65 |
| Correctness | 60 | 0 | 67 | 0 |
| Security | 60 | 0 | 67 | 0 |
| Testing | 60 | 0 | 67 | 0 |
| Architecture | 60 | 0 | 67 | 0 |
Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision.
Blocking
🟣 CRITICAL Executable bit is silently lost: SDK writeMany is not mode-aware in any shipped version — src/sandbox/index.ts
Lines 755-757 (profileFileMode) + 781-787 (push with mode) + 796 (box.fs.writeMany(viaFileApi, ...)). The PR removes the
if (mount.executable ?? PROFILE_BIN_DIR_RE.test(mount.path)) return nullguard from fileApiTarget, so executable mounts and bin-dir mounts now route to the file API instead of the exec path. It attachesmode: 0o755to each entry. But @tangle-network/sandbox's WriteManyFile interface is{ path: string; content: string }only (verified in 0.1.2, 0.3.0, 0.4.4, 0.8.2, 0.9.0, 0.9.1, 0.9.2, 0.9.3) and the implementation isasync writeMany(files){ ... await this.write(file.path, file.content) }-> POST /files/write body{path, content}(sandbox-j
🔴 HIGH New tests are tautological: they assert call-arg shape against a mock, not that the file is executable — src/sandbox/index.test.ts
Lines 1843-1877 ('batches executable and bin-dir files with executable mode, no exec') and 1913-1927 ('rewrites reused executable profile files via writeMany'). dualBox() installs
writeMany = vi.fn().mockResolvedValue(undefined)(line 1815) — a no-op that records args. The assertionsexpect(writeMany.mock.calls[0]![0]).toEqual([{ path, content, mode: 0o755 }])only prove the producer putmodein the call args; they prove nothing about whether the resulting file is executable, because the mock never sets any mode. The test named 'kee
🔴 HIGH Executable files routed to writeMany lose the executable bit — src/sandbox/index.ts
Lines 755-787 now send executable and bin-dir mounts through box.fs.writeMany with mode: 0o755. The SDK's WriteManyFile type (node_modules/@tangle-network/sandbox/dist/sandbox-BaK5AyL2.d.ts:3674-3679) only declares path and content, and its JSDoc explicitly states '(The file-write API cannot set the executable bit.)'. The latest 0.9.3 SDK implementation also forwards only {path, content} to /files/write. Consequently, skills/run.sh, bin/tool, etc. will be written without +x and will fail to execute. Keep executable/bin-dir mounts on the exec path until the SDK actually supports mode, or bump peer/dev deps to a version with WriteManyFile.mode and verify with a real int
🔴 HIGH TypeScript cannot catch the bug: local element type widens past the SDK's WriteManyFile — src/sandbox/index.ts
Line 776 declares
const viaFileApi: { path: string; content: string; mode?: number }[] = []then passes it tobox.fs.writeMany(viaFileApi, ...)at line 796. The SDK's signature iswriteMany(files: WriteManyFile[], options?)where WriteManyFile has no mode. TS excess-property checks only fire on fresh object literals, not on values typed via a wider local variable, so this assigns cleanly and typecheck is green. The local type asserts a contract the SDK does not provide. Fix: type viaFileApi as WriteManyFile[] (import the type from @tangle-network/san
🔴 HIGH writeMany mode field unverified against installed SDK type contract — src/sandbox/index.ts
The PR moves executable and bin-dir profile files from the exec path (chmod +x) to
box.fs.writeManywithmode: 0o755. However, the installed@tangle-network/sandbox@0.9.0WriteManyFileinterface (sandbox-BaK5AyL2.d.ts:3674-3678) declares only{path:string; content:string}— nomodefield. The comment at line 735-737 was updated to call the file API 'mode-aware', but the SDK type contract disagrees at the installed version. If the runtime ignores the extramodefield, executable profile files (skills/run.sh, bin/* tools) would be written without +x, silently breaking any script/tool that depends on execute permission. The PR does not bump the sandbox depe
Other
🟠 MEDIUM Mock-only tests green-light SDK capability that does not exist — src/sandbox/index.test.ts
Tests at lines 1843-1927 assert that writeMany is called with mode: 0o755, but the mock does not model SDK behavior. They therefore pass even though the real SDK ignores mode. Add an integration-level assertion that the written file is actually executable (e.g. stat returns 0o100755) before relying on the file API for executables.
🟠 MEDIUM Capability guard checks writeMany existence, not mode support; no SDK version gate — src/sandbox/index.ts
Line 775:
const fileApiAvailable = typeof box.fs?.writeMany === 'function'. This was correct before the PR (writeMany existed, mode wasn't needed). Now that the code depends on mode support, the guard no longer matches the contract: writeMany is present from 0.9.0 onward but is NOT mode-aware in any version. There is no peer-dep bump in package.json (still ^0.9.0) and no runtime probe. So a consumer resolving to 0.9.0 silently loses executable semantics. Fix: add a capability probe (e.g., feature-detect by reading box.fs.writeMany.length or a version constant the SDK exports) and fall back to exec path for executable mounts when mode support is absent.
🟡 LOW Comment at lines 735-742 and 767-772 is factually wrong about the SDK — src/sandbox/index.ts
Both comment blocks now describe
box.fs.writeManyas 'mode-aware' and 'cannot set the executable bit' has been removed from the rationale. Given no shipped SDK version supports mode on writeMany, these comments document a capability that does not exist and will mislead future readers and other agents. Revert the comment to reflect that executables stay on exec because the file API has no mode setter, or fix the SDK first.
🟡 LOW profileFileMode ?? precedence readable but fragile — src/sandbox/index.ts
Line 756:
mount.executable ?? PROFILE_BIN_DIR_RE.test(mount.path) ? 0o755 : undefined— verified correct via live evaluation (both ?? nullish coalescing and ternary interact as intended:(executable ?? binCheck) ? 0o755 : undefined). However, without parentheses, a future reader or automatic refactor could misinterpret precedence. No behavioral bug, purely a maintainability concern.
tangletools · 2026-06-27T11:16:53Z · trace
tangletools
left a comment
There was a problem hiding this comment.
❌ 5 Blocking Findings — b9cefce3
Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | 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-27T11:16:53Z · immutable trace
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 177.3s (2 bridge agents) |
| Total | 177.3s |
💰 Value — sound
Routes workspace-relative executable profile files through box.fs.writeMany() with mode: 0o755, keeping exec only for unsupported paths or SDKs without mode support; a coherent next step that passes tests, typecheck, and build.
- What it does: When
box.fs.writeManyadvertises mode support viabox.fs.supportsWriteMode,writeProfileFilesToBoxnow batches workspace-relative executable files (explicitexecutable: trueor paths matchingbin//sbin/) through the file API withmode: 0o755instead of the chunked base64/exec path. Absolute paths, bare~/~user,../.sidecarsegments, and SDKs lacking mode support still fall - Goals it achieves: Cuts exec-quota use and provisioning time for executable profile corpora (reused skills, tools in
bin/), removes the fragility of base64-chunked shell writes for the common case, and preserves safe behavior on older or limited SDKs. - Assessment: Good change. It extends the existing file-API batch path naturally (see git log
feat(sandbox): adopt box.fs.writeMany… #137,refactor(sandbox): dedupe the profile-write retry loop… #135). The capability guard is necessary because@tangle-network/sandboxis a>=0.9.0peer dependency and the installed 0.9.0 SDK does not yet exposesupportsWriteModeor filemode. Tests cover the new execu - Better / existing approach: none — this is the right approach. I searched the repo for existing
writeMany/supportsWriteMode/capability-detection patterns (grep) and inspected@tangle-network/sandbox@0.9.0types; no existing helper handles this. Version-based detection would be more fragile than the explicit capability flag. The runtime cast at src/sandbox/index.ts:764 is the minimal way to bridge the peer-dep compatibi - Model: opencode/kimi-for-coding/k2p7
- Bridge attempts: 1
🎯 Usefulness — sound-with-nits
Sound optimization: routes executable profile files onto the fast file-API path with mode 0o755 when the SDK supports it, with a proven exec fallback; the only wrinkle is a forward-declared capability flag read through a cast.
- Integration: Reachable on both real provisioning paths: new-box create (src/sandbox/index.ts:1404) and reuse/resume with auth-refresh (src/sandbox/index.ts:1175 and :1182, via materializeDeferredFilesForExistingBox at :922). The
modepayload is consumed bybox.fs.writeMany(index.ts:807), which is the same transport the codebase already uses for the non-executable corpus. The new gate is `box.fs.supportsWr - Fit with existing patterns: Fits the established transport-partition design in writeProfileFilesToBox (file-API batch vs chunked exec). The one divergence: the codebase's existing capability probe is duck-typing on the callable method (
typeof box.fs?.writeMany === 'function', index.ts:784), whereassupportsWriteModeis a separately-advertised boolean reached through a cast (index.ts:764) — so one function now holds two d - Real-world viability: Holds up on the realistic paths. The load-bearing invariant — 'never silently drop the executable bit' — is preserved: executable files only take writeMany when mode-aware (index.ts:792), and when they do
mode:0o755is attached (index.ts:759-760); mode-unaware SDKs route to exec with explicit chmod. Mixed corpus (some workspace-relative executable + absolute/unsafe) correctly splits between writ - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 Forward-declared capability flag read through a cast; two detection idioms in one function [ergonomics] ``
The new
supportsWriteModecontract is consumer-invented and applied viabox.fs as (SandboxInstance['fs'] & { supportsWriteMode?: boolean })(src/sandbox/index.ts:764). The installed SDK (0.9.0) does not declare it, and the PR depends on an unreleased SDK release shipping mode support under this exact name/mechanism. If the SDK advertises the capability differently (a version bump, a typedcapabilitiesmap, or silently acceptingmode), executables will silently stay on exec and this PR's
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.
❌ Needs Work —
|
| opencode-kimi | glm | deepseek | aggregate | |
|---|---|---|---|---|
| Readiness | 82 | 32 | 89 | 32 |
| Confidence | 65 | 65 | 65 | 65 |
| Correctness | 82 | 32 | 89 | 32 |
| Security | 82 | 32 | 89 | 32 |
| Testing | 82 | 32 | 89 | 32 |
| Architecture | 82 | 32 | 89 | 32 |
Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision.
Blocking
🔴 HIGH Capability probe box.fs.supportsWriteMode checks a field the SDK does not declare; executable-batching path is dead code in production — src/sandbox/index.ts
fileApiSupportsMode() (line 763-766) reads
box.fs.supportsWriteMode, but the pinned @tangle-network/sandbox@0.9.0FileSysteminterface declares no such member (verified in dist .d.ts for 0.9.0-0.9.3; also absent at runtime). SomodeAwareFileApiis always false against the real SDK, and the new branchif (fileApiPath !== null && (!executable || modeAwareFileApi))(line 792) routes every executable to viaExec exactly as before — the entire optimization the PR introduces ('batches executable and bin-dir files ... no exec') cannot fire in producti
🔴 HIGH mode: 0o755 passed to writeMany is silently dropped by the SDK — if the gate ever opens, executable scripts land without +x — src/sandbox/index.ts
viaFileApi entries include
...(mode !== undefined ? { mode } : {})(line 797) and are passed tobox.fs.writeMany(viaFileApi, ...)(line 807). The SDKWriteManyFiletype is{path; content}and the runtimewriteMany(verified in sandbox-joKtQ5y3.js) destructures onlyfile.path/file.content, forwarding{path, content}to POST /files/write —modeis ignored with no error. TypeScript does not catch this because the spread-built object bypasses excess-property checks and{path; content; mode?}is structurally assignable to{path; content}.
Other
🟠 MEDIUM Tests assert a fictional SDK contract; one previously-correct test was rewritten to encode the false behavior — src/sandbox/index.test.ts
dualBox() (line 1817) sets
fs: { supportsWriteMode: true, writeMany }, a combination that cannot occur against any shipped @tangle-network/sandbox version. 'batches executable and bin-dir files with executable mode, no exec' (line 1843) and 'rewrites reused executable profile files via writeMany without bash/base64 exec' (line 1927) assertwriteManyreceivesmode: 0o755andexecis not called — behavior the real S
🟠 MEDIUM Mode capability signal is not in current SDK contract — src/sandbox/index.ts
The installed @tangle-network/sandbox@0.9.0 WriteManyFile interface has only {path, content} and its JSDoc explicitly says the file-write API cannot set the executable bit (node_modules/@tangle-network/sandbox/dist/sandbox-BaK5AyL2.d.ts:3674-3717). The supportsWriteMode property is also not present on the FileSystem interface. The gating means current SDKs correctly fall back to exec, so there is no runtime regression, but the feature is dormant and assumes a future SDK will introduce exactly this property. If the SDK uses a different capability signal (e.g., version check, separate method, or different property name), this code will need another update before executable files can use the file API.
🟡 LOW Module docstring rewritten to claim writeMany is 'mode-aware', contradicting the SDK's own documentation — src/sandbox/index.ts
The comment block at lines 734-742 now describes
box.fs.writeManyas 'mode-aware' and lists 'SDKs without mode support keep executable files on exec' as a capability tier. The @tangle-network/sandbox WriteManyFile docstring states verbatim '(The file-write API cannot set the executable bit.)' and the runtime confirms it. This comment will mislead future readers into believing a feature exists. Fix: restore an accurate comment ('the file API cannot set the executable bit, so executables stay on exec') or, if a mode-supporting SDK is imminent, land this comment in the same PR that bumps the peerDep.
🟡 LOW profileFileMode: 0 as a false-positive sentinel not an issue here but worth noting — src/sandbox/index.ts
Line 759-761:
profileFileModereturns0o755orundefined. The spread at line 797 usesmode !== undefinedrather than truthiness — correct. If a future change returned0(no-perms mode), it would still be spread correctly since0 !== undefinedis true. Non-issue for this PR.
🟡 LOW viaFileApi entries carry an extra mode property outside SDK type — src/sandbox/index.ts
At line 786 the viaFileApi items are typed {path, content, mode?: number} and passed to box.fs.writeMany, which expects WriteManyFile[] ({path, content}). TypeScript structural typing accepts the extra property, and the property is only included when modeAwareFileApi is true, but the mismatch with the current SDK type means the code is relying on runtime tolerance rather than a typed contract.
🟡 LOW viaFileApi type widened to include optional mode — downstream consumers should type-check — src/sandbox/index.ts
Line 786:
viaFileApichanged from{ path: string; content: string }[]to{ path: string; content: string; mode?: number }[]. This is an internal local variable, so no API surface change. However, if any caller was pattern-matching on the old shape (unlikely since it's scoped to the function), they'd need updating. No issue in practice — the array is only passed tobox.fs.writeMany.
tangletools · 2026-06-27T11:40:30Z · trace
tangletools
left a comment
There was a problem hiding this comment.
❌ 2 Blocking Findings — 391f8d9e
Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 1/1 planned shots over 2 changed files. Global verifier still owns final merge decision. | 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-27T11:40:30Z · immutable trace
tangletools
left a comment
There was a problem hiding this comment.
🟡 Value Audit — sound-with-nits
| Verdict | sound-with-nits |
| Concerns | 1 (1 weak-concern) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 198.9s (2 bridge agents) |
| Total | 198.9s |
💰 Value — sound
Routes workspace-relative executable profile files through the SDK's file API (box.fs.writeMany) with mode: 0o755, retiring the slow exec/bash/base64 path for them while keeping exec only for unsupported targets and older SDKs.
- What it does: When
box.fs.writeManysupports file modes,writeProfileFilesToBoxnow batches inline profile files regardless of executable bit: it setsmode: 0o755for explicitexecutable: truemounts andbin/paths, otherwise writes them without mode. Paths that are absolute, bare~/~user, or contain../.sidecarstill fall back to the terminal-exec path, as do older SDKs that lack `supportsWri - Goals it achieves: Speed up and simplify profile provisioning for the common case of workspace-relative executables (skills scripts, bin tools) by using the faster FILES-rate batch API instead of the lower-rate, chunked exec path; avoid bash/base64/chmod overhead for reused executable files; and preserve correct executable permissions now that the sandbox SDK supports file modes.
- Assessment: Good. The change is coherent with the codebase's layering: it extends the existing file-API batch path, reuses the extracted
isExecutableProfileFilehelper in both branches, keeps fail-loud behavior, and adds regression tests for both the new mode-aware batch and the unsupported-path fallback. It matches the documented follow-up from the originalwriteManyadoption commit (#137) which noted th - Better / existing approach: none — this is the right approach. The previous commit (#137) explicitly anticipated this follow-up, and the implementation correctly capability-guards against older SDKs at runtime despite the peer-dependency bump, because peer dependencies are warnings, not runtime guarantees. I searched for existing file-mode or capability-detection utilities (
supportsWriteMode,0o755,capabilities) and f - Model: opencode/kimi-for-coding/k2p7
- Bridge attempts: 1
🎯 Usefulness — sound-with-nits
Correct, capability-gated optimization that routes relative executable profile files through the batched file API with mode 0o755; well-fit to the existing transport-partitioning pattern, but its real-world benefit hinges on a caller that mounts executables at workspace-relative paths, which the fra
- Integration: writeProfileFilesToBox is the deferred-file writer on the hot provisioning path (callers at src/sandbox/index.ts:1176, 1183, 1405 via splitDeferredProfileFiles + ensureWorkspaceSandbox). The new branch is reached whenever box.fs.writeMany exists AND supportsWriteMode is true AND a mount is both workspace-relative and executable. The capability is read by a forward-compat cast (index.ts:763-766) co
- Fit with existing patterns: Fits the established grain precisely. The module already partitions mounts into a file-API batch vs. a chunked-exec path based on fileApiTarget eligibility; this PR only widens the file-API side to include executable files when the SDK advertises mode support, and extracts isExecutableProfileFile/profileFileMode/fileApiSupportsMode helpers that the exec branch and file-API branch now share (index.
- Real-world viability: Degrades safely on every unsupported axis: no writeMany, no supportsWriteMode, absolute paths, bare ~, and unsafe .. segments all fall back to the existing base64/exec writer. Error semantics are preserved (the writeMany failure still wraps cause so the runtime-auth-refresh 401 detector recurses it, index.ts:807-811). The happy path and all fallbacks are covered by the test corpus. The one real-wo
- Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
🎯 Usefulness Audit
🟡 Framework's own executable-tool builder emits absolute paths, so the headline benefit bypasses the built-in tool flow [problem-fit] ``
The only producer of executable mounts in this repo is buildSandboxToolFileMounts (src/sandbox/index.ts:429-440), and normalizeSandboxToolDir (index.ts:403) forces an absolute path like /home/agent/tools//bin/ (confirmed index.test.ts:1989, and the release note's GTM example). fileApiTarget returns null for absolute paths (index.ts:747), so every built-in executable tool stays on the exec path regardless of supportsWriteMode. The new mode-aware file-API path therefore only fires for p
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.
✅ No Blockers —
|
| opencode-kimi | glm | deepseek | aggregate | |
|---|---|---|---|---|
| Readiness | 72 | 79 | 92 | 72 |
| Confidence | 70 | 70 | 70 | 70 |
| Correctness | 72 | 79 | 92 | 72 |
| Security | 72 | 79 | 92 | 72 |
| Testing | 72 | 79 | 92 | 72 |
| Architecture | 72 | 79 | 92 | 72 |
Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM devDependency and lockfile lag behind peerDependency sandbox minimum — package.json
peerDependencies at line 371 now requires
"@tangle-network/sandbox": ">=0.9.4", but devDependencies at line 339 still declares"@tangle-network/sandbox": "^0.9.0". The lockfile (pnpm-lock.yaml) still resolves@tangle-network/sandbox@0.9.0for the dev dependency. This means the repository is developed and tested against a version below the new peer floor, so the >=0.9.4 requirement is unverified. Fix: bump the devDependency to"^0.9.4"and regenerate the lockfile so CI exercises the declared minimum.
🟠 MEDIUM devDependency floor (^0.9.0) and lockfile (0.9.0) below new peerDependency floor (>=0.9.4) — package.json
Line 371 raises the peerDependency
@tangle-network/sandboxto>=0.9.4, justified by src/sandbox/index.ts:783-784 (code now relies onsupportsWriteMode/file-mode forwarding introduced in 0.9.4). But line 339 keeps devDependencies at^0.9.0, and pnpm-lock.yaml:32 pinsversion: 0.9.0. Net effect: this repo's CI/dev install resolves sandbox 0.9.0, which violates the new peer floor this PR declares, so the new mode-aware file-API path added in commits b9cefce/391f8d9 is never validated against a real SDK — only against the vi.mock at src/sandbox/index.test.ts:15. Bec
🟠 MEDIUM Local SDK version does not match new capability requirement — src/sandbox/index.ts
fileApiSupportsMode (src/sandbox/index.ts:763-766) gates executable file writes on box.fs.supportsWriteMode, a flag added in @tangle-network/sandbox 0.9.4. The PR correctly raised the peerDependency floor to >=0.9.4 (package.json:371), but left the devDependency at ^0.9.0 (package.json:339) and the lockfile still resolves 0.9.0. The installed SDK's FileSystem/WriteManyFile types have no supportsWriteMode and no mode field, so local typecheck/tests run against a SDK that cannot exercise the new mode-aware path. This masks real integration issues if the 0.9.4 WriteManyFile shape differs from the mocks. Fix: bump the devDependency to ^0.9.4 and regenerate pnpm-lock.yaml.
🟡 LOW devDependency out of sync with peerDependency bump — package.json
peerDependencies bumps @tangle-network/sandbox >=0.9.0 → >=0.9.4 (line 371), but devDependencies (line 339) remains at ^0.9.0. The range ^0.9.0 resolves to >=0.9.0 <0.10.0, which includes 0.9.4, so a fresh install picks up a compatible version. However, the code casts around
supportsWriteModeon SandboxInstance['fs'] (src/sandbox/index.ts:764) because the installed dev types don't declare it, confirming the installed devDependency predates the API. Bump devDependencies [line 339](https://github.com/tangle-network/agent-app/blob/7e03377c68c5e2b855148179394ff15e97d089f5/p
🟡 LOW Missing test for non-executable files on non-mode-aware writeMany — src/sandbox/index.test.ts
The new routing condition (!executable || modeAwareFileApi) at src/sandbox/index.ts:793 has no test for the case where writeMany exists but is NOT mode-aware and the mount is non-executable. The only test with fs: { writeMany } and no supportsWriteMode uses an executable mount ('skills/run.sh') and asserts it falls back to exec (src/sandbox/index.test.ts:1861-1873). A test with fs: { writeMany } and a non-executable relative file would verify that non-executable mounts still batch through writeMany on older SDKs.
🟡 LOW dualBox helper hardcodes supportsWriteMode:true with no override seam — src/sandbox/index.test.ts
The dualBox helper (line 1811-1818) fixes supportsWriteMode:true and its
overparam only allows overriding writeMany/exec. The negative case (line 1861-1873) correctly builds a separate box without the flag, so coverage exists, but the asymmetric shape means the partition/mixed tests cannot be re-run in mode-unaware mode without rewriting the helper. Minor maintainability nit only — no behavioral gap because=== truemakes absence and explicit-false equivalent.
🟡 LOW supportsWriteMode is a forward-looking cast, not an SDK-typed contract — src/sandbox/index.ts
fileApiSupportsMode (line 763-766) casts box.fs to
SandboxInstance['fs'] & { supportsWriteMode?: boolean }because the currently-installed SDK type (lockfile pins @tangle-network/sandbox@0.9.0) does not declare this property. The PR's package.json raises the peer to >=0.9.4 (per the code comment at line 783-784), but nothing in these two files proves 0.9.4 actually exports supportsWriteMode or honors amodefield on writeMany inputs. Impact: if the published 0.9.4 does not expose supportsWriteMode===true, executables silently stay on exec for
tangletools · 2026-06-27T12:05:47Z · trace
Superseded by re-review — no blocking findings on latest commit.
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 7 non-blocking findings — 7e03377c
Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision. | 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-06-27T12:05:47Z · immutable trace
|
ADC #2781 is merged, but @tangle-network/sandbox@0.9.4 is not published yet (npm latest is 0.9.3). This PR now declares peer @tangle-network/sandbox >=0.9.4 and keeps runtime fallback for older SDKs. I intentionally did not bump devDependency/lockfile to ^0.9.4 yet because install would fail until the SDK release exists. Next step after SDK publish: bump devDependency + lockfile to 0.9.4 and rerun CI before agent-app release. |
tangletools
left a comment
There was a problem hiding this comment.
✅ Refreshed approval after new commits — 8016610d
A previous trusted approval on this PR was invalidated by new commits.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.
tangletools · auto-approval · reason: stale_approval_refresh · 2026-06-27T13:04:50Z
tangletools
left a comment
There was a problem hiding this comment.
🟢 Value Audit — sound
| Verdict | sound |
| Concerns | 0 (none) |
| Heuristic | 0.0s |
| Duplication | 0.0s |
| Interrogation | 190.6s (2 bridge agents) |
| Total | 190.6s |
💰 Value — sound
Routes workspace-relative executable profile files (explicit executable or bin//sbin/ paths) through box.fs.writeMany with mode: 0o755, keeping the exec fallback only for absolute/unsafe paths and SDKs without mode support — a clean extension of the existing file-API batch path.
- What it does: Updates
writeProfileFilesToBoxinsrc/sandbox/index.tsso that executable inline mounts are no longer forced onto the slow chunkedbox.execbash/base64 path. Instead, when the path is workspace-relative and the SDK advertisessupportsWriteMode, it batches them throughbox.fs.writeManywithmode: 0o755. Absolute paths, bare~/~user,..or.sidecarsegments, and SDKs lacking mode - Goals it achieves: Faster, more reliable sandbox provisioning when profiles contain scripts/tools/skills by using the higher-rate file API (300/min vs exec 50/min) for executables. Removes the brittle base64-chunking exec dance for files that can be written directly. Preserves correct behavior for older SDKs and unsupported paths via runtime capability gating. Adds regression coverage showing reused executable profi
- Assessment: Good change, built in the grain of the codebase. It extends the existing
writeManybatching introduced in prior PRs rather than adding a parallel path. ExtractingisExecutableProfileFileremoves the duplicatedmount.executable ?? PROFILE_BIN_DIR_RE.test(...)logic between the file-API and exec paths. The capability guard (fileApiSupportsMode) is the right shape for backward compatibility. - Better / existing approach: none — this is the right approach. The layering matches the repo's engine/shell rule: file-write
modeis a generic SDK engine capability, while deciding which profile mounts are executable (theexecutableflag plus thebin//sbin/regex) is app-shell logic. Searchedsrc/sandbox/index.ts,src/sandbox/index.test.ts,src/skills/index.ts, andsrc/profile/index.ts; no existing equivalent - Model: opencode/kimi-for-coding/k2p7
- Bridge attempts: 1
🎯 Usefulness — sound
Extends the already-adopted box.fs.writeMany batch path to route workspace-relative executable profile files with mode: 0o755, capability-guarded so old SDKs silently keep executables on the exec path — coherent, in-grain, no existing equivalent to dedup against.
- Integration:
writeProfileFilesToBoxis the single deferred-profile materializer and is reached from three real production call sites: new-box provisioning (src/sandbox/index.ts:1405) and the runtime-auth-refresh write/retry pair (src/sandbox/index.ts:1176, 1183) insideensureWorkspaceSandbox. The new routing is exercised on every workspace sandbox boot that has deferred inline executable/bin mounts, so it - Fit with existing patterns: Fits the established pattern exactly: this PR is a continuation of the file-API transport adoption (the existing
viaFileApi/viaExecpartition at lines 787-802), not a competing mechanism. It narrows the exec fallback to its legitimate cases (absolute, bare-~, unsafe../.sidecar, and now also SDKs lackingsupportsWriteMode), which is the same grain as the priorfileApiTargeteligibili - Real-world viability: Holds up under the realistic cases. (1) Old SDK installed:
supportsWriteModeis undefined → executables route to exec unchanged, non-executables still batch via writeMany; verified the installed SDK (0.9.0)WriteManyFiletype is{path, content}with nomode(node_modules/.../sandbox-BaK5AyL2.d.ts:3674-3679), and the local array is structurally assignable since the extramode?is a subtyp - Model: opencode/zai-coding-plan/glm-5.2
- Bridge attempts: 1
No concerns — sound change, no better or existing approach found. ✅
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.
✅ No Blockers —
|
| opencode-kimi | glm | deepseek | aggregate | |
|---|---|---|---|---|
| Readiness | 85 | 80 | 89 | 80 |
| Confidence | 75 | 75 | 75 | 75 |
| Correctness | 85 | 80 | 89 | 80 |
| Security | 85 | 80 | 89 | 80 |
| Testing | 85 | 80 | 89 | 80 |
| Architecture | 85 | 80 | 89 | 80 |
Full multi-shot audit completed 3/3 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 4 changed files. Global verifier still owns final merge decision.
🟠 MEDIUM Duplicate @tangle-network/agent-interface versions in resolved tree — pnpm-lock.yaml
Lines 1250/1253/4010 show two active copies of the shared interface package: @tangle-network/sandbox@0.9.4 resolves @tangle-network/agent-interface to 0.13.0, while @tangle-network/agent-core@0.3.4, @tangle-network/agent-runtime@0.76.0, and @tangle-network/sandbox-ui@0.44.0 resolve it to 0.14.0. The old single-version state (0.10.1) is gone, so this PR introduces a split. This risks TypeScript type-identity divergence, runtime instanceof/symbol mismatches if agent-interface exports classes or unique symbols, and bundle bloat. Typecheck and the sandbox unit tests currently pass, so it is not blocking, but it should be deduped (e.g., via pnpm.overrides or a sandbox release that a
🟡 LOW peerDependency floor raised for optional sandbox peer — package.json
Line 371 changes the peer floor from '>=0.9.0' to '>=0.9.4'. Consumers pinning @tangle-network/sandbox at 0.9.0–0.9.3 will now see a peerDependencies warning on install. This is intentional (src/sandbox/index.ts in another shot uses 0.9.4 APIs) and sandbox is marked optional:true in peerDependenciesMeta (lines 391-393), so install does not hard-fail. No action required; noting for downstream-release visibility.
🟡 LOW agent-interface version split (0.13.0 nested vs 0.14.0 root) — pnpm-lock.yaml
Lines around the @tangle-network/sandbox@0.9.4 snapshot show it depends on @tangle-network/agent-interface@0.13.0, while the root consumers (@tangle-network/agent-runtime@0.76.0 at the new agent-interface@0.14.0 peer, @tangle-network/sandbox-ui@0.44.0, and the new @tangle-network/agent-core@0.3.4) resolve 0.14.0. Two copies of agent-interface now coexist in the dep tree. Impact: for zod-schema packages this is typically benign, but if any code does
instanceofchecks or relies on a singleton registry exported from agent-interface, the two versions will fail to interoperate silently at runtime (type identity mismatch). Fix: confirm sandbox@0.9.4 was intended to pin 0.13.0 (not 0.14.0); if a unified tree is desired, file an upstream sandbox patch to widen/align its agent-interface range, or
🟡 LOW Coupling assumption: supportsWriteMode===true implies the SDK honors the mode field — src/sandbox/index.ts
index.ts:786,793,794-799 assumes
supportsWriteModeand acceptance of the per-filemodeargument move together. If they ever decouple (flag true, mode ignored), executable profile files would be written via writeMany without the +x bit and the exec safety net would not fire — a silent perms regression on /bin/skills scripts. Worth a contract test that asserts writeMany receives and applies mode when supportsWriteMode===true, or a single integration smoke against a real 0.9.4 SDK instance.
🟡 LOW Peer-dep floor (>=0.9.4) and the in-code version claim are unverified against the actual SDK — src/sandbox/index.ts
package.json sets
@tangle-network/sandbox: >=0.9.4as peer and the comment at index.ts:783-784 asserts pre-0.9.4 SDKs lack supportsWriteMode. node_modules is not vendored in this worktree so I could not confirm 0.9.4 actually exports supportsWriteMode and forwards mode. If 0.9.4 ships writeMany but NOT supportsWriteMode, every executable file stays on exec (correct but no perf win) — not a bug, just a mis-stated floor. Confirm the SDK changelog once before merge.
🟡 LOW supportsWriteMode read through an as type escape hatch — src/sandbox/index.ts
index.ts:763-766 casts box.fs to
SandboxInstance['fs'] & { supportsWriteMode?: boolean }because the SDK type does not declare the field. The check is fail-safe (undefined -> false -> exec), so the runtime risk is low, but if a future @tangle-network/sandbox typessupportsWriteModewith a different shape (e.g. a method or a union) this compiles silently and the cast hides the drift. When the SDK ships a typed version, drop the cast and rely on the declared type; consider asserting the field is exactly boolean at runtime in a dev/test guard.
tangletools · 2026-06-27T13:19:32Z · trace
tangletools
left a comment
There was a problem hiding this comment.
✅ Approved — 6 non-blocking findings — 8016610d
Full multi-shot audit completed 3/3 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 4 changed files. Global verifier still owns final merge decision. | Full multi-shot audit completed 3/3 planned shots over 4 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-27T13:19:32Z · immutable trace
Summary
box.fs.writeMany()withmode: 0o755.~/~user, unsafe../.sidecar, or SDKs withoutwriteMany.Dependency
Depends on tangle-network/agent-dev-container#2781 and a
@tangle-network/sandboxrelease containing file-writemodesupport.Validation
corepack pnpm exec vitest run src/sandbox/index.test.ts -t "writeProfileFilesToBox"corepack pnpm exec vitest run src/sandbox/index.test.tsNODE_OPTIONS=--max-old-space-size=6144 corepack pnpm run typecheckNODE_OPTIONS=--max-old-space-size=6144 corepack pnpm run buildReview Guide
src/sandbox/index.ts: file API eligibility andmode: 0o755mapping for explicit executable andbin/profile files.src/sandbox/index.test.ts: no-exec regression for reused executable profile writes and preserved unsupported-path fallback.Release note
GTM uptake needs an agent-app patch release after this merges and after the ADC SDK mode-support release is available.
Refs tangle-network/agent-dev-container#2780