@skrr-ai/cli 0.1.130 → 0.1.132

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.
@@ -454,7 +454,7 @@
454
454
  "id": "speaking",
455
455
  "title": "A Commitment finds; its Agent speaks",
456
456
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
457
- "tokens": 263,
457
+ "tokens": 301,
458
458
  "aliases": [],
459
459
  "explains": []
460
460
  },
@@ -709,7 +709,7 @@
709
709
  ]
710
710
  }
711
711
  ],
712
- "hash": "6d23de37b320e5257e7e2400c36bfc79063c76c2e3984771b96a90727e95980d",
712
+ "hash": "74f6b87c1bd1f851fbfe0b1ee5da04425d1b6fdafbf55445a39e121af9c4e65b",
713
713
  "tokens": 545
714
714
  },
715
715
  "routedIndex": {
@@ -1167,7 +1167,7 @@
1167
1167
  "id": "speaking",
1168
1168
  "title": "A Commitment finds; its Agent speaks",
1169
1169
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
1170
- "tokens": 263,
1170
+ "tokens": 301,
1171
1171
  "aliases": [],
1172
1172
  "explains": []
1173
1173
  },
@@ -1353,7 +1353,7 @@
1353
1353
  ]
1354
1354
  }
1355
1355
  ],
1356
- "hash": "c7cd104ee736aa524b486eb8858dce17a2de5f69036c7c61795ce5603ce1246e",
1356
+ "hash": "6960740319e60127c5a1007fd32e77afada0b14442b5f6fb810a7fee1407cb63",
1357
1357
  "tokens": 494
1358
1358
  },
1359
1359
  "cards": {
@@ -1747,7 +1747,7 @@
1747
1747
  "routed": true,
1748
1748
  "aliases": [],
1749
1749
  "body": "## Concept model\n\n| Noun | Question it answers |\n| --- | --- |\n| **Compass** | What does good look like for this Agent, and what may it never trade away? |\n| **Northstar** | Which Commitments should exist, at what priority and on what budget? |\n| **Commitment** | Which outcome does this Agent keep true, and how does it keep checking? |\n| **Check** | What did one wake of a Commitment see, decide and do? |\n\nA Commitment is not a unit of work. A **Task** is one unit of work and a **Goal** is a dated\noutcome with key results; a Commitment watches both and may create Tasks, and is neither.\n\n## Decide\n\nFive mechanisms make something happen later, and the noun alone does not pick one:\n\n| Mechanism | What it is for | The signal that picks it |\n| --- | --- | --- |\n| **Follow-up** | Coming back to one thing, once or a bounded few times: a reminder, a watch, a check-in, an agreed action | The ask ends: \"look tomorrow\", \"tell me when CI is green\" |\n| **Trigger** | Running the Agent with a set prompt on a schedule, an event, once, or on demand | The person names when, and every run does the same work |\n| **Heartbeat** | Checking in on a conversation, group chat or Space at a frequency that backs off while unread | The person wants regular contact, not an outcome held |\n| **Commitment** | Keeping an outcome true: watched sources, a cadence and a loop that decides when to act | \"Keep X true\", \"watch this metric\": no end, and stale evidence matters |\n| **Workflow** | Running a durable graph of Tasks in order | Repeatable work whose steps depend on each other |\n\nA one-off \"look at it tomorrow\" is a follow-up, never a Commitment. Standing observation is a\nCommitment with a freshness contract, not a recurring trigger or a task board left running.\n\n## Workflow\n\n### Start a Commitment\n\n1. Read the Agent's Commitments first, and change one rather than add a near-duplicate.\n2. Create it and turn it on in one call: the outcome, what it watches, how often it checks, where\n its work goes. Turning it on runs Preflight; a refusal keeps the draft and reports the code,\n reason and fix.\n3. Leave it a draft only when the person asked to see it first.\n4. Read it back, and tell the person what it watches, how often, and whether it is on.\n\n## Authority\n\n| Actor | May do | Only a person may do |\n| --- | --- | --- |\n| Agent | Read the Commitments of an Agent it can view; create one, change it and turn it on; request a check; pause one; decide whether a finding is worth telling the owner | Lift a stop a person made; set or clear a concurrency limit; choose the Task review policy; approve an action proposal or a cadence change; configure a Northstar's governance or decide its intents |\n| Person | Everything in both columns | — |\n\nA Commitment grants no permission: its runs work under the Agent's own. A Check never writes an\nowner-facing message, and a Compass never creates, rewrites, pauses or archives a Commitment. The\nserver cannot always tell an Agent from the person whose login it holds, so an accepted call is\nnot permission: the right-hand column stays a person's.\n\n## Live state\n\n- `skrr commitments list --agent <agent-id>` — an Agent's Commitments, with status and assessment.\n- `skrr commitments show <commitment-id>` — the contract, its next check and the last one.\n- `skrr commitments roster --agent <agent-id>` — each loop: whether it is armed, its next wake, runs today.\n\n## Related guides\n\n- `tasks` — the Tasks a Commitment creates or watches.\n- `spaces` — Goals, and Workflows: durable graphs of Tasks.\n- `agents` — the Agent a Commitment belongs to, and where its runs execute.\n- `communication` — whether, what and how to tell the owner.",
1750
- "hash": "8a5ab2048ea5a6edacd881d4403a3481798876b4529f8a070d4953eebebd075f",
1750
+ "hash": "197d9b84d1a4367ecf4b7a51687604d13814ec9e9265fe662883278a7738d2fa",
1751
1751
  "tokens": 1169,
1752
1752
  "sections": [
1753
1753
  {
@@ -1824,7 +1824,7 @@
1824
1824
  "id": "speaking",
1825
1825
  "title": "A Commitment finds; its Agent speaks",
1826
1826
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
1827
- "tokens": 263,
1827
+ "tokens": 301,
1828
1828
  "aliases": [],
1829
1829
  "explains": []
1830
1830
  },
@@ -5850,7 +5850,7 @@
5850
5850
  "id": "speaking",
5851
5851
  "title": "A Commitment finds; its Agent speaks",
5852
5852
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
5853
- "tokens": 263,
5853
+ "tokens": 301,
5854
5854
  "aliases": [],
5855
5855
  "explains": []
5856
5856
  },
@@ -5966,7 +5966,7 @@
5966
5966
  "id": "speaking",
5967
5967
  "title": "A Commitment finds; its Agent speaks",
5968
5968
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
5969
- "tokens": 263,
5969
+ "tokens": 301,
5970
5970
  "aliases": [],
5971
5971
  "explains": []
5972
5972
  },
