@skrr-ai/cli 0.1.108 → 0.1.110

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 (202) hide show
  1. package/README.md +10 -0
  2. package/dist/base-command.d.ts +74 -0
  3. package/dist/base-command.js +182 -24
  4. package/dist/commands/agents/triggers/create.js +1 -1
  5. package/dist/commands/agents/triggers/update.js +1 -1
  6. package/dist/commands/agents/update.d.ts +25 -0
  7. package/dist/commands/agents/update.js +98 -3
  8. package/dist/commands/commitments/accounting.js +7 -2
  9. package/dist/commands/commitments/cost.d.ts +11 -0
  10. package/dist/commands/commitments/cost.js +26 -3
  11. package/dist/commands/commitments/create.js +2 -1
  12. package/dist/commands/commitments/operating-review.d.ts +15 -0
  13. package/dist/commands/commitments/operating-review.js +103 -50
  14. package/dist/commands/commitments/update.js +12 -5
  15. package/dist/commands/daemon/install.js +17 -1
  16. package/dist/commands/daemon/login.js +14 -0
  17. package/dist/commands/doctor.js +9 -0
  18. package/dist/commands/goals/list.js +6 -1
  19. package/dist/commands/grants/rotate.js +4 -0
  20. package/dist/commands/harnesses/prune.d.ts +26 -0
  21. package/dist/commands/harnesses/prune.js +172 -0
  22. package/dist/commands/login.js +53 -14
  23. package/dist/commands/machines/list.js +28 -6
  24. package/dist/commands/projects/show.js +1 -1
  25. package/dist/commands/revoke-daemon.js +2 -1
  26. package/dist/commands/spaces/workflows/archive.d.ts +1 -0
  27. package/dist/commands/spaces/workflows/archive.js +1 -0
  28. package/dist/commands/spaces/workflows/artifact.d.ts +1 -0
  29. package/dist/commands/spaces/workflows/artifact.js +1 -0
  30. package/dist/commands/spaces/workflows/cancel-node.d.ts +1 -0
  31. package/dist/commands/spaces/workflows/cancel-node.js +1 -0
  32. package/dist/commands/spaces/workflows/cancel.d.ts +1 -0
  33. package/dist/commands/spaces/workflows/cancel.js +6 -2
  34. package/dist/commands/spaces/workflows/create.d.ts +1 -0
  35. package/dist/commands/spaces/workflows/create.js +7 -1
  36. package/dist/commands/spaces/workflows/events.d.ts +1 -0
  37. package/dist/commands/spaces/workflows/events.js +1 -0
  38. package/dist/commands/spaces/workflows/fixtures/create.d.ts +1 -0
  39. package/dist/commands/spaces/workflows/fixtures/create.js +1 -0
  40. package/dist/commands/spaces/workflows/fixtures/list.d.ts +1 -0
  41. package/dist/commands/spaces/workflows/fixtures/list.js +1 -0
  42. package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +1 -0
  43. package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +1 -0
  44. package/dist/commands/spaces/workflows/list.d.ts +1 -0
  45. package/dist/commands/spaces/workflows/list.js +1 -0
  46. package/dist/commands/spaces/workflows/node-types.d.ts +2 -0
  47. package/dist/commands/spaces/workflows/node-types.js +24 -6
  48. package/dist/commands/spaces/workflows/pause.d.ts +1 -0
  49. package/dist/commands/spaces/workflows/pause.js +1 -0
  50. package/dist/commands/spaces/workflows/plan/show.d.ts +1 -0
  51. package/dist/commands/spaces/workflows/plan/show.js +1 -0
  52. package/dist/commands/spaces/workflows/plan/update.d.ts +1 -0
  53. package/dist/commands/spaces/workflows/plan/update.js +1 -0
  54. package/dist/commands/spaces/workflows/proposals/apply.d.ts +1 -0
  55. package/dist/commands/spaces/workflows/proposals/apply.js +1 -0
  56. package/dist/commands/spaces/workflows/proposals/confirm.d.ts +1 -0
  57. package/dist/commands/spaces/workflows/proposals/confirm.js +1 -0
  58. package/dist/commands/spaces/workflows/proposals/create.d.ts +1 -0
  59. package/dist/commands/spaces/workflows/proposals/create.js +1 -0
  60. package/dist/commands/spaces/workflows/proposals/dismiss.d.ts +1 -0
  61. package/dist/commands/spaces/workflows/proposals/dismiss.js +1 -0
  62. package/dist/commands/spaces/workflows/proposals/list.d.ts +1 -0
  63. package/dist/commands/spaces/workflows/proposals/list.js +1 -0
  64. package/dist/commands/spaces/workflows/publish.d.ts +1 -0
  65. package/dist/commands/spaces/workflows/publish.js +9 -0
  66. package/dist/commands/spaces/workflows/reconcile.d.ts +1 -0
  67. package/dist/commands/spaces/workflows/reconcile.js +1 -0
  68. package/dist/commands/spaces/workflows/resume.d.ts +1 -0
  69. package/dist/commands/spaces/workflows/resume.js +1 -0
  70. package/dist/commands/spaces/workflows/retry.d.ts +1 -0
  71. package/dist/commands/spaces/workflows/retry.js +1 -0
  72. package/dist/commands/spaces/workflows/run.d.ts +1 -0
  73. package/dist/commands/spaces/workflows/run.js +14 -7
  74. package/dist/commands/spaces/workflows/runs.d.ts +1 -0
  75. package/dist/commands/spaces/workflows/runs.js +1 -0
  76. package/dist/commands/spaces/workflows/show.d.ts +25 -0
  77. package/dist/commands/spaces/workflows/show.js +42 -4
  78. package/dist/commands/spaces/workflows/signal.d.ts +12 -0
  79. package/dist/commands/spaces/workflows/signal.js +40 -2
  80. package/dist/commands/spaces/workflows/start.d.ts +1 -0
  81. package/dist/commands/spaces/workflows/start.js +4 -1
  82. package/dist/commands/spaces/workflows/task-execution/create.d.ts +1 -0
  83. package/dist/commands/spaces/workflows/task-execution/create.js +1 -0
  84. package/dist/commands/spaces/workflows/test.d.ts +1 -0
  85. package/dist/commands/spaces/workflows/test.js +1 -0
  86. package/dist/commands/spaces/workflows/triggers/create.d.ts +1 -0
  87. package/dist/commands/spaces/workflows/triggers/create.js +1 -0
  88. package/dist/commands/spaces/workflows/triggers/fire.d.ts +1 -0
  89. package/dist/commands/spaces/workflows/triggers/fire.js +1 -0
  90. package/dist/commands/spaces/workflows/triggers/list.d.ts +1 -0
  91. package/dist/commands/spaces/workflows/triggers/list.js +1 -0
  92. package/dist/commands/spaces/workflows/triggers/update.d.ts +1 -0
  93. package/dist/commands/spaces/workflows/triggers/update.js +1 -0
  94. package/dist/commands/spaces/workflows/update.d.ts +1 -0
  95. package/dist/commands/spaces/workflows/update.js +4 -0
  96. package/dist/commands/spaces/workflows/validate.d.ts +1 -0
  97. package/dist/commands/spaces/workflows/validate.js +27 -2
  98. package/dist/commands/tasks/activity.js +17 -3
  99. package/dist/commands/tasks/bulk-update.d.ts +1 -0
  100. package/dist/commands/tasks/bulk-update.js +7 -0
  101. package/dist/commands/tasks/complete.js +2 -1
  102. package/dist/commands/tasks/create-tree.d.ts +69 -0
  103. package/dist/commands/tasks/create-tree.js +413 -47
  104. package/dist/commands/tasks/list.d.ts +2 -0
  105. package/dist/commands/tasks/list.js +25 -3
  106. package/dist/commands/tasks/rearm-recurrence.d.ts +22 -0
  107. package/dist/commands/tasks/rearm-recurrence.js +87 -0
  108. package/dist/commands/tasks/show.d.ts +9 -0
  109. package/dist/commands/tasks/show.js +79 -33
  110. package/dist/commands/tasks/timeline.js +4 -0
  111. package/dist/commands/tasks/unschedule.js +5 -1
  112. package/dist/commands/tasks/update.d.ts +1 -0
  113. package/dist/commands/tasks/update.js +17 -2
  114. package/dist/commands/triggers/audit.js +12 -3
  115. package/dist/commands/triggers/create.js +9 -3
  116. package/dist/commands/triggers/fire-detail.d.ts +7 -0
  117. package/dist/commands/triggers/fire-detail.js +30 -12
  118. package/dist/commands/triggers/fire.js +13 -3
  119. package/dist/commands/triggers/parse-intent.d.ts +7 -0
  120. package/dist/commands/triggers/parse-intent.js +31 -9
  121. package/dist/commands/triggers/update.js +1 -1
  122. package/dist/commands/workspaces/grants.js +20 -3
  123. package/dist/commands/workspaces/members.d.ts +20 -0
  124. package/dist/commands/workspaces/members.js +64 -0
  125. package/dist/commands/workspaces/stewardship.js +14 -2
  126. package/dist/help.js +12 -0
  127. package/dist/hooks/command-not-found.js +27 -1
  128. package/dist/lib/command-miss.d.ts +52 -2
  129. package/dist/lib/command-miss.js +187 -18
  130. package/dist/lib/commitment-loop-status.d.ts +8 -0
  131. package/dist/lib/commitment-loop-status.js +45 -0
  132. package/dist/lib/commitment-product.js +5 -2
  133. package/dist/lib/commitments.d.ts +18 -3
  134. package/dist/lib/commitments.js +85 -45
  135. package/dist/lib/daemon-command-hint.d.ts +15 -0
  136. package/dist/lib/daemon-command-hint.js +21 -0
  137. package/dist/lib/daemon-machine-identity-copy.d.ts +14 -0
  138. package/dist/lib/daemon-machine-identity-copy.js +27 -0
  139. package/dist/lib/daemon-machine-identity.d.ts +27 -0
  140. package/dist/lib/daemon-machine-identity.js +61 -0
  141. package/dist/lib/daemon-setup.js +10 -1
  142. package/dist/lib/daemonBrokerRefusal.js +3 -2
  143. package/dist/lib/daemonHandoff.d.ts +19 -1
  144. package/dist/lib/daemonHandoff.js +61 -1
  145. package/dist/lib/deployed-build.d.ts +43 -0
  146. package/dist/lib/deployed-build.js +66 -0
  147. package/dist/lib/grants.d.ts +27 -1
  148. package/dist/lib/grants.js +39 -21
  149. package/dist/lib/harnesses.d.ts +71 -0
  150. package/dist/lib/harnesses.js +70 -0
  151. package/dist/lib/json-mode.d.ts +11 -0
  152. package/dist/lib/json-mode.js +19 -0
  153. package/dist/lib/json-output.d.ts +25 -0
  154. package/dist/lib/json-output.js +30 -0
  155. package/dist/lib/list-output.d.ts +10 -1
  156. package/dist/lib/list-output.js +22 -1
  157. package/dist/lib/local-daemon-readiness.d.ts +90 -0
  158. package/dist/lib/local-daemon-readiness.js +143 -0
  159. package/dist/lib/machines.d.ts +117 -0
  160. package/dist/lib/machines.js +139 -0
  161. package/dist/lib/managed-instruction-local.d.ts +2 -0
  162. package/dist/lib/managed-instruction-local.js +2 -0
  163. package/dist/lib/profile-machine-identity-guard.d.ts +18 -0
  164. package/dist/lib/profile-machine-identity-guard.js +39 -0
  165. package/dist/lib/request-field-flags.d.ts +20 -0
  166. package/dist/lib/request-field-flags.js +34 -0
  167. package/dist/lib/stewardship-output.d.ts +1 -1
  168. package/dist/lib/stewardship-output.js +26 -30
  169. package/dist/lib/task-batch.d.ts +61 -4
  170. package/dist/lib/task-batch.js +316 -80
  171. package/dist/lib/task-economics.d.ts +15 -0
  172. package/dist/lib/task-economics.js +39 -2
  173. package/dist/lib/task-recurrence-outcome.d.ts +6 -6
  174. package/dist/lib/task-recurrence-outcome.js +27 -3
  175. package/dist/lib/tasks.d.ts +39 -0
  176. package/dist/lib/tasks.js +132 -0
  177. package/dist/lib/triggers.d.ts +42 -1
  178. package/dist/lib/triggers.js +98 -2
  179. package/dist/lib/workflow-issues.d.ts +14 -0
  180. package/dist/lib/workflow-issues.js +32 -0
  181. package/dist/lib/workflow-run-view.d.ts +59 -0
  182. package/dist/lib/workflow-run-view.js +110 -0
  183. package/dist/lib/workspaces.d.ts +48 -4
  184. package/dist/lib/workspaces.js +55 -0
  185. package/dist/lib/write-target.d.ts +29 -0
  186. package/dist/lib/write-target.js +72 -0
  187. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
  188. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +5 -3
  189. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.d.ts +60 -0
  190. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +130 -6
  191. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/workspaceIsolationProbeWire.d.ts +51 -0
  192. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/workspaceIsolationProbeWire.js +50 -0
  193. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
  194. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -1
  195. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.d.ts +60 -0
  196. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +128 -6
  197. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/workspaceIsolationProbeWire.d.ts +51 -0
  198. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/workspaceIsolationProbeWire.js +46 -0
  199. package/dist/node_modules/@skrr-ai/auth-core/package.json +11 -1
  200. package/dist/node_modules/@skrr-ai/data-provider/index.js +7523 -7140
  201. package/oclif.manifest.json +473 -59
  202. package/package.json +28 -1
