@skrr-ai/cli 0.1.46 → 0.1.48

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 (305) hide show
  1. package/README.md +1 -1
  2. package/dist/base-command.d.ts +18 -0
  3. package/dist/base-command.js +61 -1
  4. package/dist/commands/agents/chat.d.ts +21 -0
  5. package/dist/commands/agents/chat.js +26 -9
  6. package/dist/commands/balance/usage/breakdown.d.ts +14 -0
  7. package/dist/commands/balance/usage/breakdown.js +68 -0
  8. package/dist/commands/balance/usage.js +24 -0
  9. package/dist/commands/code/handover.d.ts +2 -2
  10. package/dist/commands/code/handover.js +12 -13
  11. package/dist/commands/code/install.js +31 -0
  12. package/dist/commands/code/update.d.ts +46 -0
  13. package/dist/commands/code/update.js +242 -0
  14. package/dist/commands/commerce/entitlements/explain.d.ts +22 -0
  15. package/dist/commands/commerce/entitlements/explain.js +40 -0
  16. package/dist/commands/commerce/incidents/audit.d.ts +20 -0
  17. package/dist/commands/commerce/incidents/audit.js +37 -0
  18. package/dist/commands/commerce/incidents/list.d.ts +22 -0
  19. package/dist/commands/commerce/incidents/list.js +49 -0
  20. package/dist/commands/commerce/incidents/resolve.d.ts +23 -0
  21. package/dist/commands/commerce/incidents/resolve.js +45 -0
  22. package/dist/commands/commerce/incidents/retry.d.ts +22 -0
  23. package/dist/commands/commerce/incidents/retry.js +45 -0
  24. package/dist/commands/commerce/incidents/show.d.ts +13 -0
  25. package/dist/commands/commerce/incidents/show.js +30 -0
  26. package/dist/commands/commerce/offers/approve.d.ts +17 -0
  27. package/dist/commands/commerce/offers/approve.js +33 -0
  28. package/dist/commands/commerce/offers/create.d.ts +18 -0
  29. package/dist/commands/commerce/offers/create.js +34 -0
  30. package/dist/commands/commerce/offers/publish.d.ts +13 -0
  31. package/dist/commands/commerce/offers/publish.js +28 -0
  32. package/dist/commands/commerce/offers/retire.d.ts +17 -0
  33. package/dist/commands/commerce/offers/retire.js +32 -0
  34. package/dist/commands/commerce/offers/validate.d.ts +18 -0
  35. package/dist/commands/commerce/offers/validate.js +33 -0
  36. package/dist/commands/commerce/products/create.d.ts +10 -0
  37. package/dist/commands/commerce/products/create.js +25 -0
  38. package/dist/commands/commerce/promotions/redeem.d.ts +13 -0
  39. package/dist/commands/commerce/promotions/redeem.js +32 -0
  40. package/dist/commands/commerce/terms/accept.d.ts +18 -0
  41. package/dist/commands/commerce/terms/accept.js +39 -0
  42. package/dist/commands/commerce/terms/show.d.ts +10 -0
  43. package/dist/commands/commerce/terms/show.js +34 -0
  44. package/dist/commands/commerce/trials/conversion-preview.d.ts +18 -0
  45. package/dist/commands/commerce/trials/conversion-preview.js +39 -0
  46. package/dist/commands/commerce/trials/start.d.ts +23 -0
  47. package/dist/commands/commerce/trials/start.js +58 -0
  48. package/dist/commands/commitments/accounting.d.ts +39 -0
  49. package/dist/commands/commitments/accounting.js +116 -0
  50. package/dist/commands/commitments/action-history.d.ts +1 -0
  51. package/dist/commands/commitments/action-history.js +8 -1
  52. package/dist/commands/commitments/case.d.ts +1 -0
  53. package/dist/commands/commitments/case.js +19 -3
  54. package/dist/commands/commitments/cases.d.ts +1 -0
  55. package/dist/commands/commitments/cases.js +11 -1
  56. package/dist/commands/commitments/checks.d.ts +1 -0
  57. package/dist/commands/commitments/checks.js +5 -1
  58. package/dist/commands/commitments/cost.d.ts +62 -0
  59. package/dist/commands/commitments/cost.js +130 -0
  60. package/dist/commands/commitments/create.js +1 -1
  61. package/dist/commands/commitments/delete.d.ts +1 -0
  62. package/dist/commands/commitments/delete.js +56 -6
  63. package/dist/commands/commitments/feedback.js +9 -1
  64. package/dist/commands/commitments/handover.js +16 -0
  65. package/dist/commands/commitments/hypotheses.d.ts +1 -0
  66. package/dist/commands/commitments/hypotheses.js +17 -2
  67. package/dist/commands/commitments/links/list.js +4 -1
  68. package/dist/commands/commitments/liveness.d.ts +18 -0
  69. package/dist/commands/commitments/liveness.js +80 -0
  70. package/dist/commands/commitments/metrics.d.ts +1 -0
  71. package/dist/commands/commitments/metrics.js +8 -1
  72. package/dist/commands/commitments/next-tick.d.ts +39 -0
  73. package/dist/commands/commitments/next-tick.js +122 -0
  74. package/dist/commands/commitments/observations.d.ts +1 -0
  75. package/dist/commands/commitments/observations.js +19 -2
  76. package/dist/commands/commitments/pause.js +12 -0
  77. package/dist/commands/commitments/receipt.d.ts +2 -0
  78. package/dist/commands/commitments/receipt.js +16 -2
  79. package/dist/commands/commitments/remediation-proposal.js +6 -2
  80. package/dist/commands/commitments/remediation-proposals.js +5 -1
  81. package/dist/commands/commitments/restore.d.ts +25 -0
  82. package/dist/commands/commitments/restore.js +46 -0
  83. package/dist/commands/commitments/show.js +32 -0
  84. package/dist/commands/commitments/trigger-status.js +33 -0
  85. package/dist/commands/commitments/update.d.ts +1 -0
  86. package/dist/commands/commitments/update.js +31 -5
  87. package/dist/commands/commitments/wake-capabilities.d.ts +0 -1
  88. package/dist/commands/commitments/wake-capabilities.js +8 -4
  89. package/dist/commands/convos/handover.d.ts +1 -0
  90. package/dist/commands/convos/handover.js +4 -0
  91. package/dist/commands/daemon/index.js +2 -0
  92. package/dist/commands/daemon/update.d.ts +19 -0
  93. package/dist/commands/daemon/update.js +48 -0
  94. package/dist/commands/enterprise/budgets/create.d.ts +11 -0
  95. package/dist/commands/enterprise/budgets/create.js +27 -0
  96. package/dist/commands/enterprise/budgets/evaluate.d.ts +17 -0
  97. package/dist/commands/enterprise/budgets/evaluate.js +32 -0
  98. package/dist/commands/enterprise/budgets/publish.d.ts +14 -0
  99. package/dist/commands/enterprise/budgets/publish.js +30 -0
  100. package/dist/commands/enterprise/contracts/activate.d.ts +14 -0
  101. package/dist/commands/enterprise/contracts/activate.js +30 -0
  102. package/dist/commands/enterprise/contracts/create.d.ts +14 -0
  103. package/dist/commands/enterprise/contracts/create.js +32 -0
  104. package/dist/commands/enterprise/contracts/issue.d.ts +18 -0
  105. package/dist/commands/enterprise/contracts/issue.js +34 -0
  106. package/dist/commands/enterprise/domains/begin.d.ts +20 -0
  107. package/dist/commands/enterprise/domains/begin.js +39 -0
  108. package/dist/commands/enterprise/domains/verify.d.ts +14 -0
  109. package/dist/commands/enterprise/domains/verify.js +32 -0
  110. package/dist/commands/enterprise/external-config/activate.d.ts +22 -0
  111. package/dist/commands/enterprise/external-config/activate.js +49 -0
  112. package/dist/commands/enterprise/external-config/set.d.ts +25 -0
  113. package/dist/commands/enterprise/external-config/set.js +123 -0
  114. package/dist/commands/enterprise/external-config/show.d.ts +12 -0
  115. package/dist/commands/enterprise/external-config/show.js +39 -0
  116. package/dist/commands/enterprise/external-config/suspend.d.ts +13 -0
  117. package/dist/commands/enterprise/external-config/suspend.js +41 -0
  118. package/dist/commands/enterprise/finance/close-snapshot.d.ts +11 -0
  119. package/dist/commands/enterprise/finance/close-snapshot.js +28 -0
  120. package/dist/commands/enterprise/finance/record-document.d.ts +18 -0
  121. package/dist/commands/enterprise/finance/record-document.js +35 -0
  122. package/dist/commands/enterprise/profile.d.ts +20 -0
  123. package/dist/commands/enterprise/profile.js +38 -0
  124. package/dist/commands/login.d.ts +13 -0
  125. package/dist/commands/login.js +77 -0
  126. package/dist/commands/machines/dedicated/index.js +3 -0
  127. package/dist/commands/machines/dedicated/service/apply.d.ts +23 -0
  128. package/dist/commands/machines/dedicated/service/apply.js +99 -0
  129. package/dist/commands/machines/dedicated/service/approve.d.ts +23 -0
  130. package/dist/commands/machines/dedicated/service/approve.js +52 -0
  131. package/dist/commands/machines/dedicated/service/create.d.ts +55 -0
  132. package/dist/commands/machines/dedicated/service/create.js +222 -0
  133. package/dist/commands/machines/dedicated/service/edit.d.ts +30 -0
  134. package/dist/commands/machines/dedicated/service/edit.js +146 -0
  135. package/dist/commands/machines/dedicated/service/exec.d.ts +26 -0
  136. package/dist/commands/machines/dedicated/service/exec.js +92 -0
  137. package/dist/commands/machines/dedicated/service/export.d.ts +29 -0
  138. package/dist/commands/machines/dedicated/service/export.js +106 -0
  139. package/dist/commands/machines/dedicated/service/index.d.ts +14 -0
  140. package/dist/commands/machines/dedicated/service/index.js +49 -0
  141. package/dist/commands/machines/dedicated/service/logs.d.ts +33 -0
  142. package/dist/commands/machines/dedicated/service/logs.js +148 -0
  143. package/dist/commands/machines/dedicated/service/ls.d.ts +20 -0
  144. package/dist/commands/machines/dedicated/service/ls.js +80 -0
  145. package/dist/commands/machines/dedicated/service/restart.d.ts +14 -0
  146. package/dist/commands/machines/dedicated/service/restart.js +29 -0
  147. package/dist/commands/machines/dedicated/service/rm.d.ts +20 -0
  148. package/dist/commands/machines/dedicated/service/rm.js +33 -0
  149. package/dist/commands/machines/dedicated/service/secret/index.d.ts +14 -0
  150. package/dist/commands/machines/dedicated/service/secret/index.js +25 -0
  151. package/dist/commands/machines/dedicated/service/secret/rm.d.ts +22 -0
  152. package/dist/commands/machines/dedicated/service/secret/rm.js +54 -0
  153. package/dist/commands/machines/dedicated/service/secret/set.d.ts +22 -0
  154. package/dist/commands/machines/dedicated/service/secret/set.js +93 -0
  155. package/dist/commands/machines/dedicated/service/start.d.ts +14 -0
  156. package/dist/commands/machines/dedicated/service/start.js +29 -0
  157. package/dist/commands/machines/dedicated/service/status.d.ts +21 -0
  158. package/dist/commands/machines/dedicated/service/status.js +85 -0
  159. package/dist/commands/machines/dedicated/service/stop.d.ts +20 -0
  160. package/dist/commands/machines/dedicated/service/stop.js +35 -0
  161. package/dist/commands/machines/dedicated/service/top.d.ts +22 -0
  162. package/dist/commands/machines/dedicated/service/top.js +120 -0
  163. package/dist/commands/machines/dedicated/sign-in-status.d.ts +22 -0
  164. package/dist/commands/machines/dedicated/sign-in-status.js +79 -0
  165. package/dist/commands/machines/dedicated/ssh-config.d.ts +28 -0
  166. package/dist/commands/machines/dedicated/ssh-config.js +66 -0
  167. package/dist/commands/machines/dedicated/ssh-proxy.d.ts +22 -0
  168. package/dist/commands/machines/dedicated/ssh-proxy.js +62 -0
  169. package/dist/commands/machines/dedicated/ssh.d.ts +29 -0
  170. package/dist/commands/machines/dedicated/ssh.js +121 -0
  171. package/dist/commands/native/allow-all.d.ts +14 -0
  172. package/dist/commands/native/allow-all.js +25 -0
  173. package/dist/commands/native/allow.d.ts +24 -0
  174. package/dist/commands/native/allow.js +45 -0
  175. package/dist/commands/native/deny.d.ts +24 -0
  176. package/dist/commands/native/deny.js +43 -0
  177. package/dist/commands/native/disable.d.ts +17 -0
  178. package/dist/commands/native/disable.js +28 -0
  179. package/dist/commands/native/enable.d.ts +12 -0
  180. package/dist/commands/native/enable.js +29 -0
  181. package/dist/commands/native/list-apps.d.ts +19 -0
  182. package/dist/commands/native/list-apps.js +30 -0
  183. package/dist/commands/native/restrict-to.d.ts +22 -0
  184. package/dist/commands/native/restrict-to.js +41 -0
  185. package/dist/commands/native/status.d.ts +19 -0
  186. package/dist/commands/native/status.js +33 -0
  187. package/dist/commands/native.d.ts +39 -0
  188. package/dist/commands/native.js +76 -0
  189. package/dist/commands/service/index.d.ts +14 -0
  190. package/dist/commands/service/index.js +31 -0
  191. package/dist/commands/service/logs.d.ts +18 -0
  192. package/dist/commands/service/logs.js +53 -0
  193. package/dist/commands/service/ls.d.ts +13 -0
  194. package/dist/commands/service/ls.js +48 -0
  195. package/dist/commands/service/propose.d.ts +34 -0
  196. package/dist/commands/service/propose.js +113 -0
  197. package/dist/commands/service/status.d.ts +17 -0
  198. package/dist/commands/service/status.js +56 -0
  199. package/dist/commands/spaces/auto-executor/runs.d.ts +13 -0
  200. package/dist/commands/spaces/auto-executor/runs.js +56 -0
  201. package/dist/commands/spaces/briefs/get.js +8 -0
  202. package/dist/commands/spaces/briefs/list.js +2 -0
  203. package/dist/commands/spaces/briefs/set.d.ts +3 -0
  204. package/dist/commands/spaces/briefs/set.js +78 -13
  205. package/dist/commands/spaces/expertise-suggestions.d.ts +12 -0
  206. package/dist/commands/spaces/expertise-suggestions.js +71 -0
  207. package/dist/commands/spaces/members/add.d.ts +1 -0
  208. package/dist/commands/spaces/members/add.js +11 -3
  209. package/dist/commands/spaces/members/list.js +11 -0
  210. package/dist/commands/store/governance/artifacts.d.ts +25 -0
  211. package/dist/commands/store/governance/artifacts.js +55 -0
  212. package/dist/commands/store/governance/assign.d.ts +16 -0
  213. package/dist/commands/store/governance/assign.js +54 -0
  214. package/dist/commands/store/governance/create-license.d.ts +18 -0
  215. package/dist/commands/store/governance/create-license.js +35 -0
  216. package/dist/commands/store/governance/install-plan.d.ts +25 -0
  217. package/dist/commands/store/governance/install-plan.js +56 -0
  218. package/dist/commands/store/governance/license-policy.d.ts +30 -0
  219. package/dist/commands/store/governance/license-policy.js +69 -0
  220. package/dist/commands/store/governance/policy.d.ts +25 -0
  221. package/dist/commands/store/governance/policy.js +65 -0
  222. package/dist/commands/store/governance/publish-release.d.ts +17 -0
  223. package/dist/commands/store/governance/publish-release.js +34 -0
  224. package/dist/commands/tasks/assign.d.ts +9 -0
  225. package/dist/commands/tasks/assign.js +108 -1
  226. package/dist/commands/tasks/deliverable/add.d.ts +15 -0
  227. package/dist/commands/tasks/deliverable/add.js +174 -0
  228. package/dist/commands/tasks/deliverable/archive.d.ts +35 -0
  229. package/dist/commands/tasks/deliverable/archive.js +205 -0
  230. package/dist/commands/tasks/labels/detach.js +3 -0
  231. package/dist/commands/tasks/labels/suggest.d.ts +24 -0
  232. package/dist/commands/tasks/labels/suggest.js +69 -0
  233. package/dist/commands/tasks/list.d.ts +16 -2
  234. package/dist/commands/tasks/list.js +100 -24
  235. package/dist/commands/tasks/show.d.ts +23 -0
  236. package/dist/commands/tasks/show.js +51 -1
  237. package/dist/commands/wiki/rm.d.ts +22 -1
  238. package/dist/commands/wiki/rm.js +52 -3
  239. package/dist/lib/agentic-stream.js +10 -2
  240. package/dist/lib/assignee-resolver.d.ts +22 -0
  241. package/dist/lib/assignee-resolver.js +26 -0
  242. package/dist/lib/balance.d.ts +6 -1
  243. package/dist/lib/balance.js +15 -0
  244. package/dist/lib/code-handover.d.ts +0 -10
  245. package/dist/lib/code-handover.js +20 -5
  246. package/dist/lib/commerce-command.d.ts +48 -0
  247. package/dist/lib/commerce-command.js +70 -0
  248. package/dist/lib/commerce.d.ts +93 -0
  249. package/dist/lib/commerce.js +129 -0
  250. package/dist/lib/commitment-product.js +1 -1
  251. package/dist/lib/commitments.d.ts +202 -29
  252. package/dist/lib/commitments.js +300 -33
  253. package/dist/lib/dedicated-lease-command.js +10 -0
  254. package/dist/lib/dedicated-machines.d.ts +37 -0
  255. package/dist/lib/dedicated-machines.js +47 -0
  256. package/dist/lib/dedicated-service-command.d.ts +60 -0
  257. package/dist/lib/dedicated-service-command.js +182 -0
  258. package/dist/lib/dedicated-service.d.ts +342 -0
  259. package/dist/lib/dedicated-service.js +741 -0
  260. package/dist/lib/dedicated-ssh.d.ts +136 -0
  261. package/dist/lib/dedicated-ssh.js +387 -0
  262. package/dist/lib/delegated-cli.js +51 -13
  263. package/dist/lib/enterprise-commerce.d.ts +67 -0
  264. package/dist/lib/enterprise-commerce.js +112 -0
  265. package/dist/lib/enterprise-external-configuration.d.ts +60 -0
  266. package/dist/lib/enterprise-external-configuration.js +58 -0
  267. package/dist/lib/first-party-harness.js +17 -3
  268. package/dist/lib/governed-store.d.ts +110 -0
  269. package/dist/lib/governed-store.js +79 -0
  270. package/dist/lib/guest-service-command.d.ts +16 -0
  271. package/dist/lib/guest-service-command.js +32 -0
  272. package/dist/lib/guest-service.d.ts +67 -0
  273. package/dist/lib/guest-service.js +112 -0
  274. package/dist/lib/prompt.d.ts +1 -0
  275. package/dist/lib/prompt.js +1 -0
  276. package/dist/lib/task-asset-upload.d.ts +20 -0
  277. package/dist/lib/task-asset-upload.js +30 -8
  278. package/dist/lib/task-extras.d.ts +23 -0
  279. package/dist/lib/task-extras.js +6 -0
  280. package/dist/lib/update-check.d.ts +80 -7
  281. package/dist/lib/update-check.js +365 -33
  282. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.d.ts +9 -3
  283. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonScopes.js +10 -3
  284. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +9 -1
  285. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +8 -0
  286. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  287. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +6 -5
  288. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.d.ts +16 -0
  289. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +21 -4
  290. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.d.ts +1 -1
  291. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/spawnEnv.js +24 -2
  292. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.d.ts +9 -3
  293. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonScopes.js +10 -3
  294. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +9 -1
  295. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +8 -0
  296. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  297. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  298. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.d.ts +16 -0
  299. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +20 -4
  300. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.d.ts +1 -1
  301. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/spawnEnv.js +24 -2
  302. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  303. package/dist/node_modules/@skrr-ai/data-provider/index.js +5067 -4821
  304. package/oclif.manifest.json +34877 -28659
  305. package/package.json +43 -1
