@skrr-ai/cli 0.1.133 → 0.1.135

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.
@@ -64,6 +64,7 @@ export interface SmartScheduleProposal {
64
64
  workingHours: WorkingHoursWindow;
65
65
  contextSummary: {
66
66
  spaceName?: string;
67
+ taskScope?: 'lead_space' | 'no_lead_space' | 'unavailable';
67
68
  goalCount: number;
68
69
  openTaskCount: number;
69
70
  truncated: boolean;
@@ -227,6 +228,10 @@ export declare function isSmartScheduleProposal(value: unknown): value is SmartS
227
228
  * HTML error page, and dumping it into the user's terminal helps nobody.
228
229
  */
229
230
  export declare function describeNonProposal(value: unknown): string;
231
+ /** Explain terminal policy outcomes without changing the machine-readable status. */
232
+ export declare function todoPolicyBlockMessage(reason?: string): string | undefined;
233
+ /** Print explanations alongside the trace rows that recorded policy blocks. */
234
+ export declare function renderTodoPolicyTraceDetails(events: ScheduleTraceEvent[], log: (line: string) => void): void;
230
235
  /** Render a To-Do list as a table. */
231
236
  export declare function renderTodoList(todos: Todo[], log: (line: string) => void): void;
232
237
  /**
@@ -5,6 +5,8 @@ exports.scheduleTraceToday = scheduleTraceToday;
5
5
  exports.scheduleTracePath = scheduleTracePath;
6
6
  exports.isSmartScheduleProposal = isSmartScheduleProposal;
7
7
  exports.describeNonProposal = describeNonProposal;
8
+ exports.todoPolicyBlockMessage = todoPolicyBlockMessage;
9
+ exports.renderTodoPolicyTraceDetails = renderTodoPolicyTraceDetails;
8
10
  exports.renderTodoList = renderTodoList;
9
11
  exports.renderCapacityWarning = renderCapacityWarning;
10
12
  exports.renderProposal = renderProposal;
@@ -106,6 +108,27 @@ function describeNonProposal(value) {
106
108
  const keys = Object.keys(value);
107
109
  return keys.length === 0 ? 'empty object' : `object with keys: ${keys.slice(0, 8).join(', ')}`;
108
110
  }
111
+ /** Explain terminal policy outcomes without changing the machine-readable status. */
112
+ function todoPolicyBlockMessage(reason) {
113
+ switch (reason) {
114
+ case 'inside_quiet_hours':
115
+ return 'Not run: this time was inside the trigger’s quiet hours. Create a new To-Do to try again.';
116
+ case 'outside_working_hours':
117
+ return 'Not run: this time was outside the trigger’s working hours. Create a new To-Do to try again.';
118
+ default:
119
+ return undefined;
120
+ }
121
+ }
122
+ /** Print explanations alongside the trace rows that recorded policy blocks. */
123
+ function renderTodoPolicyTraceDetails(events, log) {
124
+ for (const event of events) {
125
+ const message = event.type === 'todo_execution_failed'
126
+ ? todoPolicyBlockMessage(event.reason)
127
+ : undefined;
128
+ if (message)
129
+ log(` ${event.id ?? event.summary ?? 'To-Do'}: ${message}`);
130
+ }
131
+ }
109
132
  /** Render a To-Do list as a table. */
110
133
  function renderTodoList(todos, log) {
111
134
  if (todos.length === 0) {
@@ -127,6 +150,11 @@ function renderTodoList(todos, log) {
127
150
  { key: 'source', header: 'SOURCE' },
128
151
  { key: 'id', header: 'ID', verbatim: true },
129
152
  ], log);
153
+ for (const todo of todos) {
154
+ const message = todo.status === 'failed' ? todoPolicyBlockMessage(todo.result?.errorMessage) : undefined;
155
+ if (message)
156
+ log(` ${todo.id}: ${message}`);
157
+ }
130
158
  }
131
159
  /**
132
160
  * Warn at REVIEW time when approving this plan is likely to hit the wall.
@@ -160,6 +188,14 @@ function renderProposal(proposal, log) {
160
188
  const ctx = proposal.contextSummary;
161
189
  log(`Context: ${ctx.openTaskCount} open task(s), ${ctx.goalCount} goal(s)` +
162
190
  `${ctx.spaceName ? ` · ${ctx.spaceName}` : ''}${ctx.truncated ? ' (truncated)' : ''}`);
191
+ const taskScope = ctx.taskScope === 'lead_space'
192
+ ? 'Tasks were checked only in the lead Space; assigned tasks in other Spaces were not checked.'
193
+ : ctx.taskScope === 'no_lead_space'
194
+ ? 'No lead Space was found; assigned tasks in other Spaces were not checked.'
195
+ : ctx.taskScope === 'unavailable'
196
+ ? 'Task context was unavailable; the count may be incomplete.'
197
+ : 'Task search scope was not recorded for this proposal.';
198
+ log(`Task scope: ${taskScope}`);
163
199
  if (proposal.expiresAt)
164
200
  log(`Expires: ${formatStamp(proposal.expiresAt)}`);
165
201
  renderCapacityWarning(proposal.capacity, log);
@@ -170,6 +170,8 @@ export interface TriggerFireRecord {
170
170
  durationMs?: number;
171
171
  finalizedAt?: string;
172
172
  metadata?: {
173
+ recordKind?: string;
174
+ afterOccurrenceId?: string;
173
175
  replayable?: boolean;
174
176
  replayBlockedReason?: string;
175
177
  replayRequirements?: string[];
@@ -612,6 +614,10 @@ export declare const triggerApi: {
612
614
  get: (id: string) => Promise<TriggerDefinition>;
613
615
  update: (id: string, body: Record<string, unknown>) => Promise<TriggerDefinition>;
614
616
  setEnabled: (id: string, enabled: boolean) => Promise<TriggerDefinition>;
617
+ setAuthorizationRevoked: (id: string, revoked: boolean) => Promise<{
618
+ ok: boolean;
619
+ authorization?: Record<string, unknown>;
620
+ }>;
615
621
  delete: (id: string) => Promise<string>;
616
622
  fire: (id: string, body: Record<string, unknown>) => Promise<Record<string, unknown>>;
617
623
  /**
@@ -651,6 +657,17 @@ export declare const triggerApi: {
651
657
  agentId?: string;
652
658
  spaceId?: string;
653
659
  }) => Promise<TriggerQuotaStatus>;
660
+ prunePreview: (params: {
661
+ scope?: string;
662
+ agentId?: string;
663
+ spaceId?: string;
664
+ limit?: number;
665
+ }) => Promise<{
666
+ dryRun: true;
667
+ ownerWide: boolean;
668
+ wouldDelete: number;
669
+ ids: string[];
670
+ }>;
654
671
  /** Soft-delete the DISABLED triggers in a scope. Requires `confirm: true`. */
655
672
  prune: (body: {
656
673
  scope?: string;
@@ -1534,7 +1534,9 @@ function renderFireAudit(fires, log) {
1534
1534
  firedAt: fire.firedAt ?? '-',
1535
1535
  outcome: fire.outcome ?? '-',
1536
1536
  source: fire.source ?? '-',
1537
- reason: fire.reason ?? fire.errorMessage ?? '',
1537
+ reason: fire.metadata?.recordKind === 'schedule_end_marker'
1538
+ ? 'Schedule ended after prior fire'
1539
+ : fire.reason ?? fire.errorMessage ?? '',
1538
1540
  duration: fire.durationMs === undefined ? '-' : `${fire.durationMs}ms`,
1539
1541
  replay: fire.metadata?.replayable === true || fire.metadata?.replayContext
1540
1542
  ? 'yes'
@@ -1561,6 +1563,7 @@ exports.triggerApi = {
1561
1563
  setEnabled: (id, enabled) => data_provider_1.request.patch(`/api/triggers/${encodeURIComponent(id)}/enabled`, {
1562
1564
  enabled,
1563
1565
  }),
1566
+ setAuthorizationRevoked: (id, revoked) => data_provider_1.request.patch(`/api/triggers/${encodeURIComponent(id)}/authorization`, { revoked }),
1564
1567
  delete: (id) => data_provider_1.request.delete(`/api/triggers/${encodeURIComponent(id)}`),
1565
1568
  fire: (id, body) => data_provider_1.request.post(`/api/triggers/${encodeURIComponent(id)}/fire-now`, body),
1566
1569
  /**
@@ -1597,6 +1600,7 @@ exports.triggerApi = {
1597
1600
  * companion to `prune` — see `TriggerQuotaStatus`.
1598
1601
  */
1599
1602
  quota: (params) => data_provider_1.request.get(withQuery('/api/triggers/quota', params)),
1603
+ prunePreview: (params) => data_provider_1.request.get(withQuery('/api/triggers/prune/preview', params)),
1600
1604
  /** Soft-delete the DISABLED triggers in a scope. Requires `confirm: true`. */
1601
1605
  prune: (body) => data_provider_1.request.post('/api/triggers/prune', { ...body, confirm: true }),
1602
1606
  capabilities: (scope) => data_provider_1.request.get(`/api/triggers/scope-capabilities?scope=${encodeURIComponent(scope)}`),