@@ -46,9 +46,17 @@ class TriggersFire extends base_command_1.BaseCommand {
46
46
  }
47
47
  const accepted = (0, triggers_1.fireWasAccepted)(result);
48
48
  if (flags.json) {
49
- this.log(JSON.stringify(result, null, 2));
50
- if (flags.strict && !accepted)
49
+ // `ok` and the exit status are one answer: a strict refusal prints `ok: false` and why,
50
+ // never the server's transport-level `ok: true` beside exit 1 (OSK-16494).
51
+ const refused = flags.strict && !accepted;
52
+ this.log(JSON.stringify(refused
53
+ ? { ...result, ok: false, strictRefusal: (0, triggers_1.describeStrictFireRefusal)(result) }
54
+ : result, null, 2));
55
+ if (refused) {
56
+ // stdout stays the one JSON document; the reason goes to stderr.
57
+ process.stderr.write(`${(0, triggers_1.describeStrictFireRefusal)(result)}\n`);
51
58
  this.exit(1);
59
+ }
52
60
  return;
53
61
  }
54
62
  this.log(`Fire requested: outcome=${String(result.outcome ?? '-')} reason=${String(result.reason ?? '-')}`);
@@ -57,8 +65,10 @@ class TriggersFire extends base_command_1.BaseCommand {
57
65
  const note = (0, triggers_1.describeScheduledFire)(result);
58
66
  if (note)
59
67
  this.log(note);
60
- if (flags.strict && !accepted)
68
+ if (flags.strict && !accepted) {
69
+ process.stderr.write(`${(0, triggers_1.describeStrictFireRefusal)(result)}\n`);
61
70
  this.exit(1);
71
+ }
62
72
  }
