@skrr-ai/cli 0.1.118 → 0.1.120

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 (285) hide show
  1. package/dist/base-command.d.ts +32 -0
  2. package/dist/base-command.js +113 -5
  3. package/dist/commands/commands.js +11 -0
  4. package/dist/commands/commitments/action-proposal.d.ts +13 -0
  5. package/dist/commands/commitments/action-proposal.js +39 -0
  6. package/dist/commands/commitments/action-proposals/decide.js +8 -1
  7. package/dist/commands/commitments/action-proposals/execute.js +11 -1
  8. package/dist/commands/commitments/create.js +2 -2
  9. package/dist/commands/commitments/doctor.d.ts +8 -0
  10. package/dist/commands/commitments/doctor.js +22 -0
  11. package/dist/commands/commitments/execute-remediation.js +12 -1
  12. package/dist/commands/commitments/observations.js +2 -2
  13. package/dist/commands/commitments/pack/bind.d.ts +18 -1
  14. package/dist/commands/commitments/pack/bind.js +66 -8
  15. package/dist/commands/commitments/pack/plan.d.ts +4 -1
  16. package/dist/commands/commitments/pack/plan.js +30 -2
  17. package/dist/commands/commitments/update.js +8 -2
  18. package/dist/commands/completion/index.js +1 -1
  19. package/dist/commands/completion/values.js +1 -1
  20. package/dist/commands/computer-use/audio.d.ts +1 -0
  21. package/dist/commands/computer-use/audio.js +1 -0
  22. package/dist/commands/computer-use/browser.d.ts +1 -0
  23. package/dist/commands/computer-use/browser.js +1 -0
  24. package/dist/commands/computer-use/disable.d.ts +1 -0
  25. package/dist/commands/computer-use/disable.js +1 -0
  26. package/dist/commands/computer-use/enable.d.ts +1 -0
  27. package/dist/commands/computer-use/enable.js +1 -0
  28. package/dist/commands/computer-use/index.d.ts +1 -0
  29. package/dist/commands/computer-use/index.js +1 -0
  30. package/dist/commands/computer-use/install.d.ts +1 -0
  31. package/dist/commands/computer-use/install.js +1 -0
  32. package/dist/commands/computer-use/recover.d.ts +1 -0
  33. package/dist/commands/computer-use/recover.js +1 -0
  34. package/dist/commands/computer-use/status.d.ts +1 -0
  35. package/dist/commands/computer-use/status.js +1 -0
  36. package/dist/commands/computer-use/stop.d.ts +1 -0
  37. package/dist/commands/computer-use/stop.js +1 -0
  38. package/dist/commands/context.js +16 -11
  39. package/dist/commands/convos/recovery.js +1 -1
  40. package/dist/commands/daemon/diagnostics.d.ts +9 -0
  41. package/dist/commands/daemon/diagnostics.js +53 -0
  42. package/dist/commands/daemon/index.js +2 -0
  43. package/dist/commands/daemon/maintenance/attest.d.ts +15 -0
  44. package/dist/commands/daemon/maintenance/attest.js +52 -0
  45. package/dist/commands/daemon/maintenance/hold.d.ts +17 -0
  46. package/dist/commands/daemon/maintenance/hold.js +70 -0
  47. package/dist/commands/daemon/maintenance/index.d.ts +12 -0
  48. package/dist/commands/daemon/maintenance/index.js +30 -0
  49. package/dist/commands/daemon/maintenance/resume.d.ts +13 -0
  50. package/dist/commands/daemon/maintenance/resume.js +36 -0
  51. package/dist/commands/daemon/maintenance/status.d.ts +13 -0
  52. package/dist/commands/daemon/maintenance/status.js +36 -0
  53. package/dist/commands/doctor.d.ts +4 -1
  54. package/dist/commands/doctor.js +50 -6
  55. package/dist/commands/followups/plans/cancel-batch.js +6 -3
  56. package/dist/commands/followups/plans/capacity.js +7 -3
  57. package/dist/commands/followups/plans/observability.js +11 -3
  58. package/dist/commands/followups/plans/preferences/set.js +26 -8
  59. package/dist/commands/followups/plans/preferences.js +1 -1
  60. package/dist/commands/followups/plans/show.js +1 -1
  61. package/dist/commands/goals/key-results/assess.d.ts +36 -0
  62. package/dist/commands/goals/key-results/assess.js +110 -0
  63. package/dist/commands/goals/key-results/history.d.ts +30 -0
  64. package/dist/commands/goals/key-results/history.js +104 -0
  65. package/dist/commands/goals/key-results/list.d.ts +5 -4
  66. package/dist/commands/goals/key-results/list.js +12 -6
  67. package/dist/commands/goals/key-results/show.d.ts +4 -2
  68. package/dist/commands/goals/key-results/show.js +25 -4
  69. package/dist/commands/goals/key-results/update.d.ts +4 -0
  70. package/dist/commands/goals/key-results/update.js +18 -24
  71. package/dist/commands/goals/plan-now.js +12 -1
  72. package/dist/commands/goals/planner-compare.d.ts +30 -0
  73. package/dist/commands/goals/planner-compare.js +136 -0
  74. package/dist/commands/machines/dedicated/service/exec.d.ts +3 -0
  75. package/dist/commands/machines/dedicated/service/exec.js +70 -11
  76. package/dist/commands/machines/hosted/destroy.d.ts +1 -0
  77. package/dist/commands/machines/hosted/destroy.js +11 -1
  78. package/dist/commands/machines/hosted/exec.d.ts +1 -0
  79. package/dist/commands/machines/hosted/exec.js +12 -1
  80. package/dist/commands/machines/hosted/index.js +1 -0
  81. package/dist/commands/machines/hosted/operation.d.ts +14 -0
  82. package/dist/commands/machines/hosted/operation.js +51 -0
  83. package/dist/commands/machines/hosted/pull.js +1 -1
  84. package/dist/commands/machines/hosted/start.js +6 -2
  85. package/dist/commands/memory/versions/list.d.ts +2 -0
  86. package/dist/commands/memory/versions/list.js +3 -2
  87. package/dist/commands/memory/versions/show.d.ts +2 -0
  88. package/dist/commands/memory/versions/show.js +3 -2
  89. package/dist/commands/spaces/auto-executor/compare.d.ts +18 -0
  90. package/dist/commands/spaces/auto-executor/compare.js +139 -0
  91. package/dist/commands/spaces/auto-executor/runs.d.ts +3 -0
  92. package/dist/commands/spaces/auto-executor/runs.js +13 -1
  93. package/dist/commands/spaces/charter/create-from-description.d.ts +21 -0
  94. package/dist/commands/spaces/charter/create-from-description.js +77 -0
  95. package/dist/commands/spaces/charter/show.d.ts +22 -0
  96. package/dist/commands/spaces/charter/show.js +61 -0
  97. package/dist/commands/spaces/heartbeats/list.d.ts +1 -16
  98. package/dist/commands/spaces/heartbeats/list.js +13 -0
  99. package/dist/commands/spaces/install-template.js +3 -0
  100. package/dist/commands/spaces/loops/migrate.d.ts +32 -0
  101. package/dist/commands/spaces/loops/migrate.js +103 -0
  102. package/dist/commands/spaces/loops/release.d.ts +14 -0
  103. package/dist/commands/spaces/loops/release.js +59 -0
  104. package/dist/commands/spaces/notebook.d.ts +25 -0
  105. package/dist/commands/spaces/notebook.js +75 -0
  106. package/dist/commands/spaces/proposals/discard.d.ts +17 -0
  107. package/dist/commands/spaces/proposals/discard.js +17 -0
  108. package/dist/commands/spaces/proposals/keep.d.ts +17 -0
  109. package/dist/commands/spaces/proposals/keep.js +17 -0
  110. package/dist/commands/spaces/proposals/list.d.ts +24 -0
  111. package/dist/commands/spaces/proposals/list.js +89 -0
  112. package/dist/commands/spaces/skills/propose.d.ts +29 -0
  113. package/dist/commands/spaces/skills/propose.js +82 -0
  114. package/dist/commands/spaces/templates/fork.js +3 -0
  115. package/dist/commands/spaces/triggers/show.js +6 -0
  116. package/dist/commands/spaces/workflows/retry.d.ts +1 -0
  117. package/dist/commands/spaces/workflows/retry.js +8 -1
  118. package/dist/commands/spaces/workflows/triggers/create.js +3 -2
  119. package/dist/commands/spaces/workflows/triggers/fire.js +4 -0
  120. package/dist/commands/spaces/workflows/triggers/update.js +2 -1
  121. package/dist/commands/spaces/write-policy/set.d.ts +22 -0
  122. package/dist/commands/spaces/write-policy/set.js +82 -0
  123. package/dist/commands/spaces/write-policy/show.d.ts +19 -0
  124. package/dist/commands/spaces/write-policy/show.js +49 -0
  125. package/dist/commands/store/artifacts/receipt.d.ts +14 -0
  126. package/dist/commands/store/artifacts/receipt.js +34 -0
  127. package/dist/commands/store/artifacts/release.d.ts +2 -0
  128. package/dist/commands/store/artifacts/release.js +11 -0
  129. package/dist/commands/store/governance/publish-release.d.ts +2 -0
  130. package/dist/commands/store/governance/publish-release.js +30 -1
  131. package/dist/commands/store/governance/release-receipt.d.ts +12 -0
  132. package/dist/commands/store/governance/release-receipt.js +32 -0
  133. package/dist/commands/tasks/approvals/list.d.ts +11 -5
  134. package/dist/commands/tasks/approvals/list.js +13 -6
  135. package/dist/commands/tasks/attachments/facts.d.ts +12 -0
  136. package/dist/commands/tasks/attachments/facts.js +29 -0
  137. package/dist/commands/tasks/attachments/upload.d.ts +1 -0
  138. package/dist/commands/tasks/attachments/upload.js +16 -0
  139. package/dist/commands/tasks/bulk-update.js +35 -1
  140. package/dist/commands/tasks/context.d.ts +15 -0
  141. package/dist/commands/tasks/context.js +69 -0
  142. package/dist/commands/tasks/copy.d.ts +18 -0
  143. package/dist/commands/tasks/copy.js +85 -0
  144. package/dist/commands/tasks/create-tree.js +97 -23
  145. package/dist/commands/tasks/create.js +9 -1
  146. package/dist/commands/tasks/deliverable/add.js +20 -10
  147. package/dist/commands/tasks/move.js +8 -1
  148. package/dist/commands/tasks/operations/show.d.ts +16 -0
  149. package/dist/commands/tasks/operations/show.js +98 -0
  150. package/dist/commands/tasks/operations/wait.d.ts +22 -0
  151. package/dist/commands/tasks/operations/wait.js +114 -0
  152. package/dist/commands/tasks/preflight.d.ts +1 -0
  153. package/dist/commands/tasks/preflight.js +11 -1
  154. package/dist/commands/tasks/rearm-recurrence.js +4 -0
  155. package/dist/commands/tasks/result/show.js +22 -0
  156. package/dist/commands/tasks/result/submit.d.ts +1 -0
  157. package/dist/commands/tasks/result/submit.js +3 -0
  158. package/dist/commands/tasks/retry-receipt.d.ts +15 -0
  159. package/dist/commands/tasks/retry-receipt.js +89 -0
  160. package/dist/commands/tasks/retry-review.d.ts +16 -0
  161. package/dist/commands/tasks/retry-review.js +66 -0
  162. package/dist/commands/tasks/retry.d.ts +4 -8
  163. package/dist/commands/tasks/retry.js +34 -68
  164. package/dist/commands/tasks/runs.d.ts +21 -0
  165. package/dist/commands/tasks/runs.js +95 -0
  166. package/dist/commands/tasks/show.d.ts +2 -0
  167. package/dist/commands/tasks/show.js +15 -1
  168. package/dist/commands/tasks/start-receipt.d.ts +15 -0
  169. package/dist/commands/tasks/start-receipt.js +95 -0
  170. package/dist/commands/tasks/start.d.ts +4 -0
  171. package/dist/commands/tasks/start.js +49 -3
  172. package/dist/commands/tasks/update.js +3 -0
  173. package/dist/commands/tasks/upsert.js +17 -3
  174. package/dist/commands/tasks/watch.d.ts +3 -0
  175. package/dist/commands/tasks/watch.js +85 -20
  176. package/dist/commands/wiki/history.d.ts +33 -0
  177. package/dist/commands/wiki/history.js +134 -0
  178. package/dist/commands/wiki/ls.d.ts +2 -0
  179. package/dist/commands/wiki/ls.js +8 -0
  180. package/dist/commands/wiki/update.d.ts +3 -1
  181. package/dist/commands/wiki/update.js +24 -2
  182. package/dist/commands/wiki/write.d.ts +22 -0
  183. package/dist/commands/wiki/write.js +144 -6
  184. package/dist/generated/agent-guides.json +81 -81
  185. package/dist/generated/managed-instruction-guides.json +1 -1
  186. package/dist/lib/agent-guides.d.ts +9 -0
  187. package/dist/lib/agent-guides.js +23 -1
  188. package/dist/lib/agentic-stream.d.ts +5 -0
  189. package/dist/lib/agentic-stream.js +122 -3
  190. package/dist/lib/api-fetch.d.ts +4 -0
  191. package/dist/lib/api-fetch.js +25 -7
  192. package/dist/lib/auth-diagnostics.d.ts +39 -0
  193. package/dist/lib/auth-diagnostics.js +71 -0
  194. package/dist/lib/cli-client-identity.d.ts +6 -0
  195. package/dist/lib/cli-client-identity.js +16 -0
  196. package/dist/lib/cli-installation-diagnostics.d.ts +52 -0
  197. package/dist/lib/cli-installation-diagnostics.js +254 -0
  198. package/dist/lib/command-hygiene.d.ts +45 -0
  199. package/dist/lib/command-hygiene.js +413 -0
  200. package/dist/lib/commitments.d.ts +64 -3
  201. package/dist/lib/commitments.js +34 -6
  202. package/dist/lib/completion-index.d.ts +16 -4
  203. package/dist/lib/completion-index.js +50 -14
  204. package/dist/lib/config.js +7 -1
  205. package/dist/lib/daemon-maintenance-command.d.ts +22 -0
  206. package/dist/lib/daemon-maintenance-command.js +39 -0
  207. package/dist/lib/daemon-maintenance.d.ts +275 -0
  208. package/dist/lib/daemon-maintenance.js +1035 -0
  209. package/dist/lib/dedicated-service.d.ts +3 -2
  210. package/dist/lib/dedicated-service.js +11 -3
  211. package/dist/lib/governed-store.d.ts +8 -0
  212. package/dist/lib/governed-store.js +5 -0
  213. package/dist/lib/hosted-machines.d.ts +33 -2
  214. package/dist/lib/hosted-machines.js +19 -1
  215. package/dist/lib/json-output.d.ts +1 -1
  216. package/dist/lib/machines.d.ts +9 -1
  217. package/dist/lib/machines.js +15 -1
  218. package/dist/lib/memory-history-session.d.ts +14 -0
  219. package/dist/lib/memory-history-session.js +60 -0
  220. package/dist/lib/node-adapter.js +13 -0
  221. package/dist/lib/record-output.d.ts +22 -0
  222. package/dist/lib/record-output.js +78 -0
  223. package/dist/lib/roles.d.ts +3 -3
  224. package/dist/lib/scoped-memory-command.d.ts +24 -0
  225. package/dist/lib/scoped-memory-command.js +87 -5
  226. package/dist/lib/space-charter.d.ts +49 -0
  227. package/dist/lib/space-charter.js +78 -0
  228. package/dist/lib/space-loop-migration.d.ts +18 -0
  229. package/dist/lib/space-loop-migration.js +128 -0
  230. package/dist/lib/space-notebook.d.ts +22 -0
  231. package/dist/lib/space-notebook.js +140 -0
  232. package/dist/lib/space-proposal-decision-command.d.ts +36 -0
  233. package/dist/lib/space-proposal-decision-command.js +108 -0
  234. package/dist/lib/space-proposals.d.ts +44 -0
  235. package/dist/lib/space-proposals.js +186 -0
  236. package/dist/lib/space-templates.d.ts +8 -0
  237. package/dist/lib/space-templates.js +17 -0
  238. package/dist/lib/space-write-policy.d.ts +24 -0
  239. package/dist/lib/space-write-policy.js +103 -0
  240. package/dist/lib/task-agent-context-capabilities.d.ts +10 -0
  241. package/dist/lib/task-agent-context-capabilities.js +22 -0
  242. package/dist/lib/task-agent-context-compatibility.d.ts +9 -0
  243. package/dist/lib/task-agent-context-compatibility.js +30 -0
  244. package/dist/lib/task-asset-upload.d.ts +22 -0
  245. package/dist/lib/task-asset-upload.js +257 -29
  246. package/dist/lib/task-batch.d.ts +15 -1
  247. package/dist/lib/task-batch.js +35 -2
  248. package/dist/lib/task-operation-watch.d.ts +66 -0
  249. package/dist/lib/task-operation-watch.js +159 -0
  250. package/dist/lib/task-resolver.d.ts +1 -1
  251. package/dist/lib/task-resolver.js +4 -3
  252. package/dist/lib/task-runtime-headers.js +13 -3
  253. package/dist/lib/task-work.d.ts +1 -1
  254. package/dist/lib/task-work.js +35 -1
  255. package/dist/lib/task-write-attribution.d.ts +14 -0
  256. package/dist/lib/task-write-attribution.js +35 -2
  257. package/dist/lib/triggers.d.ts +11 -0
  258. package/dist/lib/triggers.js +7 -0
  259. package/dist/lib/wiki-update.d.ts +1 -0
  260. package/dist/lib/wiki-update.js +10 -1
  261. package/dist/lib/wiki.js +4 -1
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +9 -1
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +31 -15
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +1 -0
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +13 -7
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.d.ts +370 -0
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.js +315 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.d.ts +178 -0
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.js +262 -0
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.d.ts +51 -0
  271. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.js +106 -0
  272. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +9 -1
  273. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +32 -5
  274. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +1 -0
  275. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +33 -14
  276. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.d.ts +370 -0
  277. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.js +404 -0
  278. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.d.ts +178 -0
  279. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.js +342 -0
  280. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.d.ts +51 -0
  281. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.js +138 -0
  282. package/dist/node_modules/@skrr-ai/auth-core/package.json +20 -0
  283. package/dist/node_modules/@skrr-ai/data-provider/index.js +27085 -20250
  284. package/oclif.manifest.json +10570 -7247
  285. package/package.json +20 -2