@@ -35,6 +35,9 @@ class CommitmentsHypotheses extends base_command_1.BaseCommand {
35
35
  'investigation-key': core_1.Flags.string({
36
36
  description: 'Narrow to one investigation (an open loop subject key)',
37
37
  }),
38
+ cursor: core_1.Flags.string({
39
+ description: 'Continue from the next_cursor emitted by a previous page',
40
+ }),
38
41
  };
39
42
  async run() {
40
43
  this.requireAuth();
@@ -45,6 +48,7 @@ class CommitmentsHypotheses extends base_command_1.BaseCommand {
45
48
  limit: flags.limit,
46
49
  status: flags.status,
47
50
  investigationKey: flags['investigation-key'],
51
+ cursor: flags.cursor,
48
52
  });
49
53
  }
50
54
  catch (err) {
@@ -52,9 +56,20 @@ class CommitmentsHypotheses extends base_command_1.BaseCommand {
52
56
  }
53
57
  if (flags.json) {
54
58
  this.log(JSON.stringify(response, null, 2));
55
- return;
56
59
  }
57
- (0, commitments_1.renderCommitmentHypotheses)(response, (line) => this.log(line));
60
+ else {
61
+ // A filtered-out list is not an empty ledger — say which filter did it
62
+ // (OSK-10953).
63
+ const filters = [
64
+ flags.status ? `--status ${flags.status}` : null,
65
+ flags['investigation-key'] ? `--investigation-key ${flags['investigation-key']}` : null,
66
+ ].filter(Boolean);
67
+ const emptyMessage = filters.length
68
+ ? `No hypotheses match ${filters.join(' ')}.`
69
+ : 'No hypotheses recorded.';
70
+ (0, commitments_1.renderCommitmentHypotheses)(response, (line) => this.log(line), { emptyMessage });
71
+ }
72
+ (0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
58
73
  }
59
74
  }
