@skrr-ai/cli 0.1.95 → 0.1.96

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 (185) hide show
  1. package/README.md +22 -0
  2. package/dist/commands/agent/message/send.d.ts +2 -0
  3. package/dist/commands/agent/message/send.js +75 -5
  4. package/dist/commands/agents/chat.js +1 -1
  5. package/dist/commands/agents/create.d.ts +0 -3
  6. package/dist/commands/agents/create.js +0 -26
  7. package/dist/commands/agents/egress.d.ts +17 -0
  8. package/dist/commands/agents/egress.js +84 -0
  9. package/dist/commands/agents/mailbox/messages.d.ts +14 -0
  10. package/dist/commands/agents/mailbox/messages.js +52 -0
  11. package/dist/commands/agents/mailbox/show.d.ts +13 -0
  12. package/dist/commands/agents/mailbox/show.js +52 -0
  13. package/dist/commands/agents/operating-plan.js +8 -0
  14. package/dist/commands/agents/roles/capture.d.ts +16 -0
  15. package/dist/commands/agents/roles/capture.js +53 -0
  16. package/dist/commands/agents/roles/install.d.ts +1 -0
  17. package/dist/commands/agents/roles/install.js +8 -1
  18. package/dist/commands/agents/roles/preview.d.ts +2 -0
  19. package/dist/commands/agents/roles/preview.js +27 -3
  20. package/dist/commands/agents/update.d.ts +0 -3
  21. package/dist/commands/agents/update.js +1 -31
  22. package/dist/commands/agents/usage-cap.d.ts +4 -1
  23. package/dist/commands/agents/usage-cap.js +49 -10
  24. package/dist/commands/code/jobs/show.js +12 -0
  25. package/dist/commands/commitments/action-proposals/decide.d.ts +2 -0
  26. package/dist/commands/commitments/action-proposals/decide.js +12 -0
  27. package/dist/commands/commitments/action-proposals.js +7 -0
  28. package/dist/commands/commitments/create.d.ts +1 -0
  29. package/dist/commands/commitments/create.js +17 -1
  30. package/dist/commands/commitments/delivery.d.ts +1 -0
  31. package/dist/commands/commitments/delivery.js +11 -1
  32. package/dist/commands/commitments/doctor.js +4 -0
  33. package/dist/commands/commitments/effective-policy.js +26 -0
  34. package/dist/commands/commitments/endpoints/create.js +5 -2
  35. package/dist/commands/commitments/observations.d.ts +10 -0
  36. package/dist/commands/commitments/observations.js +88 -0
  37. package/dist/commands/commitments/pause.d.ts +1 -1
  38. package/dist/commands/commitments/pause.js +4 -3
  39. package/dist/commands/commitments/preflight.js +2 -1
  40. package/dist/commands/commitments/reports.d.ts +2 -0
  41. package/dist/commands/commitments/reports.js +22 -4
  42. package/dist/commands/commitments/update.d.ts +1 -0
  43. package/dist/commands/commitments/update.js +35 -5
  44. package/dist/commands/grants/create.d.ts +1 -0
  45. package/dist/commands/grants/create.js +8 -0
  46. package/dist/commands/grants/rotate.d.ts +5 -0
  47. package/dist/commands/grants/rotate.js +13 -1
  48. package/dist/commands/grants/update.d.ts +12 -0
  49. package/dist/commands/grants/update.js +27 -0
  50. package/dist/commands/machines/hosted/start.js +7 -1
  51. package/dist/commands/machines/list.js +4 -4
  52. package/dist/commands/measures/confirm.d.ts +1 -7
  53. package/dist/commands/measures/confirm.js +15 -14
  54. package/dist/commands/measures/list.d.ts +1 -7
  55. package/dist/commands/measures/list.js +1 -7
  56. package/dist/commands/measures/record.js +4 -4
  57. package/dist/commands/measures/show.d.ts +11 -0
  58. package/dist/commands/measures/show.js +26 -0
  59. package/dist/commands/northstars/governance/configure.d.ts +1 -0
  60. package/dist/commands/northstars/governance/configure.js +8 -1
  61. package/dist/commands/proposals/discard.d.ts +5 -0
  62. package/dist/commands/proposals/discard.js +8 -0
  63. package/dist/commands/proposals/keep.d.ts +5 -0
  64. package/dist/commands/proposals/keep.js +8 -0
  65. package/dist/commands/proposals/list.d.ts +15 -0
  66. package/dist/commands/proposals/list.js +74 -0
  67. package/dist/commands/proposals/show.d.ts +12 -0
  68. package/dist/commands/proposals/show.js +27 -0
  69. package/dist/commands/proposals/snooze.d.ts +5 -0
  70. package/dist/commands/proposals/snooze.js +8 -0
  71. package/dist/commands/signals/monitors/create.d.ts +9 -0
  72. package/dist/commands/signals/monitors/create.js +29 -0
  73. package/dist/commands/signals/monitors/list.d.ts +8 -0
  74. package/dist/commands/signals/monitors/list.js +16 -0
  75. package/dist/commands/signals/monitors/pause.d.ts +11 -0
  76. package/dist/commands/signals/monitors/pause.js +17 -0
  77. package/dist/commands/signals/monitors/resume.d.ts +11 -0
  78. package/dist/commands/signals/monitors/resume.js +17 -0
  79. package/dist/commands/signals/monitors/revise.d.ts +12 -0
  80. package/dist/commands/signals/monitors/revise.js +25 -0
  81. package/dist/commands/signals/monitors/show.d.ts +11 -0
  82. package/dist/commands/signals/monitors/show.js +17 -0
  83. package/dist/commands/signals/monitors/test.d.ts +12 -0
  84. package/dist/commands/signals/monitors/test.js +25 -0
  85. package/dist/commands/signals/monitors/transitions.d.ts +11 -0
  86. package/dist/commands/signals/monitors/transitions.js +17 -0
  87. package/dist/commands/signals/monitors/validate.d.ts +9 -0
  88. package/dist/commands/signals/monitors/validate.js +24 -0
  89. package/dist/commands/signals/schemas/list.d.ts +8 -0
  90. package/dist/commands/signals/schemas/list.js +16 -0
  91. package/dist/commands/signals/schemas/show.d.ts +11 -0
  92. package/dist/commands/signals/schemas/show.js +17 -0
  93. package/dist/commands/signals/sources/list.d.ts +8 -0
  94. package/dist/commands/signals/sources/list.js +16 -0
  95. package/dist/commands/signals/sources/receipts.d.ts +11 -0
  96. package/dist/commands/signals/sources/receipts.js +17 -0
  97. package/dist/commands/signals/sources/show.d.ts +11 -0
  98. package/dist/commands/signals/sources/show.js +17 -0
  99. package/dist/commands/spaces/usage.d.ts +12 -0
  100. package/dist/commands/spaces/usage.js +28 -0
  101. package/dist/commands/spaces/workflows/run.js +3 -0
  102. package/dist/commands/spaces/workflows/runs.js +2 -1
  103. package/dist/commands/spaces/workflows/update.d.ts +6 -1
  104. package/dist/commands/spaces/workflows/update.js +34 -2
  105. package/dist/commands/tasks/cascade-status.d.ts +2 -0
  106. package/dist/commands/tasks/cascade-status.js +27 -1
  107. package/dist/commands/tasks/create.d.ts +4 -0
  108. package/dist/commands/tasks/create.js +16 -0
  109. package/dist/commands/tasks/deliverable/add.js +12 -3
  110. package/dist/commands/tasks/economics-compare.d.ts +15 -0
  111. package/dist/commands/tasks/economics-compare.js +60 -0
  112. package/dist/commands/tasks/expectations/evaluate.d.ts +13 -0
  113. package/dist/commands/tasks/expectations/evaluate.js +43 -0
  114. package/dist/commands/tasks/list.d.ts +1 -0
  115. package/dist/commands/tasks/list.js +44 -1
  116. package/dist/commands/tasks/show.d.ts +5 -0
  117. package/dist/commands/tasks/show.js +17 -0
  118. package/dist/commands/tasks/update.d.ts +4 -0
  119. package/dist/commands/tasks/update.js +9 -0
  120. package/dist/commands/tasks/workflow-findings.js +2 -2
  121. package/dist/commands/triggers/create.d.ts +2 -0
  122. package/dist/commands/triggers/create.js +15 -0
  123. package/dist/commands/workspaces/grants.d.ts +12 -0
  124. package/dist/commands/workspaces/grants.js +31 -0
  125. package/dist/commands/workspaces/stewardship.d.ts +13 -0
  126. package/dist/commands/workspaces/stewardship.js +34 -0
  127. package/dist/lib/agent-config.d.ts +0 -12
  128. package/dist/lib/agent-config.js +1 -27
  129. package/dist/lib/agent-mailbox.d.ts +35 -0
  130. package/dist/lib/agent-mailbox.js +55 -0
  131. package/dist/lib/commitment-endpoints.d.ts +2 -1
  132. package/dist/lib/commitment-endpoints.js +2 -5
  133. package/dist/lib/commitment-product.d.ts +3 -1
  134. package/dist/lib/commitment-product.js +10 -0
  135. package/dist/lib/commitment-terms.js +1 -1
  136. package/dist/lib/commitments.d.ts +17 -7
  137. package/dist/lib/commitments.js +173 -85
  138. package/dist/lib/compasses.d.ts +14 -0
  139. package/dist/lib/compasses.js +25 -11
  140. package/dist/lib/grants.d.ts +5 -1
  141. package/dist/lib/grants.js +9 -1
  142. package/dist/lib/hosted-machines.d.ts +7 -0
  143. package/dist/lib/mailbox-human-command.d.ts +11 -0
  144. package/dist/lib/mailbox-human-command.js +41 -0
  145. package/dist/lib/measures.d.ts +28 -2
  146. package/dist/lib/measures.js +38 -14
  147. package/dist/lib/message-intent.d.ts +6 -2
  148. package/dist/lib/message-intent.js +1 -0
  149. package/dist/lib/northstars.js +2 -1
  150. package/dist/lib/proposal-decision-command.d.ts +19 -0
  151. package/dist/lib/proposal-decision-command.js +64 -0
  152. package/dist/lib/proposals.d.ts +8 -0
  153. package/dist/lib/proposals.js +22 -0
  154. package/dist/lib/roles.d.ts +141 -6
  155. package/dist/lib/roles.js +8 -2
  156. package/dist/lib/signals.d.ts +20 -0
  157. package/dist/lib/signals.js +24 -0
  158. package/dist/lib/space-usage.d.ts +3 -0
  159. package/dist/lib/space-usage.js +17 -0
  160. package/dist/lib/stewardship-output.d.ts +4 -0
  161. package/dist/lib/stewardship-output.js +82 -0
  162. package/dist/lib/task-asset-upload.d.ts +3 -1
  163. package/dist/lib/task-asset-upload.js +1 -0
  164. package/dist/lib/task-economics.d.ts +16 -0
  165. package/dist/lib/task-economics.js +22 -0
  166. package/dist/lib/triggers.d.ts +11 -3
  167. package/dist/lib/triggers.js +58 -1
  168. package/dist/lib/usage-discovery.d.ts +10 -0
  169. package/dist/lib/usage-discovery.js +24 -3
  170. package/dist/lib/workflow-run-budget.d.ts +12 -0
  171. package/dist/lib/workflow-run-budget.js +37 -0
  172. package/dist/lib/workspaces.d.ts +48 -0
  173. package/dist/lib/workspaces.js +8 -0
  174. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.d.ts +4 -0
  175. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/cliHandoffWire.js +14 -1
  176. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.d.ts +9 -0
  177. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/githubPushRefusal.js +49 -0
  178. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.d.ts +4 -0
  179. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/cliHandoffWire.js +12 -0
  180. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.d.ts +9 -0
  181. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/githubPushRefusal.js +44 -0
  182. package/dist/node_modules/@skrr-ai/auth-core/package.json +10 -0
  183. package/dist/node_modules/@skrr-ai/data-provider/index.js +8017 -7086
  184. package/oclif.manifest.json +3872 -1167
  185. package/package.json +22 -1
