@skrr-ai/cli 0.1.101 → 0.1.103

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 (91) hide show
  1. package/dist/base-command.js +24 -0
  2. package/dist/commands/agent/message/send.js +6 -2
  3. package/dist/commands/agents/triggers/create.js +7 -17
  4. package/dist/commands/agents/triggers/update.js +41 -28
  5. package/dist/commands/commitments/control/apply.d.ts +15 -0
  6. package/dist/commands/commitments/control/apply.js +36 -0
  7. package/dist/commands/commitments/control/preview.d.ts +17 -0
  8. package/dist/commands/commitments/control/preview.js +43 -0
  9. package/dist/commands/commitments/control/show.d.ts +12 -0
  10. package/dist/commands/commitments/control/show.js +29 -0
  11. package/dist/commands/commitments/create.js +5 -2
  12. package/dist/commands/commitments/observation/probe.d.ts +15 -0
  13. package/dist/commands/commitments/observation/probe.js +46 -0
  14. package/dist/commands/commitments/observation/summary.d.ts +9 -0
  15. package/dist/commands/commitments/observation/summary.js +31 -0
  16. package/dist/commands/commitments/preflight.js +18 -1
  17. package/dist/commands/commitments/readiness/show.d.ts +12 -0
  18. package/dist/commands/commitments/readiness/show.js +29 -0
  19. package/dist/commands/commitments/readiness/verify.d.ts +13 -0
  20. package/dist/commands/commitments/readiness/verify.js +33 -0
  21. package/dist/commands/commitments/roster.d.ts +15 -0
  22. package/dist/commands/commitments/roster.js +39 -0
  23. package/dist/commands/commitments/show.js +1 -1
  24. package/dist/commands/commitments/status.d.ts +17 -0
  25. package/dist/commands/commitments/status.js +41 -0
  26. package/dist/commands/commitments/update.js +23 -9
  27. package/dist/commands/commitments/work-plan.d.ts +11 -0
  28. package/dist/commands/commitments/work-plan.js +36 -0
  29. package/dist/commands/compass/effective-policy.d.ts +12 -0
  30. package/dist/commands/compass/effective-policy.js +34 -0
  31. package/dist/commands/compass/update.d.ts +12 -0
  32. package/dist/commands/compass/update.js +27 -0
  33. package/dist/commands/daemon/logs.d.ts +39 -1
  34. package/dist/commands/daemon/logs.js +140 -13
  35. package/dist/commands/followups/checkin.js +46 -3
  36. package/dist/commands/machines/dedicated/exec.js +3 -1
  37. package/dist/commands/proposals/discard.d.ts +4 -0
  38. package/dist/commands/proposals/discard.js +3 -0
  39. package/dist/commands/proposals/keep.d.ts +4 -0
  40. package/dist/commands/proposals/keep.js +3 -0
  41. package/dist/commands/proposals/snooze.d.ts +4 -0
  42. package/dist/commands/proposals/snooze.js +3 -0
  43. package/dist/commands/spaces/workflows/cancel-node.d.ts +16 -0
  44. package/dist/commands/spaces/workflows/cancel-node.js +44 -0
  45. package/dist/commands/spaces/workflows/cancel.d.ts +40 -0
  46. package/dist/commands/spaces/workflows/cancel.js +109 -3
  47. package/dist/commands/spaces/workflows/run.d.ts +9 -0
  48. package/dist/commands/spaces/workflows/run.js +38 -0
  49. package/dist/commands/tasks/approvals/resolve.d.ts +12 -0
  50. package/dist/commands/tasks/approvals/resolve.js +21 -5
  51. package/dist/commands/tasks/schedule.js +1 -1
  52. package/dist/commands/triggers/capabilities.js +7 -0
  53. package/dist/commands/triggers/create.js +12 -18
  54. package/dist/commands/triggers/fire.js +3 -0
  55. package/dist/commands/triggers/update.js +41 -27
  56. package/dist/commands/widgets/check.d.ts +39 -0
  57. package/dist/commands/widgets/check.js +179 -0
  58. package/dist/lib/agent-mailbox.d.ts +0 -1
  59. package/dist/lib/agent-mailbox.js +0 -1
  60. package/dist/lib/commitment-loop-status.d.ts +16 -0
  61. package/dist/lib/commitment-loop-status.js +164 -0
  62. package/dist/lib/commitments.d.ts +47 -1
  63. package/dist/lib/commitments.js +218 -6
  64. package/dist/lib/compasses.d.ts +3 -0
  65. package/dist/lib/compasses.js +1 -0
  66. package/dist/lib/delegated-cli.d.ts +23 -1
  67. package/dist/lib/delegated-cli.js +61 -4
  68. package/dist/lib/first-party-harness.d.ts +1 -1
  69. package/dist/lib/first-party-harness.js +1 -1
  70. package/dist/lib/responsibility-controls.d.ts +11 -0
  71. package/dist/lib/responsibility-controls.js +119 -0
  72. package/dist/lib/session-task-write.d.ts +13 -0
  73. package/dist/lib/session-task-write.js +63 -3
  74. package/dist/lib/stewardship-output.js +13 -2
  75. package/dist/lib/triggers.d.ts +26 -0
  76. package/dist/lib/triggers.js +134 -1
  77. package/dist/lib/widgetCheck.d.ts +123 -0
  78. package/dist/lib/widgetCheck.js +998 -0
  79. package/dist/lib/widgetStaticScan.d.ts +111 -0
  80. package/dist/lib/widgetStaticScan.js +833 -0
  81. package/dist/lib/workflow-node-control.d.ts +10 -0
  82. package/dist/lib/workflow-node-control.js +76 -0
  83. package/dist/lib/workspaces.d.ts +2 -0
  84. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +9 -1
  85. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +12 -0
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +9 -1
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +12 -0
  88. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  89. package/dist/node_modules/@skrr-ai/data-provider/index.js +11924 -8704
  90. package/oclif.manifest.json +1487 -396
  91. package/package.json +11 -2