@@ -186,6 +186,14 @@ export const DAEMON_COMPUTER_EVENTS = {
186
186
  };
187
187
  export const COMPUTER_EVENT_NAMES = Object.values(COMPUTER_EVENTS);
188
188
  export const DAEMON_COMPUTER_EVENT_NAMES = Object.values(DAEMON_COMPUTER_EVENTS);
189
+ /**
190
+ * API → daemon: an authorized person observes, configures, stops or recovers
191
+ * the machine's Computer Use provider. Answered with `daemon:computer:ack`. It
192
+ * is deliberately outside `DAEMON_COMPUTER_EVENTS`, which lists the events the
193
+ * attachment protocol itself speaks, so the registry parity over that table
194
+ * does not move.
195
+ */
196
+ export const DAEMON_COMPUTER_USE_CONTROL_EVENT = 'daemon:computer:use-control';
189
197
  /** The daemon → API events; every other `daemon:computer:*` event flows API → daemon. */
190
198
  export const DAEMON_COMPUTER_REPORT_EVENT_KEYS = [
191
199
  'ack',
@@ -432,6 +440,14 @@ export const COMPUTER_REFUSAL_CODES = [
432
440
  'too_large',
433
441
  /** The machine has as many declared services as it allows (`COMPUTER_DECLARED_SERVICES_MAX`). */
434
442
  'service_limit',
443
+ /**
444
+ * The machine's owner paused NEW work on it (OSK-19107). Refuses an `open` only:
445
+ * watching, reading files and controlling a surface that already exists keep
446
+ * working, and nothing running is touched. The refusal carries the hold's facts
447
+ * (`maintenance`), and it is not `machine_unavailable`, which says the machine is
448
+ * down: a paused machine is up.
449
+ */
450
+ 'maintenance_hold',
435
451
  ];
436
452
  /**
437
453
  * The code when it is a computer refusal, else `null`. There is one spelling
@@ -1258,7 +1274,8 @@ export function normalizeBrowserActivityOriginPolicy(input) {
1258
1274
  const origins = (items, required) => {
1259
1275
  if (!Array.isArray(items) || items.length > 20 || (required && !items.length))
1260
1276
  throw new Error('Choose from one to twenty allowed origins and up to twenty excluded origins');
1261
- return [...new Set(items.map((item) => {
1277
+ return [
1278
+ ...new Set(items.map((item) => {
1262
1279
  if (typeof item !== 'string' || item.length > 500)
1263
1280
  throw new Error('Use an exact http or https origin without a path, credentials, query or fragment');
1264
1281
  let url;
@@ -1268,19 +1285,29 @@ export function normalizeBrowserActivityOriginPolicy(input) {
1268
1285
  catch {
1269
1286
  throw new Error('Use an exact http or https origin');
1270
1287
  }
1271
- if (!['http:', 'https:'].includes(url.protocol) || url.hostname.includes('*') || url.username || url.password || item !== url.origin)
1288
+ if (!['http:', 'https:'].includes(url.protocol) ||
1289
+ url.hostname.includes('*') ||
1290
+ url.username ||
1291
+ url.password ||
1292
+ item !== url.origin)
1272
1293
  throw new Error('Use an exact http or https origin without a path, credentials, query or fragment');
1273
1294
  return url.origin;
1274
- }))].sort();
1295
+ })),
1296
+ ].sort();
1297
+ };
1298
+ return {
1299
+ allowOrigins: origins(value.allowOrigins, true),
1300
+ excludeOrigins: origins(value.excludeOrigins, false),
1275
1301
  };
1276
- return { allowOrigins: origins(value.allowOrigins, true), excludeOrigins: origins(value.excludeOrigins, false) };
1277
1302
  }
1278
1303
  export function browserActivityOriginAllowed(policy, url) {
1279
1304
  if (typeof url !== 'string')
1280
1305
  return false;
1281
1306
  try {
1282
1307
  const origin = new URL(url).origin;
1283
- return ['http:', 'https:'].includes(new URL(url).protocol) && policy.allowOrigins.includes(origin) && !policy.excludeOrigins.includes(origin);
1308
+ return (['http:', 'https:'].includes(new URL(url).protocol) &&
1309
+ policy.allowOrigins.includes(origin) &&
1310
+ !policy.excludeOrigins.includes(origin));
1284
1311
  }
1285
1312
  catch {
1286
1313
  return false;
@@ -67,6 +67,7 @@ export function categoryForDaemonTool(toolName) {
67
67
  case 'filelist':
68
68
  case 'filestat':
69
69
  case 'filereadtagged':
70
+ case 'personaldata':
70
71
  return 'read';
71
72
  case 'write':
72
73
  case 'edit':
@@ -46,8 +46,8 @@
46
46
  * heard is `firstPartyHarness.ts`'s and the API's `sessionProvider.js`'s
47
47
  * decision, not this table's.
48
48
  */
49
- import { COMPUTER_DESKTOP_CAPABILITY, COMPUTER_DESKTOP_CONTROL_CAPABILITY, DAEMON_COMPUTER_DESKTOP_EVENTS } from './desktopWire.js';
50
- import { COMPUTER_CAPABILITIES, DAEMON_COMPUTER_EVENTS, DAEMON_COMPUTER_REPORT_EVENT_KEYS, } from './computerWire.js';
49
+ import { COMPUTER_DESKTOP_CAPABILITY, COMPUTER_DESKTOP_CONTROL_CAPABILITY, DAEMON_COMPUTER_DESKTOP_EVENTS, } from './desktopWire.js';
50
+ import { COMPUTER_CAPABILITIES, DAEMON_COMPUTER_EVENTS, DAEMON_COMPUTER_REPORT_EVENT_KEYS, DAEMON_COMPUTER_USE_CONTROL_EVENT, } from './computerWire.js';
51
51
  // ---------------------------------------------------------------------------
52
52
  // Vocabulary
53
53
  // ---------------------------------------------------------------------------
@@ -283,34 +283,53 @@ const TOOLS = [
283
283
  capability: TOOL_RESPONSE_OUTBOX,
284
284
  }),
