@skrr-ai/cli 0.1.92 → 0.1.93

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 (267) hide show
  1. package/dist/base-command.d.ts +44 -0
  2. package/dist/base-command.js +96 -0
  3. package/dist/commands/agents/badge.d.ts +41 -0
  4. package/dist/commands/agents/badge.js +158 -0
  5. package/dist/commands/agents/create.d.ts +24 -0
  6. package/dist/commands/agents/create.js +212 -0
  7. package/dist/commands/agents/embed.d.ts +20 -0
  8. package/dist/commands/agents/embed.js +61 -0
  9. package/dist/commands/agents/share.d.ts +27 -0
  10. package/dist/commands/agents/share.js +100 -0
  11. package/dist/commands/agents/vanity.d.ts +21 -0
  12. package/dist/commands/agents/vanity.js +77 -0
  13. package/dist/commands/agents/visibility.d.ts +21 -1
  14. package/dist/commands/agents/visibility.js +112 -0
  15. package/dist/commands/commands.d.ts +1 -0
  16. package/dist/commands/commands.js +22 -9
  17. package/dist/commands/earnings/attributions.d.ts +17 -0
  18. package/dist/commands/earnings/attributions.js +82 -0
  19. package/dist/commands/earnings/index.js +2 -1
  20. package/dist/commands/generate-recovery-code.js +4 -3
  21. package/dist/commands/github/allow-tools.d.ts +1 -0
  22. package/dist/commands/github/app/install.d.ts +1 -0
  23. package/dist/commands/github/app/status.d.ts +1 -0
  24. package/dist/commands/github/connect.d.ts +1 -0
  25. package/dist/commands/github/connections.d.ts +1 -0
  26. package/dist/commands/github/disconnect.d.ts +1 -0
  27. package/dist/commands/github/finalize.d.ts +1 -0
  28. package/dist/commands/github/reconnect.d.ts +1 -0
  29. package/dist/commands/github/run.d.ts +1 -0
  30. package/dist/commands/github/tools.d.ts +1 -0
  31. package/dist/commands/integrations/connections/connect.d.ts +1 -0
  32. package/dist/commands/integrations/connections/disconnect.d.ts +1 -0
  33. package/dist/commands/integrations/connections/finalize.d.ts +1 -0
  34. package/dist/commands/integrations/connections/list.d.ts +1 -0
  35. package/dist/commands/integrations/connections/reconnect.d.ts +1 -0
  36. package/dist/commands/integrations/execute.d.ts +1 -0
  37. package/dist/commands/integrations/search.d.ts +1 -0
  38. package/dist/commands/integrations/toolkits.d.ts +1 -0
  39. package/dist/commands/integrations/tools/allow.d.ts +1 -0
  40. package/dist/commands/integrations/tools/list.d.ts +1 -0
  41. package/dist/commands/login.js +12 -0
  42. package/dist/commands/machines/dedicated/logs.d.ts +19 -0
  43. package/dist/commands/machines/dedicated/logs.js +103 -0
  44. package/dist/commands/machines/dedicated/power/set.js +1 -1
  45. package/dist/commands/open.d.ts +24 -0
  46. package/dist/commands/open.js +74 -0
  47. package/dist/commands/projects/archive.d.ts +1 -0
  48. package/dist/commands/projects/archive.js +23 -0
  49. package/dist/commands/projects/delete.d.ts +1 -0
  50. package/dist/commands/projects/delete.js +23 -0
  51. package/dist/commands/projects/list.d.ts +3 -0
  52. package/dist/commands/projects/list.js +12 -2
  53. package/dist/commands/spaces/actions/add.js +4 -3
  54. package/dist/commands/spaces/actions/available.js +3 -2
  55. package/dist/commands/spaces/actions/list.js +5 -4
  56. package/dist/commands/spaces/actions/replace.js +6 -5
  57. package/dist/commands/spaces/archive.js +3 -2
  58. package/dist/commands/spaces/auto-executor/preview.js +4 -3
  59. package/dist/commands/spaces/auto-executor/run.js +4 -3
  60. package/dist/commands/spaces/auto-executor/runs.js +3 -2
  61. package/dist/commands/spaces/auto-executor/update.js +4 -3
  62. package/dist/commands/spaces/bootstrap.js +3 -2
  63. package/dist/commands/spaces/briefs/delete.js +3 -2
  64. package/dist/commands/spaces/briefs/get.js +3 -2
  65. package/dist/commands/spaces/briefs/list.js +3 -2
  66. package/dist/commands/spaces/briefs/set.js +5 -4
  67. package/dist/commands/spaces/capacity.js +5 -4
  68. package/dist/commands/spaces/conversations.js +3 -2
  69. package/dist/commands/spaces/cycles/create.js +3 -2
  70. package/dist/commands/spaces/cycles/graph.js +2 -1
  71. package/dist/commands/spaces/cycles/list.js +3 -2
  72. package/dist/commands/spaces/cycles/settings.js +4 -3
  73. package/dist/commands/spaces/cycles/show.js +3 -2
  74. package/dist/commands/spaces/cycles/update.js +3 -2
  75. package/dist/commands/spaces/delete.js +4 -3
  76. package/dist/commands/spaces/expertise-suggestions.js +4 -3
  77. package/dist/commands/spaces/files/delete.js +3 -2
  78. package/dist/commands/spaces/files/folders/create.js +3 -2
  79. package/dist/commands/spaces/files/folders/delete.js +3 -2
  80. package/dist/commands/spaces/files/folders/list.js +3 -2
  81. package/dist/commands/spaces/files/folders/update.js +3 -2
  82. package/dist/commands/spaces/files/list.js +3 -2
  83. package/dist/commands/spaces/files/move.js +3 -2
  84. package/dist/commands/spaces/files/rename.js +3 -2
  85. package/dist/commands/spaces/files/upload.js +6 -5
  86. package/dist/commands/spaces/github-automations/set.js +3 -2
  87. package/dist/commands/spaces/github-automations/show.js +3 -2
  88. package/dist/commands/spaces/goals.js +2 -1
  89. package/dist/commands/spaces/heartbeats/create.js +4 -3
  90. package/dist/commands/spaces/heartbeats/delete.js +4 -3
  91. package/dist/commands/spaces/heartbeats/list.js +4 -3
  92. package/dist/commands/spaces/heartbeats/status.js +3 -2
  93. package/dist/commands/spaces/heartbeats/update.js +4 -3
  94. package/dist/commands/spaces/insights.js +5 -4
  95. package/dist/commands/spaces/labels/add.js +4 -3
  96. package/dist/commands/spaces/labels/list.js +2 -1
  97. package/dist/commands/spaces/labels/remove.js +4 -3
  98. package/dist/commands/spaces/list.d.ts +3 -0
  99. package/dist/commands/spaces/list.js +11 -2
  100. package/dist/commands/spaces/live/cards/create.js +3 -2
  101. package/dist/commands/spaces/live/cards/list.js +3 -2
  102. package/dist/commands/spaces/live/cards/reorder.js +7 -2
  103. package/dist/commands/spaces/live/scene.js +4 -3
  104. package/dist/commands/spaces/members/add.js +7 -6
  105. package/dist/commands/spaces/members/list.js +4 -3
  106. package/dist/commands/spaces/members/remove.js +7 -6
  107. package/dist/commands/spaces/move.js +3 -2
  108. package/dist/commands/spaces/pin.js +5 -4
  109. package/dist/commands/spaces/preferences/show.js +4 -3
  110. package/dist/commands/spaces/preferences/tabs.js +4 -3
  111. package/dist/commands/spaces/revisions.js +3 -2
  112. package/dist/commands/spaces/room/ensure.js +5 -4
  113. package/dist/commands/spaces/room/messages.js +3 -2
  114. package/dist/commands/spaces/room/show.js +5 -4
  115. package/dist/commands/spaces/skills/add.js +4 -3
  116. package/dist/commands/spaces/skills/list.js +3 -2
  117. package/dist/commands/spaces/skills/pin.js +4 -3
  118. package/dist/commands/spaces/skills/remove.js +4 -3
  119. package/dist/commands/spaces/snapshot.js +3 -2
  120. package/dist/commands/spaces/states/archive.js +3 -2
  121. package/dist/commands/spaces/states/create.js +3 -2
  122. package/dist/commands/spaces/states/list.js +3 -2
  123. package/dist/commands/spaces/states/reorder.js +2 -1
  124. package/dist/commands/spaces/states/update.js +3 -2
  125. package/dist/commands/spaces/summary.js +4 -3
  126. package/dist/commands/spaces/tasks.d.ts +3 -0
  127. package/dist/commands/spaces/tasks.js +14 -3
  128. package/dist/commands/spaces/triggers/delete.js +5 -4
  129. package/dist/commands/spaces/triggers/set.js +4 -3
  130. package/dist/commands/spaces/triggers/show.js +4 -3
  131. package/dist/commands/spaces/unarchive.js +3 -2
  132. package/dist/commands/spaces/update.js +5 -4
  133. package/dist/commands/spaces/views/create.js +3 -2
  134. package/dist/commands/spaces/views/list.js +3 -2
  135. package/dist/commands/spaces/views/reorder.js +6 -3
  136. package/dist/commands/spaces/views/subscribe.js +2 -1
  137. package/dist/commands/spaces/views/subscriptions.js +1 -0
  138. package/dist/commands/spaces/views/unsubscribe.js +2 -1
  139. package/dist/commands/spaces/widgets/add.js +4 -3
  140. package/dist/commands/spaces/widgets/list.js +3 -2
  141. package/dist/commands/spaces/widgets/remove.js +5 -4
  142. package/dist/commands/spaces/work-graph.js +2 -1
  143. package/dist/commands/store/install.d.ts +1 -1
  144. package/dist/commands/store/install.js +24 -8
  145. package/dist/commands/store/show.d.ts +25 -0
  146. package/dist/commands/store/show.js +203 -0
  147. package/dist/commands/store/stats.d.ts +33 -0
  148. package/dist/commands/store/stats.js +258 -0
  149. package/dist/commands/tasks/actions/attach.js +1 -1
  150. package/dist/commands/tasks/actions/detach.js +4 -3
  151. package/dist/commands/tasks/activity.js +3 -2
  152. package/dist/commands/tasks/ancestors.js +2 -1
  153. package/dist/commands/tasks/approvals/create.js +2 -1
  154. package/dist/commands/tasks/approvals/delete.js +3 -2
  155. package/dist/commands/tasks/approvals/list.js +5 -4
  156. package/dist/commands/tasks/approvals/resolve.js +2 -1
  157. package/dist/commands/tasks/archive.js +3 -2
  158. package/dist/commands/tasks/assign.js +4 -3
  159. package/dist/commands/tasks/attachments/delete.js +3 -2
  160. package/dist/commands/tasks/attachments/download.d.ts +1 -0
  161. package/dist/commands/tasks/attachments/download.js +20 -1
  162. package/dist/commands/tasks/attachments/list.js +2 -1
  163. package/dist/commands/tasks/attachments/set-role.js +2 -1
  164. package/dist/commands/tasks/attachments/upload.js +2 -1
  165. package/dist/commands/tasks/bulk-update.d.ts +1 -0
  166. package/dist/commands/tasks/bulk-update.js +106 -15
  167. package/dist/commands/tasks/cancel-cascade.d.ts +1 -0
  168. package/dist/commands/tasks/cancel-cascade.js +13 -3
  169. package/dist/commands/tasks/cascade-status.js +2 -1
  170. package/dist/commands/tasks/checkout.js +3 -2
  171. package/dist/commands/tasks/children.js +2 -1
  172. package/dist/commands/tasks/comments/add.js +7 -6
  173. package/dist/commands/tasks/comments/anchor.js +8 -7
  174. package/dist/commands/tasks/comments/delete.js +3 -2
  175. package/dist/commands/tasks/comments/list.js +2 -1
  176. package/dist/commands/tasks/comments/reopen.js +3 -2
  177. package/dist/commands/tasks/comments/resolve.js +3 -2
  178. package/dist/commands/tasks/create-tree.d.ts +63 -0
  179. package/dist/commands/tasks/create-tree.js +197 -4
  180. package/dist/commands/tasks/delete.js +5 -4
  181. package/dist/commands/tasks/descendants.js +2 -1
  182. package/dist/commands/tasks/dri-plan.js +3 -2
  183. package/dist/commands/tasks/dri-run.js +3 -2
  184. package/dist/commands/tasks/dri-status.js +2 -1
  185. package/dist/commands/tasks/duplicate-pipeline.js +2 -1
  186. package/dist/commands/tasks/execution-summary.js +2 -1
  187. package/dist/commands/tasks/execution-timeline.js +2 -1
  188. package/dist/commands/tasks/fork.js +1 -0
  189. package/dist/commands/tasks/forward.js +4 -3
  190. package/dist/commands/tasks/handover.js +1 -0
  191. package/dist/commands/tasks/interrupt.js +3 -2
  192. package/dist/commands/tasks/labels/attach.js +4 -3
  193. package/dist/commands/tasks/labels/detach.js +4 -3
  194. package/dist/commands/tasks/labels/suggest.js +5 -4
  195. package/dist/commands/tasks/list.d.ts +27 -1
  196. package/dist/commands/tasks/list.js +101 -3
  197. package/dist/commands/tasks/move.js +4 -3
  198. package/dist/commands/tasks/output.js +6 -5
  199. package/dist/commands/tasks/pause-schedule.js +3 -2
  200. package/dist/commands/tasks/promote.js +1 -0
  201. package/dist/commands/tasks/prompt-log.js +2 -1
  202. package/dist/commands/tasks/release.js +5 -4
  203. package/dist/commands/tasks/remind.js +2 -1
  204. package/dist/commands/tasks/replay.js +3 -2
  205. package/dist/commands/tasks/report.js +1 -0
  206. package/dist/commands/tasks/resume-schedule.js +3 -2
  207. package/dist/commands/tasks/retry-schedule.js +3 -2
  208. package/dist/commands/tasks/retry.js +10 -9
  209. package/dist/commands/tasks/revisions.js +2 -1
  210. package/dist/commands/tasks/runs.js +6 -5
  211. package/dist/commands/tasks/schedule.js +3 -2
  212. package/dist/commands/tasks/self-schedule.js +6 -5
  213. package/dist/commands/tasks/skills/pin.js +3 -2
  214. package/dist/commands/tasks/skills/unpin.js +3 -2
  215. package/dist/commands/tasks/snooze.js +6 -5
  216. package/dist/commands/tasks/start-all.js +5 -4
  217. package/dist/commands/tasks/subscribe.js +1 -0
  218. package/dist/commands/tasks/tags/add.js +4 -3
  219. package/dist/commands/tasks/tags/remove.js +4 -3
  220. package/dist/commands/tasks/timeline.js +3 -2
  221. package/dist/commands/tasks/today.d.ts +4 -1
  222. package/dist/commands/tasks/today.js +12 -2
  223. package/dist/commands/tasks/transcript.js +6 -5
  224. package/dist/commands/tasks/unschedule.js +3 -2
  225. package/dist/commands/tasks/unsnooze.js +3 -2
  226. package/dist/commands/tasks/unsubscribe.js +2 -1
  227. package/dist/commands/tasks/update.js +5 -4
  228. package/dist/commands/tasks/wait.js +5 -4
  229. package/dist/lib/agent-distribution.d.ts +37 -0
  230. package/dist/lib/agent-distribution.js +63 -0
  231. package/dist/lib/agent-ref.d.ts +69 -0
  232. package/dist/lib/agent-ref.js +168 -0
  233. package/dist/lib/api-fetch.d.ts +2 -0
  234. package/dist/lib/api-fetch.js +14 -3
  235. package/dist/lib/command-hygiene.d.ts +13 -0
  236. package/dist/lib/command-hygiene.js +62 -2
  237. package/dist/lib/dedicated-power.d.ts +5 -0
  238. package/dist/lib/dedicated-power.js +30 -2
  239. package/dist/lib/dry-run-plans.d.ts +50 -0
  240. package/dist/lib/dry-run-plans.js +85 -0
  241. package/dist/lib/json-output.d.ts +31 -0
  242. package/dist/lib/json-output.js +78 -0
  243. package/dist/lib/list-output.d.ts +75 -0
  244. package/dist/lib/list-output.js +266 -0
  245. package/dist/lib/machine-daemon-log.d.ts +36 -0
  246. package/dist/lib/machine-daemon-log.js +78 -0
  247. package/dist/lib/node-adapter.js +10 -1
  248. package/dist/lib/open-target.d.ts +12 -0
  249. package/dist/lib/open-target.js +108 -0
  250. package/dist/lib/rate-limit-retry.d.ts +45 -0
  251. package/dist/lib/rate-limit-retry.js +88 -0
  252. package/dist/lib/store-listing.d.ts +45 -0
  253. package/dist/lib/store-listing.js +186 -0
  254. package/dist/lib/task-batch.d.ts +67 -0
  255. package/dist/lib/task-batch.js +227 -0
  256. package/dist/lib/terminal-qr.d.ts +55 -0
  257. package/dist/lib/terminal-qr.js +119 -0
  258. package/dist/lib/web-url.d.ts +11 -0
  259. package/dist/lib/web-url.js +24 -0
  260. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +68 -0
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +47 -1
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +68 -0
  263. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +46 -0
  264. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  265. package/dist/node_modules/@skrr-ai/data-provider/index.js +6612 -6113
  266. package/oclif.manifest.json +46778 -38019
  267. package/package.json +2 -1
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.funnelLines = funnelLines;
4
+ exports.adoptionLines = adoptionLines;
5
+ exports.outcomesLines = outcomesLines;
6
+ const core_1 = require("@oclif/core");
7
+ const data_provider_1 = require("@skrr-ai/data-provider");
8
+ const base_command_1 = require("../../base-command");
9
+ const agent_ref_1 = require("../../lib/agent-ref");
10
+ const format_1 = require("../../lib/format");
11
+ const store_listing_1 = require("../../lib/store-listing");
12
+ const SECTIONS = ['funnel', 'adoption', 'outcomes'];
13
+ async function settle(read) {
14
+ try {
15
+ return { ok: true, value: await read() };
16
+ }
17
+ catch (error) {
18
+ return { ok: false, error };
19
+ }
20
+ }
21
+ function errorMessage(error) {
22
+ return error?.message || 'unavailable';
23
+ }
24
+ /**
25
+ * The publisher's readouts for one of their own Store agents: how buyers move
26
+ * through the install funnel, which releases their copies are on, and how each
27
+ * release turns out in use.
28
+ *
29
+ * Every figure is k-anonymous and publisher-only (the author, or an owner/admin
30
+ * of the organisation the listing is published as) — the same readouts the web
31
+ * shows, under the same terms (I2): the seller side's own copies are excluded, a readout covering fewer buyers than its floor returns NO figures,
32
+ * and small rows are withheld. This command prints a withheld readout as
33
+ * withheld, with the floor it missed. It never prints 0 for one, because zero
34
+ * is a claim the server did not make.
35
+ *
36
+ * There is no `--since`. Each window is fixed by the server — a caller-chosen
37
+ * length would let `days=N` minus `days=N-1` isolate a single buyer — so the
38
+ * window a readout covers is printed with it instead.
39
+ */
40
+ class StoreStats extends base_command_1.BaseCommand {
41
+ static description = 'Publisher analytics for your store agent: install funnel, release adoption and release outcomes (k-anonymous; small cohorts withheld)';
42
+ static examples = [
43
+ '<%= config.bin %> store stats agent_abc123',
44
+ '<%= config.bin %> store stats agent_abc123 --only funnel',
45
+ '<%= config.bin %> store stats agent_abc123 --json',
46
+ ];
47
+ static args = {
48
+ agent: core_1.Args.string({
49
+ description: 'Your published store agent: its id or a link to it',
50
+ required: true,
51
+ ignoreStdin: true,
52
+ }),
53
+ };
54
+ static flags = {
55
+ json: core_1.Flags.boolean({ description: 'Output the three readouts as JSON' }),
56
+ only: core_1.Flags.string({
57
+ description: 'Read one readout instead of all three',
58
+ options: [...SECTIONS],
59
+ }),
60
+ };
61
+ async run() {
62
+ this.requireAuth();
63
+ const { args, flags } = await this.parse(StoreStats);
64
+ let agentId;
65
+ try {
66
+ ({ agentId } = await (0, agent_ref_1.resolveAgentRef)(args.agent, { baseURL: this.cliConfig?.baseURL }));
67
+ }
68
+ catch (err) {
69
+ if (err instanceof agent_ref_1.AgentRefError) {
70
+ this.failWithCliError({ message: err.message, code: err.code, exit: 1, retryable: false });
71
+ }
72
+ // Resolving a share code reads the server; its failure is an API failure.
73
+ this.handleApiError(err);
74
+ }
75
+ const wanted = (section) => !flags.only || flags.only === section;
76
+ const skipped = { ok: false, error: null };
77
+ const [funnel, adoption, outcomes] = await Promise.all([
78
+ wanted('funnel')
79
+ ? settle(() => data_provider_1.dataService.getStoreAgentInstallFunnelSummary({ agentId }))
80
+ : skipped,
81
+ wanted('adoption')
82
+ ? settle(() => data_provider_1.dataService.getStoreAgentReleaseAdoptionSummary(agentId))
83
+ : skipped,
84
+ wanted('outcomes')
85
+ ? settle(() => data_provider_1.dataService.getStoreAgentReleaseOutcomes({ agentId }))
86
+ : skipped,
87
+ ]);
88
+ // Every requested readout failed: that is one answer (not yours, not
89
+ // found, signed out), and the shared error handler words it.
90
+ const attempted = [funnel, adoption, outcomes].filter((r) => r.ok || r.error !== null);
91
+ if (attempted.length > 0 && attempted.every((r) => !r.ok)) {
92
+ this.handleApiError(attempted[0].error, {
93
+ subject: `store agent ${agentId}`,
94
+ });
95
+ }
96
+ if (flags.json) {
97
+ const shape = (r) => r.ok ? r.value : r.error === null ? undefined : { error: errorMessage(r.error) };
98
+ this.log(JSON.stringify({
99
+ agentId,
100
+ funnel: shape(funnel),
101
+ adoption: shape(adoption),
102
+ outcomes: shape(outcomes),
103
+ }, null, 2));
104
+ return;
105
+ }
106
+ const blocks = [];
107
+ if (wanted('funnel')) {
108
+ blocks.push(funnel.ok
109
+ ? funnelLines(funnel.value.summary)
110
+ : ['Install funnel', ` unavailable (${errorMessage(funnel.error)})`]);
111
+ }
112
+ if (wanted('adoption')) {
113
+ blocks.push(adoption.ok
114
+ ? adoptionLines(adoption.value.summary)
115
+ : ['Release adoption', ` unavailable (${errorMessage(adoption.error)})`]);
116
+ }
117
+ if (wanted('outcomes')) {
118
+ blocks.push(outcomes.ok
119
+ ? outcomesLines(outcomes.value.outcomes)
120
+ : ['Release outcomes', ` unavailable (${errorMessage(outcomes.error)})`]);
121
+ }
122
+ blocks.forEach((lines, index) => {
123
+ if (index > 0)
124
+ this.log('');
125
+ for (const line of lines)
126
+ this.log(line);
127
+ });
128
+ }
129
+ }
130
+ exports.default = StoreStats;
131
+ function table(rows, columns) {
132
+ const out = [];
133
+ (0, format_1.renderTable)(rows, columns, (line) => out.push(` ${line}`));
134
+ return out;
135
+ }
136
+ function funnelLines(summary) {
137
+ const lines = [`Install funnel — ${(0, store_listing_1.funnelWindowLine)(summary)}`];
138
+ const testEvents = summary.excluded?.publisherTestEvents;
139
+ if (summary.suppressed) {
140
+ lines.push(` ${(0, store_listing_1.withheldLine)(summary.minimumCohort, 'buyers')}`);
141
+ }
142
+ else {
143
+ lines.push(...table(summary.funnel.map((step) => ({
144
+ step: step.label,
145
+ sessions: String(step.sessions),
146
+ events: String(step.events),
147
+ fromPlan: (0, store_listing_1.formatRate)(step.conversionFromPlan),
148
+ fromPrevious: (0, store_listing_1.formatRate)(step.conversionFromPrevious),
149
+ })), [
150
+ { key: 'step', header: 'STEP', maxWidth: 32 },
151
+ { key: 'sessions', header: 'SESSIONS' },
152
+ { key: 'events', header: 'EVENTS' },
153
+ { key: 'fromPlan', header: 'FROM PLAN' },
154
+ { key: 'fromPrevious', header: 'FROM PREV' },
155
+ ]));
156
+ const h = summary.health;
157
+ lines.push(...(0, store_listing_1.labelledLines)([
158
+ ['Buyer sessions', String(summary.sessionCount)],
159
+ [
160
+ 'Installs',
161
+ `${h.installCompletions} of ${h.installStarts} started (${(0, store_listing_1.formatRate)(h.installCompletionRate)})`,
162
+ ],
163
+ [
164
+ 'Activations',
165
+ `${h.activationCompletions} (${(0, store_listing_1.formatRate)(h.activationCompletionRate)} of installs)`,
166
+ ],
167
+ ['Failed sessions', String(h.failedSessions)],
168
+ ]));
169
+ if (summary.truncated) {
170
+ lines.push(' More events than one readout reads; figures cover the first part of the window.');
171
+ }
172
+ const cells = (0, store_listing_1.suppressedCellsLine)(summary.suppressedCells, summary.minimumCohort, 'buyers');
173
+ if (cells)
174
+ lines.push(` ${cells}`);
175
+ }
176
+ if (typeof testEvents === 'number' && testEvents > 0) {
177
+ lines.push(` Not counted: ${testEvents} event(s) from your own test installs.`);
178
+ }
179
+ return lines;
180
+ }
181
+ function adoptionLines(summary) {
182
+ const lines = [`Release adoption — ${(0, store_listing_1.adoptionWindowLine)(summary)}`];
183
+ if (summary.suppressed) {
184
+ lines.push(` ${(0, store_listing_1.withheldLine)(summary.minimumCohort, 'buyers')}`);
185
+ return lines;
186
+ }
187
+ if (summary.versions.length === 0) {
188
+ lines.push(' No version row reaches the floor.');
189
+ }
190
+ else {
191
+ lines.push(...table(summary.versions.map((v) => ({
192
+ version: v.releaseId
193
+ ? `${v.versionLabel ? `v${v.versionLabel}` : '(no label)'}${v.latest ? ' (latest)' : ''}`
194
+ : 'no recorded release',
195
+ release: v.releaseNumber === null ? '-' : String(v.releaseNumber),
196
+ installs: String(v.installs),
197
+ })), [
198
+ { key: 'version', header: 'VERSION' },
199
+ { key: 'release', header: 'RELEASE #' },
200
+ { key: 'installs', header: 'COPIES' },
201
+ ]));
202
+ }
203
+ if (summary.conflictFields.length > 0) {
204
+ lines.push(' Fields where buyers’ edits conflict with an update:');
205
+ lines.push(...table(summary.conflictFields.map((f) => ({ field: f.field, installs: String(f.installs) })), [
206
+ { key: 'field', header: 'FIELD' },
207
+ { key: 'installs', header: 'COPIES' },
208
+ ]));
209
+ }
210
+ const cells = (0, store_listing_1.suppressedCellsLine)(summary.suppressedCells, summary.minimumCohort, 'buyers');
211
+ if (cells)
212
+ lines.push(` ${cells}`);
213
+ return lines;
214
+ }
215
+ function outcomesLines(outcomes) {
216
+ const lines = [`Release outcomes — ${(0, store_listing_1.outcomesWindowLine)(outcomes)}`];
217
+ if (outcomes.suppressed) {
218
+ lines.push(` ${(0, store_listing_1.withheldLine)(outcomes.minimumCohort, 'buyer cohorts')}`);
219
+ return lines;
220
+ }
221
+ lines.push(` ${outcomes.cohortCount} buyer cohort(s).`);
222
+ if (outcomes.releases.length === 0) {
223
+ lines.push(' No release row reaches the floor.');
224
+ }
225
+ else {
226
+ lines.push(...table(outcomes.releases.map((r) => ({
227
+ version: r.versionLabel ? `v${r.versionLabel}` : r.releaseId,
228
+ runs: String(r.runs.total),
229
+ success: (0, store_listing_1.formatRate)(r.runs.successRate),
230
+ closes: String(r.taskCloses.closed),
231
+ clean: (0, store_listing_1.formatRate)(r.taskCloses.cleanRate),
232
+ reviews: `${r.buyerTestimony.reviewsAccepted} accepted / ${r.buyerTestimony.reviewsChangesRequested} changes`,
233
+ })), [
234
+ { key: 'version', header: 'VERSION' },
235
+ { key: 'runs', header: 'RUNS' },
236
+ { key: 'success', header: 'SUCCEEDED' },
237
+ { key: 'closes', header: 'TASKS CLOSED' },
238
+ { key: 'clean', header: 'CLEAN' },
239
+ { key: 'reviews', header: 'BUYER REVIEWS' },
240
+ ]));
241
+ }
242
+ // What each column rests on: runs and closes are recorded by the platform,
243
+ // reviews are what buyers said.
244
+ lines.push(' Runs and task closes are platform-recorded; reviews are buyer testimony.');
245
+ const cells = (0, store_listing_1.suppressedCellsLine)(outcomes.suppressedCells, outcomes.minimumCohort, 'buyer cohorts');
246
+ if (cells)
247
+ lines.push(` ${cells}`);
248
+ const ex = outcomes.excluded;
249
+ lines.push(...(0, store_listing_1.labelledLines)([
250
+ ['Left out: modified copies', (0, store_listing_1.exclusionValue)(ex.modifiedCopyRuns)],
251
+ ['Left out: self-assessed closes', (0, store_listing_1.exclusionValue)(ex.selfAssessedCloses)],
252
+ [
253
+ 'Left out: agent reviews/assessments',
254
+ `${(0, store_listing_1.exclusionValue)(ex.agentReviews)} / ${(0, store_listing_1.exclusionValue)(ex.agentAssessments)}`,
255
+ ],
256
+ ]));
257
+ return lines;
258
+ }
@@ -129,7 +129,7 @@ class TasksActionsAttach extends base_command_1.BaseCommand {
129
129
  this.exit(1);
130
130
  return;
131
131
  }