@@ -261,6 +261,30 @@ class BaseCommand extends core_1.Command {
261
261
  this.credentialProvenance = { kind: 'daemon-delegated' };
262
262
  }
263
263
  catch (err) {
264
+ // OSK-15990 — a refusal only a new daemon sign-in repairs (e.g.
265
+ // DEVICE_PROOF_PIN_MISMATCH) is NOT retryable: exit 75 told every
266
+ // caller to loop on it. Say so, and say what to run.
267
+ // Matched by name, not instanceof: specs mock `./lib/delegated-cli`
268
+ // down to one or two functions, and a missing class would throw here.
269
+ if (err?.name === 'DelegatedCliUnavailableError') {
270
+ const e = err;
271
+ const remedy = e.remedy && !e.message.includes(e.remedy) ? ` Fix: ${e.remedy}` : '';
272
+ this.failWithCliError({
273
+ message: `Daemon delegated skrr credential is unavailable: ${e.message}${remedy}`,
274
+ code: 'DELEGATED_CLI_CREDENTIAL_UNAVAILABLE',
275
+ // 75 (EX_TEMPFAIL) only when waiting can help; 77 (EX_NOPERM) when
276
+ // the daemon must be signed in again first.
277
+ exit: e.retryable ? 75 : 77,
278
+ retryable: e.retryable,
279
+ details: {
280
+ ...(e.upstreamStatus !== undefined ? { upstreamStatus: e.upstreamStatus } : {}),
281
+ ...(e.upstreamCode ? { upstreamCode: e.upstreamCode } : {}),
282
+ ...(e.upstreamReason ? { upstreamReason: e.upstreamReason } : {}),
283
+ ...(e.retryAt ? { retryAt: e.retryAt } : {}),
284
+ ...(e.remedy ? { remedy: e.remedy } : {}),
285
+ },
286
+ });
287
+ }
264
288
  this.failWithCliError({
265
289
  message: `Daemon delegated skrr credential is unavailable: ${err.message}`,
266
290
  code: 'DELEGATED_CLI_CREDENTIAL_UNAVAILABLE',
@@ -535,9 +535,13 @@ function messageSegmentationAdvisory({ destination, text, followingParts, }) {
535
535
  return undefined;
536
536
  if (destination.kind !== 'app_owner_dm' && destination.kind !== 'slack_owner_dm')
537
537
  return undefined;
538
- if (text.length <= exports.OWNER_DM_SEGMENTATION_SOFT_LIMIT)
538
+ // Measure what is READ. A widget block is not a thought to be split: its css, html and
539
+ // script are a program, and an advisory that counted them would invite an agent to cut
540
+ // one block across `--part`s, which the app could not read as a widget.
541
+ const prose = (0, data_provider_1.stripUiWidgetFencesForDisplay)(text, { final: true });
542
+ if (prose.length <= exports.OWNER_DM_SEGMENTATION_SOFT_LIMIT)
539
543
  return undefined;
540
- return (`[skrr] Owner-DM message is ${text.length} characters. It may read better as 2–4 short thoughts: ` +
544
+ return (`[skrr] Owner-DM message is ${prose.length} characters. It may read better as 2–4 short thoughts: ` +
541
545
  'use --part with one explicit --idempotency-key. This is only an advisory; ' +
542
546
  'use --no-message-lint to suppress it.');
543
547
  }
@@ -66,7 +66,9 @@ class AgentsTriggersCreate extends base_command_1.BaseCommand {
66
66
  multiple: true,
67
67
  }),
68
68
  timezone: core_1.Flags.string({ description: 'IANA timezone for schedule/once triggers' }),
69
- 'max-fires-per-day': core_1.Flags.integer({ description: 'Daily fire cap (schedule/stochastic)' }),
69
+ 'max-fires-per-day': core_1.Flags.integer({
70
+ description: 'Daily fire cap (schedule, stochastic and self_scheduled triggers only)',
71
+ }),
70
72
  'max-runs': core_1.Flags.integer({
71
73
  description: 'Lifetime fire cap for a schedule — the trigger disables itself after N total runs',
72
74
  }),
@@ -172,6 +174,8 @@ class AgentsTriggersCreate extends base_command_1.BaseCommand {
172
174
  let payload;
173
175
  try {
174
176
  payload = await (0, prompt_1.readJsonBody)(flags['from-json']);
177
+ // A flag for another kind is refused, not dropped (OSK-15491).
178
+ (0, triggers_1.assertKindFlagsApply)(flags.kind ?? payload.kind, flags);
175
179
  // Agent scope is injected unconditionally — even when --from-json
176
180
  // supplies a scope, the agent identity from the positional arg wins so
177
181
  // the trigger can never be silently mis-scoped to a different agent.
@@ -213,22 +217,8 @@ class AgentsTriggersCreate extends base_command_1.BaseCommand {
213
217
  filterField: flags['filter-field'],
214
218
  filterValues,
215
219
  });
216
- (0, triggers_1.setDefined)(event, {
217
- entityType: flags.entity,
218
- eventType: flags.event,
219
- filterMode: flags['filter-mode'],
220
- filterField: flags['filter-field'],
221
- filterValue: filterValues && filterValues.length > 1 ? filterValues : filterValues?.[0],
222
- debounceMs: flags['debounce-ms'],
223
- maxPerHour: flags['max-per-hour'],
224
- });
225
- const stochastic = {};
226
- (0, triggers_1.setDefined)(stochastic, {
227
- probability: flags.probability === undefined ? undefined : Number(flags.probability),
228
- jitterMs: flags['jitter-ms'],
229
- maxFiresPerDay: flags['max-fires-per-day'],
230
- evalIntervalMinutes: flags['eval-interval-minutes'],
231
- });
220
+ Object.assign(event, (0, triggers_1.buildEventConfigFromFlags)(flags, filterValues));
221
+ const stochastic = (0, triggers_1.buildStochasticConfigFromFlags)(flags);
232
222
  const selfScheduled = (0, triggers_1.buildSelfScheduledConfigFromFlags)(flags);
233
223
  const form = (0, triggers_1.buildFormConfigFromFlags)(flags);
234
224
  const chatMessage = (0, triggers_1.buildChatMessageConfigFromFlags)(flags);
@@ -55,7 +55,9 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
55
55
  multiple: true,
56
56
  }),
57
57
  timezone: core_1.Flags.string({ description: 'IANA timezone for schedule triggers' }),
58
- 'max-fires-per-day': core_1.Flags.integer({ description: 'Daily fire cap' }),
58
+ 'max-fires-per-day': core_1.Flags.integer({
59
+ description: 'Daily fire cap (schedule, stochastic and self_scheduled triggers only)',
60
+ }),
59
61
  'max-runs': core_1.Flags.integer({ description: 'Lifetime fire cap for a schedule' }),
60
62
  'end-at': core_1.Flags.string({
61
63
  description: 'ISO-8601 datetime after which a schedule stops firing',
@@ -156,6 +158,29 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
156
158
  // Scope is immutable from this surface — an agent trigger stays bound to
157
159
  // its agent. Strip any scope in the JSON so the patch can't re-home it.
158
160
  delete payload.scope;
161
+ }
162
+ catch (err) {
163
+ this.error(err.message, { exit: 1 });
164
+ }
165
+ // The trigger's kind says which config block is its own, and only that block is sent. Every
166
+ // block used to go, so `--max-fires-per-day` wrote `stochastic` and `selfScheduled` onto a
167
+ // schedule trigger and a cap onto an on_demand one that nothing reads (OSK-15491). The scope
168
+ // check that used to follow the build now comes first because it is what reads the trigger.
169
+ let scoped;
170
+ try {
171
+ scoped = await (0, triggers_1.fetchAgentScopedTrigger)(args.agentId, args.triggerId);
172
+ }
173
+ catch (err) {
174
+ if (err instanceof triggers_1.AgentTriggerScopeError)
175
+ this.error(err.message, { exit: 4 });
176
+ this.handleApiError(err);
177
+ }
178
+ const scopedKind = scoped.kind;
179
+ if (typeof scopedKind !== 'string') {
180
+ this.error(`Trigger ${args.triggerId} did not report its kind, so its settings cannot be checked.`, { exit: 1 });
181
+ }
182
+ try {
183
+ (0, triggers_1.assertKindFlagsApply)(scopedKind, flags, { kindIsFixed: true });
159
184
  const execution = {};
160
185
  const builtinAction = (0, triggers_1.buildBuiltinActionPayload)({
161
186
  builtinAction: flags['builtin-action'],
@@ -175,7 +200,10 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
175
200
  });
176
201
  const schedule = (0, triggers_1.buildScheduleConfigFromFlags)(flags);
177
202
  (0, triggers_1.assertScheduleTimingShape)(schedule);
178
- const once = (0, triggers_1.buildOnceConfigFromFlags)(flags);
203
+ const once = (0, triggers_1.buildOnceConfigFromFlags)(flags, {
204
+ kind: scopedKind,
205
+ allowNextRunAtAlias: true,
206
+ });
179
207
  const filterValues = (0, triggers_1.splitRepeated)(flags['filter-value']);
180
208
  // Advisory: a catalog this CLI has not caught up with must not make a
181
209
  // server-supported event unreachable. Warn and send; the server validates.
@@ -190,22 +218,8 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
190
218
  filterValues,
191
219
  });
192
220
  const event = {};
193
- (0, triggers_1.setDefined)(event, {
194
- entityType: flags.entity,
195
- eventType: flags.event,
196
- filterMode: flags['filter-mode'],
197
- filterField: flags['filter-field'],
198
- filterValue: filterValues && filterValues.length > 1 ? filterValues : filterValues?.[0],
199
- debounceMs: flags['debounce-ms'],
200
- maxPerHour: flags['max-per-hour'],
201
- });
202
- const stochastic = {};
203
- (0, triggers_1.setDefined)(stochastic, {
204
- probability: flags.probability === undefined ? undefined : Number(flags.probability),
205
- jitterMs: flags['jitter-ms'],
206
- maxFiresPerDay: flags['max-fires-per-day'],
207
- evalIntervalMinutes: flags['eval-interval-minutes'],
208
- });
221
+ Object.assign(event, (0, triggers_1.buildEventConfigFromFlags)(flags, filterValues));
222
+ const stochastic = (0, triggers_1.buildStochasticConfigFromFlags)(flags);
209
223
  const selfScheduled = (0, triggers_1.buildSelfScheduledConfigFromFlags)(flags);
210
224
  const form = (0, triggers_1.buildFormConfigFromFlags)(flags);
211
225
  const chatMessage = (0, triggers_1.buildChatMessageConfigFromFlags)(flags);
@@ -217,15 +231,15 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
217
231
  idempotencyWindow: flags['idempotency-window'],
218
232
  });