63
73
  }
64
74
  exports.default = TriggersFire;
@@ -1,4 +1,5 @@
1
1
  import { BaseCommand } from '../../base-command';
2
+ import { type TriggerParseIntentResponse } from '../../lib/triggers';
2
3
  export default class TriggersParseIntent extends BaseCommand {
3
4
  static description: string;
4
5
  static examples: string[];
@@ -14,3 +15,9 @@ export default class TriggersParseIntent extends BaseCommand {
14
15
  };
15
16
  run(): Promise<void>;
16
17
  }
18
+ /**
19
+ * The human rendering of a parse. Every unsupported condition is printed on its own line, never
20
+ * folded into the proposal (OSK-15402: "skip market holidays" was dropped while the summary claimed
21
+ * "every NYSE trading day"), and a clarifying question names the supported way to answer it.
22
+ */
23
+ export declare function parseIntentLines(result: TriggerParseIntentResponse, bin?: string): string[];
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseIntentLines = parseIntentLines;
3
4
  const core_1 = require("@oclif/core");
4
5
  const base_command_1 = require("../../base-command");
5
6
  const prompt_1 = require("../../lib/prompt");
@@ -21,11 +22,11 @@ class TriggersParseIntent extends base_command_1.BaseCommand {
21
22
  multiple: true,
22
23
  }),
