@skrr-ai/cli 0.1.94 → 0.1.96

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 (298) hide show
  1. package/README.md +175 -165
  2. package/bin/run.js +32 -0
  3. package/bin/update-npm-runner.cjs +33 -0
  4. package/bin/update-session.cjs +194 -0
  5. package/bin/update-worker.cjs +208 -0
  6. package/dist/base-command.js +0 -15
  7. package/dist/commands/agent/message/send.d.ts +2 -0
  8. package/dist/commands/agent/message/send.js +75 -5
  9. package/dist/commands/agents/chat.js +1 -1
  10. package/dist/commands/agents/create.d.ts +0 -3
  11. package/dist/commands/agents/create.js +0 -26
  12. package/dist/commands/agents/egress.d.ts +17 -0
  13. package/dist/commands/agents/egress.js +84 -0
  14. package/dist/commands/agents/mailbox/messages.d.ts +14 -0
  15. package/dist/commands/agents/mailbox/messages.js +52 -0
  16. package/dist/commands/agents/mailbox/show.d.ts +13 -0
  17. package/dist/commands/agents/mailbox/show.js +52 -0
  18. package/dist/commands/agents/operating-plan.js +8 -0
  19. package/dist/commands/agents/roles/capture.d.ts +16 -0
  20. package/dist/commands/agents/roles/capture.js +53 -0
  21. package/dist/commands/agents/roles/install.d.ts +1 -0
  22. package/dist/commands/agents/roles/install.js +8 -1
  23. package/dist/commands/agents/roles/preview.d.ts +2 -0
  24. package/dist/commands/agents/roles/preview.js +27 -3
  25. package/dist/commands/agents/update.d.ts +0 -3
  26. package/dist/commands/agents/update.js +1 -31
  27. package/dist/commands/agents/usage-cap.d.ts +4 -1
  28. package/dist/commands/agents/usage-cap.js +49 -10
  29. package/dist/commands/code/doctor.d.ts +1 -0
  30. package/dist/commands/code/doctor.js +6 -0
  31. package/dist/commands/code/index.js +4 -0
  32. package/dist/commands/code/install.d.ts +5 -62
  33. package/dist/commands/code/install.js +86 -279
  34. package/dist/commands/code/jobs/show.js +12 -0
  35. package/dist/commands/code/rollback.d.ts +8 -0
  36. package/dist/commands/code/rollback.js +20 -0
  37. package/dist/commands/code/update.d.ts +8 -37
  38. package/dist/commands/code/update.js +134 -213
  39. package/dist/commands/commitments/action-proposals/decide.d.ts +2 -0
  40. package/dist/commands/commitments/action-proposals/decide.js +12 -0
  41. package/dist/commands/commitments/action-proposals.js +7 -0
  42. package/dist/commands/commitments/create.d.ts +1 -0
  43. package/dist/commands/commitments/create.js +17 -1
  44. package/dist/commands/commitments/delivery.d.ts +1 -0
  45. package/dist/commands/commitments/delivery.js +11 -1
  46. package/dist/commands/commitments/doctor.js +4 -0
  47. package/dist/commands/commitments/effective-policy.js +26 -0
  48. package/dist/commands/commitments/endpoints/create.js +5 -2
  49. package/dist/commands/commitments/observations.d.ts +10 -0
  50. package/dist/commands/commitments/observations.js +88 -0
  51. package/dist/commands/commitments/pause.d.ts +1 -1
  52. package/dist/commands/commitments/pause.js +4 -3
  53. package/dist/commands/commitments/preflight.js +2 -1
  54. package/dist/commands/commitments/reports.d.ts +2 -0
  55. package/dist/commands/commitments/reports.js +22 -4
  56. package/dist/commands/commitments/update.d.ts +1 -0
  57. package/dist/commands/commitments/update.js +35 -5
  58. package/dist/commands/daemon/install.js +4 -0
  59. package/dist/commands/generate-recovery-code.d.ts +13 -1
  60. package/dist/commands/generate-recovery-code.js +146 -13
  61. package/dist/commands/grants/create.d.ts +1 -0
  62. package/dist/commands/grants/create.js +8 -0
  63. package/dist/commands/grants/rotate.d.ts +5 -0
  64. package/dist/commands/grants/rotate.js +13 -1
  65. package/dist/commands/grants/update.d.ts +12 -0
  66. package/dist/commands/grants/update.js +27 -0
  67. package/dist/commands/instructions/guide.d.ts +20 -0
  68. package/dist/commands/instructions/guide.js +84 -0
  69. package/dist/commands/instructions/install.js +57 -33
  70. package/dist/commands/instructions/setup.d.ts +14 -0
  71. package/dist/commands/instructions/setup.js +72 -0
  72. package/dist/commands/integrations/execute.js +1 -1
  73. package/dist/commands/login.d.ts +5 -6
  74. package/dist/commands/login.js +27 -11
  75. package/dist/commands/logout.js +7 -7
  76. package/dist/commands/machines/hosted/start.js +7 -1
  77. package/dist/commands/machines/list.js +4 -4
  78. package/dist/commands/measures/confirm.d.ts +1 -7
  79. package/dist/commands/measures/confirm.js +15 -14
  80. package/dist/commands/measures/list.d.ts +1 -7
  81. package/dist/commands/measures/list.js +1 -7
  82. package/dist/commands/measures/record.js +4 -4
  83. package/dist/commands/measures/show.d.ts +11 -0
  84. package/dist/commands/measures/show.js +26 -0
  85. package/dist/commands/northstars/governance/configure.d.ts +1 -0
  86. package/dist/commands/northstars/governance/configure.js +8 -1
  87. package/dist/commands/proposals/discard.d.ts +5 -0
  88. package/dist/commands/proposals/discard.js +8 -0
  89. package/dist/commands/proposals/keep.d.ts +5 -0
  90. package/dist/commands/proposals/keep.js +8 -0
  91. package/dist/commands/proposals/list.d.ts +15 -0
  92. package/dist/commands/proposals/list.js +74 -0
  93. package/dist/commands/proposals/show.d.ts +12 -0
  94. package/dist/commands/proposals/show.js +27 -0
  95. package/dist/commands/proposals/snooze.d.ts +5 -0
  96. package/dist/commands/proposals/snooze.js +8 -0
  97. package/dist/commands/security/overview.d.ts +11 -0
  98. package/dist/commands/security/overview.js +158 -0
  99. package/dist/commands/signals/monitors/create.d.ts +9 -0
  100. package/dist/commands/signals/monitors/create.js +29 -0
  101. package/dist/commands/signals/monitors/list.d.ts +8 -0
  102. package/dist/commands/signals/monitors/list.js +16 -0
  103. package/dist/commands/signals/monitors/pause.d.ts +11 -0
  104. package/dist/commands/signals/monitors/pause.js +17 -0
  105. package/dist/commands/signals/monitors/resume.d.ts +11 -0
  106. package/dist/commands/signals/monitors/resume.js +17 -0
  107. package/dist/commands/signals/monitors/revise.d.ts +12 -0
  108. package/dist/commands/signals/monitors/revise.js +25 -0
  109. package/dist/commands/signals/monitors/show.d.ts +11 -0
  110. package/dist/commands/signals/monitors/show.js +17 -0
  111. package/dist/commands/signals/monitors/test.d.ts +12 -0
  112. package/dist/commands/signals/monitors/test.js +25 -0
  113. package/dist/commands/signals/monitors/transitions.d.ts +11 -0
  114. package/dist/commands/signals/monitors/transitions.js +17 -0
  115. package/dist/commands/signals/monitors/validate.d.ts +9 -0
  116. package/dist/commands/signals/monitors/validate.js +24 -0
  117. package/dist/commands/signals/schemas/list.d.ts +8 -0
  118. package/dist/commands/signals/schemas/list.js +16 -0
  119. package/dist/commands/signals/schemas/show.d.ts +11 -0
  120. package/dist/commands/signals/schemas/show.js +17 -0
  121. package/dist/commands/signals/sources/list.d.ts +8 -0
  122. package/dist/commands/signals/sources/list.js +16 -0
  123. package/dist/commands/signals/sources/receipts.d.ts +11 -0
  124. package/dist/commands/signals/sources/receipts.js +17 -0
  125. package/dist/commands/signals/sources/show.d.ts +11 -0
  126. package/dist/commands/signals/sources/show.js +17 -0
  127. package/dist/commands/spaces/claim.d.ts +12 -0
  128. package/dist/commands/spaces/claim.js +42 -0
  129. package/dist/commands/spaces/ownership.d.ts +12 -0
  130. package/dist/commands/spaces/ownership.js +46 -0
  131. package/dist/commands/spaces/usage.d.ts +12 -0
  132. package/dist/commands/spaces/usage.js +28 -0
  133. package/dist/commands/spaces/workflows/run.js +3 -0
  134. package/dist/commands/spaces/workflows/runs.js +2 -1
  135. package/dist/commands/spaces/workflows/update.d.ts +6 -1
  136. package/dist/commands/spaces/workflows/update.js +34 -2
  137. package/dist/commands/tasks/cancel-cascade.js +1 -1
  138. package/dist/commands/tasks/cascade-status.d.ts +2 -0
  139. package/dist/commands/tasks/cascade-status.js +27 -1
  140. package/dist/commands/tasks/create-tree.d.ts +5 -1
  141. package/dist/commands/tasks/create-tree.js +35 -7
  142. package/dist/commands/tasks/create.d.ts +4 -0
  143. package/dist/commands/tasks/create.js +16 -0
  144. package/dist/commands/tasks/deliverable/add.js +12 -3
  145. package/dist/commands/tasks/economics-compare.d.ts +15 -0
  146. package/dist/commands/tasks/economics-compare.js +60 -0
  147. package/dist/commands/tasks/expectations/evaluate.d.ts +13 -0
  148. package/dist/commands/tasks/expectations/evaluate.js +43 -0
  149. package/dist/commands/tasks/interrupt.js +2 -2
  150. package/dist/commands/tasks/list.d.ts +1 -0
  151. package/dist/commands/tasks/list.js +44 -1
  152. package/dist/commands/tasks/pause-schedule.js +1 -1
  153. package/dist/commands/tasks/show.d.ts +5 -0
  154. package/dist/commands/tasks/show.js +17 -0
  155. package/dist/commands/tasks/update.d.ts +4 -0
  156. package/dist/commands/tasks/update.js +9 -0
  157. package/dist/commands/tasks/workflow-findings.js +2 -2
  158. package/dist/commands/token/list.d.ts +3 -5
  159. package/dist/commands/token/list.js +99 -57
  160. package/dist/commands/triggers/create.d.ts +2 -0
  161. package/dist/commands/triggers/create.js +15 -0
  162. package/dist/commands/update.d.ts +14 -0
  163. package/dist/commands/update.js +61 -0
  164. package/dist/commands/workspaces/grants.d.ts +12 -0
  165. package/dist/commands/workspaces/grants.js +31 -0
  166. package/dist/commands/workspaces/stewardship.d.ts +13 -0
  167. package/dist/commands/workspaces/stewardship.js +34 -0
  168. package/dist/generated/managed-instruction-guides.json +9 -0
  169. package/dist/hooks/init.d.ts +5 -0
  170. package/dist/hooks/init.js +27 -0
  171. package/dist/lib/agent-config.d.ts +0 -12
  172. package/dist/lib/agent-config.js +1 -27
  173. package/dist/lib/agent-mailbox.d.ts +35 -0
  174. package/dist/lib/agent-mailbox.js +55 -0
  175. package/dist/lib/commitment-endpoints.d.ts +2 -1
  176. package/dist/lib/commitment-endpoints.js +2 -5
  177. package/dist/lib/commitment-product.d.ts +3 -1
  178. package/dist/lib/commitment-product.js +10 -0
  179. package/dist/lib/commitment-terms.js +1 -1
  180. package/dist/lib/commitments.d.ts +17 -15
  181. package/dist/lib/commitments.js +173 -137
  182. package/dist/lib/compasses.d.ts +14 -0
  183. package/dist/lib/compasses.js +25 -11
  184. package/dist/lib/daemon-installer.d.ts +2 -0
  185. package/dist/lib/daemon-installer.js +100 -24
  186. package/dist/lib/first-party-harness-doctor.js +31 -1
  187. package/dist/lib/first-party-harness-remote-install.d.ts +71 -0
  188. package/dist/lib/first-party-harness-remote-install.js +310 -0
  189. package/dist/lib/first-party-harness-remote-update.d.ts +46 -0
  190. package/dist/lib/first-party-harness-remote-update.js +242 -0
  191. package/dist/lib/first-party-harness-startup-update.d.ts +26 -0
  192. package/dist/lib/first-party-harness-startup-update.js +166 -0
  193. package/dist/lib/first-party-harness-update.d.ts +46 -0
  194. package/dist/lib/first-party-harness-update.js +289 -0
  195. package/dist/lib/first-party-harness.js +7 -4
  196. package/dist/lib/grants.d.ts +5 -1
  197. package/dist/lib/grants.js +9 -1
  198. package/dist/lib/hosted-machines.d.ts +7 -0
  199. package/dist/lib/mailbox-human-command.d.ts +11 -0
  200. package/dist/lib/mailbox-human-command.js +41 -0
  201. package/dist/lib/managed-instruction-local.d.ts +12 -0
  202. package/dist/lib/managed-instruction-local.js +58 -0
  203. package/dist/lib/managed-instruction-setup.d.ts +35 -0
  204. package/dist/lib/managed-instruction-setup.js +306 -0
  205. package/dist/lib/measures.d.ts +28 -2
  206. package/dist/lib/measures.js +38 -14
  207. package/dist/lib/memory-sync.d.ts +1 -0
  208. package/dist/lib/memory-sync.js +279 -68
  209. package/dist/lib/message-intent.d.ts +6 -2
  210. package/dist/lib/message-intent.js +1 -0
  211. package/dist/lib/northstars.js +2 -1
  212. package/dist/lib/platform-update-local.d.ts +2 -0
  213. package/dist/lib/platform-update-local.js +113 -0
  214. package/dist/lib/platform-update.d.ts +39 -0
  215. package/dist/lib/platform-update.js +84 -0
  216. package/dist/lib/profile-machine-identity-guard.d.ts +2 -0
  217. package/dist/lib/profile-machine-identity-guard.js +13 -0
  218. package/dist/lib/prompt.d.ts +1 -0
  219. package/dist/lib/prompt.js +4 -3
  220. package/dist/lib/proposal-decision-command.d.ts +19 -0
  221. package/dist/lib/proposal-decision-command.js +64 -0
  222. package/dist/lib/proposals.d.ts +8 -0
  223. package/dist/lib/proposals.js +22 -0
  224. package/dist/lib/roles.d.ts +141 -6
  225. package/dist/lib/roles.js +8 -2
  226. package/dist/lib/signals.d.ts +20 -0
  227. package/dist/lib/signals.js +24 -0
  228. package/dist/lib/space-usage.d.ts +3 -0
  229. package/dist/lib/space-usage.js +17 -0
  230. package/dist/lib/stewardship-output.d.ts +4 -0
  231. package/dist/lib/stewardship-output.js +82 -0
  232. package/dist/lib/task-asset-upload.d.ts +3 -1
  233. package/dist/lib/task-asset-upload.js +1 -0
  234. package/dist/lib/task-batch.d.ts +9 -0
  235. package/dist/lib/task-batch.js +94 -17
  236. package/dist/lib/task-economics.d.ts +16 -0
  237. package/dist/lib/task-economics.js +22 -0
  238. package/dist/lib/task-instruction-offer.d.ts +1 -4
  239. package/dist/lib/task-instruction-offer.js +3 -129
  240. package/dist/lib/triggers.d.ts +11 -3
  241. package/dist/lib/triggers.js +58 -1
  242. package/dist/lib/update-check.d.ts +61 -53
  243. package/dist/lib/update-check.js +453 -314
  244. package/dist/lib/usage-discovery.d.ts +10 -0
  245. package/dist/lib/usage-discovery.js +24 -3
  246. package/dist/lib/workflow-run-budget.d.ts +12 -0
  247. package/dist/lib/workflow-run-budget.js +37 -0
  248. package/dist/lib/workspaces.d.ts +48 -0
  249. package/dist/lib/workspaces.js +8 -0
  250. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +4 -0
  251. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +14 -1
  252. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +3 -4
  253. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +3 -4
  254. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.d.ts +82 -0
  255. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.js +105 -0
  256. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.d.ts +110 -0
  257. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.js +945 -0
  258. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.d.ts +9 -0
  259. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.js +49 -0
  260. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.d.ts +32 -0
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.js +62 -0
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -0
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +4 -1
  264. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +35 -5
  265. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.d.ts +63 -0
  266. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.js +169 -0
  267. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.d.ts +2 -0
  268. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.js +44 -0
  269. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +4 -0
  270. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +12 -0
  271. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +3 -4
  272. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +3 -4
  273. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.d.ts +82 -0
  274. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.js +102 -0
  275. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.d.ts +110 -0
  276. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.js +923 -0
  277. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.d.ts +9 -0
  278. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.js +44 -0
  279. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.d.ts +32 -0
  280. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.js +59 -0
  281. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -0
  282. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
  283. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +35 -5
  284. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.d.ts +63 -0
  285. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.js +163 -0
  286. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.d.ts +2 -0
  287. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.js +41 -0
  288. package/dist/node_modules/@skrr-ai/auth-core/package.json +41 -1
  289. package/dist/node_modules/@skrr-ai/data-provider/index.js +8069 -7121
  290. package/docs/v1/README.md +28 -0
  291. package/docs/v1/api.md +55 -0
  292. package/docs/v1/changelog.md +16 -0
  293. package/docs/v1/check-examples.mjs +178 -0
  294. package/docs/v1/examples/api-readonly.mjs +144 -0
  295. package/docs/v1/operations.md +87 -0
  296. package/docs/v1/quickstart.md +71 -0
  297. package/oclif.manifest.json +49424 -46174
  298. package/package.json +34 -11
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.printStewardshipCoverage = printStewardshipCoverage;
4
+ exports.printWorkspaceGrants = printWorkspaceGrants;
5
+ exports.printWorkspaceStewardship = printWorkspaceStewardship;
6
+ const format_1 = require("./format");
7
+ function printStewardshipCoverage(report, log) {
8
+ if (report.coverage.complete) {
9
+ log('Coverage: complete within the bounded sources.');
10
+ return;
11
+ }
12
+ log('Coverage: incomplete. Unreadable sources do not confirm absence.');
13
+ for (const source of report.coverage.sources) {
14
+ if (source.status === 'unavailable')
15
+ log(`${source.name}: unavailable`);
16
+ else if (source.truncated)
17
+ log(`${source.name}: truncated at 200 rows`);
18
+ }
19
+ }
20
+ function printWorkspaceGrants(report, log) {
21
+ printStewardshipCoverage(report, log);
22
+ printGrantRows(report, log);
23
+ }
24
+ function printGrantRows(report, log) {
25
+ if (report.grants === null) {
26
+ log('Grants: unavailable.');
27
+ return;
28
+ }
29
+ if (!report.grants.length) {
30
+ log('No workspace Grants observed.');
31
+ return;
32
+ }
33
+ (0, format_1.renderTable)(report.grants.map((row) => ({
34
+ id: row.id,
35
+ label: row.label,
36
+ owner: row.ownerUserId,
37
+ active: row.active ? 'yes' : 'no',
38
+ expires: row.expiresAt ?? '',
39
+ envKeys: row.credential?.envKeys.join(', ') ?? '',
40
+ referencedBy: row.referencedBy === null
41
+ ? 'unavailable'
42
+ : `${row.referencedBy.join(', ')}${row.referencesTruncated ? ' (truncated)' : ''}`,
43
+ })), [
44
+ { key: 'id', header: 'ID' },
45
+ { key: 'label', header: 'LABEL' },
46
+ { key: 'owner', header: 'OWNER' },
47
+ { key: 'active', header: 'ACTIVE' },
48
+ { key: 'expires', header: 'EXPIRES' },
49
+ { key: 'envKeys', header: 'ENV NAMES' },
50
+ { key: 'referencedBy', header: 'REFERENCED BY' },
51
+ ], log);
52
+ }
53
+ function printWorkspaceStewardship(report, log) {
54
+ printStewardshipCoverage(report, log);
55
+ log(`Membership: ${report.membership.status}${report.membership.role ? ` (${report.membership.role})` : ''}`);
56
+ for (const [name, rows] of [
57
+ ['Commitments', report.commitments],
58
+ ['Approver seats', report.approverSeats],
59
+ ]) {
60
+ log(`${name}: ${rows === null ? 'unavailable' : rows.length}`);
61
+ if (rows?.length)
62
+ (0, format_1.renderTable)(rows.map((row) => ({
63
+ id: row.id,
64
+ title: row.title ?? '',
65
+ status: row.status ?? '',
66
+ agentId: row.agentId ?? '',
67
+ })), [
68
+ { key: 'id', header: 'ID' },
69
+ { key: 'title', header: 'TITLE' },
70
+ { key: 'status', header: 'STATUS' },
71
+ { key: 'agentId', header: 'EXECUTOR' },
72
+ ], log);
73
+ }
74
+ log(`Authored Agents: ${report.agents === null ? 'unavailable' : report.agents.length}`);
75
+ if (report.agents?.length)
76
+ (0, format_1.renderTable)(report.agents.map((row) => ({ id: row.id, name: row.name ?? '' })), [
77
+ { key: 'id', header: 'ID' },
78
+ { key: 'name', header: 'NAME' },
79
+ ], log);
80
+ log('Grants:');
81
+ printGrantRows(report, log);
82
+ }
@@ -1,4 +1,4 @@
1
- import type { WorkResourceKind } from '@skrr-ai/data-provider';
1
+ import type { WorkResourceKind, TaskResourceWriteReceipt } from '@skrr-ai/data-provider';
2
2
  export type TaskAssetRole = 'input' | 'evidence' | 'deliverable';