219
233
  (0, triggers_1.mergeObjectField)(payload, 'execution', execution);
220
- (0, triggers_1.mergeObjectField)(payload, 'schedule', schedule);
221
- (0, triggers_1.mergeObjectField)(payload, 'once', once);
222
- (0, triggers_1.mergeObjectField)(payload, 'event', event);
223
- // `kind` is immutable on update (rejected above), so there is no kind to
224
- // gate on here; stochastic is only non-empty when stochastic flags were passed.
225
- (0, triggers_1.mergeObjectField)(payload, 'stochastic', stochastic);
226
- (0, triggers_1.mergeObjectField)(payload, 'selfScheduled', selfScheduled);
227
- (0, triggers_1.mergeObjectField)(payload, 'form', form);
228
- (0, triggers_1.mergeObjectField)(payload, 'chatMessage', chatMessage);
234
+ (0, triggers_1.mergeTriggerKindConfig)(payload, scopedKind, {
235
+ schedule,
236
+ once,
237
+ event,
238
+ stochastic,
239
+ selfScheduled,
240
+ form,
241
+ chatMessage,
242
+ });
229
243
  }
230
244
  catch (err) {
231
245
  this.error(err.message, { exit: 1 });
@@ -235,7 +249,6 @@ class AgentsTriggersUpdate extends base_command_1.BaseCommand {
235
249
  }
236
250
  let trigger;
237
251
  try {
238
- await (0, triggers_1.fetchAgentScopedTrigger)(args.agentId, args.triggerId);
239
252
  trigger = await triggers_1.triggerApi.update(args.triggerId, payload);
240
253
  }
241
254
  catch (err) {
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsControlApply extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ 'idempotency-key': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const prompt_1 = require("../../../lib/prompt");
7
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
8
+ class CommitmentsControlApply extends base_command_1.BaseCommand {
9
+ static description = 'Apply the exact scope, version and execution targets from a saved control preview';
10
+ static examples = ['<%= config.bin %> commitments control apply <id> --from-json control.json --idempotency-key <key>'];
11
+ static args = {
12
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
13
+ };
14
+ static flags = {
15
+ 'from-json': core_1.Flags.string({ description: 'Reviewed control preview file, or - for stdin', required: true }),
16
+ 'idempotency-key': core_1.Flags.string({ description: 'Stable key for retries of this exact control request', required: true }),
17
+ reason: core_1.Flags.string({ description: 'Reason for this control (at most 1000 characters)' }),
18
+ json: core_1.Flags.boolean({ description: 'Output the actual control receipt as JSON' }),
19
+ };
20
+ async run() {
21
+ this.requireAuth();
22
+ const { args, flags } = await this.parse(CommitmentsControlApply);
23
+ try {
24
+ const body = (0, responsibility_controls_1.controlFromPreview)(args.id, await (0, prompt_1.readJsonBody)(flags['from-json']), flags['idempotency-key'], flags.reason);
25
+ const receipt = await commitments_1.commitmentApi.applyControl(args.id, body);
26
+ if (flags.json)
27
+ this.log(JSON.stringify(receipt, null, 2));
28
+ else
29
+ (0, responsibility_controls_1.renderControl)(receipt, (line) => this.log(line));
30
+ }
31
+ catch (error) {
32
+ this.handleApiError(error);
33
+ }
34
+ }
35
+ }
36
+ exports.default = CommitmentsControlApply;
@@ -0,0 +1,17 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsControlPreview extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ scope: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ target: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ assignment: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'workflow-run': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ node: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
7
+ class CommitmentsControlPreview extends base_command_1.BaseCommand {
8
+ static description = 'Review a responsibility control and its exact affected execution attempts';
9
+ static examples = [
10
+ '<%= config.bin %> commitments control preview <id> cancel_worker --assignment <id> --json > control.json',
11
+ '<%= config.bin %> commitments control preview <id> pause_observation --json > control.json',
12
+ ];
13
+ static args = {
14
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
15
+ scope: core_1.Args.string({ description: 'Control scope', options: [...responsibility_controls_1.RESPONSIBILITY_CONTROL_SCOPES], required: true, ignoreStdin: true }),
16
+ };
17
+ static flags = {
18
+ target: core_1.Flags.string({ description: 'Exact target ID (repeat for multiple targets)', multiple: true }),
19
+ assignment: core_1.Flags.string({ description: 'Assignment ID to inspect' }),
20
+ 'workflow-run': core_1.Flags.string({ description: 'Workflow episode ID to inspect' }),
21
+ node: core_1.Flags.string({ description: 'Node key in the selected workflow episode', dependsOn: ['workflow-run'] }),
22
+ json: core_1.Flags.boolean({ description: 'Output the complete frozen preview for control apply' }),
23
+ };
24
+ async run() {
25
+ this.requireAuth();
26
+ const { args, flags } = await this.parse(CommitmentsControlPreview);
27
+ try {
28
+ const preview = await commitments_1.commitmentApi.controlPreview(args.id, {
29
+ scope: args.scope,
30
+ ...(flags.target?.length ? { targetIds: flags.target.join(',') } : {}),
31
+ assignmentId: flags.assignment, workflowRunId: flags['workflow-run'], nodeKey: flags.node,
32
+ });
33
+ if (flags.json)
34
+ this.log(JSON.stringify(preview, null, 2));
35
+ else
36
+ (0, responsibility_controls_1.renderControl)(preview, (line) => this.log(line));
37
+ }
38
+ catch (error) {
39
+ this.handleApiError(error);
40
+ }
41
+ }
42
+ }
43
+ exports.default = CommitmentsControlPreview;
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsControlShow extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ controlId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
7
+ class CommitmentsControlShow extends base_command_1.BaseCommand {
8
+ static description = 'Read an exact responsibility control receipt and its current acknowledgement state';
9
+ static args = {
10
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
11
+ controlId: core_1.Args.string({ description: 'Control receipt ID', required: true, ignoreStdin: true }),
12
+ };
13
+ static flags = { json: core_1.Flags.boolean({ description: 'Output the control receipt as JSON' }) };
14
+ async run() {
15
+ this.requireAuth();
16
+ const { args, flags } = await this.parse(CommitmentsControlShow);
17
+ try {
18
+ const receipt = await commitments_1.commitmentApi.controlReceipt(args.id, args.controlId);
19
+ if (flags.json)
20
+ this.log(JSON.stringify(receipt, null, 2));
21
+ else
22
+ (0, responsibility_controls_1.renderControl)(receipt, (line) => this.log(line));
23
+ }
24
+ catch (error) {
25
+ this.handleApiError(error);
26
+ }
27
+ }
28
+ }
29
+ exports.default = CommitmentsControlShow;
@@ -251,11 +251,11 @@ JSON
251
251
  // companion flag implicitly opts the source in — mirroring how
252
252
  // `--metric-key` works — so the enum and its config never disagree.
253
253
  'watch-space': core_1.Flags.string({
254
- description: 'Space to watch (repeatable). Accepts a space id, ref, or unique title. Implies --watch space.',
254
+ description: 'One Space to watch. Accepts a space id, ref, or unique title. Implies --watch space.',
255
255
  multiple: true,
256
256
  }),
257
257
  'watch-monitor': core_1.Flags.string({
258
- description: 'Signal Monitor id to watch (repeatable). Implies --watch monitor.',
258
+ description: 'One Signal Monitor id to watch. Implies --watch monitor.',
259
259
  multiple: true,
260
260
  }),
261
261
  cadence: core_1.Flags.string({
@@ -427,6 +427,9 @@ JSON
427
427
  throw new Error('A finite policy.executionBudget.maxConcurrentRuns in --from-json requires maxConcurrentRunsReason.');
428
428
  }
429
429
  }
430
+ if (Array.isArray(payload.watchedSources)) {
431
+ payload.watchedSources = (0, commitments_1.normalizeWatchedSourceDeclarations)(payload.watchedSources);
432
+ }
430
433
  }
431
434
  catch (err) {
432
435
  this.error(err.message, { exit: 1 });
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsObservationProbe extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ 'from-json': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ 'expected-version': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'timeout-ms': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const prompt_1 = require("../../../lib/prompt");
7
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
8
+ class CommitmentsObservationProbe extends base_command_1.BaseCommand {
9
+ static description = 'Perform a bounded source-read probe for a saved responsibility or unsaved draft';
10
+ static examples = [
11
+ '<%= config.bin %> commitments observation probe <id> --expected-version 7 --timeout-ms 5000',
12
+ '<%= config.bin %> commitments observation probe --from-json draft.json --json',
13
+ ];
14
+ static args = { id: core_1.Args.string({ description: 'Saved Commitment ID; omit for an unsaved draft', ignoreStdin: true }) };
15
+ static flags = {
16
+ 'from-json': core_1.Flags.string({ description: 'Unsaved draft JSON file, or - for stdin' }),
17
+ 'expected-version': core_1.Flags.integer({ description: 'Exact saved Commitment version', min: 1 }),
18
+ 'timeout-ms': core_1.Flags.integer({ description: 'Saved source-probe timeout (1..15000ms)', min: 1, max: 15000 }),
19
+ json: core_1.Flags.boolean({ description: 'Output source evidence as JSON' }),
20
+ };
21
+ async run() {
22
+ this.requireAuth();
23
+ const { args, flags } = await this.parse(CommitmentsObservationProbe);
24
+ try {
25
+ if (Boolean(args.id) === Boolean(flags['from-json']))
26
+ throw new Error('Provide either a saved Commitment ID or --from-json for an unsaved draft.');
27
+ if (!args.id && (flags['expected-version'] !== undefined || flags['timeout-ms'] !== undefined)) {
28
+ throw new Error('--expected-version and --timeout-ms apply only to a saved Commitment.');
29
+ }
30
+ const probe = args.id
31
+ ? await commitments_1.commitmentApi.observationProbe(args.id, {
32
+ ...(flags['expected-version'] !== undefined ? { expectedVersion: flags['expected-version'] } : {}),
33
+ ...(flags['timeout-ms'] !== undefined ? { timeoutMs: flags['timeout-ms'] } : {}),
34
+ })
35
+ : await commitments_1.commitmentApi.draftObservationProbe((0, commitments_1.normalizeCreateBody)(await (0, prompt_1.readJsonBody)(flags['from-json'])));
36
+ if (flags.json)
37
+ this.log(JSON.stringify(probe, null, 2));
38
+ else
39
+ (0, responsibility_controls_1.renderProbe)(probe, (line) => this.log(line));
40
+ }
41
+ catch (error) {
42
+ this.handleApiError(error);
43
+ }
44
+ }
45
+ }
46
+ exports.default = CommitmentsObservationProbe;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsObservationSummary extends BaseCommand {
3
+ static description: string;
4
+ static flags: {
5
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
6
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ class CommitmentsObservationSummary extends base_command_1.BaseCommand {
7
+ static description = 'Read the bounded portfolio observation projection without performing new source checks';
8
+ static flags = {
9
+ agent: core_1.Flags.string({ description: 'Filter the authenticated portfolio by Agent ID' }),
10
+ json: core_1.Flags.boolean({ description: 'Output the complete observation projection as JSON' }),
11
+ };
12
+ async run() {
13
+ this.requireAuth();
14
+ const { flags } = await this.parse(CommitmentsObservationSummary);
15
+ try {
16
+ const summary = await commitments_1.commitmentApi.observationSummary({ agentId: flags.agent });
17
+ if (flags.json) {
18
+ this.log(JSON.stringify(summary, null, 2));
19
+ return;
20
+ }
21
+ this.log(`Portfolio observation: ${summary.state ?? 'unknown'}`);
22
+ this.log(`Checked at: ${summary.checkedAt ?? 'unavailable'}`);
23
+ this.log(`Coverage: ${JSON.stringify(summary.coverage ?? {})}`);
24
+ this.log(`Next wake: ${JSON.stringify(summary.nextWake ?? {})}`);
25
+ }
26
+ catch (error) {
27
+ this.handleApiError(error);
28
+ }
29
+ }
30
+ }
31
+ exports.default = CommitmentsObservationSummary;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.preflightGateLines = preflightGateLines;
4
4
  const core_1 = require("@oclif/core");
5
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
6
  const base_command_1 = require("../../base-command");
6
7
  const commitments_1 = require("../../lib/commitments");
7
8
  const prompt_1 = require("../../lib/prompt");
@@ -23,6 +24,22 @@ const prompt_1 = require("../../lib/prompt");
23
24
  * dash as a short code puts two different kinds of thing in one slot.
24
25
  */
25
26
  function preflightGateLines(gate, verbose = false) {
27
+ // "Could it contact you now?" is not a Run gate. It answers whether a message
28
+ // would reach the owner, and a limit the owner set themselves (zero nudges a day,
29
+ // quiet hours) is a chosen quiet, not a defect. It carried the same BLOCK tag, a
30
+ // bare code and no setting as the real blockers beside it ("paused", "Always-On
31
+ // off"), while the report's own `admission` field said it blocks nothing
32
+ // (OSK-15420). Say what it is in words, and which setting moves it.
33
+ if (gate.id === 'attention' && gate.verdict === 'block') {
34
+ const copy = (0, data_provider_1.describeSuppression)(gate.reason);
35
+ const lines = [
36
+ ` ${'info'.padEnd(5)} ${gate.label} — ${copy.title.toLowerCase()}${verbose && gate.reason ? ` (${gate.reason})` : ''}`,
37
+ ` ${copy.detail}`,
38
+ ];
39
+ if (copy.settingKey)
40
+ lines.push(` Setting: ${copy.settingKey}`);
41
+ return lines;
42
+ }
26
43
  const mark = gate.verdict === 'pass' ? 'ok' : gate.verdict === 'block' ? 'BLOCK' : 'warn';
27
44
  // A BLOCKING gate always states its reason. `ok` gates got a helpful `note`
28
45
  // and `warn` gates got a reason token, and the BLOCK gates — the only ones
@@ -176,7 +193,7 @@ class CommitmentsPreflight extends base_command_1.BaseCommand {
176
193
  (endpoint.reason ? ` (${endpoint.reason})` : '') +
177
194
  (!endpoint.available && endpoint.detail ? ` — ${endpoint.detail}` : ''));
178
195
  }
179
- this.log(`\nAttention: ${report.attention?.allowed ? 'delivery allowed now' : `suppressed by ${report.attention?.suppressedBy || 'policy'}`}`);
196
+ this.log(`\nAttention: ${report.attention?.allowed ? 'delivery allowed now' : `held back — ${(0, data_provider_1.describeSuppression)(report.attention?.suppressedBy).title.toLowerCase()}${report.attention?.suppressedBy ? ` (${report.attention.suppressedBy})` : ''}`}`);
180
197
  if (report.verdict === 'blocked')
181
198
  process.exitCode = 1;
182
199
  }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsReadinessShow extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ receiptId: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
7
+ class CommitmentsReadinessShow extends base_command_1.BaseCommand {
8
+ static description = 'Read one exact historical admission or activation receipt without refreshing its evidence';
9
+ static args = {
10
+ id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }),
11
+ receiptId: core_1.Args.string({ description: 'Readiness or activation receipt ID', required: true, ignoreStdin: true }),
12
+ };
13
+ static flags = { json: core_1.Flags.boolean({ description: 'Output the exact receipt as JSON' }) };
14
+ async run() {
15
+ this.requireAuth();
16
+ const { args, flags } = await this.parse(CommitmentsReadinessShow);
17
+ try {
18
+ const receipt = await commitments_1.commitmentApi.readinessReceipt(args.id, args.receiptId);
19
+ if (flags.json)
20
+ this.log(JSON.stringify(receipt, null, 2));
21
+ else
22
+ (0, responsibility_controls_1.renderReadiness)(receipt, (line) => this.log(line));
23
+ }
24
+ catch (error) {
25
+ this.handleApiError(error);
26
+ }
27
+ }
28
+ }
29
+ exports.default = CommitmentsReadinessShow;
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class CommitmentsReadinessVerify extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ 'expected-version': import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ 'timeout-ms': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../../../base-command");
5
+ const commitments_1 = require("../../../lib/commitments");
6
+ const responsibility_controls_1 = require("../../../lib/responsibility-controls");
7
+ class CommitmentsReadinessVerify extends base_command_1.BaseCommand {
8
+ static description = 'Verify one exact saved responsibility version and record canonical readiness evidence';
9
+ static args = { id: core_1.Args.string({ description: 'Commitment ID', required: true, ignoreStdin: true }) };
10
+ static flags = {
11
+ 'expected-version': core_1.Flags.integer({ description: 'Reviewed Commitment version', required: true, min: 1 }),
12
+ 'timeout-ms': core_1.Flags.integer({ description: 'Source-probe timeout (1..15000ms)', min: 1, max: 15000 }),
13
+ json: core_1.Flags.boolean({ description: 'Output the recorded readiness receipt as JSON' }),
14
+ };
15
+ async run() {
16
+ this.requireAuth();
17
+ const { args, flags } = await this.parse(CommitmentsReadinessVerify);
18
+ try {
19
+ const receipt = await commitments_1.commitmentApi.verifyReadiness(args.id, {
20
+ expectedVersion: flags['expected-version'],
21
+ ...(flags['timeout-ms'] !== undefined ? { timeoutMs: flags['timeout-ms'] } : {}),
22
+ });
23
+ if (flags.json)
24
+ this.log(JSON.stringify(receipt, null, 2));
25
+ else
26
+ (0, responsibility_controls_1.renderReadiness)(receipt, (line) => this.log(line));
27
+ }
28
+ catch (error) {
29
+ this.handleApiError(error);
30
+ }
31
+ }
32
+ }
33
+ exports.default = CommitmentsReadinessVerify;