23
24
  message: core_1.Flags.string({
24
- description: 'User message to parse (repeatable; messages are appended as user turns)',
25
+ description: 'User message to parse (repeatable; appended as user turns, after --history-json when both are given)',
25
26
  multiple: true,
26
27
  }),
27
28
  'history-json': core_1.Flags.string({
28
- description: 'Full parser history JSON array of {role:"user"|"assistant",content:string} objects',
29
+ description: 'Parser history: an inline JSON array of {role:"user"|"assistant",content:string} objects, or @file / a path to a file holding it. To answer a clarifying question, pass the `history` a previous --json run returned and add your reply with --message',
29
30
  }),
30
31
  timezone: core_1.Flags.string({ description: 'IANA timezone used for relative times' }),
31
32
  now: core_1.Flags.string({ description: 'Override current ISO timestamp used for relative times' }),
@@ -51,7 +52,10 @@ class TriggersParseIntent extends base_command_1.BaseCommand {
51
52
  if (history)
52
53
  body.history = history;
53
54
  if (flags.message && flags.message.length > 0) {
54
- body.history = flags.message.map((content) => ({ role: 'user', content }));
55
+ // Appended, never replacing: a reply to a clarifying question only means something after
56
+ // the question it answers (OSK-15402). It used to discard --history-json entirely.
57
+ const prior = Array.isArray(body.history) ? body.history : [];
58
+ body.history = [...prior, ...flags.message.map((content) => ({ role: 'user', content }))];
55
59
  }
56
60
  if (flags.timezone)
57
61
  body.timezone = flags.timezone;
@@ -83,12 +87,30 @@ class TriggersParseIntent extends base_command_1.BaseCommand {
83
87
  this.log(JSON.stringify(result, null, 2));
84
88
  return;
85
89
  }
86
- this.log(result.message ?? '(no parser message)');
87
- this.log(`Needs clarification: ${result.needsClarification ? 'yes' : 'no'}`);
88
- if (result.proposedTrigger) {
89
- this.log('');
90
- this.log(JSON.stringify(result.proposedTrigger, null, 2));
91
- }
90
+ for (const line of parseIntentLines(result, this.config.bin))
91
+ this.log(line);
92
92
  }
