@skrr-ai/cli 0.1.127 → 0.1.129

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 (165) hide show
  1. package/dist/base-command.d.ts +35 -0
  2. package/dist/base-command.js +107 -0
  3. package/dist/commands/agenda/trigger/list.d.ts +2 -1
  4. package/dist/commands/agenda/trigger/list.js +55 -6
  5. package/dist/commands/agents/chat.js +7 -0
  6. package/dist/commands/agents/create.js +3 -1
  7. package/dist/commands/browser/persistent-profile.d.ts +22 -0
  8. package/dist/commands/browser/persistent-profile.js +46 -0
  9. package/dist/commands/commitments/action-history.js +1 -1
  10. package/dist/commands/commitments/cases.js +3 -3
  11. package/dist/commands/commitments/check-now.d.ts +10 -2
  12. package/dist/commands/commitments/check-now.js +53 -3
  13. package/dist/commands/commitments/create.d.ts +6 -14
  14. package/dist/commands/commitments/create.js +64 -7
  15. package/dist/commands/commitments/doctor.js +3 -1
  16. package/dist/commands/commitments/effective-policy.d.ts +11 -1
  17. package/dist/commands/commitments/effective-policy.js +90 -4
  18. package/dist/commands/commitments/explain.js +10 -1
  19. package/dist/commands/commitments/hypotheses.js +12 -12
  20. package/dist/commands/commitments/next-tick.js +5 -0
  21. package/dist/commands/commitments/observations.js +18 -17
  22. package/dist/commands/commitments/pack/list.js +2 -1
  23. package/dist/commands/commitments/pack/plan.d.ts +6 -0
  24. package/dist/commands/commitments/pack/plan.js +19 -0
  25. package/dist/commands/commitments/plan.d.ts +14 -0
  26. package/dist/commands/commitments/plan.js +32 -0
  27. package/dist/commands/commitments/preflight.d.ts +20 -1
  28. package/dist/commands/commitments/preflight.js +118 -12
  29. package/dist/commands/commitments/show.d.ts +9 -0
  30. package/dist/commands/commitments/show.js +14 -1
  31. package/dist/commands/commitments/trigger-status.js +8 -0
  32. package/dist/commands/commitments/update.d.ts +1 -0
  33. package/dist/commands/commitments/update.js +45 -4
  34. package/dist/commands/commitments/wake-capabilities.js +13 -0
  35. package/dist/commands/compass/archive.js +4 -0
  36. package/dist/commands/compass/commitments.js +15 -1
  37. package/dist/commands/compass/create.js +11 -3
  38. package/dist/commands/compass/effective-policy.d.ts +1 -0
  39. package/dist/commands/compass/effective-policy.js +8 -7
  40. package/dist/commands/compass/revert.d.ts +8 -0
  41. package/dist/commands/compass/revert.js +25 -1
  42. package/dist/commands/compass/revisions.d.ts +6 -0
  43. package/dist/commands/compass/revisions.js +26 -2
  44. package/dist/commands/compass/tactic.d.ts +10 -3
  45. package/dist/commands/compass/tactic.js +22 -7
  46. package/dist/commands/compass/update.js +19 -3
  47. package/dist/commands/followups/act.js +1 -1
  48. package/dist/commands/followups/cancel.js +13 -0
  49. package/dist/commands/followups/observability.js +20 -1
  50. package/dist/commands/followups/plans/create.js +12 -1
  51. package/dist/commands/followups/show.js +13 -0
  52. package/dist/commands/followups/watch.js +1 -1
  53. package/dist/commands/goals/planner-config.d.ts +11 -0
  54. package/dist/commands/goals/planner-config.js +16 -0
  55. package/dist/commands/harnesses/list.js +1 -1
  56. package/dist/commands/machines/update.d.ts +5 -3
  57. package/dist/commands/machines/update.js +70 -9
  58. package/dist/commands/northstars/create.js +3 -1
  59. package/dist/commands/northstars/governance/configure.d.ts +4 -0
  60. package/dist/commands/northstars/governance/configure.js +76 -10
  61. package/dist/commands/northstars/intents/decide.d.ts +6 -0
  62. package/dist/commands/northstars/intents/decide.js +68 -15
  63. package/dist/commands/northstars/intents/list.d.ts +2 -1
  64. package/dist/commands/northstars/intents/list.js +15 -5
  65. package/dist/commands/northstars/intents.d.ts +26 -0
  66. package/dist/commands/northstars/intents.js +49 -0
  67. package/dist/commands/northstars/list.d.ts +1 -0
  68. package/dist/commands/northstars/list.js +24 -3
  69. package/dist/commands/northstars/recommendations/list.d.ts +1 -1
  70. package/dist/commands/northstars/recommendations/list.js +3 -3
  71. package/dist/commands/northstars/recommendations.d.ts +19 -0
  72. package/dist/commands/northstars/recommendations.js +42 -0
  73. package/dist/commands/northstars/review-now.d.ts +1 -0
  74. package/dist/commands/northstars/review-now.js +15 -4
  75. package/dist/commands/northstars/reviews.d.ts +1 -0
  76. package/dist/commands/northstars/reviews.js +34 -6
  77. package/dist/commands/northstars/update.js +8 -1
  78. package/dist/commands/proposals/list.js +11 -2
  79. package/dist/commands/proposals/show.js +9 -1
  80. package/dist/commands/spaces/auto-executor/preview.d.ts +14 -1
  81. package/dist/commands/spaces/auto-executor/preview.js +35 -1
  82. package/dist/commands/spaces/auto-executor/run.d.ts +17 -0
  83. package/dist/commands/spaces/auto-executor/run.js +60 -2
  84. package/dist/commands/spaces/auto-executor/runs.d.ts +9 -1
  85. package/dist/commands/spaces/auto-executor/runs.js +18 -1
  86. package/dist/commands/spaces/files/upload.js +1 -2
  87. package/dist/commands/spaces/heartbeats/create.js +7 -5
  88. package/dist/commands/spaces/heartbeats/update.js +5 -3
  89. package/dist/commands/spaces/index.js +23 -0
  90. package/dist/commands/store/artifacts/releases.d.ts +20 -0
  91. package/dist/commands/store/artifacts/releases.js +85 -0
  92. package/dist/commands/store/library.d.ts +14 -0
  93. package/dist/commands/store/library.js +71 -0
  94. package/dist/commands/tasks/list.d.ts +48 -0
  95. package/dist/commands/tasks/list.js +141 -9
  96. package/dist/commands/tasks/remind.js +23 -11
  97. package/dist/commands/tasks/retry-schedule.js +6 -3
  98. package/dist/commands/tasks/schedule.js +29 -7
  99. package/dist/commands/tasks/show.js +4 -0
  100. package/dist/generated/agent-guides.json +69 -69
  101. package/dist/lib/agent-trigger-listing.d.ts +26 -0
  102. package/dist/lib/agent-trigger-listing.js +63 -0
  103. package/dist/lib/agentic-stream.d.ts +9 -0
  104. package/dist/lib/agentic-stream.js +152 -41
  105. package/dist/lib/command-miss.js +11 -2
  106. package/dist/lib/commitment-attention-copy.d.ts +96 -0
  107. package/dist/lib/commitment-attention-copy.js +209 -0
  108. package/dist/lib/commitment-ledgers.js +3 -1
  109. package/dist/lib/commitment-loop-status.d.ts +6 -0
  110. package/dist/lib/commitment-loop-status.js +16 -6
  111. package/dist/lib/commitments.d.ts +112 -0
  112. package/dist/lib/commitments.js +250 -2
  113. package/dist/lib/compass-body-help.d.ts +20 -0
  114. package/dist/lib/compass-body-help.js +61 -0
  115. package/dist/lib/compass-refusals.d.ts +35 -0
  116. package/dist/lib/compass-refusals.js +50 -0
  117. package/dist/lib/compasses.d.ts +82 -4
  118. package/dist/lib/compasses.js +232 -12
  119. package/dist/lib/followups.d.ts +22 -1
  120. package/dist/lib/followups.js +21 -1
  121. package/dist/lib/format.d.ts +11 -0
  122. package/dist/lib/format.js +29 -0
  123. package/dist/lib/initiatives.d.ts +9 -2
  124. package/dist/lib/initiatives.js +13 -2
  125. package/dist/lib/iso-instant.d.ts +52 -0
  126. package/dist/lib/iso-instant.js +162 -0
  127. package/dist/lib/machines.d.ts +14 -1
  128. package/dist/lib/machines.js +24 -0
  129. package/dist/lib/northstars.d.ts +201 -24
  130. package/dist/lib/northstars.js +655 -27
  131. package/dist/lib/proposal-decision-command.js +21 -1
  132. package/dist/lib/proposals.d.ts +26 -1
  133. package/dist/lib/proposals.js +167 -0
  134. package/dist/lib/rate-limit-retry.d.ts +5 -0
  135. package/dist/lib/rate-limit-retry.js +19 -0
  136. package/dist/lib/roles.d.ts +1 -1
  137. package/dist/lib/space-charter.js +9 -0
  138. package/dist/lib/store-artifact-releases.d.ts +39 -0
  139. package/dist/lib/store-artifact-releases.js +12 -0
  140. package/dist/lib/store-library.d.ts +37 -0
  141. package/dist/lib/store-library.js +12 -0
  142. package/dist/lib/task-asset-upload.js +1 -2
  143. package/dist/lib/task-calendar.d.ts +19 -0
  144. package/dist/lib/task-calendar.js +72 -0
  145. package/dist/lib/task-recurrence-outcome.js +3 -1
  146. package/dist/lib/task-recurrence-summary.d.ts +15 -0
  147. package/dist/lib/task-recurrence-summary.js +228 -0
  148. package/dist/lib/task-reminder.d.ts +28 -0
  149. package/dist/lib/task-reminder.js +50 -0
  150. package/dist/lib/triggers.d.ts +13 -2
  151. package/dist/lib/triggers.js +31 -13
  152. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +11 -1
  153. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.d.ts +123 -0
  154. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.js +160 -0
  155. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
  156. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +17 -0
  157. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +11 -1
  158. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.d.ts +123 -0
  159. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.js +173 -0
  160. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
  161. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
  162. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  163. package/dist/node_modules/@skrr-ai/data-provider/index.js +6922 -6828
  164. package/oclif.manifest.json +612 -62
  165. package/package.json +4 -4
