deadbyte-mcp 0.10.0 → 0.11.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 (70) hide show
  1. package/MANIFEST.SHA256 +69 -55
  2. package/README.txt +13 -14
  3. package/bin/WORKER-REGISTRY.txt +3 -3
  4. package/bin/appcontainer-stage.exe +0 -0
  5. package/bin/appcontainer-stage.obj +0 -0
  6. package/bin/bootstrap-advapi32.exe +0 -0
  7. package/bin/bootstrap-advapi32.obj +0 -0
  8. package/bin/bootstrap-exitcode.exe +0 -0
  9. package/bin/bootstrap-exitcode.obj +0 -0
  10. package/bin/bootstrap-kernel32.exe +0 -0
  11. package/bin/bootstrap-kernel32.obj +0 -0
  12. package/bin/child-control-probe.exe +0 -0
  13. package/bin/child-control-probe.obj +0 -0
  14. package/bin/child-control-stage.exe +0 -0
  15. package/bin/child-control-stage.obj +0 -0
  16. package/bin/contained-reverse-worker.exe +0 -0
  17. package/bin/contained-reverse-worker.obj +0 -0
  18. package/bin/contained-transform-worker.exe +0 -0
  19. package/bin/contained-transform-worker.obj +0 -0
  20. package/bin/containment-probe.exe +0 -0
  21. package/bin/containment-probe.obj +0 -0
  22. package/bin/deadbyte-contain.exe +0 -0
  23. package/bin/deadbyte-contain.obj +0 -0
  24. package/bin/deadbyte-exec.exe +0 -0
  25. package/bin/deadbyte-exec.obj +0 -0
  26. package/bin/deadbyte-process-host.exe +0 -0
  27. package/bin/deadbyte-process-host.obj +0 -0
  28. package/bin/deadbyte-tunnel-host.exe +0 -0
  29. package/bin/deadbyte-tunnel-host.obj +0 -0
  30. package/controller/README.TXT +3 -3
  31. package/controller/deadbyte-controller.ps1 +1 -1
  32. package/controller/deadbyte-process-policy.json +1 -1
  33. package/docs/ARCHITECTURE.md +1 -1
  34. package/package.json +1 -1
  35. package/scripts/deferred-slot-operation.mjs +1 -1
  36. package/scripts/final-closure-r36.mjs +113 -0
  37. package/scripts/final-closure-verify-r36.mjs +208 -0
  38. package/scripts/final-closure-verify.mjs +48 -48
  39. package/scripts/final-closure.mjs +13 -13
  40. package/scripts/gate-windows-r36.ps1 +42 -0
  41. package/scripts/gate-windows.ps1 +3 -3
  42. package/scripts/release-parity-r36.mjs +200 -0
  43. package/scripts/release-parity-tests.ps1 +2 -2
  44. package/scripts/release-parity.mjs +37 -37
  45. package/scripts/windows-gate-evidence-r36.mjs +52 -0
  46. package/scripts/windows-gate-evidence.mjs +5 -5
  47. package/src/agent-memory-plane.mjs +98 -0
  48. package/src/autonomous-output-contracts.mjs +5 -2
  49. package/src/autonomous-runtime.mjs +155 -31
  50. package/src/autonomous-timeout-recovery.mjs +27 -0
  51. package/src/deadbyte-cli.mjs +37 -76
  52. package/src/effect-ledger.mjs +47 -0
  53. package/src/observation-lease.mjs +32 -0
  54. package/src/remote-live-log.mjs +59 -0
  55. package/src/remote-mcp-autonomous-smoke-client.mjs +15 -9
  56. package/src/version.mjs +1 -1
  57. package/src/worker-scheduler.mjs +53 -0
  58. package/test/autonomous-output-contract.test.mjs +1 -1
  59. package/test/core.test.mjs +1 -1
  60. package/test/production-docs.test.mjs +5 -5
  61. package/test/r33-closeout-regression.test.mjs +4 -4
  62. package/test/r33-finalization.test.mjs +6 -6
  63. package/test/r36-finalization.test.mjs +5 -5
  64. package/test/r36-release-identity.test.mjs +12 -19
  65. package/test/r37-agent-fabric.test.mjs +92 -0
  66. package/test/r37-autonomous-timeout-recovery.test.mjs +60 -0
  67. package/test/r37-finalization.test.mjs +74 -0
  68. package/test/release-version.test.mjs +42 -36
  69. package/test/remote-live-log-r37.test.mjs +47 -0
  70. package/test/remote-session-cli.test.mjs +27 -50
@@ -12,6 +12,10 @@ import { judgeProgress, stallDisposition } from './autonomous-progress.mjs';
12
12
  import { classifyProviderFailure, deriveCircuit, providerCallDisposition, providerCircuitId } from './provider-circuit.mjs';
13
13
  import { verifyObservationReceiptFile } from './observation-runtime.mjs';
14
14
  import { R36_CAPABILITY_LEDGER } from './capability-ledger.mjs';
15
+ import { deriveAgentMemory } from './agent-memory-plane.mjs';
16
+ import { effectIdentity, loopGuardDisposition, bindEffectCompletion } from './effect-ledger.mjs';
17
+ import { createWorkerScheduler } from './worker-scheduler.mjs';
18
+ import { issueObservationLease, verifyObservationLease } from './observation-lease.mjs';
15
19
 
16
20
  export const AUTONOMOUS_GOAL_SCHEMA = 'deadbyte.autonomous-goal.v1';
17
21
  export const AUTONOMOUS_EVENT_SCHEMA = 'deadbyte.autonomous-event.v1';
@@ -164,6 +168,22 @@ async function acquireLock(ctx) {
164
168
  throw new Error('autonomous lock acquisition failed');
165
169
  }
166
170
  async function releaseLock(ctx) { await rm(ctx.lockPath,{force:true}); }