@@ -6084,7 +6084,7 @@
6084
6084
  "id": "speaking",
6085
6085
  "title": "A Commitment finds; its Agent speaks",
6086
6086
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6087
- "tokens": 263,
6087
+ "tokens": 301,
6088
6088
  "aliases": [],
6089
6089
  "explains": []
6090
6090
  },
@@ -6206,7 +6206,7 @@
6206
6206
  "id": "speaking",
6207
6207
  "title": "A Commitment finds; its Agent speaks",
6208
6208
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6209
- "tokens": 263,
6209
+ "tokens": 301,
6210
6210
  "aliases": [],
6211
6211
  "explains": []
6212
6212
  },
@@ -6322,7 +6322,7 @@
6322
6322
  "id": "speaking",
6323
6323
  "title": "A Commitment finds; its Agent speaks",
6324
6324
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6325
- "tokens": 263,
6325
+ "tokens": 301,
6326
6326
  "aliases": [],
6327
6327
  "explains": []
6328
6328
  },
@@ -6438,7 +6438,7 @@
6438
6438
  "id": "speaking",
6439
6439
  "title": "A Commitment finds; its Agent speaks",
6440
6440
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6441
- "tokens": 263,
6441
+ "tokens": 301,
6442
6442
  "aliases": [],
6443
6443
  "explains": []
6444
6444
  },
@@ -6560,7 +6560,7 @@
6560
6560
  "id": "speaking",
6561
6561
  "title": "A Commitment finds; its Agent speaks",
6562
6562
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6563
- "tokens": 263,
6563
+ "tokens": 301,
6564
6564
  "aliases": [],
6565
6565
  "explains": []
6566
6566
  },
@@ -6598,9 +6598,9 @@
6598
6598
  "version": 4,
6599
6599
  "aliases": [],
6600
6600
  "explains": [],