@@ -1,6 +1,6 @@
1
1
  import { BaseCommand } from '../../../base-command';
2
2
  /**
3
- * `skrr northstars recommendations <id>` — the deterministic reviewer's
3
+ * `skrr northstars recommendations list <id>` — the deterministic reviewer's
4
4
  * user-facing suggestions.
5
5
  *
6
6
  * These are NOT the same thing as management intents. A recommendation is
@@ -5,7 +5,7 @@ const core_1 = require("@oclif/core");
5
5
  const base_command_1 = require("../../../base-command");
6
6
  const northstars_1 = require("../../../lib/northstars");
7
7
  /**
8
- * `skrr northstars recommendations <id>` — the deterministic reviewer's
8
+ * `skrr northstars recommendations list <id>` — the deterministic reviewer's
9
9
  * user-facing suggestions.
10
10
  *
11
11
  * These are NOT the same thing as management intents. A recommendation is
@@ -16,8 +16,8 @@ const northstars_1 = require("../../../lib/northstars");
16
16
  class NorthstarsRecommendationsList extends base_command_1.BaseCommand {
17
17
  static description = "List a northstar's deterministic portfolio recommendations";
18
18
  static examples = [
19
- '<%= config.bin %> northstars recommendations nst_abc123',
20
- '<%= config.bin %> northstars recommendations nst_abc123 --status open',
19
+ '<%= config.bin %> northstars recommendations list nst_abc123',
20
+ '<%= config.bin %> northstars recommendations list nst_abc123 --status open',
21
21
  ];
22
22
  static args = {
23
23
  northstarId: core_1.Args.string({ ignoreStdin: true, description: 'Northstar ID', required: true }),
@@ -0,0 +1,19 @@
1
+ import NorthstarsRecommendationsList from './recommendations/list';
2
+ /**
3
+ * `skrr northstars recommendations <northstar-id>` — the topic's default: list them.
4
+ *
5
+ * Same reasoning as `northstars intents`: the help examples showed this form and it was
6
+ * answered with "is not a command". Listing is read-only, so it is the safe default;
7
+ * `recommendations apply` and `recommendations dismiss` still resolve to their own
8
+ * commands (the longest command id wins). With no northstar id it prints the topic help.
9
+ */
10
+ export default class NorthstarsRecommendations extends NorthstarsRecommendationsList {
11
+ static description: string;
12
+ static examples: string[];
13
+ static args: typeof NorthstarsRecommendationsList.args;
14
+ static flags: {
15
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
+ };
18
+ run(): Promise<void>;
19
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const core_1 = require("@oclif/core");
7
+ const list_1 = __importDefault(require("./recommendations/list"));
8
+ /**
9
+ * `skrr northstars recommendations <northstar-id>` — the topic's default: list them.
10
+ *
11
+ * Same reasoning as `northstars intents`: the help examples showed this form and it was
12
+ * answered with "is not a command". Listing is read-only, so it is the safe default;
13
+ * `recommendations apply` and `recommendations dismiss` still resolve to their own
14
+ * commands (the longest command id wins). With no northstar id it prints the topic help.
15
+ */
16
+ class NorthstarsRecommendations extends list_1.default {
17
+ static description = "List a northstar's recommendations; subcommands: list, apply, dismiss (`recommendations <id>` is `recommendations list <id>`)";
18
+ static examples = [
19
+ '<%= config.bin %> northstars recommendations nst_abc123',
20
+ '<%= config.bin %> northstars recommendations nst_abc123 --status open',
21
+ '<%= config.bin %> northstars recommendations list nst_abc123',
22
+ '<%= config.bin %> northstars recommendations apply nst_abc123 <rec-id>',
23
+ ];
24
+ // Own, not inherited (see `northstars intents`).
25
+ static args = {
26
+ northstarId: core_1.Args.string({
27
+ ignoreStdin: true,
28
+ description: 'Northstar ID (omit to see the subcommands)',
29
+ required: false,
30
+ }),
31
+ };
32
+ static flags = list_1.default.flags;
33
+ async run() {
34
+ const { args } = await this.parse(NorthstarsRecommendations);
35
+ if (!args.northstarId) {
36
+ await this.config.runCommand('help', ['northstars', 'recommendations']);
37
+ return;
38
+ }
39
+ await super.run();
40
+ }
41
+ }
42
+ exports.default = NorthstarsRecommendations;
@@ -16,6 +16,7 @@ export default class NorthstarsReviewNow extends BaseCommand {
16
16
  };
17
17
  static flags: {
18
18
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
+ wide: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
20
  };
20
21
  run(): Promise<void>;
21
22
  }
