deadbyte-mcp 0.11.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/MANIFEST.SHA256 +126 -54
  2. package/R41-PARENT.json +15 -0
  3. package/README.txt +5 -4
  4. package/acceptance/r40/desktop-live-drift.mjs +106 -0
  5. package/acceptance/r40/desktop-live-ground.mjs +110 -0
  6. package/acceptance/r40/desktop-live-input.mjs +128 -0
  7. package/acceptance/r40/desktop-live-observe.mjs +100 -0
  8. package/acceptance/r40/desktop-live-uia.mjs +121 -0
  9. package/bin/appcontainer-stage.obj +0 -0
  10. package/bin/bootstrap-advapi32.obj +0 -0
  11. package/bin/bootstrap-exitcode.obj +0 -0
  12. package/bin/bootstrap-kernel32.obj +0 -0
  13. package/bin/child-control-probe.obj +0 -0
  14. package/bin/child-control-stage.obj +0 -0
  15. package/bin/contained-reverse-worker.obj +0 -0
  16. package/bin/contained-transform-worker.obj +0 -0
  17. package/bin/containment-probe.obj +0 -0
  18. package/bin/deadbyte-contain.obj +0 -0
  19. package/bin/deadbyte-desktop-input-r40.exe +0 -0
  20. package/bin/deadbyte-desktop-input-r40.obj +0 -0
  21. package/bin/deadbyte-desktop-observer-r40.exe +0 -0
  22. package/bin/deadbyte-desktop-observer-r40.obj +0 -0
  23. package/bin/deadbyte-desktop-uia-r40.exe +0 -0
  24. package/bin/deadbyte-desktop-uia-r40.obj +0 -0
  25. package/bin/deadbyte-exec.obj +0 -0
  26. package/bin/deadbyte-process-host.obj +0 -0
  27. package/bin/deadbyte-tunnel-host.obj +0 -0
  28. package/controller/README.TXT +7 -5
  29. package/controller/deadbyte-controller.config.psd1.example +3 -0
  30. package/controller/deadbyte-controller.ps1 +149 -4
  31. package/controller/deadbyte-desktop-policy.json +41 -0
  32. package/controller/deadbyte-process-policy.json +4 -4
  33. package/docs/ARCHITECTURE.md +6 -1
  34. package/docs/superpowers/specs/2026-09-19-r40-desktop-computer-use-design.md +214 -0
  35. package/docs/superpowers/specs/2026-09-20-r41-deterministic-memory-design.md +132 -0
  36. package/native/deadbyte-desktop-input.cpp +455 -0
  37. package/native/deadbyte-desktop-observer.cpp +253 -0
  38. package/native/deadbyte-desktop-uia.cpp +307 -0
  39. package/package.json +12 -8
  40. package/proof/CONTAINMENT-BUILD.txt +6 -6
  41. package/scripts/build-containment.ps1 +24 -14
  42. package/scripts/build-desktop-r40.ps1 +112 -0
  43. package/scripts/deferred-slot-operation-r40.mjs +126 -0
  44. package/scripts/deferred-slot-operation-r41.mjs +127 -0
  45. package/scripts/final-closure-r40.mjs +114 -0
  46. package/scripts/final-closure-r41.mjs +116 -0
  47. package/scripts/final-closure-verify-r40.mjs +212 -0
  48. package/scripts/final-closure-verify-r41.mjs +215 -0
  49. package/scripts/gate-windows-r40.ps1 +43 -0
  50. package/scripts/gate-windows-r41.ps1 +48 -0
  51. package/scripts/init-desktop-policy-r40.ps1 +85 -0
  52. package/scripts/r40-compact-ledger-probe.mjs +4 -0
  53. package/scripts/release-parity-r40.mjs +212 -0
  54. package/scripts/release-parity-r41.mjs +221 -0
  55. package/scripts/release-parity-tests-r40.ps1 +9 -0
  56. package/scripts/release-parity-tests-r41.ps1 +9 -0
  57. package/scripts/verify-memory-r41.mjs +88 -0
  58. package/scripts/verify-r41-parent.mjs +61 -0
  59. package/scripts/windows-gate-evidence-r40.mjs +52 -0
  60. package/scripts/windows-gate-evidence-r41.mjs +53 -0
  61. package/src/autonomous-context-engine.mjs +3 -1
  62. package/src/autonomous-planner-contracts.mjs +19 -1
  63. package/src/autonomous-planner.mjs +24 -0
  64. package/src/autonomous-runtime.mjs +164 -25
  65. package/src/capability-ledger.mjs +6 -1
  66. package/src/compact-gateway-mcp-tools.mjs +14 -2
  67. package/src/deadbyte-cli.mjs +72 -44
  68. package/src/desktop-contract.mjs +263 -0
  69. package/src/desktop-input-r40.mjs +148 -0
  70. package/src/desktop-mcp-tools-r40.mjs +126 -0
  71. package/src/desktop-memory-r40.mjs +272 -0
  72. package/src/desktop-observer-r40.mjs +231 -0
  73. package/src/desktop-policy-r40.mjs +110 -0
  74. package/src/desktop-runtime-r40.mjs +318 -0
  75. package/src/desktop-uia-r40.mjs +123 -0
  76. package/src/mcp-server.mjs +87 -19
  77. package/src/memory-r41.mjs +692 -0
  78. package/src/r40-compact-disarmed-probe.mjs +71 -0
  79. package/src/r40-full-surface-probe.mjs +34 -0
  80. package/src/release-generation.mjs +38 -5
  81. package/src/remote-console.mjs +41 -0
  82. package/src/remote-live-log.mjs +208 -45
  83. package/src/remote-mcp-desktop-r40-smoke-client.mjs +70 -0
  84. package/src/remote-mcp-r40-parity-client.mjs +200 -0
  85. package/src/remote-mcp-smoke-client.mjs +20 -6
  86. package/src/remote-result-journal.mjs +10 -2
  87. package/src/runtime-update.mjs +55 -17
  88. package/src/tool-audit.mjs +29 -2
  89. package/src/version.mjs +1 -1
  90. package/test/autonomous-capability-r36.test.mjs +43 -1
  91. package/test/autonomous-desktop-r40.test.mjs +188 -0
  92. package/test/capability-ledger-r36.test.mjs +1 -0
  93. package/test/cli-entrypoint.test.mjs +1 -1
  94. package/test/compact-catalog-r36.test.mjs +2 -2
  95. package/test/compact-gateway-r36.test.mjs +56 -4
  96. package/test/compact-max-catalog-r40.test.mjs +95 -0
  97. package/test/controller-desktop-r40.test.mjs +86 -0
  98. package/test/core.test.mjs +1 -1
  99. package/test/desktop-adversarial-r40.test.mjs +62 -0
  100. package/test/desktop-contract-r40.test.mjs +200 -0
  101. package/test/desktop-input-r40.test.mjs +63 -0
  102. package/test/desktop-mcp-tools-r40.test.mjs +61 -0
  103. package/test/desktop-memory-r40.test.mjs +141 -0
  104. package/test/desktop-observer-r40.test.mjs +119 -0
  105. package/test/desktop-policy-r40.test.mjs +111 -0
  106. package/test/desktop-runtime-r40.test.mjs +278 -0
  107. package/test/desktop-uia-r40.test.mjs +42 -0
  108. package/test/full-max-catalog-r40.test.mjs +91 -0
  109. package/test/helpers/autonomous-r34-fixture.mjs +3 -3
  110. package/test/memory-autonomous-integration-r41.test.mjs +31 -0
  111. package/test/memory-history-r41.test.mjs +126 -0
  112. package/test/memory-projections-r41.test.mjs +92 -0
  113. package/test/memory-retrieval-r41.test.mjs +124 -0
  114. package/test/memory-snapshot-r41.test.mjs +106 -0
  115. package/test/r33-closeout-regression.test.mjs +7 -7
  116. package/test/r33-finalization.test.mjs +15 -15
  117. package/test/r37-remote-tool-call-timeline.test.mjs +6 -5
  118. package/test/r40-finalization.test.mjs +118 -0
  119. package/test/r41-finalization.test.mjs +38 -0
  120. package/test/release-generation.test.mjs +41 -9
  121. package/test/release-version.test.mjs +20 -61
  122. package/test/remote-console-r40.test.mjs +38 -0
  123. package/test/remote-live-log-r37.test.mjs +89 -32
  124. package/test/remote-r24-catalog.test.mjs +12 -3
  125. package/test/remote-result-journal.test.mjs +15 -0
  126. package/test/remote-session-cli.test.mjs +69 -46
  127. package/test/runtime-self-update.test.mjs +44 -0
