diff --git a/packages/cli/src/agent-code.ts b/packages/cli/src/agent-code.ts index 9766d74..c3062fc 100644 --- a/packages/cli/src/agent-code.ts +++ b/packages/cli/src/agent-code.ts @@ -120,7 +120,7 @@ add_filter('datamachine_code_remote_workspace_backend_should_handle', '__return_ $sandbox_workspace_adoptions = array(); if (function_exists('wp_get_ability')) { $sandbox_adopt_callback = static function () use (&$sandbox_workspace_adoptions): void { - $sandbox_adopt_ability = wp_get_ability('datamachine/workspace-adopt'); + $sandbox_adopt_ability = wp_get_ability('datamachine-code/workspace-adopt') ?: wp_get_ability('datamachine/workspace-adopt'); if (!$sandbox_adopt_ability || !method_exists($sandbox_adopt_ability, 'execute')) { return; } diff --git a/scripts/agent-sandbox-code-smoke.ts b/scripts/agent-sandbox-code-smoke.ts index aa9a2b2..e5aef22 100644 --- a/scripts/agent-sandbox-code-smoke.ts +++ b/scripts/agent-sandbox-code-smoke.ts @@ -84,6 +84,7 @@ async function main() { assert.doesNotMatch(code, /AgentsAPIAIWP_Agent_Execution_Principal/, "sandbox chat should not collapse namespaced runtime principal references") assert.match(code, /PermissionHelper::run_as_authenticated/, "sandbox chat should execute runtime abilities in an authenticated Data Machine context") assert.match(code, /DataMachine\\Abilities\\PermissionHelper::run_as_authenticated/, "sandbox chat should emit a valid namespaced PermissionHelper class reference") + assert.match(code, /datamachine-code\/workspace-adopt/, "sandbox setup should use the canonical Data Machine Code workspace adopt ability") assert.doesNotMatch(code, /PermissionHelper::run_as_authenticated\([^\)]*,\s*1\)/, "sandbox chat should not force a user-specific Data Machine capability check") assert.doesNotMatch(code, /DataMachineAbilitiesPermissionHelper/, "sandbox chat should not collapse namespaced PermissionHelper references") assert.doesNotMatch(code, /datamachine_agent_mode_sandbox/, "sandbox chat should not depend on Data Machine agent mode filters") diff --git a/scripts/recipe-workspace-vfs-materialization-smoke.ts b/scripts/recipe-workspace-vfs-materialization-smoke.ts new file mode 100644 index 0000000..68f77f7 --- /dev/null +++ b/scripts/recipe-workspace-vfs-materialization-smoke.ts @@ -0,0 +1,72 @@ +import assert from "node:assert/strict" +import { execFile } from "node:child_process" +import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises" +import { tmpdir } from "node:os" +import { join, resolve } from "node:path" +import { promisify } from "node:util" + +const execFileAsync = promisify(execFile) +const root = resolve(import.meta.dirname, "..") +const workspace = await mkdtemp(join(tmpdir(), "wp-codebox-recipe-workspace-vfs-materialization-")) + +try { + const seed = join(workspace, "seed") + const recipePath = join(workspace, "recipe.json") + const artifacts = join(workspace, "artifacts") + await mkdir(seed, { recursive: true }) + await writeFile(join(seed, "plugin.php"), " [file.relativePath, file])) + assert.equal(changed.get("generated.txt")?.status, "added") + assert.equal(changed.get("plugin.php")?.status, "modified") + assert.equal(changed.get("remove-me.txt")?.status, "deleted") + + const patch = await readFile(join(output.artifacts.directory, "files", "patch.diff"), "utf8") + assert.match(patch, /diff --git a\/workspace\/materialization-smoke\/generated\.txt b\/workspace\/materialization-smoke\/generated\.txt/) + assert.match(patch, /\+created inside playground/) + assert.match(patch, /\+\/\/ after from playground/) + assert.match(patch, /deleted file mode 100644/) +} finally { + await rm(workspace, { recursive: true, force: true }) +} diff --git a/scripts/smoke-manifest.ts b/scripts/smoke-manifest.ts index 3c7b6f4..2618bb3 100644 --- a/scripts/smoke-manifest.ts +++ b/scripts/smoke-manifest.ts @@ -151,6 +151,7 @@ export const smokeGroups = { tsxSmoke("recipe-staged-files-smoke"), tsxSmoke("recipe-dependency-overlay-smoke"), tsxSmoke("recipe-workspace-seed-excludes-smoke"), + tsxSmoke("recipe-workspace-vfs-materialization-smoke"), tsxSmoke("recipe-runtime-evidence-smoke"), tsxSmoke("recipe-run-timeout-smoke"), tsxSmoke("recipe-playground-boot-failure-smoke"),