@@ -23,6 +23,7 @@ class NorthstarsReviewNow extends base_command_1.BaseCommand {
23
23
  };
24
24
  static flags = {
25
25
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
26
+ wide: northstars_1.northstarWideFlag,
26
27
  };
27
28
  async run() {
28
29
  this.requireAuth();
@@ -44,18 +45,28 @@ class NorthstarsReviewNow extends base_command_1.BaseCommand {
44
45
  if (review) {
45
46
  this.log(`Review ${String(review.id)} (${String(review.status)})`);
46
47
  }
47
- const allocations = Array.isArray(result.allocations) ? result.allocations.length : 0;
48
- this.log(`Allocations ${allocations} commitment(s) re-budgeted`);
48
+ this.log((0, northstars_1.describeReviewAllocations)(result));
49
+ // The allocation above gives each commitment at least 1/day; when the budget is smaller than
50
+ // the number of active commitments that adds up to more than the budget (OSK-21334).
51
+ const floorNote = (0, northstars_1.runBudgetFloorNote)(result.runBudgetFloor);
52
+ if (floorNote)
53
+ this.log(` ! ${floorNote}`);
49
54
  this.log(`Applied ${String(result.appliedIntents ?? 0)} intent(s)`);
50
55
  if (governanceRun) {
51
56
  this.log(governanceRun.reserved
52
57
  ? `Agent run ${String(governanceRun.runId)} reserved — results land asynchronously`
53
- : `Agent run not started (${String(governanceRun.reason ?? 'unknown')})`);
58
+ : `Agent run not started: ${(0, northstars_1.describeNorthstarReason)(typeof governanceRun.reason === 'string' ? governanceRun.reason : undefined)}`);
54
59
  }
55
60
  const intents = review?.intents ?? [];
61
+ // An intent budget that cut the review short must not read as "nothing to report".
62
+ const snapshot = review?.deterministicSnapshot;
63
+ const governance = result.governance;
64
+ const budgetNote = (0, northstars_1.intentBudgetNote)(snapshot?.truncatedIntents, governance?.maxIntentsPerReview);
65
+ if (budgetNote)
66
+ this.log(budgetNote);
56
67
  if (intents.length) {
57
68
  this.log('');
58
- (0, northstars_1.renderIntentList)(intents, (line) => this.log(line));
69
+ (0, northstars_1.renderIntentList)(intents, (line) => this.log(line), { wide: flags.wide });
59
70
  }
60
71
  }
