@skrr-ai/cli 0.1.21 → 0.1.23

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 (245) hide show
  1. package/README.md +83 -73
  2. package/bin/dev-fallback.js +221 -0
  3. package/bin/run.js +43 -0
  4. package/dist/base-command.d.ts +15 -0
  5. package/dist/base-command.js +71 -10
  6. package/dist/commands/agents/attach-harness.d.ts +37 -0
  7. package/dist/commands/agents/attach-harness.js +102 -3
  8. package/dist/commands/agents/chat.d.ts +69 -1
  9. package/dist/commands/agents/chat.js +202 -22
  10. package/dist/commands/agents/create.d.ts +38 -0
  11. package/dist/commands/agents/create.js +95 -2
  12. package/dist/commands/agents/schedule-trace.js +11 -0
  13. package/dist/commands/agents/show.js +29 -1
  14. package/dist/commands/api-keys/create.d.ts +24 -0
  15. package/dist/commands/api-keys/create.js +80 -0
  16. package/dist/commands/api-keys/list.d.ts +11 -0
  17. package/dist/commands/api-keys/list.js +42 -0
  18. package/dist/commands/api-keys/revoke.d.ts +14 -0
  19. package/dist/commands/api-keys/revoke.js +33 -0
  20. package/dist/commands/api-keys/rotate.d.ts +19 -0
  21. package/dist/commands/api-keys/rotate.js +42 -0
  22. package/dist/commands/balance/index.d.ts +18 -0
  23. package/dist/commands/balance/index.js +29 -0
  24. package/dist/commands/balance/show.d.ts +25 -0
  25. package/dist/commands/balance/show.js +60 -0
  26. package/dist/commands/balance/statement.d.ts +19 -0
  27. package/dist/commands/balance/statement.js +52 -0
  28. package/dist/commands/browser/doctor.d.ts +11 -0
  29. package/dist/commands/browser/doctor.js +11 -0
  30. package/dist/commands/code/jobs/approve.d.ts +25 -0
  31. package/dist/commands/code/jobs/approve.js +52 -0
  32. package/dist/commands/code/jobs/cancel.d.ts +12 -0
  33. package/dist/commands/code/jobs/cancel.js +39 -0
  34. package/dist/commands/code/jobs/index.d.ts +19 -0
  35. package/dist/commands/code/jobs/index.js +38 -0
  36. package/dist/commands/code/jobs/list.d.ts +12 -0
  37. package/dist/commands/code/jobs/list.js +87 -0
  38. package/dist/commands/code/jobs/run.d.ts +32 -0
  39. package/dist/commands/code/jobs/run.js +151 -0
  40. package/dist/commands/code/jobs/show.d.ts +12 -0
  41. package/dist/commands/code/jobs/show.js +86 -0
  42. package/dist/commands/commitments/create.d.ts +1 -0
  43. package/dist/commands/commitments/create.js +19 -5
  44. package/dist/commands/commitments/preflight.js +18 -4
  45. package/dist/commands/commitments/receipt-metrics.d.ts +39 -0
  46. package/dist/commands/commitments/receipt-metrics.js +78 -0
  47. package/dist/commands/convos/search.js +5 -5
  48. package/dist/commands/harnesses/leases/list.d.ts +3 -0
  49. package/dist/commands/harnesses/leases/list.js +59 -12
  50. package/dist/commands/harnesses/leases/show.js +36 -0
  51. package/dist/commands/harnesses/list.d.ts +18 -0
  52. package/dist/commands/harnesses/list.js +30 -0
  53. package/dist/commands/harnesses/products.js +48 -3
  54. package/dist/commands/harnesses/quota.d.ts +16 -0
  55. package/dist/commands/harnesses/quota.js +26 -1
  56. package/dist/commands/harnesses/usage.js +17 -0
  57. package/dist/commands/inbox/index.d.ts +2 -1
  58. package/dist/commands/inbox/index.js +27 -4
  59. package/dist/commands/login.js +4 -1
  60. package/dist/commands/machines/list.d.ts +1 -0
  61. package/dist/commands/machines/list.js +33 -5
  62. package/dist/commands/memory/approvals/issue.d.ts +18 -0
  63. package/dist/commands/memory/approvals/issue.js +63 -0
  64. package/dist/commands/memory/commit.js +5 -2
  65. package/dist/commands/memory/context.d.ts +3 -2
  66. package/dist/commands/memory/context.js +9 -11
  67. package/dist/commands/memory/delete.d.ts +1 -1
  68. package/dist/commands/memory/list.d.ts +1 -1
  69. package/dist/commands/memory/list.js +1 -1
  70. package/dist/commands/memory/mounts/resolve.d.ts +10 -0
  71. package/dist/commands/memory/mounts/resolve.js +27 -0
  72. package/dist/commands/memory/proposals/commit.d.ts +18 -0
  73. package/dist/commands/memory/proposals/commit.js +32 -0
  74. package/dist/commands/memory/proposals/create.d.ts +18 -0
  75. package/dist/commands/memory/proposals/create.js +56 -0
  76. package/dist/commands/memory/proposals/list.d.ts +13 -0
  77. package/dist/commands/memory/proposals/list.js +31 -0
  78. package/dist/commands/memory/proposals/promote.d.ts +22 -0
  79. package/dist/commands/memory/proposals/promote.js +33 -0
  80. package/dist/commands/memory/proposals/reject.d.ts +16 -0
  81. package/dist/commands/memory/proposals/reject.js +28 -0
  82. package/dist/commands/memory/rebuild-index.d.ts +20 -0
  83. package/dist/commands/memory/rebuild-index.js +25 -0
  84. package/dist/commands/memory/save.d.ts +1 -1
  85. package/dist/commands/memory/save.js +1 -1
  86. package/dist/commands/memory/search.d.ts +6 -3
  87. package/dist/commands/memory/search.js +27 -3
  88. package/dist/commands/memory/show.d.ts +1 -1
  89. package/dist/commands/memory/stores/archive.d.ts +14 -0
  90. package/dist/commands/memory/stores/archive.js +31 -0
  91. package/dist/commands/memory/stores/create.d.ts +12 -0
  92. package/dist/commands/memory/stores/create.js +30 -0
  93. package/dist/commands/memory/stores/delete.d.ts +15 -0
  94. package/dist/commands/memory/stores/delete.js +38 -0
  95. package/dist/commands/memory/stores/list.d.ts +10 -0
  96. package/dist/commands/memory/stores/list.js +29 -0
  97. package/dist/commands/memory/stores/show.d.ts +12 -0
  98. package/dist/commands/memory/stores/show.js +14 -0
  99. package/dist/commands/memory/stores/update.d.ts +15 -0
  100. package/dist/commands/memory/stores/update.js +39 -0
  101. package/dist/commands/memory/sync/delete.d.ts +13 -0
  102. package/dist/commands/memory/sync/delete.js +35 -0
  103. package/dist/commands/memory/sync/pull.d.ts +19 -0
  104. package/dist/commands/memory/sync/pull.js +52 -0
  105. package/dist/commands/memory/sync/push.d.ts +18 -0
  106. package/dist/commands/memory/sync/push.js +115 -0
  107. package/dist/commands/memory/sync/resolve.d.ts +23 -0
  108. package/dist/commands/memory/sync/resolve.js +27 -0
  109. package/dist/commands/memory/sync/status.d.ts +9 -0
  110. package/dist/commands/memory/sync/status.js +22 -0
  111. package/dist/commands/memory/topics/archive.d.ts +20 -0
  112. package/dist/commands/memory/topics/archive.js +29 -0
  113. package/dist/commands/memory/topics/create.d.ts +23 -0
  114. package/dist/commands/memory/topics/create.js +46 -0
  115. package/dist/commands/memory/topics/delete.d.ts +22 -0
  116. package/dist/commands/memory/topics/delete.js +30 -0
  117. package/dist/commands/memory/topics/forget.d.ts +22 -0
  118. package/dist/commands/memory/topics/forget.js +29 -0
  119. package/dist/commands/memory/topics/list.d.ts +13 -0
  120. package/dist/commands/memory/topics/list.js +22 -0
  121. package/dist/commands/memory/topics/move.d.ts +22 -0
  122. package/dist/commands/memory/topics/move.js +26 -0
  123. package/dist/commands/memory/topics/show.d.ts +17 -0
  124. package/dist/commands/memory/topics/show.js +21 -0
  125. package/dist/commands/memory/topics/update.d.ts +23 -0
  126. package/dist/commands/memory/topics/update.js +27 -0
  127. package/dist/commands/memory/tree.d.ts +5 -2
  128. package/dist/commands/memory/tree.js +20 -2
  129. package/dist/commands/memory/update.d.ts +1 -1
  130. package/dist/commands/memory/versions/list.d.ts +16 -0
  131. package/dist/commands/memory/versions/list.js +22 -0
  132. package/dist/commands/memory/versions/redact.d.ts +21 -0
  133. package/dist/commands/memory/versions/redact.js +22 -0
  134. package/dist/commands/memory/versions/restore.d.ts +20 -0
  135. package/dist/commands/memory/versions/restore.js +16 -0
  136. package/dist/commands/memory/versions/show.d.ts +15 -0
  137. package/dist/commands/memory/versions/show.js +17 -0
  138. package/dist/commands/messages/list.js +25 -8
  139. package/dist/commands/messages/show.js +10 -0
  140. package/dist/commands/store/install.js +5 -1
  141. package/dist/commands/store/releases.js +1 -1
  142. package/dist/commands/store/update.js +5 -1
  143. package/dist/commands/subscriptions/cancel.js +5 -1
  144. package/dist/commands/subscriptions/health.js +5 -1
  145. package/dist/commands/subscriptions/status.js +5 -1
  146. package/dist/commands/subscriptions/subscribe.js +5 -1
  147. package/dist/commands/tasks/activity.d.ts +2 -3
  148. package/dist/commands/tasks/activity.js +15 -5
  149. package/dist/commands/tasks/complete.d.ts +18 -150
  150. package/dist/commands/tasks/complete.js +161 -600
  151. package/dist/commands/tasks/create.d.ts +5 -0
  152. package/dist/commands/tasks/create.js +107 -4
  153. package/dist/commands/tasks/deliverable/add.d.ts +8 -0
  154. package/dist/commands/tasks/deliverable/add.js +41 -8
  155. package/dist/commands/tasks/deliverable/confirm.d.ts +5 -5
  156. package/dist/commands/tasks/deliverable/confirm.js +9 -18
  157. package/dist/commands/tasks/deliverable/list.d.ts +12 -0
  158. package/dist/commands/tasks/deliverable/list.js +37 -0
  159. package/dist/commands/tasks/events/append.d.ts +2 -0
  160. package/dist/commands/tasks/events/append.js +11 -4
  161. package/dist/commands/tasks/events/list.d.ts +1 -0
  162. package/dist/commands/tasks/events/list.js +1 -0
  163. package/dist/commands/tasks/events/tail.d.ts +1 -0
  164. package/dist/commands/tasks/events/tail.js +1 -0
  165. package/dist/commands/tasks/expectations/assess.d.ts +21 -0
  166. package/dist/commands/tasks/expectations/assess.js +77 -0
  167. package/dist/commands/tasks/expectations.js +14 -18
  168. package/dist/commands/tasks/judge.d.ts +1 -0
  169. package/dist/commands/tasks/judge.js +2 -1
  170. package/dist/commands/tasks/output.d.ts +2 -11
  171. package/dist/commands/tasks/output.js +64 -145
  172. package/dist/commands/tasks/report.d.ts +3 -3
  173. package/dist/commands/tasks/report.js +64 -41
  174. package/dist/commands/tasks/resource/add.d.ts +23 -0
  175. package/dist/commands/tasks/resource/add.js +76 -0
  176. package/dist/commands/tasks/resource/list.d.ts +13 -0
  177. package/dist/commands/tasks/resource/list.js +41 -0
  178. package/dist/commands/tasks/result/show.d.ts +13 -0
  179. package/dist/commands/tasks/result/show.js +46 -0
  180. package/dist/commands/tasks/result/submit.d.ts +26 -0
  181. package/dist/commands/tasks/result/submit.js +134 -0
  182. package/dist/commands/tasks/resume/save.d.ts +16 -0
  183. package/dist/commands/tasks/resume/save.js +59 -0
  184. package/dist/commands/tasks/resume/show.d.ts +13 -0
  185. package/dist/commands/tasks/resume/show.js +35 -0
  186. package/dist/commands/tasks/review.d.ts +17 -0
  187. package/dist/commands/tasks/review.js +54 -0
  188. package/dist/commands/tasks/runs.js +5 -0
  189. package/dist/commands/tasks/timeline.d.ts +2 -2
  190. package/dist/commands/tasks/timeline.js +10 -23
  191. package/dist/commands/tasks/updates/add.d.ts +22 -0
  192. package/dist/commands/tasks/updates/add.js +101 -0
  193. package/dist/commands/tasks/updates/list.d.ts +15 -0
  194. package/dist/commands/tasks/updates/list.js +57 -0
  195. package/dist/commands/tasks/waive.d.ts +1 -0
  196. package/dist/commands/tasks/waive.js +2 -1
  197. package/dist/lib/agentic-stream.d.ts +257 -0
  198. package/dist/lib/agentic-stream.js +490 -33
  199. package/dist/lib/balance.d.ts +8 -0
  200. package/dist/lib/commitment-product.d.ts +10 -1
  201. package/dist/lib/commitment-product.js +66 -2
  202. package/dist/lib/commitments.d.ts +4 -1
  203. package/dist/lib/commitments.js +32 -1
  204. package/dist/lib/conversation-search.d.ts +3 -0
  205. package/dist/lib/conversation-search.js +75 -0
  206. package/dist/lib/execution-target.d.ts +21 -0
  207. package/dist/lib/execution-target.js +22 -6
  208. package/dist/lib/harnesses.d.ts +82 -6
  209. package/dist/lib/harnesses.js +30 -2
  210. package/dist/lib/hosted-machines.js +9 -0
  211. package/dist/lib/inbox.d.ts +2 -1
  212. package/dist/lib/machines.d.ts +17 -0
  213. package/dist/lib/machines.js +29 -0
  214. package/dist/lib/managed-agent-keys.d.ts +104 -0
  215. package/dist/lib/managed-agent-keys.js +50 -0
  216. package/dist/lib/memory-scope.d.ts +4 -3
  217. package/dist/lib/memory-scope.js +9 -9
  218. package/dist/lib/memory-sync.d.ts +114 -0
  219. package/dist/lib/memory-sync.js +730 -0
  220. package/dist/lib/message-provenance.d.ts +42 -0
  221. package/dist/lib/message-provenance.js +89 -0
  222. package/dist/lib/scoped-memory-command.d.ts +68 -0
  223. package/dist/lib/scoped-memory-command.js +183 -0
  224. package/dist/lib/session-task-endpoints.d.ts +1 -1
  225. package/dist/lib/session-task-endpoints.js +7 -0
  226. package/dist/lib/sky-code-broker.d.ts +47 -0
  227. package/dist/lib/sky-code-broker.js +50 -0
  228. package/dist/lib/sky-code-doctor.js +10 -1
  229. package/dist/lib/task-artifact-flags.d.ts +2 -0
  230. package/dist/lib/task-artifact-flags.js +7 -0
  231. package/dist/lib/task-execution.d.ts +4 -5
  232. package/dist/lib/task-execution.js +4 -5
  233. package/dist/lib/task-extras.d.ts +1 -5
  234. package/dist/lib/task-extras.js +1 -5
  235. package/dist/lib/task-transcript.d.ts +5 -7
  236. package/dist/lib/task-transcript.js +8 -16
  237. package/dist/lib/tasks.d.ts +7 -21
  238. package/dist/lib/tasks.js +17 -20
  239. package/dist/lib/triggers.d.ts +39 -1
  240. package/dist/lib/triggers.js +70 -2
  241. package/dist/lib/usage-discovery.d.ts +17 -1
  242. package/dist/lib/usage-discovery.js +17 -1
  243. package/dist/node_modules/@skrr-ai/data-provider/index.js +3733 -3618
  244. package/oclif.manifest.json +25726 -19886
  245. package/package.json +26 -5
