@skrr-ai/cli 0.1.119 → 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 (276) hide show
  1. package/dist/base-command.d.ts +31 -0
  2. package/dist/base-command.js +106 -4
  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/spaces/auto-executor/compare.d.ts +18 -0
  86. package/dist/commands/spaces/auto-executor/compare.js +139 -0
  87. package/dist/commands/spaces/auto-executor/runs.d.ts +3 -0
  88. package/dist/commands/spaces/auto-executor/runs.js +13 -1
  89. package/dist/commands/spaces/charter/create-from-description.d.ts +21 -0
  90. package/dist/commands/spaces/charter/create-from-description.js +77 -0
  91. package/dist/commands/spaces/charter/show.d.ts +22 -0
  92. package/dist/commands/spaces/charter/show.js +61 -0
  93. package/dist/commands/spaces/heartbeats/list.d.ts +1 -16
  94. package/dist/commands/spaces/heartbeats/list.js +13 -0
  95. package/dist/commands/spaces/install-template.js +3 -0
  96. package/dist/commands/spaces/loops/migrate.d.ts +32 -0
  97. package/dist/commands/spaces/loops/migrate.js +103 -0
  98. package/dist/commands/spaces/loops/release.d.ts +14 -0
  99. package/dist/commands/spaces/loops/release.js +59 -0
  100. package/dist/commands/spaces/notebook.d.ts +25 -0
  101. package/dist/commands/spaces/notebook.js +75 -0
  102. package/dist/commands/spaces/proposals/discard.d.ts +17 -0
  103. package/dist/commands/spaces/proposals/discard.js +17 -0
  104. package/dist/commands/spaces/proposals/keep.d.ts +17 -0
  105. package/dist/commands/spaces/proposals/keep.js +17 -0
  106. package/dist/commands/spaces/proposals/list.d.ts +24 -0
  107. package/dist/commands/spaces/proposals/list.js +89 -0
  108. package/dist/commands/spaces/skills/propose.d.ts +29 -0
  109. package/dist/commands/spaces/skills/propose.js +82 -0
  110. package/dist/commands/spaces/templates/fork.js +3 -0
  111. package/dist/commands/spaces/triggers/show.js +6 -0
  112. package/dist/commands/spaces/workflows/retry.d.ts +1 -0
  113. package/dist/commands/spaces/workflows/retry.js +8 -1
  114. package/dist/commands/spaces/workflows/triggers/create.js +3 -2
  115. package/dist/commands/spaces/workflows/triggers/fire.js +4 -0
  116. package/dist/commands/spaces/workflows/triggers/update.js +2 -1
  117. package/dist/commands/spaces/write-policy/set.d.ts +22 -0
  118. package/dist/commands/spaces/write-policy/set.js +82 -0
  119. package/dist/commands/spaces/write-policy/show.d.ts +19 -0
  120. package/dist/commands/spaces/write-policy/show.js +49 -0
  121. package/dist/commands/store/artifacts/receipt.d.ts +14 -0
  122. package/dist/commands/store/artifacts/receipt.js +34 -0
  123. package/dist/commands/store/artifacts/release.d.ts +2 -0
  124. package/dist/commands/store/artifacts/release.js +11 -0
  125. package/dist/commands/store/governance/publish-release.d.ts +2 -0
  126. package/dist/commands/store/governance/publish-release.js +30 -1
  127. package/dist/commands/store/governance/release-receipt.d.ts +12 -0
  128. package/dist/commands/store/governance/release-receipt.js +32 -0
  129. package/dist/commands/tasks/approvals/list.d.ts +11 -5
  130. package/dist/commands/tasks/approvals/list.js +13 -6
  131. package/dist/commands/tasks/attachments/facts.d.ts +12 -0
  132. package/dist/commands/tasks/attachments/facts.js +29 -0
  133. package/dist/commands/tasks/attachments/upload.d.ts +1 -0
  134. package/dist/commands/tasks/attachments/upload.js +16 -0
  135. package/dist/commands/tasks/bulk-update.js +35 -1
  136. package/dist/commands/tasks/context.d.ts +15 -0
  137. package/dist/commands/tasks/context.js +69 -0
  138. package/dist/commands/tasks/copy.d.ts +18 -0
  139. package/dist/commands/tasks/copy.js +85 -0
  140. package/dist/commands/tasks/create-tree.js +97 -23
  141. package/dist/commands/tasks/create.js +9 -1
  142. package/dist/commands/tasks/deliverable/add.js +20 -10
  143. package/dist/commands/tasks/move.js +8 -1
  144. package/dist/commands/tasks/operations/show.d.ts +16 -0
  145. package/dist/commands/tasks/operations/show.js +98 -0
  146. package/dist/commands/tasks/operations/wait.d.ts +22 -0
  147. package/dist/commands/tasks/operations/wait.js +114 -0
  148. package/dist/commands/tasks/preflight.d.ts +1 -0
  149. package/dist/commands/tasks/preflight.js +11 -1
  150. package/dist/commands/tasks/rearm-recurrence.js +4 -0
  151. package/dist/commands/tasks/result/show.js +22 -0
  152. package/dist/commands/tasks/result/submit.d.ts +1 -0
  153. package/dist/commands/tasks/result/submit.js +3 -0
  154. package/dist/commands/tasks/retry-receipt.d.ts +15 -0
  155. package/dist/commands/tasks/retry-receipt.js +89 -0
  156. package/dist/commands/tasks/retry-review.d.ts +16 -0
  157. package/dist/commands/tasks/retry-review.js +66 -0
  158. package/dist/commands/tasks/retry.d.ts +4 -8
  159. package/dist/commands/tasks/retry.js +34 -68
  160. package/dist/commands/tasks/runs.d.ts +21 -0
  161. package/dist/commands/tasks/runs.js +95 -0
  162. package/dist/commands/tasks/show.d.ts +2 -0
  163. package/dist/commands/tasks/show.js +15 -1
  164. package/dist/commands/tasks/start-receipt.d.ts +15 -0
  165. package/dist/commands/tasks/start-receipt.js +95 -0
  166. package/dist/commands/tasks/start.d.ts +4 -0
  167. package/dist/commands/tasks/start.js +49 -3
  168. package/dist/commands/tasks/update.js +3 -0
  169. package/dist/commands/tasks/upsert.js +17 -3
  170. package/dist/commands/tasks/watch.d.ts +3 -0
  171. package/dist/commands/tasks/watch.js +85 -20
  172. package/dist/commands/wiki/history.d.ts +33 -0
  173. package/dist/commands/wiki/history.js +134 -0
  174. package/dist/commands/wiki/ls.d.ts +2 -0
  175. package/dist/commands/wiki/ls.js +8 -0
  176. package/dist/commands/wiki/update.d.ts +3 -1
  177. package/dist/commands/wiki/update.js +24 -2
  178. package/dist/commands/wiki/write.d.ts +22 -0
  179. package/dist/commands/wiki/write.js +144 -6
  180. package/dist/generated/agent-guides.json +81 -81
  181. package/dist/generated/managed-instruction-guides.json +1 -1
  182. package/dist/lib/agent-guides.d.ts +9 -0
  183. package/dist/lib/agent-guides.js +23 -1
  184. package/dist/lib/agentic-stream.d.ts +5 -0
  185. package/dist/lib/agentic-stream.js +122 -3
  186. package/dist/lib/auth-diagnostics.d.ts +39 -0
  187. package/dist/lib/auth-diagnostics.js +71 -0
  188. package/dist/lib/cli-client-identity.d.ts +6 -0
  189. package/dist/lib/cli-client-identity.js +16 -0
  190. package/dist/lib/cli-installation-diagnostics.d.ts +52 -0
  191. package/dist/lib/cli-installation-diagnostics.js +254 -0
  192. package/dist/lib/command-hygiene.d.ts +45 -0
  193. package/dist/lib/command-hygiene.js +413 -0
  194. package/dist/lib/commitments.d.ts +64 -3
  195. package/dist/lib/commitments.js +34 -6
  196. package/dist/lib/completion-index.d.ts +16 -4
  197. package/dist/lib/completion-index.js +50 -14
  198. package/dist/lib/config.js +7 -1
  199. package/dist/lib/daemon-maintenance-command.d.ts +22 -0
  200. package/dist/lib/daemon-maintenance-command.js +39 -0
  201. package/dist/lib/daemon-maintenance.d.ts +275 -0
  202. package/dist/lib/daemon-maintenance.js +1035 -0
  203. package/dist/lib/dedicated-service.d.ts +3 -2
  204. package/dist/lib/dedicated-service.js +11 -3
  205. package/dist/lib/governed-store.d.ts +8 -0
  206. package/dist/lib/governed-store.js +5 -0
  207. package/dist/lib/hosted-machines.d.ts +33 -2
  208. package/dist/lib/hosted-machines.js +19 -1
  209. package/dist/lib/json-output.d.ts +1 -1
  210. package/dist/lib/machines.d.ts +9 -1
  211. package/dist/lib/machines.js +15 -1
  212. package/dist/lib/node-adapter.js +13 -0
  213. package/dist/lib/record-output.d.ts +22 -0
  214. package/dist/lib/record-output.js +78 -0
  215. package/dist/lib/roles.d.ts +3 -3
  216. package/dist/lib/scoped-memory-command.d.ts +18 -0
  217. package/dist/lib/scoped-memory-command.js +53 -2
  218. package/dist/lib/space-charter.d.ts +49 -0
  219. package/dist/lib/space-charter.js +78 -0
  220. package/dist/lib/space-loop-migration.d.ts +18 -0
  221. package/dist/lib/space-loop-migration.js +128 -0
  222. package/dist/lib/space-notebook.d.ts +22 -0
  223. package/dist/lib/space-notebook.js +140 -0
  224. package/dist/lib/space-proposal-decision-command.d.ts +36 -0
  225. package/dist/lib/space-proposal-decision-command.js +108 -0
  226. package/dist/lib/space-proposals.d.ts +44 -0
  227. package/dist/lib/space-proposals.js +186 -0
  228. package/dist/lib/space-templates.d.ts +8 -0
  229. package/dist/lib/space-templates.js +17 -0
  230. package/dist/lib/space-write-policy.d.ts +24 -0
  231. package/dist/lib/space-write-policy.js +103 -0
  232. package/dist/lib/task-agent-context-capabilities.d.ts +10 -0
  233. package/dist/lib/task-agent-context-capabilities.js +22 -0
  234. package/dist/lib/task-agent-context-compatibility.d.ts +9 -0
  235. package/dist/lib/task-agent-context-compatibility.js +30 -0
  236. package/dist/lib/task-asset-upload.d.ts +22 -0
  237. package/dist/lib/task-asset-upload.js +257 -29
  238. package/dist/lib/task-batch.d.ts +15 -1
  239. package/dist/lib/task-batch.js +35 -2
  240. package/dist/lib/task-operation-watch.d.ts +66 -0
  241. package/dist/lib/task-operation-watch.js +159 -0
  242. package/dist/lib/task-resolver.d.ts +1 -1
  243. package/dist/lib/task-resolver.js +4 -3
  244. package/dist/lib/task-work.d.ts +1 -1
  245. package/dist/lib/task-work.js +35 -1
  246. package/dist/lib/task-write-attribution.d.ts +14 -0
  247. package/dist/lib/task-write-attribution.js +35 -2
  248. package/dist/lib/triggers.d.ts +11 -0
  249. package/dist/lib/triggers.js +7 -0
  250. package/dist/lib/wiki-update.d.ts +1 -0
  251. package/dist/lib/wiki-update.js +10 -1
  252. package/dist/lib/wiki.js +4 -1
  253. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +9 -1
  254. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +31 -15
  255. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +1 -0
  256. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +13 -7
  257. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.d.ts +370 -0
  258. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/guidedUpdate.js +315 -0
  259. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.d.ts +178 -0
  260. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/maintenanceReportWire.js +262 -0
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.d.ts +51 -0
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/toolApprovalSignature.js +106 -0
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +9 -1
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +32 -5
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +1 -0
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +33 -14
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.d.ts +370 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/guidedUpdate.js +404 -0
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.d.ts +178 -0
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/maintenanceReportWire.js +342 -0
  271. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.d.ts +51 -0
  272. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/toolApprovalSignature.js +138 -0
  273. package/dist/node_modules/@skrr-ai/auth-core/package.json +20 -0
  274. package/dist/node_modules/@skrr-ai/data-provider/index.js +27085 -20250
  275. package/oclif.manifest.json +10566 -7247
  276. package/package.json +20 -2