61
72
  }
@@ -18,6 +18,7 @@ export default class NorthstarsReviews extends BaseCommand {
18
18
  limit: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
19
  status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
20
  review: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
+ wide: import("@oclif/core/interfaces").BooleanFlag<boolean>;
21
22
  };
22
23
  run(): Promise<void>;
23
24
  }
@@ -28,19 +28,32 @@ class NorthstarsReviews extends base_command_1.BaseCommand {
28
28
  description: 'Filter by review status',
29
29
  options: [...northstars_1.NORTHSTAR_REVIEW_STATUSES],
30
30
  }),
31
- review: core_1.Flags.string({ description: 'Show ONE review in full, including its intents' }),
31
+ review: core_1.Flags.string({
32
+ description: 'Show ONE review in full, including its intents. Takes the full id or the short form `intents list` prints in REVIEW',
33
+ }),
34
+ wide: northstars_1.northstarWideFlag,
32
35
  };
33
36
  async run() {
34
37
  this.requireAuth();
35
38
  const { args, flags } = await this.parse(NorthstarsReviews);
36
39
  if (flags.review) {
37
- let review;
40
+ let looked;
38
41
  try {
39
- review = await northstars_1.northstarApi.review(args.northstarId, flags.review);
42
+ // The full id, or the short form `northstars intents list` prints in REVIEW.
43
+ looked = await (0, northstars_1.lookupReview)(args.northstarId, flags.review);
40
44
  }
41
45
  catch (err) {
42
46
  this.handleApiError(err);
43
47
  }
48
+ if ('ambiguous' in looked) {
49
+ this.failWithCliError({
50
+ message: `\`${flags.review}\` is the start of ${looked.ambiguous.length} reviews of this northstar (${looked.ambiguous.join(', ')}). Pass more of the id.`,
51
+ code: 'REVIEW_REF_AMBIGUOUS',
52
+ exit: 2,
53
+ retryable: false,
54
+ });
55
+ }
56
+ const review = looked.review;
44
57
  if (flags.json) {
45
58
  this.log(JSON.stringify(review, null, 2));
46
59
  return;
@@ -53,14 +66,20 @@ class NorthstarsReviews extends base_command_1.BaseCommand {
53
66
  if (review.autonomousRunId)
54
67
  this.log(`Agent run ${review.autonomousRunId}`);
55
68
  if (review.reason)
56
- this.log(`Reason ${review.reason}`);
69
+ this.log(`Reason ${(0, northstars_1.describeReviewReason)(review.reason)}`);
57
70
  const snapshot = review.deterministicSnapshot;
58
71
  if (snapshot) {
59
72
  this.log(`Health ${String(snapshot.health ?? '—')}`);
60
73
  this.log(`Allocations written ${String(snapshot.allocationsWritten ?? 0)}`);
61
74
  }
75
+ // A review the intent budget cut short is not a review with nothing to say.
76
+ const budgetNote = (0, northstars_1.intentBudgetNote)(snapshot?.truncatedIntents, snapshot?.intentCounts?.total);
77
+ if (budgetNote)
78
+ this.log(budgetNote);
62
79
  this.log('');
63
- (0, northstars_1.renderIntentList)(review.intents ?? [], (line) => this.log(line));
80
+ if (budgetNote && (review.intents ?? []).length === 0)
81
+ return;
82
+ (0, northstars_1.renderIntentList)(review.intents ?? [], (line) => this.log(line), { wide: flags.wide });
64
83
  return;
65
84
  }
66
85
  let response;
@@ -77,7 +96,16 @@ class NorthstarsReviews extends base_command_1.BaseCommand {
77
96
  this.log(JSON.stringify(response, null, 2));
78
97
  return;
79
98
  }
80
- (0, northstars_1.renderReviewList)(response.data ?? [], (line) => this.log(line));
99
+ const rows = response.data ?? [];
100
+ (0, northstars_1.renderReviewList)(rows, (line) => this.log(line));
101
+ const footer = (0, northstars_1.listFooter)({
102
+ shown: rows.length,
103
+ hasMore: response.has_more === true,
104
+ limit: flags.limit ?? 20,
105
+ max: 100,
106
+ });
107
+ if (footer)
108
+ this.log(footer);
81
109
  }
82
110
  }
83
111
  exports.default = NorthstarsReviews;
@@ -32,7 +32,10 @@ class NorthstarsUpdate extends base_command_1.BaseCommand {
32
32
  tier: core_1.Flags.string({ description: 'Priority tier', options: [...northstars_1.NORTHSTAR_PRIORITY_TIERS] }),
33
33
  weight: core_1.Flags.integer({ description: 'Priority weight (0..100)', min: 0, max: 100 }),
34
34
  'total-weight': core_1.Flags.integer({ description: 'Attention budget total weight', min: 0 }),
35
- 'max-active': core_1.Flags.integer({ description: 'Soft cap on active commitments', min: 0 }),
35
+ 'max-active': core_1.Flags.integer({
36
+ description: 'Soft cap on active commitments (0 = no cap)',
37
+ min: 0,
38
+ }),
36
39
  goal: core_1.Flags.string({ description: 'Goal ID (repeatable; replaces the list)', multiple: true }),
37
40
  agent: core_1.Flags.string({
38
41
  description: 'Agent ID (repeatable; replaces the list)',
@@ -109,6 +112,10 @@ class NorthstarsUpdate extends base_command_1.BaseCommand {
109
112
  return;
110
113
  }
111
114
  this.log(`Updated ${northstar.id} — ${northstar.title} (${northstar.status}, v${northstar.version})`);
115
+ // 0 is stored, and a review treats it as "no cap": say so here, not only in `show` (OSK-21252).
116
+ if (flags['max-active'] !== undefined) {
117
+ this.log(`Attention max active ${(0, northstars_1.describeMaxActive)(northstar.attentionBudget?.maxActiveCommitments ?? flags['max-active'])}`);
118
+ }
112
119
  }
113
120
  }
114
121
  exports.default = NorthstarsUpdate;
@@ -31,12 +31,21 @@ function emptyPageLines(narrowed, nextCursor) {
31
31
  * server could not read for this viewer is in `--json`), never "none".
32
32
  */
33
33
  function aboutFor(row) {
34
- return [row.commitmentTitle, row.agent?.name].filter(Boolean).join(' · ') || '—';
34
+ const named = [row.commitmentTitle, row.agent?.name].filter(Boolean).join(' · ');
35
+ if (named)
36
+ return named;
37
+ // A Northstar intent that targets no commitment (a proposal to start one) is about its northstar.
38
+ const northstarId = row.decisionContext?.northstarId;
39
+ return northstarId ? `northstar ${northstarId}` : '—';
35
40
  }
36
41
  /** A snoozed proposal reads `proposed` in its disposition; the wake time is what tells them apart. */
37
42
  function noteFor(row) {
38
43
  if (row.sourceStatus === 'snoozed' && row.snoozedUntil)
39
44
  return `snoozed until ${row.snoozedUntil}`;
45
+ // The inbox files a policy refusal under `discarded`; for a Northstar intent say what it was.
46
+ const intent = (0, proposals_1.northstarIntentNote)(row);
47
+ if (intent)
48
+ return intent;
40
49
  if (!row.canDecide && row.undecidableReason && row.undecidableReason !== 'settled')
41
50
  return data_provider_1.PROPOSAL_UNDECIDABLE_TEXT[row.undecidableReason];
42
51
  return '—';
@@ -86,7 +95,7 @@ class ProposalsList extends base_command_1.BaseCommand {
86
95
  }
87
96
  (0, format_1.renderTable)(result.data.map((row) => ({
88
97
  id: row.id,
89
- title: row.title,
98
+ title: (0, proposals_1.proposalTitleFor)(row),
90
99
  about: aboutFor(row),
91
100
  disposition: row.disposition,
92
101
  // Most proposals carry no estimate; "unknown" read as a failure to determine one (OSK-15377).
@@ -22,7 +22,7 @@ class ProposalsShow extends base_command_1.BaseCommand {
22
22
  static flags = { json: core_1.Flags.boolean() };
23
23
  async run() {
24
24
  this.requireAuth();
25
- const { args } = await this.parse(ProposalsShow);
25
+ const { args, flags } = await this.parse(ProposalsShow);
26
26
  const ref = (0, proposals_1.resolveProposalRef)(args.kind, args.id, this.config?.bin);
27
27
  if ('error' in ref) {
28
28
  this.failWithCliError({
@@ -48,6 +48,14 @@ class ProposalsShow extends base_command_1.BaseCommand {
48
48
  }
49
49
  this.handleApiError(error);
50
50
  }
51
+ // A Northstar intent reads as words unless --json asks for the document; every other kind still
52
+ // prints its full JSON, so a script that reads it does not change.
53
+ const lines = flags.json ? null : (0, proposals_1.renderNorthstarIntentView)(result);
54
+ if (lines) {
55
+ for (const line of lines)
56
+ this.log(line);
57
+ return;
58
+ }
51
59
  this.log(JSON.stringify(result, null, 2));
52
60
  }
53
61
  }
@@ -1,5 +1,17 @@
1
- import { type SpaceAutoExecutorRefillState } from '@skrr-ai/data-provider';
1
+ import { type SpaceAutoExecutorPreviewResponse, type SpaceAutoExecutorRefillState } from '@skrr-ai/data-provider';
2
2
  import { BaseCommand } from '../../../base-command';
3
+ type PreviewSpace = SpaceAutoExecutorPreviewResponse['space'];
4
+ /**
5
+ * "Can start" is a capacity figure, not a forecast. Printed bare next to a disabled autopilot
6
+ * it read as "one task will start now" (dogfooded: `Autopilot: disabled` / `Can start: 1 now`).
7
+ */
8
+ export declare function canStartLine(space: Pick<PreviewSpace, 'autoExecuteEnabled'>, startsAvailable: number | null): string;
9
+ /**
10
+ * Whether unattended work may run in the Space at all. Turning the board off does not revoke the
11
+ * principal and a revoked one keeps a disabled board silent, so the two have to be told apart.
12
+ * Returns null for a server that predates the field, so an old API prints no claim.
13
+ */
14
+ export declare function principalLine(space: Pick<PreviewSpace, 'executionPrincipal'>, spaceRef: string): string | null;
3
15
  export default class SpacesAutoExecutorPreview extends BaseCommand {
4
16
  static description: string;
5
17
  static examples: string[];
@@ -18,3 +30,4 @@ export default class SpacesAutoExecutorPreview extends BaseCommand {
18
30
  * not report it; `null` is one that could not read it, and says so.
19
31
  */
20
32
  export declare function refillLines(refill: SpaceAutoExecutorRefillState | null | undefined): string[];
33
+ export {};
@@ -1,10 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.canStartLine = canStartLine;
4
+ exports.principalLine = principalLine;
3
5
  exports.refillLines = refillLines;
4
6
  const core_1 = require("@oclif/core");
5
7
  const data_provider_1 = require("@skrr-ai/data-provider");
6
8
  const base_command_1 = require("../../../base-command");
7
9
  const space_output_1 = require("../../../lib/space-output");
10
+ /**
11
+ * "Can start" is a capacity figure, not a forecast. Printed bare next to a disabled autopilot
12
+ * it read as "one task will start now" (dogfooded: `Autopilot: disabled` / `Can start: 1 now`).
13
+ */
14
+ function canStartLine(space, startsAvailable) {
15
+ const capacity = (0, data_provider_1.formatLimit)(startsAvailable);
16
+ return space.autoExecuteEnabled
17
+ ? `Can start: ${capacity} now`
18
+ : `Can start: nothing — autopilot is off (capacity ${capacity})`;
19
+ }
20
+ /**
21
+ * Whether unattended work may run in the Space at all. Turning the board off does not revoke the
22
+ * principal and a revoked one keeps a disabled board silent, so the two have to be told apart.
23
+ * Returns null for a server that predates the field, so an old API prints no claim.
24
+ */
25
+ function principalLine(space, spaceRef) {
26
+ const principal = space.executionPrincipal;
27
+ if (principal === undefined)
28
+ return null;
29
+ if (principal === null) {
30
+ return ('Principal: none — nothing may run unattended here. A Space owner sets one with ' +
31
+ `\`skrr spaces auto-executor update ${spaceRef} --enabled\`.`);
32
+ }
33
+ if (principal.status === 'active')
34
+ return `Principal: active (version ${principal.version})`;
35
+ return (`Principal: revoked${principal.revokeReason ? ` (${principal.revokeReason.replace(/_/g, ' ')})` : ''} — ` +
36
+ `nothing may run unattended here until a Space owner sets it again with ` +
37
+ `\`skrr spaces auto-executor update ${spaceRef} --enabled\`.`);
38
+ }
8
39
  class SpacesAutoExecutorPreview extends base_command_1.BaseCommand {
9
40
  static description = 'Preview what a space auto-executor run would do';
10
41
  static examples = [
@@ -47,7 +78,10 @@ class SpacesAutoExecutorPreview extends base_command_1.BaseCommand {
47
78
  const { capacity } = plan;
48
79
  this.log(`Running: ${(0, data_provider_1.formatRunningCapacity)(capacity.activeCount, capacity.maxActiveTasks)}` +
49
80
  (capacity.maxActiveTasks === null ? ' (no concurrency cap)' : ''));
50
- this.log(`Can start: ${(0, data_provider_1.formatLimit)(capacity.startsAvailable)} now`);
81
+ this.log(canStartLine(space, capacity.startsAvailable));
82
+ const principal = principalLine(space, spaceRef);
83
+ if (principal)
84
+ this.log(principal);
51
85
  if (capacity.budget && !capacity.budget.unlimited) {
52
86
  this.log(`Budget: ${capacity.budget.consumedStarts}/${capacity.budget.maxStarts} starts used this round`);
53
87
  }
@@ -1,4 +1,20 @@
1
1
  import { BaseCommand } from '../../../base-command';
2
+ /** What `auto-execute-now` answered: `fired: false` carries the reason nothing started. */
3
+ type RunNowAnswer = {
4
+ fired?: boolean;
5
+ reason?: string;
6
+ runId?: string;
7
+ };
8
+ /**
9
+ * Why a manual run did not start, in words, and whether that is a refusal or just "already busy".
10
+ * The route answers 200 with `fired: false` and a `reason`; printing "Triggered" for it told an
11
+ * owner a run had started when nothing had (a Space with no execution principal never runs).
12
+ * `busy` is the normal "one is already in flight" answer, not a failure.
13
+ */
14
+ export declare function describeRunNotStarted(answer: RunNowAnswer, spaceRef: string): {
15
+ message: string;
16
+ busy: boolean;
17
+ };
2
18
  export default class SpacesAutoExecutorRun extends BaseCommand {
3
19
  static description: string;
4
20
  static args: {
@@ -9,3 +25,4 @@ export default class SpacesAutoExecutorRun extends BaseCommand {
9
25
  };
10
26
  run(): Promise<void>;
11
27
  }
28
+ export {};
@@ -1,9 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeRunNotStarted = describeRunNotStarted;
3
4
  const core_1 = require("@oclif/core");
4
5
  const data_provider_1 = require("@skrr-ai/data-provider");
5
6
  const base_command_1 = require("../../../base-command");
6
7
  const space_output_1 = require("../../../lib/space-output");
8
+ /**
9
+ * Why a manual run did not start, in words, and whether that is a refusal or just "already busy".
10
+ * The route answers 200 with `fired: false` and a `reason`; printing "Triggered" for it told an
11
+ * owner a run had started when nothing had (a Space with no execution principal never runs).
12
+ * `busy` is the normal "one is already in flight" answer, not a failure.
13
+ */
14
+ function describeRunNotStarted(answer, spaceRef) {
15
+ switch (answer.reason) {
16
+ case 'principal_missing_or_revoked':
17
+ return {
18
+ busy: false,
19
+ message: `Nothing ran: this Space has no active execution principal, so nothing may run unattended in it. ` +
20
+ `A Space owner sets one with \`skrr spaces auto-executor update ${spaceRef} --enabled\`.`,
21
+ };
22
+ case 'no_lead_agent':
23
+ return {
24
+ busy: false,
25
+ message: `Nothing ran: this Space has no lead agent to run its board. ` +
26
+ `Set one with \`skrr spaces update ${spaceRef} --lead-agent <agent-id>\`.`,
27
+ };
28
+ case 'space_not_found':
29
+ return { busy: false, message: `Nothing ran: Space ${spaceRef} was not found.` };
30
+ case 'disabled':
31
+ return {
32
+ busy: false,
33
+ message: `Nothing ran: auto-execution is turned off for this Space. ` +
34
+ `Turn it on with \`skrr spaces auto-executor update ${spaceRef} --enabled\`.`,
35
+ };
36
+ case 'active_orchestration':
37
+ case 'lock_held':
38
+ return {
39
+ busy: true,
40
+ message: `A run is already in flight for this Space${answer.runId ? ` (${answer.runId})` : ''}; ` +
41
+ `it carries this request, so no second one was started.`,
42
+ };
43
+ default:
44
+ return {
45
+ busy: false,
46
+ message: `Nothing ran${answer.reason ? ` (${answer.reason})` : ''}: the server did not start a run.`,
47
+ };
48
+ }
49
+ }
7
50
  class SpacesAutoExecutorRun extends base_command_1.BaseCommand {
8
51
  static description = 'Run a space auto-executor immediately';
9
52
  static args = {
@@ -21,10 +64,25 @@ class SpacesAutoExecutorRun extends base_command_1.BaseCommand {
21
64
  catch (err) {
22
65
  this.handleApiError(err);
23
66
  }
24
- if (flags.json)
67
+ const answer = (result ?? {});
68
+ const notStarted = answer.fired === false ? describeRunNotStarted(answer, spaceRef) : undefined;
69
+ if (flags.json) {
25
70
  this.log(JSON.stringify((0, space_output_1.withSpacePerspectiveUrl)(this.cliConfig.baseURL, spaceRef, 'execution', { result }), null, 2));
26
- else
71
+ // The payload above already says `fired: false`; the exit status says it too, so a
72
+ // script that only checks `$?` is not told a refusal succeeded.
73
+ if (notStarted && !notStarted.busy)
74
+ this.exit(1);
75
+ return;
76
+ }
77
+ if (!notStarted) {
27
78
  this.log(`Triggered auto-executor for space ${spaceRef}.`);
79
+ return;
80
+ }
81
+ if (notStarted.busy) {
82
+ this.log(notStarted.message);
83
+ return;
84
+ }
85
+ this.error(notStarted.message, { exit: 1 });
28
86
  }
29
87
  }
30
88
  exports.default = SpacesAutoExecutorRun;
@@ -1,7 +1,15 @@
1
- import { type SpaceJudgmentTurnRecord } from '@skrr-ai/data-provider';
1
+ import { type SpaceJudgmentTurnRecord, type SpaceOrchestrationRunsResponse } from '@skrr-ai/data-provider';
2
2
  import { BaseCommand } from '../../../base-command';
3
3
  /** Who held the Space's judgment turn at this tick (OSK-18003). */
4
4
  export declare function judgmentTurnLabel(turn?: SpaceJudgmentTurnRecord): string;
5
+ /**
6
+ * The first line of `runs`. The server's `enabled` is "the routine is active", which is false for a
7
+ * board the SYSTEM put to sleep as well as for one its owner turned off, so `runs` printed
8
+ * "Orchestration: disabled" for a sleeping board while `preview` said "enabled (sleeping: …)".
9
+ * Those are different states with different remedies (a task event wakes one; only the owner
10
+ * re-enables the other).
11
+ */
12
+ export declare function orchestrationLine(result: Pick<SpaceOrchestrationRunsResponse, 'enabled' | 'autoExecuteEnabled' | 'lifecycleState' | 'suspensionReason'>): string;
5
13
  export default class SpacesAutoExecutorRuns extends BaseCommand {
6
14
  static description: string;
7
15
  static examples: string[];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.judgmentTurnLabel = judgmentTurnLabel;
4
+ exports.orchestrationLine = orchestrationLine;
4
5
  const core_1 = require("@oclif/core");
5
6
  const data_provider_1 = require("@skrr-ai/data-provider");
6
7
  const base_command_1 = require("../../../base-command");
@@ -16,6 +17,22 @@ function judgmentTurnLabel(turn) {
16
17
  }
17
18
  return ' turn: unreadable, Leader stood down';
18
19
  }
20
+ /**
21
+ * The first line of `runs`. The server's `enabled` is "the routine is active", which is false for a
22
+ * board the SYSTEM put to sleep as well as for one its owner turned off, so `runs` printed
23
+ * "Orchestration: disabled" for a sleeping board while `preview` said "enabled (sleeping: …)".
24
+ * Those are different states with different remedies (a task event wakes one; only the owner
25
+ * re-enables the other).
26
+ */
27
+ function orchestrationLine(result) {
28
+ if (result.autoExecuteEnabled === false)
29
+ return 'Orchestration: disabled (turned off by the owner)';
30
+ if (result.autoExecuteEnabled === true && result.lifecycleState === 'sleeping') {
31
+ const why = result.suspensionReason ? `: ${result.suspensionReason.replace(/_/g, ' ')}` : '';
32
+ return `Orchestration: sleeping${why} — enabled; a task that can start, or \`run\`, wakes it`;
33
+ }
34
+ return `Orchestration: ${result.enabled ? 'enabled' : 'disabled'}`;
35
+ }
19
36
  class SpacesAutoExecutorRuns extends base_command_1.BaseCommand {
20
37
  static description = "List a space's recent auto-orchestration runs and its Lead health";
21
38
  static examples = [
@@ -46,7 +63,7 @@ class SpacesAutoExecutorRuns extends base_command_1.BaseCommand {
46
63
  this.log(JSON.stringify((0, space_output_1.withSpacePerspectiveUrl)(this.cliConfig.baseURL, spaceRef, 'execution', { result }), null, 2));
47
64
  return;
48
65
  }
49
- this.log(`Orchestration: ${result.enabled ? 'enabled' : 'disabled'}`);
66
+ this.log(orchestrationLine(result));
50
67
  this.log(`Lead health: ${result.leadHealth}`);
51
68
  if (result.consecutiveFailures > 0) {
52
69
  this.log(`Failures: ${result.consecutiveFailures} consecutive`);
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const fs = __importStar(require("node:fs"));
37
37
  const path = __importStar(require("node:path"));
38
- const node_buffer_1 = require("node:buffer");
39
38
  const node_crypto_1 = require("node:crypto");
40
39
  const core_1 = require("@oclif/core");
41
40
  const data_provider_1 = require("@skrr-ai/data-provider");
@@ -86,7 +85,7 @@ class SpacesFilesUpload extends base_command_1.BaseCommand {
86
85
  formData.append('spaceId', spaceRef);
87
86
  if (flags.folder)
88
87
  formData.append('folder_id', flags.folder);
89
- formData.append('file', new node_buffer_1.Blob([bytes], { type: (0, file_mime_1.mimeTypeForFilename)(filename) }), filename);
88
+ formData.append('file', new Blob([bytes], { type: (0, file_mime_1.mimeTypeForFilename)(filename) }), filename);
90
89
  let uploaded;
91
90
  try {
92
91
  uploaded = await data_provider_1.dataService.uploadFile(formData);
@@ -8,8 +8,8 @@ const space_output_1 = require("../../../lib/space-output");
8
8
  class SpacesHeartbeatsCreate extends base_command_1.BaseCommand {
9
9
  static description = 'Create a heartbeat for an agent in a space';
10
10
  static examples = [
11
- '<%= config.bin %> spaces heartbeats create <space-id> --agent <agent-id> --frequency "0 9 * * *" --prompt "Good morning"',
12
- '<%= config.bin %> spaces heartbeats create <space-id> --agent <agent-id> --frequency "0 9 * * *" --prompt "Brief" --timezone America/New_York',
11
+ '<%= config.bin %> spaces heartbeats create <space-id> --agent <agent-id> --frequency daily --prompt "Good morning"',
12
+ '<%= config.bin %> spaces heartbeats create <space-id> --agent <agent-id> --frequency 4h --prompt "Brief" --timezone America/New_York',
13
13
  '<%= config.bin %> spaces heartbeats create <space-id> --from-json heartbeat.json',
14
14
  ];
15
15
  static args = {
@@ -21,10 +21,12 @@ class SpacesHeartbeatsCreate extends base_command_1.BaseCommand {
21
21
  description: 'Path to a JSON file (or "-" for stdin) to use as the request body',
22
22
  }),
23
23
  agent: core_1.Flags.string({ description: 'Agent ID (required unless set via --from-json)' }),
24
- frequency: core_1.Flags.string({ description: 'Cron expression for heartbeat frequency' }),
24
+ frequency: core_1.Flags.string({
25
+ description: 'How often it runs, as a ladder key: 1m, 2m, 5m, 10m, 15m, 30m, hourly, 2h, 4h, 8h, daily, 2d, 4d, weekly, 2w. Not a cron expression. The time of day is fixed by the key (daily is 09:00 in --timezone).',
26
+ }),
25
27
  prompt: core_1.Flags.string({ description: 'Prompt sent to the agent on each heartbeat' }),
26
28
  timezone: core_1.Flags.string({
27
- description: 'Timezone for the cron schedule (e.g. America/New_York)',
29
+ description: 'Timezone the schedule runs in (e.g. America/New_York)',
28
30
  }),
29
31
  'max-unread-before-extend': core_1.Flags.integer({
30
32
  description: 'Max unread messages before extending the schedule (1-10)',
@@ -63,7 +65,7 @@ class SpacesHeartbeatsCreate extends base_command_1.BaseCommand {
63
65
  });
64
66
  }
65
67
  if (!payload.frequency || typeof payload.frequency !== 'string') {
66
- this.error('A frequency is required. Pass --frequency <cron> or include it in --from-json.', {
68
+ this.error('A frequency is required. Pass --frequency <key> (for example daily, or 4h) or include it in --from-json.', {
67
69
  exit: 1,
68
70
  });
69
71
  }
@@ -8,7 +8,7 @@ const space_output_1 = require("../../../lib/space-output");
8
8
  class SpacesHeartbeatsUpdate extends base_command_1.BaseCommand {
9
9
  static description = 'Update a heartbeat for an agent in a space';
10
10
  static examples = [
11
- '<%= config.bin %> spaces heartbeats update <space-id> <agent-id> --frequency "0 10 * * *"',
11
+ '<%= config.bin %> spaces heartbeats update <space-id> <agent-id> --frequency weekly',
12
12
  '<%= config.bin %> spaces heartbeats update <space-id> <agent-id> --enabled false',
13
13
  '<%= config.bin %> spaces heartbeats update <space-id> <agent-id> --from-json patch.json',
14
14
  ];
@@ -21,9 +21,11 @@ class SpacesHeartbeatsUpdate extends base_command_1.BaseCommand {
21
21
  'from-json': core_1.Flags.string({
22
22
  description: 'Path to a JSON file (or "-" for stdin) to use as the patch body',
23
23
  }),
24
- frequency: core_1.Flags.string({ description: 'Cron expression for heartbeat frequency' }),
24
+ frequency: core_1.Flags.string({
25
+ description: 'How often it runs, as a ladder key: 1m, 2m, 5m, 10m, 15m, 30m, hourly, 2h, 4h, 8h, daily, 2d, 4d, weekly, 2w. Not a cron expression. The time of day is fixed by the key (daily is 09:00 in --timezone).',
26
+ }),
25
27
  prompt: core_1.Flags.string({ description: 'Prompt sent to the agent on each heartbeat' }),
26
- timezone: core_1.Flags.string({ description: 'Timezone for the cron schedule' }),
28
+ timezone: core_1.Flags.string({ description: 'Timezone the schedule runs in' }),
27
29
  enabled: core_1.Flags.boolean({ description: 'Enable or disable the heartbeat', allowNo: true }),
28
30
  'max-unread-before-extend': core_1.Flags.integer({
29
31
  description: 'Max unread messages before extending (1-10)',