package/README.md CHANGED
@@ -15,6 +15,28 @@ skrr whoami
15
15
  skrr spaces list --json
16
16
  ```
17
17
 
18
+ The CLI is the user-facing command; `skrr daemon install` downloads and verifies
19
+ the background runtime when needed. Installing `skrrd` alone does not install
20
+ the CLI. For a user-owned installation without administrator access on macOS
21
+ or Linux, use `npm install -g --prefix "$HOME/.local" @skrr-ai/cli` and add
22
+ `$HOME/.local/bin` to your shell PATH. Verify with `command -v skrr` and
23
+ `skrr --version` in a new terminal.
24
+
25
+ The desktop app includes the CLI and installs its `skrr` wrapper on launch,
26
+ using its bundled interpreter so no separate Node.js installation is needed.
27
+ If your terminal cannot find it, choose **Help > Set Up skrr Command…**.
28
+ This verifies your shell, offers Unix PATH setup, and can copy the full command.
29
+ Existing commands owned by npm or another installer are preserved. Desktop
30
+ updates maintain the bundled wrapper; npm maintains npm installations.
31
+
32
+ The script installer sets up both `skrr` and the signed `skrrd` runtime by
33
+ default and requires Node.js 20+ with npm. To repair a machine that already has
34
+ the runtime, run `bash scripts/install-daemon.sh --cli-only` from this checkout.
35
+ Use `--daemon-only` for runtime images without npm. On Windows the equivalent
36
+ runtime-only switch is `$env:SKRR_INSTALL_DAEMON_ONLY='1'` before running
37
+ `install-daemon.ps1`. These installers use a user-owned npm prefix and leave
38
+ the system/global npm configuration unchanged.
39
+
18
40
  `login` first tries a signed-in local daemon, then browser PKCE, then a device code when the callback cannot run. With SSH or no local browser, use `skrr login --device-code`; approve it in a browser on another device. Password, MFA, passkey and configured federation challenges remain on the web sign-in page. The CLI has no password flag.
19
41
 
20
42
  To create your first Task in an existing Space, copy its ID from `spaces list` and run:
@@ -85,6 +85,8 @@ export default class AgentMessageSend extends BaseCommand {
85
85
  part: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
86
86
  'message-lint': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
87
87
  destination: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
88
+ to: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
89
+ subject: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
88
90
  channel: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
89
91
  'thread-ts': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
90
92
  'thread-root': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -114,6 +114,11 @@ class AgentMessageSend extends base_command_1.BaseCommand {
114
114
  description: 'Destination kind for the canonical intent',
115
115
  options: [...message_intent_1.CANONICAL_DESTINATION_KINDS],
116
116
  }),
117
+ to: core_1.Flags.string({
118
+ description: 'Recipient email address; repeat for up to 5 recipients',
119
+ multiple: true,
120
+ }),
121
+ subject: core_1.Flags.string({ description: 'Plain email subject (agent_email only)' }),
117
122
  channel: core_1.Flags.string({
118
123
  description: 'Slack channel ID (only meaningful with --destination slack_channel)',
119
124
  }),
@@ -178,6 +183,8 @@ class AgentMessageSend extends base_command_1.BaseCommand {
178
183
  agentId: flags.agent,
179
184
  text: flags.text,
180
185
  destinationKind: flags.destination,
186
+ recipients: flags.to,
187
+ subject: flags.subject,
181
188
  channelId: flags.channel,
182
189
  threadTs: flags['thread-ts'],
183
190
  threadRootMessageId: flags['thread-root'],
@@ -497,6 +504,9 @@ class AgentMessageSend extends base_command_1.BaseCommand {
497
504
  },
498
505
  });
499
506
  }
507
+ if (request.destination.kind === 'agent_email') {
508
+ this.error('Agent email is available only through an authorized Agent session.');
509
+ }
500
510
  // slack_owner_dm is a Gateway-only destination: it applies workspace-scoped
501
511
  // owner routing that no legacy human transport can enact.
502
512
  this.failWithCliError({
@@ -538,6 +548,14 @@ function messageSegmentationAdvisory({ destination, text, followingParts, }) {
538
548
  * from one explicit semantic idempotency key.
539
549
  */
540
550
  function buildSequencedRequests(request, followingParts, hasExplicitIdempotencyKey) {
551
+ if (request.destination.kind === 'agent_email') {
552
+ if (followingParts.length)
553
+ throw invalidIntent('Email accepts one plain-text body; --part is not supported.');
554
+ requireText(request.content.text, 'content.text', 20 * 1024);
555
+ if (Buffer.byteLength(request.content.text, 'utf8') > 20 * 1024)
556
+ throw invalidIntent('Email body exceeds 20 KiB.');
557
+ return [request];
558
+ }
541
559
  const parts = [request.content.text, ...followingParts].map((part) => requireText(part, 'part'));
542
560
  if (parts.length === 1)
543
561
  return [request];
@@ -586,6 +604,8 @@ const DELIVERY_FAILURE_STATUSES = new Set([
586
604
  'dropped',
587
605
  'expired',
588
606
  'cancelled',
607
+ 'unknown',
608
+ 'refused',
589
609
  ]);
590
610
  /**
591
611
  * Exit codes for a submitted-but-undelivered message.
@@ -723,8 +743,18 @@ function normalizeIntentPayload({ agentId, jsonBody, merged, }) {
723
743
  bodyDestination,
724
744
  overlayChannel,
725
745
  overlayThreadTs,
746
+ overlayRecipients: merged.recipients,
747
+ overlaySubject: merged.subject,
726
748
  });
727
- const text = requireText(readTextField(jsonBody, merged), 'content.text');
749
+ const text = requireText(readTextField(jsonBody, merged), 'content.text', destination.kind === 'agent_email' ? 20 * 1024 : MAX_TEXT_CHARS);
750
+ if (destination.kind === 'agent_email') {
751
+ if (Buffer.byteLength(text, 'utf8') > 20 * 1024)
752
+ throw invalidIntent('Email body exceeds 20 KiB.');
753
+ const forbidden = ['from', 'cc', 'bcc', 'html', 'attachments', 'headers', 'replyTo'];
754
+ const content = jsonBody.content;
755
+ if (forbidden.some((key) => jsonBody[key] !== undefined || content?.[key] !== undefined))
756
+ throw invalidIntent('Agent email accepts plain text only; sender and headers are server-owned.');
757
+ }
728
758
  const idempotencyKey = optionalIdempotencyKey(merged.idempotencyKey ??
729
759
  jsonBody.idempotencyKey ??
730
760
  jsonBody['idempotency_key'] ??
@@ -778,10 +808,38 @@ function pickDestinationKind({ bodyDestination, overlayKind, }) {
778
808
  }
779
809
  throw invalidIntent(`destination.kind must be one of ${message_intent_1.CANONICAL_DESTINATION_KINDS.join(', ')} (got "${normalized}").`);
780
810
  }
781
- function buildDestination({ kind, bodyDestination, overlayChannel, overlayThreadTs, }) {
811
+ function buildDestination({ kind, bodyDestination, overlayChannel, overlayThreadTs, overlayRecipients, overlaySubject, }) {
782
812
  if (kind === 'app_owner_dm' || kind === 'slack_owner_dm') {
783
813
  return { kind };
784
814
  }
815
+ if (kind === 'agent_email') {
816
+ const source = bodyDestination;
817
+ if (source &&
818
+ Object.keys(source).some((key) => !['kind', 'recipients', 'subject'].includes(key))) {
819
+ throw invalidIntent('agent_email accepts only recipients and subject.');
820
+ }
821
+ const rawRecipients = overlayRecipients ?? source?.recipients;
822
+ if (!Array.isArray(rawRecipients) || rawRecipients.length < 1 || rawRecipients.length > 5) {
823
+ throw invalidIntent('agent_email requires 1 to 5 recipients.');
824
+ }
825
+ const recipients = rawRecipients.map((value) => {
826
+ if (typeof value !== 'string' ||
827
+ value.length > 254 ||
828
+ !/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(value))
829
+ throw invalidIntent('Invalid email recipient.');
830
+ return value.toLowerCase();
831
+ });
832
+ if (new Set(recipients).size !== recipients.length)
833
+ throw invalidIntent('Email recipients must be distinct.');
834
+ const subject = overlaySubject ?? source?.subject;
835
+ if (typeof subject !== 'string' ||
836
+ !subject.trim() ||
837
+ subject.length > 200 ||
838
+ // eslint-disable-next-line no-control-regex -- Reject control characters in mail headers.
839
+ /[\r\n\x00-\x1f\x7f]/.test(subject))
840
+ throw invalidIntent('Email subject must be a single line of at most 200 characters.');
841
+ return { kind, recipients: recipients.sort(), subject: subject.trim() };
842
+ }
785
843
  const channelId = optionalString(overlayChannel ?? bodyDestination?.channelId);
786
844
  if (!channelId) {
787
845
  throw invalidIntent('slack_channel destinations require destination.channelId.');
@@ -905,6 +963,16 @@ function booleanFlagInput(argv, name, parsedValue) {
905
963
  }
906
964
  function canonicalIntentFromDestination({ agentId, idempotencyKey, destination, text, presentation, notificationPolicy, context, threadRootMessageId, embeds, }) {
907
965
  switch (destination.kind) {
966
+ case 'agent_email':
967
+ return {
968
+ protocolVersion: 1,
969
+ agentId,
970
+ intentType: 'status_update',
971
+ destination,
972
+ content: { text },
973
+ idempotencyKey,
974
+ ...(context ? { context } : {}),
975
+ };
908
976
  case 'app_owner_dm':
909
977
  return (0, message_intent_1.canonicalAppOwnerDmRequest)({
910
978
  agentId,
@@ -947,13 +1015,13 @@ function resolveAgentInput(argValue, flagValue, merged, jsonBody) {
947
1015
  { label: 'agentId in JSON input', value: fromBody ?? fromMerged },
948
1016
  ]);
949
1017
  }
950
- function requireText(value, field) {
1018
+ function requireText(value, field, maxChars = MAX_TEXT_CHARS) {
951
1019
  if (typeof value !== 'string' || !value.trim()) {
952
1020
  throw invalidIntent(`${field} is required.`);
953
1021
  }
954
1022
  const normalized = value.trim();
955
- if (normalized.length > MAX_TEXT_CHARS) {
956
- throw invalidIntent(`${field} must be ${MAX_TEXT_CHARS} characters or less.`);
1023
+ if (normalized.length > maxChars) {
1024
+ throw invalidIntent(`${field} must be ${maxChars} characters or less.`);
957
1025
  }
958
1026
  return normalized;
959
1027
  }
@@ -1043,6 +1111,8 @@ function formatEnvelope(envelope) {
1043
1111
  return `Agent message intent for ${envelope.agent.id} → ${destination}: ${status}${suffix}.${presentation}`;
1044
1112
  }
1045
1113
  function describeDestination(destination) {
1114
+ if (destination.kind === 'agent_email')
1115
+ return `agent_email:${destination.recipients.join(', ')}`;
1046
1116
  if (destination.kind === 'slack_channel') {
1047
1117
  return `slack_channel:${destination.channelId}${destination.threadTs ? `:${destination.threadTs}` : ''}`;
1048
1118
  }
@@ -594,7 +594,7 @@ class AgentsChat extends base_command_1.BaseCommand {
594
594
  'status is not managed for you. The runtime session is bound to this task for ' +
595
595
  'task context and artifact uploads; use the canonical id above.',
596
596
  ].join('\n');
597
- if (!flags.jsonl) {
597
+ if (!flags.jsonl && !flags.json) {
598
598
  this.log(`Bound to task ${task.identifier ?? taskId} (chat turn — task not checked out)`);
599
599
  }
600
600
  }
@@ -124,9 +124,6 @@ export default class AgentsCreate extends BaseCommand {
124
124
  avatar: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
125
125
  'conversation-starter': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
126
126
  'todo-working-hours': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
127
- 'reasoning-tool-escape': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
128
- 'commitment-responsibility': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
129
- 'commitment-responsibility-ceiling': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
130
127
  'max-turns': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
131
128
  'tool-resources': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
132
129
  'install-channel': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -280,32 +280,6 @@ class AgentsCreate extends base_command_1.BaseCommand {
280
280
  description: 'When this agent schedules its own work: HH:MM-HH:MM[@<IANA timezone>], e.g. ' +
281
281
  '09:00-18:00@America/Los_Angeles',
282
282
  }),
283
- // Retired (OSK-11975): a Commitment turn works under the Agent's own
284
- // permissions. Hidden, warned on use, and never sent (OSK-12068) — see
285
- // `mergeAgentConfigFlags`. Kept parseable so an old script still runs.
286
- 'reasoning-tool-escape': core_1.Flags.string({
287
- description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
288
- options: [...agent_config_1.REASONING_TOOL_ESCAPES],
289
- multiple: true,
290
- deprecated: { message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('reasoning-tool-escape') },
291
- hidden: true,
292
- }),
293
- 'commitment-responsibility': core_1.Flags.string({
294
- description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
295
- options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
296
- deprecated: {
297
- message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('commitment-responsibility'),
298
- },
299
- hidden: true,
300
- }),
301
- 'commitment-responsibility-ceiling': core_1.Flags.string({
302
- description: "Retired — has no effect and is not sent. Commitment runs use the agent's own permissions.",
303
- options: [...agent_config_1.COMMITMENT_RESPONSIBILITY_LEVELS],
304
- deprecated: {
305
- message: (0, agent_config_1.retiredCommitmentPermissionFlagMessage)('commitment-responsibility-ceiling'),
306
- },
307
- hidden: true,
308
- }),
309
283
  'max-turns': core_1.Flags.integer({ description: 'Maximum turns in one agent run (1-500)' }),
310
284
  'tool-resources': core_1.Flags.string({
311
285
  description: 'Tool resources JSON object (file_search / context / image_edit bindings)',
@@ -0,0 +1,17 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ export default class AgentsEgress 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
+ allow: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ remove: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ repo: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'remove-repo': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ clear: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
15
+ };
16
+ run(): Promise<void>;
17
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../base-command");
6
+ class AgentsEgress extends base_command_1.BaseCommand {
7
+ static description = 'Show or declare the exact hosts and repositories a hosted agent may use on its next start';
8
+ static args = { id: core_1.Args.string({ required: true, ignoreStdin: true }) };
9
+ static flags = {
10
+ allow: core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
11
+ remove: core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
12
+ repo: core_1.Flags.string({
13
+ multiple: true,
14
+ exclusive: ['clear'],
15
+ description: 'Allow a repository (owner/name) for Hosted Jobs',
16
+ }),
17
+ 'remove-repo': core_1.Flags.string({ multiple: true, exclusive: ['clear'] }),
18
+ reason: core_1.Flags.string({ exclusive: ['clear'] }),
19
+ clear: core_1.Flags.boolean({
20
+ exclusive: ['allow', 'remove', 'repo', 'remove-repo', 'reason'],
21
+ description: 'Delete the whole declaration: hosts and repositories',
22
+ }),
23
+ json: core_1.Flags.boolean(),
24
+ };
25
+ async run() {
26
+ this.requireAuth();
27
+ const { args, flags } = await this.parse(AgentsEgress);
28
+ try {
29
+ let result = await data_provider_1.dataService.getAgentEgress(args.id);
30
+ if (flags.clear)
31
+ result = await data_provider_1.dataService.clearAgentEgress(args.id);
32
+ else if (flags.allow ||
33
+ flags.remove ||
34
+ flags.repo ||
35
+ flags['remove-repo'] ||
36
+ flags.reason !== undefined) {
37
+ const remove = new Set((0, data_provider_1.normalizeAgentEgressHosts)(flags.remove || []));
38
+ const hosts = (0, data_provider_1.normalizeAgentEgressHosts)([
39
+ ...(result.declaration?.hosts || []),
40
+ ...(flags.allow || []),
41
+ ]).filter((host) => !remove.has(host));
42
+ // Repositories are sent only when this call changes them, so a hosts-only
43
+ // edit can never rewrite a list another surface set.
44
+ const touchesRepositories = Boolean(flags.repo || flags['remove-repo']);
45
+ const removeRepos = new Set((0, data_provider_1.normalizeAgentRepositories)(flags['remove-repo'] || []));
46
+ const repositories = touchesRepositories
47
+ ? (0, data_provider_1.normalizeAgentRepositories)([
48
+ ...(result.declaration?.repositories || []),
49
+ ...(flags.repo || []),
50
+ ]).filter((repository) => !removeRepos.has(repository))
51
+ : undefined;
52
+ result = await data_provider_1.dataService.setAgentEgress(args.id, {
53
+ hosts,
54
+ ...(repositories ? { repositories } : {}),
55
+ ...(flags.reason !== undefined ? { reason: flags.reason } : {}),
56
+ });
57
+ }
58
+ if (flags.json) {
59
+ this.log(JSON.stringify(result, null, 2));
60
+ return;
61
+ }
62
+ const repositories = result.declaration?.repositories;
63
+ this.log(repositories?.length
64
+ ? `Repositories: ${repositories.join(', ')} (Hosted Jobs and Commitment deliveries may use only these; git_commit push is not enabled in production turns and, when enabled, is bounded by them too; raw git in a shell is not limited by it)`
65
+ : 'Repositories: none declared (no restriction)');
66
+ if (!('policy' in result.effective)) {
67
+ this.log('Effective network unavailable: the workspace policy could not be read.');
68
+ this.log(data_provider_1.AGENT_EGRESS_EXPLANATION);
69
+ return;
70
+ }
71
+ this.log(`Network: ${result.effective.policy} (${result.effective.source}; ${result.effective.hosts.length} hosts)`);
72
+ this.log(result.effective.hosts.join(', '));
73
+ if (result.effective.droppedHosts.length)
74
+ this.log(`Workspace policy dropped: ${result.effective.droppedHosts.join(', ')}`);
75
+ if (result.effective.unreadable)
76
+ this.log('Declaration or ceiling unreadable: baseline only.');
77
+ this.log(data_provider_1.AGENT_EGRESS_EXPLANATION);
78
+ }
79
+ catch (error) {
80
+ this.handleApiError(error);
81
+ }
82
+ }
83
+ }
84
+ exports.default = AgentsEgress;
@@ -0,0 +1,14 @@
1
+ import { MailboxHumanCommand } from '../../../lib/mailbox-human-command';
2
+ export default class AgentsMailboxMessages extends MailboxHumanCommand {
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
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const mailbox_human_command_1 = require("../../../lib/mailbox-human-command");
5
+ const agent_mailbox_1 = require("../../../lib/agent-mailbox");
6
+ class AgentsMailboxMessages extends mailbox_human_command_1.MailboxHumanCommand {
7
+ static description = 'List received mailbox message metadata (human operator only; view content in agent settings)';
8
+ static examples = [
9
+ '<%= config.bin %> agents mailbox messages <agent-id> --json',
10
+ '<%= config.bin %> agents mailbox messages <agent-id> --limit 25 --cursor <cursor>',
11
+ ];
12
+ static args = {
13
+ id: core_1.Args.string({ description: 'Agent ID', required: true, ignoreStdin: true }),
14
+ };
15
+ static flags = {
16
+ json: core_1.Flags.boolean({ description: 'Output message metadata and nextCursor as JSON' }),
17
+ limit: core_1.Flags.integer({
18
+ description: 'Messages per page (1–100)',
19
+ default: 25,
20
+ min: 1,
21
+ max: 100,
22
+ }),
23
+ cursor: core_1.Flags.string({ description: 'Opaque nextCursor from a previous page' }),
24
+ };
25
+ async run() {
26
+ this.requireHumanMailboxAuth();
27
+ const { args, flags } = await this.parse(AgentsMailboxMessages);
28
+ let result;
29
+ try {
30
+ result = await (0, agent_mailbox_1.getAgentMailboxMessageMetadata)(args.id, {
31
+ limit: flags.limit,
32
+ cursor: flags.cursor,
33
+ });
34
+ }
35
+ catch (error) {
36
+ this.handleApiError(error);
37
+ }
38
+ if (flags.json) {
39
+ this.log(JSON.stringify(result, null, 2));
40
+ return;
41
+ }
42
+ if (result.data.length === 0)
43
+ this.log('No received messages on this page.');
44
+ for (const message of result.data) {
45
+ this.log(`${message.id} ${message.receivedAt} ${message.classification} ${message.status}`);
46
+ }
47
+ if (result.nextCursor)
48
+ this.log(`Next cursor: ${result.nextCursor}`);
49
+ this.log('Read mail content in the mailbox tab in agent settings.');
50
+ }
51
+ }
52
+ exports.default = AgentsMailboxMessages;
@@ -0,0 +1,13 @@
1
+ import { MailboxHumanCommand } from '../../../lib/mailbox-human-command';
2
+ export default class AgentsMailboxShow extends MailboxHumanCommand {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static examples: string[];
6
+ static args: {
7
+ id: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const mailbox_human_command_1 = require("../../../lib/mailbox-human-command");
5
+ const agent_mailbox_1 = require("../../../lib/agent-mailbox");
6
+ class AgentsMailboxShow extends mailbox_human_command_1.MailboxHumanCommand {
7
+ static description = "Show an agent's mailbox status and address (human operator only)";
8
+ static aliases = ['agents:mailbox:status'];
9
+ static examples = [
10
+ '<%= config.bin %> agents mailbox show <agent-id>',
11
+ '<%= config.bin %> agents mailbox status <agent-id> --json',
12
+ ];
13
+ static args = {
14
+ id: core_1.Args.string({ description: 'Agent ID', required: true, ignoreStdin: true }),
15
+ };
16
+ static flags = { json: core_1.Flags.boolean({ description: 'Output metadata as JSON' }) };
17
+ async run() {
18
+ this.requireHumanMailboxAuth();
19
+ const { args, flags } = await this.parse(AgentsMailboxShow);
20
+ let result;
21
+ try {
22
+ result = await (0, agent_mailbox_1.getAgentMailboxMetadata)(args.id);
23
+ }
24
+ catch (error) {
25
+ this.handleApiError(error);
26
+ }
27
+ if (flags.json) {
28
+ this.log(JSON.stringify(result, null, 2));
29
+ return;
30
+ }
31
+ const receiving = result.receivingRuntime?.status;
32
+ this.log(receiving === 'running'
33
+ ? 'Incoming processing: running (DNS and SMTP delivery are not verified by this command).'
34
+ : receiving === 'starting'
35
+ ? 'Incoming processing: starting. Refresh before using a recovery address.'
36
+ : receiving === 'unavailable'
37
+ ? 'Incoming processing: unavailable. Do not use this address for account recovery until receiving is restored.'
38
+ : 'Incoming processing: unverified. Refresh before using a recovery address.');
39
+ if (!result.mailbox) {
40
+ this.log('No mailbox provisioned. Configure the mailbox in the agent settings.');
41
+ return;
42
+ }
43
+ this.log(`Address: ${result.mailbox.address}`);
44
+ this.log(`Address lifecycle: ${result.mailbox.status}`);
45
+ this.log(`Sending: ${result.mailbox.sending}`);
46
+ if (result.mailbox.sendingPausedReason) {
47
+ this.log(`Sending paused: ${result.mailbox.sendingPausedReason}`);
48
+ }
49
+ this.log(`Version: ${result.mailbox.version}`);
50
+ }
51
+ }
52
+ exports.default = AgentsMailboxShow;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const data_provider_1 = require("@skrr-ai/data-provider");
3
4
  const core_1 = require("@oclif/core");
4
5
  const base_command_1 = require("../../base-command");
5
6
  const roles_1 = require("../../lib/roles");
@@ -26,6 +27,13 @@ class AgentOperatingPlan extends base_command_1.BaseCommand {
26
27
  this.log(` Responsibility: ${r.purpose}`);
27
28
  this.log(` Evidence: ${r.evidence.status}${r.evidence.issues?.length ? ` (${r.evidence.issues.join(', ')})` : ''}`);
28
29
  this.log(" Execution authority: tools, sandbox and approvals use the Agent's runtime permissions.");
30
+ for (const observation of r.evidenceAuthority?.observations || []) {
31
+ const comparison = (0, data_provider_1.describeObservationChange)({
32
+ ...observation.serverComparison,
33
+ changeReason: observation.serverComparison.reason,
34
+ });
35
+ this.log(` Observation: ${observation.key} — ${comparison.reason}${comparison.progress ? ` ${comparison.progress}` : ''}${comparison.reference ? `; ${comparison.reference}` : ''} (AGENT-REPORTED)`);
36
+ }
29
37
  for (const q of r.inquiries)
30
38
  this.log(` Inquiry: ${q.question} [${q.status}] — ${q.decisionImpact}`);
31
39
  for (const w of r.work)
@@ -0,0 +1,16 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ export default class RolesCapture 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
+ key: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ title: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ commitment: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ compass: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const node_fs_1 = require("node:fs");
5
+ const base_command_1 = require("../../../base-command");
6
+ const roles_1 = require("../../../lib/roles");
7
+ class RolesCapture extends base_command_1.BaseCommand {
8
+ static description = 'Capture selected owner responsibilities as a portable role draft with explicit omissions';
9
+ static args = {
10
+ id: core_1.Args.string({ required: true, ignoreStdin: true, description: 'Agent ID' }),
11
+ };
12
+ static flags = {
13
+ key: core_1.Flags.string({ required: true, description: 'Portable role key' }),
14
+ title: core_1.Flags.string({ required: true, description: 'Role title' }),
15
+ commitment: core_1.Flags.string({
16
+ required: true,
17
+ multiple: true,
18
+ description: 'Responsibility ID (repeat for each)',
19
+ }),
20
+ compass: core_1.Flags.string({ description: 'Compass to capture' }),
21
+ output: core_1.Flags.string({ description: 'Save portable spec JSON for review' }),
22
+ json: core_1.Flags.boolean({ description: 'Output draft and omissions as JSON' }),
23
+ };
24
+ async run() {
25
+ this.requireAuth();
26
+ const { args, flags } = await this.parse(RolesCapture);
27
+ try {
28
+ const result = await roles_1.roleApi.capture(args.id, {
29
+ key: flags.key,
30
+ title: flags.title,
31
+ commitmentIds: flags.commitment,
32
+ ...(flags.compass ? { compassId: flags.compass } : {}),
33
+ });
34
+ if (flags.output)
35
+ (0, node_fs_1.writeFileSync)(flags.output, `${JSON.stringify(result.spec, null, 2)}\n`, { mode: 0o600 });
36
+ if (flags.json) {
37
+ this.log(JSON.stringify(result, null, 2));
38
+ return;
39
+ }
40
+ this.log(`Captured ${result.spec.title}; review before installation.`);
41
+ for (const omission of result.omitted)
42
+ this.log(`Omitted ${omission.responsibilityKey || 'role'}.${omission.field}: ${omission.reason}`);
43
+ for (const prerequisite of result.prerequisites)
44
+ this.log(prerequisite);
45
+ if (flags.output)
46
+ this.log(`Portable draft saved to ${flags.output}.`);
47
+ }
48
+ catch (error) {
49
+ this.handleApiError(error);
50
+ }
51
+ }
52
+ }
53
+ exports.default = RolesCapture;
@@ -6,6 +6,7 @@ export default class RolesInstall extends BaseCommand {
6
6
  };
7
7
  static flags: {
8
8
  preview: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ 'confirm-rule-conflict': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
10
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
11
  };
11
12
  run(): Promise<void>;
@@ -13,6 +13,10 @@ class RolesInstall extends base_command_1.BaseCommand {
13
13
  required: true,
14
14
  description: 'Server-generated preview JSON saved by agents roles preview',
15
15
  }),
16
+ 'confirm-rule-conflict': core_1.Flags.string({
17
+ multiple: true,
18
+ description: 'Rule id the role revision changed or removes and you also edited: overwrite or delete your edit (shown as conflicts_with_owner_edit or removed_owner_edited in the preview)',
19
+ }),
16
20
  json: core_1.Flags.boolean({ description: 'Output the installation receipt as JSON' }),
17
21
  };
18
22
  async run() {
@@ -21,7 +25,10 @@ class RolesInstall extends base_command_1.BaseCommand {
21
25
  try {
22
26
  const preview = (0, roles_1.readRoleJson)(flags.preview);
23
27
  (0, roles_1.assertRolePreview)(preview);
24
- const receipt = await roles_1.roleApi.install(args.id, preview);
28
+ const confirmed = flags['confirm-rule-conflict'] ?? [];
29
+ const receipt = confirmed.length
30
+ ? await roles_1.roleApi.install(args.id, preview, confirmed)
31
+ : await roles_1.roleApi.install(args.id, preview);
25
32
  if (flags.json)
26
33
  this.log(JSON.stringify(receipt, null, 2));
27
34
  else {
@@ -6,6 +6,8 @@ export default class RolesPreview extends BaseCommand {
6
6
  };
7
7
  static flags: {
8
8
  file: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
9
+ params: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ endpoints: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
11
  bindings: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
12
  output: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
13
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;