285
285
  toDaemon('daemon:tool:cancel', 'Abandon a running tool call.'),
286
- toDaemon('daemon:computer:use-control', 'An authorized person observes, configures, stops or recovers the machine Computer Use provider.', {
287
- stability: 'experimental', capability: 'computer_use_mcp_v1', delivery: 'acked', answeredBy: 'daemon:computer:ack',
286
+ toDaemon(DAEMON_COMPUTER_USE_CONTROL_EVENT, 'An authorized person observes, configures, stops or recovers the machine Computer Use provider.', {
287
+ stability: 'experimental',
288
+ capability: 'computer_use_mcp_v1',
289
+ delivery: 'acked',
290
+ answeredBy: DAEMON_COMPUTER_EVENTS.ack,
288
291
  payload: { kind: 'zod', schema: 'daemonComputerUseControlSchema' },
289
292
  }),
290
293
  toDaemon('daemon:computer-use:rotate-credential', 'The approved hosted-desktop owner requests credential rotation for this exact active machine lease generation.', {
291
- stability: 'experimental', capability: 'computer_use_mcp_v1', delivery: 'acked', answeredBy: 'daemon:computer:ack',
294
+ stability: 'experimental',
295
+ capability: 'computer_use_mcp_v1',
296
+ delivery: 'acked',
297
+ answeredBy: DAEMON_COMPUTER_EVENTS.ack,
292
298
  payload: { kind: 'zod', schema: 'daemonComputerUseRotateCredentialSchema' },
293
299
  }),
294
300
  toDaemon('daemon:computer-use:revoke', 'Revoke cloud Computer Use bindings after owner machine authority was removed.', {
295
- stability: 'experimental', capability: 'computer_use_mcp_v1',
301
+ stability: 'experimental',
302
+ capability: 'computer_use_mcp_v1',
296
303
  payload: { kind: 'zod', schema: 'daemonComputerUseRevokeSchema' },
297
304
  }),
298
305
  ...['subscribe', 'protocol', 'unsubscribe'].map((operation) => toDaemon(DAEMON_COMPUTER_DESKTOP_EVENTS[operation], `Read-only desktop stream: ${operation}; bound to an authenticated attachment and generation.`, {
299
- stability: 'experimental', capability: COMPUTER_DESKTOP_CAPABILITY,
300
- delivery: 'acked', answeredBy: 'daemon:computer:ack',
301
- payload: { kind: 'zod', schema: `daemonComputerDesktop${operation[0].toUpperCase()}${operation.slice(1)}Schema` },
306
+ stability: 'experimental',
307
+ capability: COMPUTER_DESKTOP_CAPABILITY,
308
+ delivery: 'acked',
309
+ answeredBy: DAEMON_COMPUTER_EVENTS.ack,
310
+ payload: {
311
+ kind: 'zod',
312
+ schema: `daemonComputerDesktop${operation[0].toUpperCase()}${operation.slice(1)}Schema`,
313
+ },
302
314
  })),
303
315
  ...['control', 'input'].map((operation) => toDaemon(DAEMON_COMPUTER_DESKTOP_EVENTS[operation], `Human-only typed desktop ${operation}; exact authenticated attachment, stream and generation.`, {
304
- stability: 'experimental', capability: COMPUTER_DESKTOP_CONTROL_CAPABILITY,
305
- delivery: 'acked', answeredBy: 'daemon:computer:ack',
306
- payload: { kind: 'zod', schema: `daemonComputerDesktop${operation[0].toUpperCase()}${operation.slice(1)}Schema` },
316
+ stability: 'experimental',
317
+ capability: COMPUTER_DESKTOP_CONTROL_CAPABILITY,
318
+ delivery: 'acked',
319
+ answeredBy: DAEMON_COMPUTER_EVENTS.ack,
320
+ payload: {
321
+ kind: 'zod',
322
+ schema: `daemonComputerDesktop${operation[0].toUpperCase()}${operation.slice(1)}Schema`,
323
+ },
307
324
  })),
308
325
  toServer(DAEMON_COMPUTER_DESKTOP_EVENTS.controlChanged, 'Private desktop holder and input revocation fact; never carries a control token.', {
309
- stability: 'experimental', capability: COMPUTER_DESKTOP_CONTROL_CAPABILITY,
326
+ stability: 'experimental',
327
+ capability: COMPUTER_DESKTOP_CONTROL_CAPABILITY,
310
328
  payload: { kind: 'zod', schema: 'computerDesktopControlResultSchema' },
311
329
  }),
312
330
  toServer(DAEMON_COMPUTER_DESKTOP_EVENTS.data, 'Read-only desktop stream data or a terminal close fact for one attachment generation.', {
313
- stability: 'experimental', capability: COMPUTER_DESKTOP_CAPABILITY,
331
+ stability: 'experimental',
332
+ capability: COMPUTER_DESKTOP_CAPABILITY,
314
333
  payload: { kind: 'zod', schema: 'computerDesktopDataSchema' },
315
334
  }),
316
335
  toServer('daemon:wire:chunk', 'One slice of a tool or session response above the single-message ceiling, sha256-checked and reassembled by the API before the reassembled event reaches its normal handler. Sent only to a server that announced `serverCaps.wireChunking`; the last slice is acked by that handler (OSK-16616).', {
@@ -0,0 +1,370 @@
1
+ /**
2
+ * The pure core of a GUIDED update (OSK-19107, Space OSK-S-524, tasks M51 to M53):
3
+ * hold the machine, wait for it to be quiet, update, verify, and give the machine
4
+ * back. The Desktop app and a standalone `skrr` install both run it, so what they
5
+ * decide on, and the words they use for what is in the way, cannot drift apart.
6
+ *
7
+ * This file is DECISIONS ONLY. It performs no I/O, reads no clock and holds no
8
+ * state, so every rule below is a table test. The orchestration (a persisted flow
9
+ * record, polling, the installer, the supervisor) lives with each caller, because
10
+ * that is the part that differs between a Desktop that quits mid-flow and a CLI that
11
+ * runs in the foreground.
12
+ *
13
+ * ## Why these rules (each names the failure it prevents)
14
+ *
15
+ * - **`prepare` is a probe that briefly refuses admitted work.** While it runs the
16
+ * daemon refuses admitted tool calls with an infra-class error, and a tool-proxy Run
17
+ * that sees one drops its tools to the Hosted Machine for good. So a guided flow
18
+ * calls it ONLY when the server's reading says there is nothing admitted to refuse
19
+ * ({@link prepareBasis}), never to find out whether there is.
20
+ * - **`unknown` is an answer.** A source nobody could read is never zero and never
21
+ * ready. {@link noServerVeto} is deliberately strict: every server source must have
22
+ * been read, and none may list active or unproven work.
23
+ * - **A server source can only veto.** Only the daemon's own positively announced
24
+ * report grants `ready`; the owner's attestation and the daemon's own `prepare`
25
+ * (labelled `no_veto`, D38) are the two other bases, and each is labelled as what
26
+ * it is wherever it is shown.
27
+ * - **Blockers are shown in the words of whoever knows them.** The daemon's blocker
28
+ * `reason` and the server's holder `label` are the vocabulary; nothing here
29
+ * re-spells them. They are bounded and never a raw path, because a diagnostic can
30
+ * carry one.
31
+ * - **A new PID, an exit code or a cloud connection is not a verified update.**
32
+ * {@link verifyReplacement} requires the daemon's own `verified`, from a process
33
+ * other than the one that was replaced, for the build that was asked for, and the
34
+ * same machine identity afterwards. A different identity is the reinstall case: the
35
+ * hold is left in place and shown, never resumed.
36
+ *
37
+ * The shapes are STRUCTURAL SUBSETS of `DaemonMaintenanceView` in
38
+ * `@skrr-ai/data-provider` (`daemonMaintenance.ts`), which is the one vocabulary.
39
+ * This package cannot import it (it sits below it), so `guidedUpdate.test.ts` reads
40
+ * that file and fails when a list mirrored here drifts from it.
41
+ */
42
+ export type GuidedHolderClass = 'active' | 'pending_delivery' | 'unproven' | 'forensic';
43
+ export interface GuidedHolder {
44
+ kind: string;
45
+ class: GuidedHolderClass | string;
46
+ ref?: string;
47
+ label?: string;
48
+ since?: string | null;
49
+ detail?: string;
50
+ }
51
+ export interface GuidedSourceReading {
52
+ source: string;
53
+ read: 'ok' | 'unreadable' | 'not_announced' | string;
54
+ cause?: string;
55
+ readAt?: string;
56
+ total?: number;
57
+ holders?: GuidedHolder[];
58
+ truncated?: boolean;
59
+ }
60
+ export interface GuidedViewLike {
61
+ runtimeKey?: string;
62
+ hold: {
63
+ generation: number;
64
+ lifecycle: 'held' | 'released' | string;
65
+ reason?: string;
66
+ requestedAt?: string;
67
+ heldBy?: {
68
+ kind?: string;
69
+ id?: string;
70
+ name?: string;
71
+ };
72
+ attestation?: {
73
+ at?: string;
74
+ by?: string;
75
+ } | null;
76
+ } | null;
77
+ reading: {
78
+ state: 'draining' | 'ready' | 'unknown' | string;
79
+ cause: string | null;
80
+ readAt?: string;
81
+ sources?: GuidedSourceReading[];
82
+ } | null;
83
+ journey: {
84
+ phase: string;
85
+ modifiers?: string[];
86
+ cause?: string | null;
87
+ controls?: string[];
88
+ };
89
+ }
90
+ /** The server sources that can only veto. `daemon_report` is the only one that grants. */
91
+ export declare const GUIDED_SERVER_SOURCES: readonly ["claims", "receipts", "sessions", "runs", "leases", "custody"];
92
+ /** The refusals the owner API names, mirrored from `DAEMON_MAINTENANCE_REFUSALS`. */
93
+ export declare const GUIDED_REFUSALS: readonly ["managed_machine", "no_stable_identity", "not_found", "ambiguous", "generation_conflict", "not_held", "already_held", "attestation_not_applicable", "not_owner", "held_by_other"];
94
+ export type GuidedRefusal = (typeof GUIDED_REFUSALS)[number];
95
+ export declare function isGuidedRefusal(value: unknown): value is GuidedRefusal;
96
+ /** The daemon handoff phases, mirrored from `daemon/src/update/handoff.ts`. */
97
+ export declare const GUIDED_HANDOFF_PHASES: readonly ["ready", "deferred", "reconnecting", "verified", "failed", "rolled-back"];
98
+ /**
99
+ * What a guided flow may do with the server's answer. The flow reads `reading` and
100
+ * the fence, never the Journey's phase alone: a Journey says `back_held` for any
101
+ * process that registered after the fence, and that masks the reading it would
102
+ * otherwise carry.
103
+ */
104
+ export type Readiness =
105
+ /** No live hold on this machine (it was released, or never existed). */
106
+ {
107
+ kind: 'not_held';
108
+ }
109
+ /** A live hold, but not the generation this flow took. Never adopted. */
110
+ | {
111
+ kind: 'generation_changed';
112
+ currentGeneration: number;
113
+ }
114
+ /** The fence is not confirmed on every row, so no reading means anything yet. */
115
+ | {
116
+ kind: 'pausing';
117
+ }
118
+ /** Nothing admitted is running: the daemon's report said so, or the owner vouched. */
119
+ | {
120
+ kind: 'ready';
121
+ basis: 'evidence' | 'attested';
122
+ }
123
+ /** The daemon cannot report. No server source vetoes. Only the daemon's own check may decide. */
124
+ | {
125
+ kind: 'no_report';
126
+ } | {
127
+ kind: 'draining';
128
+ } | {
129
+ kind: 'unknown';
130
+ cause: string | null;
131
+ };
132
+ /**
133
+ * Whether the server holds a reading that nothing vetoes, for a daemon that cannot
134
+ * report (D38). Strict on purpose: a source that is absent from the list, unreadable,
135
+ * truncated, or that names active or unproven work, is a veto. `daemon_report` must
136
+ * be `not_announced`: any other answer means the reading is not the
137
+ * `no_inventory_capability` case this is for.
138
+ */
139
+ export declare function noServerVeto(sources: readonly GuidedSourceReading[] | undefined): boolean;
140
+ /**
141
+ * Read the owner API's view for a flow that took `generation`.
142
+ *
143
+ * Order matters and is the rule set (each is a test):
144
+ * 1. No live hold: `not_held`. A different live generation: `generation_changed`.
145
+ * 2. The fence is not confirmed (`pausing`): nothing below it means anything.
146
+ * 3. The reading is `ready` (the daemon's own report): `ready` by evidence.
147
+ * 4. `draining`: work is running. Evidence, never overridden.
148
+ * 5. `unknown`: ready by attestation if the Journey says the owner vouched for this
149
+ * cause; `no_report` if the daemon cannot report and no source vetoes; else
150
+ * `unknown`. No reading at all is `unknown (source_unreadable)`, never ready.
151
+ */
152
+ export declare function evaluateReadiness(view: GuidedViewLike | null | undefined, expectedGeneration: number | null): Readiness;
153
+ /** How a `prepare` is justified. Labelled on every surface as exactly this. */
154
+ export type PrepareBasis = 'evidence' | 'attested' | 'no_veto';
155
+ /**
156
+ * Whether a guided flow may call the daemon's `prepare`, and on what basis. `null`
157
+ * means NO: `prepare` is never a way to find out. A legacy daemon never gets one:
158
+ * it has no endpoint, and its restart is the owner's attested decision, not a probe.
159
+ */
160
+ export declare function prepareBasis(readiness: Readiness, opts: {
161
+ legacy: boolean;
162
+ }): PrepareBasis | null;
163
+ /**
164
+ * Whether a legacy daemon (no handoff endpoint) may be restarted by the supervisor.
165
+ * Only on the owner's attestation: the daemon cannot report what it is doing and a
166
+ * SIGTERM ends its wrappers, so nothing but the owner's word can vouch for it.
167
+ */
168
+ export declare function legacyRestartAllowed(readiness: Readiness): boolean;
169
+ export interface DaemonBlockerLike {
170
+ kind: string;
171
+ id?: string;
172
+ reason?: string;
173
+ }
174
+ export interface DesktopWorkLike {
175
+ localSessions: number;
176
+ agentBrowserWindows: number;
177
+ }
178
+ export type OwnerBlockerSource = 'server' | 'daemon' | 'desktop';
179
+ export interface OwnerBlocker {
180
+ source: OwnerBlockerSource;
181
+ /** The holder or blocker kind as its owner spelled it, or a `desktop_*` id for the app's own work. */
182
+ kind: string;
183
+ /** The server's label, or the daemon's reason, verbatim after bounding. Absent when it was unsafe to show. */
184
+ text?: string;
185
+ /** A server label for a daemon blocker the server holds under the same ref. */
186
+ label?: string;
187
+ /** A bounded identifier (a session or request id), never a path. */
188
+ id?: string;
189
+ since?: string | null;
190
+ /** For the app's own work: how many. */
191
+ count?: number;
192
+ }
193
+ export declare const MAX_OWNER_BLOCKERS = 20;
194
+ /** A sentence safe to put in front of the owner, or `undefined` when it is not. */
195
+ export declare function sanitizeBlockerText(value: unknown, max?: number): string | undefined;
196
+ /**
197
+ * Everything in the way, from the three places that know: the server's holders
198
+ * (active and unproven work: `pending_delivery` and `forensic` never block), the
199
+ * daemon's own refusal from `prepare`, and the work the Desktop app itself hosts and
200
+ * ends when it quits (`LocalSessionService` processes and agent browser windows,
201
+ * which the daemon's inventory cannot see).
202
+ *
203
+ * A daemon blocker whose id equals a server holder's ref is the same work seen twice:
204
+ * it is listed once, with the daemon's reason and the server's label. Whether the two
205
+ * ids are in fact comparable was never established (review §6.2 item 2), so a match
206
+ * only MERGES the wording and never hides a blocker that has no match.
207
+ */
208
+ export declare function describeBlockers(input: {
209
+ view?: GuidedViewLike | null;
210
+ daemon?: readonly DaemonBlockerLike[] | null;
211
+ desktop?: DesktopWorkLike | null;
212
+ }): OwnerBlocker[];
213
+ /**
214
+ * A string that changes whenever the set of things in the way changes. The "update
215
+ * now anyway" confirmation carries the one it was shown, and the action is refused
216
+ * when it no longer matches: a confirmation that names what WAS running is not a
217
+ * confirmation of what is.
218
+ */
219
+ export declare function blockersFingerprint(blockers: readonly OwnerBlocker[]): string;
220
+ /**
221
+ * The labels the owner is shown, as the server records them in the outcome
222
+ * (`acknowledged`): each bounded to the server's 160-character limit.
223
+ */
224
+ export declare function acknowledgedLabels(blockers: readonly OwnerBlocker[], max?: number): string[];
225
+ export interface HandoffBlocker {
226
+ kind: string;
227
+ id?: string;
228
+ reason: string;
229
+ }
230
+ export interface HandoffStatusLike {
231
+ protocolVersion: 1;
232
+ handoffId: string;
233
+ phase: 'ready' | 'deferred' | 'reconnecting' | 'verified' | 'failed' | 'rolled-back';
234
+ reason: string;
235
+ sourceProcessId: string;
236
+ sourceVersion: string;
237
+ target: {
238
+ path?: string;
239
+ mtimeMs?: number;
240
+ sha256: string;
241
+ };
242
+ blockers: HandoffBlocker[];
243
+ expectedSessions: unknown[];
244
+ adoptedSessionCount?: number;
245
+ verifiedBy?: {
246
+ processId: string;
247
+ version: string;
248
+ };
249
+ observer?: {
250
+ processId: string;
251
+ version: string;
252
+ buildMatches: boolean;
253
+ ready: boolean;
254
+ };
255
+ }
256
+ /**
257
+ * What a call to the daemon's loopback `/v1/update-handoff` came back as.
258
+ *
259
+ * - `absent`: a 404. The daemon answered and has no such endpoint: it predates the
260
+ * handoff (the installed 0.8.117 answers 404 to every path it does not serve). This
261
+ * is the ONLY reply that means "legacy". A refused connection is not.
262
+ * - `unauthorized`: the bootstrap secret was refused (it rotates when the daemon
263
+ * restarts). Re-read the bootstrap and try again.
264
+ * - `refused`: reachable, speaks the protocol, said no (409: no handoff owned, or the
265
+ * lease expired; 400; 413). A refusal is a value the caller shows.
266
+ * - `unreachable`: no bootstrap file, a connection error, a timeout, a malformed or
267
+ * unexpected body. Unknown: never `absent`, never `ready`.
268
+ */
269
+ export type HandoffReply = {
270
+ kind: 'ok';
271
+ status: HandoffStatusLike;
272
+ } | {
273
+ kind: 'absent';
274
+ } | {
275
+ kind: 'unauthorized';
276
+ } | {
277
+ kind: 'refused';
278
+ code?: string;
279
+ } | {
280
+ kind: 'unreachable';
281
+ };
282
+ export declare function classifyHandoffReply(input: {
283
+ /** `null` when no HTTP response arrived at all. */
284
+ statusCode: number | null;
285
+ /** The parsed JSON body, or `undefined` when there was none or it did not parse. */
286
+ body?: unknown;
287
+ }): HandoffReply;
288
+ export interface ReplacementEvidence {
289
+ /** The daemon's own answer to `status` for the handoff, or null when it did not answer. */
290
+ handoff: Pick<HandoffStatusLike, 'phase' | 'verifiedBy' | 'target' | 'reason' | 'observer'> | null;
291
+ expect: {
292
+ sourceProcessId: string;
293
+ targetSha256: string;
294
+ /** The bundled daemon's version, or null when it could not be read (the hash binds it anyway). */
295
+ version: string | null;
296
+ };
297
+ identity: {
298
+ recordedDaemonId: string;
299
+ recordedRuntimeKey: string;
300
+ /** The daemon id of the process now holding the loopback bootstrap, or null when unreadable. */
301
+ bootstrapDaemonId: string | null;
302
+ /** The runtimeKey the machine payload lists for `recordedDaemonId` now, or null when it lists none or could not be read. */
303
+ runtimeKeyNow: string | null;
304
+ };
305
+ }
306
+ export type ReplacementVerdict =
307
+ /** (1) the daemon's `verified` for this build by another process, and (2) the same identity. */
308
+ {
309
+ kind: 'verified';
310
+ } | {
311
+ kind: 'not_yet';
312
+ missing: 'daemon_status' | 'verified' | 'identity_unreadable';
313
+ }
314
+ /** The daemon id or the machine's runtimeKey changed: a reinstall. The hold is left and shown. */
315
+ | {
316
+ kind: 'reinstall';
317
+ what: 'daemon_id' | 'runtime_key';
318
+ } | {
319
+ kind: 'failed';
320
+ phase: 'failed' | 'rolled-back';
321
+ reason: string;
322
+ sameProcess: boolean;
323
+ };
324
+ /**
325
+ * Decide whether a committed replacement is complete. All of (1) and (2) must hold
326
+ * before anything else is asked of the server (3, {@link serverSawNewProcess}), and
327
+ * nothing here resumes: the verdict only says what was seen.
328
+ *
329
+ * An identity that is merely UNREADABLE (the bootstrap is mid-rotation, the machine
330
+ * payload could not be fetched) is `not_yet`, never a reinstall and never verified.
331
+ */
332
+ export declare function verifyReplacement(evidence: ReplacementEvidence): ReplacementVerdict;
333
+ export interface LegacyRestartEvidence {
334
+ before: {
335
+ startedAt: number | null;
336
+ processId: number | null;
337
+ };
338
+ after: {
339
+ daemonId: string | null;
340
+ version: string | null;
341
+ startedAt: number | null;
342
+ processId: number | null;
343
+ };
344
+ expect: {
345
+ daemonId: string;
346
+ version: string | null;
347
+ };
348
+ runtimeKeyNow: string | null;
349
+ recordedRuntimeKey: string;
350
+ }
351
+ /**
352
+ * The legacy counterpart: a daemon with no handoff cannot say `verified`, so the copy
353
+ * claims only what was seen ("restarted on version X"), never "adopted N sessions".
354
+ * A new process (a different start time and, where known, a different PID), the same
355
+ * identity, and the version it announces equal to the bundled one.
356
+ */
357
+ export declare function verifyLegacyRestart(evidence: LegacyRestartEvidence): ReplacementVerdict;
358
+ /**
359
+ * Whether the server independently saw a new process register under the held key
360
+ * (condition 3). The Journey says `back_held` for ANY process that registered since
361
+ * the fence, so it can only corroborate THIS replacement when it did not already say
362
+ * so before the commit. When it did, the answer is `not_independent`: the flow rests
363
+ * on (1) and (2) and says so.
364
+ */
365
+ export declare function serverSawNewProcess(input: {
366
+ journeyPhase: string | null | undefined;
367
+ backHeldAtCommit: boolean;
368
+ }): 'seen' | 'not_yet' | 'not_independent';
369
+ /** Whether an observed hold is the one this flow took, and still live. */
370
+ export declare function isOurLiveHold(view: GuidedViewLike | null | undefined, generation: number | null): boolean;