6601
- "body": "Read this when a Commitment run found something and you must decide whether the owner hears of it.\n\nA Check never writes to the owner. When something it found may matter, the run is handed a brief\nunder \"Owner communication — your call.\": what was found, the evidence, why it may matter and a\nsuggested next step. Those are facts to judge, not a message to forward.\n\n- Decide with everything in view: what you already said, whether the owner replied, what another\n surface already raised. One message, a different message or nothing are all valid outcomes, and\n silence is often the right one.\n- To speak from the run, return a `message` or `status_update` action intent with its `text`, or a\n `report` with its `text` for the Commitment's report destinations. Write the words yourself.\n- The owner's limits (mute, quiet hours, a daily nudge cap) decide whether a run is asked to speak\n at all, and whatever you deliver counts against them, whichever way you send it.\n\n`skrr commitments reports <commitment-id>` lists where its reports go and on what condition; the\ndefault sends only on a material change.",
6602
- "hash": "f208f179f96c5f52058be9b4870b2591ef022e658745a7f3e44779bbde87ca10",
6603
- "tokens": 263,
6601
+ "body": "Read this when a Commitment run found something and you must decide whether the owner hears of it.\n\nA Check never writes to the owner. When something it found may matter, the run is handed a brief\nunder \"Owner communication — your call.\": what was found, the evidence, why it may matter and a\nsuggested next step. Those are facts to judge, not a message to forward.\n\n- Decide with everything in view: what you already said, whether the owner replied, what another\n surface already raised. One message, a different message or nothing are all valid outcomes, and\n silence is often the right one.\n- To speak from the run, send it with `skrr agent message send` where the run allows it: it is\n delivered under the owner's limits and counted for this Commitment. Otherwise return a\n `status_update` or `report` action intent with its `text` for the Commitment's report\n destinations. A `message` action intent is recorded but never delivered. Write the words yourself.\n- The owner's limits (mute, quiet hours, a daily nudge cap) decide whether a run is asked to speak\n at all, and whatever you deliver counts against them, whichever way you send it.\n\n`skrr commitments reports <commitment-id>` lists where its reports go and on what condition; the\ndefault sends only on a material change.",
6602
+ "hash": "45fa02a0344903cc355dff0b66eee45b14dab79a8f62fba8620106b29e11e8a9",
6603
+ "tokens": 301,
6604
6604
  "sections": [
6605
6605
  {
6606
6606
  "id": "model",
@@ -6676,7 +6676,7 @@
6676
6676
  "id": "speaking",
6677
6677
  "title": "A Commitment finds; its Agent speaks",
6678
6678
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6679
- "tokens": 263,
6679
+ "tokens": 301,
6680
6680
  "aliases": [],
6681
6681
  "explains": []
6682
6682
  },
@@ -6796,7 +6796,7 @@
6796
6796
  "id": "speaking",
6797
6797
  "title": "A Commitment finds; its Agent speaks",
6798
6798
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6799
- "tokens": 263,
6799
+ "tokens": 301,
6800
6800
  "aliases": [],
6801
6801
  "explains": []
6802
6802
  },
@@ -6914,7 +6914,7 @@
6914
6914
  "id": "speaking",
6915
6915
  "title": "A Commitment finds; its Agent speaks",
6916
6916
  "readWhen": "a Commitment run found something and you must decide whether the owner hears of it",
6917
- "tokens": 263,
6917
+ "tokens": 301,
6918
6918
  "aliases": [],
6919
6919
  "explains": []
6920
6920
  },
@@ -75,9 +75,10 @@ function forwardedFlagsNote(verb, opts = {}) {
75
75
  // daemon cannot silently end up on a different deployment than the CLI that
76
76
  // installed it (OSK-279). Saying so is the difference between a flag you may
77
77
  // pass and a flag that is already being passed for you.
78
+ const help = `${base} If \`skrrd\` is not on your PATH, use its installed path instead (typically \`~/.skrr/bin/skrrd\` on macOS and Linux).`;
78
79
  return opts.binds
79
- ? `${base} \`--server\` and \`--profile\` are filled in from your CLI session unless you pass them.`
80
- : base;
80
+ ? `${help} \`--server\` and \`--profile\` are filled in from your CLI session unless you pass them.`
81
+ : help;
81
82
  }
82
83
  /** Extra well-known install locations for one runtime name, checked after PATH. */