171
+ async function runLockStatus(ctx) {
172
+ let parsed;
173
+ try { parsed = JSON.parse(await readFile(ctx.lockPath,'utf8')); }
174
+ catch (error) {
175
+ if (error?.code === 'ENOENT') return { run_busy:false, run_owner_pid:null, run_lock_created_at_utc:null };
176
+ throw new Error('autonomous lock malformed');
177
+ }
178
+ if (parsed?.schema !== 'deadbyte.autonomous-lock.v1' || parsed?.goal_id !== path.basename(ctx.dir) ||
179
+ !Number.isInteger(parsed?.pid) || parsed.pid < 1 || typeof parsed?.created_at_utc !== 'string' || !parsed.created_at_utc) {
180
+ throw new Error('autonomous lock malformed');
181
+ }
182
+ const alive=await processExists(parsed.pid);
183
+ return alive
184
+ ? { run_busy:true, run_owner_pid:parsed.pid, run_lock_created_at_utc:parsed.created_at_utc }
185
+ : { run_busy:false, run_owner_pid:null, run_lock_created_at_utc:null };
186
+ }
167
187
  async function readCancel(ctx, verifyKeyPath) {
168
188
  if (!await exists(ctx.cancelPath)) return null;
169
189
  const parsed = JSON.parse(await readFile(ctx.cancelPath,'utf8'));
@@ -339,11 +359,12 @@ function configuredCapabilityManifest({machineFsRuntime,observationRuntime,proce
339
359
  entries:Object.freeze(entries)});
340
360
  }
341
361
 
342
- async function plannerView(goal, state, codingRuntime, capabilityManifest) {
362
+ async function plannerView(goal, state, events, codingRuntime, capabilityManifest) {
343
363
  const tree = await codingRuntime.tree({ rootId:goal.root_id, path:'.', maxDepth:4, maxEntries:600 });
364
+ const memory=deriveAgentMemory(events,{maxArchival:24});
344
365
  return { mutation_epoch:state.mutation_epoch, planner_round:state.planner_round, tree:tree.entries,
345
366
  contexts:state.contexts.slice(-16), observations:state.observations.slice(-24), active_plan:state.active_plan,
346
- capabilities:capabilityManifest,
367
+ capabilities:capabilityManifest, project_memory:memory,
347
368
  recent_decisions:state.decisions.slice(-8).map(item => ({ planner_round:item.planner_round,
348
369
  action:item.decision?.action, summary:item.decision?.summary })) };
349
370
  }
@@ -361,7 +382,7 @@ async function requestPlanner(ctx, goal, events, state, policy, codingRuntime, c
361
382
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{ reason:'wall_time_limit', max_wall_ms:policy.limits.max_wall_ms });
362
383
  return null;
363
384
  }
364
- const view = await plannerView(goal,state,codingRuntime,capabilityManifest);
385
+ const view = await plannerView(goal,state,events,codingRuntime,capabilityManifest);
365
386
  let prompt = buildPlannerPrompt({ goal:{ title:goal.title, goal:goal.goal, acceptance:goal.acceptance }, policy, view });
366
387
  const repair = [...(state.planner_rejections ?? [])].reverse().find(item => item.planner_round === round) ?? null;
367
388
  if (repair) {
@@ -749,14 +770,36 @@ async function executeDelegate({ ctx, events, goal, decisionEvent, decision, pol
749
770
  }
750
771
  }
751
772
 
752
- async function runMutationProfiles({ ctx, events, goal, epoch, actionKey, policy, codingRuntime, signingKeyPath }) {
773
+ async function executeProfileWithLease({workerScheduler,ctx,events,goal,epoch,actionKey,profileId,policy,codingRuntime,signingKeyPath,r34ResumePhase=null}) {
774
+ if(!workerScheduler) throw new Error('R37 worker scheduler unavailable');
775
+ const taskId=`${goal.goal_id}:${actionKey}:${profileId}`;
776
+ const lease=workerScheduler.acquire({taskId,workerClass:'profile',cpuUnits:1,memoryMb:256});
777
+ await appendEvent(ctx,events,signingKeyPath,'worker_lease_acquired',{
778
+ lease_id:lease.lease_id,task_id:lease.task_id,worker_class:lease.worker_class,profile_id:profileId,
779
+ attempt:lease.attempt,cpu_units:lease.cpu_units,memory_mb:lease.memory_mb,expires_at_ms:lease.expires_at_ms
780
+ });
781
+ let outcomeStatus='failed';
782
+ try {
783
+ const result=await executeProfile({ctx,events,goalId:goal.goal_id,actionKey,profileId,epoch,policy,codingRuntime,signingKeyPath,r34ResumePhase});
784
+ outcomeStatus=result.status;
785
+ return result;
786
+ } finally {
787
+ const released=workerScheduler.release(lease.lease_id,{status:outcomeStatus});
788
+ await appendEvent(ctx,events,signingKeyPath,'worker_lease_released',{
789
+ lease_id:lease.lease_id,task_id:lease.task_id,worker_class:lease.worker_class,profile_id:profileId,
790
+ status:released.lease.status,released_at_ms:released.lease.released_at_ms
791
+ });
792
+ }
793
+ }
794
+
795
+ async function runMutationProfiles({ ctx, events, goal, epoch, actionKey, policy, codingRuntime, signingKeyPath, workerScheduler }) {
753
796
  const profileIds = Object.entries(policy.profiles)
754
797
  .filter(([,profile]) => profile.run_after_mutation)
755
798
  .map(([id]) => id);
756
799
  const results = [];
757
800
  for (const profileId of profileIds) {
758
- const result = await executeProfile({ ctx,events,goalId:goal.goal_id,actionKey:`${actionKey}:${profileId}`,
759
- profileId,epoch,policy,codingRuntime,signingKeyPath });
801
+ const result = await executeProfileWithLease({workerScheduler,ctx,events,goal,epoch,
802
+ actionKey:`${actionKey}:${profileId}`,profileId,policy,codingRuntime,signingKeyPath});
760
803
  results.push({ profile_id:profileId, status:result.status, observation:result.observation });
761
804
  if (result.status === 'paused') break;
762
805
  }
@@ -817,7 +860,7 @@ async function appendPatchCommit({ctx,events,signingKeyPath,started,decisionEven
817
860
  });
818
861
  }
819
862
  async function executePatch({ ctx, events, goal, state, decisionEvent, decision, nativeDiffRuntime,
820
- policy, codingRuntime, signingKeyPath, actionCoordinatesOverride = null }) {
863
+ policy, codingRuntime, signingKeyPath, workerScheduler, actionCoordinatesOverride = null }) {
821
864
  let started = patchStartedForDecision(events,decisionEvent.event_sha256);
822
865
  if (!started && state.mutation_count + decision.operations.length > policy.limits.max_mutations) {
823
866
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{
@@ -853,7 +896,7 @@ async function executePatch({ ctx, events, goal, state, decisionEvent, decision,
853
896
  if (!committed) throw new Error('completed patch action missing native diff commit');
854
897
  const epoch = committed.payload.mutation_epoch;
855
898
  const profiles = await runMutationProfiles({ ctx,events,goal,epoch,
856
- actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath });
899
+ actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath,workerScheduler });
857
900
  return { status:profiles.some(item => item.status === 'paused') ? 'paused' : 'completed',
858
901
  diff_id:diffId, mutation_epoch:epoch, profiles, recovered:true };
859
902
  }
@@ -901,12 +944,12 @@ async function executePatch({ ctx, events, goal, state, decisionEvent, decision,
901
944
  }
902
945
  const epoch = committed.payload.mutation_epoch;
903
946
  const profiles = await runMutationProfiles({ ctx,events,goal,epoch,
904
- actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath });
947
+ actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath,workerScheduler });
905
948
  return { status:profiles.some(item => item.status === 'paused') ? 'paused' : 'completed',
906
949
  diff_id:diffId, mutation_epoch:epoch, profiles, recovered };
907
950
  }
908
951
  async function executePreparedDiff({ctx,events,goal,state,decisionEvent,diffId,expectedOperationCount,
909
- policy,codingRuntime,nativeDiffRuntime,signingKeyPath}) {
952
+ policy,codingRuntime,nativeDiffRuntime,signingKeyPath,workerScheduler}) {
910
953
  let started=patchStartedForDecision(events,decisionEvent.event_sha256);
911
954
  if(!started&&state.mutation_count+expectedOperationCount>policy.limits.max_mutations){
912
955
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{reason:'mutation_limit',max_mutations:policy.limits.max_mutations});
@@ -929,7 +972,7 @@ async function executePreparedDiff({ctx,events,goal,state,decisionEvent,diffId,e
929
972
  const committed=patchCommitForAction(events,actionId);
930
973
  if(!committed) throw new Error('completed prepared diff action missing native diff commit');
931
974
  const epoch=committed.payload.mutation_epoch;
932
- const profiles=await runMutationProfiles({ctx,events,goal,epoch,actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath});
975
+ const profiles=await runMutationProfiles({ctx,events,goal,epoch,actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath,workerScheduler});
933
976
  return {status:profiles.some(item=>item.status==='paused')?'paused':'completed',diff_id:diffId,mutation_epoch:epoch,profiles,recovered:true};
934
977
  }
935
978
  const reconciliation=await reconcileStartedAction({startedEvent:started,journal:events,runtimes:{nativeDiffRuntime,codingRuntime}});
@@ -963,10 +1006,10 @@ async function executePreparedDiff({ctx,events,goal,state,decisionEvent,diffId,e
963
1006
  receipt_sha256:verified.receipt_sha256,recovered});
964
1007
  }
965
1008
  const epoch=committed.payload.mutation_epoch;
966
- const profiles=await runMutationProfiles({ctx,events,goal,epoch,actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath});
1009
+ const profiles=await runMutationProfiles({ctx,events,goal,epoch,actionKey:`mutation-${epoch}`,policy,codingRuntime,signingKeyPath,workerScheduler});
967
1010
  return {status:profiles.some(item=>item.status==='paused')?'paused':'completed',diff_id:diffId,mutation_epoch:epoch,profiles,recovered};
968
1011
  }