@@ -42,11 +42,7 @@ exports.taskLookupApi = {
42
42
  */
43
43
  followUp: (id, body) => data_provider_1.request.post(`${base(id)}/follow-up`, body),
44
44
  cancelFollowUp: (id) => data_provider_1.request.post(`${base(id)}/follow-up/cancel`, {}),
45
- /**
46
- * Atomic completion: moves the task AND writes the TASK_OUTPUT comment in one
47
- * request, so a crash between the two cannot leave a done task with no record
48
- * of what it produced.
49
- */
45
+ /** Result-first closeout: submit one immutable Result, then project status. */
50
46
  complete: (id, body) => data_provider_1.request.post(`${base(id)}/complete`, body),
51
47
  treePosition: (id, body) => data_provider_1.request.patch(`${base(id)}/tree-position`, body),
52
48
  createAndStart: (body) => data_provider_1.request.post(`${MOUNT}/create-and-start`, body),
@@ -13,7 +13,7 @@ export type ParsedTaskOutput = {
13
13
  verdict: string;
14
14
  };
15
15
  /**
16
- * Parsed `---TASK_OUTPUT---` block plus the comment it came from.
16
+ * Parsed historical `---TASK_OUTPUT---` block plus the Comment it came from.
17
17
  */
18
18
  export type TaskOutputComment = {
19
19
  commentId: string;
@@ -36,9 +36,9 @@ export type TaskOutputComment = {
36
36
  /**
37
37
  * Mirror of `api/server/services/taskCompletionFormatting.js:parseTaskOutputBlock`.
38
38
  * Kept as a CLI-local copy on purpose — the CLI cannot import from `api/`, and
39
- * the block format is a wire contract (`skrr tasks complete` writes it, the
40
- * server responders read it), not an implementation detail. Keep the two in
41
- * lockstep, including the single-line field semantics: the `m` flag makes `$`
39
+ * the block format is a historical wire contract, not an implementation
40
+ * detail. Keep the two compatibility readers in lockstep, including the
41
+ * single-line field semantics: the `m` flag makes `$`
42
42
  * match at each line end, so a value stops at its own newline. That is correct
43
43
  * by construction — `tasks complete` collapses `[\r\n]+` to spaces before
44
44
  * writing — but a hand-authored block CAN carry continuation lines, which this
@@ -63,9 +63,7 @@ export declare function normalizeMessage(message: Record<string, unknown>): Tran
63
63
  export declare function selectWindow<T>(items: T[], limit: number | null, head?: boolean): T[];
64
64
  export declare function fetchTranscript(conversationId: string): Promise<TranscriptMessage[]>;
65
65
  /**
66
- * Newest `---TASK_OUTPUT---` comment on a task, or null when the agent never
67
- * posted one (still running, failed before finalization, or completed by a path
68
- * that skipped the canonical block).
66
+ * Newest historical `---TASK_OUTPUT---` Comment, or null when none exists.
69
67
  */
70
68
  export declare function fetchLatestTaskOutputComment(taskId: string, limit?: number): Promise<TaskOutputComment | null>;
71
69
  /** Last message the agent (not the user) produced in the execution conversation. */
@@ -14,25 +14,19 @@ exports.unverifiedOutcomeNote = unverifiedOutcomeNote;
14
14
  /**
15
15
  * Task → agent-response plumbing for the `skrr` CLI.
16
16
  *
17
- * A task's real output is spread across three surfaces:
18
- * 1. `task.conversationId` the execution conversation, i.e. the messages the
19
- * agent actually produced (`skrr tasks transcript`).
20
- * 2. A `---TASK_OUTPUT---` comment posted by `skrr tasks complete` / the
21
- * TasksMCP completion path — the structured verdict.
22
- * 3. The run rows (`tasks runs` / `execution-summary`) — did it even finish.
23
- *
24
- * Nothing tied those together, so "what did the agent produce for this task?"
25
- * meant three commands plus a jq hop. This module is the shared read layer for
26
- * `tasks transcript` and `tasks output`.
17
+ * Shared transcript normalization plus read-only parsing of historical
18
+ * TASK_OUTPUT Comments. Canonical output now lives in TaskResult, TaskReview,
19
+ * TaskResourceLink, and TaskExecutionRun; no writer may call the compatibility
20
+ * functions below.
27
21
  */
28
22
  const data_provider_1 = require("@skrr-ai/data-provider");
29
23
  const TASK_OUTPUT_FIELDS = ['status', 'summary', 'artifacts', 'verdict'];
30
24
  /**
31
25
  * Mirror of `api/server/services/taskCompletionFormatting.js:parseTaskOutputBlock`.
32
26
  * Kept as a CLI-local copy on purpose — the CLI cannot import from `api/`, and
33
- * the block format is a wire contract (`skrr tasks complete` writes it, the
34
- * server responders read it), not an implementation detail. Keep the two in
35
- * lockstep, including the single-line field semantics: the `m` flag makes `$`
27
+ * the block format is a historical wire contract, not an implementation
28
+ * detail. Keep the two compatibility readers in lockstep, including the
29
+ * single-line field semantics: the `m` flag makes `$`
36
30
  * match at each line end, so a value stops at its own newline. That is correct
37
31
  * by construction — `tasks complete` collapses `[\r\n]+` to spaces before
38
32
  * writing — but a hand-authored block CAN carry continuation lines, which this
@@ -121,9 +115,7 @@ async function fetchTranscript(conversationId) {
121
115
  return list.map(normalizeMessage);
122
116
  }
123
117
  /**
124
- * Newest `---TASK_OUTPUT---` comment on a task, or null when the agent never
125
- * posted one (still running, failed before finalization, or completed by a path
126
- * that skipped the canonical block).
118
+ * Newest historical `---TASK_OUTPUT---` Comment, or null when none exists.
127
119
  */
128
120
  async function fetchLatestTaskOutputComment(taskId, limit = 50) {
129
121
  const response = (await data_provider_1.dataService.listTaskComments(taskId, { limit }));
@@ -111,7 +111,7 @@ export declare function parseDeliverableCoordinate(spec: string): {
111
111
  error: string;
112
112
  };
113
113
  /** Lifecycle values a caller may assert, for flag validation. */
114
- export declare const DELIVERABLE_LIFECYCLE_VALUES: readonly ["local", "in_review", "durable", "blocked", "superseded"];
114
+ export declare const DELIVERABLE_LIFECYCLE_VALUES: readonly ["local", "in_review", "available", "unavailable", "superseded"];
115
115
  export declare function buildTaskCreatePayload(body: TaskRecord, flags?: TaskCreateFlagValues): TaskRecord;
116
116
  /**
117
117
  * The Agent this CLI process is running AS, if any.
@@ -245,27 +245,13 @@ export declare function normalizeBulkUpdateInput(input: unknown): Array<{
245
245
  patch: TaskRecord;
246
246
  }>;
247
247
  /**
248
- * Verdict strings the server recognises on a task completion.
248
+ * Historical workflow-verdict strings recognised while parsing legacy task
249
+ * output. Canonical completion has no `--verdict`; domain conclusions live on
250
+ * TaskResult and acceptance lives on TaskReview.
249
251
  *
250
- * `--verdict` is free text: `skrr tasks complete <id> --verdict banana`
251
- * succeeds and the value is permanently recorded, while `--status` beside it
252
- * is enumerated and rejects a typo. So `--verdict aproved` closes a task with
253
- * a verdict nothing matches, quietly.
254
- *
255
- * It cannot simply be enumerated, and that is the point worth recording:
256
- *
257
- * - A REVIEWER task legitimately passes a JSON object
258
- * (`{"posture":"request_changes","confidence":0.82,"criteria":[…]}`) —
259
- * documented in the task-execution prompt and consumed by
260
- * `normalizeReviewPosture`. `options:` on the flag would refuse it.
261
- * - That normaliser accepts synonyms, and when it recognises NOTHING it does
262
- * not fail — it derives the posture from the criteria instead. So a typo
263
- * silently becomes whatever the criteria imply.
264
- *
265
- * Hence a warning, not a refusal, over the set the server actually matches.
266
- * Mirrored from `normalizeReviewPosture` in
267
- * `api/server/services/TasksMCP/taskExecutionHelpers.js` and pinned against it
268
- * by `task-verdict-parity.spec.ts`, the same way TASK_WORK_EVENT_KINDS is.
252
+ * Kept only so old `TASK_OUTPUT`/TaskWorkEvent readers can classify stored
253
+ * values consistently with `normalizeReviewPosture`. New commands must not
254
+ * import this vocabulary for authoring.
269
255
  */
270
256
  export declare const RECOGNIZED_TASK_VERDICTS: readonly ["request_changes", "changes_requested", "needs_changes", "needs_revision", "approved", "approve", "pass", "passed", "blocked"];
271
257
  /** The server's own normalisation, so the same spellings match here. */
package/dist/lib/tasks.js CHANGED
@@ -538,8 +538,18 @@ async function applyDefaultAgentToPayload(payload, defaultAgent, opts = {}) {
538
538
  }
539
539
  if (hasExplicitTaskAssignee(payload)) {
540
540
  return {
541
+ // `applied` is about the DEFAULT, not about the assignment. It reads the
542
+ // other way: a caller who named `--assignee-agent` and got back
543
+ // `{applied: false, source: 'explicit-assignee'}` stopped and went to
544
+ // verify with `tasks show`, where the assignment was perfectly correct —
545
+ // on the one output a scripted caller would check before `tasks start`
546
+ // (OSK-7712). The two subfields together assert the opposite of what they
547
+ // mean. Renaming the field would break every existing reader, so the
548
+ // note — which exists for exactly this, "an explanation for the operator,
549
+ // not an error" — says it instead.
541
550
  applied: false,
542
551
  source: 'explicit-assignee',
552
+ note: 'You named the assignee, so no default was applied. The assignment is in place.',
543
553
  agentIds: stringArray(payload.assigneeAgentIds),
544
554
  userIds: stringArray(payload.assigneeUserIds),
545
555
  };
@@ -548,6 +558,7 @@ async function applyDefaultAgentToPayload(payload, defaultAgent, opts = {}) {
548
558
  return {
549
559
  applied: false,
550
560
  source: 'existing-assignee',
561
+ note: 'The task already had an assignee, so no default was applied. It is unchanged.',
551
562
  agentIds: stringArray(opts.existingTask?.assigneeAgentIds),
552
563
  userIds: stringArray(opts.existingTask?.assigneeUserIds),
553
564
  };
@@ -809,27 +820,13 @@ function formatApiError(err) {
809
820
  return String(err);
810
821
  }
811
822
  /**
812
- * Verdict strings the server recognises on a task completion.
823
+ * Historical workflow-verdict strings recognised while parsing legacy task
824
+ * output. Canonical completion has no `--verdict`; domain conclusions live on
825
+ * TaskResult and acceptance lives on TaskReview.
813
826
  *
814
- * `--verdict` is free text: `skrr tasks complete <id> --verdict banana`
815
- * succeeds and the value is permanently recorded, while `--status` beside it
816
- * is enumerated and rejects a typo. So `--verdict aproved` closes a task with
817
- * a verdict nothing matches, quietly.
818
- *
819
- * It cannot simply be enumerated, and that is the point worth recording:
820
- *
821
- * - A REVIEWER task legitimately passes a JSON object
822
- * (`{"posture":"request_changes","confidence":0.82,"criteria":[…]}`) —
823
- * documented in the task-execution prompt and consumed by
824
- * `normalizeReviewPosture`. `options:` on the flag would refuse it.
825
- * - That normaliser accepts synonyms, and when it recognises NOTHING it does
826
- * not fail — it derives the posture from the criteria instead. So a typo
827
- * silently becomes whatever the criteria imply.
828
- *
829
- * Hence a warning, not a refusal, over the set the server actually matches.
830
- * Mirrored from `normalizeReviewPosture` in
831
- * `api/server/services/TasksMCP/taskExecutionHelpers.js` and pinned against it
832
- * by `task-verdict-parity.spec.ts`, the same way TASK_WORK_EVENT_KINDS is.
827
+ * Kept only so old `TASK_OUTPUT`/TaskWorkEvent readers can classify stored
828
+ * values consistently with `normalizeReviewPosture`. New commands must not
829
+ * import this vocabulary for authoring.
833
830
  */
834
831
  exports.RECOGNIZED_TASK_VERDICTS = [
835
832
  'request_changes',
@@ -93,8 +93,27 @@ export interface TriggerDefinition {
93
93
  selfScheduled?: Record<string, unknown>;
94
94
  form?: Record<string, unknown>;
95
95
  chatMessage?: Record<string, unknown>;
96
- audit?: Record<string, unknown>;
96
+ /**
97
+ * Fire outcomes. Typed rather than `Record<string, unknown>` for the fields
98
+ * the summary prints, so a reader cannot be shown a count the compiler never
99
+ * checked — `fireCount` is SUCCESSES and `failureCount` is failures, and
100
+ * conflating them is the confusion this shape exists to prevent (OSK-7842).
101
+ */
102
+ audit?: {
103
+ fireCount?: number;
104
+ failureCount?: number;
105
+ lastResult?: string;
106
+ lastError?: string;
107
+ lastFiredAt?: string;
108
+ [key: string]: unknown;
109
+ };
97
110
  webhook?: Record<string, unknown>;
111
+ /** Whether the SCHEDULER has actually heard of this trigger. See `armedLabel`. */
112
+ scheduleSync?: {
113
+ status?: string;
114
+ lastError?: string;
115
+ lastErrorAt?: string;
116
+ };
98
117
  /**
99
118
  * Server-DERIVED: maintained by a managed producer, so the mutation routes
100
119
  * refuse to edit or remove it. Optional because a server predating the field
@@ -303,6 +322,25 @@ export declare class AgentTriggerScopeError extends Error {
303
322
  export declare function fetchAgentScopedTrigger(agentId: string, triggerId: string): Promise<TriggerDefinition>;
304
323
  export declare function scopeLabel(trigger: TriggerDefinition): string;
305
324
  export declare function nextRunLabel(trigger: TriggerDefinition): string;
325
+ /**
326
+ * Whether a trigger will actually fire — not merely whether someone left it on.
327
+ *
328
+ * `enabled` means "not manually disabled", and two states diverge from it
329
+ * permanently:
330
+ *
331
+ * `!sync` — `enabled: true` with `scheduleSync.status` not `ok`. The row is
332
+ * on to every read surface and the scheduler has never heard of it. Twenty
333
+ * triggers were left in exactly this state in ninety minutes of production,
334
+ * and nothing on the agent, trigger or schedule surfaces reported it — so
335
+ * an operator looking at an enabled trigger had no reason to doubt it
336
+ * (OSK-7727).
337
+ * `spent` — a `once` trigger that has fired. It has no next occurrence, so
338
+ * `enabled` and "will fire again" diverge forever after the single fire; an
339
+ * agent that has been used for a while accumulates a growing list of
340
+ * `enabled: true` rows whose obvious reading is "these are armed"
341
+ * (OSK-7711).
342
+ */
343
+ export declare function armedLabel(trigger: TriggerDefinition): string;
306
344
  export declare function renderTriggerList(triggers: TriggerDefinition[], log: (line: string) => void): void;
307
345
  /**
308
346
  * The `duplicate_subscription` warning a create response may carry, as the
@@ -28,6 +28,7 @@ exports.agentRefEntity = agentRefEntity;
28
28
  exports.fetchAgentScopedTrigger = fetchAgentScopedTrigger;
29
29
  exports.scopeLabel = scopeLabel;
30
30
  exports.nextRunLabel = nextRunLabel;
31
+ exports.armedLabel = armedLabel;
31
32
  exports.renderTriggerList = renderTriggerList;
32
33
  exports.formatDuplicateSubscriptionWarning = formatDuplicateSubscriptionWarning;
33
34
  exports.armedStateLabel = armedStateLabel;
@@ -711,6 +712,35 @@ function nextRunLabel(trigger) {
711
712
  '';
712
713
  return next ? String(next) : '-';
713
714
  }
715
+ /**
716
+ * Whether a trigger will actually fire — not merely whether someone left it on.
717
+ *
718
+ * `enabled` means "not manually disabled", and two states diverge from it
719
+ * permanently:
720
+ *
721
+ * `!sync` — `enabled: true` with `scheduleSync.status` not `ok`. The row is
722
+ * on to every read surface and the scheduler has never heard of it. Twenty
723
+ * triggers were left in exactly this state in ninety minutes of production,
724
+ * and nothing on the agent, trigger or schedule surfaces reported it — so
725
+ * an operator looking at an enabled trigger had no reason to doubt it
726
+ * (OSK-7727).
727
+ * `spent` — a `once` trigger that has fired. It has no next occurrence, so
728
+ * `enabled` and "will fire again" diverge forever after the single fire; an
729
+ * agent that has been used for a while accumulates a growing list of
730
+ * `enabled: true` rows whose obvious reading is "these are armed"
731
+ * (OSK-7711).
732
+ */
733
+ function armedLabel(trigger) {
734
+ if (trigger.enabled === false)
735
+ return 'no';
736
+ const sync = trigger.scheduleSync?.status;
737
+ if (sync && sync !== 'ok')
738
+ return `!${sync}`;
739
+ if (trigger.kind === 'once' && trigger.once && trigger.once.firedAt) {
740
+ return 'spent';
741
+ }
742
+ return 'yes';
743
+ }
714
744
  function renderTriggerList(triggers, log) {
715
745
  if (triggers.length === 0) {
716
746
  log('No triggers.');
@@ -719,18 +749,25 @@ function renderTriggerList(triggers, log) {
719
749
  (0, format_1.renderTable)(triggers.map((trigger) => ({
720
750
  id: trigger.id ?? '-',
721
751
  kind: trigger.kind ?? '-',
722
- enabled: trigger.enabled === false ? 'no' : 'yes',
752
+ enabled: armedLabel(trigger),
723
753
  scope: scopeLabel(trigger),
724
754
  next: nextRunLabel(trigger),
725
755
  label: trigger.label ?? '',
726
756
  })), [
727
757
  { key: 'id', header: 'ID', verbatim: true },
728
758
  { key: 'kind', header: 'KIND', maxWidth: 14 },
729
- { key: 'enabled', header: 'ON' },
759
+ { key: 'enabled', header: 'ARMED' },
730
760
  { key: 'scope', header: 'SCOPE', maxWidth: 42 },
731
761
  { key: 'next', header: 'NEXT/LAST', maxWidth: 24 },
732
762
  { key: 'label', header: 'LABEL', maxWidth: 32 },
733
763
  ], log);
764
+ const unsynced = triggers.filter((t) => armedLabel(t).startsWith('!'));
765
+ if (unsynced.length > 0) {
766
+ log('');
767
+ log(`${unsynced.length} trigger(s) are enabled but the scheduler has not registered them — ` +
768
+ 'they will not fire until the orphan reconciler succeeds. ' +
769
+ 'See `scheduleSync.lastError` in `triggers show <id> --json`.');
770
+ }
734
771
  }
735
772
  /**
736
773
  * The `duplicate_subscription` warning a create response may carry, as the
@@ -841,6 +878,37 @@ function renderTriggerSummary(trigger, log, options = {}) {
841
878
  const next = nextRunLabel(trigger);
842
879
  if (next !== '-')
843
880
  log(`Next/last:${next.length > 0 ? ` ${next}` : ''}`);
881
+ /*
882
+ * What actually happened when it fired.
883
+ *
884
+ * This summary printed nothing about outcomes at all: two one-shot runs
885
+ * fired, died, and the only surface that held the reason was `audit.lastError`
886
+ * in raw `--json` (OSK-7842). And the count alone misleads in the same
887
+ * direction, because `fireCount` counts SUCCESSES — so a trigger that fails
888
+ * every single time reads `fires 0` next to a recent fire time, which is what
889
+ * a trigger that has never run looks like too.
890
+ *
891
+ * Both numbers are therefore printed together, and only when there is
892
+ * something to say. `failureCount` is absent on rows last written before it
893
+ * existed, so it is reported only when present rather than defaulted to 0 —
894
+ * "not counted" must not render as "never failed".
895
+ */
896
+ const audit = trigger.audit;
897
+ if (audit) {
898
+ const fires = audit.fireCount ?? 0;
899
+ const failures = audit.failureCount;
900
+ if (fires > 0 || failures !== undefined || audit.lastResult || audit.lastError) {
901
+ const parts = [`${fires} succeeded`];
902
+ if (failures !== undefined)
903
+ parts.push(`${failures} failed`);
904
+ if (audit.lastResult)
905
+ parts.push(`last ${audit.lastResult}`);
906
+ log(`Fires: ${parts.join(', ')}`);
907
+ }
908
+ // The reason, at the surface a reader reaches for — not only in `--json`.
909
+ if (audit.lastError)
910
+ log(`Last error: ${audit.lastError}`);
911
+ }
844
912
  if (trigger.webhook?.configured !== undefined) {
845
913
  log(`Webhook: ${trigger.webhook.configured ? 'configured' : 'not configured'}`);
846
914
  }
@@ -6,7 +6,23 @@ import type { CommandManifest } from './command-manifest';
6
6
  * domain. These smaller views are derived from that same manifest; there is no
7
7
  * second, hand-maintained command catalogue to drift from the binary.
8
8
  */
9
- export declare const USAGE_OVERVIEW_TOKEN_BUDGET = 200;
9
+ /**
10
+ * A bound on an agent's FIRST read, not an inventory of today's topics.
11
+ *
12
+ * The overview is one header line plus every domain name, so its cost grows
13
+ * linearly with the topic count — and it had reached exactly 200, meaning the
14
+ * next legitimate domain anyone added failed the hygiene audit no matter how
15
+ * small it was. Adding four commands under `api-keys` measured 201. A guard
16
+ * pinned to the current total stops expressing "keep the first read cheap" and
17
+ * starts expressing "do not add topics", which is not what it is for.
18
+ *
19
+ * Raised with headroom rather than to exactly fit, so the next person does not
20
+ * have to make this same judgment for one token. If it is reached again, the
21
+ * better question is whether the new commands have a natural home in an
22
+ * existing domain — folding is preferable to a new topic when one exists — and
23
+ * only then whether the bound is still the right size.
24
+ */
25
+ export declare const USAGE_OVERVIEW_TOKEN_BUDGET = 240;
10
26
  export declare const USAGE_DOMAIN_TOKEN_BUDGET = 500;
11
27
  export type UsageCommand = {
12
28
  command: string;
@@ -17,7 +17,23 @@ const command_manifest_1 = require("./command-manifest");
17
17
  * domain. These smaller views are derived from that same manifest; there is no
18
18
  * second, hand-maintained command catalogue to drift from the binary.
19
19
  */
20
- exports.USAGE_OVERVIEW_TOKEN_BUDGET = 200;
20
+ /**
21
+ * A bound on an agent's FIRST read, not an inventory of today's topics.
22
+ *
23
+ * The overview is one header line plus every domain name, so its cost grows
24
+ * linearly with the topic count — and it had reached exactly 200, meaning the
25
+ * next legitimate domain anyone added failed the hygiene audit no matter how
26
+ * small it was. Adding four commands under `api-keys` measured 201. A guard
27
+ * pinned to the current total stops expressing "keep the first read cheap" and
28
+ * starts expressing "do not add topics", which is not what it is for.
29
+ *
30
+ * Raised with headroom rather than to exactly fit, so the next person does not
31
+ * have to make this same judgment for one token. If it is reached again, the
32
+ * better question is whether the new commands have a natural home in an
33
+ * existing domain — folding is preferable to a new topic when one exists — and
34
+ * only then whether the bound is still the right size.
35
+ */
36
+ exports.USAGE_OVERVIEW_TOKEN_BUDGET = 240;
21
37
  exports.USAGE_DOMAIN_TOKEN_BUDGET = 500;
22
38
  const GENERIC_FLAGS = new Set(['bare', 'help', 'json', 'token', 'workspace']);
23
39
  /**