132
- const singleTaskId = taskId;
132
+ const singleTaskId = await this.resolveEntityRef('task', taskId);
133
133
  let current;
134
134
  try {
135
135
  current = await data_provider_1.dataService.getTask(singleTaskId, { enrich: false });
@@ -89,9 +89,10 @@ class TasksActionsDetach extends base_command_1.BaseCommand {
89
89
  this.exit(1);
90
90
  return;
91
91
  }
92
+ const taskRef = await this.resolveEntityRef('task', taskId);
92
93
  let current;
93
94
  try {
94
- current = await data_provider_1.dataService.getTask(taskId, { enrich: false });
95
+ current = await data_provider_1.dataService.getTask(taskRef, { enrich: false });
95
96
  }
96
97
  catch (err) {
97
98
  this.handleApiError(err);
@@ -109,7 +110,7 @@ class TasksActionsDetach extends base_command_1.BaseCommand {
109
110
  let updated;
110
111
  try {
111
112
  updated = await data_provider_1.dataService.updateTask({
112
- taskId: taskId,
113
+ taskId: taskRef,
113
114
  data: { attachedActionRefs: remaining },
114
115
  });
115
116
  }
@@ -120,7 +121,7 @@ class TasksActionsDetach extends base_command_1.BaseCommand {
120
121
  this.log(JSON.stringify(updated, null, 2));
121
122
  return;
122
123
  }
123
- this.log(`Detached ${existing.length - remaining.length} action(s) from task ${taskId}.`);
124
+ this.log(`Detached ${existing.length - remaining.length} action(s) from task ${taskRef}.`);
124
125
  this.log(remaining.length
125
126
  ? `Still attached: ${remaining.map(refKey).join(', ')}`
126
127
  : 'No actions attached.');
@@ -88,9 +88,10 @@ class TasksActivity extends base_command_1.BaseCommand {
88
88
  async run() {
89
89
  this.requireAuth();
90
90
  const { args, flags } = await this.parse(TasksActivity);
91
+ const taskRef = await this.resolveEntityRef('task', args.id);
91
92
  let response;
92
93
  try {
93
- response = await data_provider_1.dataService.listTaskActivityEvents(args.id, { limit: flags.limit });
94
+ response = await data_provider_1.dataService.listTaskActivityEvents(taskRef, { limit: flags.limit });
94
95
  }
95
96
  catch (err) {
96
97
  this.handleApiError(err);
@@ -105,7 +106,7 @@ class TasksActivity extends base_command_1.BaseCommand {
105
106
  // "No activity." was a claim about the TASK. It is only ever a claim about
106
107
  // this VIEW: a Task predating the canonical model has its history in the
107
108
  // legacy activity log, which this endpoint does not read.
108
- this.log(await (0, task_legacy_1.emptyCanonicalView)(args.id, 'Activity'));
109
+ this.log(await (0, task_legacy_1.emptyCanonicalView)(taskRef, 'Activity'));
109
110
  return;
110
111
  }
111
112
  (0, format_1.renderTable)(items.map(activityRow), [
@@ -20,9 +20,10 @@ class TasksAncestors extends base_command_1.BaseCommand {
20
20
  async run() {
21
21
  this.requireAuth();
22
22
  const { args, flags } = await this.parse(TasksAncestors);
23
+ const taskRef = await this.resolveEntityRef('task', args.id);
23
24
  let response;
24
25
  try {
25
- response = await data_provider_1.dataService.getTaskAncestors(args.id);
26
+ response = await data_provider_1.dataService.getTaskAncestors(taskRef);
26
27
  }
27
28
  catch (err) {
28
29
  this.handleApiError(err);
@@ -32,6 +32,7 @@ class TasksApprovalsCreate extends base_command_1.BaseCommand {
32
32
  async run() {
33
33
  this.requireAuth();
34
34
  const { args, flags } = await this.parse(TasksApprovalsCreate);
35
+ const taskRef = await this.resolveEntityRef('task', args.id);
35
36
  const data = { type: flags.type };
36
37
  if (flags['approver-agent'])
37
38
  data.approverAgentId = flags['approver-agent'];
@@ -40,7 +41,7 @@ class TasksApprovalsCreate extends base_command_1.BaseCommand {
40
41
  let result;
41
42
  try {
42
43
  result = await data_provider_1.dataService.createTaskApproval({
43
- taskId: args.id,
44
+ taskId: taskRef,
44
45
  data: data,
45
46
  });
46
47
  }
@@ -20,9 +20,10 @@ class TasksApprovalsDelete extends base_command_1.BaseCommand {
20
20
  async run() {
21
21
  this.requireAuth();
22
22
  const { args, flags } = await this.parse(TasksApprovalsDelete);
23
+ const taskRef = await this.resolveEntityRef('task', args.id);
23
24
  let confirmed;
24
25
  try {
25
- confirmed = await (0, prompt_1.confirmDestructive)(`Delete approval ${args.approvalId} from task ${args.id}? This cannot be undone.`, flags.yes);
26
+ confirmed = await (0, prompt_1.confirmDestructive)(`Delete approval ${args.approvalId} from task ${taskRef}? This cannot be undone.`, flags.yes);
26
27
  }
27
28
  catch (err) {
28
29
  const e = err;
@@ -33,7 +34,7 @@ class TasksApprovalsDelete extends base_command_1.BaseCommand {
33
34
  return;
34
35
  }
35
36
  try {
36
- await data_provider_1.dataService.deleteTaskApproval({ taskId: args.id, approvalId: args.approvalId });
37
+ await data_provider_1.dataService.deleteTaskApproval({ taskId: taskRef, approvalId: args.approvalId });
37
38
  }
38
39
  catch (err) {
39
40
  this.handleApiError(err);
@@ -165,9 +165,10 @@ class TasksApprovalsList extends base_command_1.BaseCommand {
165
165
  async run() {
166
166
  this.requireAuth();
167
167
  const { args, flags } = await this.parse(TasksApprovalsList);
168
+ const taskRef = await this.resolveEntityRef('task', args.id);
168
169
  let response;
169
170
  try {
170
- response = await data_provider_1.dataService.listTaskApprovals(args.id);
171
+ response = await data_provider_1.dataService.listTaskApprovals(taskRef);
171
172
  }
172
173
  catch (err) {
173
174
  this.handleApiError(err);
@@ -183,7 +184,7 @@ class TasksApprovalsList extends base_command_1.BaseCommand {
183
184
  let blockedRun = null;
184
185
  let runsRead = false;
185
186
  try {
186
- const runs = (await data_provider_1.dataService.getTaskRuns(args.id));
187
+ const runs = (await data_provider_1.dataService.getTaskRuns(taskRef));
187
188
  blockedRun = permissionBlockedRun(runs?.data ?? []);
188
189
  runsRead = true;
189
190
  }
@@ -202,13 +203,13 @@ class TasksApprovalsList extends base_command_1.BaseCommand {
202
203
  const out = runsRead
203
204
  ? {
204
205
  ...payload,
205
- blockedRun: blockedRun ? blockedRunSummary(blockedRun, this.config.bin, args.id) : null,
206
+ blockedRun: blockedRun ? blockedRunSummary(blockedRun, this.config.bin, taskRef) : null,
206
207
  }
207
208
  : payload;
208
209
  this.log(JSON.stringify(out, null, 2));
209
210
  return;
210
211
  }
211
- const blockLines = blockedRun ? permissionBlockLines(blockedRun, this.config.bin, args.id) : [];
212
+ const blockLines = blockedRun ? permissionBlockLines(blockedRun, this.config.bin, taskRef) : [];
212
213
  if (items.length === 0) {
213
214
  this.log('No approval requests.');
214
215
  if (blockLines.length > 0) {
@@ -26,13 +26,14 @@ class TasksApprovalsResolve extends base_command_1.BaseCommand {
26
26
  async run() {
27
27
  this.requireAuth();
28
28
  const { args, flags } = await this.parse(TasksApprovalsResolve);
29
+ const taskRef = await this.resolveEntityRef('task', args.id);
29
30
  const data = { status: flags.status };
30
31
  if (flags.reason)
31
32
  data.reason = flags.reason;
32
33
  let result;
33
34
  try {
34
35
  result = await data_provider_1.dataService.resolveTaskApproval({
35
- taskId: args.id,
36
+ taskId: taskRef,
36
37
  approvalId: args.approvalId,
37
38
  data: data,
38
39
  });
@@ -21,11 +21,12 @@ class TasksArchive extends base_command_1.BaseCommand {
21
21
  async run() {
22
22
  this.requireAuth();
23
23
  const { args, flags } = await this.parse(TasksArchive);
24
+ const taskId = await this.resolveEntityRef('task', args.id);
24
25
  let result;
25
26
  try {
26
27
  result = flags.unarchive
27
- ? await data_provider_1.dataService.unarchiveTask(args.id)
28
- : await data_provider_1.dataService.archiveTask(args.id);
28
+ ? await data_provider_1.dataService.unarchiveTask(taskId)
29
+ : await data_provider_1.dataService.archiveTask(taskId);
29
30
  }
30
31
  catch (err) {
31
32
  this.handleApiError(err);
@@ -109,6 +109,7 @@ class TasksAssign extends base_command_1.BaseCommand {
109
109
  details: { suggestion: failure.suggestion, context: failure.details },
110
110
  });
111
111
  }
112
+ const taskRef = await this.resolveEntityRef('task', taskIdentity.id);
112
113
  const personQueries = [...(args.person ? [args.person] : []), ...(flags.person ?? [])];
113
114
  const agentQueries = flags.agent ?? [];
114
115
  if (!flags.list && !flags.suggest && personQueries.length === 0 && agentQueries.length === 0) {
@@ -129,7 +130,7 @@ class TasksAssign extends base_command_1.BaseCommand {
129
130
  }
130
131
  let task;
131
132
  try {
132
- task = await data_provider_1.dataService.getTask(taskIdentity.id, { enrich: false });
133
+ task = await data_provider_1.dataService.getTask(taskRef, { enrich: false });
133
134
  }
134
135
  catch (err) {
135
136
  this.handleApiError(err);
@@ -185,7 +186,7 @@ class TasksAssign extends base_command_1.BaseCommand {
185
186
  let updated;
186
187
  try {
187
188
  updated = await data_provider_1.dataService.updateTask({
188
- taskId: taskIdentity.id,
189
+ taskId: taskRef,
189
190
  data: payload,
190
191
  });
191
192
  }
@@ -204,7 +205,7 @@ class TasksAssign extends base_command_1.BaseCommand {
204
205
  return;
205
206
  }
206
207
  const t = updated;
207
- const ref = t.identifier ?? t.id ?? taskIdentity.id;
208
+ const ref = t.identifier ?? t.id ?? taskRef;
208
209
  let verb = 'Assigned';
209
210
  if (flags.remove)
210
211
  verb = 'Unassigned';
@@ -20,9 +20,10 @@ class TasksAttachmentsDelete extends base_command_1.BaseCommand {
20
20
  async run() {
21
21
  this.requireAuth();
22
22
  const { args, flags } = await this.parse(TasksAttachmentsDelete);
23
+ const taskRef = await this.resolveEntityRef('task', args.id);
23
24
  let confirmed;
24
25
  try {
25
- confirmed = await (0, prompt_1.confirmDestructive)(`Delete attachment ${args.attachmentId} from task ${args.id}? This cannot be undone.`, flags.yes);
26
+ confirmed = await (0, prompt_1.confirmDestructive)(`Delete attachment ${args.attachmentId} from task ${taskRef}? This cannot be undone.`, flags.yes);
26
27
  }
27
28
  catch (err) {
28
29
  const e = err;
@@ -33,7 +34,7 @@ class TasksAttachmentsDelete extends base_command_1.BaseCommand {
33
34
  return;
34
35
  }
35
36
  try {
36
- await data_provider_1.dataService.deleteTaskAttachment({ taskId: args.id, attachmentId: args.attachmentId });
37
+ await data_provider_1.dataService.deleteTaskAttachment({ taskId: taskRef, attachmentId: args.attachmentId });
37
38
  }
38
39
  catch (err) {
39
40
  this.handleApiError(err);
@@ -8,6 +8,7 @@ export default class TasksAttachmentsDownload extends BaseCommand {
8
8
  };
9
9
  static flags: {
10
10
  out: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
12
  };
12
13
  run(): Promise<void>;
13
14
  }
@@ -52,13 +52,22 @@ class TasksAttachmentsDownload extends base_command_1.BaseCommand {
52
52
  description: 'Output path (use - for stdout)',
53
53
  required: true,
54
54
  }),
55
+ json: core_1.Flags.boolean({
56
+ description: 'Print {path, bytes} as JSON after writing a file (not valid with --out -)',
57
+ }),
55
58
  };
56
59
  async run() {
57
60
  this.requireAuth();
58
61
  const { args, flags } = await this.parse(TasksAttachmentsDownload);
62
+ const taskRef = await this.resolveEntityRef('task', args.id);
63
+ if (flags.json && flags.out === '-') {
64
+ this.error('--json cannot be combined with --out - (stdout carries the file bytes).', {
65
+ exit: 2,
66
+ });
67
+ }
59
68
  let buffer;
60
69
  try {
61
- buffer = await data_provider_1.dataService.downloadTaskAttachment(args.id, args.attachmentId);
70
+ buffer = await data_provider_1.dataService.downloadTaskAttachment(taskRef, args.attachmentId);
62
71
  }
63
72
  catch (err) {
64
73
  this.handleApiError(err);
@@ -71,6 +80,16 @@ class TasksAttachmentsDownload extends base_command_1.BaseCommand {
71
80
  }
72
81
  else {
73
82
  fs.writeFileSync(flags.out, bytes);
83
+ if (flags.json) {
84
+ this.log(JSON.stringify({
85
+ object: 'task_attachment_download',
86
+ taskId: taskRef,
87
+ attachmentId: args.attachmentId,
88
+ path: flags.out,
89
+ bytes: bytes.length,
90
+ }));
91
+ return;
92
+ }
74
93
  this.log(`Wrote ${bytes.length} bytes to ${flags.out}`);
75
94
  }
76
95
  }
@@ -51,9 +51,10 @@ class TasksAttachmentsList extends base_command_1.BaseCommand {
51
51
  async run() {
52
52
  this.requireAuth();
53
53
  const { args, flags } = await this.parse(TasksAttachmentsList);
54
+ const taskRef = await this.resolveEntityRef('task', args.id);
54
55
  let response;
55
56
  try {
56
- response = await data_provider_1.dataService.listTaskAttachments(args.id);
57
+ response = await data_provider_1.dataService.listTaskAttachments(taskRef);
57
58
  }
58
59
  catch (err) {
59
60
  this.handleApiError(err);
@@ -35,10 +35,11 @@ class TasksAttachmentsSetRole extends base_command_1.BaseCommand {
35
35
  async run() {
36
36
  this.requireAuth();
37
37
  const { args, flags } = await this.parse(TasksAttachmentsSetRole);
38
+ const taskRef = await this.resolveEntityRef('task', args.id);
38
39
  let attachment;
39
40
  try {
40
41
  attachment = await data_provider_1.dataService.setTaskAttachmentRole({
41
- taskId: args.id,
42
+ taskId: taskRef,
42
43
  attachmentId: args.attachmentId,
43
44
  role: flags.role,
44
45
  });
@@ -24,13 +24,14 @@ class TasksAttachmentsUpload extends base_command_1.BaseCommand {
24
24
  async run() {
25
25
  this.requireAuth();
26
26
  const { args, flags } = await this.parse(TasksAttachmentsUpload);
27
+ const taskRef = await this.resolveEntityRef('task', args.id);
27
28
  // The pipeline — buffered vs direct, session vs generic — lives in
28
29
  // task-asset-upload.ts so `--attach` on updates/result/complete/comments
29
30
  // makes the same routing decisions byte for byte (OSK-9863).
30
31
  let asset;
31
32
  try {
32
33
  asset = await (0, task_asset_upload_1.uploadTaskAssetFile)({
33
- taskId: args.id,
34
+ taskId: taskRef,
34
35
  filePath: flags.file,
35
36
  role: flags.role,
36
37
  });
@@ -5,6 +5,7 @@ export default class TasksBulkUpdate extends BaseCommand {
5
5
  static flags: {
6
6
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
7
  'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
8
+ 'dry-run': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
8
9
  'continue-on-error': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
10
  };
10
11
  run(): Promise<void>;