Bug
When using createSandbox() + sandbox.run(), the "Context window: NNNk" line is never printed after iterations, even though it works correctly with the top-level run().
Root cause
createSandbox.ts builds its own reuseFactoryLayer that calls makeEffect without passing bindMountHandle:
// createSandbox.ts ~L294
const reuseFactoryLayer = Layer.succeed(SandboxFactory, {
withSandbox: (makeEffect) =>
makeEffect({
hostWorktreePath: worktreePath,
sandboxRepoPath: sandboxRepoDir,
applyToHost,
// bindMountHandle is never passed here
})
});
But in Orchestrator.ts, session capture (and therefore usage parsing) only runs when bindMountHandle is present:
// Orchestrator.ts ~L371
if (provider.captureSessions && sessionId && bindMountHandle) {
// capture session, parse usage ...
}
Since bindMountHandle is always undefined in the createSandbox path, usage stays undefined on every IterationResult, and buildContextWindowLines returns nothing.
The top-level run() uses WorktreeDockerSandboxFactory which does pass bindMountHandle, so context window output works there.
Why it's an oversight
The usage capture was added in #406 and the display in #459 — both only touched run.ts. createSandbox.ts was never updated to forward providerHandle through the factory.
Fix
In createSandbox.ts, pass providerHandle as bindMountHandle in the makeEffect call:
const reuseFactoryLayer = Layer.succeed(SandboxFactory, {
withSandbox: (makeEffect) =>
makeEffect({
hostWorktreePath: worktreePath,
sandboxRepoPath: sandboxRepoDir,
applyToHost,
bindMountHandle: providerHandle as BindMountSandboxHandle | undefined,
})
});
providerHandle is already available in the closure via SandboxHandleContext.
Workaround
Use two separate top-level sandcastle.run() calls with branchStrategy: { type: "branch", branch } instead of createSandbox + sandbox.run(). This uses the full factory which passes bindMountHandle correctly.
Bug
When using
createSandbox()+sandbox.run(), the "Context window: NNNk" line is never printed after iterations, even though it works correctly with the top-levelrun().Root cause
createSandbox.tsbuilds its ownreuseFactoryLayerthat callsmakeEffectwithout passingbindMountHandle:But in
Orchestrator.ts, session capture (and therefore usage parsing) only runs whenbindMountHandleis present:Since
bindMountHandleis alwaysundefinedin thecreateSandboxpath,usagestaysundefinedon everyIterationResult, andbuildContextWindowLinesreturns nothing.The top-level
run()usesWorktreeDockerSandboxFactorywhich does passbindMountHandle, so context window output works there.Why it's an oversight
The usage capture was added in #406 and the display in #459 — both only touched
run.ts.createSandbox.tswas never updated to forwardproviderHandlethrough the factory.Fix
In
createSandbox.ts, passproviderHandleasbindMountHandlein themakeEffectcall:providerHandleis already available in the closure viaSandboxHandleContext.Workaround
Use two separate top-level
sandcastle.run()calls withbranchStrategy: { type: "branch", branch }instead ofcreateSandbox + sandbox.run(). This uses the full factory which passesbindMountHandlecorrectly.