@@ -3,7 +3,7 @@ import { mkdirSync, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync }
33import { tmpdir } from "node:os"
44import { join } from "node:path"
55import { chdir , cwd } from "node:process"
6- import { AGENT_TASK_RUN_REQUEST_SCHEMA , AGENT_TASK_RUN_RESULT_JSON_SCHEMA , AGENT_TASK_RUN_RESULT_SCHEMA , ARTIFACT_RESULT_ENVELOPE_SCHEMA , HEADLESS_AGENT_TASK_REQUEST_JSON_SCHEMA , HEADLESS_AGENT_TASK_REQUEST_SCHEMA , HEADLESS_AGENT_TASK_RESULT_JSON_SCHEMA , HEADLESS_AGENT_TASK_RESULT_SCHEMA , PREVIEW_LEASE_SCHEMA , TYPED_ARTIFACT_SCHEMA , buildAgentTaskRecipe , headlessAgentTaskRequestToRunInput , normalizeAgentRuntimeExecutionChanges , normalizeAgentRuntimeWorkload , normalizeAgentTaskRunResult , normalizeAgentTerminalResult , normalizeArtifactResultTypedArtifacts , normalizeHeadlessAgentTaskRequest , normalizeHeadlessAgentTaskResult , normalizeRecipeRunSummary , normalizeTaskInput } from "../packages/runtime-core/src/index.js"
6+ import { AGENT_TASK_RUN_REQUEST_SCHEMA , AGENT_TASK_RUN_RESULT_JSON_SCHEMA , AGENT_TASK_RUN_RESULT_SCHEMA , ARTIFACT_RESULT_ENVELOPE_SCHEMA , HEADLESS_AGENT_TASK_REQUEST_JSON_SCHEMA , HEADLESS_AGENT_TASK_REQUEST_SCHEMA , HEADLESS_AGENT_TASK_RESULT_JSON_SCHEMA , HEADLESS_AGENT_TASK_RESULT_SCHEMA , PREVIEW_LEASE_SCHEMA , TYPED_ARTIFACT_SCHEMA , WORKSPACE_DELTA_JSON_SCHEMA , WORKSPACE_DELTA_SCHEMA , buildAgentTaskRecipe , headlessAgentTaskRequestToRunInput , normalizeAgentRuntimeExecutionChanges , normalizeAgentRuntimeWorkload , normalizeAgentTaskRunResult , normalizeAgentTerminalResult , normalizeArtifactResultTypedArtifacts , normalizeHeadlessAgentTaskRequest , normalizeHeadlessAgentTaskResult , normalizeRecipeRunSummary , normalizeTaskInput , workspaceDeltaFromAgentTaskRunResult } from "../packages/runtime-core/src/index.js"
77import { effectivePolicyCommands } from "../packages/runtime-core/src/contracts.js"
88import { commandCatalogOutput } from "../packages/cli/src/commands/discovery.js"
99import { agentTaskResultFromRun , agentTaskRunExitCode , agentTaskRunJsonOutput , normalizeAgentTaskRunCliInput , writeAgentTaskRunResultFile } from "../packages/cli/src/commands/agent-task-run.js"
@@ -222,6 +222,60 @@ assert.equal(headlessResult.preview?.public_url, "https://preview.example.test/"
222222assert . equal ( headlessResult . evidence_refs [ 0 ] . kind , "codebox-evidence-bundle" )
223223assert . equal ( headlessResult . agent_task_run_result . schema , AGENT_TASK_RUN_RESULT_SCHEMA )
224224
225+ const workspaceDeltaResult = normalizeAgentTaskRunResult ( {
226+ success : true ,
227+ artifacts : [
228+ { kind : "codebox-changed-files" , path : "files/changed-files.json" , bytes : 128 , sha256 : "changed" } ,
229+ { kind : "codebox-patch" , path : "files/patch.diff" , bytes : 256 , sha256 : "patch" } ,
230+ ] ,
231+ agent_result : {
232+ changedFiles : { artifact : "files/changed-files.json" , bytes : 128 , count : 1 , sha256 : "changed" } ,
233+ patch : { artifact : "files/patch.diff" , bytes : 256 , sha256 : "patch" } ,
234+ } ,
235+ } )
236+ const workspaceDelta = workspaceDeltaFromAgentTaskRunResult ( workspaceDeltaResult )
237+ assert . equal ( workspaceDelta . schema , WORKSPACE_DELTA_SCHEMA )
238+ assert . equal ( workspaceDelta . status , "changed" )
239+ assert . equal ( workspaceDelta . changed_files ?. path , "files/changed-files.json" )
240+ assert . equal ( workspaceDelta . patch ?. path , "files/patch.diff" )
241+ assert . equal ( normalizeHeadlessAgentTaskResult ( workspaceDeltaResult ) . workspace_delta . status , "changed" )
242+ assert . equal ( WORKSPACE_DELTA_JSON_SCHEMA . additionalProperties , false )
243+ assert . equal ( WORKSPACE_DELTA_JSON_SCHEMA . properties . changed_files . required . includes ( "path" ) , true )
244+
245+ assert . equal ( workspaceDeltaFromAgentTaskRunResult ( normalizeAgentTaskRunResult ( { success : true , no_op : true } ) ) . status , "no_op" )
246+
247+ const hostPathDelta = workspaceDeltaFromAgentTaskRunResult ( normalizeAgentTaskRunResult ( {
248+ success : true ,
249+ artifacts : [
250+ { kind : "codebox-changed-files" , path : "/private/codebox/files/changed-files.json" } ,
251+ { kind : "codebox-patch" , path : "/private/codebox/files/patch.diff" } ,
252+ ] ,
253+ } ) )
254+ assert . equal ( hostPathDelta . status , "unavailable" )
255+ assert . equal ( hostPathDelta . diagnostics . filter ( ( diagnostic ) => diagnostic . code === "workspace_delta.artifact_not_portable" ) . length , 2 )
256+
257+ for ( const path of [ "\\private\\codebox\\files\\changed-files.json" , "\\\\host\\share\\files\\changed-files.json" , "C:\\codebox\\files\\changed-files.json" , "files/../changed-files.json" ] ) {
258+ const malformedDelta = workspaceDeltaFromAgentTaskRunResult ( normalizeAgentTaskRunResult ( {
259+ success : true ,
260+ artifacts : [
261+ { kind : "codebox-changed-files" , path } ,
262+ { kind : "codebox-patch" , path : "files/patch.diff" } ,
263+ ] ,
264+ } ) )
265+ assert . equal ( malformedDelta . status , "unavailable" )
266+ assert . equal ( malformedDelta . changed_files , undefined )
267+ assert . equal ( JSON . stringify ( malformedDelta ) . includes ( "private/codebox" ) , false , "workspace delta never leaks a host artifact path" )
268+ }
269+
270+ const inferredFilenameDelta = workspaceDeltaFromAgentTaskRunResult ( normalizeAgentTaskRunResult ( {
271+ success : true ,
272+ artifacts : [
273+ { kind : "artifact" , path : "files/changed-files.json" } ,
274+ { kind : "artifact" , path : "files/patch.diff" } ,
275+ ] ,
276+ } ) )
277+ assert . equal ( inferredFilenameDelta . status , "unavailable" , "workspace delta only accepts explicitly typed artifacts" )
278+
225279const headlessJsonOutput = agentTaskRunJsonOutput ( {
226280 success : true ,
227281 schema : "wp-codebox/agent-task-run/v1" ,
0 commit comments