93
93
  }
94
94
  exports.default = TriggersParseIntent;
95
+ /**
96
+ * The human rendering of a parse. Every unsupported condition is printed on its own line, never
97
+ * folded into the proposal (OSK-15402: "skip market holidays" was dropped while the summary claimed
98
+ * "every NYSE trading day"), and a clarifying question names the supported way to answer it.
99
+ */
100
+ function parseIntentLines(result, bin = 'skrr') {
101
+ const lines = [result.message ?? '(no parser message)'];
102
+ lines.push(`Needs clarification: ${result.needsClarification ? 'yes' : 'no'}`);
103
+ const unsupported = Array.isArray(result.unsupported) ? result.unsupported : [];
104
+ if (unsupported.length > 0) {
105
+ lines.push('', 'Not applied by this trigger:');
106
+ for (const item of unsupported)
107
+ lines.push(` - "${item.text}" (${item.kind}): ${item.reason}`);
108
+ }
109
+ if (result.proposedTrigger) {
110
+ lines.push('', JSON.stringify(result.proposedTrigger, null, 2));
111
+ }
112
+ else if (result.needsClarification) {
113
+ lines.push('', 'To answer, run it again with your reply after the earlier messages, e.g.', ` ${bin} triggers parse-intent --scope <kind> --ref <key=value> --message "<first message>" --message "<your answer>"`, 'or pass the returned `history` (see --json) with --history-json and add --message "<your answer>".');
114
+ }
115
+ return lines;
116
+ }
@@ -56,7 +56,7 @@ class TriggersUpdate extends base_command_1.BaseCommand {
56
56
  description: 'ISO-8601 datetime after which a schedule stops firing',
57
57
  }),
58
58
  'stale-catchup-ms': core_1.Flags.integer({
59
- description: 'How late a missed occurrence may still run, in ms (a positive number). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
59
+ description: 'How late a missed occurrence may still run, in ms, from 1000 (1 second) to 31622400000 (366 days). After downtime, an occurrence more than this overdue is skipped rather than run late, and the schedule moves to its next future slot. Unset: 3600000 (1 hour).',
60
60
  }),
61
61
  at: core_1.Flags.string({ description: 'ISO-8601 datetime for once triggers' }),
62
62
  entity: core_1.Flags.string({
@@ -18,10 +18,11 @@ class WorkspacesGrants extends base_command_1.BaseCommand {
18
18
  const { args, flags } = await this.parse(WorkspacesGrants);
19
19
  try {
20
20
  const report = await (0, workspaces_1.listWorkspaceGrants)(args.workspaceId);
21
- if (flags.json)
21
+ if (flags.json) {
22
22
  this.log(JSON.stringify(report, null, 2));
23
- else
24
- (0, stewardship_output_1.printWorkspaceGrants)(report, (line) => this.log(line));
23
+ return;
24
+ }
25
+ (0, stewardship_output_1.printWorkspaceGrants)(report, (line) => this.log(line), await memberNames(args.workspaceId));
25
26
  }
26
27
  catch (error) {
27
28
  this.handleApiError(error);
@@ -29,3 +30,19 @@ class WorkspacesGrants extends base_command_1.BaseCommand {
29
30
  }
30
31
  }
31
32
  exports.default = WorkspacesGrants;
33
+ /**
34
+ * Owner ids to names, for the table's OWNER column (OSK-15357). Best effort: the
35
+ * report is already authoritative, and a members read that fails only leaves
36
+ * the column showing ids, as it did before.
37
+ */
38
+ async function memberNames(workspaceId) {
39
+ try {
40
+ const members = await (0, workspaces_1.listWorkspaceMembers)(workspaceId);
41
+ return new Map(members
42
+ .map((member) => [member.userId, member.name ?? member.email ?? ''])
43
+ .filter(([, name]) => name));
44
+ }
45
+ catch {
46
+ return new Map();
47
+ }
48
+ }
@@ -0,0 +1,20 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * `skrr workspaces members` — who is in a workspace, with the user id the
4
+ * other workspace commands take (OSK-15356).
5
+ *
6
+ * `workspaces stewardship` needs a member's user id, and nothing in this
7
+ * command family printed one but `skrr whoami` (your own). An owner handing
8
+ * over a departing member's work had no way to find theirs.
9
+ */
10
+ export default class WorkspacesMembers extends BaseCommand {
11
+ static description: string;
12
+ static examples: string[];
13
+ static args: {
14
+ workspaceId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
15
+ };
16
+ static flags: {
17
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
18
+ };
19
+ run(): Promise<void>;
20
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../base-command");
5
+ const format_1 = require("../../lib/format");
6
+ const workspaces_1 = require("../../lib/workspaces");
7
+ /**
8
+ * `skrr workspaces members` — who is in a workspace, with the user id the
9
+ * other workspace commands take (OSK-15356).
10
+ *
11
+ * `workspaces stewardship` needs a member's user id, and nothing in this
12
+ * command family printed one but `skrr whoami` (your own). An owner handing
13
+ * over a departing member's work had no way to find theirs.
14
+ */
15
+ class WorkspacesMembers extends base_command_1.BaseCommand {
16
+ static description = 'List the current members of a workspace with their user ids and roles';
17
+ static examples = [
18
+ '<%= config.bin %> workspaces members <workspace-id>',
19
+ '<%= config.bin %> workspaces members <workspace-id> --json',
20
+ ];
21
+ static args = {
22
+ workspaceId: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Workspace ID' }),
23
+ };
24
+ static flags = {
25
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
26
+ };
27
+ async run() {
28
+ this.requireAuth();
29
+ const { args, flags } = await this.parse(WorkspacesMembers);
30
+ let members;
31
+ try {
32
+ members = await (0, workspaces_1.listWorkspaceMembers)(args.workspaceId);
33
+ }
34
+ catch (error) {
35
+ this.handleApiError(error);
36
+ return;
37
+ }
38
+ if (flags.json) {
39
+ this.printJsonResult(members);
40
+ return;
41
+ }
42
+ if (members.length === 0) {
43
+ this.log('No current members.');
44
+ return;
45
+ }
46
+ (0, format_1.renderTable)(members.map((member) => ({
47
+ userId: member.userId,
48
+ name: member.name ?? '—',
49
+ email: member.email ?? '—',
50
+ role: member.role ?? '—',
51
+ joined: member.joinedAt ?? '—',
52
+ })), [
53
+ { key: 'userId', header: 'USER ID', verbatim: true },
54
+ { key: 'name', header: 'NAME', maxWidth: 28 },
55
+ { key: 'email', header: 'EMAIL', maxWidth: 36 },
56
+ { key: 'role', header: 'ROLE' },
57
+ { key: 'joined', header: 'JOINED' },
58
+ ], (line) => this.log(line));
59
+ this.log('');
60
+ this.log('Current members only: someone who has left is not listed. ' +
61
+ `\`skrr workspaces stewardship ${args.workspaceId} <user-id|email>\` reads one member's handover.`);
62
+ }
63
+ }
64
+ exports.default = WorkspacesMembers;
@@ -8,13 +8,15 @@ class WorkspacesStewardship extends base_command_1.BaseCommand {
8
8
  static description = 'Read a member’s workspace stewardship metadata (person owner/admin only)';
9
9
  static examples = [
10
10
  '<%= config.bin %> workspaces stewardship <workspace-id> <user-id> --json',
11
+ '<%= config.bin %> workspaces stewardship <workspace-id> person@example.com',
11
12
  ];
12
13
  static args = {
13
14
  workspaceId: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Workspace ID' }),
14
15
  userId: core_1.Args.string({
15
16
  required: true,
16
17
  ignoreStdin: true,
17
- description: 'Member user ID: 24 hexadecimal characters, not an email (`skrr whoami` prints your own)',
18
+ description: "Member user ID (24 hexadecimal characters) or a current member's email. " +
19
+ '`skrr workspaces members <workspace-id>` lists them; `skrr whoami` prints your own',
18
20
  }),
19
21
  };
20
22
  static flags = {
@@ -23,8 +25,18 @@ class WorkspacesStewardship extends base_command_1.BaseCommand {
23
25
  async run() {
24
26
  this.requireAuth();
25
27
  const { args, flags } = await this.parse(WorkspacesStewardship);
28
+ let userId;
26
29
  try {
27
- const report = await (0, workspaces_1.getWorkspaceStewardship)(args.workspaceId, args.userId);
30
+ userId = await (0, workspaces_1.resolveMemberUserId)(args.workspaceId, args.userId);
31
+ }
32
+ catch (error) {
33
+ if (error instanceof workspaces_1.MemberReferenceError)
34
+ this.error(error.message, { exit: 1 });
35
+ this.handleApiError(error);
36
+ return;
37
+ }
38
+ try {
39
+ const report = await (0, workspaces_1.getWorkspaceStewardship)(args.workspaceId, userId);
28
40
  if (flags.json)
29
41
  this.log(JSON.stringify(report, null, 2));
30
42
  else
package/dist/help.js CHANGED
@@ -61,6 +61,18 @@ class SkrrHelp extends core_1.Help {
61
61
  // so it must fall through — only an id that is neither a command nor a
62
62
  // topic is a miss.
63
63
  if (id && !this.config.findCommand(id) && !this.config.findTopic(id)) {
64
+ // `skrr tasks get --help` is asked about the command `skrr tasks get` runs
65
+ // as: the same synonym the hook resolves when it is run (OSK-16434).
66
+ const flagStart = argv.findIndex((token) => token.startsWith('-'));
67
+ const words = flagStart === -1 ? argv : argv.slice(0, flagStart);
68
+ const synonym = (0, command_miss_1.resolveVerbSynonym)(lookup, words);
69
+ if (synonym) {
70
+ return super.showHelp([
71
+ ...synonym.id.split(':'),
72
+ ...synonym.rest,
73
+ ...(flagStart === -1 ? [] : argv.slice(flagStart)),
74
+ ]);
75
+ }
64
76
  throw new Error((0, command_miss_1.describeCommandMiss)(lookup, id));
65
77
  }
66
78
  return super.showHelp(argv);
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
3
4
  const command_manifest_1 = require("../lib/command-manifest");
4
5
  const usage_discovery_1 = require("../lib/usage-discovery");
5
6
  const command_miss_1 = require("../lib/command-miss");
7
+ const json_mode_1 = require("../lib/json-mode");
6
8
  /**
7
9
  * Turn "command not found" back into the truth when the command DOES exist.
8
10
  *
@@ -65,6 +67,30 @@ const hook = async function (opts) {
65
67
  throw err;
66
68
  }
67
69
  }
70
+ const lookup = (0, command_miss_1.lookupFromConfig)(this.config);
71
+ const rawArgv = process.argv.slice(2);
72
+ const words = (0, command_miss_1.typedCommandWords)(id, rawArgv);
73
+ // A read verb spelled the other way (`tasks get`, `machines ls`) means the
74
+ // command that exists. Run it rather than refuse: refusing sent a reader to a
75
+ // suggestion list that did not contain the command they meant (OSK-16434).
76
+ // Only `list`/`ls` and `show`/`get`, only when the typed spelling is not a
77
+ // command of that topic, and only when the other one is.
78
+ const synonym = (0, command_miss_1.resolveVerbSynonym)(lookup, words);
79
+ if (synonym) {
80
+ // Said to a person, never to a pipe: a script gets its output undisturbed.
81
+ if (process.stderr.isTTY && !(0, json_mode_1.wantsJsonFromArgv)(rawArgv)) {
82
+ process.stderr.write(`\`${synonym.typed}\` is \`${synonym.resolved}\`.\n`);
83
+ }
84
+ return this.config.runCommand(synonym.id, [...synonym.rest, ...(opts.argv ?? [])]);
85
+ }
86
+ // `--json` asked for a document. A miss is a refusal like any other, and every
87
+ // other refusal prints `{ok:false, error}`; this one printed prose, so the
88
+ // pipe into `jq` failed on the prose and hid the refusal (OSK-16434). Exit
89
+ // status 1, as before.
90
+ if ((0, json_mode_1.wantsJsonFromArgv)([...rawArgv, ...(opts.argv ?? [])])) {
91
+ process.stdout.write(`${JSON.stringify((0, command_miss_1.commandMissEnvelope)(lookup, id, words), null, 2)}\n`);
92
+ core_1.Errors.exit(1);
93
+ }
68
94
  // The message itself lives in `lib/command-miss`, shared with the help
69
95
  // class — `skrr daemon reload` reaches this hook and `skrr daemon reload
70
96
  // --help` does not, so the two surfaces have to read from one description or
@@ -76,7 +102,7 @@ const hook = async function (opts) {
76
102
  // — a typo would silently look like success, which is far worse than the
77
103
  // message this hook was written to improve. (I shipped exactly that for one
78
104
  // build; `skrr shortcuts lst` said nothing and exited 0.)
79
- throw new Error((0, command_miss_1.describeCommandMiss)((0, command_miss_1.lookupFromConfig)(this.config), id));
105
+ throw new Error((0, command_miss_1.describeCommandMiss)(lookup, id));
80
106
  };
81
107
  exports.default = hook;
82
108
  class VirtualUsageFlagError extends Error {
@@ -57,7 +57,20 @@ export declare function nearestCommands(id: string, all: string[], limit?: numbe
57
57
  */
58
58
  export declare function helpSubjectId(tokens: readonly string[], config: CommandLookup): string;
59
59
  /**
60
- * The message for a colon-joined id that did not resolve.
60
+ * A command miss, in parts: what is wrong, what to do, and the commands that
61
+ * would do it. The text a person reads is `message` and `fix` on separate lines;
62
+ * a script reads `suggestions` without parsing either (OSK-16434).
63
+ */
64
+ export type CommandMiss = {
65
+ message: string;
66
+ fix?: string;
67
+ /** Full commands, `skrr tasks show` — never prose. */
68
+ suggestions: string[];
69
+ };
70
+ /** The text form: exactly what a miss has always printed. */
71
+ export declare function describeCommandMiss(config: CommandLookup, id: string): string;
72
+ /**
73
+ * The miss for a colon-joined id that did not resolve.
61
74
  *
62
75
  * Two shapes, in order:
63
76
  *
@@ -68,7 +81,7 @@ export declare function helpSubjectId(tokens: readonly string[], config: Command
68
81
  * suggest the nearest siblings under the same topic before falling back to
69
82
  * the whole command list.
70
83
  */
71
- export declare function describeCommandMiss(config: CommandLookup, id: string): string;
84
+ export declare function analyzeCommandMiss(config: CommandLookup, id: string): CommandMiss;
72
85
  /** Adapt an oclif `Config` to the lookup shape above. */
73
86
  export declare function lookupFromConfig(config: {
74
87
  bin: string;
@@ -80,3 +93,40 @@ export declare function lookupFromConfig(config: {
80
93
  name?: string;
81
94
  }>;
82
95
  }): CommandLookup;
96
+ export type VerbSynonym = {
97
+ /** The command that really exists, colon-joined: `tasks:show`. */
98
+ id: string;
99
+ /** What the reader typed after the verb: the arguments of the real command. */
100
+ rest: string[];
101
+ /** The two spellings, spoken: `skrr tasks get` and `skrr tasks show`. */
102
+ typed: string;
103
+ resolved: string;
104
+ };
105
+ /**
106
+ * The real command a mis-spelled READ verb means, when a synonym of it exists
107
+ * under the same topic path.
108
+ *
109
+ * `words` are the leading, non-flag tokens as the reader typed them. The scan
110
+ * walks down the real topic path; at the first word that is not part of it, that
111
+ * word is the verb, and only a synonym that is itself a command qualifies. A
112
+ * word that is a real command, or a prefix of one, is never reinterpreted.
113
+ */
114
+ export declare function resolveVerbSynonym(config: CommandLookup, words: readonly string[]): VerbSynonym | null;
115
+ /**
116
+ * The words a person typed for the command, recovered from the process argv.
117
+ *
118
+ * oclif joins the words it takes for a command with `:`, so a positional that
119
+ * itself contains a colon cannot be told apart from two words in the id. The
120
+ * raw argv can: its leading tokens, joined, are the id.
121
+ */
122
+ export declare function typedCommandWords(id: string, rawArgv: readonly string[]): string[];
123
+ /**
124
+ * What `--json` prints for a miss: the same `{ok:false, error}` every other
125
+ * refusal prints, so a script that parses refusals parses this one — instead of
126
+ * `jq` reading prose and failing with "Invalid numeric literal", which is how
127
+ * the report found it.
128
+ */
129
+ export declare function commandMissEnvelope(config: CommandLookup, id: string, words: readonly string[]): {
130
+ ok: false;
131
+ error: Record<string, unknown>;
132
+ };