@@ -0,0 +1,342 @@
1
+ /**
2
+ * The maintenance report wire contract (Machine Maintenance, OSK-19107, task M24;
3
+ * `docs/architecture/machine-maintenance/implementation-plan-2026-10-24.md` §3.5,
4
+ * `phase0/m04-quiescence-evidence.md` §2.5 and §2.6).
5
+ *
6
+ * Declared ONCE, here. The daemon is published and cannot import the API, so the
7
+ * capability name, the payload shape and its bounds live in this package, which
8
+ * every end can import (`@skrr-ai/auth-core/maintenance-report-wire`).
9
+ * `maintenanceReportWire.test.ts` fails on a second spelling of the capability
10
+ * anywhere else in the repo. The shape follows `dedicatedRuntimeBusyWire.ts`, the
11
+ * precedent for a positively announced, fail-closed report, and differs from it
12
+ * only where the owner's pause needs more.
13
+ *
14
+ * WHAT THE REPORT SAYS
15
+ * ---------------------------------------------------------------------------
16
+ * "What does this daemon process hold right now that an update would take from
17
+ * the owner, and has anything been admitted since the last time you asked?" It is
18
+ * a LOCAL read summarised into counts, the handoff's own restart blockers, and
19
+ * the daemon's own update handoff phase.
20
+ *
21
+ * It is EVIDENCE, never authority. The fence does not depend on it: a daemon that
22
+ * lies, or one that sends nothing, cannot make a held machine accept work. Only
23
+ * this report can grant `ready` (a server-side source can only veto it), and a
24
+ * daemon that never announces the capability can only reach `ready` by the
25
+ * owner's attestation.
26
+ *
27
+ * FAIL CLOSED, in three places
28
+ * ---------------------------------------------------------------------------
29
+ * 1. A count is `0` only when the daemon positively counted. A source that could
30
+ * not be read is `complete: 'unknown'`; a daemon that is leaving is
31
+ * `complete: false`. A reader MUST treat both as busy, whatever the counts
32
+ * say (`maintenanceReportIsQuiet` is the one place that says so).
33
+ * 2. A report that is malformed in ANY field is `null` from
34
+ * `parseMaintenanceReport`, and the caller treats the machine as not quiet.
35
+ * A count that is missing, negative, fractional or not a safe integer is not
36
+ * "zero": it is a different, broken report. A version this parser does not
37
+ * know is `null` too: a newer shape needs its own announced capability.
38
+ * 3. Bounds. The blocker list and every string are clamped, so one report can
39
+ * never be large enough to matter, and a field that is NOT in the contract is
40
+ * never copied into what the parser returns (the result is built from a
41
+ * fresh object, so `__proto__` and its kin cannot ride along).
42
+ *
43
+ * `admittedTotal`
44
+ * ---------------------------------------------------------------------------
45
+ * A MONOTONIC counter of admissions since this process started. The server proves
46
+ * "nothing was admitted between two reports" by comparing two values, without
47
+ * trusting the daemon's clock. It counts at every place the daemon admits work
48
+ * and OVER-counts on purpose (one admission may be noted at the gate and again
49
+ * where the work registers): a second increment can only make the proof harder,
50
+ * never easier. A path that the daemon cannot count must say so in
51
+ * `daemon/src/maintenance-report.ts`, not hide in a zero.
52
+ */
53
+ export const MAINTENANCE_REPORT_CAPABILITY = 'maintenance_report_v1';
54
+ /** The heartbeat (and register) key the report rides under. Sent only by a daemon that announced the capability. */
55
+ export const MAINTENANCE_REPORT_HEARTBEAT_KEY = 'maintenanceReport';
56
+ export const MAINTENANCE_REPORT_VERSION = 1;
57
+ /**
58
+ * The daemon's own update handoff phases (`daemon/src/update/handoff.ts`), and the
59
+ * members of `DaemonMaintenanceHandoff.phase` in `@skrr-ai/data-provider`. A phase
60
+ * outside this list is a newer protocol and makes the whole report `null`.
61
+ */
62
+ export const MAINTENANCE_REPORT_HANDOFF_PHASES = [
63
+ 'ready',
64
+ 'deferred',
65
+ 'reconnecting',
66
+ 'verified',
67
+ 'failed',
68
+ 'rolled-back',
69
+ ];
70
+ export const MAINTENANCE_REPORT_LIMITS = {
71
+ /** The handoff's blockers carried for the "waiting on" text; the counts, not this list, decide busy. */
72
+ maxBlockers: 32,
73
+ maxKindLength: 32,
74
+ maxIdLength: 128,
75
+ maxReasonLength: 240,
76
+ maxHandoffIdLength: 64,
77
+ maxHandoffReasonLength: 64,
78
+ maxProcessStartIdLength: 64,
79
+ /** Hard ceiling on the serialized report. The clamps above keep a valid one well under it. */
80
+ maxSerializedBytes: 20_000,
81
+ };
82
+ const PROCESS_START_ID_PATTERN = /^[A-Za-z0-9_.:-]+$/;
83
+ // C0 controls and DEL. A blocker's text is shown to an owner and logged.
84
+ // eslint-disable-next-line no-control-regex
85
+ const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/g;
86
+ function isRecord(value) {
87
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
88
+ }
89
+ /**
90
+ * An OWN property, or `undefined`. A key the sender did not put on the object
91
+ * itself is never read from its prototype chain, so a polluted `Object.prototype`
92
+ * (or a sender that smuggles a `__proto__`) cannot supply a field the report
93
+ * did not carry.
94
+ */
95
+ function field(record, key) {
96
+ return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;
97
+ }
98
+ /** ISO text for an epoch-ms value, or `''` when the value is not a representable time. */
99
+ function isoFromMs(ms) {
100
+ if (typeof ms !== 'number' || !Number.isFinite(ms))
101
+ return '';
102
+ const date = new Date(ms);
103
+ return Number.isNaN(date.getTime()) ? '' : date.toISOString();
104
+ }
105
+ function count(value) {
106
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null;
107
+ }
108
+ function clampText(value, max) {
109
+ if (typeof value !== 'string')
110
+ return null;
111
+ const clean = value.replace(CONTROL_CHARACTERS, ' ');
112
+ return clean.length > max ? clean.slice(0, max) : clean;
113
+ }
114
+ function isoOf(value) {
115
+ if (typeof value !== 'string')
116
+ return null;
117
+ const ms = Date.parse(value);
118
+ if (!Number.isFinite(ms))
119
+ return null;
120
+ try {
121
+ return new Date(ms).toISOString();
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
127
+ function completeOf(value) {
128
+ return value === true || value === false || value === 'unknown' ? value : undefined;
129
+ }
130
+ /**
131
+ * The reader's view of a daemon's heartbeat section. Anything malformed, from a
132
+ * daemon that did not announce the capability, an unknown version, or oversized
133
+ * is `null`, and the caller must then treat the machine as NOT quiet. Never
134
+ * trusts a field it did not validate and never copies one it does not know.
135
+ */
136
+ export function parseMaintenanceReport(raw) {
137
+ if (!isRecord(raw))
138
+ return null;
139
+ if (field(raw, 'version') !== MAINTENANCE_REPORT_VERSION)
140
+ return null;
141
+ const processStartId = field(raw, 'processStartId');
142
+ if (typeof processStartId !== 'string' ||
143
+ processStartId.length < 1 ||
144
+ processStartId.length > MAINTENANCE_REPORT_LIMITS.maxProcessStartIdLength ||
145
+ !PROCESS_START_ID_PATTERN.test(processStartId)) {
146
+ return null;
147
+ }
148
+ const readAt = isoOf(field(raw, 'readAt'));
149
+ if (readAt === null)
150
+ return null;
151
+ const complete = completeOf(field(raw, 'complete'));
152
+ if (complete === undefined)
153
+ return null;
154
+ const admittedTotal = count(field(raw, 'admittedTotal'));
155
+ if (admittedTotal === null)
156
+ return null;
157
+ const rawInflight = field(raw, 'inflight');
158
+ if (!isRecord(rawInflight))
159
+ return null;
160
+ const sessions = count(field(rawInflight, 'sessions'));
161
+ const tools = count(field(rawInflight, 'tools'));
162
+ const terminals = count(field(rawInflight, 'terminals'));
163
+ const providerDependencies = count(field(rawInflight, 'providerDependencies'));
164
+ const walUnconfirmed = count(field(rawInflight, 'walUnconfirmed'));
165
+ if (sessions === null ||
166
+ tools === null ||
167
+ terminals === null ||
168
+ providerDependencies === null ||
169
+ walUnconfirmed === null) {
170
+ return null;
171
+ }
172
+ const rawBlockers = field(raw, 'blockers');
173
+ if (!Array.isArray(rawBlockers))
174
+ return null;
175
+ const rawTruncated = field(raw, 'blockersTruncated');
176
+ if (rawTruncated !== undefined && typeof rawTruncated !== 'boolean')
177
+ return null;
178
+ const limit = MAINTENANCE_REPORT_LIMITS.maxBlockers;
179
+ const blockers = [];
180
+ // Only the first `limit` elements are looked at: the work is bounded by the
181
+ // contract, not by what the sender chose to send.
182
+ for (let index = 0; index < rawBlockers.length && blockers.length < limit; index += 1) {
183
+ const element = rawBlockers[index];
184
+ if (!isRecord(element))
185
+ return null;
186
+ const kind = clampText(field(element, 'kind'), MAINTENANCE_REPORT_LIMITS.maxKindLength);
187
+ const reason = clampText(field(element, 'reason'), MAINTENANCE_REPORT_LIMITS.maxReasonLength);
188
+ if (kind === null || kind === '' || reason === null)
189
+ return null;
190
+ const blocker = { kind, reason };
191
+ const rawId = field(element, 'id');
192
+ if (rawId !== undefined) {
193
+ const id = clampText(rawId, MAINTENANCE_REPORT_LIMITS.maxIdLength);
194
+ if (id === null)
195
+ return null;
196
+ blocker.id = id;
197
+ }
198
+ blockers.push(blocker);
199
+ }
200
+ const blockersTruncated = rawBlockers.length > limit || rawTruncated === true;
201
+ // The key is part of the contract: `null` says "no handoff", and an absent key
202
+ // says nothing, which is not a way to claim there is none.
203
+ const rawHandoff = field(raw, 'handoff');
204
+ if (rawHandoff === undefined)
205
+ return null;
206
+ let handoff = null;
207
+ if (rawHandoff !== null) {
208
+ if (!isRecord(rawHandoff))
209
+ return null;
210
+ const phase = field(rawHandoff, 'phase');
211
+ if (!MAINTENANCE_REPORT_HANDOFF_PHASES.includes(phase))
212
+ return null;
213
+ const handoffId = clampText(field(rawHandoff, 'handoffId'), MAINTENANCE_REPORT_LIMITS.maxHandoffIdLength);
214
+ if (handoffId === null || handoffId === '')
215
+ return null;
216
+ handoff = { phase: phase, handoffId };
217
+ const rawReason = field(rawHandoff, 'reason');
218
+ if (rawReason !== undefined) {
219
+ const reason = clampText(rawReason, MAINTENANCE_REPORT_LIMITS.maxHandoffReasonLength);
220
+ if (reason === null)
221
+ return null;
222
+ handoff.reason = reason;
223
+ }
224
+ const rawExpiresAt = field(rawHandoff, 'expiresAt');
225
+ if (rawExpiresAt !== undefined) {
226
+ const expiresAt = isoOf(rawExpiresAt);
227
+ if (expiresAt === null)
228
+ return null;
229
+ handoff.expiresAt = expiresAt;
230
+ }
231
+ }
232
+ const report = {
233
+ version: MAINTENANCE_REPORT_VERSION,
234
+ processStartId,
235
+ readAt,
236
+ complete,
237
+ admittedTotal,
238
+ inflight: { sessions, tools, terminals, providerDependencies, walUnconfirmed },
239
+ blockers,
240
+ blockersTruncated,
241
+ handoff,
242
+ };
243
+ if (JSON.stringify(report).length > MAINTENANCE_REPORT_LIMITS.maxSerializedBytes)
244
+ return null;
245
+ return report;
246
+ }
247
+ /**
248
+ * A report as it was stored (JSON text on the presence row). Anything that does
249
+ * not parse, or does not validate, is `null`: a stored value is an input like any
250
+ * other and is read with the same suspicion.
251
+ */
252
+ export function parseStoredMaintenanceReport(stored) {
253
+ if (typeof stored !== 'string' || stored === '')
254
+ return null;
255
+ if (stored.length > MAINTENANCE_REPORT_LIMITS.maxSerializedBytes)
256
+ return null;
257
+ try {
258
+ return parseMaintenanceReport(JSON.parse(stored));
259
+ }
260
+ catch {
261
+ return null;
262
+ }
263
+ }
264
+ /**
265
+ * The one definition of a POSITIVE ZERO: the daemon read every source and found
266
+ * nothing. `complete: 'unknown'` and `complete: false` are never zero whatever
267
+ * the counts say, because the counts were not (all) read.
268
+ *
269
+ * A blocker that is not work (a missing restart owner, say) does not make a
270
+ * report non-quiet; readiness is "nothing is running", not "the daemon can
271
+ * restart itself".
272
+ */
273
+ export function maintenanceReportIsQuiet(report) {
274
+ if (!report)
275
+ return false;
276
+ if (report.complete !== true)
277
+ return false;
278
+ const { sessions, tools, terminals, providerDependencies, walUnconfirmed } = report.inflight;
279
+ return (sessions === 0 &&
280
+ tools === 0 &&
281
+ terminals === 0 &&
282
+ providerDependencies === 0 &&
283
+ walUnconfirmed === 0);
284
+ }
285
+ /**
286
+ * A report that says nothing was counted. The shape the daemon sends when it
287
+ * could not read an inventory source at all, and the shape `buildMaintenanceReport`
288
+ * falls back to when it was handed something the contract cannot carry.
289
+ */
290
+ export function unknownMaintenanceReport(processStartId, readAtMs, admittedTotal = 0) {
291
+ return {
292
+ version: MAINTENANCE_REPORT_VERSION,
293
+ processStartId,
294
+ readAt: isoFromMs(readAtMs) || new Date(0).toISOString(),
295
+ complete: 'unknown',
296
+ admittedTotal: count(admittedTotal) ?? 0,
297
+ inflight: { sessions: 0, tools: 0, terminals: 0, providerDependencies: 0, walUnconfirmed: 0 },
298
+ blockers: [],
299
+ blockersTruncated: false,
300
+ handoff: null,
301
+ };
302
+ }
303
+ /**
304
+ * Build the wire report from what the daemon read. Input the contract cannot
305
+ * carry (a negative count, a blocker with no kind, a time that is not a time)
306
+ * becomes an `unknown` report rather than a throw or a report that parses to
307
+ * something else, so the result parses whenever `processStartId` is a real id (the
308
+ * daemon's always is). A builder that threw would turn a bad read into silence,
309
+ * and silence is the absence of a report, which the server reads the same way,
310
+ * but later.
311
+ */
312
+ export function buildMaintenanceReport(input) {
313
+ const blockers = input.blockers
314
+ .slice(0, MAINTENANCE_REPORT_LIMITS.maxBlockers)
315
+ .map((blocker) => ({
316
+ kind: blocker.kind,
317
+ ...(blocker.id !== undefined ? { id: blocker.id } : {}),
318
+ reason: blocker.reason,
319
+ }));
320
+ const candidate = {
321
+ version: MAINTENANCE_REPORT_VERSION,
322
+ processStartId: input.processStartId,
323
+ readAt: isoFromMs(input.readAtMs),
324
+ complete: input.complete,
325
+ admittedTotal: input.admittedTotal,
326
+ inflight: { ...input.inflight },
327
+ blockers,
328
+ blockersTruncated: input.blockers.length > MAINTENANCE_REPORT_LIMITS.maxBlockers,
329
+ handoff: input.handoff
330
+ ? {
331
+ phase: input.handoff.phase,
332
+ handoffId: input.handoff.handoffId,
333
+ ...(input.handoff.reason !== undefined ? { reason: input.handoff.reason } : {}),
334
+ ...(input.handoff.expiresAtMs !== undefined
335
+ ? { expiresAt: isoFromMs(input.handoff.expiresAtMs) }
336
+ : {}),
337
+ }
338
+ : null,
339
+ };
340
+ return (parseMaintenanceReport(candidate) ??
341
+ unknownMaintenanceReport(input.processStartId, input.readAtMs, input.admittedTotal));
342
+ }
@@ -177,6 +177,57 @@ export declare function signToolApproval(args: {
177
177
  now?: number;
178
178
  ttlMs?: number;
179
179
  }): SignedToolApproval;
180
+ /** A short-lived platform-signed assertion for exactly one local executor. */
181
+ export interface PersonalDataExecutorLeasePayload {
182
+ v: 1;
183
+ leaseId: string;
184
+ /** The daemon identity registered for this machine. */
185
+ daemonId: string;
186
+ /** Fresh random daemon-start nonce; restart invalidates every prior lease. */
187
+ daemonInstanceId: string;
188
+ /** Account whose interactive session requested this local executor. */
189
+ ownerUserId: string;
190
+ /** Fixed, sorted set of operations this executor may make available. */
191
+ capabilities: string[];
192
+ issuedAt: number;
193
+ expiresAt: number;
194
+ }
195
+ export interface SignedPersonalDataExecutorLease {
196
+ v: 1;
197
+ payload: string;
198
+ kid: string;
199
+ sig: string;
200
+ }
201
+ export type PersonalDataExecutorLeaseVerdict = {
202
+ ok: true;
203
+ leaseId: string;
204
+ ownerUserId: string;
205
+ expiresAt: number;
206
+ } | {
207
+ ok: false;
208
+ reason: 'absent' | 'malformed' | 'unknown_key' | 'signature' | 'daemon_binding' | 'capabilities' | 'expired' | 'window';
209
+ };
210
+ /** Server-side mint. The caller must authorize the requesting user separately. */
211
+ export declare function signPersonalDataExecutorLease(args: {
212
+ leaseId: string;
213
+ daemonId: string;
214
+ daemonInstanceId: string;
215
+ ownerUserId: string;
216
+ capabilities: readonly string[];
217
+ signer: ApprovalSigner;
218
+ now?: number;
219
+ ttlMs?: number;
220
+ }): SignedPersonalDataExecutorLease | null;
221
+ /**
222
+ * Daemon-side verifier. It trusts the same independently pinned platform
223
+ * keyset as v2 tool approvals, but a separate signature domain and schema.
224
+ */
225
+ export declare function verifyPersonalDataExecutorLease(lease: unknown, expected: {
226
+ daemonId: string;
227
+ daemonInstanceId: string;
228
+ capabilities: readonly string[];
229
+ now?: number;
230
+ }, keyset: ApprovalKeyset): PersonalDataExecutorLeaseVerdict;
180
231
  export interface SignedToolApprovalCall {
181
232
  toolUseId: string;
182
233
  toolName: string;
@@ -44,6 +44,13 @@ export const TOOL_APPROVAL_SIGNED_CAPABILITY = 'tool_approval_signed_v1';
44
44
  */
45
45
  const ATTESTATION_SIGNING_DOMAIN = 'skrr-tool-approval-v2\n';
46
46
  const KEYSET_SIGNING_DOMAIN = 'skrr-tool-approval-keyset-v1\n';
47
+ /**
48
+ * A distinct domain for the local personal-data executor. A tool approval is
49
+ * a user's decision about one action; an executor lease is evidence that the
50
+ * platform authenticated one particular trusted local process. Neither
51
+ * signature can be substituted for the other.
52
+ */
53
+ const PERSONAL_DATA_EXECUTOR_LEASE_SIGNING_DOMAIN = 'skrr-personal-data-executor-lease-v1\n';
47
54
  /** A key id: short, printable, and safe to put in a log line. */
48
55
  const KID_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
49
56
  /** Bounds on untrusted wire input, so a hostile document cannot cost much. */
@@ -51,6 +58,11 @@ const MAX_PAYLOAD_BYTES = 4096;
51
58
  const MAX_KEYSET_BYTES = 16 * 1024;
52
59
  const MAX_KEYSET_KEYS = 16;
53
60
  const MAX_KEYSET_SIGNATURES = 16;
61
+ const MAX_EXECUTOR_LEASE_CAPABILITIES = 8;
62
+ const MAX_EXECUTOR_LEASE_TTL_MS = 5 * 60 * 1000;
63
+ const EXECUTOR_LEASE_CLOCK_SKEW_MS = 30_000;
64
+ const EXECUTOR_LEASE_ID_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;
65
+ const EXECUTOR_CAPABILITY_PATTERN = /^[a-z0-9_.:-]{1,128}$/;
54
66
  /** Derive the wire public key from a private (or public) Ed25519 KeyObject. */
55
67
  export function approvalPublicKeyFromKeyObject(kid, key) {
56
68
  const publicKey = key.type === 'private' ? createPublicKey(key) : key;
@@ -86,6 +98,24 @@ function verifySignature(domain, message, sigB64, key) {
86
98
  function signMessage(domain, message, privateKey) {
87
99
  return signEd25519(null, Buffer.from(domain + message, 'utf8'), privateKey).toString('base64');
88
100
  }
101
+ function isExecutorLeaseId(value) {
102
+ return typeof value === 'string' && EXECUTOR_LEASE_ID_PATTERN.test(value);
103
+ }
104
+ function isExecutorLeaseText(value, max = 128) {
105
+ return typeof value === 'string' && value.length > 0 && value.length <= max && !/[\u0000-\u001f]/.test(value);
106
+ }
107
+ function canonicalExecutorCapabilities(value) {
108
+ if (!Array.isArray(value) || value.length === 0 || value.length > MAX_EXECUTOR_LEASE_CAPABILITIES) {
109
+ return null;
110
+ }
111
+ const capabilities = value.map((entry) => typeof entry === 'string' ? entry : '');
112
+ if (capabilities.some((entry) => !EXECUTOR_CAPABILITY_PATTERN.test(entry)))
113
+ return null;
114
+ const sorted = [...capabilities].sort();
115
+ if (new Set(sorted).size !== sorted.length)
116
+ return null;
117
+ return sorted;
118
+ }
89
119
  /** Code-unit order: the same on every runtime, unlike `localeCompare`. */
90
120
  function compareKid(a, b) {
91
121
  if (a === b)
@@ -255,6 +285,114 @@ export function signToolApproval(args) {
255
285
  sig: signMessage(ATTESTATION_SIGNING_DOMAIN, text, args.signer.privateKey),
256
286
  };
257
287
  }
288
+ /** Server-side mint. The caller must authorize the requesting user separately. */
289
+ export function signPersonalDataExecutorLease(args) {
290
+ const capabilities = canonicalExecutorCapabilities(args.capabilities);
291
+ const ttlMs = args.ttlMs ?? MAX_EXECUTOR_LEASE_TTL_MS;
292
+ const now = args.now ?? Date.now();
293
+ if (!isExecutorLeaseId(args.leaseId) ||
294
+ !isExecutorLeaseText(args.daemonId) ||
295
+ !isExecutorLeaseId(args.daemonInstanceId) ||
296
+ !isExecutorLeaseText(args.ownerUserId) ||
297
+ !capabilities ||
298
+ !Number.isSafeInteger(now) ||
299
+ !Number.isSafeInteger(ttlMs) ||
300
+ ttlMs <= 0 ||
301
+ ttlMs > MAX_EXECUTOR_LEASE_TTL_MS) {
302
+ return null;
303
+ }
304
+ const payload = {
305
+ v: 1,
306
+ leaseId: args.leaseId,
307
+ daemonId: args.daemonId,
308
+ daemonInstanceId: args.daemonInstanceId,
309
+ ownerUserId: args.ownerUserId,
310
+ capabilities,
311
+ issuedAt: now,
312
+ expiresAt: now + ttlMs,
313
+ };
314
+ const text = canonicalApprovalJson(payload);
315
+ return {
316
+ v: 1,
317
+ payload: text,
318
+ kid: args.signer.kid,
319
+ sig: signMessage(PERSONAL_DATA_EXECUTOR_LEASE_SIGNING_DOMAIN, text, args.signer.privateKey),
320
+ };
321
+ }
322
+ /**
323
+ * Daemon-side verifier. It trusts the same independently pinned platform
324
+ * keyset as v2 tool approvals, but a separate signature domain and schema.
325
+ */
326
+ export function verifyPersonalDataExecutorLease(lease, expected, keyset) {
327
+ if (lease === undefined || lease === null)
328
+ return { ok: false, reason: 'absent' };
329
+ if (!lease || typeof lease !== 'object' || Array.isArray(lease)) {
330
+ return { ok: false, reason: 'malformed' };
331
+ }
332
+ const wire = lease;
333
+ if (wire.v !== 1 ||
334
+ typeof wire.payload !== 'string' ||
335
+ wire.payload.length === 0 ||
336
+ wire.payload.length > MAX_PAYLOAD_BYTES ||
337
+ typeof wire.kid !== 'string' ||
338
+ typeof wire.sig !== 'string') {
339
+ return { ok: false, reason: 'malformed' };
340
+ }
341
+ const pinnedKey = keyset.keys.find((key) => key.kid === wire.kid);
342
+ const key = pinnedKey ? ed25519PublicKey(pinnedKey.publicKeySpkiB64) : null;
343
+ if (!key)
344
+ return { ok: false, reason: 'unknown_key' };
345
+ if (!verifySignature(PERSONAL_DATA_EXECUTOR_LEASE_SIGNING_DOMAIN, wire.payload, wire.sig, key)) {
346
+ return { ok: false, reason: 'signature' };
347
+ }
348
+ let parsed;
349
+ try {
350
+ parsed = JSON.parse(wire.payload);
351
+ }
352
+ catch {
353
+ return { ok: false, reason: 'malformed' };
354
+ }
355
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
356
+ return { ok: false, reason: 'malformed' };
357
+ }
358
+ const payload = parsed;
359
+ const issuedAt = payload.issuedAt;
360
+ const expiresAt = payload.expiresAt;
361
+ const capabilities = canonicalExecutorCapabilities(payload.capabilities);
362
+ if (payload.v !== 1 ||
363
+ !isExecutorLeaseId(payload.leaseId) ||
364
+ !isExecutorLeaseText(payload.daemonId) ||
365
+ !isExecutorLeaseId(payload.daemonInstanceId) ||
366
+ !isExecutorLeaseText(payload.ownerUserId) ||
367
+ !capabilities ||
368
+ typeof issuedAt !== 'number' ||
369
+ typeof expiresAt !== 'number' ||
370
+ !Number.isSafeInteger(issuedAt) ||
371
+ !Number.isSafeInteger(expiresAt)) {
372
+ return { ok: false, reason: 'malformed' };
373
+ }
374
+ const expectedCapabilities = canonicalExecutorCapabilities(expected.capabilities);
375
+ if (!expectedCapabilities || capabilities.join('\u0000') !== expectedCapabilities.join('\u0000')) {
376
+ return { ok: false, reason: 'capabilities' };
377
+ }
378
+ if (payload.daemonId !== expected.daemonId || payload.daemonInstanceId !== expected.daemonInstanceId) {
379
+ return { ok: false, reason: 'daemon_binding' };
380
+ }
381
+ const now = expected.now ?? Date.now();
382
+ if (expiresAt <= issuedAt ||
383
+ expiresAt - issuedAt > MAX_EXECUTOR_LEASE_TTL_MS ||
384
+ issuedAt > now + EXECUTOR_LEASE_CLOCK_SKEW_MS) {
385
+ return { ok: false, reason: 'window' };
386
+ }
387
+ if (expiresAt <= now)
388
+ return { ok: false, reason: 'expired' };
389
+ return {
390
+ ok: true,
391
+ leaseId: payload.leaseId,
392
+ ownerUserId: payload.ownerUserId,
393
+ expiresAt,
394
+ };
395
+ }
258
396
  /**
259
397
  * Daemon side: verify a v2 attestation against the pinned keyset and the call.
260
398
  * Order matters: nothing in the payload is READ until the signature verified
@@ -114,6 +114,16 @@
114
114
  "default": "./dist/cjs/dedicatedRuntimeBusyWire.js"
115
115
  }
116
116
  },
117
+ "./maintenance-report-wire": {
118
+ "import": {
119
+ "types": "./dist/esm/maintenanceReportWire.d.ts",
120
+ "default": "./dist/esm/maintenanceReportWire.js"
121
+ },
122
+ "require": {
123
+ "types": "./dist/cjs/maintenanceReportWire.d.ts",
124
+ "default": "./dist/cjs/maintenanceReportWire.js"
125
+ }
126
+ },
117
127
  "./computer-wire": {
118
128
  "import": {
119
129
  "types": "./dist/esm/computerWire.d.ts",
@@ -264,6 +274,16 @@
264
274
  "default": "./dist/cjs/restartArtifact.js"
265
275
  }
266
276
  },
277
+ "./guided-update": {
278
+ "import": {
279
+ "types": "./dist/esm/guidedUpdate.d.ts",
280
+ "default": "./dist/esm/guidedUpdate.js"
281
+ },
282
+ "require": {
283
+ "types": "./dist/cjs/guidedUpdate.d.ts",
284
+ "default": "./dist/cjs/guidedUpdate.js"
285
+ }
286
+ },
267
287
  "./tool-operation-outcome": {
268
288
  "import": {
269
289
  "types": "./dist/esm/toolOperationOutcome.d.ts",