@skrr-ai/cli 0.1.36 → 0.1.38

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 (266) hide show
  1. package/README.md +17 -4
  2. package/bin/dev-fallback.js +167 -4
  3. package/dist/base-command.js +46 -2
  4. package/dist/commands/agents/actions/create.d.ts +5 -0
  5. package/dist/commands/agents/actions/create.js +42 -5
  6. package/dist/commands/agents/actions/delete.d.ts +1 -0
  7. package/dist/commands/agents/actions/delete.js +7 -0
  8. package/dist/commands/agents/actions/update.d.ts +5 -0
  9. package/dist/commands/agents/actions/update.js +27 -1
  10. package/dist/commands/agents/api-actions/add.d.ts +41 -0
  11. package/dist/commands/agents/api-actions/add.js +205 -0
  12. package/dist/commands/agents/api-actions/index.d.ts +39 -0
  13. package/dist/commands/agents/api-actions/index.js +103 -0
  14. package/dist/commands/agents/api-actions/remove.d.ts +14 -0
  15. package/dist/commands/agents/api-actions/remove.js +36 -0
  16. package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
  17. package/dist/commands/agents/avatar/default/apply.js +56 -0
  18. package/dist/commands/agents/avatar/default/index.d.ts +29 -0
  19. package/dist/commands/agents/avatar/default/index.js +61 -0
  20. package/dist/commands/agents/avatar/default/set.d.ts +24 -0
  21. package/dist/commands/agents/avatar/default/set.js +120 -0
  22. package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
  23. package/dist/commands/agents/avatar/library/delete.js +47 -0
  24. package/dist/commands/agents/avatar/library/index.d.ts +16 -0
  25. package/dist/commands/agents/avatar/library/index.js +56 -0
  26. package/dist/commands/agents/avatar/presets.d.ts +19 -0
  27. package/dist/commands/agents/avatar/presets.js +56 -0
  28. package/dist/commands/agents/avatar/upload.js +7 -1
  29. package/dist/commands/agents/categories/create.d.ts +14 -0
  30. package/dist/commands/agents/categories/create.js +46 -0
  31. package/dist/commands/agents/categories/delete.d.ts +13 -0
  32. package/dist/commands/agents/categories/delete.js +41 -0
  33. package/dist/commands/agents/categories/index.d.ts +36 -0
  34. package/dist/commands/agents/categories/index.js +135 -0
  35. package/dist/commands/agents/categories/update.d.ts +22 -0
  36. package/dist/commands/agents/categories/update.js +59 -0
  37. package/dist/commands/agents/chat.d.ts +21 -0
  38. package/dist/commands/agents/chat.js +94 -7
  39. package/dist/commands/agents/create.d.ts +10 -0
  40. package/dist/commands/agents/create.js +64 -3
  41. package/dist/commands/agents/ensure-default.d.ts +27 -0
  42. package/dist/commands/agents/ensure-default.js +65 -0
  43. package/dist/commands/agents/list.d.ts +15 -0
  44. package/dist/commands/agents/list.js +31 -1
  45. package/dist/commands/agents/mute.d.ts +16 -0
  46. package/dist/commands/agents/mute.js +38 -0
  47. package/dist/commands/agents/pin.d.ts +16 -0
  48. package/dist/commands/agents/pin.js +38 -0
  49. package/dist/commands/agents/scene-background/upload.d.ts +30 -0
  50. package/dist/commands/agents/scene-background/upload.js +97 -0
  51. package/dist/commands/agents/show.js +13 -0
  52. package/dist/commands/agents/tools/auth.d.ts +19 -0
  53. package/dist/commands/agents/tools/auth.js +41 -0
  54. package/dist/commands/agents/tools/calls.d.ts +36 -0
  55. package/dist/commands/agents/tools/calls.js +117 -0
  56. package/dist/commands/agents/tools/index.d.ts +20 -0
  57. package/dist/commands/agents/tools/index.js +77 -0
  58. package/dist/commands/agents/unmute.d.ts +16 -0
  59. package/dist/commands/agents/unmute.js +38 -0
  60. package/dist/commands/agents/unpin.d.ts +16 -0
  61. package/dist/commands/agents/unpin.js +38 -0
  62. package/dist/commands/agents/update.d.ts +12 -0
  63. package/dist/commands/agents/update.js +74 -3
  64. package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
  65. package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
  66. package/dist/commands/convos/messages.d.ts +13 -0
  67. package/dist/commands/convos/messages.js +40 -16
  68. package/dist/commands/daemon/index.js +8 -1
  69. package/dist/commands/daemon/logs.d.ts +26 -0
  70. package/dist/commands/daemon/logs.js +56 -0
  71. package/dist/commands/daemon/uninstall.js +1 -1
  72. package/dist/commands/followups/act.d.ts +22 -0
  73. package/dist/commands/followups/act.js +103 -0
  74. package/dist/commands/followups/cancel.d.ts +20 -0
  75. package/dist/commands/followups/cancel.js +50 -0
  76. package/dist/commands/followups/checkin.d.ts +27 -0
  77. package/dist/commands/followups/checkin.js +107 -0
  78. package/dist/commands/followups/list.d.ts +24 -0
  79. package/dist/commands/followups/list.js +90 -0
  80. package/dist/commands/followups/observability.d.ts +23 -0
  81. package/dist/commands/followups/observability.js +114 -0
  82. package/dist/commands/followups/remind.d.ts +26 -0
  83. package/dist/commands/followups/remind.js +106 -0
  84. package/dist/commands/followups/reschedule.d.ts +15 -0
  85. package/dist/commands/followups/reschedule.js +48 -0
  86. package/dist/commands/followups/resolve.d.ts +23 -0
  87. package/dist/commands/followups/resolve.js +54 -0
  88. package/dist/commands/followups/show.d.ts +12 -0
  89. package/dist/commands/followups/show.js +46 -0
  90. package/dist/commands/followups/watch.d.ts +51 -0
  91. package/dist/commands/followups/watch.js +211 -0
  92. package/dist/commands/goals/labels/add.js +19 -2
  93. package/dist/commands/goals/labels/remove.js +22 -2
  94. package/dist/commands/harnesses/forget.js +28 -0
  95. package/dist/commands/harnesses/install.d.ts +41 -0
  96. package/dist/commands/harnesses/install.js +165 -0
  97. package/dist/commands/harnesses/installers.d.ts +45 -0
  98. package/dist/commands/harnesses/installers.js +155 -0
  99. package/dist/commands/harnesses/list.d.ts +82 -1
  100. package/dist/commands/harnesses/list.js +104 -12
  101. package/dist/commands/harnesses/models.js +10 -1
  102. package/dist/commands/harnesses/show.d.ts +15 -0
  103. package/dist/commands/harnesses/show.js +44 -3
  104. package/dist/commands/harnesses/update.js +1 -1
  105. package/dist/commands/harnesses/usage.d.ts +25 -0
  106. package/dist/commands/harnesses/usage.js +24 -2
  107. package/dist/commands/instructions/status.js +13 -1
  108. package/dist/commands/labels/list.d.ts +24 -1
  109. package/dist/commands/labels/list.js +62 -19
  110. package/dist/commands/machines/dedicated/catalog.js +4 -15
  111. package/dist/commands/machines/dedicated/create.d.ts +8 -0
  112. package/dist/commands/machines/dedicated/create.js +58 -1
  113. package/dist/commands/machines/dedicated/destroy.js +18 -4
  114. package/dist/commands/machines/dedicated/list.js +9 -6
  115. package/dist/commands/machines/hosted/list.js +12 -0
  116. package/dist/commands/machines/list.js +11 -0
  117. package/dist/commands/machines/show.d.ts +1 -0
  118. package/dist/commands/machines/show.js +40 -11
  119. package/dist/commands/memory/governance/index.d.ts +21 -0
  120. package/dist/commands/memory/governance/index.js +64 -0
  121. package/dist/commands/memory/governance/set.d.ts +24 -0
  122. package/dist/commands/memory/governance/set.js +95 -0
  123. package/dist/commands/memory/provenance.d.ts +18 -0
  124. package/dist/commands/memory/provenance.js +66 -0
  125. package/dist/commands/profiles/list.d.ts +23 -0
  126. package/dist/commands/profiles/list.js +96 -0
  127. package/dist/commands/search/skills.d.ts +11 -1
  128. package/dist/commands/search/skills.js +26 -8
  129. package/dist/commands/skills/details.d.ts +2 -0
  130. package/dist/commands/skills/details.js +24 -1
  131. package/dist/commands/skills/import-as-actions.d.ts +32 -0
  132. package/dist/commands/skills/import-as-actions.js +175 -0
  133. package/dist/commands/skills/install.d.ts +2 -0
  134. package/dist/commands/skills/install.js +24 -1
  135. package/dist/commands/skills/invocable.js +6 -2
  136. package/dist/commands/skills/local.d.ts +40 -0
  137. package/dist/commands/skills/local.js +160 -0
  138. package/dist/commands/skills/search.d.ts +11 -1
  139. package/dist/commands/skills/search.js +29 -8
  140. package/dist/commands/spaces/actions/add.js +23 -5
  141. package/dist/commands/spaces/actions/available.js +3 -0
  142. package/dist/commands/spaces/actions/list.d.ts +5 -0
  143. package/dist/commands/spaces/actions/list.js +49 -3
  144. package/dist/commands/spaces/actions/run.d.ts +28 -0
  145. package/dist/commands/spaces/actions/run.js +146 -0
  146. package/dist/commands/spaces/actions/update.js +27 -5
  147. package/dist/commands/spaces/create.d.ts +3 -0
  148. package/dist/commands/spaces/create.js +32 -2
  149. package/dist/commands/spaces/label-summaries.d.ts +27 -0
  150. package/dist/commands/spaces/label-summaries.js +64 -0
  151. package/dist/commands/spaces/labels/add.js +19 -2
  152. package/dist/commands/spaces/labels/remove.js +22 -2
  153. package/dist/commands/spaces/show.js +2 -0
  154. package/dist/commands/spaces/task-rollups.d.ts +5 -0
  155. package/dist/commands/spaces/task-rollups.js +15 -4
  156. package/dist/commands/spaces/update.d.ts +5 -0
  157. package/dist/commands/spaces/update.js +41 -4
  158. package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
  159. package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +105 -0
  160. package/dist/commands/tasks/actions/attach.js +32 -7
  161. package/dist/commands/tasks/complete.d.ts +1 -0
  162. package/dist/commands/tasks/complete.js +21 -1
  163. package/dist/commands/tasks/create.d.ts +3 -0
  164. package/dist/commands/tasks/create.js +34 -2
  165. package/dist/commands/tasks/events/append.js +29 -6
  166. package/dist/commands/tasks/expectations/assess.d.ts +12 -0
  167. package/dist/commands/tasks/expectations/assess.js +123 -14
  168. package/dist/commands/tasks/expectations.js +95 -17
  169. package/dist/commands/tasks/follow-up.js +2 -2
  170. package/dist/commands/tasks/labels/attach.js +20 -3
  171. package/dist/commands/tasks/labels/detach.js +21 -3
  172. package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
  173. package/dist/commands/tasks/lifecycle/attach.js +47 -0
  174. package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
  175. package/dist/commands/tasks/lifecycle/definitions.js +59 -0
  176. package/dist/commands/tasks/lifecycle/detach.d.ts +19 -0
  177. package/dist/commands/tasks/lifecycle/detach.js +72 -0
  178. package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
  179. package/dist/commands/tasks/lifecycle/history.js +38 -0
  180. package/dist/commands/tasks/lifecycle/migrate.d.ts +14 -0
  181. package/dist/commands/tasks/lifecycle/migrate.js +68 -0
  182. package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
  183. package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
  184. package/dist/commands/tasks/lifecycle/reopen.d.ts +15 -0
  185. package/dist/commands/tasks/lifecycle/reopen.js +71 -0
  186. package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
  187. package/dist/commands/tasks/lifecycle/show.js +27 -0
  188. package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
  189. package/dist/commands/tasks/lifecycle/start.js +30 -0
  190. package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
  191. package/dist/commands/tasks/lifecycle/transition.js +109 -0
  192. package/dist/commands/tasks/list.js +16 -9
  193. package/dist/commands/tasks/move.d.ts +1 -0
  194. package/dist/commands/tasks/move.js +29 -0
  195. package/dist/commands/tasks/result/submit.js +11 -1
  196. package/dist/commands/tasks/review-queue.d.ts +44 -0
  197. package/dist/commands/tasks/review-queue.js +314 -0
  198. package/dist/commands/tasks/show.d.ts +11 -0
  199. package/dist/commands/tasks/show.js +139 -4
  200. package/dist/commands/tasks/trust.js +7 -2
  201. package/dist/commands/tasks/update.d.ts +1 -0
  202. package/dist/commands/tasks/update.js +83 -0
  203. package/dist/commands/tasks/updates/add.js +1 -1
  204. package/dist/commands/token/list.d.ts +22 -0
  205. package/dist/commands/token/list.js +68 -0
  206. package/dist/commands/token/revoke.d.ts +23 -0
  207. package/dist/commands/token/revoke.js +53 -0
  208. package/dist/lib/agent-actions.d.ts +92 -11
  209. package/dist/lib/agent-actions.js +171 -25
  210. package/dist/lib/agent-config.d.ts +11 -0
  211. package/dist/lib/agent-config.js +85 -3
  212. package/dist/lib/agent-pin-mute.d.ts +29 -0
  213. package/dist/lib/agent-pin-mute.js +30 -0
  214. package/dist/lib/agent-visual-refs.d.ts +33 -0
  215. package/dist/lib/agent-visual-refs.js +267 -0
  216. package/dist/lib/agentic-stream.d.ts +6 -0
  217. package/dist/lib/agentic-stream.js +34 -3
  218. package/dist/lib/assignee-resolver.d.ts +1 -1
  219. package/dist/lib/assignee-resolver.js +8 -0
  220. package/dist/lib/bulk-task-targets.d.ts +12 -0
  221. package/dist/lib/bulk-task-targets.js +34 -1
  222. package/dist/lib/cli-installers.d.ts +130 -0
  223. package/dist/lib/cli-installers.js +145 -0
  224. package/dist/lib/command-miss.js +55 -7
  225. package/dist/lib/dedicated-lease-command.d.ts +13 -0
  226. package/dist/lib/dedicated-lease-command.js +22 -1
  227. package/dist/lib/dedicated-machines.d.ts +95 -1
  228. package/dist/lib/dedicated-machines.js +236 -2
  229. package/dist/lib/failed-lookup.d.ts +3 -0
  230. package/dist/lib/failed-lookup.js +40 -0
  231. package/dist/lib/first-party-harness-agent.js +16 -2
  232. package/dist/lib/first-party-harness-doctor.d.ts +15 -0
  233. package/dist/lib/first-party-harness-doctor.js +126 -27
  234. package/dist/lib/followups.d.ts +115 -0
  235. package/dist/lib/followups.js +127 -0
  236. package/dist/lib/harnesses.d.ts +8 -0
  237. package/dist/lib/instruction-input.d.ts +19 -1
  238. package/dist/lib/instruction-input.js +52 -1
  239. package/dist/lib/label-ref.d.ts +95 -0
  240. package/dist/lib/label-ref.js +163 -0
  241. package/dist/lib/label-scope.d.ts +17 -2
  242. package/dist/lib/label-scope.js +27 -7
  243. package/dist/lib/local-skills.d.ts +98 -0
  244. package/dist/lib/local-skills.js +195 -0
  245. package/dist/lib/machines.d.ts +10 -10
  246. package/dist/lib/machines.js +23 -1
  247. package/dist/lib/search-query.d.ts +19 -0
  248. package/dist/lib/search-query.js +35 -0
  249. package/dist/lib/space-custom-actions.d.ts +72 -0
  250. package/dist/lib/space-custom-actions.js +117 -0
  251. package/dist/lib/space-resolver.d.ts +1 -21
  252. package/dist/lib/space-resolver.js +19 -10
  253. package/dist/lib/task-closure.d.ts +33 -0
  254. package/dist/lib/task-closure.js +104 -0
  255. package/dist/lib/task-lifecycle-output.d.ts +14 -0
  256. package/dist/lib/task-lifecycle-output.js +209 -0
  257. package/dist/lib/task-ref-resolver.d.ts +1 -17
  258. package/dist/lib/task-ref-resolver.js +18 -8
  259. package/dist/lib/tasks.d.ts +3 -0
  260. package/dist/lib/tasks.js +40 -3
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
  263. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  264. package/dist/node_modules/@skrr-ai/data-provider/index.js +5559 -4897
  265. package/oclif.manifest.json +33890 -28690
  266. package/package.json +24 -6