60
75
  exports.default = CommitmentsHypotheses;
@@ -34,7 +34,10 @@ class CommitmentsLinksList extends base_command_1.BaseCommand {
34
34
  return;
35
35
  }
36
36
  for (const link of links) {
37
- this.log(`${link.id} ${link.targetType}:${link.target?.title || link.targetId} [${link.roles.join(', ')}] ${link.status}`);
37
+ // `origin: 'goal_lineage'` rows are derived from `goal.commitmentId`, not
38
+ // a work-link row — `links detach` cannot remove them (OSK-10960).
39
+ const provenance = link.origin === 'goal_lineage' ? ' (via goals link — remove with goals unlink)' : '';
40
+ this.log(`${link.id} ${link.targetType}:${link.target?.title || link.targetId} [${link.roles.join(', ')}] ${link.status}${provenance}`);
38
41
  }
39
42
  }
40
43
  }
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * `skrr commitments liveness` — is the liveness witness itself alive?
4
+ *
5
+ * Per-commitment health is on `show`; this is the SWEEP's health — the marker
6
+ * the reconciler writes each pass. A stale sweep means every per-commitment
7
+ * verdict is also stale, which no single-commitment surface can tell you
8
+ * (OSK-10958). `healthy: false` or a null `lastSweepAt` means the witness is
9
+ * not running, not that commitments are fine.
10
+ */
11
+ export default class CommitmentsLiveness extends BaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const commitments_1 = require("../../lib/commitments");
6
+ /**
7
+ * `skrr commitments liveness` — is the liveness witness itself alive?
8
+ *
9
+ * Per-commitment health is on `show`; this is the SWEEP's health — the marker
10
+ * the reconciler writes each pass. A stale sweep means every per-commitment
11
+ * verdict is also stale, which no single-commitment surface can tell you
12
+ * (OSK-10958). `healthy: false` or a null `lastSweepAt` means the witness is
13
+ * not running, not that commitments are fine.
14
+ */
15
+ class CommitmentsLiveness extends base_command_1.BaseCommand {
16
+ static description = 'Show liveness sweep health — when the witness last ran and what it saw';
17
+ static examples = [
18
+ '<%= config.bin %> commitments liveness',
19
+ '<%= config.bin %> commitments liveness --json',
20
+ ];
21
+ static flags = {
22
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
23
+ };
24
+ async run() {
25
+ this.requireAuth();
26
+ const { flags } = await this.parse(CommitmentsLiveness);
27
+ let health;
28
+ try {
29
+ health = (await commitments_1.commitmentApi.livenessSweep());
30
+ }
31
+ catch (err) {
32
+ this.handleApiError(err);
33
+ }
34
+ if (flags.json) {
35
+ this.log(JSON.stringify(health, null, 2));
36
+ return;
37
+ }
38
+ for (const line of formatSweepHealth(health))
39
+ this.log(line);
40
+ }
41
+ }
42
+ exports.default = CommitmentsLiveness;
43
+ function formatSweepHealth(health) {
44
+ const lines = [];
45
+ if (!health.lastSweepAt) {
46
+ lines.push('Liveness sweep: NO SWEEP RECORDED');
47
+ lines.push(' The reconciler has never completed a sweep on this deployment —');
48
+ lines.push(' every per-commitment health verdict is unverified.');
49
+ return lines;
50
+ }
51
+ const age = health.sweepAgeSeconds ?? 0;
52
+ const status = health.healthy ? 'healthy' : 'STALE';
53
+ lines.push(`Liveness sweep: ${status} (${formatAge(age)} old)`);
54
+ lines.push(` last sweep: ${health.lastSweepAt}`);
55
+ const tick = health.lastTick;
56
+ if (tick) {
57
+ lines.push(` last tick: scanned ${tick.scanned ?? 0}` +
58
+ ` | on_track ${tick.onTrack ?? 0}` +
59
+ ` | stalled ${tick.stalled ?? 0}` +
60
+ ` | unknown ${tick.unknown ?? 0}` +
61
+ ` | unjudged ${tick.unjudged ?? 0}` +
62
+ ` | alerted ${tick.alerted ?? 0}` +
63
+ ` | errors ${tick.errors ?? 0}`);
64
+ }
65
+ if (health.cursor?.id) {
66
+ lines.push(` cursor: ${health.cursor.id}${health.cursor.at ? ` @ ${health.cursor.at}` : ''}`);
67
+ }
68
+ return lines;
69
+ }
70
+ function formatAge(seconds) {
71
+ if (seconds < 90)
72
+ return `${seconds}s`;
73
+ const minutes = Math.floor(seconds / 60);
74
+ if (minutes < 90)
75
+ return `${minutes}m`;
76
+ const hours = Math.floor(minutes / 60);
77
+ if (hours < 48)
78
+ return `${hours}h ${minutes % 60}m`;
79
+ return `${Math.floor(hours / 24)}d ${hours % 24}h`;
80
+ }
@@ -15,6 +15,7 @@ export default class CommitmentsMetrics extends BaseCommand {
15
15
  static flags: {
16
16
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
17
  limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
19
  };
19
20
  run(): Promise<void>;
20
21
  }