83
84
  function fallbackPathsForRuntime(name) {
@@ -243,7 +243,7 @@ export declare function forgetHarness(id: string): Promise<unknown>;
243
243
  * server (`pruneSupersededHarnesses.js`, `REASONS`) and worded once, in
244
244
  * `harnessPruneReasonSentence`, so the table and `--json` never disagree.
245
245
  */
246
- export type HarnessPruneReason = 'recent' | 'latest_registration' | 'no_live_sibling' | 'pinned' | 'granted' | 'default' | 'aliased' | 'changed_since_plan';
246
+ export type HarnessPruneReason = 'recent' | 'latest_registration' | 'no_live_sibling' | 'has_usage' | 'pinned' | 'granted' | 'default' | 'aliased' | 'changed_since_plan';
247
247
  export interface HarnessPruneRow {
248
248
  id: string;
249
249
  daemonId: string | null;
@@ -257,6 +257,8 @@ export interface HarnessPruneRow {
257
257
  daemonId: string | null;
258
258
  lastSeenAt: string | null;
259
259
  };
260
+ /** The gone lease a row this call removes (or would) belonged to (`--include-gone-leases`). */
261
+ goneLease?: string;
260
262
  /** Set on kept rows. */
261
263
  reason?: HarnessPruneReason;
262
264
  /** For `pinned`: who holds the pin. Other people's agents are a count, never named. */
@@ -300,6 +302,7 @@ export declare function pruneHarnesses(options?: {
300
302
  dryRun: boolean;
301
303
  limit?: number;
302
304
  minUnseenMs?: number;
305
+ includeGoneLeases?: boolean;
303
306
  }): Promise<HarnessPruneResult>;
304
307
  /**
305
308
  * `--older-than` takes a whole number with a unit: `90m`, `36h`, `7d`. A bare
@@ -192,6 +192,7 @@ async function pruneHarnesses(options = { dryRun: true }) {
192
192
  dryRun: options.dryRun,
193
193
  ...(options.limit !== undefined ? { limit: options.limit } : {}),
194
194
  ...(options.minUnseenMs !== undefined ? { minUnseenMs: options.minUnseenMs } : {}),
195
+ ...(options.includeGoneLeases ? { includeGoneLeases: true } : {}),
195
196
  },
196
197
  });
197
198
  }
@@ -219,6 +220,8 @@ function harnessPruneReasonSentence(row) {
219
220
  return 'the newest registration of its provider on that machine';
220
221
  case 'no_live_sibling':
221
222
  return 'nothing has replaced it - no daemon on that machine is online for this provider';
223
+ case 'has_usage':
224
+ return 'usage is recorded against it, so the row keeps the name that usage is attributed to';
222
225
  case 'pinned': {
223
226
  const names = (row.detail?.agents ?? []).map((a) => a.name ?? a.id);
224
227
  const more = row.detail?.moreAgents ?? 0;
@@ -68,6 +68,11 @@ export interface SmartScheduleProposal {
68
68
  truncated: boolean;
69
69
  };
70
70
  todos: ProposedTodo[];
71
+ nextRunSuggestion?: {
72
+ runAt: string;
73
+ reason?: string;
74
+ confidence?: number;
75
+ };
71
76
  /**
72
77
  * Agent-scope trigger budget at proposal time. Advisory — approval enforces
73
78
  * it for real — but it is the difference between a warning the user can act
@@ -105,6 +110,12 @@ export interface ApproveSmartScheduleResponse {
105
110
  }>;
106
111
  /** Post-write budget, so a caller approving several plans sees the wall coming. */
107
112
  capacity?: TriggerCapacity;
113
+ scheduledNextRun?: {
114
+ created?: boolean;
115
+ triggerId?: string;
116
+ skippedReason?: string;
117
+ message?: string;
118
+ } | null;
108
119
  }
109
120
  /**
110
121
  * The self-schedule TRACE — why the agent's day looks the way it does.
@@ -145,6 +156,8 @@ export interface ScheduleTrace {
145
156
  has_more?: boolean;
146
157
  next_cursor?: string | null;
147
158
  }
159
+ /** Calendar day at an instant in the zone used for the schedule query. */
160
+ export declare function scheduleTraceToday(now: Date, timezone: string): string;
148
161
  export declare function scheduleTracePath(params: {
149
162
  agentId: string;
150
163
  date: string;
@@ -163,7 +176,7 @@ export declare const scheduleApi: {
163
176
  limit?: number;
164
177
  cursor?: string;
165
178
  }) => Promise<ScheduleTrace>;
166
- listTodos: (agentId: string, date?: string) => Promise<ListTodosResponse>;
179
+ listTodos: (agentId: string, date?: string, timezone?: string) => Promise<ListTodosResponse>;
167
180
  getTodo: (todoId: string) => Promise<Todo>;
168
181
  createTodo: (input: CreateTodoInput) => Promise<Todo>;
169
182
  /** Cancel a To-Do (DELETE soft-cancels pending; see todos.js). */
@@ -171,6 +184,7 @@ export declare const scheduleApi: {
171
184
  proposeSmartSchedule: (input: {
172
185
  agentId: string;
173
186
  workingHoursOverride?: WorkingHoursWindow;
187
+ timezone?: string;
174
188
  regenerateHint?: string;
175
189
  }) => Promise<SmartScheduleProposal>;
176
190
  pendingProposal: (agentId: string) => Promise<{
@@ -180,6 +194,7 @@ export declare const scheduleApi: {
180
194
  agentId: string;
181
195
  proposalId: string;
182
196
  todos: ApproveTodoInput[];
197
+ approveNextRunSuggestion?: boolean;
183
198
  saveHoursAsDefault?: boolean;
184
199
  workingHours?: WorkingHoursWindow;
185
200
  }) => Promise<ApproveSmartScheduleResponse>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.scheduleApi = void 0;
4
+ exports.scheduleTraceToday = scheduleTraceToday;
4
5
  exports.scheduleTracePath = scheduleTracePath;
5
6
  exports.isSmartScheduleProposal = isSmartScheduleProposal;
6
7
  exports.describeNonProposal = describeNonProposal;
@@ -29,6 +30,17 @@ exports.proposalToApproveTodos = proposalToApproveTodos;
29
30
  const data_provider_1 = require("@skrr-ai/data-provider");
30
31
  const format_1 = require("./format");
31
32
  const triggers_1 = require("./triggers");
33
+ /** Calendar day at an instant in the zone used for the schedule query. */
34
+ function scheduleTraceToday(now, timezone) {
35
+ const parts = new Intl.DateTimeFormat('en-CA', {
36
+ timeZone: timezone,
37
+ year: 'numeric',
38
+ month: '2-digit',
39
+ day: '2-digit',
40
+ }).formatToParts(now);
41
+ const part = (type) => parts.find((item) => item.type === type)?.value;
42
+ return `${part('year')}-${part('month')}-${part('day')}`;
43
+ }
32
44
  function scheduleTracePath(params) {
33
45
  return (0, triggers_1.withQuery)('/api/todos/smart-schedule/trace', {
34
46
  agentId: params.agentId,
@@ -40,13 +52,13 @@ function scheduleTracePath(params) {
40
52
  });
41
53
  }
42
54
  /** Build the `/api/todos` list query — agentId is required, date optional. */
43
- function todoListPath(agentId, date) {
44
- return (0, triggers_1.withQuery)('/api/todos', { agentId, date });
55
+ function todoListPath(agentId, date, timezone) {
56
+ return (0, triggers_1.withQuery)('/api/todos', { agentId, date, timezone });
45
57
  }
46
58
  exports.scheduleApi = {
47
59
  /** The self-schedule trace for one agent-day. See `scheduleTracePath`. */
48
60
  scheduleTrace: (params) => data_provider_1.request.get(scheduleTracePath(params)),
49
- listTodos: (agentId, date) => data_provider_1.request.get(todoListPath(agentId, date)),
61
+ listTodos: (agentId, date, timezone) => data_provider_1.request.get(todoListPath(agentId, date, timezone)),
50
62
  getTodo: (todoId) => data_provider_1.request.get(`/api/todos/${encodeURIComponent(todoId)}`),
51
63
  createTodo: (input) => data_provider_1.request.post('/api/todos', input),
52
64
  /** Cancel a To-Do (DELETE soft-cancels pending; see todos.js). */
@@ -150,6 +162,9 @@ function renderProposal(proposal, log) {
150
162
  if (proposal.expiresAt)
151
163
  log(`Expires: ${formatStamp(proposal.expiresAt)}`);
152
164
  renderCapacityWarning(proposal.capacity, log);
165
+ if (proposal.nextRunSuggestion) {
166
+ log(`Next run: ${formatStamp(proposal.nextRunSuggestion.runAt)}${proposal.nextRunSuggestion.reason ? ` · ${proposal.nextRunSuggestion.reason}` : ''}`);
167
+ }
153
168
  log('');
154
169
  const live = proposal.todos.filter((t) => !t.dropped);
155
170
  if (live.length === 0) {