@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,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const daemon_maintenance_command_1 = require("../../../lib/daemon-maintenance-command");
5
+ const daemon_maintenance_1 = require("../../../lib/daemon-maintenance");
6
+ class DaemonMaintenanceAttest extends daemon_maintenance_command_1.DaemonMaintenanceCommand {
7
+ static description = 'Say the machine is ready when it cannot say so itself (--ready), or proceed anyway while work is still running (--proceed). Recorded as your word, never as evidence from the machine. The hold stays in force until you resume it.';
8
+ static examples = [
9
+ '<%= config.bin %> daemon maintenance attest "Studio Mac" --ready',
10
+ '<%= config.bin %> daemon maintenance attest "Studio Mac" --proceed',
11
+ '<%= config.bin %> daemon maintenance attest rk1:7c2e…:default --ready --json',
12
+ ];
13
+ static args = {
14
+ machine: core_1.Args.string({
15
+ ignoreStdin: true,
16
+ required: false,
17
+ description: 'Machine id, name or runtimeKey of a held machine. Omit it only when exactly one machine is held.',
18
+ }),
19
+ };
20
+ static flags = {
21
+ ready: core_1.Flags.boolean({
22
+ description: 'I have checked: mark it ready. Only accepted when the machine cannot report what is running, or a stop was never proven.',
23
+ }),
24
+ proceed: core_1.Flags.boolean({
25
+ description: 'Proceed anyway: record that you are updating while the reading shows work running or unreadable, naming what was shown.',
26
+ }),
27
+ generation: core_1.Flags.integer({
28
+ min: 1,
29
+ description: 'The generation of the hold this applies to. Without it, the live one.',
30
+ }),
31
+ json: core_1.Flags.boolean({
32
+ description: 'Print exactly one JSON document (schema 1) and nothing else on stdout',
33
+ }),
34
+ };
35
+ async run() {
36
+ this.requireAuth();
37
+ const { args, flags } = await this.parse(DaemonMaintenanceAttest);
38
+ if (flags.ready === flags.proceed) {
39
+ this.conclude((0, daemon_maintenance_1.invalidFlagRun)('attest', flags.ready
40
+ ? 'Pass --ready or --proceed, not both.'
41
+ : 'Pass --ready (it is ready) or --proceed (update anyway).'), flags.json);
42
+ return;
43
+ }
44
+ const run = await (0, daemon_maintenance_1.runAttest)({
45
+ ref: args.machine,
46
+ kind: flags.ready ? 'attest_ready' : 'proceed_anyway',
47
+ generation: flags.generation,
48
+ }, (0, daemon_maintenance_1.defaultIo)((line) => this.progressLine(line)));
49
+ this.conclude(run, flags.json);
50
+ }
51
+ }
52
+ exports.default = DaemonMaintenanceAttest;
@@ -0,0 +1,17 @@
1
+ import { DaemonMaintenanceCommand } from '../../../lib/daemon-maintenance-command';
2
+ export default class DaemonMaintenanceHold extends DaemonMaintenanceCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ machine: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ 'auto-resume': import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ wait: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ timeout: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ explain: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const daemon_maintenance_command_1 = require("../../../lib/daemon-maintenance-command");
6
+ const daemon_maintenance_1 = require("../../../lib/daemon-maintenance");
7
+ class DaemonMaintenanceHold extends daemon_maintenance_command_1.DaemonMaintenanceCommand {
8
+ static description = 'Hold NEW work on one of your own machines. Nothing that is running is stopped. With --wait ready, wait until the machine says it is safe to update: exit 0 ready, 1 refused, 2 still pending at the timeout, 3 unknown. A timeout never releases the hold.';
9
+ static examples = [
10
+ '<%= config.bin %> daemon maintenance hold "Studio Mac" --reason "Updating the daemon"',
11
+ '<%= config.bin %> daemon maintenance hold "Studio Mac" --wait ready --timeout 30m',
12
+ '<%= config.bin %> daemon maintenance hold "Studio Mac" --auto-resume --wait ready --json',
13
+ '<%= config.bin %> daemon maintenance hold rk1:7c2e…:default --wait ready --explain',
14
+ ];
15
+ static args = {
16
+ machine: core_1.Args.string({
17
+ ignoreStdin: true,
18
+ required: false,
19
+ description: 'Machine id, name or runtimeKey. A machine that runs several profiles is ambiguous: name one daemon by its runtimeKey. Omit it only when exactly one daemon qualifies.',
20
+ }),
21
+ };
22
+ static flags = {
23
+ reason: core_1.Flags.string({
24
+ description: `Why, at most ${data_provider_1.DAEMON_MAINTENANCE_REASON_MAX_LENGTH} characters. Anyone the machine is shared with can read it.`,
25
+ }),
26
+ 'auto-resume': core_1.Flags.boolean({
27
+ description: 'Release the hold by itself when the machine comes back on a new process',
28
+ default: false,
29
+ }),
30
+ wait: core_1.Flags.string({
31
+ options: ['ready'],
32
+ description: "Wait until the machine is ready. The state it waits for is the server's, never a guess made here.",
33
+ }),
34
+ timeout: core_1.Flags.string({
35
+ description: 'How long --wait waits, such as 90s, 30m or 2h (default 30m, at most 24h). Reaching it does NOT release the hold.',
36
+ }),
37
+ explain: core_1.Flags.boolean({
38
+ description: 'Show how the state was reached: each source that was read, in order, and what it found',
39
+ }),
40
+ json: core_1.Flags.boolean({
41
+ description: 'Print exactly one JSON document (schema 1) and nothing else on stdout; progress goes to stderr',
42
+ }),
43
+ };
44
+ async run() {
45
+ this.requireAuth();
46
+ const { args, flags } = await this.parse(DaemonMaintenanceHold);
47
+ if (flags.timeout !== undefined && flags.wait === undefined) {
48
+ this.conclude((0, daemon_maintenance_1.invalidFlagRun)('hold', '--timeout only applies with --wait ready.'), flags.json);
49
+ return;
50
+ }
51
+ let wait;
52
+ if (flags.wait !== undefined) {
53
+ const timeout = (0, daemon_maintenance_1.parseTimeout)(flags.timeout);
54
+ if (!timeout.ok) {
55
+ this.conclude((0, daemon_maintenance_1.invalidFlagRun)('hold', timeout.message), flags.json);
56
+ return;
57
+ }
58
+ wait = { timeoutMs: timeout.ms };
59
+ }
60
+ const run = await (0, daemon_maintenance_1.runHold)({
61
+ ref: args.machine,
62
+ reason: flags.reason,
63
+ autoResume: flags['auto-resume'],
64
+ wait,
65
+ explain: flags.explain,
66
+ }, (0, daemon_maintenance_1.defaultIo)((line) => this.progressLine(line)));
67
+ this.conclude(run, flags.json);
68
+ }
69
+ }
70
+ exports.default = DaemonMaintenanceHold;
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ /**
3
+ * `skrr daemon maintenance` — the topic page.
4
+ *
5
+ * Says the model once: a hold stops NEW work on a machine and never touches what is
6
+ * running, so an update can wait for the work to finish instead of cutting it off.
7
+ */
8
+ export default class DaemonMaintenance extends Command {
9
+ static description: string;
10
+ static examples: string[];
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ /**
5
+ * `skrr daemon maintenance` — the topic page.
6
+ *
7
+ * Says the model once: a hold stops NEW work on a machine and never touches what is
8
+ * running, so an update can wait for the work to finish instead of cutting it off.
9
+ */
10
+ class DaemonMaintenance extends core_1.Command {
11
+ static description = 'Hold new work on one of your own machines so you can update it without losing what is running: hold it, wait until it is ready, update it, resume it. A hold never stops anything that is already running.';
12
+ static examples = [
13
+ '<%= config.bin %> daemon maintenance hold "Studio Mac" --reason "Updating the daemon" --wait ready --timeout 30m',
14
+ '<%= config.bin %> daemon maintenance status',
15
+ '<%= config.bin %> daemon maintenance resume "Studio Mac"',
16
+ '<%= config.bin %> daemon maintenance attest "Studio Mac" --ready',
17
+ ];
18
+ async run() {
19
+ this.log('Hold new work on one of your own machines while you update it:');
20
+ this.log(' skrr daemon maintenance hold stop NEW work on a machine; --wait ready waits for it to be safe');
21
+ this.log(' skrr daemon maintenance status what is held, and whether it is ready');
22
+ this.log(' skrr daemon maintenance resume release a hold; work that waited starts again');
23
+ this.log(' skrr daemon maintenance attest say the machine is ready, when it cannot say so itself');
24
+ this.log('');
25
+ this.log('A hold stops starts, never what is running. Waiting that times out does NOT release it.');
26
+ this.log('Exit codes of `hold --wait ready`: 0 ready, 1 refused, 2 still pending at the timeout, 3 unknown.');
27
+ this.log('Machines managed by the platform (hosted, Dedicated) cannot be held: they are updated for you.');
28
+ }
29
+ }
30
+ exports.default = DaemonMaintenance;
@@ -0,0 +1,13 @@
1
+ import { DaemonMaintenanceCommand } from '../../../lib/daemon-maintenance-command';
2
+ export default class DaemonMaintenanceResume extends DaemonMaintenanceCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ machine: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ generation: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const daemon_maintenance_command_1 = require("../../../lib/daemon-maintenance-command");
5
+ const daemon_maintenance_1 = require("../../../lib/daemon-maintenance");
6
+ class DaemonMaintenanceResume extends daemon_maintenance_command_1.DaemonMaintenanceCommand {
7
+ static description = 'Release a hold: new work can start on the machine again, and work that waited behind the hold starts by itself.';
8
+ static examples = [
9
+ '<%= config.bin %> daemon maintenance resume "Studio Mac"',
10
+ '<%= config.bin %> daemon maintenance resume "Studio Mac" --generation 3',
11
+ '<%= config.bin %> daemon maintenance resume rk1:7c2e…:default --json',
12
+ ];
13
+ static args = {
14
+ machine: core_1.Args.string({
15
+ ignoreStdin: true,
16
+ required: false,
17
+ description: 'Machine id, name or runtimeKey of a held machine. Omit it only when exactly one machine is held.',
18
+ }),
19
+ };
20
+ static flags = {
21
+ generation: core_1.Flags.integer({
22
+ min: 1,
23
+ description: 'Release exactly this generation of the hold (the number `status` shows). Without it, the live one. If the hold changed since, nothing is released and the current generation is named.',
24
+ }),
25
+ json: core_1.Flags.boolean({
26
+ description: 'Print exactly one JSON document (schema 1) and nothing else on stdout',
27
+ }),
28
+ };
29
+ async run() {
30
+ this.requireAuth();
31
+ const { args, flags } = await this.parse(DaemonMaintenanceResume);
32
+ const run = await (0, daemon_maintenance_1.runResume)({ ref: args.machine, generation: flags.generation }, (0, daemon_maintenance_1.defaultIo)((line) => this.progressLine(line)));
33
+ this.conclude(run, flags.json);
34
+ }
35
+ }
36
+ exports.default = DaemonMaintenanceResume;
@@ -0,0 +1,13 @@
1
+ import { DaemonMaintenanceCommand } from '../../../lib/daemon-maintenance-command';
2
+ export default class DaemonMaintenanceStatus extends DaemonMaintenanceCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ machine: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ explain: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const daemon_maintenance_command_1 = require("../../../lib/daemon-maintenance-command");
5
+ const daemon_maintenance_1 = require("../../../lib/daemon-maintenance");
6
+ class DaemonMaintenanceStatus extends daemon_maintenance_command_1.DaemonMaintenanceCommand {
7
+ static description = 'Show what is held and whether it is ready: every hold you have, or one machine';
8
+ static examples = [
9
+ '<%= config.bin %> daemon maintenance status',
10
+ '<%= config.bin %> daemon maintenance status "Studio Mac"',
11
+ '<%= config.bin %> daemon maintenance status "Studio Mac" --explain',
12
+ '<%= config.bin %> daemon maintenance status rk1:7c2e…:default --json',
13
+ ];
14
+ static args = {
15
+ machine: core_1.Args.string({
16
+ ignoreStdin: true,
17
+ required: false,
18
+ description: 'Machine id, name or runtimeKey. Omit it to list every hold you have, orphaned ones included.',
19
+ }),
20
+ };
21
+ static flags = {
22
+ json: core_1.Flags.boolean({
23
+ description: 'Print exactly one JSON document (schema 1) and nothing else on stdout',
24
+ }),
25
+ explain: core_1.Flags.boolean({
26
+ description: 'Show how the state was reached: each source that was read, in order, and what it found',
27
+ }),
28
+ };
29
+ async run() {
30
+ this.requireAuth();
31
+ const { args, flags } = await this.parse(DaemonMaintenanceStatus);
32
+ const run = await (0, daemon_maintenance_1.runStatus)({ ref: args.machine, explain: flags.explain }, (0, daemon_maintenance_1.defaultIo)((line) => this.progressLine(line)));
33
+ this.conclude(run, flags.json);
34
+ }
35
+ }
36
+ exports.default = DaemonMaintenanceStatus;
@@ -1,4 +1,5 @@
1
1
  import { BaseCommand } from '../base-command';
2
+ import { type CliInstallationDiagnostics } from '../lib/cli-installation-diagnostics';
2
3
  type OclifPluginAvailability = {
3
4
  configured: string[];
4
5
  missing: string[];
@@ -25,7 +26,9 @@ export declare function configuredOclifPluginAvailability(root: string): OclifPl
25
26
  * same CLI: a named question per check, a mark, and the remedy beside the
26
27
  * failure. `--json` is unchanged.
27
28
  */
28
- export declare function doctorCheckLines(checks: Record<string, boolean>, issues: string[], bin: string): string[];
29
+ export declare function doctorCheckLines(checks: Record<string, boolean>, issues: string[], bin: string, remedies?: Record<string, (bin: string) => string>): string[];
30
+ /** Render the same installation facts as --json without hiding PATH precedence. */
31
+ export declare function doctorInstallationLines(diagnostics: CliInstallationDiagnostics): string[];
29
32
  export default class Doctor extends BaseCommand {
30
33
  static description: string;
31
34
  static examples: string[];
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.configuredOclifPluginAvailability = configuredOclifPluginAvailability;
37
37
  exports.doctorCheckLines = doctorCheckLines;
38
+ exports.doctorInstallationLines = doctorInstallationLines;
38
39
  const fs = __importStar(require("node:fs"));
39
40
  const path = __importStar(require("node:path"));
40
41
  const core_1 = require("@oclif/core");
@@ -50,6 +51,7 @@ const command_manifest_1 = require("../lib/command-manifest");
50
51
  const completion_index_1 = require("../lib/completion-index");
51
52
  const runtime_context_1 = require("../lib/runtime-context");
52
53
  const deployed_build_1 = require("../lib/deployed-build");
54
+ const cli_installation_diagnostics_1 = require("../lib/cli-installation-diagnostics");
53
55
  const outbox_1 = require("../lib/outbox");
54
56
  /**
55
57
  * What each check actually verifies, in the words a reader thinks in.
@@ -84,6 +86,7 @@ const ISSUE_REMEDIES = {
84
86
  control_plane_unavailable_auth_not_verifiable: () => 'The server is down, not your credential — retry when it is back.',
85
87
  auth_token_present_but_user_lookup_failed: (bin) => `The server rejected the credential. Sign in again: ${bin} login`,
86
88
  not_signed_in_or_no_token_available: (bin) => `Sign in: ${bin} login — or in --bare mode, set OVERSKY_TOKEN.`,
89
+ cli_installation_version_drift: () => 'Inspect the installation section below before changing PATH or removing any package.',
87
90
  };
88
91
  /**
89
92
  * Oclif loads configured plugins before it dispatches a command. A stale
@@ -131,7 +134,7 @@ function configuredOclifPluginAvailability(root) {
131
134
  * same CLI: a named question per check, a mark, and the remedy beside the
132
135
  * failure. `--json` is unchanged.
133
136
  */
134
- function doctorCheckLines(checks, issues, bin) {
137
+ function doctorCheckLines(checks, issues, bin, remedies = ISSUE_REMEDIES) {
135
138
  const lines = ['Checks:'];
136
139
  for (const [key, passed] of Object.entries(checks)) {
137
140
  const label = CHECK_LABELS[key] || key;
@@ -141,13 +144,37 @@ function doctorCheckLines(checks, issues, bin) {
141
144
  lines.push('', 'Issues:');
142
145
  for (const issue of issues) {
143
146
  lines.push(` - ${issue}`);
144
- const remedy = ISSUE_REMEDIES[issue];
147
+ const remedy = remedies[issue];
145
148
  if (remedy)
146
149
  lines.push(` ${remedy(bin)}`);
147
150
  }
148
151
  }
149
152
  return lines;
150
153
  }
154
+ /** Render the same installation facts as --json without hiding PATH precedence. */
155
+ function doctorInstallationLines(diagnostics) {
156
+ const lines = ['CLI installations:'];
157
+ if (!diagnostics.active) {
158
+ lines.push(' Active: could not identify this CLI package from local metadata.');
159
+ }
160
+ else {
161
+ lines.push(` Active: v${diagnostics.active.version} — ${diagnostics.active.paths[0]} ` +
162
+ `(${diagnostics.active.owner})`);
163
+ }
164
+ for (const candidate of diagnostics.candidates) {
165
+ if (candidate.pathPrecedence === null)
166
+ continue;
167
+ lines.push(` PATH #${candidate.pathPrecedence}: v${candidate.version} — ${candidate.paths[0]}` +
168
+ (candidate.active ? ' (active package)' : ''));
169
+ }
170
+ for (const candidate of diagnostics.unrecognisedExecutables) {
171
+ const location = candidate.pathPrecedence === null ? candidate.source : `PATH #${candidate.pathPrecedence}`;
172
+ lines.push(` ${location}: ${candidate.path} (not recognised as @skrr-ai/cli)`);
173
+ }
174
+ if (diagnostics.remedy)
175
+ lines.push(` Remedy: ${diagnostics.remedy}`);
176
+ return lines;
177
+ }
151
178
  class Doctor extends base_command_1.BaseCommand {
152
179
  static description = 'Check whether the skrr CLI is ready for agent automation';
153
180
  static examples = ['<%= config.bin %> doctor', '<%= config.bin %> doctor --json'];
@@ -162,11 +189,14 @@ class Doctor extends base_command_1.BaseCommand {
162
189
  const pkgFile = path.join(root, 'package.json');
163
190
  const binFile = path.join(root, 'bin', 'run.js');
164
191
  const oclifPlugins = configuredOclifPluginAvailability(root);
165
- const credential = (0, auth_storage_1.readFromBackend)(this.cliConfig.baseURL);
192
+ const installations = (0, cli_installation_diagnostics_1.inspectCliInstallations)({ activeRoot: root });
193
+ const credential = this.bareMode
194
+ ? { bundle: null, backend: 'none', originStatus: 'none' }
195
+ : (0, auth_storage_1.readFromBackend)(this.cliConfig.baseURL);
166
196
  // Completion data is auxiliary to diagnosis. Refresh it opportunistically
167
197
  // here so normal maintenance keeps Tab data current, but do not let a
168
198
  // network outage make `skrr doctor` itself fail.
169
- await (0, completion_index_1.refreshCompletionIndex)(this.config.cacheDir);
199
+ await (0, completion_index_1.refreshCompletionIndex)(this.config.cacheDir, this.completionCacheScope());
170
200
  let manifestLoaded = false;
171
201
  let commandCount = 0;
172
202
  let hasContext = false;
@@ -277,10 +307,12 @@ class Doctor extends base_command_1.BaseCommand {
277
307
  ? ['auth_token_present_but_user_lookup_failed']
278
308
  : []),
279
309
  ...(!checks.authToken ? ['not_signed_in_or_no_token_available'] : []),
310
+ ...(installations.hasVersionDrift ? ['cli_installation_version_drift'] : []),
280
311
  ...(credential.ownerStatus === 'foreign'
281
312
  ? ['stored_credential_belongs_to_another_skrr_config_run_skrr_login']
282
313
  : []),
283
314
  ];
315
+ const authResolution = this.authResolution();
284
316
  const payload = {
285
317
  ok: issues.length === 0,
286
318
  cli: {
@@ -290,7 +322,10 @@ class Doctor extends base_command_1.BaseCommand {
290
322
  node: process.version,
291
323
  command: process.argv.slice(1).join(' '),
292
324
  },
325
+ installations,
293
326
  server: this.cliConfig.baseURL,
327
+ // Additive provenance: keep the legacy `server` string unchanged.
328
+ serverSource: authResolution.server.source,
294
329
  // The commit the server's API image and its published web shell were
295
330
  // each built from. They differ whenever a release changed only one.
296
331
  deployed,
@@ -324,6 +359,7 @@ class Doctor extends base_command_1.BaseCommand {
324
359
  'invalidated and re-authenticating will not help — retry once the service recovers.',
325
360
  }
326
361
  : null,
362
+ resolution: authResolution,
327
363
  },
328
364
  runtime: (0, runtime_context_1.readRuntimeContext)(),
329
365
  // OSK-2806 — the incident surface. During an outage a user is looking at
@@ -357,7 +393,7 @@ class Doctor extends base_command_1.BaseCommand {
357
393
  return;
358
394
  }
359
395
  this.log(`skrr CLI ${payload.cli.version} at ${root}`);
360
- this.log(`Server: ${payload.server}`);
396
+ this.log(`Server: ${authResolution.server.origin ?? 'configured server (invalid URL)'} (${payload.serverSource})`);
361
397
  for (const line of (0, deployed_build_1.deployedBuildLines)(deployed))
362
398
  this.log(line);
363
399
  this.log(`Auth: ${payload.auth.signedIn
@@ -365,6 +401,8 @@ class Doctor extends base_command_1.BaseCommand {
365
401
  : serverReachability === 'unavailable'
366
402
  ? 'unverifiable — the server is not responding'
367
403
  : 'not signed in'}`);
404
+ if (!payload.auth.signedIn)
405
+ this.log(`Auth resolution: ${authResolution.suggestion}`);
368
406
  const queued = payload.service.queuedWrites;
369
407
  if (queued > 0) {
370
408
  this.log(`Queued: ${queued} write(s) held locally because the API was unavailable — ` +
@@ -382,7 +420,13 @@ class Doctor extends base_command_1.BaseCommand {
382
420
  this.log(`Plugins: missing ${oclifPlugins.missing.join(', ')}`);
383
421
  }
384
422
  this.log('');
385
- for (const line of doctorCheckLines(checks, issues, this.config.bin))
423
+ for (const line of doctorInstallationLines(installations))
424
+ this.log(line);
425
+ this.log('');
426
+ for (const line of doctorCheckLines(checks, issues, this.config.bin, {
427
+ ...ISSUE_REMEDIES,
428
+ cli_installation_version_drift: () => installations.remedy ?? 'Inspect the installation section below before changing PATH or removing any package.',
429
+ }))
386
430
  this.log(line);
387
431
  if (issues.length > 0) {
388
432
  this.exit(1);
@@ -90,14 +90,17 @@ class CancelContinuityBatch extends base_command_1.BaseCommand {
90
90
  this.handleApiError(err);
91
91
  return;
92
92
  }
93
+ const unconfirmed = !result.complete ||
94
+ result.outcomes.some((outcome) => outcome.status === 'failed' || outcome.status === 'unknown');
95
+ // The document is printed before the exit code is set, so `ok` is decided
96
+ // here: a batch with a failed or unconfirmed member must not read as a success.
93
97
  if (flags.json)
94
- this.log(JSON.stringify(result, null, 2));
98
+ this.printJsonResult(result, { ok: !unconfirmed });
95
99
  else {
96
100
  for (const outcome of result.outcomes)
97
101
  this.log(`${outcome.id}: ${outcome.status}${outcome.plan ? ` [${outcome.plan.state}] r${outcome.plan.revision}` : ''}${outcome.code ? ` (${outcome.code})` : ''}`);
98
102
  }
99
- if (!result.complete ||
100
- result.outcomes.some((outcome) => outcome.status === 'failed' || outcome.status === 'unknown')) {
103
+ if (unconfirmed) {
101
104
  if (!flags.json)
102
105
  this.log('Some cancellations were not confirmed. Read their current state and revisions before making another change.');
103
106
  process.exitCode = result.outcomes.some((outcome) => outcome.status === 'unknown') ? 5 : 2;
@@ -18,14 +18,18 @@ class LookbackPlansCapacity extends base_command_1.BaseCommand {
18
18
  agentId = (0, followups_1.resolveFollowUpAgent)(flags.agent).id;
19
19
  }
20
20
  catch (err) {
21
- this.failWithCliError({ message: err instanceof Error ? err.message : String(err),
22
- code: 'AGENT_CONTEXT_AMBIGUOUS', exit: 2, retryable: false });
21
+ this.failWithCliError({
22
+ message: err instanceof Error ? err.message : String(err),
23
+ code: 'AGENT_CONTEXT_AMBIGUOUS',
24
+ exit: 2,
25
+ retryable: false,
26
+ });
23
27
  return;
24
28
  }
25
29
  try {
26
30
  const result = await lookbackPlans_1.lookbackPlansApi.capacity({ agentId });
27
31
  if (flags.json) {
28
- this.log(JSON.stringify(result, null, 2));
32
+ this.printJsonResult(result);
29
33
  return;
30
34
  }
31
35
  this.log(`${result.scope.agentId}: ${result.remaining}/${result.limit} plans remaining (${result.used} admitted this UTC day).`);
@@ -7,7 +7,10 @@ const followups_1 = require("../../../lib/followups");
7
7
  class LookbackPlansObservability extends base_command_1.BaseCommand {
8
8
  static description = 'Inspect bounded lookback scheduling health and evaluation outcomes';
9
9
  static flags = {
10
- agent: core_1.Flags.string({ description: 'Agent ID (default: bound session agent)', exclusive: ['all-agents'] }),
10
+ agent: core_1.Flags.string({
11
+ description: 'Agent ID (default: bound session agent)',
12
+ exclusive: ['all-agents'],
13
+ }),
11
14
  'all-agents': core_1.Flags.boolean({ description: 'Inspect all owned agents', exclusive: ['agent'] }),
12
15
  limit: core_1.Flags.integer({ description: 'Maximum sampled plans (1..100)', min: 1, max: 100 }),
13
16
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
@@ -20,13 +23,18 @@ class LookbackPlansObservability extends base_command_1.BaseCommand {
20
23
  agentId = flags['all-agents'] ? undefined : (0, followups_1.resolveFollowUpAgent)(flags.agent).id;
21
24
  }
22
25
  catch (err) {
23
- this.failWithCliError({ message: err instanceof Error ? err.message : String(err), code: 'AGENT_CONTEXT_AMBIGUOUS', exit: 2, retryable: false });
26
+ this.failWithCliError({
27
+ message: err instanceof Error ? err.message : String(err),
28
+ code: 'AGENT_CONTEXT_AMBIGUOUS',
29
+ exit: 2,
30
+ retryable: false,
31
+ });
24
32
  return;
25
33
  }
26
34
  try {
27
35
  const result = await lookbackPlans_1.lookbackPlansApi.observability({ agentId, limit: flags.limit });
28
36
  if (flags.json) {
29
- this.log(JSON.stringify(result, null, 2));
37
+ this.printJsonResult(result);
30
38
  return;
31
39
  }
32
40
  this.log(`${result.sample.plans} plans sampled${result.sample.truncated ? ' (more exist)' : ''}.`);
@@ -9,7 +9,10 @@ class SetContinuityPreferences extends base_command_1.BaseCommand {
9
9
  static description = 'Update conversation continuity preferences using the exact selected-scope revision';
10
10
  static flags = {
11
11
  agent: core_1.Flags.string({ description: 'Agent override scope; must agree with agentId in input' }),
12
- 'from-json': core_1.Flags.string({ description: 'JSON update with expectedRevision and settings or inherit:true; - reads stdin', required: true }),
12
+ 'from-json': core_1.Flags.string({
13
+ description: 'JSON update with expectedRevision and settings or inherit:true; - reads stdin',
14
+ required: true,
15
+ }),
13
16
  json: core_1.Flags.boolean({ description: 'Output the authoritative preference envelope as JSON' }),
14
17
  };
15
18
  async run() {
@@ -20,7 +23,12 @@ class SetContinuityPreferences extends base_command_1.BaseCommand {
20
23
  body = (0, continuityPreferences_1.continuityPreferencesInput)(await (0, prompt_1.readJsonBody)(flags['from-json']), flags.agent);
21
24
  }
22
25
  catch (err) {
23
- this.failWithCliError({ code: 'CONTINUITY_PREFERENCES_INVALID', message: err instanceof Error ? err.message : String(err), exit: 2, retryable: false });
26
+ this.failWithCliError({
27
+ code: 'CONTINUITY_PREFERENCES_INVALID',
28
+ message: err instanceof Error ? err.message : String(err),
29
+ exit: 2,
30
+ retryable: false,
31
+ });
24
32
  return;
25
33
  }
26
34
  let result;
@@ -29,19 +37,29 @@ class SetContinuityPreferences extends base_command_1.BaseCommand {
29
37
  }
30
38
  catch (err) {
31
39
  if ((0, lookbackPlans_1.isLookbackMutationOutcomeUnknown)(err)) {
32
- const current = await lookbackPlans_1.lookbackPlansApi.preferences({ agentId: body.agentId }).catch(() => null);
33
- this.failWithCliError({ code: 'CONTINUITY_PREFERENCES_OUTCOME_UNCONFIRMED',
40
+ const current = await lookbackPlans_1.lookbackPlansApi
41
+ .preferences({ agentId: body.agentId })
42
+ .catch(() => null);
43
+ this.failWithCliError({
44
+ code: 'CONTINUITY_PREFERENCES_OUTCOME_UNCONFIRMED',
34
45
  message: 'The preference update outcome could not be confirmed. Read the same scope before deciding on another change.',
35
- exit: 5, retryable: false, details: { scope: { agentId: body.agentId || null }, expectedRevision: body.expectedRevision,
36
- readback: current ? 'observed' : 'unavailable', ...(current ? { currentPreferences: current } : {}),
37
- remedy: 'Do not blindly retry. Read the selected scope and use its current revision for any deliberate new update.' } });
46
+ exit: 5,
47
+ retryable: false,
48
+ details: {
49
+ scope: { agentId: body.agentId || null },
50
+ expectedRevision: body.expectedRevision,
51
+ readback: current ? 'observed' : 'unavailable',
52
+ ...(current ? { currentPreferences: current } : {}),
53
+ remedy: 'Do not blindly retry. Read the selected scope and use its current revision for any deliberate new update.',
54
+ },
55
+ });
38
56
  return;
39
57
  }
40
58
  this.handleApiError(err);
41
59
  return;
42
60
  }
43
61
  if (flags.json)
44
- this.log(JSON.stringify(result, null, 2));
62
+ this.printJsonResult(result);
45
63
  else
46
64
  for (const line of (0, continuityPreferences_1.continuityPreferencesLines)(result))
47
65
  this.log(line);
@@ -16,7 +16,7 @@ class ContinuityPreferences extends base_command_1.BaseCommand {
16
16
  try {
17
17
  const result = await lookbackPlans_1.lookbackPlansApi.preferences({ agentId: flags.agent });
18
18
  if (flags.json)
19
- this.log(JSON.stringify(result, null, 2));
19
+ this.printJsonResult(result);
20
20
  else
21
21
  for (const line of (0, continuityPreferences_1.continuityPreferencesLines)(result))
22
22
  this.log(line);
@@ -13,7 +13,7 @@ class LookbackPlansShow extends base_command_1.BaseCommand {
13
13
  try {
14
14
  const result = await lookbackPlans_1.lookbackPlansApi.show(args.id);
15
15
  if (flags.json) {
16
- this.log(JSON.stringify(result, null, 2));
16
+ this.printJsonResult(result);
17
17
  return;
18
18
  }
19
19
  this.log((0, lookbackPlans_1.lookbackPlanSummary)(result.plan));