969
- async function runRequiredReleaseProfiles({ ctx, events, goal, state, policy, codingRuntime, signingKeyPath }) {
1012
+ async function runRequiredReleaseProfiles({ ctx, events, goal, state, policy, codingRuntime, signingKeyPath, workerScheduler }) {
970
1013
  const requiredIds = Object.entries(policy.profiles)
971
1014
  .filter(([,profile]) => profile.required_for_release)
972
1015
  .map(([id]) => id);
@@ -977,9 +1020,9 @@ async function runRequiredReleaseProfiles({ ctx, events, goal, state, policy, co
977
1020
  results.push({ profile_id:profileId, status:'passed', observation:existing, existing:true });
978
1021
  continue;
979
1022
  }
980
- const result = await executeProfile({ ctx,events,goalId:goal.goal_id,
981
- actionKey:`release-${state.mutation_epoch}:${profileId}`, profileId,
982
- epoch:state.mutation_epoch,policy,codingRuntime,signingKeyPath });
1023
+ const result = await executeProfileWithLease({workerScheduler,ctx,events,goal,
1024
+ actionKey:`release-${state.mutation_epoch}:${profileId}`,profileId,
1025
+ epoch:state.mutation_epoch,policy,codingRuntime,signingKeyPath});
983
1026
  results.push({ profile_id:profileId, ...result });
984
1027
  if (result.status === 'paused') break;
985
1028
  }
@@ -1153,7 +1196,7 @@ function r34ReasonHash(goal,decisionEvent,reason) {
1153
1196
  }
1154
1197
  async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,policy,codingRuntime,
1155
1198
  nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,
1156
- signingKeyPath,verifyKeyPath}) {
1199
+ signingKeyPath,verifyKeyPath,workerScheduler}) {
1157
1200
  let loop=deriveLoopState(goal,events);
1158
1201
  if (decision.kind === 'plan_create') {
1159
1202
  if (loop.phase !== 'PLAN' || loop.plan) throw new Error('R34 plan_create requires empty PLANNING state');
@@ -1196,7 +1239,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1196
1239
  try {
1197
1240
  outcome=await executePatch({ctx,events,goal,state,decisionEvent,
1198
1241
  decision:{operations:decision.action.operations,summary:`R34 ${currentStep.step_id}`},nativeDiffRuntime,
1199
- policy,codingRuntime,signingKeyPath,actionCoordinatesOverride:{planId:loop.plan_id,
1242
+ policy,codingRuntime,signingKeyPath,workerScheduler,actionCoordinatesOverride:{planId:loop.plan_id,
1200
1243
  planVersion:loop.plan_version,stepId:currentStep.step_id}});
1201
1244
  } catch (error) {
1202
1245
  const detail=truncated(error,512);
@@ -1209,7 +1252,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1209
1252
  }
1210
1253
  } else if (decision.action.kind === 'run_profile') {
1211
1254
  await assertRunAuthority(goal.root_id);
1212
- outcome=await executeProfile({ctx,events,goalId:goal.goal_id,
1255
+ outcome=await executeProfileWithLease({workerScheduler,ctx,events,goal,
1213
1256
  actionKey:`r34-${decisionEvent.event_sha256}`,profileId:decision.action.profile_id,
1214
1257
  epoch:state.mutation_epoch,policy,codingRuntime,signingKeyPath,r34ResumePhase:loop.phase});
1215
1258
  } else if (decision.action.kind === 'delegate') {
@@ -1219,7 +1262,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1219
1262
  } else if (decision.action.kind === 'native_diff_apply') {
1220
1263
  await assertRunAuthority(goal.root_id);
1221
1264
  outcome=await executePreparedDiff({ctx,events,goal,state,decisionEvent,diffId:decision.action.diff_id,
1222
- expectedOperationCount:decision.action.expected_operation_count,policy,codingRuntime,nativeDiffRuntime,signingKeyPath});
1265
+ expectedOperationCount:decision.action.expected_operation_count,policy,codingRuntime,nativeDiffRuntime,signingKeyPath,workerScheduler});
1223
1266
  } else if (['machine_fs_mkdir','machine_fs_move','machine_fs_delete'].includes(decision.action.kind)) {
1224
1267
  await assertRunAuthority(goal.root_id);
1225
1268
  if(!machineFsRuntime) throw new Error('machine filesystem runtime unavailable');
@@ -1240,7 +1283,7 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1240
1283
  }
1241
1284
  }
1242
1285
  outcome=await executePatch({ctx,events,goal,state,decisionEvent,decision:{operations,summary:`R36 ${decision.action.kind}`},
1243
- nativeDiffRuntime,policy,codingRuntime,signingKeyPath});
1286
+ nativeDiffRuntime,policy,codingRuntime,signingKeyPath,workerScheduler});
1244
1287
  } else if (capabilityIdForOperation(decision.action)) {
1245
1288
  outcome=await executeDelegate({ctx,events,goal,decisionEvent,
1246
1289
  decision:{operation:decision.action},policy,
@@ -1347,14 +1390,14 @@ async function executeR34Decision({ctx,events,goal,state,decisionEvent,decision,
1347
1390
  throw new Error(`unsupported R34 decision '${String(decision.kind)}'`);
1348
1391
  }
1349
1392
 
1350
- async function executeDecision({ ctx, events, goal, state, decisionEvent, policy, codingRuntime,
1393
+ async function executeDecisionCore({ ctx, events, goal, state, decisionEvent, policy, codingRuntime,
1351
1394
  nativeDiffRuntime, machineFsRuntime, observationRuntime, processRuntime, semanticRuntime, assertRunAuthority,
1352
- signingKeyPath, verifyKeyPath }) {
1395
+ signingKeyPath, verifyKeyPath, workerScheduler }) {
1353
1396
  const decision = decisionEvent.decision;
1354
1397
  if (decision?.schema === 'deadbyte.autonomous-decision.v2') {
1355
1398
  const outcome=await executeR34Decision({ctx,events,goal,state,decisionEvent,decision,policy,codingRuntime,
1356
1399
  nativeDiffRuntime,machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,
1357
- signingKeyPath,verifyKeyPath});
1400
+ signingKeyPath,verifyKeyPath,workerScheduler});
1358
1401
  await appendEvent(ctx,events,signingKeyPath,'decision_completed',{
1359
1402
  decision_event_sha256:decisionEvent.event_sha256,action:decision.kind,
1360
1403
  outcome_status:outcome.status ?? 'completed'
@@ -1384,15 +1427,15 @@ async function executeDecision({ ctx, events, goal, state, decisionEvent, policy
1384
1427
  } else if (decision.action === 'patch') {
1385
1428
  await assertRunAuthority(goal.root_id);
1386
1429
  outcome = await executePatch({ ctx,events,goal,state,decisionEvent,decision,nativeDiffRuntime,
1387
- policy,codingRuntime,signingKeyPath });
1430
+ policy,codingRuntime,signingKeyPath,workerScheduler });
1388
1431
  } else if (decision.action === 'delegate') {
1389
1432
  outcome = await executeDelegate({ ctx,events,goal,decisionEvent,decision,policy,
1390
1433
  runtimes:{ machineFsRuntime,observationRuntime,processRuntime },assertRunAuthority,signingKeyPath,verifyKeyPath });
1391
1434
  } else if (decision.action === 'run_profile') {
1392
1435
  await assertRunAuthority(goal.root_id);
1393
- outcome = await executeProfile({ ctx,events,goalId:goal.goal_id,
1394
- actionKey:`planner-${decisionEvent.event_sha256}`, profileId:decision.profile_id,
1395
- epoch:state.mutation_epoch,policy,codingRuntime,signingKeyPath });
1436
+ outcome = await executeProfileWithLease({workerScheduler,ctx,events,goal,
1437
+ actionKey:`planner-${decisionEvent.event_sha256}`,profileId:decision.profile_id,
1438
+ epoch:state.mutation_epoch,policy,codingRuntime,signingKeyPath});
1396
1439
  } else if (decision.action === 'pause') {
1397
1440
  await appendEvent(ctx,events,signingKeyPath,'goal_paused',{
1398
1441
  reason:decision.reason, planner_summary:decision.summary
@@ -1414,6 +1457,83 @@ async function executeDecision({ ctx, events, goal, state, decisionEvent, policy
1414
1457
  return outcome;
1415
1458
  }
1416
1459
 
1460
+ function effectDescriptor(goal,state,events,decisionEvent){
1461
+ const decision=decisionEvent?.decision;
1462
+ let action=null,coordinates=null;
1463
+ if(decision?.schema==='deadbyte.autonomous-decision.v2'&&decision.kind==='act'){
1464
+ const loop=deriveLoopState(goal,events);
1465
+ if(!loop.plan_id||!loop.current_step?.step_id) return null;
1466
+ action=decision.action;
1467
+ coordinates={planId:loop.plan_id,stepId:loop.current_step.step_id};
1468
+ }else if(['patch','delegate','run_profile'].includes(decision?.action)){
1469
+ coordinates=patchActionCoordinates(state);
1470
+ if(decision.action==='patch') action={kind:'patch',operations:decision.operations};
1471
+ else if(decision.action==='delegate') action={kind:'delegate',operation:decision.operation};
1472
+ else action={kind:'run_profile',profile_id:decision.profile_id};
1473
+ }
1474
+ if(!action||!coordinates) return null;
1475
+ const observed=[...events].reverse().find(event=>[
1476
+ 'inspection_completed','inspect_completed','profile_completed','delegated_action_completed','observation_completed'
1477
+ ].includes(event.type)&&SHA256_RE.test(event.event_sha256??''))?.event_sha256 ?? state.journal_head_sha256;
1478
+ return {action,planId:coordinates.planId,stepId:coordinates.stepId,observationHeadSha256:observed};
1479
+ }
1480
+
1481
+ async function executeDecision(args) {
1482
+ const {ctx,events,goal,state,decisionEvent,signingKeyPath}=args;
1483
+ const descriptor=effectDescriptor(goal,state,events,decisionEvent);
1484
+ if(!descriptor) return executeDecisionCore(args);
1485
+ const lease=issueObservationLease({goalId:goal.goal_id,mutationEpoch:state.mutation_epoch,
1486
+ observations:[{event_sha256:descriptor.observationHeadSha256}],ttlMs:120000});
1487
+ verifyObservationLease(lease,{goalId:goal.goal_id,currentMutationEpoch:state.mutation_epoch,
1488
+ observationHeadSha256:descriptor.observationHeadSha256});
1489
+ if(!events.some(event=>event.type==='observation_lease_issued'&&event.payload?.lease_id===lease.lease_id)){
1490
+ await appendEvent(ctx,events,signingKeyPath,'observation_lease_issued',{
1491
+ lease_id:lease.lease_id,mutation_epoch:lease.mutation_epoch,
1492
+ observation_head_sha256:lease.observation_head_sha256,expires_at_ms:lease.expires_at_ms,
1493
+ decision_event_sha256:decisionEvent.event_sha256
1494
+ });
1495
+ }
1496
+ const effect=effectIdentity({goalId:goal.goal_id,planId:descriptor.planId,stepId:descriptor.stepId,
1497
+ mutationEpoch:state.mutation_epoch,action:descriptor.action,observationHeadSha256:descriptor.observationHeadSha256});
1498
+ const guard=loopGuardDisposition(events,effect,{maxRepeats:2,window:48});
1499
+ if(!guard.allowed){
1500
+ await appendEvent(ctx,events,signingKeyPath,'effect_guard_blocked',{
1501
+ effect_id:effect.effect_id,fingerprint:effect.fingerprint,repeated_count:guard.repeated_count,
1502
+ max_repeats:guard.max_repeats,reason:guard.reason,decision_event_sha256:decisionEvent.event_sha256
1503
+ });
1504
+ await appendEvent(ctx,events,signingKeyPath,'goal_paused',{reason:'effect_repeat_limit',
1505
+ effect_id:effect.effect_id,fingerprint:effect.fingerprint});
1506
+ return {status:'paused',reason:'effect_repeat_limit'};
1507
+ }
1508
+ if(!events.some(event=>event.type==='effect_started'&&event.payload?.effect_id===effect.effect_id)){
1509
+ await appendEvent(ctx,events,signingKeyPath,'effect_started',{
1510
+ ...effect,observation_lease_id:lease.lease_id,decision_event_sha256:decisionEvent.event_sha256
1511
+ });
1512
+ }
1513
+ try{
1514
+ const outcome=await executeDecisionCore(args);
1515
+ if(!events.some(event=>['effect_completed','effect_failed'].includes(event.type)&&event.payload?.effect_id===effect.effect_id)){
1516
+ const completion=bindEffectCompletion(effect,{status:outcome?.status??'completed',
1517
+ mutation_epoch:deriveState(goal,events).mutation_epoch,observation_lease_id:lease.lease_id});
1518
+ await appendEvent(ctx,events,signingKeyPath,'effect_completed',{
1519
+ ...completion,observation_lease_id:lease.lease_id,decision_event_sha256:decisionEvent.event_sha256,
1520
+ outcome_status:outcome?.status??'completed'
1521
+ });
1522
+ }
1523
+ return outcome;
1524
+ }catch(error){
1525
+ if(!events.some(event=>['effect_completed','effect_failed'].includes(event.type)&&event.payload?.effect_id===effect.effect_id)){
1526
+ const completion=bindEffectCompletion(effect,{status:'failed',error:truncated(error,512),
1527
+ mutation_epoch:deriveState(goal,events).mutation_epoch,observation_lease_id:lease.lease_id});
1528
+ await appendEvent(ctx,events,signingKeyPath,'effect_failed',{
1529
+ ...completion,observation_lease_id:lease.lease_id,decision_event_sha256:decisionEvent.event_sha256,
1530
+ detail:truncated(error,512)
1531
+ });
1532
+ }
1533
+ throw error;
1534
+ }
1535
+ }
1536
+
1417
1537
  function terminalState(state) {
1418
1538
  return ['succeeded','cancelled'].includes(state.state);
1419
1539
  }
@@ -1442,6 +1562,9 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1442
1562
  if (!policy || !codingRuntime || !nativeDiffRuntime) throw new Error('autonomous runtime requires policy/coding/native-diff runtimes');
1443
1563
  if (!signingKeyPath || !verifyKeyPath) throw new Error('autonomous runtime requires trust keys');
1444
1564
  const capabilityManifest=configuredCapabilityManifest({machineFsRuntime,observationRuntime,processRuntime,semanticRuntime});
1565
+ const profileTimeoutCeiling=Math.max(120000,...Object.values(policy.profiles??{}).map(profile=>
1566
+ Number.isInteger(profile?.timeout_ms)&&profile.timeout_ms>0?profile.timeout_ms+120000:120000));
1567
+ const workerScheduler=createWorkerScheduler({maxConcurrent:2,totalCpuUnits:2,totalMemoryMb:2048,leaseMs:profileTimeoutCeiling});
1445
1568
  async function sessionStatus() {
1446
1569
  const autonomous = await autonomousSessionStatus(policy);
1447
1570
  const coding = await codingRuntime.sessionStatus();
@@ -1500,8 +1623,9 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1500
1623
  const journal = await readEvents(ctx,verifyKeyPath);
1501
1624
  const derived = deriveState(goal,journal);
1502
1625
  const loop = publicLoopState(loopStateOrNull(goal,journal));
1626
+ const lock=await runLockStatus(ctx);
1503
1627
  return { status:'ok', goal_id:goalId, goal_sha256:goal.goal_sha256,
1504
- title:goal.title, root_id:goal.root_id, journal_verified:true, ...derived,
1628
+ title:goal.title, root_id:goal.root_id, journal_verified:true, ...derived, ...lock,
1505
1629
  ...(loop ? {loop} : {}) };
1506
1630
  }
1507
1631
 
@@ -1577,7 +1701,7 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1577
1701
  }
1578
1702
  state = deriveState(goal,journal);
1579
1703
  const profiles = await runRequiredReleaseProfiles({ ctx,events:journal,goal,state,
1580
- policy,codingRuntime,signingKeyPath });
1704
+ policy,codingRuntime,signingKeyPath,workerScheduler });
1581
1705
  if (profiles.some(item => item.status === 'paused')) {
1582
1706
  return { status:'paused', goal_id:goal.goal_id, ready:false,
1583
1707
  reason:'release_profile_interrupted', mutation_epoch:state.mutation_epoch };
@@ -1658,7 +1782,7 @@ export function createAutonomousRuntime({ policy, codingRuntime, nativeDiffRunti
1658
1782
  try {
1659
1783
  outcome = await executeDecision({ ctx,events:journal,goal,state,
1660
1784
  decisionEvent:state.pending_decision,policy,codingRuntime,nativeDiffRuntime,machineFsRuntime,
1661
- observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,signingKeyPath,verifyKeyPath });
1785
+ observationRuntime,processRuntime,semanticRuntime,assertRunAuthority,signingKeyPath,verifyKeyPath,workerScheduler });
1662
1786
  } catch (error) {
1663
1787
  const loop=loopStateOrNull(goal,journal);
1664
1788
  if (!loop || loop.pending_action || !isAuthorityUnavailable(error)) throw error;
@@ -0,0 +1,27 @@
1
+ const HEX64=/^[0-9a-f]{64}$/;
2
+
3
+ export function classifyAutonomousTimeoutRecovery(status,{beforeJournalHead}={}){
4
+ if(!status||typeof status!=='object'||Array.isArray(status)) throw new Error('autonomous timeout status invalid');
5
+ if(!HEX64.test(beforeJournalHead??'')) throw new Error('autonomous timeout before journal head invalid');
6
+ if(status.status!=='ok') throw new Error('autonomous timeout status not ok');
7
+ if(!HEX64.test(status.journal_head_sha256??'')) throw new Error('autonomous timeout journal head invalid');
8
+ if(status.state==='succeeded') return Object.freeze({kind:'completed',state:'succeeded',journal_head_sha256:status.journal_head_sha256});
9
+ if(status.state==='cancelled'||status.state==='paused'){
10
+ return Object.freeze({kind:'terminal_failure',state:status.state,reason:status.reason??null,journal_head_sha256:status.journal_head_sha256});
11
+ }
12
+ if(status.state!=='pending'&&status.state!=='running') throw new Error(`autonomous timeout unexpected state: ${status.state}`);
13
+ if(status.run_busy===true){
14
+ return Object.freeze({kind:'wait',state:status.state,reason:'server_run_in_flight',journal_head_sha256:status.journal_head_sha256});
15
+ }
16
+ if(status.run_busy!==false) throw new Error('autonomous timeout run-lock state unavailable');
17
+ if(status.pending_request!==null&&status.pending_request!==undefined){
18
+ return Object.freeze({kind:'wait',state:status.state,reason:'planner_request_in_flight',journal_head_sha256:status.journal_head_sha256});
19
+ }
20
+ if(status.pending_decision!==null&&status.pending_decision!==undefined){
21
+ return Object.freeze({kind:'wait',state:status.state,reason:'decision_in_flight',journal_head_sha256:status.journal_head_sha256});
22
+ }
23
+ if(status.journal_head_sha256===beforeJournalHead){
24
+ return Object.freeze({kind:'wait',state:status.state,reason:'no_durable_progress',journal_head_sha256:status.journal_head_sha256});
25
+ }
26
+ return Object.freeze({kind:'resumable',state:status.state,reason:'durable_cycle_completed',journal_head_sha256:status.journal_head_sha256});
27
+ }
@@ -9,7 +9,7 @@ import { fileURLToPath } from 'node:url';
9
9
  import { defaultPublicKeyPath } from './trust.mjs';
10
10
  import { verifyAuditChain } from './audit-verify.mjs';
11
11
  import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
12
- import { createLiveActivityTracker, formatCompactAuditEvent, formatRemoteLifecycle } from './remote-live-log.mjs';
12
+ import { createLiveTimelineTracker, formatCompactAuditEvent, formatRemoteLifecycle, formatRuntimeDiagnosticLine } from './remote-live-log.mjs';
13
13
 
14
14
  const REMOTE_COMMANDS=new Set([
15
15
  'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
@@ -34,9 +34,8 @@ function printHelp(){
34
34
  process.stdout.write([
35
35
  'DEADBYTE MCP CLI','',
36
36
  ' npx deadbyte-mcp@latest mcp # stdio MCP server for local clients',
37
- ' npx deadbyte-mcp@latest remote # compact foreground device session',
38
- ' npx deadbyte-mcp@latest remote --verbose # detailed audit + bridge logs',
39
- ' npx deadbyte-mcp@latest remote --resume <cursor> # replay missed compact results, then reconnect',
37
+ ' npx deadbyte-mcp@latest remote # unified foreground device session + live timeline',
38
+ ' npx deadbyte-mcp@latest remote --resume <cursor> # replay missed results, then reconnect',
40
39
  ' npx deadbyte-mcp@latest remote status',
41
40
  ' npx deadbyte-mcp@latest remote restart',
42
41
  ' npx deadbyte-mcp@latest supervisor status',
@@ -78,35 +77,15 @@ async function listLogFiles(root){
78
77
  }
79
78
  return files;
80
79
  }
81
- function formatLogLine(file,line,{verbose=false,activityTracker=null}={}){
80
+ function formatLogLine(file,line,{activityTracker=null}={}){
82
81
  if(!line) return null;
83
82
  if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
84
83
  try{
85
84
  const event=JSON.parse(line);
86
- if(!verbose) return activityTracker?activityTracker.observe(event):formatCompactAuditEvent(event);
87
- const seq=Number.isInteger(event.seq)?`#${event.seq}`:'#?';
88
- const request=typeof event.request_id==='string'?` ${event.request_id.slice(0,8)}`:'';
89
- const tool=typeof event.tool==='string'?` ${event.tool}`:'';
90
- let marker='';
91
- if(event.event_type==='tool.request') marker='📥 ';
92
- else if(event.event_type==='tool.result'){
93
- if(event.outcome?.is_error===true) marker='📤❌ ';
94
- else if(event.outcome?.is_error===false) marker='📤✅ ';
95
- else marker='📤 ';
96
- }
97
- return `${marker}[AUDIT ${seq}] ${event.event_type||'event'}${tool}${request}`;
98
- }catch{return verbose?`[AUDIT] ${line}`:null;}
99
- }
100
- if(!verbose) return null;
101
- const label=path.basename(file).replace(/\.log$/i,'').toUpperCase();
102
- let marker='';
103
- if(/\[TOOL IN \]/.test(line)) marker='📥 ';
104
- else if(/\[TOOL OUT\]/.test(line)){
105
- if(/"is_error"\s*:\s*true/.test(line)) marker='📤❌ ';
106
- else if(/"is_error"\s*:\s*false/.test(line)) marker='📤✅ ';
107
- else marker='📤 ';
85
+ return activityTracker?activityTracker.observe(event):formatCompactAuditEvent(event);
86
+ }catch{return null;}
108
87
  }
109
- return `${marker}[${label}] ${line}`;
88
+ return formatRuntimeDiagnosticLine(file,line);
110
89
  }
111
90
  function remoteResultJournalPath(root,sessionId){return path.join(root,'runtime','remote-results',`${sessionId}.json`);}
112
91
  function auditTerminalResult(file,line){
@@ -117,7 +96,7 @@ function auditTerminalResult(file,line){
117
96
  return {request_id:event.request_id,tool:event.tool,status:event.outcome?.is_error===true?'error':'ok',observed_at_utc:observed,
118
97
  payload_sha256:createHash('sha256').update(Buffer.from(line,'utf8')).digest('hex')};
119
98
  }
120
- async function replayRemoteResults(root,cursor,{verbose=false}={}){
99
+ async function replayRemoteResults(root,cursor){
121
100
  const parsed=parseRemoteResultCursor(cursor);
122
101
  const file=remoteResultJournalPath(root,parsed.session_id);
123
102
  await requireRegular(file,'remote result journal');
@@ -127,7 +106,7 @@ async function replayRemoteResults(root,cursor,{verbose=false}={}){
127
106
  const page=await journal.replayAfter(next,{limit:200});
128
107
  for(const event of page.events){
129
108
  const marker=event.status==='error'?'[ERR]':'[OK]';
130
- process.stdout.write(`${verbose?'[REPLAY] ': '[REPLAY] '}${marker} ${event.tool} [cursor r1:${event.session_id}:${event.seq}]\n`);
109
+ process.stdout.write(`[REPLAY] ${marker} ${event.tool} [cursor r1:${event.session_id}:${event.seq}]\n`);
131
110
  }
132
111
  next=page.next_cursor;
133
112
  if(!page.has_more) return next;
@@ -151,10 +130,8 @@ async function snapshotRemoteLogOffsets(root){
151
130
  }
152
131
  return offsets;
153
132
  }
154
- async function tailRemoteLogs(root,signal,{verbose=false,journal=null,offsets=null,activityTracker=null}={}){
155
- process.stdout.write(verbose
156
- ?'📜 [LOG] Live logs active. Press Ctrl+C to disconnect and revoke authority.\n'
157
- :'[LOG] Live activity. Ctrl+C disconnects and revokes authority.\n');
133
+ async function tailRemoteLogs(root,signal,{journal=null,offsets=null,activityTracker=null}={}){
134
+ process.stdout.write('[LOG] Unified live timeline. Ctrl+C disconnects and revokes authority.\n');
158
135
  const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
159
136
  while(!signal.aborted){
160
137
  for(const file of await listLogFiles(root)){
@@ -165,22 +142,20 @@ async function tailRemoteLogs(root,signal,{verbose=false,journal=null,offsets=nu
165
142
  const terminal=auditTerminalResult(file,line);
166
143
  let recorded=null;
167
144
  if(terminal&&journal) recorded=await journal.recordTerminal(terminal);
168
- if(recorded?.duplicate&&!verbose) continue;
169
- const formatted=formatLogLine(file,line,{verbose,activityTracker});
145
+ if(recorded?.duplicate) continue;
146
+ const formatted=formatLogLine(file,line,{activityTracker});
170
147
  if(!formatted) continue;
171
- if(!verbose&&recorded) process.stdout.write(`${formatted} [cursor ${recorded.cursor}]\n`);
148
+ if(recorded) process.stdout.write(`${formatted} [cursor ${recorded.cursor}]\n`);
172
149
  else process.stdout.write(`${formatted}\n`);
173
150
  }
174
151
  }
175
152
  try{await sleep(250,null,{signal});}catch(error){if(error?.name!=='AbortError') throw error;}
176
153
  }
177
154
  }
178
- async function cleanupRemoteSession(ctx,{verbose=false}={}){
155
+ async function cleanupRemoteSession(ctx){
179
156
  for(const command of SESSION_CLEANUP){
180
157
  try{
181
- const result=invokeController(ctx,command,verbose
182
- ?{allowFailure:true}
183
- :{allowFailure:true,capture:true,echoCaptured:false});
158
+ const result=invokeController(ctx,command,{allowFailure:true,capture:true,echoCaptured:false});
184
159
  if(result.status!==0) process.stderr.write(`⚠️ [WARN] cleanup ${command} exit=${result.status}\n`);
185
160
  }
186
161
  catch(error){process.stderr.write(`⚠️ [WARN] cleanup ${command}: ${String(error?.message||error)}\n`);}
@@ -259,15 +234,15 @@ async function releaseRemoteSession(ctx,marker){
259
234
  const same=current?.schema==='deadbyte.remote-session.v2'&&current.owner_pid===marker.owner_pid&&current.session_nonce===marker.session_nonce;
260
235
  if(same) await rm(remoteSessionMarker(ctx.root),{force:true});
261
236
  }
262
- async function runRemoteSession({verbose=false,resumeCursor=null}={}){
237
+ async function runRemoteSession({resumeCursor=null}={}){
263
238
  const ctx=await remoteContext();
264
- if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor,{verbose});
239
+ if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor);
265
240
  await recoverRemoteSession(ctx);
266
241
  const marker=await claimRemoteSession(ctx);
267
242
  const resultJournal=await openRemoteResultJournal({
268
243
  filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
269
244
  });
270
- const activityTracker=createLiveActivityTracker();
245
+ const activityTracker=createLiveTimelineTracker();
271
246
  const aborter=new AbortController();
272
247
  const abort=()=>aborter.abort();
273
248
  const watchStdin=!process.stdin.isTTY;
@@ -276,67 +251,53 @@ async function runRemoteSession({verbose=false,resumeCursor=null}={}){
276
251
  let ready=false;
277
252
  let logTask=null;
278
253
  try{
279
- if(verbose) process.stdout.write('DEADBYTE MCP DEVICE SESSION\n');
280
- else process.stdout.write('DEADBYTE MCP\n');
254
+ process.stdout.write('DEADBYTE MCP\n');
281
255
  process.stdout.write(`${formatRemoteLifecycle('device_start')}\n`);
282
256
  process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new')}\n`);
283
257
  const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
284
- logTask=tailRemoteLogs(ctx.root,aborter.signal,{verbose,journal:resultJournal,offsets:logOffsets,activityTracker});
285
- if(verbose) process.stdout.write('[INFO] Starting local + remote runtime...\n');
286
- else process.stdout.write('[BOOT] Starting local + remote runtime...\n');
258
+ logTask=tailRemoteLogs(ctx.root,aborter.signal,{journal:resultJournal,offsets:logOffsets,activityTracker});
259
+ process.stdout.write('[BOOT] Starting local + remote runtime...\n');
287
260
  const started=[];
288
261
  for(const command of SESSION_START){
289
- if(!verbose){
290
- if(command==='start') process.stdout.write('[BOOT] Starting bridge/runtime...\n');
291
- else process.stdout.write(`🔐 [AUTH] Arming ${command.slice(3)}...\n`);
292
- }
293
- const controllerResult=invokeController(ctx,command,verbose?{}:{capture:true,echoCaptured:false});
262
+ if(command==='start') process.stdout.write('[BOOT] Starting bridge/runtime...\n');
263
+ else process.stdout.write(`🔐 [AUTH] Arming ${command.slice(3)}...\n`);
264
+ const controllerResult=invokeController(ctx,command,{capture:true,echoCaptured:false});
294
265
  started.push(controllerResult);
295
266
  if(command==='start'){
296
267
  process.stdout.write(`${formatRemoteLifecycle('bridge_connected')}\n`);
297
268
  process.stdout.write(`${formatRemoteLifecycle('cloud_connected')}\n`);
298
269
  }
299
270
  }
300
- if(!verbose){
301
- const startText=started[0]?.stdout||'';
302
- const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
303
- process.stdout.write('[OK] ONLINE\n');
304
- process.stdout.write(`${formatRemoteLifecycle('ready')}\n`);
305
- if(url) process.stdout.write(`URL: ${url}\n`);
306
- process.stdout.write('🔐 [AUTH] Verifying process, coding, autonomous; host must stay DISARMED...\n');
307
- }else process.stdout.write('🛡️ [AUTHORITY] Verifying runtime planes; host must stay DISARMED...\n');
271
+ const startText=started[0]?.stdout||'';
272
+ const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
273
+ process.stdout.write('[OK] ONLINE\n');
274
+ process.stdout.write(`${formatRemoteLifecycle('ready')}\n`);
275
+ if(url) process.stdout.write(`URL: ${url}\n`);
276
+ process.stdout.write('🔐 [AUTH] Verifying process, coding, autonomous; host must stay DISARMED...\n');
308
277
  for(const [command,pattern] of SESSION_STATUS){
309
- const result=invokeController(ctx,command,{capture:true,echoCaptured:verbose});
278
+ const result=invokeController(ctx,command,{capture:true,echoCaptured:false});
310
279
  if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command} state mismatch`);
311
280
  }
312
281
  ready=true;
313
- if(verbose) process.stdout.write('[DEVICE] DEADBYTE MCP online; process/coding/autonomous ARMED; host DISARMED.\n');
314
- else process.stdout.write('🔐 [AUTH] ARMED: process, coding, autonomous | host DISARMED\n');
282
+ process.stdout.write('🔐 [AUTH] ARMED: process, coding, autonomous | host DISARMED\n');
315
283
  await logTask;
316
284
  }finally{
317
285
  const wasAborted=aborter.signal.aborted;
318
286
  aborter.abort();
319
287
  if(logTask) await logTask.catch(()=>{});
320
- if(!verbose){for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);}
288
+ for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);
321
289
  process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
322
290
  if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
323
291
  process.stdout.write(`${formatRemoteLifecycle('cleanup')}\n`);
324
- if(ready||!wasAborted) process.stdout.write(verbose?'[INFO] Closing remote device session and revoking authority...\n':'[INFO] Disconnecting; revoking authority...\n');
325
- await cleanupRemoteSession(ctx,{verbose});
292
+ if(ready||!wasAborted) process.stdout.write('[INFO] Disconnecting; revoking authority...\n');
293
+ await cleanupRemoteSession(ctx);
326
294
  await releaseRemoteSession(ctx,marker);
327
295
  }
328
296
  }
329
297
  async function runRemote(args){
330
298
  if(args.length===0){await runRemoteSession();return;}
331
- if(args.length===1&&args[0]==='--verbose'){await runRemoteSession({verbose:true});return;}
332
299
  if(args.length===2&&args[0]==='--resume'){await runRemoteSession({resumeCursor:args[1]});return;}
333
- if(args.length===3&&args[0]==='--verbose'&&args[1]==='--resume'){
334
- await runRemoteSession({verbose:true,resumeCursor:args[2]});return;
335
- }
336
- if(args.length===3&&args[0]==='--resume'&&args[2]==='--verbose'){
337
- await runRemoteSession({verbose:true,resumeCursor:args[1]});return;
338
- }
339
- if(args.length>1) throw new Error('remote accepts one controller command, --verbose, or --resume <cursor>');
300
+ if(args.length>1) throw new Error('remote accepts one controller command or --resume <cursor>');
340
301
  const command=args[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
341
302
  const ctx=await remoteContext();
342
303
  const result=invokeController(ctx,command,{allowFailure:true});