@@ -339,15 +339,16 @@ function normalizeGoal(policy, { submissionId, rootId, title = '', goal, accepta
339
339
  return Object.freeze({ ...body, goal_sha256:sha256Object(body) });
340
340
  }
341
341
 
342
- function configuredCapabilityManifest({machineFsRuntime,observationRuntime,processRuntime,semanticRuntime}) {
342
+ function configuredCapabilityManifest({machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime}) {
343
343
  const plannerReachable=id => id === 'coding.stat' || id === 'coding.search' || id === 'coding.files_read' ||
344
344
  id.startsWith('semantic.') || id.startsWith('native_diff.') || id.startsWith('process.') ||
345
- id.startsWith('machine_fs.') || id.startsWith('observation.') || id === 'autonomous.release_gate';
345
+ id.startsWith('machine_fs.') || id.startsWith('observation.') || id.startsWith('desktop.') || id === 'autonomous.release_gate';
346
346
  const runtimeEnabled=entry => {
347
347
  if (entry.runtime_flag === 'DEADBYTE_CODING_RUNTIME' || entry.runtime_flag === 'DEADBYTE_AUTONOMOUS_RUNTIME') return true;
348
348
  if (entry.runtime_flag === 'DEADBYTE_MACHINE_FS_RUNTIME') return Boolean(machineFsRuntime);
349
349
  if (entry.runtime_flag === 'DEADBYTE_PROCESS_RUNTIME') return Boolean(processRuntime);
350
350
  if (entry.runtime_flag === 'DEADBYTE_OBSERVATION_RUNTIME') return Boolean(observationRuntime);
351
+ if (entry.runtime_flag === 'DEADBYTE_DESKTOP_RUNTIME') return Boolean(desktopRuntime);
351
352
  return entry.runtime_flag === null;
352
353
  };
353
354
  const entries=R36_CAPABILITY_LEDGER.entries
@@ -359,19 +360,24 @@ function configuredCapabilityManifest({machineFsRuntime,observationRuntime,proce
359
360
  entries:Object.freeze(entries)});
360
361
  }
361
362
 
362
- async function plannerView(goal, state, events, codingRuntime, capabilityManifest) {
363
+ async function plannerView(goal, state, events, codingRuntime, capabilityManifest, desktopMemoryProvider=null,memoryProvider=null) {
363
364
  const tree = await codingRuntime.tree({ rootId:goal.root_id, path:'.', maxDepth:4, maxEntries:600 });
364
365
  const memory=deriveAgentMemory(events,{maxArchival:24});
366
+ const desktopMemory=desktopMemoryProvider?await desktopMemoryProvider.plannerContext():null;
367
+ const codingAuthority=memoryProvider?await codingRuntime.sessionStatus():null;
368
+ const longTerm=memoryProvider?await memoryProvider.refresh({goal,events,currentPlan:state.active_plan,currentFiles:[],currentSymbols:[],
369
+ currentAuthority:{coding:{armed:codingAuthority.armed,reason:codingAuthority.reason}}}):null;
365
370
  return { mutation_epoch:state.mutation_epoch, planner_round:state.planner_round, tree:tree.entries,
366
371
  contexts:state.contexts.slice(-16), observations:state.observations.slice(-24), active_plan:state.active_plan,
367
- capabilities:capabilityManifest, project_memory:memory,
372
+ capabilities:capabilityManifest, project_memory:memory, desktop_memory:desktopMemory,
373
+ long_term_memory:longTerm?.planner_context??null,memory_evidence:longTerm,
368
374
  recent_decisions:state.decisions.slice(-8).map(item => ({ planner_round:item.planner_round,
369
375
  action:item.decision?.action, summary:item.decision?.summary })) };
370
376
  }
371
377
  function requestIdFor(goalId, plannerRound, journalHead) {
372
378
  return sha256Object({ schema:'deadbyte.autonomous-planner-request.v1', goal_id:goalId, planner_round:plannerRound, journal_head_sha256:journalHead });
373
379
  }
374
- async function requestPlanner(ctx, goal, events, state, policy, codingRuntime, capabilityManifest, signingKeyPath) {
380
+ async function requestPlanner(ctx, goal, events, state, policy, codingRuntime, capabilityManifest, desktopMemoryProvider,memoryProvider, signingKeyPath) {
375
381
  if (state.pending_request) return state.pending_request;
376
382
  const round = state.planner_round + 1;
377
383
  if (round > goal.max_iterations) {
@@ -382,7 +388,7 @@ async function requestPlanner(ctx, goal, events, state, policy, codingRuntime, c
382
388
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{ reason:'wall_time_limit', max_wall_ms:policy.limits.max_wall_ms });
383
389
  return null;
384
390
  }
385
- const view = await plannerView(goal,state,events,codingRuntime,capabilityManifest);
391
+ const view = await plannerView(goal,state,events,codingRuntime,capabilityManifest,desktopMemoryProvider,memoryProvider);
386
392
  let prompt = buildPlannerPrompt({ goal:{ title:goal.title, goal:goal.goal, acceptance:goal.acceptance }, policy, view });
387
393
  const repair = [...(state.planner_rejections ?? [])].reverse().find(item => item.planner_round === round) ?? null;
388
394
  if (repair) {
@@ -395,6 +401,14 @@ Repair only the decision contract. Return one corrected strict JSON decision; do
395
401
  const requestId = requestIdFor(goal.goal_id,round,state.journal_head_sha256);
396
402
  const payload = { request_id:requestId, planner_round:round, mutation_epoch:state.mutation_epoch,
397
403
  prompt, prompt_sha256:sha256Bytes(Buffer.from(prompt,'utf8')), backend:policy.planner.backend,
404
+ ...(view.memory_evidence?{
405
+ working_memory_sha256:view.memory_evidence.working_memory_sha256,
406
+ memory_snapshot_sha256:view.memory_evidence.snapshot_sha256,
407
+ memory_index_sha256:view.memory_evidence.index_sha256,
408
+ historical_archive_sha256:view.memory_evidence.historical_archive_sha256,
409
+ historical_index_sha256:view.memory_evidence.historical_index_sha256,
410
+ memory_source_release_manifest:view.memory_evidence.source_release_manifest
411
+ }:{}),
398
412
  ...(repair ? { repair_of_request_id:repair.request_id, rejection_event_sha256:repair.event_sha256 } : {}) };
399
413
  await appendEvent(ctx,events,signingKeyPath,'planner_requested',payload);
400
414
  return payload;
@@ -511,7 +525,10 @@ async function requestProviderWithCircuit({ctx,events,goal,policy,pending,signin
511
525
  provider_id:providerId,request_id:pending.request_id,failure_class:classifyProviderFailure(error),
512
526
  probe:disposition.probe===true
513
527
  });
514
- circuit=providerCircuitSnapshot(policy,events);
528
+ // Bind the transition to the durable failure event's own timestamp. A short OPEN
529
+ // interval must not expire inside the same run before the caller observes the pause.
530
+ const failureObservedAt=events.at(-1)?.created_at_utc;
531
+ circuit=providerCircuitSnapshot(policy,events,failureObservedAt);
515
532
  if (circuit.state==='OPEN'||circuit.state==='UNAVAILABLE') {
516
533
  const reason=circuit.state==='UNAVAILABLE'?'provider_circuit_unavailable':'provider_circuit_open';
517
534
  return {waiting:await enterProviderCircuitWait({ctx,events,goal,policy,signingKeyPath,reason,circuit})};
@@ -519,9 +536,9 @@ async function requestProviderWithCircuit({ctx,events,goal,policy,pending,signin
519
536
  throw error;
520
537
  }
521
538
  }
522
- async function acceptPlannerDecision({ ctx, events, goal, state, policy, codingRuntime, capabilityManifest, signingKeyPath, plannerResponse }) {
539
+ async function acceptPlannerDecision({ ctx, events, goal, state, policy, codingRuntime, capabilityManifest, desktopMemoryProvider,memoryProvider, signingKeyPath, plannerResponse }) {
523
540
  let currentState = state;
524
- let pending = currentState.pending_request ?? await requestPlanner(ctx,goal,events,currentState,policy,codingRuntime,capabilityManifest,signingKeyPath);
541
+ let pending = currentState.pending_request ?? await requestPlanner(ctx,goal,events,currentState,policy,codingRuntime,capabilityManifest,desktopMemoryProvider,memoryProvider,signingKeyPath);
525
542
  if (!pending) return null;
526
543
  let suppliedResponse = plannerResponse;
527
544
  while (pending) {
@@ -560,7 +577,7 @@ async function acceptPlannerDecision({ ctx, events, goal, state, policy, codingR
560
577
  return { needs_planner:false, rejected:true, paused:true };
561
578
  }
562
579
  currentState = deriveState(goal,events);
563
- pending = await requestPlanner(ctx,goal,events,currentState,policy,codingRuntime,capabilityManifest,signingKeyPath);
580
+ pending = await requestPlanner(ctx,goal,events,currentState,policy,codingRuntime,capabilityManifest,desktopMemoryProvider,memoryProvider,signingKeyPath);
564
581
  if (!pending) return null;
565
582
  if (policy.planner.backend === 'client_sampling') return { needs_planner:true, request:pending };
566
583
  continue;
@@ -568,6 +585,12 @@ async function acceptPlannerDecision({ ctx, events, goal, state, policy, codingR
568
585
  const event = await appendEvent(ctx,events,signingKeyPath,'planner_decision',{
569
586
  request_id:pending.request_id, planner_round:pending.planner_round, mutation_epoch:pending.mutation_epoch,
570
587
  backend:response.backend, model:response.model ?? 'unknown', response_sha256:sha256Bytes(Buffer.from(response.raw_text,'utf8')),
588
+ ...(pending.working_memory_sha256?{
589
+ working_memory_sha256:pending.working_memory_sha256,memory_snapshot_sha256:pending.memory_snapshot_sha256,
590
+ memory_index_sha256:pending.memory_index_sha256,
591
+ historical_archive_sha256:pending.historical_archive_sha256,historical_index_sha256:pending.historical_index_sha256,
592
+ memory_source_release_manifest:pending.memory_source_release_manifest
593
+ }:{}),
571
594
  decision
572
595
  });
573
596
  return { needs_planner:false, event, decision };
@@ -599,7 +622,7 @@ async function executeInspect({ ctx, events, goal, decisionEvent, decision, codi
599
622
  return { status:'completed', contexts };
600
623
  }
601
624
 
602
- const DELEGATED_MUTATIONS = new Set(['process_start','process_action','process_terminate','observation_search_cancel']);
625
+ const DELEGATED_MUTATIONS = new Set(['process_start','process_action','process_terminate','observation_search_cancel','desktop_action']);
603
626
  const CAPABILITY_BY_ACTION=Object.freeze({
604
627
  search:'coding.search',stat:'coding.stat',multi_read:'coding.files_read',
605
628
  semantic_outline:'semantic.outline',semantic_definition:'semantic.definition',semantic_references:'semantic.references',
@@ -609,7 +632,8 @@ const CAPABILITY_BY_ACTION=Object.freeze({
609
632
  machine_fs_stat:'machine_fs.stat',machine_fs_list:'machine_fs.list',machine_fs_read:'machine_fs.read',machine_fs_mkdir:'machine_fs.mkdir',machine_fs_move:'machine_fs.move',machine_fs_delete:'machine_fs.delete',
610
633
  machine_stat:'machine_fs.stat',machine_list:'machine_fs.list',machine_read:'machine_fs.read',
611
634
  observation_search_start:'observation.search_start',observation_search_status:'observation.search_status',observation_search_page:'observation.search_page',observation_search_cancel:'observation.search_cancel',
612
- observation_process_list:'observation.process_list',observation_system_status:'observation.system_status'
635
+ observation_process_list:'observation.process_list',observation_system_status:'observation.system_status',
636
+ desktop_status:'desktop.status',desktop_observe:'desktop.observe',desktop_target:'desktop.target',desktop_action:'desktop.action'
613
637
  });
614
638
  function capabilityIdForOperation(operation){return CAPABILITY_BY_ACTION[operation?.kind]??null;}
615
639
  function assertDelegatedIdentity(events, operation) {
@@ -623,9 +647,27 @@ function assertDelegatedIdentity(events, operation) {
623
647
  event.payload?.operation?.kind === 'process_start' && event.payload?.result?.session_id === operation.session_id);
624
648
  if (!owned) throw new Error(`delegated process session '${operation.session_id}' is stale or belongs to another goal`);
625
649
  }
650
+ if(operation.kind==='desktop_target'){
651
+ const owned=events.some(event=>event.type==='delegated_action_completed'&&
652
+ event.payload?.operation?.kind==='desktop_observe'&&event.payload?.result?.frame?.frame_id===operation.frame_id);
653
+ if(!owned) throw new Error(`desktop frame '${operation.frame_id}' was not freshly observed by this goal`);
654
+ }
655
+ if(operation.kind==='desktop_action'){
656
+ const frameOwned=events.some(event=>event.type==='delegated_action_completed'&&
657
+ ['desktop_observe','desktop_target'].includes(event.payload?.operation?.kind)&&
658
+ event.payload?.result?.frame?.frame_id===operation.expected_frame_id);
659
+ if(!frameOwned) throw new Error(`desktop action frame '${operation.expected_frame_id}' was not observed or grounded by this goal`);
660
+ if(operation.target_id!==null){
661
+ const targetOwned=events.some(event=>event.type==='delegated_action_completed'&&
662
+ event.payload?.operation?.kind==='desktop_target'&&
663
+ event.payload?.result?.target?.target_id===operation.target_id&&
664
+ event.payload?.result?.frame?.frame_id===operation.expected_frame_id);
665
+ if(!targetOwned) throw new Error(`desktop target '${operation.target_id}' is stale or belongs to another goal`);
666
+ }
667
+ }
626
668
  }
627
- async function invokeDelegatedOperation(goal, operation, runtimes) {
628
- const { codingRuntime, semanticRuntime, nativeDiffRuntime, machineFsRuntime, observationRuntime, processRuntime } = runtimes;
669
+ async function invokeDelegatedOperation(goal, operation, runtimes, desktopContext=null) {
670
+ const { codingRuntime, semanticRuntime, nativeDiffRuntime, machineFsRuntime, observationRuntime, processRuntime, desktopRuntime } = runtimes;
629
671
  switch (operation.kind) {
630
672
  case 'stat':
631
673
  return codingRuntime.stat({rootId:goal.root_id,relativePath:operation.path,hash:operation.hash});
@@ -713,6 +755,33 @@ async function invokeDelegatedOperation(goal, operation, runtimes) {
713
755
  case 'process_terminate':
714
756
  if (!processRuntime) throw new Error('process runtime unavailable');
715
757
  return processRuntime.terminate({ sessionId:operation.session_id });
758
+ case 'desktop_status':
759
+ if(!desktopRuntime) throw new Error('desktop runtime unavailable');
760
+ return desktopRuntime.status();
761
+ case 'desktop_observe':
762
+ if(!desktopRuntime) throw new Error('desktop runtime unavailable');
763
+ return desktopRuntime.observe({preview:false});
764
+ case 'desktop_target':
765
+ if(!desktopRuntime) throw new Error('desktop runtime unavailable');
766
+ return desktopRuntime.ground({frameId:operation.frame_id,query:operation.uia_query});
767
+ case 'desktop_action': {
768
+ if(!desktopRuntime) throw new Error('desktop runtime unavailable');
769
+ if(!desktopContext) throw new Error('desktop autonomous effect context missing');
770
+ const result=await desktopRuntime.action({
771
+ intentId:desktopContext.intentId,kind:operation.action_kind,expectedFrameId:operation.expected_frame_id,
772
+ targetId:operation.target_id,point:operation.point,scrollDelta:operation.scroll_delta,
773
+ keyChord:operation.key_chord,text:operation.text,effectContext:desktopContext.effectContext
774
+ });
775
+ const {action,...rest}=result;
776
+ return Object.freeze({...rest,action_summary:Object.freeze({
777
+ schema:'deadbyte.desktop-action-summary.v1',intent_id:action.intent_id,kind:action.kind,
778
+ frame_id:action.frame_id,desktop_epoch:action.desktop_epoch,topology_sha256:action.topology_sha256,
779
+ expected_window:action.expected_window,target_id:action.target_id,point:action.point,
780
+ scroll_delta:action.scroll_delta,key_chord:action.key_chord,text_sha256:action.text_sha256,
781
+ ...(action.kind==='text_input'?{text_bytes:Buffer.byteLength(action.text??'','utf8')}:{}),
782
+ action_sha256:action.action_sha256
783
+ })});
784
+ }
716
785
  default: throw new Error(`unsupported delegated operation '${String(operation.kind)}'`);
717
786
  }
718
787
  }
@@ -735,6 +804,27 @@ async function verifyDelegatedEvidence(operation, result, runtimes, verifyKeyPat
735
804
  journal_head_sha256:checked.head_sha256 };
736
805
  }
737
806
  }
807
+ if(operation.kind.startsWith('desktop_')&&operation.kind!=='desktop_status'){
808
+ if(!runtimes.desktopRuntime?.verifyReceipt) throw new Error('desktop receipt verifier unavailable');
809
+ const refs=[];
810
+ if(operation.kind==='desktop_observe'&&result?.receipt_id) refs.push([result.receipt_id,result.receipt_sha256,'desktop_observation']);
811
+ if(operation.kind==='desktop_target'&&result?.grounding?.receipt_id) refs.push([result.grounding.receipt_id,result.grounding.receipt_sha256,'desktop_grounding']);
812
+ if(operation.kind==='desktop_action'){
813
+ refs.push(
814
+ [result?.started_receipt_id,result?.started_receipt_sha256,'desktop_action_started'],
815
+ [result?.post_receipt_id,result?.post_receipt_sha256,'desktop_post_observation'],
816
+ [result?.receipt_id,result?.receipt_sha256,'desktop_action_completed']
817
+ );
818
+ }
819
+ if(refs.length<1||refs.some(([id,sha])=>typeof id!=='string'||!SHA256_RE.test(sha??''))) throw new Error('desktop delegated evidence references missing');
820
+ const verified=[];
821
+ for(const [id,sha,kind] of refs){
822
+ const proof=await runtimes.desktopRuntime.verifyReceipt({receiptId:id});
823
+ if(!proof.ok||proof.receipt_sha256!==sha||proof.kind!==kind) throw new Error('desktop delegated receipt mismatch');
824
+ verified.push({receipt_id:id,receipt_sha256:sha,kind});
825
+ }
826
+ return {kind:'desktop_receipts',receipts:verified,result_sha256:sha256Object(result)};
827
+ }
738
828
  return { kind:'runtime_result', result_sha256:sha256Object(result) };
739
829
  }
740
830
  async function executeDelegate({ ctx, events, goal, decisionEvent, decision, policy, runtimes, assertRunAuthority,
@@ -742,6 +832,22 @@ async function executeDelegate({ ctx, events, goal, decisionEvent, decision, pol
742
832
  const capabilityId=capabilityIdForOperation(decision.operation);
743
833
  if(!capabilityId) throw new Error(`unsupported typed capability action '${String(decision.operation?.kind)}'`);
744
834
  const actionKey = `capability-${decisionEvent.event_sha256}`;
835
+ if(decision.operation.kind==='desktop_action'){
836
+ if(!runtimes.desktopRuntime) throw new Error('desktop runtime unavailable');
837
+ const desktopStatus=await runtimes.desktopRuntime.status();
838
+ if(!desktopStatus.armed||!desktopStatus.action_kinds.includes(decision.operation.action_kind)){
839
+ if(!events.some(event=>event.type==='waiting_entered'&&event.payload?.reason==='desktop_authority_unavailable')){
840
+ await appendEvent(ctx,events,signingKeyPath,'waiting_entered',{
841
+ reason:'desktop_authority_unavailable',requires_approval:true,resume_phase:'ACT',
842
+ desktop_action_kind:decision.operation.action_kind
843
+ });
844
+ }
845
+ await appendEvent(ctx,events,signingKeyPath,'goal_paused',{
846
+ reason:'desktop_authority_unavailable',desktop_action_kind:decision.operation.action_kind
847
+ });
848
+ return {status:'paused',reason:'desktop_authority_unavailable'};
849
+ }
850
+ }
745
851
  const prior = [...events].reverse().find(event => event.type === 'delegated_action_completed' && event.payload?.action_key === actionKey);
746
852
  if (prior) return { status:'completed', result:prior.payload.result, existing:true };
747
853
  const started = [...events].reverse().find(event => event.type === 'delegated_action_started' && event.payload?.action_key === actionKey);
@@ -755,7 +861,20 @@ async function executeDelegate({ ctx, events, goal, decisionEvent, decision, pol
755
861
  try {
756
862
  assertDelegatedIdentity(events,decision.operation);
757
863
  if (DELEGATED_MUTATIONS.has(decision.operation.kind)) await assertRunAuthority(goal.root_id);
758
- const result = await invokeDelegatedOperation(goal,decision.operation,runtimes);
864
+ let desktopContext=null;
865
+ if(decision.operation.kind==='desktop_action'){
866
+ const loop=deriveLoopState(goal,events);
867
+ const current=deriveState(goal,events);
868
+ desktopContext={
869
+ intentId:sha256Object({schema:'deadbyte.autonomous-desktop-intent.v1',goal_id:goal.goal_id,
870
+ decision_event_sha256:decisionEvent.event_sha256,operation:decision.operation}),
871
+ effectContext:{
872
+ goalId:goal.goal_id,planId:loop.plan_id,stepId:loop.current_step?.step_id??'desktop',
873
+ mutationEpoch:current.mutation_epoch,observationHeadSha256:decision.operation.expected_frame_id
874
+ }
875
+ };
876
+ }
877
+ const result = await invokeDelegatedOperation(goal,decision.operation,runtimes,desktopContext);
759
878
  if (Buffer.byteLength(canonicalJson(result),'utf8') > policy.limits.max_context_bytes) {
760
879
  throw new Error('delegated result exceeds autonomous context bound');
761
880
  }
@@ -764,6 +883,23 @@ async function executeDelegate({ ctx, events, goal, decisionEvent, decision, pol
764
883
  decision_event_sha256:decisionEvent.event_sha256, operation:decision.operation, result, evidence });
765
884
  return { status:'completed', result, evidence };
766
885
  } catch (error) {
886
+ if(decision.operation.kind==='desktop_action'){
887
+ const sideEffectState=error?.side_effect_state??null;
888
+ const reason=sideEffectState==='unknown'?'desktop_outcome_unknown':
889
+ sideEffectState==='not_started'?'desktop_effect_not_started':'desktop_action_failed';
890
+ const resumePhase=sideEffectState==='unknown'?'CRITIC':'ACT';
891
+ if(!events.some(event=>event.type==='waiting_entered'&&event.payload?.reason===reason)){
892
+ await appendEvent(ctx,events,signingKeyPath,'waiting_entered',{
893
+ reason,requires_approval:true,resume_phase:resumePhase,
894
+ receipt_id:error?.receipt_id??null,receipt_sha256:error?.receipt_sha256??null
895
+ });
896
+ }
897
+ await appendEvent(ctx,events,signingKeyPath,'goal_paused',{
898
+ reason,action_key:actionKey,operation_kind:decision.operation.kind,side_effect_state:sideEffectState,
899
+ receipt_id:error?.receipt_id??null,receipt_sha256:error?.receipt_sha256??null,detail:truncated(error)
900
+ });
901
+ return {status:'paused',reason,side_effect_state:sideEffectState};
902
+ }
767
903
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{ reason:'delegated_action_failed', action_key:actionKey,
768
904
  operation_kind:decision.operation.kind, detail:truncated(error) });
769
905
  return { status:'paused', reason:'delegated_action_failed' };
@@ -1195,7 +1331,7 @@ function r34ReasonHash(goal,decisionEvent,reason) {
1195
1331
  decision_event_sha256:decisionEvent.event_sha256,reason:String(reason ?? '')});
1196
1332
  }
1197
1333
  async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,policy,codingRuntime,
1198
- nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,
1334
+ nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime,assertRunAuthority,
1199
1335
  signingKeyPath,verifyKeyPath,workerScheduler}) {
1200
1336
  let loop=deriveLoopState(goal,events);
1201
1337
  if (decision.kind === 'plan_create') {
@@ -1258,7 +1394,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1258
1394
  } else if (decision.action.kind === 'delegate') {
1259
1395
  outcome=await executeDelegate({ctx,events,goal,decisionEvent,
1260
1396
  decision:{operation:decision.action.operation},policy,
1261
- runtimes:{codingRuntime,semanticRuntime,nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime},assertRunAuthority,signingKeyPath,verifyKeyPath});
1397
+ runtimes:{codingRuntime,semanticRuntime,nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,desktopRuntime},assertRunAuthority,signingKeyPath,verifyKeyPath});
1262
1398
  } else if (decision.action.kind === 'native_diff_apply') {
1263
1399
  await assertRunAuthority(goal.root_id);
1264
1400
  outcome=await executePreparedDiff({ctx,events,goal,state,decisionEvent,diffId:decision.action.diff_id,
@@ -1287,7 +1423,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1287
1423
  } else if (capabilityIdForOperation(decision.action)) {
1288
1424
  outcome=await executeDelegate({ctx,events,goal,decisionEvent,
1289
1425
  decision:{operation:decision.action},policy,
1290
- runtimes:{codingRuntime,semanticRuntime,nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime},assertRunAuthority,signingKeyPath,verifyKeyPath});
1426
+ runtimes:{codingRuntime,semanticRuntime,nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,desktopRuntime},assertRunAuthority,signingKeyPath,verifyKeyPath});
1291
1427
  } else {
1292
1428
  throw new Error(`unsupported R34 action '${String(decision.action.kind)}'`);
1293
1429
  }
@@ -1391,12 +1527,12 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1391
1527
  }
1392
1528
 
1393
1529
  async function executeDecisionCore({ ctx, events, goal, state, decisionEvent, policy, codingRuntime,
1394
- nativeDiffRuntime, machineFsRuntime, observationRuntime, processRuntime, semanticRuntime, assertRunAuthority,
1530
+ nativeDiffRuntime, machineFsRuntime, observationRuntime, processRuntime, semanticRuntime, desktopRuntime, assertRunAuthority,
1395
1531
  signingKeyPath, verifyKeyPath, workerScheduler }) {
1396
1532
  const decision = decisionEvent.decision;
1397
1533
  if (decision?.schema === 'deadbyte.autonomous-decision.v2') {
1398
1534
  const outcome=await executeR34Decision({ctx,events,goal,state,decisionEvent,decision,policy,codingRuntime,
1399
- nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,
1535
+ nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime,assertRunAuthority,
1400
1536
  signingKeyPath,verifyKeyPath,workerScheduler});
1401
1537
  await appendEvent(ctx,events,signingKeyPath,'decision_completed',{
1402
1538
  decision_event_sha256:decisionEvent.event_sha256,action:decision.kind,
@@ -1463,6 +1599,7 @@ function effectDescriptor(goal,state,events,decisionEvent){
1463
1599
  if(decision?.schema==='deadbyte.autonomous-decision.v2'&&decision.kind==='act'){
1464
1600
  const loop=deriveLoopState(goal,events);
1465
1601
  if(!loop.plan_id||!loop.current_step?.step_id) return null;
1602
+ if(String(decision.action?.kind??'').startsWith('desktop_')) return null;
1466
1603
  action=decision.action;
1467
1604
  coordinates={planId:loop.plan_id,stepId:loop.current_step.step_id};
1468
1605
  }else if(['patch','delegate','run_profile'].includes(decision?.action)){
@@ -1558,10 +1695,11 @@ function isAuthorityUnavailable(error) {
1558
1695
  }
1559
1696
 
1560
1697
  export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRuntime, machineFsRuntime = null,
1561
- observationRuntime = null, processRuntime = null, semanticRuntime = null, signingKeyPath, verifyKeyPath }) {
1698
+ observationRuntime = null, processRuntime = null, semanticRuntime = null, desktopRuntime = null,
1699
+ desktopMemoryProvider = null,memoryProvider=null, signingKeyPath, verifyKeyPath }) {
1562
1700
  if (!policy || !codingRuntime || !nativeDiffRuntime) throw new Error('autonomous runtime requires policy/coding/native-diff runtimes');
1563
1701
  if (!signingKeyPath || !verifyKeyPath) throw new Error('autonomous runtime requires trust keys');
1564
- const capabilityManifest=configuredCapabilityManifest({machineFsRuntime,observationRuntime,processRuntime,semanticRuntime});
1702
+ const capabilityManifest=configuredCapabilityManifest({machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime});
1565
1703
  const profileTimeoutCeiling=Math.max(120000,...Object.values(policy.profiles??{}).map(profile=>
1566
1704
  Number.isInteger(profile?.timeout_ms)&&profile.timeout_ms>0?profile.timeout_ms+120000:120000));
1567
1705
  const workerScheduler=createWorkerScheduler({maxConcurrent:2,totalCpuUnits:2,totalMemoryMb:2048,leaseMs:profileTimeoutCeiling});
@@ -1612,7 +1750,8 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1612
1750
  const journal = [];
1613
1751
  await appendEvent(ctx,journal,signingKeyPath,'goal_created',{
1614
1752
  submission_id:submissionId, root_id:rootId, title, goal_sha256:normalized.goal_sha256,
1615
- max_iterations:normalized.max_iterations
1753
+ max_iterations:normalized.max_iterations,
1754
+ ...(memoryProvider?{source_release_manifest:memoryProvider.source_release_manifest}:{})
1616
1755
  });
1617
1756
  return { status:'accepted', goal_id:goalId, goal_sha256:normalized.goal_sha256, state:'pending' };
1618
1757
  }
@@ -1782,7 +1921,7 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1782
1921
  try {
1783
1922
  outcome = await executeDecision({ ctx,events:journal,goal,state,
1784
1923
  decisionEvent:state.pending_decision,policy,codingRuntime,nativeDiffRuntime,machineFsRuntime,
1785
- observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,signingKeyPath,verifyKeyPath,workerScheduler });
1924
+ observationRuntime,processRuntime,semanticRuntime,desktopRuntime,assertRunAuthority,signingKeyPath,verifyKeyPath,workerScheduler });
1786
1925
  } catch (error) {
1787
1926
  const loop=loopStateOrNull(goal,journal);
1788
1927
  if (!loop || loop.pending_action || !isAuthorityUnavailable(error)) throw error;
@@ -1807,7 +1946,7 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1807
1946
  continue;
1808
1947
  }
1809
1948
  const accepted = await acceptPlannerDecision({ ctx,events:journal,goal,state,policy,codingRuntime,capabilityManifest,
1810
- signingKeyPath,plannerResponse:suppliedResponse });
1949
+ desktopMemoryProvider,memoryProvider,signingKeyPath,plannerResponse:suppliedResponse });
1811
1950
  suppliedResponse = null;
1812
1951
  if (accepted?.needs_planner) {
1813
1952
  state = deriveState(goal,journal);
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
 
3
3
  export const CAPABILITY_LEDGER_SCHEMA='deadbyte.capability-ledger.v1';
4
- const AUTHORITIES=new Set(['none','process','coding','autonomous','host']);
4
+ const AUTHORITIES=new Set(['none','process','coding','autonomous','desktop','host']);
5
5
  const PROFILE_ENV='DEADBYTE_CAPABILITY_PROFILE';
6
6
  const COMPACT_TOOL_LIMIT=42;
7
7
 
@@ -135,6 +135,11 @@ export const R36_CAPABILITY_ENTRIES=Object.freeze([
135
135
  gateway('observation.process_list','machine_process_list','machine_observe','process_list','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
136
136
  gateway('observation.system_status','machine_system_status','machine_observe','system_status','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
137
137
 
138
+ gateway('desktop.status','desktop_status','desktop_control','status','DEADBYTE_DESKTOP_RUNTIME','none',{receipt_class:'desktop'}),
139
+ gateway('desktop.observe','desktop_observe','desktop_control','observe','DEADBYTE_DESKTOP_RUNTIME','none',{receipt_class:'desktop'}),
140
+ gateway('desktop.target','desktop_target','desktop_control','target','DEADBYTE_DESKTOP_RUNTIME','none',{receipt_class:'desktop'}),
141
+ gateway('desktop.action','desktop_action','desktop_control','action','DEADBYTE_DESKTOP_RUNTIME','desktop',{mutating:true,receipt_class:'desktop'}),
142
+
138
143
  direct('autonomous.session_status','autonomous_session_status','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'autonomous'}),
139
144
  direct('native_diff.preview','native_diff_preview','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'native_diff'}),
140
145
  direct('native_diff.apply','native_diff_apply','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'native_diff'}),
@@ -1,5 +1,7 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import * as z from 'zod/v4';
2
3
  import { compactGatewayOutputSchema, compactGatewayResult } from './compact-gateway-output-contracts.mjs';
4
+ import { desktopControlInputSchema,invokeDesktopOperation } from './desktop-mcp-tools-r40.mjs';
3
5
 
4
6
  const id=z.string().regex(/^[A-Za-z0-9._-]{1,64}$/);
5
7
  const rel=z.string().min(1).max(2048);
@@ -117,12 +119,22 @@ async function machineObserve(args,machineRuntime,observationRuntime){
117
119
  return invoke(args.op,observationRuntime,'observation',map[args.op]);
118
120
  }
119
121
 
120
- export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime}){
122
+ export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime,desktopRuntime,catalogProvider}){
121
123
  if(!server) throw new Error('compact gateway registration requires server');
122
124
  if(profile!=='compact') return;
123
- server.registerTool('capability_manifest',{description:'Read the canonical R36 capability ledger and active compact profile.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>compactGatewayResult({status:'ok',op:'manifest',result:{schema:'deadbyte.capability-manifest.v1',profile,ledger_sha256:ledger?.ledger_sha256??null,capabilities:ledger?.entries??[]}},false));
125
+ if(typeof catalogProvider!=='function') throw new Error('compact gateway requires catalogProvider');
126
+ server.registerTool('capability_manifest',{description:'Read the canonical capability ledger and exact active compact tool catalog.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>{
127
+ const toolCatalog=[...catalogProvider()].map(String).sort();
128
+ if(toolCatalog.length<1||new Set(toolCatalog).size!==toolCatalog.length) throw new Error('compact catalog provider returned invalid catalog');
129
+ const catalogSha256=createHash('sha256').update(JSON.stringify(toolCatalog),'utf8').digest('hex');
130
+ return compactGatewayResult({status:'ok',op:'manifest',result:{
131
+ schema:'deadbyte.capability-manifest.v2',profile,ledger_sha256:ledger?.ledger_sha256??null,
132
+ tool_catalog:toolCatalog,tool_count:toolCatalog.length,catalog_sha256:catalogSha256,capabilities:ledger?.entries??[]
133
+ }},false);
134
+ });
124
135
  server.registerTool('coding_inspect',{description:'Typed compact coding inspection and semantic navigation gateway. No arbitrary tool dispatch.',inputSchema:codingInspectInputSchema,outputSchema:compactGatewayOutputSchema},args=>codingInspect(args,codingRuntime,semanticRuntime));
125
136
  server.registerTool('machine_fs',{description:'Typed compact machine filesystem gateway preserving root policy and mutation preconditions.',inputSchema:machineFsGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineFs(args,machineFsRuntime));
126
137
  server.registerTool('process_session',{description:'Typed compact DEADBYTE-owned process session gateway. No raw stdin or PID authority.',inputSchema:processSessionGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>processSession(args,processRuntime));
127
138
  server.registerTool('machine_observe',{description:'Typed compact machine identity and read-only observation gateway. Revoke is intentionally excluded.',inputSchema:machineObserveInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineObserve(args,machineRuntime,observationRuntime));
139
+ server.registerTool('desktop_control',{description:'Typed Desktop observe, target, status and guarded action gateway. No arbitrary dispatch; mutation still requires separate Desktop authority.',inputSchema:desktopControlInputSchema,outputSchema:compactGatewayOutputSchema},args=>invokeDesktopOperation(args,desktopRuntime));
128
140
  }