@@ -22,13 +22,19 @@ class CommitmentsMetrics extends base_command_1.BaseCommand {
22
22
  static flags = {
23
23
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
24
24
  limit: core_1.Flags.integer({ description: 'Days to include', min: 1, max: 200 }),
25
+ cursor: core_1.Flags.string({
26
+ description: 'Continue from the next_cursor emitted by a previous page',
27
+ }),
25
28
  };
26
29
  async run() {
27
30
  this.requireAuth();
28
31
  const { args, flags } = await this.parse(CommitmentsMetrics);
29
32
  let response;
30
33
  try {
31
- response = await commitments_1.commitmentApi.dailyMetrics(args.commitmentId, flags.limit);
34
+ response = await commitments_1.commitmentApi.dailyMetrics(args.commitmentId, {
35
+ limit: flags.limit,
36
+ cursor: flags.cursor,
37
+ });
32
38
  }
33
39
  catch (err) {
34
40
  this.handleApiError(err);
@@ -38,6 +44,7 @@ class CommitmentsMetrics extends base_command_1.BaseCommand {
38
44
  return;
39
45
  }
40
46
  (0, commitments_1.renderCommitmentMetrics)(response, (line) => this.log(line));
47
+ (0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
41
48
  }
42
49
  }
43
50
  exports.default = CommitmentsMetrics;
@@ -0,0 +1,39 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ import { type CommitmentNextTickProjection } from '../../lib/commitments';
3
+ /**
4
+ * `skrr commitments next-tick <id>` — what the NEXT check would decide.
5
+ *
6
+ * Every other read on a commitment is retrospective: `checks` says what it
7
+ * decided, `receipt` says what one wake produced, `trigger-status` says when it
8
+ * will fire again. None of them answers the question an operator actually has
9
+ * when a commitment is about to nudge somebody — "what is it about to do, and
10
+ * on what grounds" — and the only way to find out used to be to run a real
11
+ * check, which changes the thing you were trying to observe.
12
+ *
13
+ * The server's projection stops at the DecisionEnvelope → Arbiter boundary: no
14
+ * Check row, no budget debit, no delivery gate, no contract write. That is what
15
+ * makes this safe to ask from a terminal, and it is why the envelope is only
16
+ * printed under `--json` — the decision and its policy trail are the answer;
17
+ * the envelope is the evidence behind it.
18
+ */
19
+ export default class CommitmentsNextTick extends BaseCommand {
20
+ static description: string;
21
+ static examples: string[];
22
+ static args: {
23
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
24
+ };
25
+ static flags: {
26
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
27
+ };
28
+ run(): Promise<void>;
29
+ }
30
+ /**
31
+ * Pure renderer for the next-tick projection.
32
+ *
33
+ * Kept separate from the command for the same reason `formatTriggerStatus` is:
34
+ * it can be unit-tested without a live API, and the command body stays a thin
35
+ * fetch + print. Defensive about every field — this is a projection of a
36
+ * versioned envelope, so a missing key is a shape change, not a reason to throw
37
+ * in front of somebody debugging a live commitment.
38
+ */
39
+ export declare function formatNextTick(projection: CommitmentNextTickProjection): string[];
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatNextTick = formatNextTick;
4
+ const core_1 = require("@oclif/core");
5
+ const base_command_1 = require("../../base-command");
6
+ const commitments_1 = require("../../lib/commitments");
7
+ /**
8
+ * `skrr commitments next-tick <id>` — what the NEXT check would decide.
9
+ *
10
+ * Every other read on a commitment is retrospective: `checks` says what it
11
+ * decided, `receipt` says what one wake produced, `trigger-status` says when it
12
+ * will fire again. None of them answers the question an operator actually has
13
+ * when a commitment is about to nudge somebody — "what is it about to do, and
14
+ * on what grounds" — and the only way to find out used to be to run a real
15
+ * check, which changes the thing you were trying to observe.
16
+ *
17
+ * The server's projection stops at the DecisionEnvelope → Arbiter boundary: no
18
+ * Check row, no budget debit, no delivery gate, no contract write. That is what
19
+ * makes this safe to ask from a terminal, and it is why the envelope is only
20
+ * printed under `--json` — the decision and its policy trail are the answer;
21
+ * the envelope is the evidence behind it.
22
+ */
23
+ class CommitmentsNextTick extends base_command_1.BaseCommand {
24
+ static description = 'Preview what the next check would decide, without running one (no budget, no side effects)';
25
+ static examples = [
26
+ '<%= config.bin %> commitments next-tick obj_abc123',
27
+ '<%= config.bin %> commitments next-tick obj_abc123 --json',
28
+ ];
29
+ static args = {
30
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
31
+ };
32
+ static flags = {
33
+ json: core_1.Flags.boolean({
34
+ description: 'Output the full projection, including the DecisionEnvelope',
35
+ }),
36
+ };
37
+ async run() {
38
+ this.requireAuth();
39
+ const { args, flags } = await this.parse(CommitmentsNextTick);
40
+ let projection;
41
+ try {
42
+ projection = await commitments_1.commitmentApi.nextTick(args.id);
43
+ }
44
+ catch (err) {
45
+ this.handleApiError(err);
46
+ }
47
+ if (flags.json) {
48
+ this.log(JSON.stringify(projection, null, 2));
49
+ return;
50
+ }
51
+ for (const line of formatNextTick(projection))
52
+ this.log(line);
53
+ }
54
+ }
55
+ exports.default = CommitmentsNextTick;
56
+ /**
57
+ * Pure renderer for the next-tick projection.
58
+ *
59
+ * Kept separate from the command for the same reason `formatTriggerStatus` is:
60
+ * it can be unit-tested without a live API, and the command body stays a thin
61
+ * fetch + print. Defensive about every field — this is a projection of a
62
+ * versioned envelope, so a missing key is a shape change, not a reason to throw
63
+ * in front of somebody debugging a live commitment.
64
+ */
65
+ function formatNextTick(projection) {
66
+ const decision = projection.decision ?? {};
67
+ const lines = [
68
+ `Next tick for ${projection.commitmentId ?? '-'} (projected ${projection.projectedAt ?? '-'})`,
69
+ '',
70
+ // The header states what this did NOT do, because the value of the command
71
+ // is entirely in that: a reader who thinks a check just ran will misread
72
+ // every number on the commitment afterwards.
73
+ 'Projection only — no check was recorded, no budget spent, no action routed.',
74
+ '',
75
+ `Posture: ${decision.posture ?? '-'}`,
76
+ `Health: ${decision.health ?? '-'}`,
77
+ `Risk: ${decision.riskLevel ?? '-'}`,
78
+ `Confidence: ${decision.confidence ?? '-'}`,
79
+ ];
80
+ if (decision.whyNow)
81
+ lines.push(`Why now: ${decision.whyNow}`);
82
+ // OSK-11433 — the projected envelope health is a delta read; the stored
83
+ // liveness verdict is the independent witness. Print the witness too so a
84
+ // dispatch-refusal loop can't hide behind an on_track projection.
85
+ if (projection.health || projection.liveness) {
86
+ const census = projection.liveness?.terminalDispositionCensus;
87
+ const detail = [
88
+ projection.liveness?.diagnosisKind,
89
+ census?.workFailures
90
+ ? `${census.workFailures} recent run failure${census.workFailures === 1 ? '' : 's'}`
91
+ : null,
92
+ ]
93
+ .filter(Boolean)
94
+ .join(', ');
95
+ lines.push(`Liveness: ${projection.health ?? '-'}` + (detail ? ` (${detail})` : ''));
96
+ }
97
+ const actions = decision.actionPlan ?? [];
98
+ lines.push('');
99
+ if (actions.length === 0) {
100
+ lines.push('Action plan: none');
101
+ }
102
+ else {
103
+ lines.push(`Action plan (${actions.length}):`);
104
+ for (const action of actions) {
105
+ const label = action.summary || action.title || '';
106
+ lines.push(` - ${action.kind || action.type || 'action'}${label ? `: ${label}` : ''}`);
107
+ }
108
+ }
109
+ const trace = decision.policyTrace ?? [];
110
+ lines.push('');
111
+ if (trace.length === 0) {
112
+ lines.push('Policy trace: none');
113
+ }
114
+ else {
115
+ lines.push(`Policy trace (${trace.length}):`);
116
+ for (const entry of trace) {
117
+ lines.push(` ${entry.rule ?? '-'} → ${entry.decision ?? '-'}` +
118
+ (entry.reason ? ` — ${entry.reason}` : ''));
119
+ }
120
+ }
121
+ return lines;
122
+ }
@@ -26,6 +26,7 @@ export default class CommitmentsObservations extends BaseCommand {
26
26
  'declared-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
27
27
  'changed-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
28
28
  since: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
29
+ cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
29
30
  };
30
31
  run(): Promise<void>;
31
32
  }
@@ -38,6 +38,9 @@ class CommitmentsObservations extends base_command_1.BaseCommand {
38
38
  description: 'Only readings the server judged a material change',
39
39
  }),