3
3
  /**
4
4
  * What the bytes ARE in the work ledger, for an upload that is the archived
@@ -24,6 +24,8 @@ export interface TaskAssetLedgerResource {
24
24
  expectationIds?: string[];
25
25
  }
26
26
  export interface UploadedTaskAsset {
27
+ /** The canonical Task relationship and exact Resource version recorded by this upload. */
28
+ resourceReceipt?: TaskResourceWriteReceipt;
27
29
  id: string;
28
30
  /**
29
31
  * sha256 (hex) of the bytes the server STORED, as the server recorded them.
@@ -148,6 +148,7 @@ async function uploadTaskAssetFile(opts) {
148
148
  filename,
149
149
  mimeType,
150
150
  deduplicated: result.deduplicated === true,
151
+ ...(result.resourceReceipt ? { resourceReceipt: result.resourceReceipt } : {}),
151
152
  };
152
153
  }
153
154
  /**
@@ -4,6 +4,7 @@ export type ApiFailure = {
4
4
  status?: number;
5
5
  code?: string;
6
6
  retryable: boolean;
7
+ requestId?: string;
7
8
  };
8
9
  /** Normalize a thrown API error (or a per-item batch error) into one shape. */
9
10
  export declare function describeApiFailure(err: unknown): ApiFailure;