@@ -41,21 +41,70 @@ class TasksExpectationsAssess extends base_command_1.BaseCommand {
41
41
  }),
42
42
  'spec-version': core_1.Flags.integer({ description: 'Task specification version being assessed' }),
43
43
  'idempotency-key': core_1.Flags.string({ description: 'Stable retry key' }),
44
+ all: core_1.Flags.boolean({
45
+ description: 'Assess every Expectation still awaiting one on this Task, with the same decision ' +
46
+ 'and reason. Already-settled Expectations are left alone, and ones already judged ' +
47
+ 'unmet are skipped unless --include-unmet.',
48
+ }),
49
+ 'include-unmet': core_1.Flags.boolean({
50
+ description: 'With --all, also re-assess Expectations somebody judged unmet — for after the work ' +
51
+ 'was fixed. Overwrites a considered rejection, so it is never implied.',
52
+ }),
44
53
  json: core_1.Flags.boolean({ description: 'Output JSON' }),
45
54
  };
55
+ /**
56
+ * Which Expectations `--all` covers.
57
+ *
58
+ * ONLY the ones nothing has settled. An already-assessed Expectation carries
59
+ * somebody's judgement, and a bulk pass that overwrote it would silently
60
+ * replace a considered `unmet` with a blanket `met` — which is the one thing a
61
+ * batch verb must never do. Overriding an existing assessment stays a
62
+ * deliberate, single, named act.
63
+ */
64
+ async awaitingIds(taskId, { includeUnmet = false } = {}) {
65
+ const acceptance = await data_provider_1.dataService.getTaskAcceptance(taskId);
66
+ const gatingUnsettled = acceptance.expectations.filter((expectation) => expectation.gating && !expectation.met);
67
+ /*
68
+ * A row somebody judged `unmet` is SKIPPED by default and NAMED either way.
69
+ *
70
+ * Skipping is right: a blanket `--all --decision met` that swept up a
71
+ * reviewer's considered "no" is the one thing a batch verb must never do.
72
+ * Saying nothing about it was not: the row displayed as "needs assessment"
73
+ * (it no longer does), `--all` reported the Task settled, and the board
74
+ * could never be cleared because the only bulk verb silently declined to
75
+ * touch the only rows left.
76
+ */
77
+ const rejected = gatingUnsettled
78
+ .filter((expectation) => expectation.state === 'unmet')
79
+ .map((expectation) => expectation.id);
80
+ const ids = gatingUnsettled
81
+ .filter((expectation) => !expectation.assessmentId || (includeUnmet && expectation.state === 'unmet'))
82
+ .map((expectation) => expectation.id);
83
+ return { ids, rejected };
84
+ }
46
85
  async run() {
47
86
  this.requireAuth();
48
87
  const { args, flags } = await this.parse(TasksExpectationsAssess);
49
88
  // `assess <task> <expectation>` gives both; `assess <expectation>` inside a
50
89
  // task runtime gives one, and it is the Expectation.
51
90
  const expectationId = args.expectation ?? args.task;
52
- if (!expectationId) {
53
- this.error('An Expectation id is required: `tasks expectations assess <task> <expectation>`', {
91
+ if (!expectationId && !flags.all) {
92
+ this.error('An Expectation id is required: `tasks expectations assess <task> <expectation>`, ' +
93
+ 'or pass --all to settle every Expectation still awaiting one.', {
54
94
  exit: 1,
55
95
  });
56
96
  }
97
+ /*
98
+ * Which positional is the TASK.
99
+ *
100
+ * `assess <task> <expectation>` gives both, so the first is the Task.
101
+ * `assess <expectation>` inside a task runtime gives one, and it is the
102
+ * Expectation — there is no Task positional to read. With `--all` there is
103
+ * no Expectation to name at all, so a lone positional is the Task again.
104
+ */
105
+ const taskPositional = flags.all || args.expectation ? args.task : undefined;
57
106
  const task = (0, task_resolver_1.resolveTaskIdentity)({
58
- positionalId: args.expectation ? args.task : undefined,
107
+ positionalId: taskPositional,
59
108
  flagTask: flags.task,
60
109
  });
61
110
  const evidenceRefs = (flags.evidence || []).map((raw) => {
@@ -75,22 +124,82 @@ class TasksExpectationsAssess extends base_command_1.BaseCommand {
75
124
  evidenceRefs,
76
125
  expectedSpecVersion: flags['spec-version'],
77
126
  };
78
- let result;
79
- try {
127
+ const reuseCallerKey = Boolean(flags['idempotency-key']) && !flags.all;
128
+ const submit = async (id) => {
80
129
  const data = {
81
130
  ...payload,
82
- expectationId,
83
- idempotencyKey: flags['idempotency-key'] ||
84
- (0, outbox_1.idempotencyKeyFor)('task-expectation-assessment', task.id, JSON.stringify({ expectationId, ...payload })),
131
+ expectationId: id,
132
+ // A per-expectation key under `--all`: one caller-supplied key reused
133
+ // across the set would make the second write a duplicate of the first,
134
+ // settling exactly one Expectation while reporting several.
135
+ idempotencyKey: reuseCallerKey
136
+ ? flags['idempotency-key']
137
+ : (0, outbox_1.idempotencyKeyFor)('task-expectation-assessment', task.id, JSON.stringify({ expectationId: id, ...payload })),
85
138
  };
86
139
  const sessionPath = await (0, session_task_endpoints_1.sessionScopedTaskPath)('assessment');
87
- result = sessionPath
140
+ return sessionPath
88
141
  ? await (0, api_fetch_1.apiFetch)(sessionPath, { method: 'POST', body: data })
89
- : await data_provider_1.dataService.assessTaskExpectation({
90
- taskId: task.id,
91
- expectationId,
92
- data,
93
- });
142
+ : await data_provider_1.dataService.assessTaskExpectation({ taskId: task.id, expectationId: id, data });
143
+ };
144
+ if (flags.all) {
145
+ let ids;
146
+ let rejected;
147
+ try {
148
+ ({ ids, rejected } = await this.awaitingIds(task.id, {
149
+ includeUnmet: flags['include-unmet'],
150
+ }));
151
+ }
152
+ catch (error) {
153
+ this.handleApiError(error);
154
+ return;
155
+ }
156
+ const skippedRejections = flags['include-unmet'] ? [] : rejected;
157
+ if (ids.length === 0) {
158
+ if (skippedRejections.length > 0) {
159
+ // "Nothing is awaiting assessment" was true of what this command
160
+ // WOULD touch and false about the Task, which is the distinction that
161
+ // made the board unclearable.
162
+ this.log(`Nothing is awaiting a first assessment, but ${skippedRejections.length} ` +
163
+ `Expectation(s) were judged unmet: ${skippedRejections.join(', ')}.`);
164
+ this.log(`Fix the work and re-assess ${skippedRejections.length === 1 ? 'it' : 'them'} by id, ` +
165
+ 'or re-run with --include-unmet to overwrite the rejection.');
166
+ return;
167
+ }
168
+ this.log('Nothing is awaiting assessment on this Task.');
169
+ return;
170
+ }
171
+ if (skippedRejections.length > 0) {
172
+ this.log(`Skipping ${skippedRejections.length} Expectation(s) judged unmet ` +
173
+ `(${skippedRejections.join(', ')}) — pass --include-unmet to re-assess them.`);
174
+ }
175
+ // Each write is reported on its own. A partial failure must leave the
176
+ // caller knowing exactly which Expectations were settled, because the
177
+ // remedy is to re-run for the rest — a single rolled-up "failed" would
178
+ // make that impossible to work out.
179
+ const settled = [];
180
+ const failed = [];
181
+ for (const id of ids) {
182
+ try {
183
+ await submit(id);
184
+ settled.push(id);
185
+ }
186
+ catch (error) {
187
+ failed.push({ id, message: error?.message || 'unknown error' });
188
+ }
189
+ }
190
+ if (flags.json) {
191
+ return this.log(JSON.stringify({ decision: flags.decision, settled, failed }, null, 2));
192
+ }
193
+ this.log(`Recorded ${settled.length} Expectation(s) as ${flags.decision}: ${settled.join(', ')}`);
194
+ for (const failure of failed)
195
+ this.log(` FAILED ${failure.id}: ${failure.message}`);
196
+ if (failed.length > 0)
197
+ this.exit(1);
198
+ return;
199
+ }
200
+ let result;
201
+ try {
202
+ result = await submit(expectationId);
94
203
  }
95
204
  catch (error) {
96
205
  this.handleApiError(error);
@@ -4,6 +4,8 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const data_provider_2 = require("@skrr-ai/data-provider");
6
6
  const base_command_1 = require("../../base-command");
7
+ const data_provider_3 = require("@skrr-ai/data-provider");
8
+ const task_closure_1 = require("../../lib/task-closure");
7
9
  /**
8
10
  * `skrr tasks expectations <task>` — what this task owes, and how far each got.
9
11
  *
@@ -12,18 +14,21 @@ const base_command_1 = require("../../base-command");
12
14
  * could disagree with the gate that refuses the task — and the reader would
13
15
  * have no way to tell which was lying.
14
16
  */
15
- const STATE_LABEL = {
16
- met: 'done',
17
- waived: 'dropped',
18
- blocked: 'stuck',
19
- // Its own word, because its next action is its own: somebody looks, rather
20
- // than somebody works. Reading it as 'not yet' sends people to redo finished
21
- // work, which is precisely the confusion the state was added to remove.
22
- unverified: 'needs a look',
23
- underway: 'on its way',
24
- owed: 'not yet',
25
- unassessed: 'needs assessment',
26
- };
17
+ /*
18
+ * The labels come from `@skrr-ai/data-provider`, not from here.
19
+ *
20
+ * This file said `dropped` where the user had typed `waived` and `done` where
21
+ * they had typed `met`; the web said `Waived` and `Met`; and an unjudged row
22
+ * read as `not yet` in one column and `needs assessment` in the trailer. Three
23
+ * spellings of one vocabulary is how a user stops trusting that the word they
24
+ * wrote is the word that was stored.
25
+ *
26
+ * A state derived from a DECISION now reads back as that decision's own word.
27
+ * `owed` and `unassessed` stay distinct — "nobody produced it" and "nobody
28
+ * judged it" are different next actions — and the legend below says so, which
29
+ * the near-synonymous English never could on its own.
30
+ */
31
+ const STATE_LABEL = data_provider_3.EXPECTATION_STATE_LABEL;
27
32
  /**
28
33
  * The evidence gap, on the rows where a reader can act on it.
29
34
  *
@@ -62,8 +67,26 @@ function evidenceGap(expectation) {
62
67
  return '';
63
68
  return ` (has ${expectation.evidenceLevel}, needs ${expectation.requiredEvidence})`;
64
69
  }
70
+ /**
71
+ * `done (agent)` rather than `done`.
72
+ *
73
+ * An agent may assess any Expectation, so the control that keeps this honest is
74
+ * not permission — it is that a reader can always see whose judgement closed a
75
+ * row and decide how much to trust it. Printed only on rows an assessment
76
+ * actually settled; a state derived from the deliverable ledger has no assessor
77
+ * and must not be given a fake one.
78
+ */
79
+ function assessorSuffix(expectation) {
80
+ if (!expectation.assessedByKind)
81
+ return '';
82
+ // `unmet` joins them: a rejection is a judgement, and whose it was matters at
83
+ // least as much as whose `met` it was.
84
+ if (!['met', 'waived', 'unmet'].includes(expectation.state))
85
+ return '';
86
+ return ` (${(0, task_closure_1.describeAssessor)(expectation.assessedByKind)})`;
87
+ }
65
88
  function line(expectation) {
66
- const label = STATE_LABEL[expectation.state] || expectation.state;
89
+ const label = (STATE_LABEL[expectation.state] || expectation.state) + assessorSuffix(expectation);
67
90
  const from = expectation.source === 'space' ? ' [space default]' : '';
68
91
  /*
69
92
  * `sentence` before `text`.
@@ -75,7 +98,7 @@ function line(expectation) {
75
98
  * thing is owed. The fallback is for a row that predates the resolved field.
76
99
  */
77
100
  const sentence = expectation.sentence || expectation.text;
78
- return ` ${expectation.id.padEnd(18)} ${label.padEnd(18)} ${sentence}${evidenceGap(expectation)}${from}`;
101
+ return ` ${expectation.id.padEnd(18)} ${label.padEnd(22)} ${sentence}${evidenceGap(expectation)}${from}`;
79
102
  }
80
103
  class TasksExpectations extends base_command_1.BaseCommand {
81
104
  static description = 'Show what must be true before the Task can close and the evidence-backed assessment state';
@@ -127,9 +150,13 @@ class TasksExpectations extends base_command_1.BaseCommand {
127
150
  // "2 of 2 met" for a Task where one expectation was dropped, which is the
128
151
  // one thing a reader checking this line needs to know.
129
152
  const waived = gating.filter((e) => e.state === 'waived').length;
130
- const met = gating.filter((e) => e.met).length - waived;
153
+ const met = gating.filter((e) => e.passed ?? e.state === 'met').length;
154
+ const rejected = gating.filter((e) => e.state === 'unmet').length;
131
155
  this.log('');
132
- this.log(`${met} of ${gating.length} met${waived > 0 ? ` · ${waived} waived` : ''} · overall: ${acceptance.state}`);
156
+ this.log(`${met} of ${gating.length} met` +
157
+ (waived > 0 ? ` · ${waived} waived` : '') +
158
+ (rejected > 0 ? ` · ${rejected} unmet` : '') +
159
+ ` · overall: ${acceptance.state}`);
133
160
  // Space defaults are copied into the Task at creation. `source=space`
134
161
  // remains useful provenance, but these are Task-owned Expectations now and
135
162
  // are assessed exactly like explicitly declared ones.
@@ -156,6 +183,24 @@ class TasksExpectations extends base_command_1.BaseCommand {
156
183
  if (settleable > 0) {
157
184
  this.log(`${settleable} awaiting assessment — use \`${this.config.bin} tasks expectations assess\`.`);
158
185
  }
186
+ /*
187
+ * A rejection is not an absence, and it used to read as one.
188
+ *
189
+ * `unmet` collapsed into `owed`/`unassessed`, so a reviewer's written "no"
190
+ * displayed as "needs assessment" — inviting someone to do the judging that
191
+ * had already been done, while the bulk settle skipped the row because it
192
+ * could see the assessment the display had hidden.
193
+ */
194
+ const rejectedRows = acceptance.expectations.filter((e) => e.state === 'unmet');
195
+ if (rejectedRows.length > 0) {
196
+ this.log(`${rejectedRows.length} judged unmet — fix the work and re-assess, or waive ` +
197
+ `${rejectedRows.length === 1 ? 'it' : 'them'}:`);
198
+ for (const row of rejectedRows) {
199
+ const who = row.assessedByKind ? ` by ${(0, task_closure_1.describeAssessor)(row.assessedByKind)}` : '';
200
+ const when = row.assessedAt ? ` on ${String(row.assessedAt).slice(0, 10)}` : '';
201
+ this.log(` ${row.id}${who}${when}${row.reason ? `: ${row.reason}` : ''}`);
202
+ }
203
+ }
159
204
  // Named separately from `unjudged`, and with a different command, because
160
205
  // the two look alike on the board and are not: one needs a verdict on prose,
161
206
  // the other needs somebody to look at a thing that already exists.
@@ -200,7 +245,40 @@ class TasksExpectations extends base_command_1.BaseCommand {
200
245
  const settled = gating.filter((e) => e.met).length;
201
246
  if (gating.length > settled) {
202
247
  this.log('');
203
- this.log('The current Result cannot be accepted while these Expectations remain unmet.');
248
+ /*
249
+ * Say what is OWED, not what is forbidden.
250
+ *
251
+ * This read: "The current Result cannot be accepted while these
252
+ * Expectations remain unmet." That gate stopped existing in `56a6ded703`
253
+ * — unmet Expectations are advisory, and `assertTaskMayClose` throws on
254
+ * exactly one code, which is not this one. The Task closes; the unmet
255
+ * items are stamped onto `resolution.closure`.
256
+ *
257
+ * So the sentence asserted an outcome this command never evaluated, and
258
+ * asserted it wrongly: an operator who believed it would go hunting for a
259
+ * way to force a close that needs no forcing. It is the same failure as
260
+ * the hard-coded "it is ready for review" that this batch removed,
261
+ * pointing the other way.
262
+ */
263
+ this.log(
264
+ // Tense-neutral on purpose: this command reads acceptance only, and
265
+ // fetching the Task as well — one extra round trip on every call — just
266
+ // to choose between "closing is allowed" and "was closed over these" is
267
+ // not worth it. This sentence is true before the close and after it.
268
+ `${gating.length - settled} Expectation(s) still owed. They do not block closing; ` +
269
+ 'whatever is outstanding when a Task closes is recorded on `resolution.closure`.');
270
+ }
271
+ /*
272
+ * A legend, because two of these states are near-synonyms in English and
273
+ * genuinely different in what they ask of the reader.
274
+ */
275
+ const shown = new Set(acceptance.expectations.map((e) => e.state));
276
+ const legend = ['owed', 'unassessed', 'unmet']
277
+ .filter((state) => shown.has(state))
278
+ .map((state) => `${data_provider_3.EXPECTATION_STATE_LABEL[state]} = ${data_provider_3.EXPECTATION_STATE_HINT[state]}`);
279
+ if (legend.length > 1) {
280
+ this.log('');
281
+ this.log(legend.join(' · '));
204
282
  }
205
283
  }
206
284
  }
@@ -73,8 +73,8 @@ class TasksFollowUp extends base_command_1.BaseCommand {
73
73
  description: 'Optional SLA fallback delay in seconds for event or poll_until follow-ups',
74
74
  }),
75
75
  visibility: core_1.Flags.string({
76
- description: 'Whether follow-up runs silently or sends a visible message',
77
- options: ['silent', 'notify'],
76
+ description: 'Always silent — the wake speaks only when the check finds something. Kept for compatibility; notify is not available',
77
+ options: ['silent'],
78
78
  }),
79
79
  priority: core_1.Flags.string({
80
80
  description: 'Follow-up task priority',
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
+ const label_ref_1 = require("../../../lib/label-ref");
6
7
  /**
7
8
  * Incremental label attach. `dataService.updateTask` only accepts a whole-list
8
9
  * `labelIds: string[]`, so we fetch the current task, append the new label
@@ -27,7 +28,7 @@ class TasksLabelsAttach extends base_command_1.BaseCommand {
27
28
  static flags = {
28
29
  json: core_1.Flags.boolean({ description: 'Output the updated task as JSON' }),
29
30
  'label-id': core_1.Flags.string({
30
- description: 'Label id to attach (repeatable). Create labels with `skrr tasks labels create`.',
31
+ description: 'Label to attach — id, or a name from `skrr labels list --applicable-to task`. An unknown name is refused, never created (repeatable).',
31
32
  multiple: true,
32
33
  required: true,
33
34
  }),
@@ -35,10 +36,26 @@ class TasksLabelsAttach extends base_command_1.BaseCommand {
35
36
  async run() {
36
37
  this.requireAuth();
37
38
  const { args, flags } = await this.parse(TasksLabelsAttach);
38
- const incoming = (flags['label-id'] ?? []).map((id) => id.trim()).filter((id) => id.length > 0);
39
- if (incoming.length === 0) {
39
+ const refs = (flags['label-id'] ?? []).map((id) => id.trim()).filter((id) => id.length > 0);
40
+ if (refs.length === 0) {
40
41
  this.error('At least one --label-id is required.', { exit: 1 });
41
42
  }
43
+ // A name is resolved against the DECLARED vocabulary; an unknown one is
44
+ // refused with the near misses named, never created. See lib/label-ref.
45
+ let incoming = [];
46
+ try {
47
+ incoming = await (0, label_ref_1.resolveLabelRefs)(refs, {
48
+ applicableTo: 'task',
49
+ ...(process.env.OVERSKY_WORKSPACE_ID
50
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
51
+ : {}),
52
+ });
53
+ }
54
+ catch (err) {
55
+ if (err instanceof label_ref_1.LabelRefError)
56
+ this.error(err.message, { exit: 1 });
57
+ this.handleApiError(err);
58
+ }
42
59
  let current;
43
60
  try {
44
61
  current = await data_provider_1.dataService.getTask(args.id, { enrich: false });
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../../base-command");
6
+ const label_ref_1 = require("../../../lib/label-ref");
6
7
  /**
7
8
  * Incremental label detach. Mirror of `labels attach` — fetch, filter, write
8
9
  * back the whole `labelIds` list. Matches label ids exactly (they are opaque
@@ -20,7 +21,7 @@ class TasksLabelsDetach extends base_command_1.BaseCommand {
20
21
  static flags = {
21
22
  json: core_1.Flags.boolean({ description: 'Output the updated task as JSON' }),
22
23
  'label-id': core_1.Flags.string({
23
- description: 'Label id to detach (repeatable)',
24
+ description: 'Label to detach — id, or a name from `skrr labels list --applicable-to task` (repeatable)',
24
25
  multiple: true,
25
26
  required: true,
26
27
  }),
@@ -28,10 +29,27 @@ class TasksLabelsDetach extends base_command_1.BaseCommand {
28
29
  async run() {
29
30
  this.requireAuth();
30
31
  const { args, flags } = await this.parse(TasksLabelsDetach);
31
- const targets = new Set((flags['label-id'] ?? []).map((id) => id.trim()).filter((id) => id.length > 0));
32
- if (targets.size === 0) {
32
+ const refs = (flags['label-id'] ?? []).map((id) => id.trim()).filter((id) => id.length > 0);
33
+ if (refs.length === 0) {
33
34
  this.error('At least one --label-id is required.', { exit: 1 });
34
35
  }
36
+ // A name is resolved against the DECLARED vocabulary; an unknown one is
37
+ // refused with the near misses named, never created. See lib/label-ref.
38
+ let resolvedTargets = [];
39
+ try {
40
+ resolvedTargets = await (0, label_ref_1.resolveLabelRefs)(refs, {
41
+ applicableTo: 'task',
42
+ ...(process.env.OVERSKY_WORKSPACE_ID
43
+ ? { workspaceId: process.env.OVERSKY_WORKSPACE_ID }
44
+ : {}),
45
+ });
46
+ }
47
+ catch (err) {
48
+ if (err instanceof label_ref_1.LabelRefError)
49
+ this.error(err.message, { exit: 1 });
50
+ this.handleApiError(err);
51
+ }
52
+ const targets = new Set(resolvedTargets);
35
53
  let current;
36
54
  try {
37
55
  current = await data_provider_1.dataService.getTask(args.id, { enrich: false });
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class TasksLifecycleAttach extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ pack: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ definition: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ version: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const task_lifecycle_output_1 = require("../../../lib/task-lifecycle-output");
7
+ class TasksLifecycleAttach extends base_command_1.BaseCommand {
8
+ static description = 'Attach a lifecycle protocol to a Task — a built-in pack or a Space definition';
9
+ static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
10
+ static flags = {
11
+ pack: core_1.Flags.string({ description: "Built-in pack id, e.g. 'finding' or 'doc_to_task'" }),
12
+ definition: core_1.Flags.string({ description: 'WorkflowDefinition id (kind task_lifecycle)' }),
13
+ version: core_1.Flags.string({ description: 'Pin a specific published version id' }),
14
+ json: core_1.Flags.boolean({ description: 'Output JSON' }),
15
+ };
16
+ async run() {
17
+ this.requireAuth();
18
+ const { args, flags } = await this.parse(TasksLifecycleAttach);
19
+ const taskId = await this.resolveTaskReference(args.id);
20
+ if (flags.pack && flags.definition) {
21
+ this.error('Pass either --pack or --definition, not both.', { exit: 2 });
22
+ }
23
+ if (!flags.pack && !flags.definition) {
24
+ this.error('Pass --pack <id> or --definition <id>. See: tasks lifecycle definitions', {
25
+ exit: 2,
26
+ });
27
+ }
28
+ let response;
29
+ try {
30
+ response = await data_provider_1.dataService.attachTaskLifecycle({
31
+ taskId,
32
+ ...(flags.pack ? { packId: flags.pack } : {}),
33
+ ...(flags.definition ? { definitionId: flags.definition } : {}),
34
+ ...(flags.version ? { versionId: flags.version } : {}),
35
+ });
36
+ }
37
+ catch (error) {
38
+ this.handleApiError(error);
39
+ }
40
+ if (flags.json)
41
+ return this.log(JSON.stringify(response, null, 2));
42
+ this.log(`Attached lifecycle${flags.pack ? ` pack '${flags.pack}'` : ` definition ${flags.definition}`}.`);
43
+ (0, task_lifecycle_output_1.renderTaskLifecycleSummary)(response, (line) => this.log(line));
44
+ this.log(`Start it: skrr tasks lifecycle start ${taskId}`);
45
+ }
46
+ }
47
+ exports.default = TasksLifecycleAttach;
@@ -0,0 +1,11 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class TasksLifecycleDefinitions extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ class TasksLifecycleDefinitions extends base_command_1.BaseCommand {
7
+ static description = 'List the lifecycle definitions and built-in packs a Task can attach';
8
+ static args = {
9
+ id: core_1.Args.string({
10
+ required: true,
11
+ ignoreStdin: true,
12
+ description: 'Task ID or identifier — definitions are listed for its Space',
13
+ }),
14
+ };
15
+ static flags = { json: core_1.Flags.boolean({ description: 'Output JSON' }) };
16
+ async run() {
17
+ this.requireAuth();
18
+ const { args, flags } = await this.parse(TasksLifecycleDefinitions);
19
+ const taskId = await this.resolveTaskReference(args.id);
20
+ let response;
21
+ try {
22
+ response = await data_provider_1.dataService.listTaskLifecycleDefinitions(taskId);
23
+ }
24
+ catch (error) {
25
+ this.handleApiError(error);
26
+ }
27
+ if (flags.json)
28
+ return this.log(JSON.stringify(response, null, 2));
29
+ if (response.packs.length) {
30
+ this.log('Built-in packs:');
31
+ for (const pack of response.packs) {
32
+ this.log(` ${pack.id} v${pack.packVersion} — ${pack.title}${pack.description ? ` — ${pack.description}` : ''}`);
33
+ if (pack.stageKeys?.length) {
34
+ this.log(` stages: ${pack.stageKeys.join(' → ')}`);
35
+ }
36
+ }
37
+ }
38
+ if (response.definitions.length) {
39
+ this.log('Space definitions:');
40
+ for (const definition of response.definitions) {
41
+ this.log(` ${definition.id} v${definition.version} — ${definition.title}${definition.packId ? ` (pack ${definition.packId} v${definition.packVersion ?? '?'})` : ''}`);
42
+ // `attach --version` and `migrate --version` take a VERSION id, and
43
+ // this was the only place they could come from — and it printed the
44
+ // definition id and a version NUMBER, neither of which those flags
45
+ // accept. `migrate` was unusable without reading the API.
46
+ if (definition.publishedVersionId) {
47
+ this.log(` published version: ${definition.publishedVersionId} (pass to --version)`);
48
+ }
49
+ if (definition.stageKeys?.length) {
50
+ this.log(` stages: ${definition.stageKeys.join(' → ')}`);
51
+ }
52
+ }
53
+ }
54
+ if (!response.packs.length && !response.definitions.length) {
55
+ this.log('No lifecycle definitions are available to this Task.');
56
+ }
57
+ }
58
+ }
59
+ exports.default = TasksLifecycleDefinitions;
@@ -0,0 +1,19 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class TasksLifecycleDetach extends BaseCommand {
3
+ static description: string;
4
+ /**
5
+ * oclif prints `description` in help and nothing else, so a one-liner that
6
+ * repeats the summary tells a reader nothing about an operation that is not
7
+ * obviously reversible. Say what it does to each thing it touches.
8
+ */
9
+ static examples: string[];
10
+ static args: {
11
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
12
+ };
13
+ static flags: {
14
+ reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ 'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
17
+ };
18
+ run(): Promise<void>;
19
+ }