40
40
  since: core_1.Flags.string({ description: 'ISO date — only observations made after it' }),
41
+ cursor: core_1.Flags.string({
42
+ description: 'Continue from the next_cursor emitted by a previous page',
43
+ }),
41
44
  };
42
45
  async run() {
43
46
  this.requireAuth();
@@ -49,6 +52,7 @@ class CommitmentsObservations extends base_command_1.BaseCommand {
49
52
  declaredOnly: flags['declared-only'] || undefined,
50
53
  changedOnly: flags['changed-only'] || undefined,
51
54
  since: flags.since,
55
+ cursor: flags.cursor,
52
56
  });
53
57
  }
54
58
  catch (err) {
@@ -56,9 +60,22 @@ class CommitmentsObservations extends base_command_1.BaseCommand {
56
60
  }
57
61
  if (flags.json) {
58
62
  this.log(JSON.stringify(response, null, 2));
59
- return;
60
63
  }
61
- (0, commitments_1.renderCommitmentObservations)(response, (line) => this.log(line));
64
+ else {
65
+ // "The commitment has none" and "your filter matched none" are different
66
+ // facts; a filter that empties the list must not claim the first
67
+ // (OSK-10953).
68
+ const filters = [
69
+ flags['declared-only'] ? '--declared-only' : null,
70
+ flags['changed-only'] ? '--changed-only' : null,
71
+ flags.since ? `--since ${flags.since}` : null,
72
+ ].filter(Boolean);
73
+ const emptyMessage = filters.length
74
+ ? `No observations match ${filters.join(' ')}.`
75
+ : 'No observations recorded.';
76
+ (0, commitments_1.renderCommitmentObservations)(response, (line) => this.log(line), { emptyMessage });
77
+ }
78
+ (0, commitments_1.renderListPageHint)(response, (line) => this.log(line));
62
79
  }
