Skip to content

feat(tools): remote_task replaces the cloudflare sandbox mode - #106

Closed
geminixiang wants to merge 2 commits into
mainfrom
feat/remote-task-executor
Closed

geminixiang wants to merge 2 commits into
mainfrom
feat/remote-task-executor

Conversation

@geminixiang

Copy link
Copy Markdown
Owner

Implements ADR 0002, now moved from proposed to accepted.

The type was claiming something the runtime never did

Remote execution was never a sandbox runtime. It holds no workspace projection, and the code already agreed:

  • ActorExecutionResolver resolved mounts (execution-resolver.ts:65) and the Cloudflare branch discarded them
  • the bridge payload has no mount concept at all
  • credentials.fileMounts was false
  • getPathContext returned a host/runtime root pair with no translation between them

So sessions, MEMORY.md, and skills were always on the mikan host and never on the remote side. No deployment loses data in this move — there was nothing out there to lose.

What it becomes

A tool. Each remote_task call gets a throwaway mikan-task-<uuid> sandbox, which is the point: parallel calls cannot see or disturb each other, so fan-out and dynamic workflows work.

A sticky per-conversation id was the alternative and was rejected — it would carry scratch state between calls (exactly the persistence this decision rejects) and would make one conversation's parallel calls collide.

The tool is registered only when CLOUDFLARE_SANDBOX_URL is set, so a host without a bridge never advertises a capability it cannot fulfil.

One deliberate non-goal

The task executor receives no vault credentials. The conversation vault belongs to the sandbox runtime; shipping a default that sends a user's credentials to a remote third party is not something to do quietly. There is a regression test pinning it. Say the word if you want opt-in credential passing and I will design it separately.

The consequence ADR 0002 predicted

allowsAmbientDefaultSharedVault collapses to image alone, and its comment now states a trust rule instead of a topology one. That framing matters: the old "isolated sandboxes" wording is exactly how agent-sandbox got added to the list in 19845f7 by pattern-matching, and it would have pulled in gondolin — whose entire purpose is running code from people you do not trust. The test now asserts gondolin stays excluded, with the reason.

Migration

--sandbox=cloudflare:* is rejected at startup with guidance, following the sandbox.gondolin.remote precedent. Keep CLOUDFLARE_SANDBOX_URL set to retain remote fan-out via the tool.

Docs

A new remote-task page replaces sandbox/cloudflare.md across all four locales, and the mode tables lose the row, card, and column. Also fixes the gondolin lifecycle cell, which still read "worker-hosted" after #103.

Verification

lint, fmt:check, knip, build, 1391/1391 — and this commit passed the real pre-commit hook with no --no-verify, thanks to #105.

Not exercised against a live bridge (no Worker deployed here); the tool's transport is covered by 7 unit tests including abort, non-zero exit, bridge error, and the no-credentials guard.

Git resolves its repository from the environment before it looks at the
working directory. When the suite runs inside a git hook -- husky's
pre-commit runs `npm test` -- git exports GIT_DIR to the hook, and every
git a fixture spawns inherits it. With GIT_DIR set and no GIT_WORK_TREE,
git treats the fixture's cwd as the work tree, so `git add -A` in a
throwaway /tmp repo stages the deletion of every file tracked in *this*
repository.

That is not hypothetical. It is why `deploy/pm2/ecosystem.config.cjs`
silently left the index during the gondolin work, and .gitignore's
unanchored `ecosystem.config.cjs` then refused to let `git add -A` put
it back, so the file looked deliberately deleted. It also made the hook
unusable: the fixture's own commit re-enters this repo's pre-commit in a
directory with no package.json and fails, which is why recent commits
needed --no-verify.

Eight test files spawn git, so the fix is one setup file that strips the
ambient pointers rather than eight patches.

Also anchors the two .gitignore patterns that made the damage stick:
`/ecosystem.config.cjs` so the tracked deploy template at any depth is
no longer matched, and `node_modules` without the trailing slash so a
symlink -- which worktrees sometimes get -- is not committable.
Un-ignoring the deploy template exposes it to knip, which has no reason
to resolve a pm2 config, so deploy/** joins the knip ignore list.

Verified two ways: pointing GIT_DIR at a decoy repo gives 3 failures and
a wrecked index before, 23 passes and an untouched decoy after; and this
commit itself passes the real pre-commit hook end to end -- lint,
fmt:check, knip, build, 1390/1390 -- leaving a clean index.
Implements ADR 0002. Remote execution was never a sandbox runtime: it
holds no workspace projection, so nothing it writes survives a turn and
nothing from the conversation is visible to it. The type claimed
otherwise -- ActorExecutionResolver resolved mounts and the Cloudflare
branch discarded them, the bridge payload has no mount concept, and
credentials.fileMounts was false -- so sessions and MEMORY.md were
always on the mikan host and never on the remote side.

So it becomes a tool. Each remote_task call gets a throwaway
mikan-task-<uuid> sandbox, which is the point: parallel calls cannot see
or disturb each other. A sticky per-conversation id would carry scratch
state between calls, reintroducing the persistence this rejects, and
would make one conversation's parallel calls collide. The tool is
registered only when CLOUDFLARE_SANDBOX_URL is set, so a host without a
bridge never advertises a capability it cannot fulfil.

The task executor gets no vault credentials. The conversation vault
belongs to the sandbox runtime; sending a user's credentials to a remote
third party is not a default worth shipping, and nothing here needs it.

--sandbox=cloudflare:* is rejected at startup with migration guidance,
following the sandbox.gondolin.remote precedent.

The consequence the ADR predicted lands too: allowsAmbientDefaultShared-
Vault collapses to image alone, and its comment now states a trust rule
instead of a topology one. The old "isolated sandboxes" framing is how
agent-sandbox was added to that list in 19845f7, and it would have
pulled in gondolin -- whose whole purpose is running untrusted code.

Docs: a remote-task page replaces sandbox/cloudflare.md across all four
locales, and the capability tables lose the column. Also corrects the
gondolin lifecycle cell, still reading "worker-hosted" after #103.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 25, 2026

Copy link
Copy Markdown

Deploying mikan with  Cloudflare Pages  Cloudflare Pages

Latest commit: d0a4fc8
Status: ✅  Deploy successful!
Preview URL: https://56afc41e.mikan-1wv.pages.dev
Branch Preview URL: https://feat-remote-task-executor.mikan-1wv.pages.dev

View logs

@geminixiang

Copy link
Copy Markdown
Owner Author

Closing because this item has had no activity for more than 30 days. Please reopen it or create a fresh follow-up if the work is still relevant.

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.

1 participant