Skip to content

feat(emdash-bot): hybrid computer/sandbox execution layer + investigation skills (bot next-gen 3/5) - #2381

Merged
ascorbic merged 13 commits into
bot-nextgen/02-machine-fix-loopfrom
bot-nextgen/03-computer-exec
Aug 9, 2026
Merged

feat(emdash-bot): hybrid computer/sandbox execution layer + investigation skills (bot next-gen 3/5)#2381
ascorbic merged 13 commits into
bot-nextgen/02-machine-fix-loopfrom
bot-nextgen/03-computer-exec

Conversation

@ascorbic

@ascorbic ascorbic commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Slice 3 of the bot next-gen stack (on #2376). Replaces emdash-bot's execution plumbing with a hybrid execEnv and lands the investigation skills.

  • Hybrid execution: @cloudflare/computer 0.1.1 (pinned exact) provides the isolate surface — durable SQLite VFS on a new WorkspaceDO (append-only migration v4), in-VFS isomorphic-git (clone/status/diff without a container), and just-bash isolate exec via the Worker Loader. The existing @cloudflare/sandbox container keeps the real-Linux work (pnpm install, astro build, vitest, agent-browser). computer's own container backend requires computerd, which Cloudflare has not published (private in their monorepo; verified against the tarball and repo) — the exec-env.ts module is the single flip-point when that changes.
  • Stateless VFS→container coherence: before every container exec, the changed set is re-derived from the VFS via git status --porcelain -z and materialized into the container checkout. No in-memory bookkeeping — correctness survives isolate eviction/resume in both directions (adversarial review found the stateful version lost edits across isolate restarts; the stateless design eliminates the class).
  • Skills: the investigation skill set (index + repro-public/repro-admin/repro-api/diagnose/verify/fix) lands as Flue 2 skill directories — isolate-first/container-on-demand guidance and evidence-carrying verdicts ("could not reproduce" with transcript is a first-class outcome) baked into each.
  • Hardening: readArtifact accepts bare filenames only (traversal/absolute/symlink rejected); every exec is deadline-bounded across both substrates.

Investigation model stays @cf/moonshotai/kimi-k2.7-code (verified id); classifier unchanged.

Closes #

Type of change

Maintainer-directed: implements the bot next-gen design; no separate Discussion.

Checklist

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Claude Fable 5 (Claude Code; built and adversarially reviewed by Fable subagents, incl. a delta re-review of the coherence fix)

Screenshots / test output

unit:        111 passed (111)
integration:  35 passed (35)
build:       index.js 9.25 MB raw / 2.06 MB gzip (within Workers limits; headroom noted)

Known live-validation items deferred to the slice-5 eval harness (cannot be exercised in CI): isolate exec + VFS git clone against real bindings, container attach round-trip, bundle headroom watch.


Try this PR

Open a fresh playground →

A full working EmDash site, deployed from this branch. Each visit gets its own session-scoped sandbox: no login needed and no shared state. Try the admin, edit content, hit the public site.

Tracks bot-nextgen/03-computer-exec. Updated automatically when the playground redeploys.

@changeset-bot

changeset-bot Bot commented Aug 8, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 89ef4d6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ascorbic ascorbic changed the title bot nextgen/03 computer exec feat(emdash-bot): hybrid computer/sandbox execution layer + investigation skills (bot next-gen 3/5) Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Scope check

This PR changes 1,893 lines across 19 files. Large PRs are harder to review and more likely to be closed without review.

If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs.

See CONTRIBUTING.md for contribution guidelines.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
emdash-playground 89ef4d6 Aug 09 2026, 11:24 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
emdash-demo-cache 89ef4d6 Aug 09 2026, 11:25 AM

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
⚠️ Deployment skipped
View logs
emdash-demo-do 78e4b0e Aug 09 2026, 09:17 AM

@pkg-pr-new

pkg-pr-new Bot commented Aug 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@2381

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@2381

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@2381

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@2381

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@2381

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@2381

emdash

npm i https://pkg.pr.new/emdash@2381

create-emdash

npm i https://pkg.pr.new/create-emdash@2381

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@2381

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@2381

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@2381

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@2381

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@2381

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@2381

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@2381

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@2381

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@2381

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@2381

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@2381

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@2381

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@2381

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@2381

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@2381

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@2381

commit: 89ef4d6

@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 207faf1 to 3b16598 Compare August 8, 2026 15:37
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 97757a9 to 3b16598 Compare August 8, 2026 16:43
@ascorbic
ascorbic marked this pull request as ready for review August 8, 2026 16:50
Copilot AI lite review requested due to automatic review settings August 8, 2026 16:51
@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Aug 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR upgrades infra/emdash-bot to a hybrid execution model, introducing an isolate/VFS substrate (via @cloudflare/computer) alongside the existing container-based sandbox, and lands the next-gen “investigation” skill set used by the bot’s maintainer-triggered workflow.

Changes:

  • Add @cloudflare/computer@0.1.1 and wire a new WorkspaceDO (SQLite-backed VFS + worker-shell exec via Dynamic Worker Loader) into the bot Worker.
  • Introduce an ExecEnv abstraction that routes commands to isolate vs container and re-materializes VFS changes into the container from git status --porcelain -z.
  • Add the investigation skill directory set (repro/diagnose/verify/fix/investigate), update the investigate agent to use them, and add targeted unit tests for the execEnv seam.

Reviewed changes

Copilot reviewed 17 out of 19 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pnpm-lock.yaml Locks @cloudflare/computer@0.1.1 and related dependency graph adjustments.
infra/emdash-bot/package.json Adds @cloudflare/computer dependency for isolate/VFS execution.
infra/emdash-bot/wrangler.jsonc Enables experimental compat flag, adds worker_loaders, and registers WorkspaceDO as sqlite-enabled (v4).
infra/emdash-bot/vitest.workers.config.ts Adds a Vite plugin stub for SKILL.md imports to keep worker-pool bundles parseable in tests.
infra/emdash-bot/tests/unit/sandbox-deadline.test.ts Removes tests for the deleted withSandboxDeadlines wrapper; keeps withDeadline coverage.
infra/emdash-bot/tests/unit/exec-env.test.ts New unit test suite covering exec routing, deadlines, container reuse, VFS→container materialization, artifact containment, and clone behavior.
infra/emdash-bot/.flue/raw.d.ts Adds a module declaration for */SKILL.md imports as Flue SkillReferences.
infra/emdash-bot/.flue/lib/sandbox-deadline.ts Removes withSandboxDeadlines, leaving withDeadline as the shared deadline primitive.
infra/emdash-bot/.flue/lib/exec-env.ts New hybrid execution layer (ExecEnv) bridging isolate VFS + sandbox container; includes porcelain parsing + artifact egress hardening.
infra/emdash-bot/.flue/cloudflare.ts Adds WorkspaceDO based on withWorkspace, configures worker-shell backend using the LOADER binding.
infra/emdash-bot/.flue/agents/investigate.ts Replaces sandbox-only plumbing with ExecEnv, registers skills, and exposes isolate/container tools to the agent.
infra/emdash-bot/.flue/skills/investigate/SKILL.md New “spine” skill defining the end-to-end investigation pipeline and execution discipline.
infra/emdash-bot/.flue/skills/diagnose/SKILL.md New diagnose leaf skill (isolate-only inspection + evidence-carrying output).
infra/emdash-bot/.flue/skills/verify/SKILL.md New verify leaf skill that gates fixes on intended vs bug behavior with citations.
infra/emdash-bot/.flue/skills/repro-admin/SKILL.md New admin repro leaf skill (container + agent-browser + dev-bypass flow).
infra/emdash-bot/.flue/skills/repro-public/SKILL.md New public-site repro leaf skill (container + agent-browser against public routes).
infra/emdash-bot/.flue/skills/repro-api/SKILL.md New API/CLI repro leaf skill (prefer failing vitest test in container).
infra/emdash-bot/.flue/skills/fix/SKILL.md New fix leaf skill (implements diagnose fix when verify says bug; enforces repo conventions).
infra/emdash-bot/.flue/skills/investigate/instructions.md Removes the legacy freeform instructions doc in favor of SKILL-based workflow.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 354 to 356
{
name: "git-push-capability",
command: `cd ${REPO_DIR} && git config http.https://github.com/.extraHeader '${PUSH_CAPABILITY_HEADER}: ${pushCapability}'`,
command: `cd ${REPO_DIR} && git checkout '${branch}' && git reset --hard 'origin/${branch}'`,
},
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Aug 8, 2026
@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label Aug 8, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This PR is the right next slice for emdash-bot: it replaces the previous all-container setup with an isolate-first/computer VFS layer plus a sandbox fallback, and lands the Flue 2 investigation skill set. The stateless VFS→container materialization design fixes the coherence problem described in the PR (edits are re-derived from git status on every container exec instead of tracked in memory), and the test coverage for rename, non-ASCII, and cross-isolate materialization is good.

I checked the new exec-env.ts seam, the refactored Investigate agent, the WorkspaceDO plumbing, the wrangler migration, the deadline helpers, and the tests. I also searched for remaining references to the removed withSandboxDeadlines/useSandbox/defineSkill patterns and for stale call sites of the old sandbox setup. No user-facing routes were touched, so AGENTS concerns about Lingui, RTL Tailwind, SQL safety, locale filtering, and logged-out query counts do not apply here.

I did find a few concrete issues that should be addressed before merge:

  1. A transient getWorkspace() failure is cached as a rejected promise forever, so the run can never recover.
  2. useSkill(fixSkill) is called conditionally, which is unsafe if the Flue runtime uses React-style hook ordering.
  3. wrangler.test.jsonc and the workers-pool test entry still only list Sandbox/OrchestratorDO; they need to reflect the new WorkspaceDO and LOADER binding and the experimental flag so tests mirror production.
  4. Several top-of-file comments repeat PR rationale / rejected alternatives, which violates AGENTS.md comment discipline.

None of these are catastrophic, but #1 and #3 are real regressions/footguns.


Findings

  • [needs fixing] infra/emdash-bot/.flue/agents/investigate.ts:284-290

    The clientPromise in fromWorkspaceClientLazy is set with ??= getWorkspace(stub). If that first RPC call rejects, the rejected promise is cached forever and every subsequent readFile/exec call will rethrow it, even if the DO has recovered. A single transient failure on the first call poisons the entire run.

    function fromWorkspaceClientLazy(getClient: () => ReturnType<typeof getWorkspace>) {
    	let backend: ReturnType<typeof fromWorkspaceClient> | undefined;
    	const resolve = async () => {
    		if (backend) return backend;
    		const client = await getClient();
    		backend = fromWorkspaceClient(client);
    		return backend;
    	};
    
  • [needs fixing] infra/emdash-bot/.flue/agents/investigate.ts:91-92

    Calling useSkill inside a conditional breaks React-style hook ordering. If the Flue runtime tracks hook position, a re-render with a different input.mode (or even just a future code path) will corrupt persisted hook state. The skill should be registered unconditionally, or you should use a Flue API that explicitly supports conditional registration.

    	useSkill(reproPublicSkill);
    	useSkill(fixSkill);
    
  • [needs fixing] infra/emdash-bot/wrangler.test.jsonc:38-53

    wrangler.test.jsonc still only declares Sandbox and OrchestratorDO. The file's own comment says to keep it in sync with production bindings, but the PR adds WorkspaceDO, the LOADER worker loader, and the experimental compatibility flag in wrangler.jsonc. Without them, the workers-pool tests are not exercising the same shapes as the deployed Worker.

    	"compatibility_flags": ["nodejs_compat", "experimental"],
    
    	// ... existing containers / ai / durable_objects additions ...
    
    	"worker_loaders": [
    		{
    			"binding": "LOADER",
    		},
    	],
    

    Also add WorkspaceDO to the durable-object bindings and the test-only migration new_sqlite_classes, and re-export it from tests/integration/_entry.ts.

  • [needs fixing] infra/emdash-bot/tests/integration/_entry.ts:16-17

    The test entry re-exports the DO classes declared in wrangler.test.jsonc. Since WorkspaceDO was added to production, it needs to be re-exported here as well once wrangler.test.jsonc is updated.

    export { Sandbox, ContainerProxy, WorkspaceDO } from "../../.flue/cloudflare.js";
    
  • [suggestion] infra/emdash-bot/.flue/lib/exec-env.ts:1-22

    This header comment contains PR-style rationale and rejected alternatives ("computerd is not shippable yet", "Swapping to computer's CloudflareContainerBackend later", "GitHub reads: emdash is public"). AGENTS.md says comments should address future readers, not summarize the PR or justify decisions. Trim it to the invariants a reader needs to know, and move the architecture rationale to the PR description.

    // exec-env: single seam over the investigation's two execution substrates.
    // Every @cloudflare/computer and @cloudflare/sandbox touchpoint lives here.
    // VFS is authoritative for source; container checkout is re-synced from git status before each container exec.
    // Only the container side performs pnpm/astro/vitest/agent-browser work.
    
  • [suggestion] infra/emdash-bot/.flue/cloudflare.ts:124-133

    This block repeats the architecture rationale from exec-env.ts ("computerd is not shippable yet", "the flip-point when it becomes so"). Per AGENTS.md, comments should explain invariants, not restate the PR rationale or reference rejected alternatives. Keep only what is needed to understand the class boundaries.

    // Isolate + VFS substrate for execEnv's IsolateBackend.
    // WorkspaceDO hosts the SQLite-backed filesystem and the worker-shell isolate backend.
    // See exec-env.ts for the agent-side seam.
    

@emdashbot emdashbot Bot removed the bot:review Trigger an emdashbot code review on this PR label Aug 8, 2026
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 84a7f8e to e771ab5 Compare August 9, 2026 06:25
@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label Aug 9, 2026
@ascorbic

ascorbic commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed in e771ab5: a failed workspace connection is no longer cached as a rejected promise (the next call retries), wrangler.test.jsonc now mirrors the production WorkspaceDO/LOADER bindings and the experimental compatibility flag (with WorkspaceDO re-exported from the test entry), and the exec-env/cloudflare header comments are trimmed to invariants. The workers-pool integration suite passes against the updated bindings.

The conditional useSkill(fixSkill) is left as-is. Flue 2 documents useSkill — along with useTool, usePersistentState, and the event hooks — as conditional/reorderable between renders; hooks are not positionally tracked. input.mode is also immutable initialData for the life of a run, so the condition can never change across re-renders. Registering the skill unconditionally would load fix instructions into non-fix investigations.

~ 🤖 Claude Fable 5

@github-actions github-actions Bot added the review/needs-rereview Author pushed changes since the last review label Aug 9, 2026
@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond review/needs-rereview Author pushed changes since the last review and removed review/needs-rereview Author pushed changes since the last review review/awaiting-author Reviewed; waiting on the author to respond labels Aug 9, 2026
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 28da451 to 0873a1c Compare August 9, 2026 08:01
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch 2 times, most recently from 113e7ea to d0b0af0 Compare August 9, 2026 08:31
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 78e4b0e to 64afe94 Compare August 9, 2026 10:51
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 64afe94 to 2b8b15f Compare August 9, 2026 11:07
ascorbic added 13 commits August 9, 2026 12:21
Thin, testable seam wrapping the two investigation substrates: computer
0.1.1 Workspace (isolate/fs/git) and @cloudflare/sandbox (container). Routes
exec by target, bounds every op with a deadline, bridges VFS edits into the
container checkout, and confines every @cloudflare/computer touchpoint to one
module so the future computerd flip is a single-adapter change.
emdash is public, so the VFS read-clone needs no auth and runs via an
isolate git command; fs+runtime reach the DO through their RPC stubs, so the
seam lives agent-side. Drops the in-DO typed-git dependency and keeps token
minting confined to the container push path.
Ports the repro-public/repro-admin/repro-api/diagnose/verify/fix leaf skills
and the investigate spine from the gen-1 .flue/skills content onto computer's
tool model, as flat SKILL.md directories the agent loads per mode. Replaces the
single investigate/instructions.md.
Adds the WorkspaceDO (computer Workspace + worker-shell isolate backend via a
LOADER binding) and swaps the investigate agent off useSandbox onto execEnv:
read/write/edit/ls/grep + an exec tool the model routes isolate-vs-container,
skills loaded per mode, VFS clone at setup. Container stays @cloudflare/sandbox.
Bindings: experimental flag, worker_loaders, WorkspaceDO DO + append-only v4
migration. Build + 107 unit + 35 integration green; typecheck at baseline.
withSandboxDeadlines wrapped Flue's useSandbox SessionEnv, which the execEnv
swap removed. withDeadline (still used by the classifier, orchestrator, and
execEnv) stays.
…F4/F9)

F1: derive the container sync set from the VFS itself (git status against the
checkout) before every container exec, instead of tracking dirty paths in
memory. Materializing before each exec -- not only at attach -- closes the
edit-after-attach gap (stale container source, and a fix push that omits
post-attach edits) and survives an isolate resume, since the VFS is the only
source consulted. Removes #dirtyPaths and the write-through path; the one-time
base checkout stays in the injected attachContainer.

F4: readArtifact takes a bare filename under .bot-artifacts/ -- rejects path
separators, '.'/'..', absolute forms, and a symlinked target.

F9: rewrite the module header to operative facts; the coherence claim is now
true because every container exec re-derives from the VFS.
Non-z porcelain C-escapes and quotes special-character paths, so a delete of
such a path silently no-opped in the container (surviving stale file), and the
' -> ' rename heuristic misfired on paths containing that literal. Switch to
'git status --porcelain -z': NUL-delimited, never quoted or escaped, with
rename/copy old paths in a trailing NUL field (new-then-old). Adds rename and
non-ASCII regression tests.
… mirror WorkspaceDO bindings in the test config
…gated push capability; align skill docs with agent-owned pushes
@ascorbic
ascorbic force-pushed the bot-nextgen/03-computer-exec branch from 2b8b15f to 89ef4d6 Compare August 9, 2026 11:21
@ascorbic
ascorbic merged commit 4ebeb0a into main Aug 9, 2026
60 of 62 checks passed
@ascorbic
ascorbic deleted the bot-nextgen/03-computer-exec branch August 9, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

overlap review/needs-rereview Author pushed changes since the last review size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants