@skrr-ai/cli 0.1.9 → 0.1.11

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 (109) hide show
  1. package/dist/base-command.d.ts +1 -13
  2. package/dist/base-command.js +78 -1
  3. package/dist/commands/browser/skill/show.js +7 -1
  4. package/dist/commands/code/index.d.ts +1 -0
  5. package/dist/commands/code/index.js +9 -1
  6. package/dist/commands/commitments/analytics/index.js +2 -0
  7. package/dist/commands/daemon/byok.d.ts +1 -0
  8. package/dist/commands/daemon/byok.js +2 -1
  9. package/dist/commands/daemon/install.d.ts +1 -0
  10. package/dist/commands/daemon/install.js +2 -1
  11. package/dist/commands/daemon/login.d.ts +31 -0
  12. package/dist/commands/daemon/login.js +56 -0
  13. package/dist/commands/daemon/restart.d.ts +9 -0
  14. package/dist/commands/daemon/restart.js +36 -0
  15. package/dist/commands/daemon/start.d.ts +1 -0
  16. package/dist/commands/daemon/start.js +2 -1
  17. package/dist/commands/daemon/status.d.ts +1 -0
  18. package/dist/commands/daemon/status.js +2 -1
  19. package/dist/commands/daemon/stop.d.ts +1 -0
  20. package/dist/commands/daemon/stop.js +2 -1
  21. package/dist/commands/daemon/uninstall.d.ts +1 -0
  22. package/dist/commands/daemon/uninstall.js +2 -1
  23. package/dist/commands/daemon/unlock.d.ts +9 -0
  24. package/dist/commands/daemon/unlock.js +33 -0
  25. package/dist/commands/goals/key-results/create.js +32 -1
  26. package/dist/commands/goals/key-results/update.d.ts +11 -0
  27. package/dist/commands/goals/key-results/update.js +80 -2
  28. package/dist/commands/goals/plan-now.d.ts +54 -2
  29. package/dist/commands/goals/plan-now.js +175 -18
  30. package/dist/commands/goals/planner-config.d.ts +60 -9
  31. package/dist/commands/goals/planner-config.js +82 -34
  32. package/dist/commands/goals/revisions.js +17 -0
  33. package/dist/commands/goals/show.d.ts +17 -0
  34. package/dist/commands/goals/show.js +90 -3
  35. package/dist/commands/login.js +36 -3
  36. package/dist/commands/spaces/create.js +2 -1
  37. package/dist/commands/spaces/index.js +9 -1
  38. package/dist/commands/spaces/list.d.ts +18 -0
  39. package/dist/commands/spaces/list.js +57 -7
  40. package/dist/commands/spaces/show.js +4 -1
  41. package/dist/commands/spaces/summary.d.ts +4 -0
  42. package/dist/commands/spaces/summary.js +77 -1
  43. package/dist/commands/spaces/update.d.ts +4 -0
  44. package/dist/commands/spaces/update.js +38 -1
  45. package/dist/commands/tasks/actionability.js +40 -1
  46. package/dist/commands/tasks/activity.d.ts +29 -0
  47. package/dist/commands/tasks/activity.js +47 -0
  48. package/dist/commands/tasks/complete.d.ts +47 -0
  49. package/dist/commands/tasks/complete.js +159 -12
  50. package/dist/commands/tasks/create.d.ts +26 -0
  51. package/dist/commands/tasks/create.js +60 -1
  52. package/dist/commands/tasks/events/append.d.ts +2 -0
  53. package/dist/commands/tasks/events/append.js +41 -10
  54. package/dist/commands/tasks/events/list.js +60 -9
  55. package/dist/commands/tasks/output.js +22 -2
  56. package/dist/commands/tasks/ready.d.ts +38 -0
  57. package/dist/commands/tasks/ready.js +37 -0
  58. package/dist/commands/tasks/runs.d.ts +22 -0
  59. package/dist/commands/tasks/runs.js +110 -2
  60. package/dist/commands/tasks/show.d.ts +28 -0
  61. package/dist/commands/tasks/show.js +61 -0
  62. package/dist/commands/tasks/timeline.d.ts +7 -0
  63. package/dist/commands/tasks/timeline.js +34 -3
  64. package/dist/commands/tasks/update.d.ts +20 -0
  65. package/dist/commands/tasks/update.js +38 -1
  66. package/dist/commands/whoami.d.ts +40 -0
  67. package/dist/commands/whoami.js +61 -10
  68. package/dist/commands/wiki/ls.d.ts +23 -0
  69. package/dist/commands/wiki/ls.js +63 -10
  70. package/dist/commands/wiki/mv.d.ts +70 -0
  71. package/dist/commands/wiki/mv.js +198 -4
  72. package/dist/commands/wiki/rm.js +12 -1
  73. package/dist/commands/wiki/write.js +35 -3
  74. package/dist/help.d.ts +27 -0
  75. package/dist/help.js +48 -0
  76. package/dist/hooks/command-not-found.d.ts +31 -0
  77. package/dist/hooks/command-not-found.js +12 -80
  78. package/dist/lib/command-miss.d.ts +60 -0
  79. package/dist/lib/command-miss.js +128 -0
  80. package/dist/lib/commitment-analytics.d.ts +10 -0
  81. package/dist/lib/commitment-analytics.js +10 -0
  82. package/dist/lib/config.d.ts +40 -0
  83. package/dist/lib/config.js +72 -9
  84. package/dist/lib/daemonBroker.d.ts +7 -1
  85. package/dist/lib/daemonBroker.js +71 -0
  86. package/dist/lib/daemonHandoff.d.ts +38 -0
  87. package/dist/lib/daemonHandoff.js +297 -0
  88. package/dist/lib/exec-oversky.d.ts +30 -0
  89. package/dist/lib/exec-oversky.js +41 -0
  90. package/dist/lib/format.d.ts +7 -0
  91. package/dist/lib/format.js +27 -5
  92. package/dist/lib/login.js +22 -2
  93. package/dist/lib/sky-code.js +9 -4
  94. package/dist/lib/task-transcript.d.ts +9 -0
  95. package/dist/lib/task-transcript.js +13 -2
  96. package/dist/lib/tasks.d.ts +34 -0
  97. package/dist/lib/tasks.js +70 -1
  98. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.d.ts +50 -0
  99. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/configRoot.js +67 -0
  100. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
  101. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +7 -1
  102. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.d.ts +50 -0
  103. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/configRoot.js +59 -0
  104. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
  105. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +3 -0
  106. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  107. package/dist/node_modules/@skrr-ai/data-provider/index.js +15 -4
  108. package/oclif.manifest.json +15713 -15480
  109. package/package.json +5 -3
@@ -367,19 +367,7 @@ export declare function withSubject(subject: string | undefined, message: string
367
367
  * Exported for tests.
368
368
  */
369
369
  export declare function describeHarnessUnavailable(body: Record<string, unknown> | null, bin?: string): string;
370
- /**
371
- * Enrich the server's `ASSIGNEE_NOT_IN_SPACE` rejection with the same
372
- * copy-pasteable remedy the by-name resolution failure already gives (OSK-4864).
373
- *
374
- * When a caller names an assignee that is not a member of the space, the CLI's
375
- * own name-resolution path (`ASSIGNEE_NOT_FOUND`) says "add one with
376
- * `skrr spaces members add`". The server's id-based rejection reaches
377
- * `handleApiError` as a bare sentence that interpolates ids and offers no next
378
- * step, so the two paths for the same mistake read very differently. Append the
379
- * remedy unless the server already named it.
380
- *
381
- * Exported for tests.
382
- */
370
+ export declare function describeResourceNotFound(serverMessage: string | undefined, bin?: string, baseURL?: string): string | null;
383
371
  export declare function describeAssigneeNotInSpace(serverMessage: string | undefined, bin?: string): string;
384
372
  /**
385
373
  * Whether an automated retry of the IDENTICAL request could plausibly succeed.
@@ -5,6 +5,7 @@ exports.assigneePayloadNeedsResolution = assigneePayloadNeedsResolution;
5
5
  exports.parseGlobalFlags = parseGlobalFlags;
6
6
  exports.withSubject = withSubject;
7
7
  exports.describeHarnessUnavailable = describeHarnessUnavailable;
8
+ exports.describeResourceNotFound = describeResourceNotFound;
8
9
  exports.describeAssigneeNotInSpace = describeAssigneeNotInSpace;
9
10
  exports.describeForbidden = describeForbidden;
10
11
  exports.isRetryableFailure = isRetryableFailure;
@@ -288,6 +289,16 @@ class BaseCommand extends core_1.Command {
288
289
  kind: (0, auth_core_1.classifyTokenKind)(accessToken),
289
290
  };
290
291
  }
292
+ else if (autoResult.outcome.reason === 'rate_limited') {
293
+ // Otherwise the only thing the user sees is "Not signed in", which is
294
+ // true and points at the wrong repair: they are signed in, the local
295
+ // broker is just being throttled, and the fix is to wait rather than
296
+ // to log in again. Reachable in the ordinary way — a cold machine
297
+ // running several skrr commands at once has every process brokering,
298
+ // because none of them has a token yet.
299
+ process.stderr.write('[skrr] The local skrr runtime is being rate-limited while brokering logins. ' +
300
+ 'This is transient — retry in a few minutes, or run `skrr login` to sign in directly.\n');
301
+ }
291
302
  else if (autoResult.outcome.reason === 'base_url_mismatch' &&
292
303
  autoResult.outcome.daemonServerUrl) {
293
304
  // The user is about to see "Not signed in" — give them the
@@ -869,7 +880,15 @@ class BaseCommand extends core_1.Command {
869
880
  }
870
881
  else if (e.status === 404) {
871
882
  this.failWithCliError({
872
- message: say(bodyMessage || 'Not found.'),
883
+ // Give the by-id path the remedy the by-name path already carries.
884
+ // The server answers a stale id with a bare `Space not found`, while
885
+ // a typo'd NAME gets a message naming `spaces list` and `--q`. A
886
+ // pasted stale id is the MORE common mistake and got the worse
887
+ // message, because a UUID short-circuits the resolver and the
888
+ // failure only surfaces here as a 404.
889
+ message: say(describeResourceNotFound(bodyMessage, this.config.bin, this.cliConfig?.baseURL) ||
890
+ bodyMessage ||
891
+ 'Not found.'),
873
892
  code: bodyCode || 'NOT_FOUND',
874
893
  status: e.status,
875
894
  exit: 4,
@@ -1222,6 +1241,64 @@ function describeHarnessUnavailable(body, bin = 'skrr') {
1222
1241
  *
1223
1242
  * Exported for tests.
1224
1243
  */
1244
+ /**
1245
+ * A bare `<Thing> not found` from the server, given the remedy the by-name
1246
+ * path already carries.
1247
+ *
1248
+ * `skrr spaces show <stale-uuid>` answered `Space not found` / NOT_FOUND and
1249
+ * stopped there, while a typo'd NAME got a genuinely good error naming
1250
+ * `spaces list` and `spaces list --q`. The by-id path is the MORE common
1251
+ * mistake — a stale or mistyped id pasted from somewhere — and it got the
1252
+ * worse message, because a UUID short-circuits the resolver and the failure
1253
+ * only surfaces later as a server 404.
1254
+ *
1255
+ * Same shape and same remedy as `describeAssigneeNotInSpace` above, whose own
1256
+ * comment records the identical asymmetry for assignees (OSK-4864).
1257
+ *
1258
+ * Keyed on the server's exact sentence rather than the code, because
1259
+ * `NOT_FOUND` is generic across resources and the sentence is what says which
1260
+ * one. An unrecognised subject falls through unchanged — a wrong hint is worse
1261
+ * than none.
1262
+ */
1263
+ const NOT_FOUND_REMEDIES = {
1264
+ 'Space not found': 'spaces list',
1265
+ 'Task not found': 'tasks list',
1266
+ 'Goal not found': 'goals list',
1267
+ 'Agent not found': 'agents list',
1268
+ };
1269
+ /**
1270
+ * Subjects whose ids are DEPLOYMENT-SCOPED, where "not found" most often means
1271
+ * "not found HERE" rather than "does not exist".
1272
+ *
1273
+ * An agent id minted on one deployment cannot resolve on another, and the
1274
+ * machine's own managed `CLAUDE.md` identity block prints agent ids without
1275
+ * recording which deployment they belong to. So a machine whose CLI default
1276
+ * moves between deployments keeps a platform-authored instruction telling its
1277
+ * local coding agent to run `agent message send --agent <id>` with ids that
1278
+ * cannot resolve — and the failure lands on the one sanctioned agent-to-user
1279
+ * path, where it reads as "the agent silently stopped being able to reach its
1280
+ * owner".
1281
+ *
1282
+ * Naming the server turns that into a diagnosable error. It does not FIX the
1283
+ * stale block — the block should record its own deployment, which is a
1284
+ * server-side change — but it stops the symptom being mute.
1285
+ */
1286
+ const DEPLOYMENT_SCOPED_SUBJECTS = new Set(['Agent not found']);
1287
+ function describeResourceNotFound(serverMessage, bin = 'skrr', baseURL) {
1288
+ const base = serverMessage?.trim();
1289
+ if (!base)
1290
+ return null;
1291
+ const listCommand = NOT_FOUND_REMEDIES[base];
1292
+ if (!listCommand)
1293
+ return null;
1294
+ const where = DEPLOYMENT_SCOPED_SUBJECTS.has(base) && baseURL ? ` on ${baseURL}` : '';
1295
+ const scoped = DEPLOYMENT_SCOPED_SUBJECTS.has(base)
1296
+ ? `\n → ids are per-deployment, so one from another server (or from a stale managed ` +
1297
+ `\`CLAUDE.md\` identity block) will not resolve here. \`${bin} context\` names this server.`
1298
+ : '';
1299
+ return (`${base}${where}\n → list what you can see with \`${bin} ${listCommand}\`, ` +
1300
+ `or search with \`${bin} ${listCommand} --q "<text>"\`.${scoped}`);
1301
+ }
1225
1302
  function describeAssigneeNotInSpace(serverMessage, bin = 'skrr') {
1226
1303
  const base = serverMessage?.trim() || 'That assignee is not a member of this space.';
1227
1304
  if (base.includes(`${bin} spaces members add`))
@@ -5,7 +5,13 @@ const browser_1 = require("../../browser");
5
5
  class BrowserSkillShow extends core_1.Command {
6
6
  static description = 'Print the version-matched skrr Browser agent skill';
7
7
  static args = {
8
- name: core_1.Args.string({ description: 'Skill name (core)' }),
8
+ // `ignoreStdin` or oclif fills this positional from STDIN whenever stdin is
9
+ // not a TTY — so `echo x | skrr browser skill show` took the piped bytes as
10
+ // the skill name and failed with "Unknown skrr Browser skill: x", while the
11
+ // identical command with stdin closed printed the skill. `skrr commands
12
+ // --audit` names this rule (ARG_IMPLICIT_STDIN_ENABLED) and this was its
13
+ // only error.
14
+ name: core_1.Args.string({ description: 'Skill name (core)', ignoreStdin: true }),
9
15
  };
10
16
  async run() {
11
17
  const { args } = await this.parse(BrowserSkillShow);
@@ -11,6 +11,7 @@ import { Command } from '@oclif/core';
11
11
  * that parses successfully and is then silently dropped.
12
12
  */
13
13
  export default class Code extends Command {
14
+ static summary: string;
14
15
  static description: string;
15
16
  static strict: boolean;
16
17
  static examples: string[];
@@ -17,7 +17,15 @@ const sky_code_managed_1 = require("../../lib/sky-code-managed");
17
17
  * that parses successfully and is then silently dropped.
18
18
  */
19
19
  class Code extends core_1.Command {
20
- static description = 'Start the skrr Code interactive coding agent in this directory. Everything after ' +
20
+ // oclif renders `summary` in a command listing and `description` only in the
21
+ // command's own help. Without one, the forwarding note below — which has to
22
+ // be long, because it is explaining an absent FLAGS section — was printed in
23
+ // full inside `skrr --help`, twice (under TOPICS and again under COMMANDS),
24
+ // turning the top-level index into prose. Same trade the `skrr daemon`
25
+ // pass-throughs make: the note reaches whoever asks about this command, and
26
+ // nobody else.
27
+ static summary = 'Start the skrr Code interactive coding agent in this directory';
28
+ static description = 'Everything after ' +
21
29
  `\`code\` is forwarded to the engine unchanged, so engine flags are not listed here — ` +
22
30
  `run \`skrr code run --help\` for this wrapper, or the engine's own help for its ` +
23
31
  `flags. ${sky_code_managed_1.SKRR_AGENT_FLAG} is the one flag this wrapper consumes itself.`;
@@ -26,7 +26,9 @@ const REPORT_RUNNERS = {
26
26
  decision,
27
27
  }),
28
28
  distribution: ({ days, workspace }) => commitment_analytics_1.commitmentAnalyticsApi.distribution({ days, workspaceId: workspace }),
29
+ 'distribution-tripwire': ({ limit, workspace }) => commitment_analytics_1.commitmentAnalyticsApi.distributionTripwire({ limit, workspaceId: workspace }),
29
30
  'attention-budget': ({ days, limit }) => commitment_analytics_1.commitmentAnalyticsApi.attentionBudget({ days, limit }),
31
+ 'decision-inbox': () => commitment_analytics_1.commitmentAnalyticsApi.decisionInbox(),
30
32
  'action-adapters-audit': () => commitment_analytics_1.commitmentAnalyticsApi.actionAdapterAudit(),
31
33
  'recovery-metrics': ({ limit }) => commitment_analytics_1.commitmentAnalyticsApi.recoveryMetrics({ limit }),
32
34
  recovery: ({ limit }) => commitment_analytics_1.commitmentAnalyticsApi.recovery({ limit }),
@@ -6,6 +6,7 @@ import { Command } from '@oclif/core';
6
6
  */
7
7
  export default class DaemonByok extends Command {
8
8
  static aliases: string[];
9
+ static summary: string;
9
10
  static description: string;
10
11
  static strict: boolean;
11
12
  static examples: string[];
@@ -12,7 +12,8 @@ class DaemonByok extends core_1.Command {
12
12
  // whole topic, and without a per-command alias only the bare topic
13
13
  // resolved: every subcommand under it failed.
14
14
  static aliases = ['daemons:byok'];
15
- static description = 'Manage local BYOK provider credentials in the daemon profile Keychain';
15
+ static summary = 'Manage local BYOK provider credentials in the daemon profile Keychain';
16
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('byok');
16
17
  static strict = false;
17
18
  static examples = [
18
19
  '<%= config.bin %> daemon byok status',
@@ -13,6 +13,7 @@ import { Command } from '@oclif/core';
13
13
  */
14
14
  export default class DaemonInstall extends Command {
15
15
  static aliases: string[];
16
+ static summary: string;
16
17
  static description: string;
17
18
  static strict: boolean;
18
19
  run(): Promise<void>;
@@ -20,7 +20,8 @@ class DaemonInstall extends core_1.Command {
20
20
  // whole topic, and without a per-command alias only the bare topic
21
21
  // resolved: every subcommand under it failed.
22
22
  static aliases = ['daemons:install'];
23
- static description = 'Install the local skrr runtime as a background service';
23
+ static summary = 'Install the local skrr runtime as a background service';
24
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('install', { binds: true });
24
25
  static strict = false; // forward all args verbatim — see run()
25
26
  async run() {
26
27
  // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
@@ -0,0 +1,31 @@
1
+ import { Command } from '@oclif/core';
2
+ /**
3
+ * `skrr daemon login` — authenticate the local runtime.
4
+ *
5
+ * Exists because the CLI and the daemon deliberately keep SEPARATE credentials
6
+ * (distinct keychain namespaces, distinct refresh families, independent
7
+ * revocation), and nothing made that legible. `skrr login` mints a cli-scope
8
+ * credential; the daemon reads a daemon-scope one. So the daemon would refuse to
9
+ * start, print `AUTH_BINDING_MISMATCH`, and the operator would run `skrr login`,
10
+ * complete a full browser flow, and get the identical error back — because the
11
+ * only command that could clear it lived on a second binary they had no reason to
12
+ * know existed (OSK-303).
13
+ *
14
+ * This does not merge the two credentials, and should not: daemon scope is
15
+ * deliberately LOWER-privileged than cli scope (`requireHumanScope` refuses it
16
+ * from billing, account management, password change and deletion), and separate
17
+ * revocation means losing a machine is not losing your session. What it removes
18
+ * is the user having to PERFORM that separation.
19
+ *
20
+ * `--env` / `--server` default to the deployment the CLI is on, for the same
21
+ * reason `install` does: a daemon authenticated against a different deployment
22
+ * than its CLI is the split OSK-279 exists to prevent, and picking it up from the
23
+ * session is how one command stops producing two answers.
24
+ */
25
+ export default class DaemonLogin extends Command {
26
+ static aliases: string[];
27
+ static summary: string;
28
+ static description: string;
29
+ static strict: boolean;
30
+ run(): Promise<void>;
31
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const daemon_binding_1 = require("../../lib/daemon-binding");
5
+ const exec_oversky_1 = require("../../lib/exec-oversky");
6
+ /**
7
+ * `skrr daemon login` — authenticate the local runtime.
8
+ *
9
+ * Exists because the CLI and the daemon deliberately keep SEPARATE credentials
10
+ * (distinct keychain namespaces, distinct refresh families, independent
11
+ * revocation), and nothing made that legible. `skrr login` mints a cli-scope
12
+ * credential; the daemon reads a daemon-scope one. So the daemon would refuse to
13
+ * start, print `AUTH_BINDING_MISMATCH`, and the operator would run `skrr login`,
14
+ * complete a full browser flow, and get the identical error back — because the
15
+ * only command that could clear it lived on a second binary they had no reason to
16
+ * know existed (OSK-303).
17
+ *
18
+ * This does not merge the two credentials, and should not: daemon scope is
19
+ * deliberately LOWER-privileged than cli scope (`requireHumanScope` refuses it
20
+ * from billing, account management, password change and deletion), and separate
21
+ * revocation means losing a machine is not losing your session. What it removes
22
+ * is the user having to PERFORM that separation.
23
+ *
24
+ * `--env` / `--server` default to the deployment the CLI is on, for the same
25
+ * reason `install` does: a daemon authenticated against a different deployment
26
+ * than its CLI is the split OSK-279 exists to prevent, and picking it up from the
27
+ * session is how one command stops producing two answers.
28
+ */
29
+ class DaemonLogin extends core_1.Command {
30
+ static aliases = ['daemons:login'];
31
+ static summary = 'Authenticate the local skrr runtime (separate from `skrr login`)';
32
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('login', { binds: true });
33
+ static strict = false; // forward all args verbatim — see run()
34
+ async run() {
35
+ // `this.argv`, NOT `this.parse()` — `strict = false` relaxes POSITIONAL
36
+ // arity and oclif still rejects any flag this command has not declared
37
+ // (OSK-296).
38
+ const argv = this.argv;
39
+ try {
40
+ // `--cwd` is deliberately NOT defaulted here. `skrrd login` resolves it
41
+ // from the installed service definition, which is the only authoritative
42
+ // answer; guessing it from the CLI's cwd is exactly the mistake that made
43
+ // the old default wrong.
44
+ const code = await (0, exec_oversky_1.execOversky)(['login', ...(0, daemon_binding_1.bindToCliSession)(argv)]);
45
+ this.exit(code);
46
+ }
47
+ catch (err) {
48
+ if (err.message === 'oversky-not-installed') {
49
+ this.log((0, exec_oversky_1.notInstalledMessage)());
50
+ this.exit(127);
51
+ }
52
+ throw err;
53
+ }
54
+ }
55
+ }
56
+ exports.default = DaemonLogin;
@@ -0,0 +1,9 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DaemonRestart extends Command {
3
+ static aliases: string[];
4
+ static summary: string;
5
+ static description: string;
6
+ static strict: boolean;
7
+ static examples: string[];
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const exec_oversky_1 = require("../../lib/exec-oversky");
5
+ class DaemonRestart extends core_1.Command {
6
+ // `skrr daemons <sub>` — the plural is advertised as an alias for the
7
+ // whole topic, and without a per-command alias only the bare topic
8
+ // resolved: every subcommand under it failed.
9
+ static aliases = ['daemons:restart'];
10
+ static summary = 'Restart the local skrr daemon, preserving its current supervision mode';
11
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('restart');
12
+ static strict = false; // forward all args verbatim — see run()
13
+ static examples = [
14
+ '<%= config.bin %> daemon restart',
15
+ '<%= config.bin %> daemon restart --profile work',
16
+ ];
17
+ async run() {
18
+ // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
19
+ // arity and oclif still rejects any flag this command has not declared —
20
+ // so every `skrrd` flag would be unreachable through the wrapper that
21
+ // exists to reach it (OSK-296).
22
+ const argv = this.argv;
23
+ try {
24
+ const code = await (0, exec_oversky_1.execOversky)(['restart', ...argv]);
25
+ this.exit(code);
26
+ }
27
+ catch (err) {
28
+ if (err.message === 'oversky-not-installed') {
29
+ this.log((0, exec_oversky_1.notInstalledMessage)());
30
+ this.exit(127);
31
+ }
32
+ throw err;
33
+ }
34
+ }
35
+ }
36
+ exports.default = DaemonRestart;
@@ -1,6 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class DaemonStart extends Command {
3
3
  static aliases: string[];
4
+ static summary: string;
4
5
  static description: string;
5
6
  static strict: boolean;
6
7
  run(): Promise<void>;
@@ -7,7 +7,8 @@ class DaemonStart extends core_1.Command {
7
7
  // whole topic, and without a per-command alias only the bare topic
8
8
  // resolved: every subcommand under it failed.
9
9
  static aliases = ['daemons:start'];
10
- static description = 'Start the local skrr daemon';
10
+ static summary = 'Start the local skrr daemon';
11
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('start');
11
12
  static strict = false; // forward all args verbatim — see run()
12
13
  async run() {
13
14
  // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
@@ -1,6 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class DaemonStatus extends Command {
3
3
  static aliases: string[];
4
+ static summary: string;
4
5
  static description: string;
5
6
  static strict: boolean;
6
7
  run(): Promise<void>;
@@ -7,7 +7,8 @@ class DaemonStatus extends core_1.Command {
7
7
  // whole topic, and without a per-command alias only the bare topic
8
8
  // resolved: every subcommand under it failed.
9
9
  static aliases = ['daemons:status'];
10
- static description = 'Show skrr daemon status (config, connection, services)';
10
+ static summary = 'Show skrr daemon status (config, connection, services)';
11
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('status');
11
12
  static strict = false;
12
13
  async run() {
13
14
  // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
@@ -1,6 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class DaemonStop extends Command {
3
3
  static aliases: string[];
4
+ static summary: string;
4
5
  static description: string;
5
6
  static strict: boolean;
6
7
  run(): Promise<void>;
@@ -7,7 +7,8 @@ class DaemonStop extends core_1.Command {
7
7
  // whole topic, and without a per-command alias only the bare topic
8
8
  // resolved: every subcommand under it failed.
9
9
  static aliases = ['daemons:stop'];
10
- static description = 'Stop the local skrr daemon';
10
+ static summary = 'Stop the local skrr daemon';
11
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('stop');
11
12
  static strict = false;
12
13
  async run() {
13
14
  // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
@@ -13,6 +13,7 @@ import { Command } from '@oclif/core';
13
13
  */
14
14
  export default class DaemonUninstall extends Command {
15
15
  static aliases: string[];
16
+ static summary: string;
16
17
  static description: string;
17
18
  static strict: boolean;
18
19
  run(): Promise<void>;
@@ -19,7 +19,8 @@ class DaemonUninstall extends core_1.Command {
19
19
  // whole topic, and without a per-command alias only the bare topic
20
20
  // resolved: every subcommand under it failed.
21
21
  static aliases = ['daemons:uninstall'];
22
- static description = "Remove the local skrr runtime's background service (local state is left alone)";
22
+ static summary = "Remove the local skrr runtime's background service (local state is left alone)";
23
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('uninstall');
23
24
  static strict = false; // forward all args verbatim — see run()
24
25
  async run() {
25
26
  // `this.argv`, NOT `this.parse()`. `strict = false` relaxes POSITIONAL
@@ -0,0 +1,9 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class DaemonUnlock extends Command {
3
+ static aliases: string[];
4
+ static summary: string;
5
+ static description: string;
6
+ static strict: boolean;
7
+ static examples: string[];
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const exec_oversky_1 = require("../../lib/exec-oversky");
5
+ class DaemonUnlock extends core_1.Command {
6
+ // `skrr daemons <sub>` — the plural is advertised as an alias for the
7
+ // whole topic, and without a per-command alias only the bare topic
8
+ // resolved: every subcommand under it failed.
9
+ static aliases = ['daemons:unlock'];
10
+ static summary = 'Clear a stranded singleton lock (daemon.lock) left by a crashed skrr daemon';
11
+ static description = (0, exec_oversky_1.forwardedFlagsNote)('unlock');
12
+ static strict = false; // forward all args verbatim — see run()
13
+ static examples = ['<%= config.bin %> daemon unlock'];
14
+ async run() {
15
+ // Recovery verbs are the ones that most need to be reachable from the
16
+ // wrapper: you go looking for `unlock` exactly when the daemon is wedged,
17
+ // which is the worst moment to discover the CLI cannot reach it and that
18
+ // the verb lives on a second binary you have to learn about first.
19
+ const argv = this.argv;
20
+ try {
21
+ const code = await (0, exec_oversky_1.execOversky)(['unlock', ...argv]);
22
+ this.exit(code);
23
+ }
24
+ catch (err) {
25
+ if (err.message === 'oversky-not-installed') {
26
+ this.log((0, exec_oversky_1.notInstalledMessage)());
27
+ this.exit(127);
28
+ }
29
+ throw err;
30
+ }
31
+ }
32
+ }
33
+ exports.default = DaemonUnlock;
@@ -28,7 +28,16 @@ class GoalsKeyResultsCreate extends base_command_1.BaseCommand {
28
28
  }),
29
29
  title: core_1.Flags.string({ description: 'Key result title (required unless set via --from-json)' }),
30
30
  description: core_1.Flags.string({ description: 'Key result description' }),
31
- progress: core_1.Flags.integer({ description: 'Progress 0–100 (used in manual mode)' }),
31
+ // The bound is declared, not just described. `--progress 150` and
32
+ // `--progress -5` both came back as a bare `Invalid request data /
33
+ // HTTP_400` from the server — byte-identical for two different mistakes,
34
+ // in a CLI that gives excellent field-level errors for enums. oclif
35
+ // refuses an out-of-range value naming the range, before the round trip.
36
+ progress: core_1.Flags.integer({
37
+ description: 'Progress 0–100 (used in manual mode)',
38
+ min: 0,
39
+ max: 100,
40
+ }),
32
41
  'progress-mode': core_1.Flags.string({
33
42
  description: 'How progress is tracked',
34
43
  options: [...data_provider_1.KEY_RESULT_PROGRESS_MODES],
@@ -78,6 +87,28 @@ class GoalsKeyResultsCreate extends base_command_1.BaseCommand {
78
87
  }
79
88
  const k = created;
80
89
  this.log(`Created key result ${k.id ?? '?'} on goal ${args.goalId} - ${k.title ?? '(no title)'}`);
90
+ if (k.progressMode === 'auto')
91
+ this.warn(AUTO_MODE_NOTE);
81
92
  }
82
93
  }
83
94
  exports.default = GoalsKeyResultsCreate;
95
+ /**
96
+ * Why an `auto` key result reads as `-` from the CLI.
97
+ *
98
+ * Auto progress is computed from tasks linked to THIS key result
99
+ * (`Task.keyResultIds`), and the task↔key-result link is a DOCUMENTED
100
+ * omission from the CLI surface — it sits in `domain-api-parity.spec.ts`'s
101
+ * allowlist with a stated reason. So `--progress-mode auto` is offered by a
102
+ * surface that cannot make it move, and `resolveKeyResultProgress` renders
103
+ * `_computedProgress ?? null` for auto, i.e. `-`, while a `--progress` value
104
+ * you set is stored and returned by `update`.
105
+ *
106
+ * The result was one CLI reporting two different values for one field: the
107
+ * write echoed 40 and the list showed `-`. Saying so at the point of use is
108
+ * the honest fix; silently rendering the stored number instead would hide a
109
+ * real distinction (a manual value is not a computed one), and adding the
110
+ * link command would reverse a recorded decision.
111
+ */
112
+ const AUTO_MODE_NOTE = 'Auto progress is computed from tasks linked to this key result, and linking a task to a key ' +
113
+ 'result is deliberately not in the CLI — so this reads as "-" here until it is linked ' +
114
+ 'elsewhere. Use --progress-mode manual to track a number from the CLI.';
@@ -25,3 +25,14 @@ export default class GoalsKeyResultsUpdate extends BaseCommand {
25
25
  };
26
26
  run(): Promise<void>;
27
27
  }
28
+ /**
29
+ * The sentence to print when `done` and a sub-100 progress are made to
30
+ * disagree, or `null` when they do not. Exported for `update.spec.ts`.
31
+ *
32
+ * Returns a warning rather than reconciling the two: pulling progress to 100
33
+ * would be the CLI inventing a policy the server does not have, and it would
34
+ * destroy the recorded number on the way.
35
+ */
36
+ export declare function describeDoneDisagreement(status: string | undefined, progress: number | null): string | null;
37
+ /** How the server now holds one patched field, for the confirmation line. */
38
+ export declare function describeField(kr: Record<string, unknown>, field: string): string;