@@ -39,8 +40,16 @@ export type BatchCreateFailure = {
39
40
  key: string;
40
41
  /** Not attempted because its parent was not created (or an earlier chunk failed). */
41
42
  skipped: boolean;
43
+ /** Unknown is submitted, not equivalent to not_attempted. */
44
+ outcome?: 'unknown' | 'not_attempted' | 'failed';
45
+ externalKey?: string;
42
46
  error: ApiFailure;
43
47
  };
48
+ /** A lost response is not a lost write. Only READ here; never retry a write. */
49
+ export declare function reconcileSubmittedNodes(nodes: BatchCreateNode[], mapping: Record<string, string>, error: ApiFailure, deadlineAt?: number): Promise<{
50
+ rows: BatchCreatedRow[];
51
+ failures: BatchCreateFailure[];
52
+ }>;
44
53
  export type BatchCreateOutcome = {
45
54
  supported: false;
46
55
  } | {
@@ -4,6 +4,7 @@ exports.describeApiFailure = describeApiFailure;
4
4
  exports.isBatchRouteMissing = isBatchRouteMissing;
5
5
  exports.chunkItems = chunkItems;
6
6
  exports.batchIdempotencyKey = batchIdempotencyKey;
7
+ exports.reconcileSubmittedNodes = reconcileSubmittedNodes;
7
8
  exports.createNodesViaBatch = createNodesViaBatch;
8
9
  exports.patchTasksViaBatch = patchTasksViaBatch;
9
10
  /**
@@ -17,9 +18,10 @@ exports.patchTasksViaBatch = patchTasksViaBatch;
17
18
  */
18
19
  const node_crypto_1 = require("node:crypto");
19
20
  const data_provider_1 = require("@skrr-ai/data-provider");
21
+ const tasks_1 = require("./tasks");
20
22
  /** Normalize a thrown API error (or a per-item batch error) into one shape. */
21
23
  function describeApiFailure(err) {
22
- const e = err;
24
+ const e = (err ?? {});
23
25
  let code = e.code;
24
26
  let message = e.message ?? String(err);
25
27
  if (e.body) {
@@ -37,7 +39,8 @@ function describeApiFailure(err) {
37
39
  message,
38
40
  ...(status ? { status } : {}),
39
41
  ...(code ? { code } : {}),
40
- retryable: status === 408 || status === 425 || status === 429 || (status ?? 0) >= 500,
42
+ ...(e.requestId ? { requestId: e.requestId } : {}),
43
+ retryable: !status || status === 408 || status === 425 || status === 429 || (status ?? 0) >= 500,
41
44
  };
42
45
  }
43
46
  /**
@@ -66,6 +69,52 @@ function batchIdempotencyKey(kind, items) {
66
69
  const digest = (0, node_crypto_1.createHash)('sha256').update((0, data_provider_1.stableJson)(items)).digest('hex').slice(0, 40);
67
70
  return `cli-${kind}-batch:${digest}`;
68
71
  }
72
+ /** A lost response is not a lost write. Only READ here; never retry a write. */
73
+ async function reconcileSubmittedNodes(nodes, mapping, error, deadlineAt = Date.now() + 5000) {
74
+ const rows = [];
75
+ const failures = [];
76
+ // Limit simultaneous reads: a 100-item batch must not become 100 connections.
77
+ for (const group of chunkItems(nodes, 4)) {
78
+ await Promise.all(group.map(async (node) => {
79
+ const externalKey = typeof node.payload.externalKey === 'string' ? node.payload.externalKey : undefined;
80
+ if (externalKey && Date.now() < deadlineAt) {
81
+ let timer;
82
+ try {
83
+ const read = (0, tasks_1.findTaskByExternalKey)({
84
+ externalKey, spaceId: node.payload.spaceId, goalId: node.payload.goalId,
85
+ });
86
+ const existing = await Promise.race([read, new Promise((resolve) => {
87
+ timer = setTimeout(() => resolve(null), Math.max(1, deadlineAt - Date.now()));
88
+ })]);
89
+ if (existing?.task?.externalKey === externalKey && (0, tasks_1.taskId)(existing.task)) {
90
+ const id = (0, tasks_1.taskId)(existing.task);
91
+ mapping[node.key] = id;
92
+ rows.push({ key: node.key, id, status: 'exists', externalKey,
93
+ ...(typeof existing.task.identifier === 'string' ? { identifier: existing.task.identifier } : {}),
94
+ });
95
+ return;
96
+ }
97
+ }
98
+ catch { /* A failed read does not prove the write failed. */ }
99
+ finally {
100
+ clearTimeout(timer);
101
+ }
102
+ }
103
+ failures.push({ key: node.key, skipped: false, outcome: 'unknown',
104
+ ...(externalKey ? { externalKey } : {}),
105
+ error: { ...error, code: 'BATCH_OUTCOME_UNKNOWN', retryable: Boolean(externalKey),
106
+ message: `The result for "${node.key}" is unknown. ` +
107
+ (externalKey ? `No committed task was confirmed by external key "${externalKey}"; the original write may still finish. Re-run the same keyed tree to reconcile and resume.` :
108
+ 'This node has no stable external key. Inspect the Space before another write; do not re-run --fresh blindly.'),
109
+ },
110
+ });
111
+ }));
112
+ }
113
+ const position = new Map(nodes.map((n, i) => [n.key, i]));
114
+ rows.sort((a, b) => position.get(a.key) - position.get(b.key));
115
+ failures.sort((a, b) => position.get(a.key) - position.get(b.key));
116
+ return { rows, failures };
117
+ }
69
118
  /**
70
119
  * Create `nodes` (parents before children) in chunks. `mapping` holds key -> id
71
120
  * for nodes that already exist and is extended in place. Stops after the first
@@ -117,25 +166,45 @@ async function createNodesViaBatch(nodes, mapping) {
117
166
  catch (err) {
118
167
  if (chunkIndex === 0 && isBatchRouteMissing(err))
119
168
  return { supported: false };
120
- failures.push({ key: sent[0].key, skipped: false, error: describeApiFailure(err) });
121
- for (const node of sent.slice(1)) {
122
- failures.push({
123
- key: node.key,
124
- skipped: true,
125
- error: {
126
- message: `Not attempted: the batch request containing "${sent[0].key}" failed`,
127
- code: 'BATCH_NOT_ATTEMPTED',
128
- retryable: true,
129
- },
130
- });
169
+ const error = describeApiFailure(err);
170
+ const uncertain = !error.status || error.status === 408 || error.status >= 500 || error.code === 'IDEMPOTENCY_IN_PROGRESS';
171
+ if (uncertain) {
172
+ const recovered = await reconcileSubmittedNodes(sent, mapping, error);
173
+ rows.push(...recovered.rows);
174
+ failures.push(...recovered.failures);
175
+ // Even a fully reconciled chunk stops here: no extra write follows a
176
+ // lost response during this run. Later chunks are explicitly unstarted.
177
+ const remaining = nodes.slice((chunkIndex + 1) * (data_provider_1.TASK_BATCH_MAX_ITEMS ?? 100));
178
+ for (const node of remaining)
179
+ failures.push({ key: node.key, skipped: true,
180
+ outcome: 'not_attempted', externalKey: node.payload.externalKey,
181
+ error: { message: 'Not started after a batch transport failure; resume the same keyed tree.', code: 'BATCH_NOT_ATTEMPTED', retryable: true }, });
182
+ }
183
+ else {
184
+ for (const node of sent)
185
+ failures.push({ key: node.key, skipped: false, outcome: 'failed', error });
186
+ for (const node of nodes.slice((chunkIndex + 1) * (data_provider_1.TASK_BATCH_MAX_ITEMS ?? 100))) {
187
+ failures.push({ key: node.key, skipped: true, outcome: 'not_attempted',
188
+ error: { message: 'Not started after a batch refusal.', code: 'BATCH_NOT_ATTEMPTED', retryable: true } });
189
+ }
131
190
  }
132
191
  break;
133
192
  }
134
193
  let failed = false;
135
- for (const [i, result] of response.results.entries()) {
136
- const node = sent[i];
137
- if (!node)
194
+ const reconciliationDeadlineAt = Date.now() + 5000;
195
+ for (const [i, node] of sent.entries()) {
196
+ const result = response.results?.find((r) => r.index === i);
197
+ if (!result || result.status === 'pending' || (result.ok && !result.id) || (result.error?.status ?? 0) >= 500) {
198
+ const recovered = await reconcileSubmittedNodes([{ ...node, payload: {
199
+ ...node.payload, ...(result?.externalKey ? { externalKey: result.externalKey } : {}),
200
+ } }], mapping, {
201
+ message: 'Batch did not confirm this submitted write', code: 'BATCH_OUTCOME_UNKNOWN', retryable: true,
202
+ }, reconciliationDeadlineAt);
203
+ rows.push(...recovered.rows);
204
+ failures.push(...recovered.failures);
205
+ failed = true;
138
206
  continue;
207
+ }
139
208
  if (result.ok && result.id) {
140
209
  mapping[node.key] = result.id;
141
210
  rows.push({
@@ -151,6 +220,8 @@ async function createNodesViaBatch(nodes, mapping) {
151
220
  failures.push({
152
221
  key: node.key,
153
222
  skipped: result.status === 'skipped',
223
+ outcome: result.status === 'skipped' ? 'not_attempted' : 'failed',
224
+ ...(result.externalKey ? { externalKey: result.externalKey } : {}),
154
225
  error: result.error
155
226
  ? {
156
227
  message: result.error.message,
@@ -162,8 +233,14 @@ async function createNodesViaBatch(nodes, mapping) {
162
233
  });
163
234
  }
164
235
  }
165
- if (failed)
236
+ if (failed) {
237
+ for (const node of nodes.slice((chunkIndex + 1) * (data_provider_1.TASK_BATCH_MAX_ITEMS ?? 100))) {
238
+ failures.push({ key: node.key, skipped: true, outcome: 'not_attempted',
239
+ externalKey: node.payload.externalKey,
240
+ error: { message: 'Not started after an incomplete batch; resume the same keyed tree.', code: 'BATCH_NOT_ATTEMPTED', retryable: true }, });
241
+ }
166
242
  break;
243
+ }
167
244
  }
168
245
  return { supported: true, rows, failures };
169
246
  }
@@ -0,0 +1,16 @@
1
+ export declare function economicsFromFlags(flags: {
2
+ savings?: string;
3
+ per?: string;
4
+ effort?: string;
5
+ risk?: string;
6
+ }, existing?: unknown): {
7
+ savings?: {
8
+ amount: number;
9
+ currency: "USD";
10
+ per: "month" | "year" | "once";
11
+ } | undefined;
12
+ effortHours?: number | undefined;
13
+ risk?: "low" | "medium" | "high" | undefined;
14
+ confidence?: "low" | "medium" | "high" | undefined;
15
+ rationale?: string | undefined;
16
+ } | undefined;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.economicsFromFlags = economicsFromFlags;
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ function economicsFromFlags(flags, existing) {
6
+ if ([flags.savings, flags.per, flags.effort, flags.risk].every((value) => value === undefined))
7
+ return undefined;
8
+ if ((flags.savings === undefined) !== (flags.per === undefined))
9
+ throw new Error('--savings and --per must be supplied together (USD/month, year or once).');
10
+ for (const value of [flags.savings, flags.effort])
11
+ if (value !== undefined && value.trim() === '')
12
+ throw new Error('Economic amounts must be explicit nonnegative numbers.');
13
+ const content = existing && typeof existing === 'object' ? existing : {};
14
+ return data_provider_1.ProposalEconomicsInputSchema.parse({
15
+ ...content,
16
+ ...(flags.savings !== undefined
17
+ ? { savings: { amount: Number(flags.savings), currency: 'USD', per: flags.per } }
18
+ : {}),
19
+ ...(flags.effort !== undefined ? { effortHours: Number(flags.effort) } : {}),
20
+ ...(flags.risk !== undefined ? { risk: flags.risk } : {}),
21
+ });
22
+ }
@@ -1,5 +1,2 @@
1
- /**
2
- * Best-effort contextual activation after a human successfully uses a task
3
- * command. It must never change the task command's exit status.
4
- */
1
+ /** Task creation and login share the same machine-bound, provider-scoped offer. */
5
2
  export declare function maybeOfferTaskManagementInstructions(log: (message: string) => void): Promise<void>;
@@ -1,134 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.maybeOfferTaskManagementInstructions = maybeOfferTaskManagementInstructions;
4
- const auth_core_1 = require("@skrr-ai/auth-core");
5
- const data_provider_1 = require("@skrr-ai/data-provider");
6
- const config_1 = require("./config");
7
- const daemon_target_1 = require("./daemon-target");
8
- const prompt_1 = require("./prompt");
9
- const TEMPLATE_KEY = 'oversky-task-management';
10
- function capabilitiesOf(daemon) {
11
- if (Array.isArray(daemon.capabilities))
12
- return daemon.capabilities.map(String);
13
- if (typeof daemon.capabilities !== 'string')
14
- return [];
15
- try {
16
- const parsed = JSON.parse(daemon.capabilities);
17
- if (Array.isArray(parsed))
18
- return parsed.map(String);
19
- }
20
- catch {
21
- // Older daemon rows used comma-separated capabilities.
22
- }
23
- return daemon.capabilities
24
- .split(',')
25
- .map((capability) => capability.trim())
26
- .filter(Boolean);
27
- }
28
- function detectedProviders(daemon) {
29
- const capabilities = capabilitiesOf(daemon);
30
- const providers = [];
31
- if (capabilities.includes('claude_session'))
32
- providers.push('claude');
33
- if (capabilities.includes('codex_session'))
34
- providers.push('codex');
35
- // A daemon advertises the first-party harness under whichever spelling its
36
- // version speaks; any of them means the harness is there, and the offer names
37
- // it canonically, which is what the server stores.
38
- if (capabilities.some(auth_core_1.isFirstPartyHarnessCapability))
39
- providers.push(auth_core_1.FIRST_PARTY_HARNESS_PROVIDER);
40
- return providers;
41
- }
42
- function providerLabel(provider) {
43
- if (provider === 'claude')
44
- return 'Claude Code';
45
- if (provider === 'codex')
46
- return 'Codex';
47
- return auth_core_1.FIRST_PARTY_HARNESS.displayName;
48
- }
49
- function providerPath(provider) {
50
- if (provider === 'claude')
51
- return '~/.claude/CLAUDE.md';
52
- if (provider === 'codex')
53
- return '~/.codex/AGENTS.md';
54
- // The engine home follows the ENGINE's namespace, not the provider slug — the
55
- // engine reads its managed `AGENTS.md` from there (contract §5).
56
- return `~/.skrr/${(0, auth_core_1.firstPartyHarnessHomeDirname)()}/AGENTS.md`;
57
- }
58
- function shouldSkipOffer() {
59
- return Boolean(!process.stdin.isTTY ||
60
- !process.stdout.isTTY ||
61
- process.env.CI ||
62
- process.env.OVERSKY_HEADLESS ||
63
- process.env.OVERSKY_SESSION_TASK_ID ||
64
- process.env.OVERSKY_SESSION_AGENT_ID ||
65
- process.env.OVERSKY_DISABLE_INSTRUCTION_OFFER === '1');
66
- }
67
- /**
68
- * Best-effort contextual activation after a human successfully uses a task
69
- * command. It must never change the task command's exit status.
70
- */
4
+ const managed_instruction_setup_1 = require("./managed-instruction-setup");
5
+ /** Task creation and login share the same machine-bound, provider-scoped offer. */
71
6
  async function maybeOfferTaskManagementInstructions(log) {
72
- if (shouldSkipOffer())
73
- return;
74
- try {
75
- // The offer speaks of "this machine", so on a Dedicated Runtime guest only the
76
- // guest's own daemon may be the candidate — never the first eligible row of the
77
- // account, which is the owner's laptop (OSK-8759). A guest whose daemon has
78
- // published no id gets no candidate. Off a guest nothing is read here and the
79
- // search below is unchanged.
80
- const local = (0, daemon_target_1.localMachine)({ baseURL: (0, config_1.loadConfig)().baseURL });
81
- if (local.dedicatedRuntime && !local.daemonId)
82
- return;
83
- const [daemons, offerResponse] = await Promise.all([
84
- data_provider_1.dataService.getDaemons(),
85
- data_provider_1.dataService.getManagedInstructionOffer(TEMPLATE_KEY),
86
- ]);
87
- const candidate = daemons.active.find((daemon) => {
88
- if (local.dedicatedRuntime && daemon.daemonId !== local.daemonId)
89
- return false;
90
- if (!detectedProviders(daemon).length)
91
- return false;
92
- return offerResponse.offers.find((offer) => offer.daemonId === daemon.daemonId)?.eligible;
93
- });
94
- if (!candidate)
95
- return;
96
- const providers = detectedProviders(candidate);
97
- const labels = providers.map(providerLabel).join(' and ');
98
- log('');
99
- log(`Let ${labels} manage skrr tasks automatically?`);
100
- log('skrr will add a removable managed block to the user-level agent files on this machine.');
101
- log('Type v to review the exact instruction, y to install and keep it updated, or press Enter for not now.');
102
- const answer = (await (0, prompt_1.prompt)('Install task-management instructions? [y/N/v] ')).toLowerCase();
103
- let accepted = answer === 'y' || answer === 'yes';
104
- if (answer === 'v' || answer === 'view') {
105
- log('');
106
- log('--- exact managed instruction ---');
107
- log(offerResponse.preset.body);
108
- log('--- end instruction ---');
109
- log('');
110
- log('Targets:');
111
- for (const provider of providers) {
112
- log(`- ${providerLabel(provider)}: ${providerPath(provider)}`);
113
- }
114
- accepted = await (0, prompt_1.confirm)('Install this instruction and keep it updated?', true);
115
- }
116
- if (!accepted) {
117
- await data_provider_1.dataService.respondManagedInstructionOffer(TEMPLATE_KEY, {
118
- daemonId: candidate.daemonId,
119
- action: 'snooze',
120
- });
121
- log('Not now. skrr will not ask again for 14 days.');
122
- return;
123
- }
124
- await data_provider_1.dataService.acceptManagedInstructionOffer(TEMPLATE_KEY, {
125
- daemonId: candidate.daemonId,
126
- providers,
127
- });
128
- log(`Installation queued for ${labels}; check Settings for confirmed file status.`);
129
- }
130
- catch {
131
- // A discovery nudge must never turn a successful task operation into a
132
- // failed command. Settings remains the durable recovery/control surface.
133
- }
7
+ await (0, managed_instruction_setup_1.maybeOfferManagedInstructionSetup)({ log, trigger: 'task' });
134
8
  }
@@ -1,4 +1,4 @@
1
- import { type EmbeddedActionRef, type TriggerPreflightReport } from '@skrr-ai/data-provider';
1
+ import { type EmbeddedActionRef, type TriggerPreflightReport, type TriggerSensorConfig } from '@skrr-ai/data-provider';
2
2
  export declare const TRIGGER_KINDS: readonly ["schedule", "once", "event", "stochastic", "self_scheduled", "on_demand", "form", "chat_message"];
3
3
  export declare const TRIGGER_SCOPE_KINDS: readonly ["agent", "group_chat_subscriber", "space_oracle", "space_subscriber", "key_result_watcher", "task_watcher", "goal_watcher", "entity_reminder"];
4
4
  /**
@@ -18,7 +18,7 @@ export declare const TRIGGER_SCOPE_KINDS: readonly ["agent", "group_chat_subscri
18
18
  * capability was live and unreachable. `watch_until` and `sensor_poll` had been
19
19
  * in that state for longer.
20
20
  */
21
- export declare const TRIGGER_EXECUTOR_MODES: readonly ["send_message", "run_only", "enqueue_group_chat_agent_turn", "enqueue_assistant_turn", "enqueue_space_assistant_turn", "proactive_orchestrator_check", "auto_dream_orchestrator", "task_schedule_fire", "goal_planner_tick", "morning_briefing", "builtin_action", "task_execute", "watch_until", "sensor_poll", "external_work_task", "notify_user", "space_cycle_rollover"];
21
+ export declare const TRIGGER_EXECUTOR_MODES: readonly ["send_message", "run_only", "enqueue_group_chat_agent_turn", "enqueue_assistant_turn", "enqueue_space_assistant_turn", "proactive_orchestrator_check", "auto_dream_orchestrator", "task_schedule_fire", "goal_planner_tick", "morning_briefing", "builtin_action", "task_execute", "watch_until", "sensor_poll", "external_work_task", "notify_user", "space_cycle_rollover", "workflow_signal"];
22
22
  export declare const TRIGGER_EVENT_FILTER_MODES: readonly ["equals", "contains", "in_set"];
23
23
  export declare const TRIGGER_CONCURRENCY_POLICIES: readonly ["coalesce_if_active", "allow_parallel"];
24
24
  export declare const TRIGGER_FORM_RESPONSE_MODES: readonly ["thank_you_page", "redirect_url", "run_complete"];
@@ -85,7 +85,9 @@ export interface TriggerDefinition {
85
85
  kind?: string;
86
86
  refs?: Record<string, unknown>;
87
87
  };
88
- execution?: Record<string, unknown>;
88
+ execution?: Record<string, unknown> & {
89
+ sensor?: TriggerSensorConfig;
90
+ };
89
91
  schedule?: Record<string, unknown>;
90
92
  once?: Record<string, unknown>;
91
93
  event?: Record<string, unknown>;
@@ -341,6 +343,12 @@ export declare function nextRunLabel(trigger: TriggerDefinition): string;
341
343
  * (OSK-7711).
342
344
  */
343
345
  export declare function armedLabel(trigger: TriggerDefinition): string;
346
+ /**
347
+ * A keyed sensor that is still ENABLED but degraded (an item has failed for
348
+ * dozens of polls) reads `yes` in ARMED, which is true and not the whole story.
349
+ * Marked here so the list says it, not only `triggers show`.
350
+ */
351
+ export declare function degradedMarker(trigger: TriggerDefinition): string;
344
352
  export declare function renderTriggerList(triggers: TriggerDefinition[], log: (line: string) => void): void;
345
353
  /**
346
354
  * The `duplicate_subscription` warning a create response may carry, as the
@@ -29,6 +29,7 @@ exports.fetchAgentScopedTrigger = fetchAgentScopedTrigger;
29
29
  exports.scopeLabel = scopeLabel;
30
30
  exports.nextRunLabel = nextRunLabel;
31
31
  exports.armedLabel = armedLabel;
32
+ exports.degradedMarker = degradedMarker;
32
33
  exports.renderTriggerList = renderTriggerList;
33
34
  exports.formatDuplicateSubscriptionWarning = formatDuplicateSubscriptionWarning;
34
35
  exports.armedStateLabel = armedStateLabel;
@@ -99,6 +100,9 @@ exports.TRIGGER_EXECUTOR_MODES = [
99
100
  'external_work_task',
100
101
  'notify_user',
101
102
  'space_cycle_rollover',
103
+ // Resolve a workflow step an agent parked with `workflow_await`, when this
104
+ // trigger's event arrives. Needs `--workflow-event-key`.
105
+ 'workflow_signal',
102
106
  ];
103
107
  exports.TRIGGER_EVENT_FILTER_MODES = ['equals', 'contains', 'in_set'];
104
108
  exports.TRIGGER_CONCURRENCY_POLICIES = ['coalesce_if_active', 'allow_parallel'];
@@ -748,6 +752,15 @@ function armedLabel(trigger) {
748
752
  }
749
753
  return 'yes';
750
754
  }
755
+ /**
756
+ * A keyed sensor that is still ENABLED but degraded (an item has failed for
757
+ * dozens of polls) reads `yes` in ARMED, which is true and not the whole story.
758
+ * Marked here so the list says it, not only `triggers show`.
759
+ */
760
+ function degradedMarker(trigger) {
761
+ const reason = trigger.execution?.sensor?.state?.degradedReason;
762
+ return reason ? ' (degraded)' : '';
763
+ }
751
764
  function renderTriggerList(triggers, log) {
752
765
  if (triggers.length === 0) {
753
766
  log('No triggers.');
@@ -756,7 +769,7 @@ function renderTriggerList(triggers, log) {
756
769
  (0, format_1.renderTable)(triggers.map((trigger) => ({
757
770
  id: trigger.id ?? '-',
758
771
  kind: trigger.kind ?? '-',
759
- enabled: armedLabel(trigger),
772
+ enabled: `${armedLabel(trigger)}${degradedMarker(trigger)}`,
760
773
  scope: scopeLabel(trigger),
761
774
  next: nextRunLabel(trigger),
762
775
  label: trigger.label ?? '',
@@ -768,6 +781,12 @@ function renderTriggerList(triggers, log) {
768
781
  { key: 'next', header: 'NEXT/LAST', maxWidth: 24 },
769
782
  { key: 'label', header: 'LABEL', maxWidth: 32 },
770
783
  ], log);
784
+ const degraded = triggers.filter((t) => degradedMarker(t));
785
+ if (degraded.length > 0) {
786
+ log('');
787
+ log(`${degraded.length} trigger(s) are enabled but degraded — ` +
788
+ 'see `Degraded:` in `triggers show <id>`.');
789
+ }
771
790
  const unsynced = triggers.filter((t) => armedLabel(t).startsWith('!'));
772
791
  if (unsynced.length > 0) {
773
792
  log('');
@@ -872,6 +891,44 @@ function renderTriggerSummary(trigger, log, options = {}) {
872
891
  log(`Label: ${trigger.label}`);
873
892
  if (trigger.execution?.mode)
874
893
  log(`Mode: ${String(trigger.execution.mode)}`);
894
+ const sensor = trigger.execution?.mode === 'sensor_poll' ? trigger.execution.sensor : undefined;
895
+ if (sensor?.measureSink) {
896
+ log(`Measure: ${sensor.measureSink.measureId} — platform fetched, unconfirmed`);
897
+ if (sensor.state?.lastSinkError)
898
+ log(`Sink: ${sensor.state.lastSinkError}`);
899
+ else if (sensor.state?.lastSinkAt)
900
+ log(`Sink: last reading ${sensor.state.lastSinkValue ?? '-'} at ${sensor.state.lastSinkAt}`);
901
+ else
902
+ log('Sink: awaiting a numeric reading');
903
+ }
904
+ // A keyed sensor can be quietly blind (items held back, unreadable, failing).
905
+ // Each count is printed, and zero is printed too: "0" and "absent" must read
906
+ // differently from a sensor that has never been counted.
907
+ if (sensor?.cursor?.mode === 'keyed' && sensor.state) {
908
+ const st = sensor.state;
909
+ const n = (v) => v ?? 0;
910
+ log(`Keyed: deferred ${n(st.deferredCount)}, unreadable ${n(st.unreadableCount)}, failed ${n(st.failedItemCount)}, quarantined ${n(st.quarantinedCount)}, duplicates ${n(st.duplicateCount)}, unsubjected ${n(st.unsubjectedCount)} (cumulative)`);
911
+ }
912
+ if (sensor?.cursor?.mode === 'keyed' && sensor.state) {
913
+ const st = sensor.state;
914
+ // A reseed publishes nothing by design, so it is the one change nothing
915
+ // else records: say when it happened, why, and how often.
916
+ if (st.reseededAt) {
917
+ const why = st.reseededReason
918
+ ? (data_provider_1.KEYED_RESEED_COPY[st.reseededReason] ?? st.reseededReason)
919
+ : 'reason not recorded';
920
+ log(`Reseeded: ${st.reseededAt} (${st.reseededReason ?? 'unknown'}: ${why}); ${st.reseedCount ?? 1} time(s); nothing was published for it`);
921
+ }
922
+ if (st.itemFailurePolls)
923
+ log(`Items: failing for ${st.itemFailurePolls} poll(s) in a row`);
924
+ }
925
+ // The sensor is degraded, not just carrying a line of text: say it first.
926
+ if (sensor?.state?.degradedReason)
927
+ log(`Degraded: ${sensor.state.degradedReason}`);
928
+ if (sensor?.state?.consecutiveErrors)
929
+ log(`Errors: ${sensor.state.consecutiveErrors} feed failure(s) in a row (the sensor disables itself if the feed keeps failing)`);
930
+ if (sensor?.state?.lastError)
931
+ log(`Problem: ${sensor.state.lastError}`);
875
932
  // An `external_work_task` writes into someone else's system, and which
876
933
  // contract governs that write — and whether it posts by itself — was readable
877
934
  // only by pulling `execution.effectPolicy` out of raw JSON. A trigger that can