63
80
  }
64
81
  exports.default = CommitmentsObservations;
@@ -30,6 +30,18 @@ class CommitmentsPause extends base_command_1.BaseCommand {
30
30
  return;
31
31
  }
32
32
  this.log(`Paused commitment ${args.id}.`);
33
+ // The status write is the fence and it has landed. The teardown of the
34
+ // wake tree behind it is best-effort, and used to be silent — so a pause
35
+ // that left triggers live looked exactly like one that did not. Say which
36
+ // happened; a reconciler will converge the degraded case, but a person
37
+ // deciding whether they are really stopped should not have to assume it.
38
+ const teardown = commitment
39
+ .teardown;
40
+ if (teardown?.status === 'degraded') {
41
+ this.warn('The control loop is stopped, but some scheduled wakes may not have been retired yet. ' +
42
+ 'They cannot run anything — every wake is refused while this Commitment is paused — ' +
43
+ `and the reconciler retries automatically. Check with: skrr commitments trigger-status ${args.id}`);
44
+ }
33
45
  (0, commitments_1.renderCommitmentSummary)(commitment, (line) => this.log(line));
34
46
  }
35
47
  }
@@ -8,6 +8,8 @@ export default class CommitmentsReceipt extends BaseCommand {
8
8
  static flags: {
9
9
  latest: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
10
  limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ check: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ run: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
13
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
14
  verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
15
  };
@@ -6,11 +6,21 @@ const commitments_1 = require("../../lib/commitments");
6
6
  const commitment_product_1 = require("../../lib/commitment-product");
7
7
  class CommitmentsReceipt extends base_command_1.BaseCommand {
8
8
  static description = 'Explain what happened from the event through work, delivery, and verification';
9
- static examples = ['<%= config.bin %> commitments receipt <id> --latest'];
9
+ static examples = [
10
+ '<%= config.bin %> commitments receipt <id> --latest',
11
+ '<%= config.bin %> commitments receipt <id> --check objchk_abc',
12
+ '<%= config.bin %> commitments receipt <id> --run arun_abc',
13
+ ];
10
14
  static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
11
15
  static flags = {
12
16
  latest: core_1.Flags.boolean({ description: 'Show the latest wake (default)' }),
13
17
  limit: core_1.Flags.integer({ description: 'Number of receipts to show', min: 1, max: 100 }),
18
+ check: core_1.Flags.string({
19
+ description: 'Explain one specific check — its exact receipt, not the latest-N window',
20
+ }),
21
+ run: core_1.Flags.string({
22
+ description: 'Explain the run — resolves to the receipt of the check that minted it',
23
+ }),
14
24
  json: core_1.Flags.boolean({ description: 'Output projected receipts as JSON' }),
15
25
  verbose: core_1.Flags.boolean({ description: 'Include source IDs and diagnostic traces' }),
16
26
  };
@@ -18,7 +28,11 @@ class CommitmentsReceipt extends base_command_1.BaseCommand {
18
28
  this.requireAuth();
19
29
  const { args, flags } = await this.parse(CommitmentsReceipt);
20
30
  try {
21
- const result = await commitments_1.commitmentApi.receipts(args.id, flags.latest ? 1 : flags.limit || 1);
31
+ const result = await commitments_1.commitmentApi.receipts(args.id, {
32
+ limit: flags.latest ? 1 : flags.limit || 1,
33
+ checkId: flags.check,
34
+ runId: flags.run,
35
+ });
22
36
  if (flags.json)
23
37
  return this.log(JSON.stringify(result, null, 2));
24
38
  if (!result.receipts.length)
@@ -12,7 +12,7 @@ class CommitmentsRemediationProposal extends base_command_1.BaseCommand {
12
12
  static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
13
13
  async run() {
14
14
  this.requireAuth();
15
- const { args } = await this.parse(CommitmentsRemediationProposal);
15
+ const { args, flags } = await this.parse(CommitmentsRemediationProposal);
16
16
  let result;
17
17
  try {
18
18
  result = await commitments_1.commitmentApi.remediationProposal(args.commitmentId, args.proposalId);
@@ -20,7 +20,11 @@ class CommitmentsRemediationProposal extends base_command_1.BaseCommand {
20
20
  catch (error) {
21
21
  this.handleApiError(error);
22
22
  }
23
- this.log(JSON.stringify(result, null, 2));
23
+ if (flags.json) {
24
+ this.log(JSON.stringify(result, null, 2));
25
+ return;
26
+ }
27
+ (0, commitments_1.renderCommitmentRemediationProposal)(result, (line) => this.log(line));
24
28
  }
25
29
  }
26
30
  exports.default = CommitmentsRemediationProposal;
@@ -28,7 +28,11 @@ class CommitmentsRemediationProposals extends base_command_1.BaseCommand {
28
28
  catch (error) {
29
29
  this.handleApiError(error);
30
30
  }
31
- this.log(JSON.stringify(result, null, 2));
31
+ if (flags.json) {
32
+ this.log(JSON.stringify(result, null, 2));
33
+ return;
34
+ }
35
+ (0, commitments_1.renderCommitmentRemediationProposals)(result, (line) => this.log(line));
32
36
  }
33
37
  }
34
38
  exports.default = CommitmentsRemediationProposals;
@@ -0,0 +1,25 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * `skrr commitments restore <id>` — bring back a deleted commitment.
4
+ *
5
+ * Deleting is a soft tombstone, so the row and its whole history were always
6
+ * still there; until now there was simply no way for anyone to reach them
7
+ * again, which is the storage cost of a recoverable delete with none of the
8
+ * benefit.
9
+ *
10
+ * It comes back PAUSED, never active. Restoring the record and re-granting the
11
+ * authority to act are two decisions, and the second still has to pass the
12
+ * activation preflight — so a restore can never quietly put an agent back to
13
+ * work.
14
+ */
15
+ export default class CommitmentsRestore extends BaseCommand {
16
+ static description: string;
17
+ static examples: string[];
18
+ static args: {
19
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
20
+ };
21
+ static flags: {
22
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
23
+ };
24
+ run(): Promise<void>;
25
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const web_url_1 = require("../../lib/web-url");
6
+ const commitments_1 = require("../../lib/commitments");
7
+ /**
8
+ * `skrr commitments restore <id>` — bring back a deleted commitment.
9
+ *
10
+ * Deleting is a soft tombstone, so the row and its whole history were always
11
+ * still there; until now there was simply no way for anyone to reach them
12
+ * again, which is the storage cost of a recoverable delete with none of the
13
+ * benefit.
14
+ *
15
+ * It comes back PAUSED, never active. Restoring the record and re-granting the
16
+ * authority to act are two decisions, and the second still has to pass the
17
+ * activation preflight — so a restore can never quietly put an agent back to
18
+ * work.
19
+ */
20
+ class CommitmentsRestore extends base_command_1.BaseCommand {
21
+ static description = 'Restore a deleted commitment (it comes back paused — resume it separately)';
22
+ static examples = ['<%= config.bin %> commitments restore <commitment-id>'];
23
+ static args = {
24
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
25
+ };
26
+ static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
27
+ async run() {
28
+ this.requireAuth();
29
+ const { args, flags } = await this.parse(CommitmentsRestore);
30
+ let commitment;
31
+ try {
32
+ commitment = await commitments_1.commitmentApi.restore(args.id);
33
+ }
34
+ catch (err) {
35
+ this.handleApiError(err);
36
+ }
37
+ if (flags.json) {
38
+ this.log(JSON.stringify((0, web_url_1.withCommitmentUrl)(this.cliConfig.baseURL, commitment), null, 2));
39
+ return;
40
+ }
41
+ this.log(`Restored commitment ${args.id}. It is paused.`);
42
+ this.log(` Start it again with: skrr commitments resume ${args.id}`);
43
+ (0, commitments_1.renderCommitmentSummary)(commitment, (line) => this.log(line));
44
+ }
45
+ }
46
+ exports.default = CommitmentsRestore;
@@ -50,6 +50,38 @@ class CommitmentsShow extends base_command_1.BaseCommand {
50
50
  return;
51
51
  }
52
52
  (0, commitments_1.renderCommitmentSummary)(response.commitment, (line) => this.log(line), response.latestCheck);
53
+ // `show` is the first surface a person reaches after linking something, and
54
+ // it used to render only watchedSources — a freshly linked goal or task was
55
+ // invisible until you knew to run `links list` (OSK-10963).
56
+ try {
57
+ const links = await commitments_1.commitmentApi.workLinks(args.id);
58
+ const active = (links.data || []).filter((link) => link.status === 'active');
59
+ if (active.length) {
60
+ this.log('Links:');
61
+ for (const link of active) {
62
+ const roles = Array.isArray(link.roles) ? link.roles.join(', ') : '';
63
+ this.log(` - ${link.targetType}:${link.targetId}${roles ? ` (${roles})` : ''}${link.isDelivery ? ' · delivery' : ''}`);
64
+ }
65
+ }
66
+ }
67
+ catch {
68
+ // The header still stands on its own when the links read is unavailable.
69
+ }
70
+ // `goals link` writes goal.commitmentId — an edge that lives on the GOAL,
71
+ // so `links list` can never see it. The lineage projection aggregates both
72
+ // link models; without it, a goal the commitment visibly advances is
73
+ // unrenderable from its own headline view (OSK-10963).
74
+ try {
75
+ const lineage = await commitments_1.commitmentApi.workLineage(args.id, 50);
76
+ const hasAny = ['goals', 'tasks', 'runs'].some((key) => Array.isArray(lineage?.[key]) && lineage[key].length > 0);
77
+ if (hasAny) {
78
+ this.log('');
79
+ (0, commitments_1.renderCommitmentLineage)(lineage, (line) => this.log(line));
80
+ }
81
+ }
82
+ catch {
83
+ // Lineage is a hint on the headline view, not load-bearing.
84
+ }
53
85
  try {
54
86
  const receipts = await commitments_1.commitmentApi.receipts(args.id, 1);
55
87
  if (receipts.receipts[0]) {