@wave-ai-os/wave-cli 0.1.86 → 0.1.88

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.
package/dist/index.cjs CHANGED
@@ -3,11 +3,230 @@
3
3
 
4
4
  // src/index.ts
5
5
  var import_commander3 = require("commander");
6
- var import_zod21 = require("zod");
6
+ var import_zod22 = require("zod");
7
7
 
8
8
  // src/cli.ts
9
9
  var import_commander2 = require("commander");
10
10
 
11
+ // src/authStorage.ts
12
+ var import_node_child_process = require("child_process");
13
+ var import_node_fs = require("fs");
14
+ var import_promises = require("fs/promises");
15
+ var import_node_os = require("os");
16
+ var import_node_path = require("path");
17
+ var import_node_util = require("util");
18
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
19
+ var KEYCHAIN_SERVICE = "wave-cli";
20
+ var FILE_NAME = "auth-token.json";
21
+ var DEFAULT_STORAGE_MODE = "auto";
22
+ var activeOptions = {};
23
+ function configureAuthStorage(options) {
24
+ activeOptions = { ...options };
25
+ }
26
+ async function withAuthStorageOptions(options, callback) {
27
+ const previous = activeOptions;
28
+ activeOptions = { ...options };
29
+ try {
30
+ return await callback();
31
+ } finally {
32
+ activeOptions = previous;
33
+ }
34
+ }
35
+ function normalize(raw) {
36
+ if (typeof raw !== "string") return void 0;
37
+ const trimmed = raw.trim();
38
+ return trimmed.length > 0 ? trimmed : void 0;
39
+ }
40
+ function authHome() {
41
+ return normalize(activeOptions.home) ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".wave");
42
+ }
43
+ function tokenPath() {
44
+ return (0, import_node_path.join)(authHome(), FILE_NAME);
45
+ }
46
+ function configPath() {
47
+ return normalize(activeOptions.configPath) ?? (0, import_node_path.join)(authHome(), "config.json");
48
+ }
49
+ function storageMode() {
50
+ return activeOptions.mode ?? DEFAULT_STORAGE_MODE;
51
+ }
52
+ function accountForBaseUrl(baseUrl) {
53
+ return normalize(baseUrl) ?? "default";
54
+ }
55
+ async function commandExists(command) {
56
+ try {
57
+ await (0, import_promises.access)(command, import_node_fs.constants.X_OK);
58
+ return true;
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+ async function keychainAvailable() {
64
+ if (process.platform !== "darwin") return false;
65
+ if (storageMode() === "file" || storageMode() === "disabled") return false;
66
+ return commandExists("/usr/bin/security");
67
+ }
68
+ async function preferredStorage() {
69
+ const mode = storageMode();
70
+ if (mode === "disabled") return "disabled";
71
+ if (mode === "file") return "file";
72
+ if (mode === "keychain") return await keychainAvailable() ? "keychain" : "file";
73
+ return await keychainAvailable() ? "keychain" : "file";
74
+ }
75
+ async function readKeychainToken(baseUrl) {
76
+ try {
77
+ const { stdout } = await execFileAsync("/usr/bin/security", [
78
+ "find-generic-password",
79
+ "-a",
80
+ accountForBaseUrl(baseUrl),
81
+ "-s",
82
+ KEYCHAIN_SERVICE,
83
+ "-w"
84
+ ], { encoding: "utf8" });
85
+ return normalize(String(stdout)) ?? null;
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+ async function writeKeychainToken(token, baseUrl) {
91
+ await execFileAsync("/usr/bin/security", [
92
+ "add-generic-password",
93
+ "-a",
94
+ accountForBaseUrl(baseUrl),
95
+ "-s",
96
+ KEYCHAIN_SERVICE,
97
+ "-w",
98
+ token,
99
+ "-U"
100
+ ]);
101
+ }
102
+ async function deleteKeychainToken(baseUrl) {
103
+ try {
104
+ await execFileAsync("/usr/bin/security", [
105
+ "delete-generic-password",
106
+ "-a",
107
+ accountForBaseUrl(baseUrl),
108
+ "-s",
109
+ KEYCHAIN_SERVICE
110
+ ]);
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ }
116
+ async function readFileToken(baseUrl) {
117
+ const path = tokenPath();
118
+ if (!(0, import_node_fs.existsSync)(path)) return null;
119
+ try {
120
+ const raw = await (0, import_promises.readFile)(path, "utf8");
121
+ const payload = JSON.parse(raw);
122
+ const token = normalize(payload.token);
123
+ const storedBaseUrl = normalize(payload.baseUrl);
124
+ const requestedBaseUrl = normalize(baseUrl);
125
+ if (!token) return null;
126
+ if (storedBaseUrl !== requestedBaseUrl) return null;
127
+ return token;
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ async function writeFileToken(token, baseUrl) {
133
+ const home = authHome();
134
+ const path = tokenPath();
135
+ await (0, import_promises.mkdir)(home, { recursive: true, mode: 448 });
136
+ await (0, import_promises.writeFile)(
137
+ path,
138
+ `${JSON.stringify({ token, baseUrl: baseUrl ?? null, updatedAt: (/* @__PURE__ */ new Date()).toISOString() })}
139
+ `,
140
+ { mode: 384 }
141
+ );
142
+ await (0, import_promises.chmod)(path, 384);
143
+ }
144
+ async function deleteFileToken() {
145
+ const path = tokenPath();
146
+ if (!(0, import_node_fs.existsSync)(path)) return false;
147
+ await (0, import_promises.rm)(path, { force: true });
148
+ return true;
149
+ }
150
+ async function readStoredToken(baseUrl) {
151
+ const mode = await preferredStorage();
152
+ if (mode === "disabled") return null;
153
+ if (mode === "keychain") {
154
+ const keychainToken = await readKeychainToken(baseUrl);
155
+ if (keychainToken) return { token: keychainToken, source: "keychain" };
156
+ }
157
+ const fileToken = await readFileToken(baseUrl);
158
+ return fileToken ? { token: fileToken, source: "file" } : null;
159
+ }
160
+ async function writeStoredToken(token, baseUrl) {
161
+ const mode = await preferredStorage();
162
+ if (mode === "disabled") {
163
+ return { kind: "disabled", available: false };
164
+ }
165
+ if (mode === "keychain") {
166
+ try {
167
+ await writeKeychainToken(token, baseUrl);
168
+ return {
169
+ kind: "keychain",
170
+ available: true,
171
+ service: KEYCHAIN_SERVICE,
172
+ account: accountForBaseUrl(baseUrl)
173
+ };
174
+ } catch {
175
+ await writeFileToken(token, baseUrl);
176
+ return { kind: "file", available: true, path: tokenPath() };
177
+ }
178
+ }
179
+ await writeFileToken(token, baseUrl);
180
+ return { kind: "file", available: true, path: tokenPath() };
181
+ }
182
+ async function persistBaseUrl(baseUrl) {
183
+ const path = configPath();
184
+ let existing = {};
185
+ if ((0, import_node_fs.existsSync)(path)) {
186
+ const raw = await (0, import_promises.readFile)(path, "utf8");
187
+ const parsed = JSON.parse(raw);
188
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
189
+ throw new Error(`Wave config file must contain a JSON object: ${path}`);
190
+ }
191
+ existing = parsed;
192
+ }
193
+ await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
194
+ await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
195
+ `, {
196
+ mode: 384
197
+ });
198
+ await (0, import_promises.chmod)(path, 384);
199
+ return path;
200
+ }
201
+ async function removeStoredToken(baseUrl) {
202
+ const removedKeychain = await deleteKeychainToken(baseUrl);
203
+ const removedFile = await deleteFileToken();
204
+ return removedKeychain || removedFile;
205
+ }
206
+ async function getAuthStorageInfo(baseUrl) {
207
+ const mode = await preferredStorage();
208
+ if (mode === "disabled") return { kind: "disabled", available: false };
209
+ if (mode === "keychain") {
210
+ return {
211
+ kind: "keychain",
212
+ available: true,
213
+ service: KEYCHAIN_SERVICE,
214
+ account: accountForBaseUrl(baseUrl)
215
+ };
216
+ }
217
+ const path = tokenPath();
218
+ let available = true;
219
+ if ((0, import_node_fs.existsSync)(path)) {
220
+ try {
221
+ const modeBits = (await (0, import_promises.stat)(path)).mode & 511;
222
+ available = modeBits === 384;
223
+ } catch {
224
+ available = false;
225
+ }
226
+ }
227
+ return { kind: "file", available, path };
228
+ }
229
+
11
230
  // src/commands/tasks.ts
12
231
  var import_zod3 = require("zod");
13
232
 
@@ -192,7 +411,7 @@ var ATLAS_LEDGER_VARIABLE_TYPES = {
192
411
  };
193
412
  var SECRET_KEY_PATTERN = /(authorization|password|passwd|secret|token|jwt|credential|api[_-]?key)/i;
194
413
  var MAX_EVIDENCE_DEPTH = 5;
195
- function normalize(raw) {
414
+ function normalize2(raw) {
196
415
  if (typeof raw !== "string") {
197
416
  return void 0;
198
417
  }
@@ -200,12 +419,12 @@ function normalize(raw) {
200
419
  return trimmed.length > 0 ? trimmed : void 0;
201
420
  }
202
421
  function atlasContextFromConfig(config) {
203
- const organizationId = normalize(config.organizationId);
204
- const memberId = normalize(config.atlasMemberId);
205
- const chatId = normalize(config.atlasChatId);
206
- const assistantMessageId = normalize(config.atlasAssistantMessageId);
207
- const activeTool = normalize(config.atlasActiveTool);
208
- const targetTool = normalize(config.atlasTargetTool);
422
+ const organizationId = normalize2(config.organizationId);
423
+ const memberId = normalize2(config.atlasMemberId);
424
+ const chatId = normalize2(config.atlasChatId);
425
+ const assistantMessageId = normalize2(config.atlasAssistantMessageId);
426
+ const activeTool = normalize2(config.atlasActiveTool);
427
+ const targetTool = normalize2(config.atlasTargetTool);
209
428
  if (!organizationId || !memberId || !chatId || !assistantMessageId || !activeTool || !targetTool) {
210
429
  return null;
211
430
  }
@@ -216,8 +435,8 @@ function atlasContextFromConfig(config) {
216
435
  assistantMessageId,
217
436
  activeTool,
218
437
  targetTool,
219
- routeReason: normalize(config.atlasRouteReason),
220
- actionId: normalize(config.atlasActionId)
438
+ routeReason: normalize2(config.atlasRouteReason),
439
+ actionId: normalize2(config.atlasActionId)
221
440
  };
222
441
  }
223
442
  function summarizeVariableShape(value, key = void 0, depth = 0) {
@@ -253,7 +472,7 @@ function shouldReportAtlasActionLedgerEvent(input) {
253
472
  return input.operationType === "mutation" && input.field !== ATLAS_LEDGER_FIELD;
254
473
  }
255
474
  function deterministicAtlasActionId(input, config) {
256
- const requestSegment = normalize(config.requestId) ? `:${config.requestId}` : "";
475
+ const requestSegment = normalize2(config.requestId) ? `:${config.requestId}` : "";
257
476
  return `cli:${input.command}:${input.field}${requestSegment}`;
258
477
  }
259
478
  function buildAtlasEvidenceRefs(params) {
@@ -584,118 +803,6 @@ function buildSparse422Diagnostic(input) {
584
803
  }
585
804
  };
586
805
  }
587
- function isFeedbackCreateCommand(input) {
588
- return input.operationType === "mutation" && input.command === "feedbacks.create";
589
- }
590
- function asRecord(value) {
591
- if (!value || typeof value !== "object" || Array.isArray(value)) {
592
- return null;
593
- }
594
- return value;
595
- }
596
- function asNonEmptyString(value) {
597
- if (typeof value !== "string") {
598
- return null;
599
- }
600
- const trimmed = value.trim();
601
- return trimmed.length > 0 ? trimmed : null;
602
- }
603
- function extractFeedbackIdentity(variables) {
604
- const organizationId = asNonEmptyString(variables.organization_id) ?? asNonEmptyString(variables.organizationId);
605
- const params = asRecord(variables.params);
606
- const feedback = params ? asRecord(params.feedback) : null;
607
- const name = feedback ? asNonEmptyString(feedback.name) : null;
608
- const quarter = feedback ? asNonEmptyString(feedback.quarter) : null;
609
- const year = feedback ? asNonEmptyString(feedback.year) : null;
610
- if (!organizationId || !name || !quarter || !year) {
611
- return null;
612
- }
613
- return {
614
- organizationId,
615
- name,
616
- quarter,
617
- year
618
- };
619
- }
620
- function collectMessageStrings(value) {
621
- if (typeof value === "string") {
622
- return [value];
623
- }
624
- if (Array.isArray(value)) {
625
- return value.flatMap((entry2) => collectMessageStrings(entry2));
626
- }
627
- if (!value || typeof value !== "object") {
628
- return [];
629
- }
630
- return Object.values(value).flatMap(
631
- (entry2) => collectMessageStrings(entry2)
632
- );
633
- }
634
- function isDuplicateFeedbackMutationError(mutationPayload) {
635
- const messages = collectMessageStrings(mutationPayload.errors);
636
- return messages.some(
637
- (message) => message.toLowerCase().includes("already been taken")
638
- );
639
- }
640
- function extractFeedbackListNode(graph) {
641
- const data = asRecord(graph.data);
642
- const feedbacks = data ? asRecord(data.feedbacks) : null;
643
- if (!feedbacks) {
644
- return null;
645
- }
646
- const rows = Array.isArray(feedbacks.data) ? feedbacks.data : [];
647
- const first = rows.find((entry2) => asRecord(entry2));
648
- return first ? first : null;
649
- }
650
- function buildFeedbackReuseEnvelope(params) {
651
- return {
652
- envelope: buildEnvelope({
653
- ok: true,
654
- command: params.command,
655
- status: params.status,
656
- data: {
657
- [params.field]: {
658
- ok: true,
659
- status: params.status,
660
- errorCode: null,
661
- data: {
662
- data: params.feedbackNode
663
- },
664
- errors: null,
665
- reusedExisting: true,
666
- idempotency: {
667
- reason: params.reason
668
- }
669
- }
670
- },
671
- error: null,
672
- requestId: params.requestId
673
- }),
674
- exitCode: EXIT_CODES.success
675
- };
676
- }
677
- function buildFeedbackFindRequestBody(command, identity) {
678
- return buildGraphqlBody({
679
- config: {
680
- baseUrl: "http://localhost",
681
- token: "placeholder",
682
- timeoutMs: 1e3,
683
- debug: false
684
- },
685
- command,
686
- operationType: "query",
687
- field: "feedbacks",
688
- variables: {
689
- organization_id: identity.organizationId,
690
- name: identity.name,
691
- quarter: identity.quarter,
692
- year: identity.year,
693
- page: 1,
694
- per: 1
695
- },
696
- selectionSet: "{ data { id type attributes { id name slug year quarter organizationId memberIds } } count currentPage totalPages }"
697
- });
698
- }
699
806
  async function requestGraphqlHttp(params) {
700
807
  const response = await fetch(params.url, {
701
808
  method: "POST",
@@ -787,29 +894,6 @@ async function finalizeGraphqlResult(input, url, result) {
787
894
  }
788
895
  return result;
789
896
  }
790
- async function findExistingFeedback(params) {
791
- const command = `${params.input.command}.find-existing`;
792
- const body = buildFeedbackFindRequestBody(command, params.identity);
793
- const http = await requestGraphqlHttp({
794
- input: params.input,
795
- url: params.url,
796
- requestId: params.requestId,
797
- body,
798
- controller: params.controller
799
- });
800
- const gqlErrors = http.graph.errors;
801
- if (Array.isArray(gqlErrors) && gqlErrors.length > 0) {
802
- return null;
803
- }
804
- const feedbackNode = extractFeedbackListNode(http.graph);
805
- if (!feedbackNode) {
806
- return null;
807
- }
808
- return {
809
- feedbackNode,
810
- requestId: http.requestId
811
- };
812
- }
813
897
  function graphqlTypeForValue(value) {
814
898
  if (Array.isArray(value)) {
815
899
  const firstNonNull = value.find((item) => item !== null && item !== void 0);
@@ -909,32 +993,6 @@ async function graphqlRequest(input) {
909
993
  const controller = new AbortController();
910
994
  const timeoutId = setTimeout(() => controller.abort(), input.config.timeoutMs);
911
995
  try {
912
- if (isFeedbackCreateCommand(input)) {
913
- const feedbackIdentity = extractFeedbackIdentity(input.variables);
914
- if (feedbackIdentity) {
915
- const existing = await findExistingFeedback({
916
- input,
917
- url,
918
- requestId,
919
- controller,
920
- identity: feedbackIdentity
921
- });
922
- if (existing) {
923
- return finalizeGraphqlResult(
924
- input,
925
- url,
926
- buildFeedbackReuseEnvelope({
927
- command: input.command,
928
- field: input.field,
929
- status: 200,
930
- requestId: existing.requestId,
931
- feedbackNode: existing.feedbackNode,
932
- reason: "preexisting"
933
- })
934
- );
935
- }
936
- }
937
- }
938
996
  const http = await requestGraphqlHttpWithRetry({
939
997
  input,
940
998
  url,
@@ -979,32 +1037,6 @@ async function graphqlRequest(input) {
979
1037
  const ok = Boolean(mutationPayload.ok);
980
1038
  const status = typeof mutationPayload.status === "number" ? mutationPayload.status : ok ? 200 : 400;
981
1039
  if (!ok) {
982
- if (isFeedbackCreateCommand(input) && isDuplicateFeedbackMutationError(mutationPayload)) {
983
- const feedbackIdentity = extractFeedbackIdentity(input.variables);
984
- if (feedbackIdentity) {
985
- const existing = await findExistingFeedback({
986
- input,
987
- url,
988
- requestId: responseRequestId,
989
- controller,
990
- identity: feedbackIdentity
991
- });
992
- if (existing) {
993
- return finalizeGraphqlResult(
994
- input,
995
- url,
996
- buildFeedbackReuseEnvelope({
997
- command: input.command,
998
- field: input.field,
999
- status: 200,
1000
- requestId: existing.requestId,
1001
- feedbackNode: existing.feedbackNode,
1002
- reason: "duplicate_race"
1003
- })
1004
- );
1005
- }
1006
- }
1007
- }
1008
1040
  const mutationErrors = mutationPayload.errors ?? null;
1009
1041
  const details = {
1010
1042
  errors: mutationErrors,
@@ -1094,7 +1126,7 @@ async function graphqlRequest(input) {
1094
1126
  }
1095
1127
 
1096
1128
  // src/output.ts
1097
- var import_node_fs = require("fs");
1129
+ var import_node_fs2 = require("fs");
1098
1130
  var RETRYABLE_WRITE_CODES = /* @__PURE__ */ new Set(["EAGAIN", "EINTR"]);
1099
1131
  var RETRY_BACKOFF_MS = 1;
1100
1132
  var EnvelopeEmittedSignal = class extends Error {
@@ -1113,7 +1145,7 @@ function writeStdoutFully(text) {
1113
1145
  let offset = 0;
1114
1146
  while (offset < buffer.length) {
1115
1147
  try {
1116
- const bytesWritten = (0, import_node_fs.writeSync)(fd, buffer, offset, buffer.length - offset);
1148
+ const bytesWritten = (0, import_node_fs2.writeSync)(fd, buffer, offset, buffer.length - offset);
1117
1149
  if (bytesWritten <= 0) {
1118
1150
  sleepBriefly(RETRY_BACKOFF_MS);
1119
1151
  continue;
@@ -1165,6 +1197,8 @@ var RESOURCE_QUERY_FIELDS = {
1165
1197
  "archivedAt",
1166
1198
  "organizationId",
1167
1199
  "memberId",
1200
+ "member",
1201
+ "assignee",
1168
1202
  "creatorId",
1169
1203
  "projectId",
1170
1204
  "projectSlug",
@@ -1212,6 +1246,7 @@ var RESOURCE_QUERY_FIELDS = {
1212
1246
  "role",
1213
1247
  "status",
1214
1248
  "title",
1249
+ "rolePurpose",
1215
1250
  "firstName",
1216
1251
  "lastName",
1217
1252
  "createdAt",
@@ -1457,14 +1492,6 @@ var RESOURCE_QUERY_FIELDS = {
1457
1492
  "acceptedAnswerIds",
1458
1493
  "labelIds"
1459
1494
  ],
1460
- feedback: [
1461
- "name",
1462
- "slug",
1463
- "year",
1464
- "quarter",
1465
- "organizationId",
1466
- "memberIds"
1467
- ],
1468
1495
  survey: [
1469
1496
  "name",
1470
1497
  "slug",
@@ -1626,7 +1653,6 @@ var RESOURCE_FIELD_ALIASES = {
1626
1653
  stand_ups: "stand_up",
1627
1654
  headlines: "headline",
1628
1655
  questions: "question",
1629
- feedbacks: "feedback",
1630
1656
  surveys: "survey",
1631
1657
  responsibilities: "responsibility",
1632
1658
  smart_kpi_views: "smart_kpi_view",
@@ -1662,7 +1688,8 @@ function defaultQuerySelectionSet(field, isList) {
1662
1688
  const canonicalField = RESOURCE_FIELD_ALIASES[field] ?? field;
1663
1689
  const explicitFields = RESOURCE_QUERY_FIELDS[canonicalField];
1664
1690
  if (explicitFields) {
1665
- const attributes = explicitFields.length > 0 ? `attributes { ${Array.from(/* @__PURE__ */ new Set(["id", ...explicitFields])).join(" ")} }` : "attributes";
1691
+ const detailFields = canonicalField === "smart_kpi" && !isList ? ["smartKpiMetrics { id date value }", "smartKpiGoals { id date value }"] : [];
1692
+ const attributes = explicitFields.length > 0 ? `attributes { ${Array.from(/* @__PURE__ */ new Set(["id", ...explicitFields, ...detailFields])).join(" ")} }` : "attributes";
1666
1693
  if (isList) {
1667
1694
  return `{ data { id type ${attributes} } count currentPage totalPages }`;
1668
1695
  }
@@ -1881,213 +1908,6 @@ var import_node_fs3 = require("fs");
1881
1908
  var import_promises2 = require("fs/promises");
1882
1909
  var import_node_path2 = require("path");
1883
1910
 
1884
- // src/authStorage.ts
1885
- var import_node_child_process = require("child_process");
1886
- var import_node_fs2 = require("fs");
1887
- var import_promises = require("fs/promises");
1888
- var import_node_os = require("os");
1889
- var import_node_path = require("path");
1890
- var import_node_util = require("util");
1891
- var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
1892
- var KEYCHAIN_SERVICE = "wave-cli";
1893
- var FILE_NAME = "auth-token.json";
1894
- function normalize2(raw) {
1895
- if (typeof raw !== "string") return void 0;
1896
- const trimmed = raw.trim();
1897
- return trimmed.length > 0 ? trimmed : void 0;
1898
- }
1899
- function authHome(env = process.env) {
1900
- return normalize2(env.WAVE_CLI_HOME) ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".wave");
1901
- }
1902
- function tokenPath(env = process.env) {
1903
- return (0, import_node_path.join)(authHome(env), FILE_NAME);
1904
- }
1905
- function configPath(env = process.env) {
1906
- return normalize2(env.WAVE_CONFIG_PATH) ?? (0, import_node_path.join)(authHome(env), "config.json");
1907
- }
1908
- function storageMode(env = process.env) {
1909
- const raw = normalize2(env.WAVE_CLI_AUTH_STORAGE)?.toLowerCase();
1910
- if (raw === "keychain" || raw === "file" || raw === "disabled") return raw;
1911
- return "auto";
1912
- }
1913
- function accountForBaseUrl(baseUrl) {
1914
- return normalize2(baseUrl) ?? "default";
1915
- }
1916
- async function commandExists(command) {
1917
- try {
1918
- await (0, import_promises.access)(command, import_node_fs2.constants.X_OK);
1919
- return true;
1920
- } catch {
1921
- return false;
1922
- }
1923
- }
1924
- async function keychainAvailable(env = process.env) {
1925
- if (process.platform !== "darwin") return false;
1926
- if (storageMode(env) === "file" || storageMode(env) === "disabled") return false;
1927
- return commandExists("/usr/bin/security");
1928
- }
1929
- async function preferredStorage(env = process.env) {
1930
- const mode = storageMode(env);
1931
- if (mode === "disabled") return "disabled";
1932
- if (mode === "file") return "file";
1933
- if (mode === "keychain") return await keychainAvailable(env) ? "keychain" : "file";
1934
- return await keychainAvailable(env) ? "keychain" : "file";
1935
- }
1936
- async function readKeychainToken(baseUrl) {
1937
- try {
1938
- const { stdout } = await execFileAsync("/usr/bin/security", [
1939
- "find-generic-password",
1940
- "-a",
1941
- accountForBaseUrl(baseUrl),
1942
- "-s",
1943
- KEYCHAIN_SERVICE,
1944
- "-w"
1945
- ], { encoding: "utf8" });
1946
- return normalize2(String(stdout)) ?? null;
1947
- } catch {
1948
- return null;
1949
- }
1950
- }
1951
- async function writeKeychainToken(token, baseUrl) {
1952
- await execFileAsync("/usr/bin/security", [
1953
- "add-generic-password",
1954
- "-a",
1955
- accountForBaseUrl(baseUrl),
1956
- "-s",
1957
- KEYCHAIN_SERVICE,
1958
- "-w",
1959
- token,
1960
- "-U"
1961
- ]);
1962
- }
1963
- async function deleteKeychainToken(baseUrl) {
1964
- try {
1965
- await execFileAsync("/usr/bin/security", [
1966
- "delete-generic-password",
1967
- "-a",
1968
- accountForBaseUrl(baseUrl),
1969
- "-s",
1970
- KEYCHAIN_SERVICE
1971
- ]);
1972
- return true;
1973
- } catch {
1974
- return false;
1975
- }
1976
- }
1977
- async function readFileToken(baseUrl, env = process.env) {
1978
- const path = tokenPath(env);
1979
- if (!(0, import_node_fs2.existsSync)(path)) return null;
1980
- try {
1981
- const raw = await (0, import_promises.readFile)(path, "utf8");
1982
- const payload = JSON.parse(raw);
1983
- const token = normalize2(payload.token);
1984
- const storedBaseUrl = normalize2(payload.baseUrl);
1985
- const requestedBaseUrl = normalize2(baseUrl);
1986
- if (!token) return null;
1987
- if (storedBaseUrl !== requestedBaseUrl) return null;
1988
- return token;
1989
- } catch {
1990
- return null;
1991
- }
1992
- }
1993
- async function writeFileToken(token, baseUrl, env = process.env) {
1994
- const home = authHome(env);
1995
- const path = tokenPath(env);
1996
- await (0, import_promises.mkdir)(home, { recursive: true, mode: 448 });
1997
- await (0, import_promises.writeFile)(
1998
- path,
1999
- `${JSON.stringify({ token, baseUrl: baseUrl ?? null, updatedAt: (/* @__PURE__ */ new Date()).toISOString() })}
2000
- `,
2001
- { mode: 384 }
2002
- );
2003
- await (0, import_promises.chmod)(path, 384);
2004
- }
2005
- async function deleteFileToken(env = process.env) {
2006
- const path = tokenPath(env);
2007
- if (!(0, import_node_fs2.existsSync)(path)) return false;
2008
- await (0, import_promises.rm)(path, { force: true });
2009
- return true;
2010
- }
2011
- async function readStoredToken(baseUrl) {
2012
- const mode = await preferredStorage();
2013
- if (mode === "disabled") return null;
2014
- if (mode === "keychain") {
2015
- const keychainToken = await readKeychainToken(baseUrl);
2016
- if (keychainToken) return { token: keychainToken, source: "keychain" };
2017
- }
2018
- const fileToken = await readFileToken(baseUrl);
2019
- return fileToken ? { token: fileToken, source: "file" } : null;
2020
- }
2021
- async function writeStoredToken(token, baseUrl) {
2022
- const mode = await preferredStorage();
2023
- if (mode === "disabled") {
2024
- return { kind: "disabled", available: false };
2025
- }
2026
- if (mode === "keychain") {
2027
- try {
2028
- await writeKeychainToken(token, baseUrl);
2029
- return {
2030
- kind: "keychain",
2031
- available: true,
2032
- service: KEYCHAIN_SERVICE,
2033
- account: accountForBaseUrl(baseUrl)
2034
- };
2035
- } catch {
2036
- await writeFileToken(token, baseUrl);
2037
- return { kind: "file", available: true, path: tokenPath() };
2038
- }
2039
- }
2040
- await writeFileToken(token, baseUrl);
2041
- return { kind: "file", available: true, path: tokenPath() };
2042
- }
2043
- async function persistBaseUrl(baseUrl, env = process.env) {
2044
- const path = configPath(env);
2045
- let existing = {};
2046
- if ((0, import_node_fs2.existsSync)(path)) {
2047
- const raw = await (0, import_promises.readFile)(path, "utf8");
2048
- const parsed = JSON.parse(raw);
2049
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2050
- throw new Error(`Wave config file must contain a JSON object: ${path}`);
2051
- }
2052
- existing = parsed;
2053
- }
2054
- await (0, import_promises.mkdir)((0, import_node_path.dirname)(path), { recursive: true, mode: 448 });
2055
- await (0, import_promises.writeFile)(path, `${JSON.stringify({ ...existing, baseUrl }, null, 2)}
2056
- `, {
2057
- mode: 384
2058
- });
2059
- await (0, import_promises.chmod)(path, 384);
2060
- return path;
2061
- }
2062
- async function removeStoredToken(baseUrl) {
2063
- const removedKeychain = await deleteKeychainToken(baseUrl);
2064
- const removedFile = await deleteFileToken();
2065
- return removedKeychain || removedFile;
2066
- }
2067
- async function getAuthStorageInfo(baseUrl) {
2068
- const mode = await preferredStorage();
2069
- if (mode === "disabled") return { kind: "disabled", available: false };
2070
- if (mode === "keychain") {
2071
- return {
2072
- kind: "keychain",
2073
- available: true,
2074
- service: KEYCHAIN_SERVICE,
2075
- account: accountForBaseUrl(baseUrl)
2076
- };
2077
- }
2078
- const path = tokenPath();
2079
- let available = true;
2080
- if ((0, import_node_fs2.existsSync)(path)) {
2081
- try {
2082
- const modeBits = (await (0, import_promises.stat)(path)).mode & 511;
2083
- available = modeBits === 384;
2084
- } catch {
2085
- available = false;
2086
- }
2087
- }
2088
- return { kind: "file", available, path };
2089
- }
2090
-
2091
1911
  // src/authClient.ts
2092
1912
  var import_node_crypto2 = require("crypto");
2093
1913
 
@@ -2534,17 +2354,15 @@ async function resolveWithAuthenticatedOrganization(context) {
2534
2354
  if (organizationId) resolved.organizationId = organizationId;
2535
2355
  return resolved;
2536
2356
  }
2537
- function defaultConfigPath(env) {
2538
- const explicitEnv = normalize3(env.WAVE_CONFIG_PATH);
2539
- if (explicitEnv) return explicitEnv;
2540
- const candidate = (0, import_node_path2.join)(authHome(env), "config.json");
2357
+ function defaultConfigPath() {
2358
+ const candidate = (0, import_node_path2.join)(authHome(), "config.json");
2541
2359
  return (0, import_node_fs3.existsSync)(candidate) ? candidate : void 0;
2542
2360
  }
2543
2361
  async function resolveConfigFileContext(options, env) {
2544
2362
  const path = firstDefined(
2545
2363
  normalize3(options.configPath),
2546
2364
  normalize3(options.config),
2547
- defaultConfigPath(env)
2365
+ defaultConfigPath()
2548
2366
  );
2549
2367
  if (!path) return {};
2550
2368
  if (!(0, import_node_fs3.existsSync)(path)) {
@@ -2689,13 +2507,13 @@ function parseRequiredOption(raw, flag) {
2689
2507
  function optionKey(flag) {
2690
2508
  return flag.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
2691
2509
  }
2692
- function asRecord2(value) {
2510
+ function asRecord(value) {
2693
2511
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2694
2512
  }
2695
2513
  function visibleSearchText(row) {
2696
- const record = asRecord2(row);
2514
+ const record = asRecord(row);
2697
2515
  if (!record) return "";
2698
- const attributes = asRecord2(record.attributes);
2516
+ const attributes = asRecord(record.attributes);
2699
2517
  const values = [];
2700
2518
  for (const field of SEARCHABLE_VISIBLE_FIELDS) {
2701
2519
  const topLevelValue = record[field];
@@ -2709,7 +2527,7 @@ function matchesSearchQuery(row, query) {
2709
2527
  return visibleSearchText(row).includes(query.toLowerCase());
2710
2528
  }
2711
2529
  function filterListEnvelopeByQuery(payload, query) {
2712
- const record = asRecord2(payload);
2530
+ const record = asRecord(payload);
2713
2531
  if (!record || !Array.isArray(record.data)) return payload;
2714
2532
  const filteredData = record.data.filter((row) => matchesSearchQuery(row, query));
2715
2533
  return {
@@ -3636,9 +3454,65 @@ var subitemUpdateContract = {
3636
3454
  rootKey: "subitem",
3637
3455
  fields: subitemFields
3638
3456
  };
3457
+ var reminderFields = {
3458
+ title: { type: "string", example: "Follow up with customer" },
3459
+ description: { type: "string" },
3460
+ due_at: { type: "string" },
3461
+ starts_at: { type: "string" },
3462
+ timezone: { type: "string", example: "America/Phoenix" },
3463
+ schedule: {
3464
+ type: "object",
3465
+ example: { type: "once", due_at: "2026-09-01T09:00:00-07:00" }
3466
+ },
3467
+ notification: {
3468
+ type: "object",
3469
+ example: { channels: ["in_app"], lead_minutes: 15 }
3470
+ },
3471
+ resources_attributes: { type: "array" },
3472
+ reminder_delegates_attributes: { type: "array" }
3473
+ };
3474
+ var reminderCreateContract = {
3475
+ rootKey: "reminder",
3476
+ fields: reminderFields,
3477
+ required: ["title", "schedule", "notification"],
3478
+ additionalProperties: false
3479
+ };
3480
+ var reminderUpdateContract = {
3481
+ rootKey: "reminder",
3482
+ fields: reminderFields,
3483
+ additionalProperties: false
3484
+ };
3485
+ var sketchFields = {
3486
+ name: { type: "string" },
3487
+ creation_key: { type: "string" },
3488
+ member_id: { type: "string" },
3489
+ teams_ids: { type: "array", items: { type: "string" } },
3490
+ status: {
3491
+ type: "string",
3492
+ enum: ["backlog", "planned", "in_progress", "completed", "cancelled", "ready_for_qa", "blocked"]
3493
+ },
3494
+ priority: { type: "string", enum: PRIORITIES }
3495
+ };
3496
+ var sketchCreateContract = {
3497
+ rootKey: "sketch",
3498
+ fields: sketchFields,
3499
+ required: ["name", "teams_ids", "creation_key"],
3500
+ additionalProperties: false
3501
+ };
3502
+ var sketchMetadataUpdateContract = {
3503
+ rootKey: "sketch",
3504
+ fields: Object.fromEntries(
3505
+ Object.entries(sketchFields).filter(([field]) => field !== "creation_key")
3506
+ ),
3507
+ additionalProperties: false
3508
+ };
3639
3509
  var CONTRACTS = {
3640
3510
  "list-items.create": listItemCreateContract,
3641
3511
  "list-items.update": listItemUpdateContract,
3512
+ "reminders.create": reminderCreateContract,
3513
+ "reminders.update": reminderUpdateContract,
3514
+ "sketches.create": sketchCreateContract,
3515
+ "sketches.update-metadata": sketchMetadataUpdateContract,
3642
3516
  "subitems.create": subitemCreateContract,
3643
3517
  "subitems.update": subitemUpdateContract
3644
3518
  };
@@ -3710,8 +3584,10 @@ function validateOperationDataJson(operationId2, value) {
3710
3584
  const missing = (contract.required ?? []).filter(
3711
3585
  (field) => entity[field] === void 0 || entity[field] === null || entity[field] === ""
3712
3586
  );
3587
+ const unsupported = contract.additionalProperties === false ? Object.keys(entity).filter((field) => !Object.prototype.hasOwnProperty.call(contract.fields, field)) : [];
3713
3588
  return [
3714
3589
  ...missing.map((field) => `${contract.rootKey}.${field} is required.`),
3590
+ ...unsupported.map((field) => `${contract.rootKey}.${field} is not permitted.`),
3715
3591
  ...validateFields(contract.fields, entity, [contract.rootKey])
3716
3592
  ].map(
3717
3593
  (error) => `Invalid input value for dataJson: ${error}`
@@ -3755,14 +3631,25 @@ function entitySchema(contract) {
3755
3631
  ])
3756
3632
  ),
3757
3633
  ...contract.required ? { required: [...contract.required] } : {},
3758
- additionalProperties: true
3634
+ additionalProperties: contract.additionalProperties ?? true
3759
3635
  };
3760
3636
  }
3637
+ function exampleValue2(contract) {
3638
+ if (contract.example !== void 0) return contract.example;
3639
+ if (contract.type === "array") return [];
3640
+ if (contract.type === "object") return {};
3641
+ if (contract.type === "number") return 0;
3642
+ if (contract.type === "boolean") return false;
3643
+ return "example";
3644
+ }
3761
3645
  function exampleDataJsonForOperation(operationId2) {
3762
3646
  const contract = CONTRACTS[operationId2];
3763
3647
  if (!contract) return null;
3764
3648
  const entity = Object.fromEntries(
3765
- (contract.required ?? []).map((field) => [field, "example"])
3649
+ (contract.required ?? []).map((field) => {
3650
+ const fieldContract = contract.fields[field];
3651
+ return [field, fieldContract ? exampleValue2(fieldContract) : "example"];
3652
+ })
3766
3653
  );
3767
3654
  return { [contract.rootKey]: entity };
3768
3655
  }
@@ -3868,7 +3755,7 @@ function registerEntityCrudCommands(program, config) {
3868
3755
  const entityCommand = program.command(config.command).description(config.description);
3869
3756
  const createHelp4 = buildDataJsonHelp(config.rootKey, "create") ?? "JSON object, optionally wrapped with root key";
3870
3757
  const updateHelp5 = buildDataJsonHelp(config.rootKey, "update") ?? "JSON object, optionally wrapped with root key";
3871
- const listField2 = config.listField ?? (config.resourcePath === "feedback" ? "feedbacks" : config.resourcePath);
3758
+ const listField2 = config.listField ?? config.resourcePath;
3872
3759
  const list = entityCommand.command("list").option("--page <page>").option("--per <per>");
3873
3760
  const listParams = config.listParams ?? [];
3874
3761
  const listParamHelp = config.listParamHelp ?? {};
@@ -3908,12 +3795,14 @@ function registerEntityCrudCommands(program, config) {
3908
3795
  isList: true
3909
3796
  });
3910
3797
  });
3911
- registerGraphqlSearchCommand(entityCommand, {
3912
- command: config.command,
3913
- field: listField2,
3914
- variableTypes: config.listVariableTypes,
3915
- selectionSet: config.listSelectionSet
3916
- });
3798
+ if (config.registerSearch !== false) {
3799
+ registerGraphqlSearchCommand(entityCommand, {
3800
+ command: config.command,
3801
+ field: listField2,
3802
+ variableTypes: config.listVariableTypes,
3803
+ selectionSet: config.listSelectionSet
3804
+ });
3805
+ }
3917
3806
  const show = entityCommand.command("show").requiredOption("--id <id>");
3918
3807
  showParams.forEach((param) => {
3919
3808
  const cliParam = param.replace(/_/g, "-");
@@ -3924,7 +3813,7 @@ function registerEntityCrudCommands(program, config) {
3924
3813
  const context = await resolveCommandContext(cmd.optsWithGlobals());
3925
3814
  const organizationId = resolveOrganizationId(context.organizationId);
3926
3815
  const defaultCommand = `${config.command}.show`;
3927
- const defaultField = config.showField ?? (config.resourcePath === "feedback" ? "feedback" : toSingularResourceName(config.resourcePath));
3816
+ const defaultField = config.showField ?? toSingularResourceName(config.resourcePath);
3928
3817
  const mappedShowParams = Object.fromEntries(
3929
3818
  showParams.map((param) => {
3930
3819
  const optionKey2 = param.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
@@ -4008,6 +3897,22 @@ function registerEntityCrudCommands(program, config) {
4008
3897
  }
4009
3898
  });
4010
3899
  });
3900
+ for (const mutation of config.idMutationCommands ?? []) {
3901
+ entityCommand.command(mutation.command).description(mutation.description).requiredOption("--id <id>").action(async (opts, cmd) => {
3902
+ const id = idSchema2.parse(opts.id);
3903
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
3904
+ const organizationId = resolveOrganizationId(context.organizationId);
3905
+ await runGraphqlMutationCommand({
3906
+ command: `${config.command}.${mutation.command}`,
3907
+ runtimeOptions: context.runtimeOptions,
3908
+ field: mutation.field,
3909
+ variables: {
3910
+ organization_id: organizationId,
3911
+ [mutation.idVariable]: id
3912
+ }
3913
+ });
3914
+ });
3915
+ }
4011
3916
  }
4012
3917
  var __testables = {
4013
3918
  toSingularResourceName,
@@ -4038,13 +3943,13 @@ var projectPriorityValues = projectPrioritySchema.options.join(", ");
4038
3943
  var projectCreateDataJsonHelp = buildDataJsonHelp("project", "create") ?? 'JSON object for project or {"project": {...}}';
4039
3944
  var projectUpdateDataJsonHelp = buildDataJsonHelp("project", "update") ?? 'JSON object for project or {"project": {...}}';
4040
3945
  function projectsIndexMinimalSelectionSet(includeProjectTypes = false) {
4041
- return `{ count currentPage totalPages data { id type attributes { name slug status priority${includeProjectTypes ? " projectType" : ""} } } }`;
3946
+ return `{ count currentPage totalPages data { id type attributes { name slug status priority createdAt updatedAt${includeProjectTypes ? " projectType" : ""} } } }`;
4042
3947
  }
4043
3948
  var displayPreferenceAttributesSelectionSet = "attributes { id viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId }";
4044
3949
  var filterPreferenceAttributesSelectionSet = "attributes { id filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId }";
4045
3950
  var healthUpdateSummarySelectionSet = "id type value memberId status createdAt updatedAt updatableType updatableId parentUpdateId emojis { id name memberId } resources { ...ResourceSummaryFull }";
4046
3951
  var projectShowFullSelectionSet = `{ id type name slug description status priority createdAt updatedAt startDate targetDate archivedAt memberId organizationId teamIds emoji { id name memberId } backgroundImage { backgroundType gradientStart gradientEnd gradientDegrees color imageUrl image { url lowUrl } } favorites { id memberId } resources { ...ResourceSummaryFull } displayPreference { id type ${displayPreferenceAttributesSelectionSet} viewType favorite groupingField groupToggleState memberId focusMemberId focusTeamId displayableId displayableType preferenceType agendaItemId } filterPreferences { id type ${filterPreferenceAttributesSelectionSet} filterType filter memberId focusMemberId focusTeamId filterableId filterableType preferenceType agendaItemId } healthUpdates { ${healthUpdateSummarySelectionSet} replies { ${healthUpdateSummarySelectionSet} replies { id type } } } } fragment ResourceSummaryFull on ResourceSummary { id resourceType slug url skillId skill { id name slug emoji scope description } metadata { urlName imageUrl siteName providerName mediaType skillId skillName skillSlug skillScope skillEmoji skillDescription } attachment { id fileKey filename url } content { id name slug type firstChildSlug childCount } }`;
4047
- function asRecord3(value) {
3952
+ function asRecord2(value) {
4048
3953
  return value && typeof value === "object" ? value : null;
4049
3954
  }
4050
3955
  function toNonEmptyString(value) {
@@ -4077,9 +3982,9 @@ function parseProjectPriority(value) {
4077
3982
  return parsed.data.toUpperCase();
4078
3983
  }
4079
3984
  function normalizeProjectRowForDisplay(row) {
4080
- const record = asRecord3(row);
3985
+ const record = asRecord2(row);
4081
3986
  if (!record) return row;
4082
- const attributes = asRecord3(record.attributes);
3987
+ const attributes = asRecord2(record.attributes);
4083
3988
  const topLevelName = toNonEmptyString(record.name);
4084
3989
  const topLevelTitle = toNonEmptyString(record.title);
4085
3990
  const attributeName = toNonEmptyString(attributes?.name);
@@ -4094,7 +3999,7 @@ function normalizeProjectRowForDisplay(row) {
4094
3999
  };
4095
4000
  }
4096
4001
  function normalizeProjectsListForDisplay(payload) {
4097
- const record = asRecord3(payload);
4002
+ const record = asRecord2(payload);
4098
4003
  if (!record || !Array.isArray(record.data)) return payload;
4099
4004
  return {
4100
4005
  ...record,
@@ -4312,7 +4217,7 @@ var MEETING_STATUSES = /* @__PURE__ */ new Set(["upcoming", "active", "completed
4312
4217
  var MEETING_REPEATS = /* @__PURE__ */ new Set(["never", "weekly", "biweekly", "monthly", "quarterly"]);
4313
4218
  var createHelp2 = buildDataJsonHelp("meeting", "create") ?? 'JSON object for meeting or {"meeting": {...}}';
4314
4219
  var updateHelp2 = buildDataJsonHelp("meeting", "update") ?? 'JSON object for meeting or {"meeting": {...}}';
4315
- function asNonEmptyString2(value) {
4220
+ function asNonEmptyString(value) {
4316
4221
  if (typeof value !== "string") {
4317
4222
  return void 0;
4318
4223
  }
@@ -4370,7 +4275,7 @@ function normalizeMeetingCreateBody(body) {
4370
4275
  });
4371
4276
  }
4372
4277
  const meeting = { ...entity };
4373
- const type = asNonEmptyString2(meeting.type);
4278
+ const type = asNonEmptyString(meeting.type);
4374
4279
  if (!type || !MEETING_TYPES.has(type)) {
4375
4280
  throw new CliError({
4376
4281
  message: "Invalid meeting.type. Use one of: TeamMeeting, OneOnOneMeeting.",
@@ -4380,8 +4285,8 @@ function normalizeMeetingCreateBody(body) {
4380
4285
  details: { field: "meeting.type", allowed: Array.from(MEETING_TYPES) }
4381
4286
  });
4382
4287
  }
4383
- const memberId = asNonEmptyString2(meeting.member_id);
4384
- const date = asNonEmptyString2(meeting.date);
4288
+ const memberId = asNonEmptyString(meeting.member_id);
4289
+ const date = asNonEmptyString(meeting.date);
4385
4290
  const startTime = toFiniteNumber(meeting.start_time, "meeting.start_time");
4386
4291
  const missingRequired = [];
4387
4292
  if (!memberId) missingRequired.push("member_id");
@@ -4396,7 +4301,7 @@ function normalizeMeetingCreateBody(body) {
4396
4301
  details: { requiredFields: ["member_id", "date", "start_time"], rootKey: "meeting" }
4397
4302
  });
4398
4303
  }
4399
- const status = asNonEmptyString2(meeting.status);
4304
+ const status = asNonEmptyString(meeting.status);
4400
4305
  if (status && !MEETING_STATUSES.has(status)) {
4401
4306
  throw new CliError({
4402
4307
  message: "Invalid meeting.status. Use one of: upcoming, active, completed.",
@@ -4406,7 +4311,7 @@ function normalizeMeetingCreateBody(body) {
4406
4311
  details: { field: "meeting.status", allowed: Array.from(MEETING_STATUSES) }
4407
4312
  });
4408
4313
  }
4409
- const repeats = asNonEmptyString2(meeting.repeats) ?? "never";
4314
+ const repeats = asNonEmptyString(meeting.repeats) ?? "never";
4410
4315
  if (!MEETING_REPEATS.has(repeats)) {
4411
4316
  throw new CliError({
4412
4317
  message: "Invalid meeting.repeats. Use one of: never, weekly, biweekly, monthly, quarterly.",
@@ -4485,6 +4390,22 @@ function registerMeetingCommands(program) {
4485
4390
  isShow: true
4486
4391
  });
4487
4392
  });
4393
+ meetings.command("note-show").description("Read the authorized AI note context for a meeting").requiredOption("--id <id>").action(async (opts, cmd) => {
4394
+ const meetingId = idSchema5.parse(opts.id);
4395
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
4396
+ const organizationId = resolveOrganizationId(context.organizationId);
4397
+ await runGraphqlQueryCommand({
4398
+ command: "meetings.note-show",
4399
+ runtimeOptions: context.runtimeOptions,
4400
+ field: "meeting_note_by_meeting",
4401
+ variables: {
4402
+ organization_id: organizationId,
4403
+ meeting_id: meetingId
4404
+ },
4405
+ selectionSet: "{ answerContext }",
4406
+ isShow: true
4407
+ });
4408
+ });
4488
4409
  meetings.command("notes").requiredOption("--id <id>").requiredOption("--content <content>").action(async (opts, cmd) => {
4489
4410
  const id = idSchema5.parse(opts.id);
4490
4411
  const notes = notesSchema.parse(opts.content);
@@ -4540,10 +4461,25 @@ function registerMeetingCommands(program) {
4540
4461
 
4541
4462
  // src/commands/members.ts
4542
4463
  var import_zod8 = require("zod");
4543
- var idSchema6 = import_zod8.z.string().min(1);
4464
+ var idSchema6 = import_zod8.z.string().trim().min(1);
4544
4465
  var createHelp3 = buildDataJsonHelp("member", "create") ?? 'JSON object for member or {"member": {...}}';
4545
4466
  var updateHelp3 = buildDataJsonHelp("member", "update") ?? 'JSON object for member or {"member": {...}}';
4546
4467
  var MEMBER_META_PROFILE_SELECTION = "{ id type memberId summary profile attributes { id memberId summary profile } }";
4468
+ var MEMBER_REFERENCE_RESOLUTION_SELECTION = `{
4469
+ status
4470
+ reasonCode
4471
+ organizationId
4472
+ reference
4473
+ eligibilityPolicy
4474
+ complete
4475
+ source
4476
+ asOf
4477
+ traceId
4478
+ receiptId
4479
+ memberId
4480
+ memberName
4481
+ candidates { memberId memberName status eligible }
4482
+ }`;
4547
4483
  function parseStrictBooleanOption(value, optionName) {
4548
4484
  if (typeof value === "boolean") {
4549
4485
  return value;
@@ -4600,6 +4536,29 @@ function registerMemberCommands(program) {
4600
4536
  command: "members",
4601
4537
  field: "members"
4602
4538
  });
4539
+ members.command("resolve").description("Resolve a member reference within the authenticated organization").requiredOption("--query <query>", "Member name or email reference").action(async (opts, cmd) => {
4540
+ const reference = idSchema6.parse(opts.query);
4541
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
4542
+ const organizationId = resolveOrganizationId(context.organizationId);
4543
+ await runGraphqlQueryCommand({
4544
+ command: "members.resolve",
4545
+ runtimeOptions: context.runtimeOptions,
4546
+ operationName: "MemberReferenceResolution",
4547
+ field: "member_reference_resolution",
4548
+ variables: normalizeGraphqlVariables2({
4549
+ organization_id: organizationId,
4550
+ reference,
4551
+ trace_id: context.runtimeOptions.requestId
4552
+ }),
4553
+ variableTypes: {
4554
+ organization_id: "ID!",
4555
+ reference: "String!",
4556
+ trace_id: "String"
4557
+ },
4558
+ selectionSet: MEMBER_REFERENCE_RESOLUTION_SELECTION,
4559
+ isShow: true
4560
+ });
4561
+ });
4603
4562
  members.command("meta-profile").description("Read a member meta profile by member id").requiredOption("--member-id <memberId>", "Member id").requiredOption("--json", "Emit the stable JSON envelope").action(async (opts, cmd) => {
4604
4563
  const memberId = idSchema6.parse(opts.memberId);
4605
4564
  const context = await resolveCommandContext(cmd.optsWithGlobals());
@@ -4668,10 +4627,69 @@ function registerMemberCommands(program) {
4668
4627
  });
4669
4628
  }
4670
4629
 
4671
- // src/commands/skills.ts
4630
+ // src/commands/resources.ts
4672
4631
  var import_zod9 = require("zod");
4673
- var idSchema7 = import_zod9.z.string().min(1);
4674
- var limitSchema = import_zod9.z.coerce.number().int().positive();
4632
+ var resourceTypeSchema = import_zod9.z.enum([
4633
+ "project",
4634
+ "team",
4635
+ "agent",
4636
+ "automation",
4637
+ "file"
4638
+ ]);
4639
+ var referenceSchema = import_zod9.z.string().trim().min(1);
4640
+ var RESOURCE_REFERENCE_RESOLUTION_SELECTION = `{
4641
+ status
4642
+ reasonCode
4643
+ organizationId
4644
+ resourceType
4645
+ reference
4646
+ eligibilityPolicy
4647
+ complete
4648
+ source
4649
+ asOf
4650
+ traceId
4651
+ receiptId
4652
+ resourceId
4653
+ resourceName
4654
+ candidates { resourceId resourceName resourceType status eligible }
4655
+ }`;
4656
+ function registerResourceCommands(program) {
4657
+ const resources = program.command("resources").description("Organization-scoped resource resolution");
4658
+ resources.command("resolve").description("Resolve a project, team, agent, automation, or file reference").requiredOption(
4659
+ "--type <type>",
4660
+ "Resource type: project, team, agent, automation, or file"
4661
+ ).requiredOption("--query <query>", "Resource name or reference").action(async (opts, cmd) => {
4662
+ const resourceType = resourceTypeSchema.parse(opts.type);
4663
+ const reference = referenceSchema.parse(opts.query);
4664
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
4665
+ const organizationId = resolveOrganizationId(context.organizationId);
4666
+ await runGraphqlQueryCommand({
4667
+ command: "resources.resolve",
4668
+ runtimeOptions: context.runtimeOptions,
4669
+ operationName: "OrganizationResourceReferenceResolution",
4670
+ field: "organization_resource_reference_resolution",
4671
+ variables: normalizeGraphqlVariables2({
4672
+ organization_id: organizationId,
4673
+ resource_type: resourceType,
4674
+ reference,
4675
+ trace_id: context.runtimeOptions.requestId
4676
+ }),
4677
+ variableTypes: {
4678
+ organization_id: "ID!",
4679
+ resource_type: "String!",
4680
+ reference: "String!",
4681
+ trace_id: "String"
4682
+ },
4683
+ selectionSet: RESOURCE_REFERENCE_RESOLUTION_SELECTION,
4684
+ isShow: true
4685
+ });
4686
+ });
4687
+ }
4688
+
4689
+ // src/commands/skills.ts
4690
+ var import_zod10 = require("zod");
4691
+ var idSchema7 = import_zod10.z.string().min(1);
4692
+ var limitSchema = import_zod10.z.coerce.number().int().positive();
4675
4693
  var SKILL_SELECTION = `{
4676
4694
  id
4677
4695
  type
@@ -4747,14 +4765,14 @@ function registerSkillCommands(program) {
4747
4765
  }
4748
4766
 
4749
4767
  // src/commands/issues.ts
4750
- var import_zod10 = require("zod");
4751
- var issueGroupIdSchema = import_zod10.z.string().min(1);
4752
- var idSchema8 = import_zod10.z.string().min(1);
4753
- var nameSchema = import_zod10.z.string().min(1);
4754
- var issueTypeSchema = import_zod10.z.string().min(1).refine((value) => value === "short_term" || value === "long_term", {
4768
+ var import_zod11 = require("zod");
4769
+ var issueGroupIdSchema = import_zod11.z.string().min(1);
4770
+ var idSchema8 = import_zod11.z.string().min(1);
4771
+ var nameSchema = import_zod11.z.string().min(1);
4772
+ var issueTypeSchema = import_zod11.z.string().min(1).refine((value) => value === "short_term" || value === "long_term", {
4755
4773
  message: "Invalid issue type. Use one of: short_term, long_term."
4756
4774
  });
4757
- var issueStatusSchema = import_zod10.z.string().min(1).refine((value) => value === "open" || value === "completed", {
4775
+ var issueStatusSchema = import_zod11.z.string().min(1).refine((value) => value === "open" || value === "completed", {
4758
4776
  message: "Invalid issue status. Use one of: open, completed."
4759
4777
  });
4760
4778
  var updateHelp4 = buildDataJsonHelp("issue", "update") ?? 'JSON object for issue or {"issue": {...}}';
@@ -5022,13 +5040,35 @@ var SMART_KPI_NAMES = [
5022
5040
  var SMART_KPI_NAME_SET = new Set(SMART_KPI_NAMES);
5023
5041
 
5024
5042
  // src/commands/systemTools.ts
5043
+ var REMINDER_ATTRIBUTES_SELECTION = `
5044
+ id
5045
+ organizationId
5046
+ creatorId
5047
+ title
5048
+ description
5049
+ dueAt
5050
+ startsAt
5051
+ timezone
5052
+ schedule
5053
+ notification
5054
+ status
5055
+ nextTriggerAt
5056
+ lastTriggeredAt
5057
+ clearedAt
5058
+ reminderDelegates { id memberId organizationId }
5059
+ delegateMembers { id email firstName lastName organizationId }
5060
+ resources { id resourceType url creatorId attachment { id fileKey filename } }
5061
+ createdAt
5062
+ updatedAt
5063
+ `;
5064
+ var REMINDER_LIST_SELECTION = `{ data { id type attributes { ${REMINDER_ATTRIBUTES_SELECTION} } } count currentPage totalPages }`;
5065
+ var REMINDER_SHOW_SELECTION = `{ id type attributes { ${REMINDER_ATTRIBUTES_SELECTION} } }`;
5025
5066
  var TODO_STATUSES = /* @__PURE__ */ new Set(["open", "completed"]);
5026
5067
  var KNOWLEDGE_CONTENT_TYPES = /* @__PURE__ */ new Set(["company", "policy", "process"]);
5027
5068
  var KNOWLEDGE_STATUSES = /* @__PURE__ */ new Set(["draft", "published"]);
5028
5069
  var NEWS_STATUSES = /* @__PURE__ */ new Set(["active", "completed"]);
5029
5070
  var NEWS_HEADLINE_TYPES = /* @__PURE__ */ new Set(["team", "org_wide"]);
5030
5071
  var QUESTION_STATUSES = /* @__PURE__ */ new Set(["asked", "answered"]);
5031
- var PULSE_STATUSES = /* @__PURE__ */ new Set(["on_track", "at_risk", "off_track"]);
5032
5072
  var SURVEY_RECIPIENT_TYPES = /* @__PURE__ */ new Set(["member", "team", "org_wide"]);
5033
5073
  var SURVEY_NAMES = /* @__PURE__ */ new Set([
5034
5074
  "employee_net_promoter_score",
@@ -5041,21 +5081,6 @@ var SURVEY_NAMES = /* @__PURE__ */ new Set([
5041
5081
  "manager_review",
5042
5082
  "onboarding"
5043
5083
  ]);
5044
- var FEEDBACK_QUARTERS = /* @__PURE__ */ new Set(["q1", "q2", "q3", "q4"]);
5045
- var FEEDBACK_NAMES = /* @__PURE__ */ new Set([
5046
- "productivity_and_focus",
5047
- "company_collaboration",
5048
- "project_management",
5049
- "employee_engagement",
5050
- "training_and_development",
5051
- "innovation_and_creativity",
5052
- "customer_insights",
5053
- "process_improvement",
5054
- "leadership_and_management",
5055
- "company_culture",
5056
- "roadmap_and_strategy",
5057
- "customer_testing_and_feedback"
5058
- ]);
5059
5084
  var SCORECARD_INTERVALS = /* @__PURE__ */ new Set([
5060
5085
  "daily",
5061
5086
  "weekly",
@@ -5106,7 +5131,7 @@ function normalizeTodosCreateBody(body) {
5106
5131
  }
5107
5132
  return { ...body, todo };
5108
5133
  }
5109
- function asNonEmptyString3(value) {
5134
+ function asNonEmptyString2(value) {
5110
5135
  if (typeof value !== "string") {
5111
5136
  return void 0;
5112
5137
  }
@@ -5114,7 +5139,7 @@ function asNonEmptyString3(value) {
5114
5139
  return trimmed.length > 0 ? trimmed : void 0;
5115
5140
  }
5116
5141
  function validateEnumField(params) {
5117
- const value = asNonEmptyString3(params.rawValue);
5142
+ const value = asNonEmptyString2(params.rawValue);
5118
5143
  if (!value) {
5119
5144
  return void 0;
5120
5145
  }
@@ -5148,7 +5173,7 @@ function normalizeKnowledgeCreateBody(body) {
5148
5173
  message: "Invalid content.status. Use one of: draft, published."
5149
5174
  });
5150
5175
  content.status = status ?? "draft";
5151
- const memberId = asNonEmptyString3(content.member_id);
5176
+ const memberId = asNonEmptyString2(content.member_id);
5152
5177
  if (!memberId) {
5153
5178
  throwMissingRequiredCreateFields("content", ["member_id"]);
5154
5179
  }
@@ -5157,7 +5182,7 @@ function normalizeKnowledgeCreateBody(body) {
5157
5182
  }
5158
5183
  function normalizeNewsCreateBody(body) {
5159
5184
  const headline = ensureEntityObject(body, "headline");
5160
- const memberId = asNonEmptyString3(headline.member_id);
5185
+ const memberId = asNonEmptyString2(headline.member_id);
5161
5186
  if (!memberId) {
5162
5187
  throwMissingRequiredCreateFields("headline", ["member_id"]);
5163
5188
  }
@@ -5186,14 +5211,14 @@ function normalizeNewsCreateBody(body) {
5186
5211
  }
5187
5212
  function normalizeQuestionsCreateBody(body) {
5188
5213
  const question = ensureEntityObject(body, "question");
5189
- const summary = asNonEmptyString3(question.summary);
5190
- const currentName = asNonEmptyString3(question.name);
5214
+ const summary = asNonEmptyString2(question.summary);
5215
+ const currentName = asNonEmptyString2(question.name);
5191
5216
  if (!currentName && summary) {
5192
5217
  question.name = summary;
5193
5218
  }
5194
5219
  delete question.summary;
5195
- const name = asNonEmptyString3(question.name);
5196
- const memberId = asNonEmptyString3(question.member_id);
5220
+ const name = asNonEmptyString2(question.name);
5221
+ const memberId = asNonEmptyString2(question.member_id);
5197
5222
  const missing = [];
5198
5223
  if (!name) missing.push("name");
5199
5224
  if (!memberId) missing.push("member_id");
@@ -5215,13 +5240,13 @@ function normalizeQuestionsCreateBody(body) {
5215
5240
  }
5216
5241
  function normalizeQuestionsUpdateBody(body) {
5217
5242
  const question = ensureEntityObject(body, "question");
5218
- const summary = asNonEmptyString3(question.summary);
5219
- const currentName = asNonEmptyString3(question.name);
5243
+ const summary = asNonEmptyString2(question.summary);
5244
+ const currentName = asNonEmptyString2(question.name);
5220
5245
  if (!currentName && summary) {
5221
5246
  question.name = summary;
5222
5247
  }
5223
5248
  delete question.summary;
5224
- const name = asNonEmptyString3(question.name);
5249
+ const name = asNonEmptyString2(question.name);
5225
5250
  if (name) {
5226
5251
  question.name = name;
5227
5252
  }
@@ -5236,37 +5261,10 @@ function normalizeQuestionsUpdateBody(body) {
5236
5261
  }
5237
5262
  return { ...body, question };
5238
5263
  }
5239
- function normalizePulseCreateBody(body) {
5240
- const healthUpdate = ensureEntityObject(body, "health_update");
5241
- const healthUpdatableId = asNonEmptyString3(healthUpdate.health_updatable_id) ?? asNonEmptyString3(healthUpdate.updatable_id);
5242
- const healthUpdatableType = asNonEmptyString3(healthUpdate.health_updatable_type) ?? asNonEmptyString3(healthUpdate.updatable_type);
5243
- const memberId = asNonEmptyString3(healthUpdate.member_id);
5244
- const status = validateEnumField({
5245
- rawValue: healthUpdate.status,
5246
- field: "health_update.status",
5247
- allowed: PULSE_STATUSES,
5248
- message: "Invalid health_update.status. Use one of: on_track, at_risk, off_track."
5249
- });
5250
- const missing = [];
5251
- if (!healthUpdatableId) missing.push("health_updatable_id");
5252
- if (!healthUpdatableType) missing.push("health_updatable_type");
5253
- if (!memberId) missing.push("member_id");
5254
- if (!status) missing.push("status");
5255
- if (missing.length > 0) {
5256
- throwMissingRequiredCreateFields("health_update", missing);
5257
- }
5258
- healthUpdate.health_updatable_id = healthUpdatableId;
5259
- healthUpdate.health_updatable_type = healthUpdatableType;
5260
- healthUpdate.member_id = memberId;
5261
- healthUpdate.status = status;
5262
- delete healthUpdate.updatable_id;
5263
- delete healthUpdate.updatable_type;
5264
- return { ...body, health_update: healthUpdate };
5265
- }
5266
5264
  function normalizeSurveysCreateBody(body) {
5267
5265
  const survey = ensureEntityObject(body, "survey");
5268
- const title = asNonEmptyString3(survey.title);
5269
- const currentName = asNonEmptyString3(survey.name);
5266
+ const title = asNonEmptyString2(survey.title);
5267
+ const currentName = asNonEmptyString2(survey.name);
5270
5268
  if (!currentName && title) {
5271
5269
  survey.name = title;
5272
5270
  }
@@ -5295,8 +5293,8 @@ function normalizeSurveysCreateBody(body) {
5295
5293
  }
5296
5294
  function normalizeSurveysUpdateBody(body) {
5297
5295
  const survey = ensureEntityObject(body, "survey");
5298
- const title = asNonEmptyString3(survey.title);
5299
- const currentName = asNonEmptyString3(survey.name);
5296
+ const title = asNonEmptyString2(survey.title);
5297
+ const currentName = asNonEmptyString2(survey.name);
5300
5298
  if (!currentName && title) {
5301
5299
  survey.name = title;
5302
5300
  }
@@ -5321,77 +5319,16 @@ function normalizeSurveysUpdateBody(body) {
5321
5319
  }
5322
5320
  return { ...body, survey };
5323
5321
  }
5324
- function normalizeFeedbacksCreateBody(body) {
5325
- const feedback = ensureEntityObject(body, "feedback");
5326
- const title = asNonEmptyString3(feedback.title);
5327
- const currentName = asNonEmptyString3(feedback.name);
5328
- if (!currentName && title) {
5329
- feedback.name = title;
5330
- }
5331
- delete feedback.title;
5332
- const name = validateEnumField({
5333
- rawValue: feedback.name,
5334
- field: "feedback.name",
5335
- allowed: FEEDBACK_NAMES,
5336
- message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
5337
- });
5338
- const quarter = validateEnumField({
5339
- rawValue: feedback.quarter,
5340
- field: "feedback.quarter",
5341
- allowed: FEEDBACK_QUARTERS,
5342
- message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
5343
- });
5344
- const year = asNonEmptyString3(feedback.year);
5345
- const missing = [];
5346
- if (!name) missing.push("name");
5347
- if (!quarter) missing.push("quarter");
5348
- if (!year) missing.push("year");
5349
- if (missing.length > 0) {
5350
- throwMissingRequiredCreateFields("feedback", missing);
5351
- }
5352
- feedback.name = name;
5353
- feedback.quarter = quarter;
5354
- feedback.year = year;
5355
- return { ...body, feedback };
5356
- }
5357
- function normalizeFeedbacksUpdateBody(body) {
5358
- const feedback = ensureEntityObject(body, "feedback");
5359
- const title = asNonEmptyString3(feedback.title);
5360
- const currentName = asNonEmptyString3(feedback.name);
5361
- if (!currentName && title) {
5362
- feedback.name = title;
5363
- }
5364
- delete feedback.title;
5365
- const name = validateEnumField({
5366
- rawValue: feedback.name,
5367
- field: "feedback.name",
5368
- allowed: FEEDBACK_NAMES,
5369
- message: "Invalid feedback.name. Use one of: productivity_and_focus, company_collaboration, project_management, employee_engagement, training_and_development, innovation_and_creativity, customer_insights, process_improvement, leadership_and_management, company_culture, roadmap_and_strategy, customer_testing_and_feedback."
5370
- });
5371
- if (name) {
5372
- feedback.name = name;
5373
- }
5374
- const quarter = validateEnumField({
5375
- rawValue: feedback.quarter,
5376
- field: "feedback.quarter",
5377
- allowed: FEEDBACK_QUARTERS,
5378
- message: "Invalid feedback.quarter. Use one of: q1, q2, q3, q4."
5379
- });
5380
- if (quarter) {
5381
- feedback.quarter = quarter;
5382
- }
5383
- return { ...body, feedback };
5384
- }
5385
5322
  function normalizeAccountabilityCreateBody(body) {
5386
5323
  const responsibility = ensureEntityObject(body, "responsibility");
5387
- const summary = asNonEmptyString3(responsibility.summary);
5388
- const currentName = asNonEmptyString3(responsibility.name);
5324
+ const summary = asNonEmptyString2(responsibility.summary);
5325
+ const currentName = asNonEmptyString2(responsibility.name);
5389
5326
  if (!currentName && summary) {
5390
5327
  responsibility.name = summary;
5391
5328
  }
5392
5329
  delete responsibility.summary;
5393
- const name = asNonEmptyString3(responsibility.name);
5394
- const memberId = asNonEmptyString3(responsibility.member_id);
5330
+ const name = asNonEmptyString2(responsibility.name);
5331
+ const memberId = asNonEmptyString2(responsibility.member_id);
5395
5332
  const missing = [];
5396
5333
  if (!name) missing.push("name");
5397
5334
  if (!memberId) missing.push("member_id");
@@ -5406,8 +5343,8 @@ function normalizeAccountabilityCreateBody(body) {
5406
5343
  }
5407
5344
  function normalizeAccountabilityUpdateBody(body) {
5408
5345
  const responsibility = ensureEntityObject(body, "responsibility");
5409
- const summary = asNonEmptyString3(responsibility.summary);
5410
- const currentName = asNonEmptyString3(responsibility.name);
5346
+ const summary = asNonEmptyString2(responsibility.summary);
5347
+ const currentName = asNonEmptyString2(responsibility.name);
5411
5348
  if (!currentName && summary) {
5412
5349
  responsibility.name = summary;
5413
5350
  }
@@ -5439,7 +5376,7 @@ function parseSmartKpiViewCreateBody(raw) {
5439
5376
  }
5440
5377
  function normalizeSmartKpiViewCreateBody(body) {
5441
5378
  const smartKpiView = ensureEntityObject(body, "smart_kpi_view");
5442
- const name = asNonEmptyString3(smartKpiView.name);
5379
+ const name = asNonEmptyString2(smartKpiView.name);
5443
5380
  if (!name) {
5444
5381
  throwMissingRequiredCreateFields("smart_kpi_view", ["name"]);
5445
5382
  }
@@ -5477,9 +5414,9 @@ function buildKpisCreateMutation(params) {
5477
5414
  });
5478
5415
  }
5479
5416
  const smartKpi = { ...entity };
5480
- const name = asNonEmptyString3(smartKpi.name);
5481
- const smartKpiViewId = asNonEmptyString3(smartKpi.smart_kpi_view_id);
5482
- const measurableGroupId = asNonEmptyString3(smartKpi.measurable_group_id);
5417
+ const name = asNonEmptyString2(smartKpi.name);
5418
+ const smartKpiViewId = asNonEmptyString2(smartKpi.smart_kpi_view_id);
5419
+ const measurableGroupId = asNonEmptyString2(smartKpi.measurable_group_id);
5483
5420
  const hasAllowedName = typeof name === "string" && SMART_KPI_NAME_SET.has(name);
5484
5421
  if (!name) {
5485
5422
  throw new CliError({
@@ -5499,7 +5436,7 @@ function buildKpisCreateMutation(params) {
5499
5436
  measurable_type: "number",
5500
5437
  condition: "greater_than_or_equal_to"
5501
5438
  };
5502
- const notes = asNonEmptyString3(smartKpi.notes);
5439
+ const notes = asNonEmptyString2(smartKpi.notes);
5503
5440
  if (notes) {
5504
5441
  measurable.notes = notes;
5505
5442
  }
@@ -5568,6 +5505,32 @@ function registerSmartKpiViewCommands(program) {
5568
5505
  });
5569
5506
  }
5570
5507
  function registerSystemToolCommands(program) {
5508
+ registerEntityCrudCommands(program, {
5509
+ command: "reminders",
5510
+ description: "Reminder operations",
5511
+ resourcePath: "reminders",
5512
+ rootKey: "reminder",
5513
+ requiredCreateFields: ["title"],
5514
+ listParams: ["status", "sort"],
5515
+ allowQueryJson: false,
5516
+ registerSearch: false,
5517
+ listSelectionSet: REMINDER_LIST_SELECTION,
5518
+ showSelectionSet: REMINDER_SHOW_SELECTION,
5519
+ idMutationCommands: [
5520
+ {
5521
+ command: "clear",
5522
+ description: "Clear a reminder while retaining its history",
5523
+ field: "clear_reminder",
5524
+ idVariable: "reminder_id"
5525
+ },
5526
+ {
5527
+ command: "destroy",
5528
+ description: "Cancel a reminder while retaining its history",
5529
+ field: "destroy_reminder",
5530
+ idVariable: "reminder_id"
5531
+ }
5532
+ ]
5533
+ });
5571
5534
  registerEntityCrudCommands(program, {
5572
5535
  command: "lists",
5573
5536
  description: "List operations",
@@ -5712,18 +5675,6 @@ function registerSystemToolCommands(program) {
5712
5675
  listParams: ["answered", "asked"],
5713
5676
  allowQueryJson: false
5714
5677
  });
5715
- registerEntityCrudCommands(program, {
5716
- command: "pulse",
5717
- description: "Pulse operations",
5718
- resourcePath: "health_updates",
5719
- rootKey: "health_update",
5720
- listField: "feedbacks",
5721
- showField: "feedback",
5722
- requiredCreateFields: ["health_updatable_id", "health_updatable_type", "member_id", "status"],
5723
- normalizeCreateBody: normalizePulseCreateBody,
5724
- listParams: ["last", "latest", "start_date", "name", "quarter", "year"],
5725
- allowQueryJson: false
5726
- });
5727
5678
  registerEntityCrudCommands(program, {
5728
5679
  command: "surveys",
5729
5680
  description: "Survey operations",
@@ -5735,17 +5686,6 @@ function registerSystemToolCommands(program) {
5735
5686
  listParams: ["completed", "current_member", "due", "exclude_completed", "sent"],
5736
5687
  allowQueryJson: false
5737
5688
  });
5738
- registerEntityCrudCommands(program, {
5739
- command: "feedbacks",
5740
- description: "Feedback operations",
5741
- resourcePath: "feedback",
5742
- rootKey: "feedback",
5743
- requiredCreateFields: ["name", "quarter", "year"],
5744
- normalizeCreateBody: normalizeFeedbacksCreateBody,
5745
- normalizeUpdateBody: normalizeFeedbacksUpdateBody,
5746
- listParams: ["last", "latest", "start_date"],
5747
- allowQueryJson: false
5748
- });
5749
5689
  registerEntityCrudCommands(program, {
5750
5690
  command: "accountability",
5751
5691
  description: "Accountability operations",
@@ -5818,8 +5758,8 @@ function registerSystemToolCommands(program) {
5818
5758
  }
5819
5759
 
5820
5760
  // src/commands/teams.ts
5821
- var import_zod11 = require("zod");
5822
- var idSchema9 = import_zod11.z.string().min(1);
5761
+ var import_zod12 = require("zod");
5762
+ var idSchema9 = import_zod12.z.string().min(1);
5823
5763
  function registerTeamCommands(program) {
5824
5764
  const teams = program.command("teams").description("Team operations");
5825
5765
  teams.command("list").option("--page <page>").option("--per <per>").action(async (opts, cmd) => {
@@ -5885,8 +5825,8 @@ function registerTeamCommands(program) {
5885
5825
  }
5886
5826
 
5887
5827
  // src/commands/organizations.ts
5888
- var import_zod12 = require("zod");
5889
- var idSchema10 = import_zod12.z.string().min(1);
5828
+ var import_zod13 = require("zod");
5829
+ var idSchema10 = import_zod13.z.string().min(1);
5890
5830
  function isRecord3(value) {
5891
5831
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5892
5832
  }
@@ -5902,7 +5842,7 @@ function ensureRootObject(body, rootKey) {
5902
5842
  }
5903
5843
  return { ...root };
5904
5844
  }
5905
- function asNonEmptyString4(value) {
5845
+ function asNonEmptyString3(value) {
5906
5846
  if (typeof value !== "string") {
5907
5847
  return void 0;
5908
5848
  }
@@ -5912,7 +5852,7 @@ function asNonEmptyString4(value) {
5912
5852
  function normalizeOrganizationUpdateBody(body) {
5913
5853
  const organization = ensureRootObject(body, "organization");
5914
5854
  const detail = isRecord3(organization.organization_detail_attributes) ? { ...organization.organization_detail_attributes } : {};
5915
- const workspaceName = asNonEmptyString4(organization.workspace_name);
5855
+ const workspaceName = asNonEmptyString3(organization.workspace_name);
5916
5856
  if (workspaceName) {
5917
5857
  detail.workspace_name = workspaceName;
5918
5858
  }
@@ -5925,7 +5865,7 @@ function normalizeOrganizationUpdateBody(body) {
5925
5865
  function normalizeOrganizationMetaProfileUpdateBody(body) {
5926
5866
  const root = ensureRootObject(body, "organization_meta_profile");
5927
5867
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5928
- const title = asNonEmptyString4(root.title);
5868
+ const title = asNonEmptyString3(root.title);
5929
5869
  if (title) {
5930
5870
  const companyIdentity = isRecord3(profile.company_identity) ? { ...profile.company_identity } : {};
5931
5871
  companyIdentity.one_sentence_summary = title;
@@ -5955,7 +5895,7 @@ function normalizeOrganizationMetaProfileUpdateBody(body) {
5955
5895
  function normalizeKeyMetricMetaProfileUpdateBody(body) {
5956
5896
  const root = ensureRootObject(body, "key_metric_meta_profile");
5957
5897
  const profile = isRecord3(root.profile) ? { ...root.profile } : {};
5958
- const annualRevenue = asNonEmptyString4(root.annual_revenue);
5898
+ const annualRevenue = asNonEmptyString3(root.annual_revenue);
5959
5899
  if (annualRevenue) {
5960
5900
  const financial = isRecord3(profile.financial) ? { ...profile.financial } : {};
5961
5901
  financial.revenue = annualRevenue;
@@ -6111,8 +6051,8 @@ function registerOrganizationCommands(program) {
6111
6051
  }
6112
6052
 
6113
6053
  // src/commands/foundation.ts
6114
- var import_zod13 = require("zod");
6115
- var idSchema11 = import_zod13.z.string().min(1);
6054
+ var import_zod14 = require("zod");
6055
+ var idSchema11 = import_zod14.z.string().min(1);
6116
6056
  var STRATEGIC_PLAN_ALLOWED_UPDATE_KEYS = /* @__PURE__ */ new Set([
6117
6057
  "published_at",
6118
6058
  "profile",
@@ -6139,7 +6079,7 @@ function ensureRootObject2(body, rootKey) {
6139
6079
  }
6140
6080
  return { ...root };
6141
6081
  }
6142
- function asNonEmptyString5(value) {
6082
+ function asNonEmptyString4(value) {
6143
6083
  if (typeof value !== "string") {
6144
6084
  return void 0;
6145
6085
  }
@@ -6167,8 +6107,8 @@ function normalizeStrategicPlanUpdateBody(body) {
6167
6107
  }
6168
6108
  function normalizeStrategicObjectiveUpdateBody(body) {
6169
6109
  const strategicObjective = ensureRootObject2(body, "strategic_objective");
6170
- const title = asNonEmptyString5(strategicObjective.title);
6171
- if (!asNonEmptyString5(strategicObjective.summary) && title) {
6110
+ const title = asNonEmptyString4(strategicObjective.title);
6111
+ if (!asNonEmptyString4(strategicObjective.summary) && title) {
6172
6112
  strategicObjective.summary = title;
6173
6113
  }
6174
6114
  delete strategicObjective.title;
@@ -6191,8 +6131,8 @@ function normalizeStrategicObjectiveUpdateBody(body) {
6191
6131
  }
6192
6132
  function normalizeAnnualObjectiveCreateBody(body) {
6193
6133
  const annualObjective = ensureRootObject2(body, "annual_objective");
6194
- const title = asNonEmptyString5(annualObjective.title);
6195
- if (!asNonEmptyString5(annualObjective.name) && title) {
6134
+ const title = asNonEmptyString4(annualObjective.title);
6135
+ if (!asNonEmptyString4(annualObjective.name) && title) {
6196
6136
  annualObjective.name = title;
6197
6137
  }
6198
6138
  delete annualObjective.title;
@@ -6200,8 +6140,8 @@ function normalizeAnnualObjectiveCreateBody(body) {
6200
6140
  }
6201
6141
  function normalizeQuarterlyObjectiveCreateBody(body) {
6202
6142
  const quarterlyObjective = ensureRootObject2(body, "quarterly_objective");
6203
- const title = asNonEmptyString5(quarterlyObjective.title);
6204
- if (!asNonEmptyString5(quarterlyObjective.name) && title) {
6143
+ const title = asNonEmptyString4(quarterlyObjective.title);
6144
+ if (!asNonEmptyString4(quarterlyObjective.name) && title) {
6205
6145
  quarterlyObjective.name = title;
6206
6146
  }
6207
6147
  delete quarterlyObjective.title;
@@ -6313,9 +6253,9 @@ function registerFoundationCommands(program) {
6313
6253
  }
6314
6254
 
6315
6255
  // src/commands/childEntities.ts
6316
- var import_zod14 = require("zod");
6317
- var idSchema12 = import_zod14.z.string().min(1);
6318
- var jsonObjectSchema = import_zod14.z.record(import_zod14.z.string(), import_zod14.z.unknown());
6256
+ var import_zod15 = require("zod");
6257
+ var idSchema12 = import_zod15.z.string().min(1);
6258
+ var jsonObjectSchema = import_zod15.z.record(import_zod15.z.string(), import_zod15.z.unknown());
6319
6259
  var NOTE_DETAIL_FIELDS = [
6320
6260
  "notes",
6321
6261
  "hasNotes",
@@ -6344,7 +6284,18 @@ function requiredParentSearchOption(parentFlag, parentKind) {
6344
6284
  }
6345
6285
  function buildChildResourceSelectionSet(parentField, extraFields = []) {
6346
6286
  const fields = Array.from(
6347
- /* @__PURE__ */ new Set(["id", "type", "name", "status", "priority", "rank", "dueDate", "memberId", parentField, ...extraFields])
6287
+ /* @__PURE__ */ new Set([
6288
+ "id",
6289
+ "type",
6290
+ "name",
6291
+ "status",
6292
+ "priority",
6293
+ "rank",
6294
+ "dueDate",
6295
+ "memberId",
6296
+ parentField,
6297
+ ...extraFields
6298
+ ])
6348
6299
  );
6349
6300
  const attributeFields = fields.filter((field) => field !== "type");
6350
6301
  return `{ ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } }`;
@@ -6352,6 +6303,30 @@ function buildChildResourceSelectionSet(parentField, extraFields = []) {
6352
6303
  function buildChildListSelectionSet(parentField, extraFields = []) {
6353
6304
  return `{ data ${buildChildResourceSelectionSet(parentField, extraFields)} count currentPage totalPages }`;
6354
6305
  }
6306
+ function buildChildShowSelectionSet(parentField, extraFields = []) {
6307
+ const fields = Array.from(
6308
+ /* @__PURE__ */ new Set([
6309
+ "id",
6310
+ "type",
6311
+ "name",
6312
+ "status",
6313
+ "priority",
6314
+ "rank",
6315
+ "dueDate",
6316
+ "memberId",
6317
+ parentField,
6318
+ "notes",
6319
+ "hasNotes",
6320
+ "hasUnreadNotes",
6321
+ "notesUpdatedAt",
6322
+ "notesLastReadAt",
6323
+ "estimateIds",
6324
+ ...extraFields
6325
+ ])
6326
+ );
6327
+ const attributeFields = fields.filter((field) => field !== "type");
6328
+ return `{ ${fields.join(" ")} attributes { ${attributeFields.join(" ")} } }`;
6329
+ }
6355
6330
  function parseJsonObject2(raw) {
6356
6331
  try {
6357
6332
  const parsed = JSON.parse(raw);
@@ -6729,19 +6704,22 @@ function registerChildEntityCommands(program) {
6729
6704
  updateField: "update_talking_point",
6730
6705
  destroyField: "destroy_talking_point",
6731
6706
  idVariable: "talking_point_id",
6707
+ showField: "talking_point",
6732
6708
  listOperationName: "TalkingPointsList",
6709
+ showOperationName: "TalkingPointsShow",
6733
6710
  createOperationName: "TalkingPointsCreate",
6734
6711
  updateOperationName: "TalkingPointsUpdate",
6735
6712
  destroyOperationName: "TalkingPointsDestroy",
6736
6713
  listSelectionSet: buildChildListSelectionSet("meetingId", ["description", "creatorId", "slug"]),
6714
+ showSelectionSet: buildChildShowSelectionSet("meetingId", ["description", "creatorId", "slug"]),
6737
6715
  listParentTypedField: "meetingId"
6738
6716
  });
6739
6717
  }
6740
6718
 
6741
6719
  // src/commands/content.ts
6742
- var import_zod15 = require("zod");
6743
- var idSchema13 = import_zod15.z.string().min(1);
6744
- var nonEmptyString = import_zod15.z.string().min(1);
6720
+ var import_zod16 = require("zod");
6721
+ var idSchema13 = import_zod16.z.string().min(1);
6722
+ var nonEmptyString = import_zod16.z.string().min(1);
6745
6723
  var contentAttributesSelection = "attributes { id type name slug content firstChildSlug rootParentSlug status contentType lastEdited organizationId memberId focusMemberId focusTeamId teamId creatorId createdAt updatedAt childCount assignmentType contentableId contentableSlug contentableType votesTotal labelIds rootContentId parentContentId }";
6746
6724
  function assertUpdateFields(params) {
6747
6725
  if (!params.name && !params.content && !params.status) {
@@ -6929,9 +6907,9 @@ function registerContentCommands(program) {
6929
6907
  }
6930
6908
 
6931
6909
  // src/commands/markdownTree.ts
6932
- var import_zod16 = require("zod");
6933
- var nonEmptyString2 = import_zod16.z.string().min(1);
6934
- var nonNegativeInt = import_zod16.z.coerce.number().int().min(0);
6910
+ var import_zod17 = require("zod");
6911
+ var nonEmptyString2 = import_zod17.z.string().min(1);
6912
+ var nonNegativeInt = import_zod17.z.coerce.number().int().min(0);
6935
6913
  function addScopeOptions(command) {
6936
6914
  return command.requiredOption("--tool-key <toolKey>").requiredOption("--node-key <nodeKey>").option("--parent-id <parentId>").option("--record-id <recordId>").option("--member-id <memberId>").option("--team-id <teamId>").option("--content-type <contentType>").option("--tree-view");
6937
6915
  }
@@ -7096,11 +7074,11 @@ function registerMarkdownTreeCommands(program) {
7096
7074
  }
7097
7075
 
7098
7076
  // src/commands/navigation.ts
7099
- var import_zod17 = require("zod");
7077
+ var import_zod18 = require("zod");
7100
7078
 
7101
7079
  // src/internalOptions.ts
7102
7080
  var INTERNAL_OPTIONS_KEY = "__waveInternalOptions";
7103
- function asRecord4(value) {
7081
+ function asRecord3(value) {
7104
7082
  if (!value || typeof value !== "object" || Array.isArray(value)) {
7105
7083
  return null;
7106
7084
  }
@@ -7114,7 +7092,7 @@ function setInternalCliOptions(program, options) {
7114
7092
  function getInternalCliOptions(command) {
7115
7093
  let current = command;
7116
7094
  while (current) {
7117
- const record = asRecord4(current[INTERNAL_OPTIONS_KEY]);
7095
+ const record = asRecord3(current[INTERNAL_OPTIONS_KEY]);
7118
7096
  if (record) {
7119
7097
  return {
7120
7098
  enableRetryOnEmptyPhrase: record.enableRetryOnEmptyPhrase === true
@@ -7126,8 +7104,8 @@ function getInternalCliOptions(command) {
7126
7104
  }
7127
7105
 
7128
7106
  // src/commands/navigation.ts
7129
- var nonEmpty = import_zod17.z.string().min(1);
7130
- var nonNegativeInt2 = import_zod17.z.coerce.number().int().min(0);
7107
+ var nonEmpty = import_zod18.z.string().min(1);
7108
+ var nonNegativeInt2 = import_zod18.z.coerce.number().int().min(0);
7131
7109
  var MIGRATED_BRANCHES = ["directory", "projects", "knowledge"];
7132
7110
  function normalizeText(input) {
7133
7111
  if (typeof input !== "string") return "";
@@ -7910,14 +7888,14 @@ function registerMutationCapabilityCommands(program) {
7910
7888
  // src/commands/osmd.ts
7911
7889
  var import_promises3 = require("fs/promises");
7912
7890
  var import_node_path3 = require("path");
7913
- var import_zod18 = require("zod");
7891
+ var import_zod19 = require("zod");
7914
7892
  var import_commander = require("commander");
7915
7893
 
7916
7894
  // src/operationManifest.ts
7917
7895
  var import_node_crypto3 = require("crypto");
7918
7896
 
7919
7897
  // src/version.ts
7920
- var CLI_VERSION = "0.1.85";
7898
+ var CLI_VERSION = "0.1.88";
7921
7899
 
7922
7900
  // src/operationMetadata.ts
7923
7901
  var DISCOVERY_OPERATION_IDS = [
@@ -7945,14 +7923,14 @@ var DISCOVERY_OPERATION_IDS = [
7945
7923
  "customers.examples",
7946
7924
  "customers.schema",
7947
7925
  "datasheets.examples",
7926
+ "data-pipeline.examples",
7927
+ "data-pipeline.schema",
7948
7928
  "datasheets.schema",
7949
7929
  "desktop-context.examples",
7950
7930
  "desktop-context.schema",
7951
7931
  "doctor",
7952
7932
  "doctor.examples",
7953
7933
  "doctor.schema",
7954
- "feedbacks.examples",
7955
- "feedbacks.schema",
7956
7934
  "foundation.examples",
7957
7935
  "foundation.schema",
7958
7936
  "issue-groups.examples",
@@ -7989,8 +7967,6 @@ var DISCOVERY_OPERATION_IDS = [
7989
7967
  "project-content.schema",
7990
7968
  "projects.examples",
7991
7969
  "projects.schema",
7992
- "pulse.examples",
7993
- "pulse.schema",
7994
7970
  "questions.examples",
7995
7971
  "questions.schema",
7996
7972
  "recognition.examples",
@@ -8032,7 +8008,9 @@ var DISCOVERY_OPERATION_IDS = [
8032
8008
  "todos.examples",
8033
8009
  "todos.schema",
8034
8010
  "whiteboards.examples",
8035
- "whiteboards.schema"
8011
+ "whiteboards.schema",
8012
+ "sketches.examples",
8013
+ "sketches.schema"
8036
8014
  ];
8037
8015
  var READ_OPERATION_IDS = [
8038
8016
  "accountability.list",
@@ -8060,12 +8038,15 @@ var READ_OPERATION_IDS = [
8060
8038
  "customers.show",
8061
8039
  "datasheets.list",
8062
8040
  "datasheets.open",
8041
+ "data-pipeline.execute-source-action",
8042
+ "data-pipeline.overview",
8043
+ "data-pipeline.source-actions",
8044
+ "data-pipeline.sources",
8063
8045
  "datasheets.show",
8046
+ "desktop-context.activity",
8047
+ "desktop-context.member-statuses",
8064
8048
  "desktop-context.recent",
8065
8049
  "desktop-context.status",
8066
- "feedbacks.list",
8067
- "feedbacks.search",
8068
- "feedbacks.show",
8069
8050
  "find",
8070
8051
  "foundation.annual-objectives.list",
8071
8052
  "foundation.annual-objectives.search",
@@ -8101,6 +8082,7 @@ var READ_OPERATION_IDS = [
8101
8082
  "mail.message",
8102
8083
  "mail.messages",
8103
8084
  "mail.open",
8085
+ "mail.relay-evidence",
8104
8086
  "mail.settings",
8105
8087
  "mail.snippets",
8106
8088
  "mail.sync-status",
@@ -8112,12 +8094,15 @@ var READ_OPERATION_IDS = [
8112
8094
  "markdown-tree.root",
8113
8095
  "markdown-tree.subtree",
8114
8096
  "meetings.list",
8097
+ "meetings.note-show",
8115
8098
  "meetings.search",
8116
8099
  "meetings.show",
8117
8100
  "members.list",
8118
8101
  "members.meta-profile",
8102
+ "members.resolve",
8119
8103
  "members.search",
8120
8104
  "members.show",
8105
+ "resources.resolve",
8121
8106
  "milestones.list",
8122
8107
  "milestones.search",
8123
8108
  "milestones.show",
@@ -8162,9 +8147,6 @@ var READ_OPERATION_IDS = [
8162
8147
  "projects.list",
8163
8148
  "projects.search",
8164
8149
  "projects.show",
8165
- "pulse.list",
8166
- "pulse.search",
8167
- "pulse.show",
8168
8150
  "questions.list",
8169
8151
  "questions.search",
8170
8152
  "questions.show",
@@ -8176,6 +8158,8 @@ var READ_OPERATION_IDS = [
8176
8158
  "rock-collections.list",
8177
8159
  "rock-collections.search",
8178
8160
  "rock-collections.show",
8161
+ "reminders.list",
8162
+ "reminders.show",
8179
8163
  "rocks.list",
8180
8164
  "rocks.search",
8181
8165
  "rocks.show",
@@ -8188,6 +8172,8 @@ var READ_OPERATION_IDS = [
8188
8172
  "skills.list",
8189
8173
  "skills.show",
8190
8174
  "stand-ups.list",
8175
+ "signatures.list",
8176
+ "signatures.show",
8191
8177
  "stand-ups.search",
8192
8178
  "stand-ups.show",
8193
8179
  "subissues.list",
@@ -8211,13 +8197,12 @@ var READ_OPERATION_IDS = [
8211
8197
  "support.settings",
8212
8198
  "support.ticket-counts",
8213
8199
  "support.tickets",
8214
- "signatures.list",
8215
- "signatures.show",
8216
8200
  "surveys.list",
8217
8201
  "surveys.search",
8218
8202
  "surveys.show",
8219
8203
  "talking-points.list",
8220
8204
  "talking-points.search",
8205
+ "talking-points.show",
8221
8206
  "tasks.list",
8222
8207
  "tasks.search",
8223
8208
  "tasks.show",
@@ -8239,7 +8224,10 @@ var READ_OPERATION_IDS = [
8239
8224
  "tree",
8240
8225
  "whiteboards.list",
8241
8226
  "whiteboards.open",
8242
- "whiteboards.show"
8227
+ "whiteboards.show",
8228
+ "sketches.list",
8229
+ "sketches.open",
8230
+ "sketches.show"
8243
8231
  ];
8244
8232
  var WRITE_OPERATION_IDS = [
8245
8233
  "accountability.create",
@@ -8290,8 +8278,6 @@ var WRITE_OPERATION_IDS = [
8290
8278
  "datasheets.view.delete",
8291
8279
  "datasheets.view.reorder",
8292
8280
  "datasheets.view.update",
8293
- "feedbacks.create",
8294
- "feedbacks.update",
8295
8281
  "foundation.annual-objectives.create",
8296
8282
  "foundation.annual-objectives.update",
8297
8283
  "foundation.quarterly-objectives.create",
@@ -8339,8 +8325,6 @@ var WRITE_OPERATION_IDS = [
8339
8325
  "project-content.update",
8340
8326
  "projects.create",
8341
8327
  "projects.update",
8342
- "pulse.create",
8343
- "pulse.update",
8344
8328
  "questions.create",
8345
8329
  "questions.update",
8346
8330
  "rock-collections.create",
@@ -8348,6 +8332,10 @@ var WRITE_OPERATION_IDS = [
8348
8332
  "rocks.create",
8349
8333
  "rocks.update",
8350
8334
  "rocks.update-status",
8335
+ "reminders.clear",
8336
+ "reminders.create",
8337
+ "reminders.destroy",
8338
+ "reminders.update",
8351
8339
  "scorecard-groups.create",
8352
8340
  "scorecard-groups.update",
8353
8341
  "scorecards.create",
@@ -8389,7 +8377,9 @@ var WRITE_OPERATION_IDS = [
8389
8377
  "todo-groups.create",
8390
8378
  "todo-groups.update",
8391
8379
  "todos.create",
8392
- "todos.update"
8380
+ "todos.update",
8381
+ "sketches.create",
8382
+ "sketches.update-metadata"
8393
8383
  ];
8394
8384
  var DIRECT_MACHINE_WRITE_OPERATION_IDS = /* @__PURE__ */ new Set(["automations.create"]);
8395
8385
  var AUTH_OPERATION_IDS = ["login", "logout"];
@@ -8410,6 +8400,8 @@ var DESTRUCTIVE_OPERATION_IDS = /* @__PURE__ */ new Set([
8410
8400
  "datasheets.view.delete",
8411
8401
  "milestones.destroy",
8412
8402
  "project-content.destroy",
8403
+ "reminders.clear",
8404
+ "reminders.destroy",
8413
8405
  "signatures.destroy",
8414
8406
  "signatures.void",
8415
8407
  "subissues.destroy",
@@ -8426,6 +8418,14 @@ var OPERATION_IDS_BY_CLASSIFICATION = {
8426
8418
  auth: AUTH_OPERATION_IDS
8427
8419
  };
8428
8420
  var metadataByOperationId = /* @__PURE__ */ new Map();
8421
+ function assertDataPipelineReadOnlyRegistration(id, metadata) {
8422
+ if (!id.startsWith("data-pipeline.")) return;
8423
+ const isReadOnlyOperation = metadata.classification === "read" && metadata.atlasSafetyClass === "read_only" || metadata.classification === "discovery" && metadata.atlasSafetyClass === "discovery";
8424
+ if (isReadOnlyOperation && !metadata.requiresApproval && !metadata.machine.supportsPreview) {
8425
+ return;
8426
+ }
8427
+ throw new Error(`Data Pipeline operations must remain read-only: ${id}`);
8428
+ }
8429
8429
  for (const [classification, operationIds] of Object.entries(OPERATION_IDS_BY_CLASSIFICATION)) {
8430
8430
  for (const id of operationIds) {
8431
8431
  if (metadataByOperationId.has(id)) {
@@ -8435,7 +8435,7 @@ for (const [classification, operationIds] of Object.entries(OPERATION_IDS_BY_CLA
8435
8435
  if (DESTRUCTIVE_OPERATION_IDS.has(id) && classification !== "write") {
8436
8436
  throw new Error(`Destructive Wave CLI operation must be a write: ${id}`);
8437
8437
  }
8438
- metadataByOperationId.set(id, {
8438
+ const metadata = {
8439
8439
  classification,
8440
8440
  requiresApproval: classification === "write" && !DIRECT_MACHINE_WRITE_OPERATION_IDS.has(id),
8441
8441
  atlasSafetyClass,
@@ -8445,7 +8445,9 @@ for (const [classification, operationIds] of Object.entries(OPERATION_IDS_BY_CLA
8445
8445
  supportsExecute: true,
8446
8446
  executionMode: "sync"
8447
8447
  }
8448
- });
8448
+ };
8449
+ assertDataPipelineReadOnlyRegistration(id, metadata);
8450
+ metadataByOperationId.set(id, metadata);
8449
8451
  }
8450
8452
  }
8451
8453
  function registeredOperationMetadata(id) {
@@ -8607,15 +8609,15 @@ function buildOperationManifest(program) {
8607
8609
  }
8608
8610
 
8609
8611
  // src/commands/osmd.ts
8610
- var sourceSchema = import_zod18.z.enum([
8612
+ var sourceSchema = import_zod19.z.enum([
8611
8613
  "canonical_osmd",
8612
8614
  "agent_overlay",
8613
8615
  "agent_wiki",
8614
8616
  "thread_workspace"
8615
8617
  ]);
8616
- var accessSchema = import_zod18.z.enum(["read_only", "read_write", "append_only"]).catch("read_write");
8617
- var ownerSchema = import_zod18.z.enum(["system", "atlas"]);
8618
- var suggestedActionSchema = import_zod18.z.enum([
8618
+ var accessSchema = import_zod19.z.enum(["read_only", "read_write", "append_only"]).catch("read_write");
8619
+ var ownerSchema = import_zod19.z.enum(["system", "atlas"]);
8620
+ var suggestedActionSchema = import_zod19.z.enum([
8619
8621
  "read",
8620
8622
  "create",
8621
8623
  "init",
@@ -8624,7 +8626,7 @@ var suggestedActionSchema = import_zod18.z.enum([
8624
8626
  "forbidden",
8625
8627
  "invalid_parent"
8626
8628
  ]).catch("update");
8627
- var agentMarkdownErrorCodeSchema = import_zod18.z.enum([
8629
+ var agentMarkdownErrorCodeSchema = import_zod19.z.enum([
8628
8630
  "canonical_osmd_read_only",
8629
8631
  "agent_parent_not_found",
8630
8632
  "agent_file_not_found",
@@ -8635,9 +8637,9 @@ var agentMarkdownErrorCodeSchema = import_zod18.z.enum([
8635
8637
  "invalid_agent_wiki_path"
8636
8638
  ]);
8637
8639
  var agentMarkdownErrorCodeFieldSchema = agentMarkdownErrorCodeSchema.nullable().catch(null);
8638
- var nonEmptyString3 = import_zod18.z.string().min(1);
8639
- var nonNegativeInt3 = import_zod18.z.coerce.number().int().min(0);
8640
- var positiveInt = import_zod18.z.coerce.number().int().min(1);
8640
+ var nonEmptyString3 = import_zod19.z.string().min(1);
8641
+ var nonNegativeInt3 = import_zod19.z.coerce.number().int().min(0);
8642
+ var positiveInt = import_zod19.z.coerce.number().int().min(1);
8641
8643
  var supportedAgentOverlaySystemFiles = ["notes.md", "summary.md"];
8642
8644
  var supportedWikiIndexFile = "index.md";
8643
8645
  var supportedWikiLogFile = "log.md";
@@ -8653,20 +8655,20 @@ var supportedWikiControlledPatterns = supportedWikiControlledFolders.map(
8653
8655
  );
8654
8656
  var controlledWikiSlugPattern = /^[a-z0-9][a-z0-9-]*$/;
8655
8657
  var agentMarkdownSlugPattern = /^[a-z0-9][a-z0-9-]*$/;
8656
- var osmdSearchScopeSchema = import_zod18.z.enum([
8658
+ var osmdSearchScopeSchema = import_zod19.z.enum([
8657
8659
  "os-only",
8658
8660
  "agent-overlay-only",
8659
8661
  "agent-wiki-only",
8660
8662
  "combined"
8661
8663
  ]);
8662
- var osmdLintScopeSchema = import_zod18.z.enum([
8664
+ var osmdLintScopeSchema = import_zod19.z.enum([
8663
8665
  "combined",
8664
8666
  "agent-overlay-only",
8665
8667
  "agent-wiki-only"
8666
8668
  ]);
8667
- var osmdMemoryQualityScopeSchema = import_zod18.z.enum(["agent-overlay-only"]);
8668
- var osmdIngestKindSchema = import_zod18.z.enum(["text", "file", "url", "transcript"]);
8669
- var osmdRawSourceTypeSchema = import_zod18.z.enum([
8669
+ var osmdMemoryQualityScopeSchema = import_zod19.z.enum(["agent-overlay-only"]);
8670
+ var osmdIngestKindSchema = import_zod19.z.enum(["text", "file", "url", "transcript"]);
8671
+ var osmdRawSourceTypeSchema = import_zod19.z.enum([
8670
8672
  "pasted_text",
8671
8673
  "uploaded_markdown",
8672
8674
  "uploaded_text",
@@ -8675,37 +8677,37 @@ var osmdRawSourceTypeSchema = import_zod18.z.enum([
8675
8677
  "meeting_transcript",
8676
8678
  "url"
8677
8679
  ]);
8678
- var agentMarkdownFileSchema = import_zod18.z.preprocess(
8680
+ var agentMarkdownFileSchema = import_zod19.z.preprocess(
8679
8681
  normalizeAgentMarkdownJsonKeys,
8680
- import_zod18.z.object({
8681
- path: import_zod18.z.string(),
8682
+ import_zod19.z.object({
8683
+ path: import_zod19.z.string(),
8682
8684
  source: sourceSchema,
8683
8685
  access: accessSchema,
8684
8686
  owner: ownerSchema,
8685
- exists: import_zod18.z.boolean(),
8686
- canCreate: import_zod18.z.boolean(),
8687
- canUpdate: import_zod18.z.boolean(),
8688
- canAppend: import_zod18.z.boolean(),
8689
- wikiRole: import_zod18.z.string().nullable().optional(),
8690
- formatVersion: import_zod18.z.string().nullable().optional(),
8691
- createdAt: import_zod18.z.string().nullable().optional(),
8692
- updatedAt: import_zod18.z.string().nullable().optional(),
8693
- ingestedAt: import_zod18.z.string().nullable().optional(),
8694
- lastSeenAt: import_zod18.z.string().nullable().optional(),
8695
- canonicalParentUpdatedAt: import_zod18.z.string().nullable().optional(),
8696
- parentRef: import_zod18.z.string().nullable().optional(),
8697
- agentChildrenAllowed: import_zod18.z.boolean(),
8687
+ exists: import_zod19.z.boolean(),
8688
+ canCreate: import_zod19.z.boolean(),
8689
+ canUpdate: import_zod19.z.boolean(),
8690
+ canAppend: import_zod19.z.boolean(),
8691
+ wikiRole: import_zod19.z.string().nullable().optional(),
8692
+ formatVersion: import_zod19.z.string().nullable().optional(),
8693
+ createdAt: import_zod19.z.string().nullable().optional(),
8694
+ updatedAt: import_zod19.z.string().nullable().optional(),
8695
+ ingestedAt: import_zod19.z.string().nullable().optional(),
8696
+ lastSeenAt: import_zod19.z.string().nullable().optional(),
8697
+ canonicalParentUpdatedAt: import_zod19.z.string().nullable().optional(),
8698
+ parentRef: import_zod19.z.string().nullable().optional(),
8699
+ agentChildrenAllowed: import_zod19.z.boolean(),
8698
8700
  suggestedAction: suggestedActionSchema,
8699
8701
  errorCode: agentMarkdownErrorCodeFieldSchema.optional(),
8700
- content: import_zod18.z.string().nullable().optional(),
8701
- url: import_zod18.z.string().nullable().optional(),
8702
- workspaceId: import_zod18.z.string().nullable().optional(),
8703
- fileId: import_zod18.z.string().nullable().optional(),
8704
- name: import_zod18.z.string().nullable().optional(),
8705
- displayName: import_zod18.z.string().nullable().optional(),
8706
- contentSha: import_zod18.z.string().nullable().optional(),
8707
- versionSha: import_zod18.z.string().nullable().optional(),
8708
- mediaType: import_zod18.z.string().nullable().optional()
8702
+ content: import_zod19.z.string().nullable().optional(),
8703
+ url: import_zod19.z.string().nullable().optional(),
8704
+ workspaceId: import_zod19.z.string().nullable().optional(),
8705
+ fileId: import_zod19.z.string().nullable().optional(),
8706
+ name: import_zod19.z.string().nullable().optional(),
8707
+ displayName: import_zod19.z.string().nullable().optional(),
8708
+ contentSha: import_zod19.z.string().nullable().optional(),
8709
+ versionSha: import_zod19.z.string().nullable().optional(),
8710
+ mediaType: import_zod19.z.string().nullable().optional()
8709
8711
  }).transform((value) => ({
8710
8712
  ...value,
8711
8713
  wikiRole: value.wikiRole ?? null,
@@ -8728,31 +8730,31 @@ var agentMarkdownFileSchema = import_zod18.z.preprocess(
8728
8730
  mediaType: value.mediaType ?? null
8729
8731
  }))
8730
8732
  );
8731
- var agentMarkdownFilesSchema = import_zod18.z.array(agentMarkdownFileSchema);
8732
- var agentMarkdownMutationDataSchema = import_zod18.z.union([
8733
+ var agentMarkdownFilesSchema = import_zod19.z.array(agentMarkdownFileSchema);
8734
+ var agentMarkdownMutationDataSchema = import_zod19.z.union([
8733
8735
  agentMarkdownFileSchema,
8734
- import_zod18.z.object({ files: agentMarkdownFilesSchema })
8736
+ import_zod19.z.object({ files: agentMarkdownFilesSchema })
8735
8737
  ]);
8736
- var osmdSearchCandidateSchema = import_zod18.z.preprocess(
8738
+ var osmdSearchCandidateSchema = import_zod19.z.preprocess(
8737
8739
  normalizeAgentMarkdownJsonKeys,
8738
- import_zod18.z.object({
8739
- path: import_zod18.z.string(),
8740
+ import_zod19.z.object({
8741
+ path: import_zod19.z.string(),
8740
8742
  source: sourceSchema,
8741
8743
  access: accessSchema,
8742
8744
  owner: ownerSchema,
8743
- wikiRole: import_zod18.z.string().nullable().optional(),
8744
- formatVersion: import_zod18.z.string().nullable().optional(),
8745
- parentRef: import_zod18.z.string().nullable().optional(),
8746
- exists: import_zod18.z.boolean(),
8747
- agentChildrenAllowed: import_zod18.z.boolean(),
8748
- title: import_zod18.z.string(),
8749
- label: import_zod18.z.string(),
8750
- snippet: import_zod18.z.string().nullable().optional(),
8751
- rank: import_zod18.z.number().int(),
8752
- matchReason: import_zod18.z.string().nullable().optional(),
8753
- toolKey: import_zod18.z.string().nullable().optional(),
8754
- nodeKey: import_zod18.z.string().nullable().optional(),
8755
- nodeKind: import_zod18.z.string().nullable().optional()
8745
+ wikiRole: import_zod19.z.string().nullable().optional(),
8746
+ formatVersion: import_zod19.z.string().nullable().optional(),
8747
+ parentRef: import_zod19.z.string().nullable().optional(),
8748
+ exists: import_zod19.z.boolean(),
8749
+ agentChildrenAllowed: import_zod19.z.boolean(),
8750
+ title: import_zod19.z.string(),
8751
+ label: import_zod19.z.string(),
8752
+ snippet: import_zod19.z.string().nullable().optional(),
8753
+ rank: import_zod19.z.number().int(),
8754
+ matchReason: import_zod19.z.string().nullable().optional(),
8755
+ toolKey: import_zod19.z.string().nullable().optional(),
8756
+ nodeKey: import_zod19.z.string().nullable().optional(),
8757
+ nodeKind: import_zod19.z.string().nullable().optional()
8756
8758
  }).transform((value) => ({
8757
8759
  ...value,
8758
8760
  wikiRole: value.wikiRole ?? null,
@@ -8765,26 +8767,26 @@ var osmdSearchCandidateSchema = import_zod18.z.preprocess(
8765
8767
  nodeKind: value.nodeKind ?? null
8766
8768
  }))
8767
8769
  );
8768
- var osmdSearchResultSchema = import_zod18.z.preprocess(
8770
+ var osmdSearchResultSchema = import_zod19.z.preprocess(
8769
8771
  normalizeAgentMarkdownJsonKeys,
8770
- import_zod18.z.object({
8771
- query: import_zod18.z.string(),
8772
- scope: import_zod18.z.string(),
8773
- count: import_zod18.z.number().int().min(0),
8774
- candidates: import_zod18.z.array(osmdSearchCandidateSchema)
8772
+ import_zod19.z.object({
8773
+ query: import_zod19.z.string(),
8774
+ scope: import_zod19.z.string(),
8775
+ count: import_zod19.z.number().int().min(0),
8776
+ candidates: import_zod19.z.array(osmdSearchCandidateSchema)
8775
8777
  })
8776
8778
  );
8777
- var osmdWikiLintIssueSchema = import_zod18.z.preprocess(
8779
+ var osmdWikiLintIssueSchema = import_zod19.z.preprocess(
8778
8780
  normalizeAgentMarkdownJsonKeys,
8779
- import_zod18.z.object({
8780
- code: import_zod18.z.string(),
8781
- severity: import_zod18.z.string(),
8782
- path: import_zod18.z.string(),
8783
- source: import_zod18.z.string().nullable().optional(),
8784
- parentRef: import_zod18.z.string().nullable().optional(),
8785
- message: import_zod18.z.string(),
8786
- suggestedAction: import_zod18.z.string().nullable().optional(),
8787
- canAutoFix: import_zod18.z.boolean()
8781
+ import_zod19.z.object({
8782
+ code: import_zod19.z.string(),
8783
+ severity: import_zod19.z.string(),
8784
+ path: import_zod19.z.string(),
8785
+ source: import_zod19.z.string().nullable().optional(),
8786
+ parentRef: import_zod19.z.string().nullable().optional(),
8787
+ message: import_zod19.z.string(),
8788
+ suggestedAction: import_zod19.z.string().nullable().optional(),
8789
+ canAutoFix: import_zod19.z.boolean()
8788
8790
  }).transform((value) => ({
8789
8791
  ...value,
8790
8792
  source: value.source ?? null,
@@ -8792,37 +8794,37 @@ var osmdWikiLintIssueSchema = import_zod18.z.preprocess(
8792
8794
  suggestedAction: value.suggestedAction ?? null
8793
8795
  }))
8794
8796
  );
8795
- var osmdWikiLintResultSchema = import_zod18.z.preprocess(
8797
+ var osmdWikiLintResultSchema = import_zod19.z.preprocess(
8796
8798
  normalizeAgentMarkdownJsonKeys,
8797
- import_zod18.z.object({
8798
- status: import_zod18.z.string(),
8799
- summary: import_zod18.z.object({
8800
- totalIssues: import_zod18.z.number().int().min(0),
8801
- errors: import_zod18.z.number().int().min(0),
8802
- warnings: import_zod18.z.number().int().min(0),
8803
- suggestions: import_zod18.z.number().int().min(0)
8799
+ import_zod19.z.object({
8800
+ status: import_zod19.z.string(),
8801
+ summary: import_zod19.z.object({
8802
+ totalIssues: import_zod19.z.number().int().min(0),
8803
+ errors: import_zod19.z.number().int().min(0),
8804
+ warnings: import_zod19.z.number().int().min(0),
8805
+ suggestions: import_zod19.z.number().int().min(0)
8804
8806
  }),
8805
- issues: import_zod18.z.array(osmdWikiLintIssueSchema)
8807
+ issues: import_zod19.z.array(osmdWikiLintIssueSchema)
8806
8808
  })
8807
8809
  );
8808
- var nullableCountSchema = import_zod18.z.preprocess(
8810
+ var nullableCountSchema = import_zod19.z.preprocess(
8809
8811
  (value) => value === void 0 || value === null || value === "" ? null : value,
8810
- import_zod18.z.coerce.number().int().min(0).nullable()
8812
+ import_zod19.z.coerce.number().int().min(0).nullable()
8811
8813
  ).catch(null);
8812
- var osmdMemoryQualityIssueSchema = import_zod18.z.preprocess(
8814
+ var osmdMemoryQualityIssueSchema = import_zod19.z.preprocess(
8813
8815
  normalizeAgentMarkdownJsonKeys,
8814
- import_zod18.z.object({
8815
- code: import_zod18.z.string().nullable().optional(),
8816
- issueCode: import_zod18.z.string().nullable().optional(),
8817
- path: import_zod18.z.string().nullable().optional(),
8818
- parentRef: import_zod18.z.string().nullable().optional(),
8819
- dimension: import_zod18.z.string().nullable().optional(),
8820
- evidence: import_zod18.z.string().nullable().optional(),
8821
- evidenceSnippet: import_zod18.z.string().nullable().optional(),
8822
- message: import_zod18.z.string().nullable().optional(),
8823
- severity: import_zod18.z.string().nullable().optional(),
8824
- suggestedAction: import_zod18.z.string().nullable().optional(),
8825
- canAutoFix: import_zod18.z.boolean().nullable().optional()
8816
+ import_zod19.z.object({
8817
+ code: import_zod19.z.string().nullable().optional(),
8818
+ issueCode: import_zod19.z.string().nullable().optional(),
8819
+ path: import_zod19.z.string().nullable().optional(),
8820
+ parentRef: import_zod19.z.string().nullable().optional(),
8821
+ dimension: import_zod19.z.string().nullable().optional(),
8822
+ evidence: import_zod19.z.string().nullable().optional(),
8823
+ evidenceSnippet: import_zod19.z.string().nullable().optional(),
8824
+ message: import_zod19.z.string().nullable().optional(),
8825
+ severity: import_zod19.z.string().nullable().optional(),
8826
+ suggestedAction: import_zod19.z.string().nullable().optional(),
8827
+ canAutoFix: import_zod19.z.boolean().nullable().optional()
8826
8828
  }).passthrough().transform((value) => ({
8827
8829
  ...value,
8828
8830
  code: value.code ?? value.issueCode ?? "unknown_issue",
@@ -8837,16 +8839,16 @@ var osmdMemoryQualityIssueSchema = import_zod18.z.preprocess(
8837
8839
  canAutoFix: value.canAutoFix === true ? true : false
8838
8840
  }))
8839
8841
  );
8840
- var osmdMemoryQualityOverlaySchema = import_zod18.z.preprocess(
8842
+ var osmdMemoryQualityOverlaySchema = import_zod19.z.preprocess(
8841
8843
  normalizeAgentMarkdownJsonKeys,
8842
- import_zod18.z.object({
8843
- path: import_zod18.z.string().nullable().optional(),
8844
- parentRef: import_zod18.z.string().nullable().optional(),
8845
- status: import_zod18.z.string().nullable().optional(),
8846
- score: import_zod18.z.union([import_zod18.z.number(), import_zod18.z.string()]).nullable().optional(),
8847
- overallScore: import_zod18.z.union([import_zod18.z.number(), import_zod18.z.string()]).nullable().optional(),
8848
- dimensions: import_zod18.z.unknown().nullable().optional(),
8849
- issues: import_zod18.z.array(osmdMemoryQualityIssueSchema).optional()
8844
+ import_zod19.z.object({
8845
+ path: import_zod19.z.string().nullable().optional(),
8846
+ parentRef: import_zod19.z.string().nullable().optional(),
8847
+ status: import_zod19.z.string().nullable().optional(),
8848
+ score: import_zod19.z.union([import_zod19.z.number(), import_zod19.z.string()]).nullable().optional(),
8849
+ overallScore: import_zod19.z.union([import_zod19.z.number(), import_zod19.z.string()]).nullable().optional(),
8850
+ dimensions: import_zod19.z.unknown().nullable().optional(),
8851
+ issues: import_zod19.z.array(osmdMemoryQualityIssueSchema).optional()
8850
8852
  }).passthrough().transform((value) => ({
8851
8853
  ...value,
8852
8854
  path: value.path ?? null,
@@ -8858,9 +8860,9 @@ var osmdMemoryQualityOverlaySchema = import_zod18.z.preprocess(
8858
8860
  issues: value.issues ?? []
8859
8861
  }))
8860
8862
  );
8861
- var osmdMemoryQualitySummarySchema = import_zod18.z.preprocess(
8863
+ var osmdMemoryQualitySummarySchema = import_zod19.z.preprocess(
8862
8864
  normalizeAgentMarkdownJsonKeys,
8863
- import_zod18.z.object({
8865
+ import_zod19.z.object({
8864
8866
  evaluatedCount: nullableCountSchema.optional(),
8865
8867
  passCount: nullableCountSchema.optional(),
8866
8868
  warnCount: nullableCountSchema.optional(),
@@ -8878,19 +8880,19 @@ var osmdMemoryQualitySummarySchema = import_zod18.z.preprocess(
8878
8880
  failCount: value.failCount ?? value.failures ?? null
8879
8881
  }))
8880
8882
  );
8881
- var osmdMemoryQualityResultSchema = import_zod18.z.preprocess(
8883
+ var osmdMemoryQualityResultSchema = import_zod19.z.preprocess(
8882
8884
  normalizeAgentMarkdownJsonKeys,
8883
- import_zod18.z.object({
8884
- status: import_zod18.z.string(),
8885
- scope: import_zod18.z.string().nullable().optional(),
8885
+ import_zod19.z.object({
8886
+ status: import_zod19.z.string(),
8887
+ scope: import_zod19.z.string().nullable().optional(),
8886
8888
  evaluatedCount: nullableCountSchema.optional(),
8887
8889
  passCount: nullableCountSchema.optional(),
8888
8890
  warnCount: nullableCountSchema.optional(),
8889
8891
  failCount: nullableCountSchema.optional(),
8890
8892
  summary: osmdMemoryQualitySummarySchema.optional(),
8891
- weakestOverlays: import_zod18.z.array(osmdMemoryQualityOverlaySchema).optional(),
8892
- issues: import_zod18.z.array(osmdMemoryQualityIssueSchema).optional(),
8893
- scores: import_zod18.z.array(osmdMemoryQualityOverlaySchema).optional()
8893
+ weakestOverlays: import_zod19.z.array(osmdMemoryQualityOverlaySchema).optional(),
8894
+ issues: import_zod19.z.array(osmdMemoryQualityIssueSchema).optional(),
8895
+ scores: import_zod19.z.array(osmdMemoryQualityOverlaySchema).optional()
8894
8896
  }).passthrough().transform((value) => {
8895
8897
  const summary = isRecord5(value.summary) ? value.summary : null;
8896
8898
  return {
@@ -8914,24 +8916,24 @@ function normalizeOsmdIngestFileRecordInput(value) {
8914
8916
  }
8915
8917
  return normalized;
8916
8918
  }
8917
- var osmdIngestFileRecordSchema = import_zod18.z.preprocess(
8919
+ var osmdIngestFileRecordSchema = import_zod19.z.preprocess(
8918
8920
  normalizeOsmdIngestFileRecordInput,
8919
- import_zod18.z.object({
8920
- path: import_zod18.z.string(),
8921
- source: import_zod18.z.string().nullable().optional(),
8922
- access: import_zod18.z.string().nullable().optional(),
8923
- owner: import_zod18.z.string().nullable().optional(),
8924
- parentRef: import_zod18.z.string().nullable().optional(),
8925
- exists: import_zod18.z.boolean().nullable().optional(),
8926
- canCreate: import_zod18.z.boolean().nullable().optional(),
8927
- canUpdate: import_zod18.z.boolean().nullable().optional(),
8928
- canAppend: import_zod18.z.boolean().nullable().optional(),
8929
- wikiRole: import_zod18.z.string().nullable().optional(),
8930
- formatVersion: import_zod18.z.string().nullable().optional(),
8931
- createdAt: import_zod18.z.string().nullable().optional(),
8932
- updatedAt: import_zod18.z.string().nullable().optional(),
8933
- suggestedAction: import_zod18.z.string().nullable().optional(),
8934
- errorCode: import_zod18.z.string().nullable().optional()
8921
+ import_zod19.z.object({
8922
+ path: import_zod19.z.string(),
8923
+ source: import_zod19.z.string().nullable().optional(),
8924
+ access: import_zod19.z.string().nullable().optional(),
8925
+ owner: import_zod19.z.string().nullable().optional(),
8926
+ parentRef: import_zod19.z.string().nullable().optional(),
8927
+ exists: import_zod19.z.boolean().nullable().optional(),
8928
+ canCreate: import_zod19.z.boolean().nullable().optional(),
8929
+ canUpdate: import_zod19.z.boolean().nullable().optional(),
8930
+ canAppend: import_zod19.z.boolean().nullable().optional(),
8931
+ wikiRole: import_zod19.z.string().nullable().optional(),
8932
+ formatVersion: import_zod19.z.string().nullable().optional(),
8933
+ createdAt: import_zod19.z.string().nullable().optional(),
8934
+ updatedAt: import_zod19.z.string().nullable().optional(),
8935
+ suggestedAction: import_zod19.z.string().nullable().optional(),
8936
+ errorCode: import_zod19.z.string().nullable().optional()
8935
8937
  }).passthrough().transform((value) => ({
8936
8938
  ...value,
8937
8939
  source: value.source ?? null,
@@ -8950,17 +8952,17 @@ var osmdIngestFileRecordSchema = import_zod18.z.preprocess(
8950
8952
  errorCode: value.errorCode ?? null
8951
8953
  }))
8952
8954
  );
8953
- var osmdIngestResultSchema = import_zod18.z.preprocess(
8955
+ var osmdIngestResultSchema = import_zod19.z.preprocess(
8954
8956
  normalizeAgentMarkdownJsonKeys,
8955
- import_zod18.z.object({
8956
- rawSourceId: import_zod18.z.union([import_zod18.z.string(), import_zod18.z.number()]).nullable().optional(),
8957
- sourceSummaryPath: import_zod18.z.string().nullable().optional(),
8957
+ import_zod19.z.object({
8958
+ rawSourceId: import_zod19.z.union([import_zod19.z.string(), import_zod19.z.number()]).nullable().optional(),
8959
+ sourceSummaryPath: import_zod19.z.string().nullable().optional(),
8958
8960
  sourceSummaryFile: osmdIngestFileRecordSchema.nullable().optional(),
8959
- slug: import_zod18.z.string().nullable().optional(),
8960
- runLint: import_zod18.z.boolean().nullable().optional(),
8961
- createdFiles: import_zod18.z.array(osmdIngestFileRecordSchema).optional(),
8962
- updatedFiles: import_zod18.z.array(osmdIngestFileRecordSchema).optional(),
8963
- skippedUpdates: import_zod18.z.array(import_zod18.z.unknown()).optional(),
8961
+ slug: import_zod19.z.string().nullable().optional(),
8962
+ runLint: import_zod19.z.boolean().nullable().optional(),
8963
+ createdFiles: import_zod19.z.array(osmdIngestFileRecordSchema).optional(),
8964
+ updatedFiles: import_zod19.z.array(osmdIngestFileRecordSchema).optional(),
8965
+ skippedUpdates: import_zod19.z.array(import_zod19.z.unknown()).optional(),
8964
8966
  lintResult: osmdWikiLintResultSchema.nullable().optional()
8965
8967
  }).passthrough().transform((value) => ({
8966
8968
  ...value,
@@ -8975,37 +8977,37 @@ var osmdIngestResultSchema = import_zod18.z.preprocess(
8975
8977
  lintResult: value.lintResult ?? null
8976
8978
  }))
8977
8979
  );
8978
- var mutationPayloadSchema = import_zod18.z.object({
8979
- ok: import_zod18.z.boolean(),
8980
- status: import_zod18.z.number(),
8981
- errorCode: import_zod18.z.string().nullable().optional(),
8982
- data: import_zod18.z.unknown().nullable().optional(),
8983
- errors: import_zod18.z.unknown().nullable().optional()
8980
+ var mutationPayloadSchema = import_zod19.z.object({
8981
+ ok: import_zod19.z.boolean(),
8982
+ status: import_zod19.z.number(),
8983
+ errorCode: import_zod19.z.string().nullable().optional(),
8984
+ data: import_zod19.z.unknown().nullable().optional(),
8985
+ errors: import_zod19.z.unknown().nullable().optional()
8984
8986
  });
8985
- var markdownTreeNodeSchema = import_zod18.z.lazy(
8986
- () => import_zod18.z.object({
8987
- toolKey: import_zod18.z.string(),
8988
- nodeKey: import_zod18.z.string(),
8989
- nodeKind: import_zod18.z.string(),
8990
- runtimeLabel: import_zod18.z.string(),
8991
- path: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
8987
+ var markdownTreeNodeSchema = import_zod19.z.lazy(
8988
+ () => import_zod19.z.object({
8989
+ toolKey: import_zod19.z.string(),
8990
+ nodeKey: import_zod19.z.string(),
8991
+ nodeKind: import_zod19.z.string(),
8992
+ runtimeLabel: import_zod19.z.string(),
8993
+ path: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
8992
8994
  source: sourceSchema,
8993
8995
  access: accessSchema,
8994
8996
  owner: ownerSchema,
8995
- parentRef: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
8996
- agentChildrenAllowed: import_zod18.z.boolean(),
8997
- exists: import_zod18.z.boolean(),
8998
- resolvedScope: import_zod18.z.object({
8999
- parentId: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
9000
- recordId: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
9001
- memberId: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
9002
- teamId: import_zod18.z.string().nullable().optional().transform((value) => value ?? null),
9003
- contentType: import_zod18.z.string().nullable().optional().transform((value) => value ?? null)
8997
+ parentRef: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
8998
+ agentChildrenAllowed: import_zod19.z.boolean(),
8999
+ exists: import_zod19.z.boolean(),
9000
+ resolvedScope: import_zod19.z.object({
9001
+ parentId: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
9002
+ recordId: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
9003
+ memberId: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
9004
+ teamId: import_zod19.z.string().nullable().optional().transform((value) => value ?? null),
9005
+ contentType: import_zod19.z.string().nullable().optional().transform((value) => value ?? null)
9004
9006
  }),
9005
- isLeaf: import_zod18.z.boolean(),
9006
- treeView: import_zod18.z.boolean(),
9007
- details: import_zod18.z.unknown().nullable(),
9008
- children: import_zod18.z.array(markdownTreeNodeSchema).optional().transform((value) => value ?? [])
9007
+ isLeaf: import_zod19.z.boolean(),
9008
+ treeView: import_zod19.z.boolean(),
9009
+ details: import_zod19.z.unknown().nullable(),
9010
+ children: import_zod19.z.array(markdownTreeNodeSchema).optional().transform((value) => value ?? [])
9009
9011
  })
9010
9012
  );
9011
9013
  var AGENT_MARKDOWN_FILE_SELECTION = `{
@@ -9697,15 +9699,15 @@ function normalizeAgentFilePath(file, parentRef) {
9697
9699
  const trimmed = nonEmptyString3.parse(file).trim().replace(/^\/+|\/+$/g, "");
9698
9700
  const fileName = trimmed.startsWith(".agent/") ? trimmed.slice(".agent/".length) : trimmed;
9699
9701
  const isThreadWorkspace = atlasThreadWorkspaceParentRefPattern.test(parentRef);
9700
- const isSupportedFile = isThreadWorkspace ? /^[a-z0-9][a-z0-9-]*\.(?:md|txt)$/.test(fileName) : isSupportedAgentOverlayFileName(fileName);
9702
+ const isSupportedFile = isThreadWorkspace ? /^[a-z0-9][a-z0-9-]*\.(?:md|txt|csv)$/.test(fileName) : isSupportedAgentOverlayFileName(fileName);
9701
9703
  if (fileName.includes("\\") || fileName.includes("/") || fileName === "." || fileName === ".." || !isSupportedFile) {
9702
9704
  throw new CliError({
9703
- message: isThreadWorkspace ? "Atlas task workspaces support only lowercase kebab-case .md or .txt basenames." : ".agent supports only notes.md, summary.md, or <lowercase-kebab-slug>.md.",
9705
+ message: isThreadWorkspace ? "Atlas task workspaces support only lowercase kebab-case .md, .txt, or .csv basenames." : ".agent supports only notes.md, summary.md, or <lowercase-kebab-slug>.md.",
9704
9706
  kind: "invalid_args",
9705
9707
  status: 400,
9706
9708
  exitCode: EXIT_CODES.invalidArgs,
9707
9709
  details: {
9708
- supportedFiles: isThreadWorkspace ? ["<lowercase-kebab-slug>.md", "<lowercase-kebab-slug>.txt"] : [...supportedAgentOverlaySystemFiles, "<lowercase-kebab-slug>.md"]
9710
+ supportedFiles: isThreadWorkspace ? ["<lowercase-kebab-slug>.md", "<lowercase-kebab-slug>.txt", "<lowercase-kebab-slug>.csv"] : [...supportedAgentOverlaySystemFiles, "<lowercase-kebab-slug>.md"]
9709
9711
  }
9710
9712
  });
9711
9713
  }
@@ -11188,7 +11190,7 @@ function positiveInt2(raw, fallback) {
11188
11190
  function requestTimeoutMs(totalTimeoutMs) {
11189
11191
  return Math.max(1e3, Math.min(totalTimeoutMs, 1e4));
11190
11192
  }
11191
- function asRecord5(value) {
11193
+ function asRecord4(value) {
11192
11194
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
11193
11195
  }
11194
11196
  function asString(value) {
@@ -11238,9 +11240,9 @@ function cliTokenFromPoll(payload) {
11238
11240
  return asString(payload.cliToken) ?? asString(payload.cli_token) ?? asString(payload.token);
11239
11241
  }
11240
11242
  function unwrapMutationResult(value) {
11241
- const record = asRecord5(value);
11243
+ const record = asRecord4(value);
11242
11244
  if (!record) return null;
11243
- const data = asRecord5(record.data);
11245
+ const data = asRecord4(record.data);
11244
11246
  if (data && (Object.prototype.hasOwnProperty.call(record, "ok") || Object.prototype.hasOwnProperty.call(record, "errors") || Object.prototype.hasOwnProperty.call(record, "errorCode") || Object.prototype.hasOwnProperty.call(record, "error_code"))) {
11245
11247
  return data;
11246
11248
  }
@@ -11305,7 +11307,7 @@ async function runTokenLogin(cmd, opts) {
11305
11307
  exitCode: mapStatusToExitCode(status.error.status)
11306
11308
  });
11307
11309
  }
11308
- const statusData = asRecord5(status.result.data.cliAuthStatus) ?? {};
11310
+ const statusData = asRecord4(status.result.data.cliAuthStatus) ?? {};
11309
11311
  const storage = await writeStoredToken(token, baseUrl);
11310
11312
  const configPath2 = opts.saveBaseUrl ? await persistBaseUrl(baseUrl) : void 0;
11311
11313
  return printEnvelopeAndExit({
@@ -11522,7 +11524,7 @@ async function runLogout(cmd) {
11522
11524
  });
11523
11525
  if (result.ok) {
11524
11526
  requestId = result.result.requestId;
11525
- const payload = asRecord5(result.result.data.revokeCliToken) ?? {};
11527
+ const payload = asRecord4(result.result.data.revokeCliToken) ?? {};
11526
11528
  revokedRemote = payload.ok !== false;
11527
11529
  } else {
11528
11530
  requestId = result.requestId;
@@ -11585,7 +11587,7 @@ async function runAuthStatus(cmd) {
11585
11587
  exitCode: mapStatusToExitCode(result.error.status)
11586
11588
  });
11587
11589
  }
11588
- const status = asRecord5(result.result.data.cliAuthStatus) ?? {};
11590
+ const status = asRecord4(result.result.data.cliAuthStatus) ?? {};
11589
11591
  const baseAuthStatus = status.baseAuthStatus;
11590
11592
  return printEnvelopeAndExit({
11591
11593
  envelope: envelope({
@@ -11852,6 +11854,26 @@ var RECENT_TOOL_SUPPORT_REGISTRY = [
11852
11854
  ]
11853
11855
  }
11854
11856
  }),
11857
+ entry({
11858
+ cliKey: "sketches",
11859
+ displayName: "Sketches",
11860
+ backend: backendToolKey("sketches"),
11861
+ routes: ["/sketches", "/sketches/[sketchId]"],
11862
+ capabilityCategories: ["collaboration", "design", "metadata", "read_only_discovery"],
11863
+ sensitiveOutputNotes: [
11864
+ "Sketch commands must not print document bytes, collaboration updates, embedded files, comments, or auth material."
11865
+ ],
11866
+ implementation: {
11867
+ milestone: "WAVE-12",
11868
+ status: "implemented_command_surface",
11869
+ enabledCommands: ["open", "list", "show", "create", "update-metadata"],
11870
+ forbiddenCommands: ["save-document", "render", "export", "import"],
11871
+ notes: [
11872
+ "The Sketch surface is limited to metadata and does not provide an editor, renderer, binary transport, or provider connector.",
11873
+ "Create and metadata update use the existing typed GraphQL mutations."
11874
+ ]
11875
+ }
11876
+ }),
11855
11877
  entry({
11856
11878
  cliKey: "time-tracking",
11857
11879
  displayName: "Time Tracking",
@@ -12855,36 +12877,188 @@ function registerWhiteboardsCommands(program) {
12855
12877
  return printEnvelopeAndExit({
12856
12878
  envelope: {
12857
12879
  ok: true,
12858
- command: "whiteboards.open",
12880
+ command: "whiteboards.open",
12881
+ status: 200,
12882
+ data,
12883
+ error: null,
12884
+ meta: { requestId: "local_whiteboards" }
12885
+ }
12886
+ });
12887
+ });
12888
+ addListFilterOptions2(
12889
+ whiteboards.command("list").description("Read safe Whiteboards metadata")
12890
+ ).action(async (opts, cmd) => {
12891
+ await runWhiteboardsQuery(cmd, {
12892
+ command: "whiteboards.list",
12893
+ operationName: "Whiteboards",
12894
+ field: "whiteboards",
12895
+ variables: listFilters2(opts),
12896
+ variableTypes: listVariableTypes2(),
12897
+ isList: true,
12898
+ selectionSet: WHITEBOARDS_SELECTION
12899
+ });
12900
+ });
12901
+ whiteboards.command("show").description("Read safe Whiteboard detail metadata").requiredOption("--slug <slug>").action(async (opts, cmd) => {
12902
+ await runWhiteboardsQuery(cmd, {
12903
+ command: "whiteboards.show",
12904
+ operationName: "Whiteboard",
12905
+ field: "whiteboard",
12906
+ variables: { slug: opts.slug },
12907
+ variableTypes: { organization_id: "ID!", slug: "ID!" },
12908
+ isShow: true,
12909
+ selectionSet: WHITEBOARD_SELECTION
12910
+ });
12911
+ });
12912
+ }
12913
+
12914
+ // src/commands/sketches.ts
12915
+ var SKETCH_METADATA_SELECTION = "id name slug status priority archivedAt organizationId memberId teamIds documentGeneration documentVersion partytimeRoomId partytimeRoomVersion createdAt updatedAt";
12916
+ var SKETCHES_SELECTION = `{ count currentPage totalPages data { ${SKETCH_METADATA_SELECTION} } }`;
12917
+ var SKETCH_SELECTION = `{ ${SKETCH_METADATA_SELECTION} }`;
12918
+ function baseVariables4(contextOrganizationId) {
12919
+ return { organization_id: resolveOrganizationId(contextOrganizationId) };
12920
+ }
12921
+ function listFilters3(opts) {
12922
+ return {
12923
+ page: opts.page,
12924
+ per: opts.per,
12925
+ team_id: opts.teamId,
12926
+ member_id: opts.memberId,
12927
+ include_archived: opts.includeArchived
12928
+ };
12929
+ }
12930
+ function listVariableTypes3() {
12931
+ return {
12932
+ organization_id: "ID!",
12933
+ page: "Int",
12934
+ per: "Int",
12935
+ team_id: "ID",
12936
+ member_id: "ID",
12937
+ include_archived: "Boolean"
12938
+ };
12939
+ }
12940
+ async function runSketchQuery(cmd, config) {
12941
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
12942
+ await runGraphqlQueryCommand({
12943
+ command: config.command,
12944
+ operationName: config.operationName,
12945
+ runtimeOptions: context.runtimeOptions,
12946
+ field: config.field,
12947
+ variables: normalizeGraphqlVariables2({
12948
+ ...baseVariables4(context.organizationId),
12949
+ ...config.variables
12950
+ }),
12951
+ ...config.variableTypes ? { variableTypes: config.variableTypes } : {},
12952
+ ...config.isList ? { isList: true } : {},
12953
+ ...config.isShow ? { isShow: true } : {},
12954
+ selectionSet: config.selectionSet
12955
+ });
12956
+ }
12957
+ function addListFilterOptions3(command) {
12958
+ return command.option("--page <page>").option("--per <per>").option("--team-id <teamId>").option("--member-id <memberId>").option("--include-archived <includeArchived>");
12959
+ }
12960
+ function sketchOpenData() {
12961
+ const tool = getRecentToolSupport("sketches");
12962
+ return {
12963
+ cliKey: "sketches",
12964
+ displayName: "Sketches",
12965
+ backend: {
12966
+ toolKey: tool?.backend.toolKey ?? "sketches",
12967
+ status: tool?.backend.status ?? "verified_wave_02",
12968
+ sourceMilestone: tool?.backend.sourceMilestone ?? "WAVE-02"
12969
+ },
12970
+ route: tool?.safeRouteTargets.primaryRoute ?? "/sketches",
12971
+ safeRouteTargets: tool?.safeRouteTargets ?? {
12972
+ primaryRoute: "/sketches",
12973
+ deepLinkTemplates: ["/sketches", "/sketches/[sketchId]"],
12974
+ status: "verified_wave_03",
12975
+ sourceMilestone: "WAVE-03"
12976
+ },
12977
+ implementation: {
12978
+ enabledCommands: ["open", "list", "show", "create", "update-metadata"],
12979
+ excludedCommands: ["save-document", "render", "export", "import"]
12980
+ },
12981
+ sensitiveOutputNotes: tool?.sensitiveOutputNotes ?? [
12982
+ "Sketch commands return metadata only and never return document bytes, collaboration updates, embedded files, comments, or tokens."
12983
+ ]
12984
+ };
12985
+ }
12986
+ function registerSketchCommands(program) {
12987
+ const sketches = program.command("sketches").description("Sketch metadata operations with bounded create and update support");
12988
+ sketches.command("open").description("Return verified Sketches app routes without opening a browser").option("--readable", "Print the primary route path only").option("--json", "Emit the stable JSON envelope").action((opts) => {
12989
+ const data = sketchOpenData();
12990
+ if (opts.readable && !opts.json) return printTextAndExit({ text: String(data.route) });
12991
+ return printEnvelopeAndExit({
12992
+ envelope: {
12993
+ ok: true,
12994
+ command: "sketches.open",
12859
12995
  status: 200,
12860
12996
  data,
12861
12997
  error: null,
12862
- meta: { requestId: "local_whiteboards" }
12998
+ meta: { requestId: "local_sketches" }
12863
12999
  }
12864
13000
  });
12865
13001
  });
12866
- addListFilterOptions2(
12867
- whiteboards.command("list").description("Read safe Whiteboards metadata")
12868
- ).action(async (opts, cmd) => {
12869
- await runWhiteboardsQuery(cmd, {
12870
- command: "whiteboards.list",
12871
- operationName: "Whiteboards",
12872
- field: "whiteboards",
12873
- variables: listFilters2(opts),
12874
- variableTypes: listVariableTypes2(),
12875
- isList: true,
12876
- selectionSet: WHITEBOARDS_SELECTION
12877
- });
12878
- });
12879
- whiteboards.command("show").description("Read safe Whiteboard detail metadata").requiredOption("--slug <slug>").action(async (opts, cmd) => {
12880
- await runWhiteboardsQuery(cmd, {
12881
- command: "whiteboards.show",
12882
- operationName: "Whiteboard",
12883
- field: "whiteboard",
13002
+ addListFilterOptions3(sketches.command("list").description("Read safe Sketch metadata")).action(
13003
+ async (opts, cmd) => {
13004
+ await runSketchQuery(cmd, {
13005
+ command: "sketches.list",
13006
+ operationName: "Sketches",
13007
+ field: "sketches",
13008
+ variables: listFilters3(opts),
13009
+ variableTypes: listVariableTypes3(),
13010
+ isList: true,
13011
+ selectionSet: SKETCHES_SELECTION
13012
+ });
13013
+ }
13014
+ );
13015
+ sketches.command("show").description("Read safe Sketch detail metadata").requiredOption("--slug <slug>").action(async (opts, cmd) => {
13016
+ await runSketchQuery(cmd, {
13017
+ command: "sketches.show",
13018
+ operationName: "Sketch",
13019
+ field: "sketch",
12884
13020
  variables: { slug: opts.slug },
12885
13021
  variableTypes: { organization_id: "ID!", slug: "ID!" },
12886
13022
  isShow: true,
12887
- selectionSet: WHITEBOARD_SELECTION
13023
+ selectionSet: SKETCH_SELECTION
13024
+ });
13025
+ });
13026
+ sketches.command("create").description("Create a Sketch with a required team and idempotency key").requiredOption("--data-json <dataJson>", 'Sketch JSON or {"sketch": {...}}').action(async (opts, cmd) => {
13027
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
13028
+ const body = __testables.normalizeBody(String(opts.dataJson), "sketch");
13029
+ assertOperationPayload("sketches.create", body);
13030
+ await runGraphqlMutationCommand({
13031
+ command: "sketches.create",
13032
+ runtimeOptions: context.runtimeOptions,
13033
+ field: "create_sketch",
13034
+ variables: {
13035
+ organization_id: resolveOrganizationId(context.organizationId),
13036
+ params: body
13037
+ },
13038
+ variableTypes: {
13039
+ organization_id: "ID!",
13040
+ params: "CreateSketchParamsInput!"
13041
+ }
13042
+ });
13043
+ });
13044
+ sketches.command("update-metadata").description("Update bounded Sketch metadata; document content is never accepted").requiredOption("--id <id>").requiredOption("--data-json <dataJson>", 'Sketch metadata JSON or {"sketch": {...}}').action(async (opts, cmd) => {
13045
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
13046
+ const body = __testables.normalizeBody(String(opts.dataJson), "sketch");
13047
+ assertOperationPayload("sketches.update-metadata", body);
13048
+ await runGraphqlMutationCommand({
13049
+ command: "sketches.update-metadata",
13050
+ runtimeOptions: context.runtimeOptions,
13051
+ field: "update_sketch",
13052
+ variables: {
13053
+ organization_id: resolveOrganizationId(context.organizationId),
13054
+ sketch_id: String(opts.id),
13055
+ params: body
13056
+ },
13057
+ variableTypes: {
13058
+ organization_id: "ID!",
13059
+ sketch_id: "ID!",
13060
+ params: "UpdateSketchParamsInput!"
13061
+ }
12888
13062
  });
12889
13063
  });
12890
13064
  }
@@ -12919,7 +13093,7 @@ var TIME_TRACKING_FORBIDDEN_COMMANDS = [
12919
13093
  "payroll",
12920
13094
  "billing"
12921
13095
  ];
12922
- function baseVariables4(contextOrganizationId) {
13096
+ function baseVariables5(contextOrganizationId) {
12923
13097
  return {
12924
13098
  organization_id: resolveOrganizationId(contextOrganizationId)
12925
13099
  };
@@ -12974,7 +13148,7 @@ async function runTimeTrackingQuery(cmd, config) {
12974
13148
  runtimeOptions: context.runtimeOptions,
12975
13149
  field: config.field,
12976
13150
  variables: normalizeGraphqlVariables2({
12977
- ...baseVariables4(context.organizationId),
13151
+ ...baseVariables5(context.organizationId),
12978
13152
  ...config.variables
12979
13153
  }),
12980
13154
  variableTypes: config.variableTypes,
@@ -13236,11 +13410,11 @@ function sanitizePlannerJson(value) {
13236
13410
  }
13237
13411
  return output;
13238
13412
  }
13239
- function asRecord6(value) {
13413
+ function asRecord5(value) {
13240
13414
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
13241
13415
  }
13242
13416
  function readPlannerStateKey(value, keys) {
13243
- const record = asRecord6(value);
13417
+ const record = asRecord5(value);
13244
13418
  if (!record) {
13245
13419
  return null;
13246
13420
  }
@@ -13435,6 +13609,7 @@ var MAIL_ENABLED_COMMANDS = [
13435
13609
  "open",
13436
13610
  "validate-provider",
13437
13611
  "workspace",
13612
+ "relay-evidence",
13438
13613
  "accounts",
13439
13614
  "messages",
13440
13615
  "conversations",
@@ -13500,6 +13675,9 @@ var MAIL_SETTINGS_SELECTION = "{ id organizationId memberId defaultMailAccountId
13500
13675
  var MAIL_UNREAD_COUNT_SELECTION = "{ total byAccount byLabel }";
13501
13676
  var MAIL_SYNC_STATUS_SELECTION = "{ id status operationStatus operationToolKey accountId accountIds page per view importedCount updatedCount providerCount counts errorCode statusCode queuedAt startedAt completedAt createdAt updatedAt }";
13502
13677
  var MAIL_WORKSPACE_SELECTION = `{ accounts ${MAIL_ACCOUNT_SELECTION} messages ${MAIL_MESSAGES_SELECTION} labels ${MAIL_LABEL_SELECTION} snippets ${MAIL_SNIPPET_SELECTION} settings ${MAIL_SETTINGS_SELECTION} unreadCount ${MAIL_UNREAD_COUNT_SELECTION} }`;
13678
+ var MAIL_RELAY_EVIDENCE_ACCOUNT_SELECTION = "{ id provider service status connectionState syncStatus emailAddress displayName lastSyncedAt }";
13679
+ var MAIL_RELAY_EVIDENCE_MESSAGE_SELECTION = "{ id mailAccountId subject from status direction sentAt receivedAt snippet createdAt updatedAt }";
13680
+ var MAIL_RELAY_EVIDENCE_SELECTION = `{ accounts ${MAIL_RELAY_EVIDENCE_ACCOUNT_SELECTION} messages { count currentPage totalPages data ${MAIL_RELAY_EVIDENCE_MESSAGE_SELECTION} } }`;
13503
13681
  var OUTLOOK_PROVIDER_VALIDATION_EVIDENCE = {
13504
13682
  provider: "microsoft",
13505
13683
  oauthProviderId: "wave-microsoft-outlook",
@@ -13664,7 +13842,8 @@ function buildMailOpenData() {
13664
13842
  forbiddenCommands: [...MAIL_FORBIDDEN_COMMANDS]
13665
13843
  },
13666
13844
  sensitiveOutputNotes: tool?.sensitiveOutputNotes ?? [
13667
- "Mail commands are metadata-only and must not print message bodies, subjects, snippets, contacts, attachments, provider payloads, token material, account addresses/display names, label names/colors, snippet content, preferences, signatures, sync search text, sync error bodies, or user-authored mail content."
13845
+ "Default Mail commands are metadata-only and must not print message bodies, subjects, snippets, contacts, attachments, provider payloads, token material, account addresses/display names, label names/colors, snippet content, preferences, signatures, sync search text, sync error bodies, or user-authored mail content.",
13846
+ "mail relay-evidence is the explicit bounded exception for an authenticated, user-authorized relay: it exposes mailbox identity plus sender, subject, date, and snippet metadata, but never bodies, recipients, attachments, provider IDs, or token material."
13668
13847
  ]
13669
13848
  };
13670
13849
  }
@@ -13777,6 +13956,26 @@ function registerMailCommands(program) {
13777
13956
  isShow: true
13778
13957
  });
13779
13958
  });
13959
+ addPaginationOptions(
13960
+ mail.command("relay-evidence").description(
13961
+ "Read bounded mailbox identity and recent message metadata for an explicitly authorized relay"
13962
+ ).option("--account-id <accountId>")
13963
+ ).action(async (opts, cmd) => {
13964
+ await runMailQuery(cmd, opts, {
13965
+ command: "mail.relay-evidence",
13966
+ operationName: "MailRelayEvidence",
13967
+ field: "mail_workspace",
13968
+ variables: mailWorkspaceVariables,
13969
+ variableTypes: {
13970
+ organization_id: "ID!",
13971
+ account_id: "ID",
13972
+ page: "Int",
13973
+ per: "Int"
13974
+ },
13975
+ selectionSet: MAIL_RELAY_EVIDENCE_SELECTION,
13976
+ isShow: true
13977
+ });
13978
+ });
13780
13979
  mail.command("accounts").description("Read safe Mail account metadata").action(async (opts, cmd) => {
13781
13980
  await runMailQuery(cmd, opts, {
13782
13981
  command: "mail.accounts",
@@ -13932,14 +14131,14 @@ function registerMailCommands(program) {
13932
14131
  }
13933
14132
 
13934
14133
  // src/commands/phantom.ts
13935
- var import_zod19 = require("zod");
13936
- var nonNegativeInt4 = import_zod19.z.coerce.number().int().min(0);
13937
- var nullableString = import_zod19.z.string().nullable().optional().transform((value) => value ?? null);
13938
- var idString = import_zod19.z.union([import_zod19.z.string(), import_zod19.z.number()]).transform((value) => String(value));
13939
- var nullableIdString = import_zod19.z.union([import_zod19.z.string(), import_zod19.z.number()]).nullable().optional().transform(
14134
+ var import_zod20 = require("zod");
14135
+ var nonNegativeInt4 = import_zod20.z.coerce.number().int().min(0);
14136
+ var nullableString = import_zod20.z.string().nullable().optional().transform((value) => value ?? null);
14137
+ var idString = import_zod20.z.union([import_zod20.z.string(), import_zod20.z.number()]).transform((value) => String(value));
14138
+ var nullableIdString = import_zod20.z.union([import_zod20.z.string(), import_zod20.z.number()]).nullable().optional().transform(
13940
14139
  (value) => value === void 0 || value === null ? null : String(value)
13941
14140
  );
13942
- var jsonObject = import_zod19.z.record(import_zod19.z.string(), import_zod19.z.unknown());
14141
+ var jsonObject = import_zod20.z.record(import_zod20.z.string(), import_zod20.z.unknown());
13943
14142
  var PHANTOM_LEDGER_INVENTORY_SELECTION = `{
13944
14143
  schemaVersion
13945
14144
  runsCount
@@ -14152,10 +14351,10 @@ var PHANTOM_LEDGER_KEY_ALIASES = {
14152
14351
  content_hash: "contentHash",
14153
14352
  observed_at: "observedAt"
14154
14353
  };
14155
- var phantomLedgerInventorySchema = import_zod19.z.preprocess(
14354
+ var phantomLedgerInventorySchema = import_zod20.z.preprocess(
14156
14355
  normalizePhantomLedgerKeys,
14157
- import_zod19.z.object({
14158
- schemaVersion: import_zod19.z.string(),
14356
+ import_zod20.z.object({
14357
+ schemaVersion: import_zod20.z.string(),
14159
14358
  runsCount: nonNegativeInt4,
14160
14359
  observationsCount: nonNegativeInt4,
14161
14360
  candidatesCount: nonNegativeInt4,
@@ -14165,16 +14364,16 @@ var phantomLedgerInventorySchema = import_zod19.z.preprocess(
14165
14364
  reportsCount: nonNegativeInt4
14166
14365
  })
14167
14366
  );
14168
- var phantomRunSchema = import_zod19.z.preprocess(
14367
+ var phantomRunSchema = import_zod20.z.preprocess(
14169
14368
  normalizePhantomLedgerKeys,
14170
- import_zod19.z.object({
14369
+ import_zod20.z.object({
14171
14370
  id: idString,
14172
14371
  organizationId: idString,
14173
- notificationId: import_zod19.z.union([import_zod19.z.string(), import_zod19.z.number()]).nullable().optional().transform(
14372
+ notificationId: import_zod20.z.union([import_zod20.z.string(), import_zod20.z.number()]).nullable().optional().transform(
14174
14373
  (value) => value === void 0 || value === null ? null : String(value)
14175
14374
  ),
14176
- status: import_zod19.z.string(),
14177
- triggerType: import_zod19.z.string(),
14375
+ status: import_zod20.z.string(),
14376
+ triggerType: import_zod20.z.string(),
14178
14377
  startedAt: nullableString,
14179
14378
  completedAt: nullableString,
14180
14379
  scannedFileCount: nonNegativeInt4,
@@ -14184,163 +14383,163 @@ var phantomRunSchema = import_zod19.z.preprocess(
14184
14383
  errorCount: nonNegativeInt4,
14185
14384
  warningCount: nonNegativeInt4,
14186
14385
  errorMessage: nullableString,
14187
- dryRun: import_zod19.z.boolean(),
14188
- schemaVersion: import_zod19.z.string(),
14386
+ dryRun: import_zod20.z.boolean(),
14387
+ schemaVersion: import_zod20.z.string(),
14189
14388
  testRunId: nullableString,
14190
14389
  idempotencyKey: nullableString,
14191
14390
  ledgerMetadata: jsonObject.catch({}),
14192
- createdAt: import_zod19.z.string(),
14193
- updatedAt: import_zod19.z.string()
14391
+ createdAt: import_zod20.z.string(),
14392
+ updatedAt: import_zod20.z.string()
14194
14393
  })
14195
14394
  );
14196
- var phantomRunListItemSchema = import_zod19.z.preprocess(
14395
+ var phantomRunListItemSchema = import_zod20.z.preprocess(
14197
14396
  normalizePhantomLedgerKeys,
14198
- import_zod19.z.object({
14397
+ import_zod20.z.object({
14199
14398
  id: idString,
14200
14399
  organizationId: idString,
14201
- status: import_zod19.z.string(),
14202
- triggerType: import_zod19.z.string(),
14203
- dryRun: import_zod19.z.boolean(),
14204
- schemaVersion: import_zod19.z.string(),
14400
+ status: import_zod20.z.string(),
14401
+ triggerType: import_zod20.z.string(),
14402
+ dryRun: import_zod20.z.boolean(),
14403
+ schemaVersion: import_zod20.z.string(),
14205
14404
  testRunId: nullableString,
14206
- createdAt: import_zod19.z.string(),
14207
- updatedAt: import_zod19.z.string()
14405
+ createdAt: import_zod20.z.string(),
14406
+ updatedAt: import_zod20.z.string()
14208
14407
  })
14209
14408
  );
14210
- var phantomReportSchema = import_zod19.z.preprocess(
14409
+ var phantomReportSchema = import_zod20.z.preprocess(
14211
14410
  normalizePhantomLedgerKeys,
14212
- import_zod19.z.object({
14411
+ import_zod20.z.object({
14213
14412
  id: idString,
14214
14413
  organizationId: idString,
14215
14414
  phantomRunId: idString,
14216
- status: import_zod19.z.string(),
14217
- reportType: import_zod19.z.string(),
14218
- schemaVersion: import_zod19.z.string(),
14415
+ status: import_zod20.z.string(),
14416
+ reportType: import_zod20.z.string(),
14417
+ schemaVersion: import_zod20.z.string(),
14219
14418
  markdownPath: nullableString,
14220
14419
  payload: jsonObject.catch({}),
14221
14420
  testRunId: nullableString,
14222
- idempotencyKey: import_zod19.z.string(),
14223
- createdAt: import_zod19.z.string(),
14224
- updatedAt: import_zod19.z.string()
14421
+ idempotencyKey: import_zod20.z.string(),
14422
+ createdAt: import_zod20.z.string(),
14423
+ updatedAt: import_zod20.z.string()
14225
14424
  })
14226
14425
  );
14227
- var phantomObservationSchema = import_zod19.z.preprocess(
14426
+ var phantomObservationSchema = import_zod20.z.preprocess(
14228
14427
  normalizePhantomLedgerKeys,
14229
- import_zod19.z.object({
14428
+ import_zod20.z.object({
14230
14429
  id: idString,
14231
14430
  organizationId: idString,
14232
14431
  phantomRunId: idString,
14233
- status: import_zod19.z.string(),
14234
- observationType: import_zod19.z.string(),
14432
+ status: import_zod20.z.string(),
14433
+ observationType: import_zod20.z.string(),
14235
14434
  targetType: nullableString,
14236
14435
  targetId: nullableString,
14237
14436
  sourceTable: nullableString,
14238
14437
  sourceRecordId: nullableString,
14239
14438
  sourceEventId: nullableString,
14240
14439
  contentHash: nullableString,
14241
- observedAt: import_zod19.z.string(),
14242
- confidence: import_zod19.z.coerce.number(),
14440
+ observedAt: import_zod20.z.string(),
14441
+ confidence: import_zod20.z.coerce.number(),
14243
14442
  payload: jsonObject.catch({}),
14244
- schemaVersion: import_zod19.z.string(),
14443
+ schemaVersion: import_zod20.z.string(),
14245
14444
  testRunId: nullableString,
14246
- idempotencyKey: import_zod19.z.string(),
14247
- createdAt: import_zod19.z.string(),
14248
- updatedAt: import_zod19.z.string()
14445
+ idempotencyKey: import_zod20.z.string(),
14446
+ createdAt: import_zod20.z.string(),
14447
+ updatedAt: import_zod20.z.string()
14249
14448
  })
14250
14449
  );
14251
- var phantomCandidateSchema = import_zod19.z.preprocess(
14450
+ var phantomCandidateSchema = import_zod20.z.preprocess(
14252
14451
  normalizePhantomLedgerKeys,
14253
- import_zod19.z.object({
14452
+ import_zod20.z.object({
14254
14453
  id: idString,
14255
14454
  organizationId: idString,
14256
14455
  phantomRunId: idString,
14257
14456
  phantomObservationId: nullableString,
14258
- status: import_zod19.z.string(),
14259
- candidateType: import_zod19.z.string(),
14457
+ status: import_zod20.z.string(),
14458
+ candidateType: import_zod20.z.string(),
14260
14459
  targetType: nullableString,
14261
14460
  targetId: nullableString,
14262
14461
  title: nullableString,
14263
- dryRun: import_zod19.z.boolean(),
14462
+ dryRun: import_zod20.z.boolean(),
14264
14463
  payload: jsonObject.catch({}),
14265
- approvalStatus: import_zod19.z.string(),
14464
+ approvalStatus: import_zod20.z.string(),
14266
14465
  approvedById: nullableIdString,
14267
14466
  approvedAt: nullableString,
14268
14467
  approvalSource: nullableString,
14269
14468
  approvalReason: nullableString,
14270
14469
  approvalMetadata: jsonObject.catch({}),
14271
- schemaVersion: import_zod19.z.string(),
14470
+ schemaVersion: import_zod20.z.string(),
14272
14471
  testRunId: nullableString,
14273
- idempotencyKey: import_zod19.z.string(),
14274
- createdAt: import_zod19.z.string(),
14275
- updatedAt: import_zod19.z.string()
14472
+ idempotencyKey: import_zod20.z.string(),
14473
+ createdAt: import_zod20.z.string(),
14474
+ updatedAt: import_zod20.z.string()
14276
14475
  })
14277
14476
  );
14278
- var phantomCandidateEvidenceSchema = import_zod19.z.preprocess(
14477
+ var phantomCandidateEvidenceSchema = import_zod20.z.preprocess(
14279
14478
  normalizePhantomLedgerKeys,
14280
- import_zod19.z.object({
14479
+ import_zod20.z.object({
14281
14480
  id: idString,
14282
14481
  organizationId: idString,
14283
14482
  phantomCandidateId: idString,
14284
14483
  phantomObservationId: nullableString,
14285
- evidenceType: import_zod19.z.string(),
14484
+ evidenceType: import_zod20.z.string(),
14286
14485
  sourceType: nullableString,
14287
14486
  sourceId: nullableString,
14288
14487
  contentHash: nullableString,
14289
14488
  payload: jsonObject.catch({}),
14290
- schemaVersion: import_zod19.z.string(),
14489
+ schemaVersion: import_zod20.z.string(),
14291
14490
  testRunId: nullableString,
14292
- idempotencyKey: import_zod19.z.string(),
14293
- createdAt: import_zod19.z.string(),
14294
- updatedAt: import_zod19.z.string()
14491
+ idempotencyKey: import_zod20.z.string(),
14492
+ createdAt: import_zod20.z.string(),
14493
+ updatedAt: import_zod20.z.string()
14295
14494
  })
14296
14495
  );
14297
- var phantomValidationSchema = import_zod19.z.preprocess(
14496
+ var phantomValidationSchema = import_zod20.z.preprocess(
14298
14497
  normalizePhantomLedgerKeys,
14299
- import_zod19.z.object({
14498
+ import_zod20.z.object({
14300
14499
  id: idString,
14301
14500
  organizationId: idString,
14302
14501
  phantomRunId: idString,
14303
14502
  phantomCandidateId: idString,
14304
- status: import_zod19.z.string(),
14305
- validationType: import_zod19.z.string(),
14306
- dryRun: import_zod19.z.boolean(),
14503
+ status: import_zod20.z.string(),
14504
+ validationType: import_zod20.z.string(),
14505
+ dryRun: import_zod20.z.boolean(),
14307
14506
  payload: jsonObject.catch({}),
14308
14507
  resultPayload: jsonObject.catch({}),
14309
- schemaVersion: import_zod19.z.string(),
14508
+ schemaVersion: import_zod20.z.string(),
14310
14509
  testRunId: nullableString,
14311
- idempotencyKey: import_zod19.z.string(),
14312
- createdAt: import_zod19.z.string(),
14313
- updatedAt: import_zod19.z.string()
14510
+ idempotencyKey: import_zod20.z.string(),
14511
+ createdAt: import_zod20.z.string(),
14512
+ updatedAt: import_zod20.z.string()
14314
14513
  })
14315
14514
  );
14316
- var phantomApplyOperationSchema = import_zod19.z.preprocess(
14515
+ var phantomApplyOperationSchema = import_zod20.z.preprocess(
14317
14516
  normalizePhantomLedgerKeys,
14318
- import_zod19.z.object({
14517
+ import_zod20.z.object({
14319
14518
  id: idString,
14320
14519
  organizationId: idString,
14321
14520
  phantomRunId: idString,
14322
14521
  phantomCandidateId: idString,
14323
- status: import_zod19.z.string(),
14324
- operationType: import_zod19.z.string(),
14325
- dryRun: import_zod19.z.boolean(),
14522
+ status: import_zod20.z.string(),
14523
+ operationType: import_zod20.z.string(),
14524
+ dryRun: import_zod20.z.boolean(),
14326
14525
  targetType: nullableString,
14327
14526
  targetId: nullableString,
14328
14527
  payload: jsonObject.catch({}),
14329
14528
  resultPayload: jsonObject.catch({}),
14330
- schemaVersion: import_zod19.z.string(),
14529
+ schemaVersion: import_zod20.z.string(),
14331
14530
  testRunId: nullableString,
14332
- idempotencyKey: import_zod19.z.string(),
14333
- createdAt: import_zod19.z.string(),
14334
- updatedAt: import_zod19.z.string()
14531
+ idempotencyKey: import_zod20.z.string(),
14532
+ createdAt: import_zod20.z.string(),
14533
+ updatedAt: import_zod20.z.string()
14335
14534
  })
14336
14535
  );
14337
- var phantomRunsSchema = import_zod19.z.array(phantomRunListItemSchema);
14338
- var phantomReportsSchema = import_zod19.z.array(phantomReportSchema);
14339
- var phantomObservationsSchema = import_zod19.z.array(phantomObservationSchema);
14340
- var phantomCandidatesSchema = import_zod19.z.array(phantomCandidateSchema);
14341
- var phantomCandidateEvidencesSchema = import_zod19.z.array(phantomCandidateEvidenceSchema);
14342
- var phantomValidationsSchema = import_zod19.z.array(phantomValidationSchema);
14343
- var phantomApplyOperationsSchema = import_zod19.z.array(phantomApplyOperationSchema);
14536
+ var phantomRunsSchema = import_zod20.z.array(phantomRunListItemSchema);
14537
+ var phantomReportsSchema = import_zod20.z.array(phantomReportSchema);
14538
+ var phantomObservationsSchema = import_zod20.z.array(phantomObservationSchema);
14539
+ var phantomCandidatesSchema = import_zod20.z.array(phantomCandidateSchema);
14540
+ var phantomCandidateEvidencesSchema = import_zod20.z.array(phantomCandidateEvidenceSchema);
14541
+ var phantomValidationsSchema = import_zod20.z.array(phantomValidationSchema);
14542
+ var phantomApplyOperationsSchema = import_zod20.z.array(phantomApplyOperationSchema);
14344
14543
  function isRecord6(value) {
14345
14544
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
14346
14545
  }
@@ -15818,7 +16017,7 @@ var URL_OR_TRANSPORT_KEY = /(?:^|_)(?:url|uri|token|nonce|post_fields|postfields
15818
16017
  function isRecord7(value) {
15819
16018
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15820
16019
  }
15821
- function asNonEmptyString6(value) {
16020
+ function asNonEmptyString5(value) {
15822
16021
  if (typeof value !== "string") return null;
15823
16022
  const trimmed = value.trim();
15824
16023
  return trimmed.length > 0 ? trimmed : null;
@@ -15863,7 +16062,7 @@ function parseCreatePayload(raw, mode) {
15863
16062
  ["name", "subject", "message", "expires_at", "visibility", "metadata", "recipients"],
15864
16063
  "--data-json"
15865
16064
  );
15866
- const parsedMode = asNonEmptyString6(mode);
16065
+ const parsedMode = asNonEmptyString5(mode);
15867
16066
  if (parsedMode !== "request" && parsedMode !== "self_sign") {
15868
16067
  throw new CliError({
15869
16068
  message: "signatures create requires --mode request or --mode self_sign.",
@@ -15881,9 +16080,9 @@ function parseUpdatePayload(raw, options) {
15881
16080
  ["name", "subject", "message", "expires_at", "visibility", "recipients", "fields"],
15882
16081
  "--data-json"
15883
16082
  );
15884
- const name = asNonEmptyString6(options.name);
15885
- const subject = asNonEmptyString6(options.subject);
15886
- const message = asNonEmptyString6(options.message);
16083
+ const name = asNonEmptyString5(options.name);
16084
+ const subject = asNonEmptyString5(options.subject);
16085
+ const message = asNonEmptyString5(options.message);
15887
16086
  const patch = {
15888
16087
  ...data,
15889
16088
  ...name ? { name } : {},
@@ -16018,8 +16217,8 @@ function requireUploadTarget(payload) {
16018
16217
  exitCode: EXIT_CODES.networkOrUpstream
16019
16218
  });
16020
16219
  }
16021
- const postUrl = asNonEmptyString6(attributes.postUrl);
16022
- const fileKey = asNonEmptyString6(attributes.getUrl);
16220
+ const postUrl = asNonEmptyString5(attributes.postUrl);
16221
+ const fileKey = asNonEmptyString5(attributes.getUrl);
16023
16222
  const rawPostFields = attributes.postFields;
16024
16223
  if (!postUrl || !fileKey || !isRecord7(rawPostFields) || !fileKey.startsWith("uploads/signatures/")) {
16025
16224
  throw new CliError({
@@ -16269,72 +16468,72 @@ function registerSignatureCommands(program) {
16269
16468
  }
16270
16469
 
16271
16470
  // src/commands/atlasAuthoring.ts
16272
- var import_zod20 = require("zod");
16273
- var idSchema15 = import_zod20.z.string().trim().min(1);
16274
- var idempotencyKeySchema = import_zod20.z.string().min(1).refine((value) => value.trim() === value, "Idempotency key must not have leading or trailing whitespace.");
16275
- var skillScopeSchema = import_zod20.z.enum(["ADMIN_GLOBAL", "MEMBER_PERSONAL"]);
16276
- var isoDateSchema = import_zod20.z.iso.date();
16277
- var nonEmptyStringSchema = import_zod20.z.string().trim().min(1);
16471
+ var import_zod21 = require("zod");
16472
+ var idSchema15 = import_zod21.z.string().trim().min(1);
16473
+ var idempotencyKeySchema = import_zod21.z.string().min(1).refine((value) => value.trim() === value, "Idempotency key must not have leading or trailing whitespace.");
16474
+ var skillScopeSchema = import_zod21.z.enum(["ADMIN_GLOBAL", "MEMBER_PERSONAL"]);
16475
+ var isoDateSchema = import_zod21.z.iso.date();
16476
+ var nonEmptyStringSchema = import_zod21.z.string().trim().min(1);
16278
16477
  var AUTOMATION_RUN_HTTP_TIMEOUT_MS = 6e4;
16279
- var agentToolAccessSchema = import_zod20.z.array(
16280
- import_zod20.z.object({
16478
+ var agentToolAccessSchema = import_zod21.z.array(
16479
+ import_zod21.z.object({
16281
16480
  tool_key: nonEmptyStringSchema,
16282
16481
  scope_value: nonEmptyStringSchema
16283
16482
  }).strict()
16284
16483
  ).min(1);
16285
16484
  var agentToolAccessUpdateSchema = agentToolAccessSchema.min(0);
16286
- var agentPluginConnectionsSchema = import_zod20.z.array(
16287
- import_zod20.z.object({
16485
+ var agentPluginConnectionsSchema = import_zod21.z.array(
16486
+ import_zod21.z.object({
16288
16487
  external_tool_connection_id: nonEmptyStringSchema,
16289
16488
  tool_key: nonEmptyStringSchema,
16290
16489
  scope_value: nonEmptyStringSchema.optional(),
16291
- allowed_tools: import_zod20.z.array(nonEmptyStringSchema).optional(),
16292
- allowed_scopes: import_zod20.z.array(nonEmptyStringSchema).optional(),
16293
- requires_confirmation: import_zod20.z.boolean().optional(),
16294
- enabled: import_zod20.z.boolean().optional()
16490
+ allowed_tools: import_zod21.z.array(nonEmptyStringSchema).optional(),
16491
+ allowed_scopes: import_zod21.z.array(nonEmptyStringSchema).optional(),
16492
+ requires_confirmation: import_zod21.z.boolean().optional(),
16493
+ enabled: import_zod21.z.boolean().optional()
16295
16494
  }).strict()
16296
16495
  ).min(1);
16297
- var agentPluginConnectionUpdateSchema = import_zod20.z.array(
16298
- import_zod20.z.union([
16299
- import_zod20.z.object({
16496
+ var agentPluginConnectionUpdateSchema = import_zod21.z.array(
16497
+ import_zod21.z.union([
16498
+ import_zod21.z.object({
16300
16499
  id: nonEmptyStringSchema,
16301
- _destroy: import_zod20.z.literal(true)
16500
+ _destroy: import_zod21.z.literal(true)
16302
16501
  }).strict(),
16303
- import_zod20.z.object({
16502
+ import_zod21.z.object({
16304
16503
  id: nonEmptyStringSchema.optional(),
16305
16504
  external_tool_connection_id: nonEmptyStringSchema.optional(),
16306
16505
  tool_key: nonEmptyStringSchema.optional(),
16307
16506
  scope_value: nonEmptyStringSchema.optional(),
16308
- allowed_tools: import_zod20.z.array(nonEmptyStringSchema).optional(),
16309
- allowed_scopes: import_zod20.z.array(nonEmptyStringSchema).optional(),
16310
- requires_confirmation: import_zod20.z.boolean().optional(),
16311
- enabled: import_zod20.z.boolean().optional()
16507
+ allowed_tools: import_zod21.z.array(nonEmptyStringSchema).optional(),
16508
+ allowed_scopes: import_zod21.z.array(nonEmptyStringSchema).optional(),
16509
+ requires_confirmation: import_zod21.z.boolean().optional(),
16510
+ enabled: import_zod21.z.boolean().optional()
16312
16511
  }).strict().superRefine((value, context) => {
16313
16512
  if (value.id || value.external_tool_connection_id && value.tool_key) return;
16314
16513
  context.addIssue({
16315
- code: import_zod20.z.ZodIssueCode.custom,
16514
+ code: import_zod21.z.ZodIssueCode.custom,
16316
16515
  message: "Plugin updates require an id, or both external_tool_connection_id and tool_key for a new grant."
16317
16516
  });
16318
16517
  })
16319
16518
  ])
16320
16519
  );
16321
- var agentTriggerSchema = import_zod20.z.object({
16322
- trigger_type: import_zod20.z.literal("cron"),
16520
+ var agentTriggerSchema = import_zod21.z.object({
16521
+ trigger_type: import_zod21.z.literal("cron"),
16323
16522
  cron_expression: nonEmptyStringSchema,
16324
16523
  timezone: nonEmptyStringSchema,
16325
- starts_at: import_zod20.z.iso.datetime({ offset: true }).nullable().optional(),
16326
- ends_at: import_zod20.z.iso.datetime({ offset: true }).nullable().optional(),
16327
- max_runs: import_zod20.z.number().int().positive().nullable().optional(),
16328
- enabled: import_zod20.z.boolean().optional()
16524
+ starts_at: import_zod21.z.iso.datetime({ offset: true }).nullable().optional(),
16525
+ ends_at: import_zod21.z.iso.datetime({ offset: true }).nullable().optional(),
16526
+ max_runs: import_zod21.z.number().int().positive().nullable().optional(),
16527
+ enabled: import_zod21.z.boolean().optional()
16329
16528
  }).strict();
16330
- var agentTriggerUpdateSchema = import_zod20.z.union([
16529
+ var agentTriggerUpdateSchema = import_zod21.z.union([
16331
16530
  agentTriggerSchema.extend({ id: nonEmptyStringSchema.optional() }).strict(),
16332
- import_zod20.z.object({
16531
+ import_zod21.z.object({
16333
16532
  id: nonEmptyStringSchema,
16334
- _destroy: import_zod20.z.literal(true)
16533
+ _destroy: import_zod21.z.literal(true)
16335
16534
  }).strict()
16336
16535
  ]);
16337
- var automationConfigSchema = import_zod20.z.record(import_zod20.z.string(), import_zod20.z.unknown());
16536
+ var automationConfigSchema = import_zod21.z.record(import_zod21.z.string(), import_zod21.z.unknown());
16338
16537
  var AGENT_SELECTION = `{
16339
16538
  id
16340
16539
  type
@@ -16490,7 +16689,7 @@ var AUTOMATION_RUN_STATUS_SELECTION = `{
16490
16689
  queuedAt
16491
16690
  completedAt
16492
16691
  }`;
16493
- function asRecord7(value) {
16692
+ function asRecord6(value) {
16494
16693
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
16495
16694
  }
16496
16695
  function asRequiredString(value) {
@@ -16521,7 +16720,7 @@ function requirePaginationInteger(value, key, minimum) {
16521
16720
  });
16522
16721
  }
16523
16722
  function normalizeAutomationList(payload) {
16524
- const page = asRecord7(payload);
16723
+ const page = asRecord6(payload);
16525
16724
  if (!page || !Array.isArray(page.data)) {
16526
16725
  throw new CliError({
16527
16726
  message: "Automation list response did not include a paginated data collection.",
@@ -16532,8 +16731,8 @@ function normalizeAutomationList(payload) {
16532
16731
  }
16533
16732
  const rows = page.data;
16534
16733
  const data = rows.map((value) => {
16535
- const row = asRecord7(value);
16536
- const attributes = asRecord7(row?.attributes);
16734
+ const row = asRecord6(value);
16735
+ const attributes = asRecord6(row?.attributes);
16537
16736
  if (!row || !attributes) {
16538
16737
  throw new CliError({
16539
16738
  message: "Automation list response included a malformed automation record.",
@@ -16618,13 +16817,13 @@ function parseJsonOption(value, optionName, schema) {
16618
16817
  return schema.parse(parseJson(String(value), optionName));
16619
16818
  }
16620
16819
  function normalizePersistedCreatePayload(payload) {
16621
- const mutation = asRecord7(payload);
16622
- const mutationData = asRecord7(mutation?.data);
16623
- const persisted = asRecord7(mutationData?.data) ?? mutationData;
16624
- const attributes = asRecord7(persisted?.attributes);
16625
- const automationExecution = asRecord7(attributes?.automation_execution) ?? asRecord7(attributes?.automationExecution);
16626
- const meta = asRecord7(mutationData?.meta);
16627
- const idempotency = asRecord7(meta?.atlas_idempotency);
16820
+ const mutation = asRecord6(payload);
16821
+ const mutationData = asRecord6(mutation?.data);
16822
+ const persisted = asRecord6(mutationData?.data) ?? mutationData;
16823
+ const attributes = asRecord6(persisted?.attributes);
16824
+ const automationExecution = asRecord6(attributes?.automation_execution) ?? asRecord6(attributes?.automationExecution);
16825
+ const meta = asRecord6(mutationData?.meta);
16826
+ const idempotency = asRecord6(meta?.atlas_idempotency);
16628
16827
  const id = asRequiredString(persisted?.id);
16629
16828
  const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
16630
16829
  const replay = idempotency?.replay;
@@ -16655,10 +16854,10 @@ function normalizePersistedCreatePayload(payload) {
16655
16854
  };
16656
16855
  }
16657
16856
  function normalizePersistedUpdatePayload(payload) {
16658
- const mutation = asRecord7(payload);
16659
- const mutationData = asRecord7(mutation?.data);
16660
- const persisted = asRecord7(mutationData?.data) ?? mutationData;
16661
- const attributes = asRecord7(persisted?.attributes);
16857
+ const mutation = asRecord6(payload);
16858
+ const mutationData = asRecord6(mutation?.data);
16859
+ const persisted = asRecord6(mutationData?.data) ?? mutationData;
16860
+ const attributes = asRecord6(persisted?.attributes);
16662
16861
  const id = asRequiredString(persisted?.id);
16663
16862
  const slug = asRequiredString(persisted?.slug) ?? asRequiredString(attributes?.slug);
16664
16863
  const updateVersion = asRequiredString(persisted?.updateVersion) ?? asRequiredString(attributes?.updateVersion) ?? asRequiredString(attributes?.update_version);
@@ -16679,7 +16878,7 @@ function normalizePersistedUpdatePayload(payload) {
16679
16878
  };
16680
16879
  }
16681
16880
  function normalizeAutomationRunPayload(payload) {
16682
- const mutation = asRecord7(payload);
16881
+ const mutation = asRecord6(payload);
16683
16882
  if (!mutation) {
16684
16883
  throw new CliError({
16685
16884
  message: "Automation run response did not include a mutation payload.",
@@ -16697,7 +16896,7 @@ function normalizeAutomationRunPayload(payload) {
16697
16896
  data: mutation.data ?? null
16698
16897
  };
16699
16898
  }
16700
- const data = asRecord7(mutation.data);
16899
+ const data = asRecord6(mutation.data);
16701
16900
  const automationTaskId = asRequiredString(data?.automation_task_id);
16702
16901
  const automationTaskSlug = asRequiredString(data?.automation_task_slug);
16703
16902
  const agentId = asRequiredString(data?.agent_id);
@@ -17012,7 +17211,7 @@ function registerAtlasAuthoringCommands(program) {
17012
17211
  "--service <service>",
17013
17212
  "Supported service: gmail, calendar, slack, or stripe"
17014
17213
  ).action(async (opts, cmd) => {
17015
- const service = import_zod20.z.enum(["gmail", "calendar", "slack", "stripe"]).parse(opts.service);
17214
+ const service = import_zod21.z.enum(["gmail", "calendar", "slack", "stripe"]).parse(opts.service);
17016
17215
  const context = await resolveCommandContext(cmd.optsWithGlobals());
17017
17216
  const organizationId = resolveOrganizationId(context.organizationId);
17018
17217
  await runGraphqlQueryCommand({
@@ -17297,6 +17496,15 @@ var VARIABLE_TYPES = {
17297
17496
  organization_id: "ID!",
17298
17497
  member_id: "ID"
17299
17498
  };
17499
+ var ACTIVITY_VARIABLE_TYPES = {
17500
+ ...VARIABLE_TYPES,
17501
+ start_at: "ISO8601DateTime!",
17502
+ end_at: "ISO8601DateTime!"
17503
+ };
17504
+ var MEMBER_STATUSES_VARIABLE_TYPES = {
17505
+ organization_id: "ID!",
17506
+ member_ids: "[ID!]!"
17507
+ };
17300
17508
  function parseRecentLimit(value) {
17301
17509
  const limit = Number(value);
17302
17510
  if (!Number.isInteger(limit) || limit < 1 || limit > 50) {
@@ -17304,6 +17512,25 @@ function parseRecentLimit(value) {
17304
17512
  }
17305
17513
  return limit;
17306
17514
  }
17515
+ function parseIsoDateTime(optionName, value) {
17516
+ const timestamp = Date.parse(value);
17517
+ if (!Number.isFinite(timestamp) || !value.includes("T")) {
17518
+ throw new Error(`${optionName} must be an ISO 8601 date-time`);
17519
+ }
17520
+ return value;
17521
+ }
17522
+ function validateActivityRange(startAt, endAt) {
17523
+ if (Date.parse(endAt) <= Date.parse(startAt)) {
17524
+ throw new Error("end-at must be after start-at");
17525
+ }
17526
+ }
17527
+ function parseMemberIds(value) {
17528
+ const memberIds = [...new Set(value.split(",").map((id) => id.trim()).filter(Boolean))];
17529
+ if (memberIds.length < 1 || memberIds.length > 100) {
17530
+ throw new Error("member-ids must contain between 1 and 100 unique member IDs");
17531
+ }
17532
+ return memberIds;
17533
+ }
17307
17534
  async function runDesktopContextQuery(cmd, params) {
17308
17535
  const context = await resolveCommandContext(cmd.optsWithGlobals());
17309
17536
  await runGraphqlQueryCommand({
@@ -17314,9 +17541,12 @@ async function runDesktopContextQuery(cmd, params) {
17314
17541
  variables: normalizeGraphqlVariables2({
17315
17542
  organization_id: resolveOrganizationId(context.organizationId),
17316
17543
  member_id: params.memberId,
17317
- limit: params.limit
17544
+ member_ids: params.memberIds,
17545
+ limit: params.limit,
17546
+ start_at: params.startAt,
17547
+ end_at: params.endAt
17318
17548
  }),
17319
- variableTypes: {
17549
+ variableTypes: params.command === "desktop-context.activity" ? ACTIVITY_VARIABLE_TYPES : params.command === "desktop-context.member-statuses" ? MEMBER_STATUSES_VARIABLE_TYPES : {
17320
17550
  ...VARIABLE_TYPES,
17321
17551
  ...params.command === "desktop-context.recent" ? { limit: "Int" } : {}
17322
17552
  },
@@ -17334,6 +17564,18 @@ function registerDesktopContextCommands(program) {
17334
17564
  memberId: opts.memberId
17335
17565
  });
17336
17566
  });
17567
+ desktopContext.command("member-statuses").description("Read capture and enrollment status for up to 100 organization members").requiredOption(
17568
+ "--member-ids <memberIds>",
17569
+ "Comma-separated organization member IDs (1-100)",
17570
+ parseMemberIds
17571
+ ).action(async (opts, cmd) => {
17572
+ await runDesktopContextQuery(cmd, {
17573
+ command: "desktop-context.member-statuses",
17574
+ operationName: "DesktopContextMemberStatuses",
17575
+ field: "desktop_context_member_statuses",
17576
+ memberIds: opts.memberIds
17577
+ });
17578
+ });
17337
17579
  desktopContext.command("recent").description("Read recent sanitized evidence excerpts").option("--member-id <memberId>", "Member scope; defaults to the authenticated member").option("--limit <limit>", "Maximum observations (1-50)", parseRecentLimit).action(async (opts, cmd) => {
17338
17580
  await runDesktopContextQuery(cmd, {
17339
17581
  command: "desktop-context.recent",
@@ -17343,6 +17585,380 @@ function registerDesktopContextCommands(program) {
17343
17585
  limit: opts.limit
17344
17586
  });
17345
17587
  });
17588
+ desktopContext.command("activity").description("Read canonical active, AFK, gap, and app duration for a bounded range").requiredOption(
17589
+ "--start-at <dateTime>",
17590
+ "Inclusive ISO 8601 range start",
17591
+ (value) => parseIsoDateTime("start-at", value)
17592
+ ).requiredOption(
17593
+ "--end-at <dateTime>",
17594
+ "Exclusive ISO 8601 range end",
17595
+ (value) => parseIsoDateTime("end-at", value)
17596
+ ).option("--member-id <memberId>", "Member scope; defaults to the authenticated member").action(async (opts, cmd) => {
17597
+ validateActivityRange(opts.startAt, opts.endAt);
17598
+ await runDesktopContextQuery(cmd, {
17599
+ command: "desktop-context.activity",
17600
+ operationName: "DesktopContextActivity",
17601
+ field: "desktop_context_activity_summary",
17602
+ memberId: opts.memberId,
17603
+ startAt: opts.startAt,
17604
+ endAt: opts.endAt
17605
+ });
17606
+ });
17607
+ }
17608
+
17609
+ // src/commands/dataPipeline.ts
17610
+ var MAX_PARAMETERS_JSON_BYTES = 16384;
17611
+ var SECRET_LIKE_PARAMETER_KEY = /(?:^|_)(?:api_?key|authorization|credential|password|secret|token)(?:$|_)/i;
17612
+ var UNSAFE_PARAMETER_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
17613
+ var ORGANIZATION_VARIABLE_TYPES = {
17614
+ organization_id: "ID!"
17615
+ };
17616
+ var SOURCES_VARIABLE_TYPES = {
17617
+ ...ORGANIZATION_VARIABLE_TYPES,
17618
+ category_key: "String!"
17619
+ };
17620
+ var SOURCE_ACTIONS_VARIABLE_TYPES = {
17621
+ ...ORGANIZATION_VARIABLE_TYPES,
17622
+ source_id: "ID!"
17623
+ };
17624
+ var EXECUTE_SOURCE_ACTION_VARIABLE_TYPES = {
17625
+ ...SOURCE_ACTIONS_VARIABLE_TYPES,
17626
+ category_key: "String!",
17627
+ provider_key: "String!",
17628
+ action_key: "String!",
17629
+ parameters: "JSON"
17630
+ };
17631
+ var PROVIDER_SELECTION = `
17632
+ organizationPluginId
17633
+ key
17634
+ name
17635
+ categories
17636
+ availability
17637
+ integrationKey
17638
+ connectorProvider
17639
+ connectorService
17640
+ logoAssetPath
17641
+ `.trim();
17642
+ var OVERVIEW_SELECTION = `
17643
+ {
17644
+ totalSourceCount
17645
+ connectedSourceCount
17646
+ categoriesConfiguredCount
17647
+ actionRequiredCount
17648
+ categories {
17649
+ key
17650
+ name
17651
+ description
17652
+ iconKey
17653
+ sortOrder
17654
+ allowedSourceTypes
17655
+ suggestedSourceLabels
17656
+ sourceCount
17657
+ activeSourceCount
17658
+ attentionSourceCount
17659
+ status
17660
+ providers {
17661
+ ${PROVIDER_SELECTION}
17662
+ }
17663
+ }
17664
+ }
17665
+ `.trim();
17666
+ var SOURCE_SELECTION = `
17667
+ {
17668
+ id
17669
+ type
17670
+ organizationId
17671
+ categoryKey
17672
+ sourceType
17673
+ providerKey
17674
+ organizationPluginId
17675
+ name
17676
+ url
17677
+ status
17678
+ connection
17679
+ configuration
17680
+ metadata
17681
+ lastSyncedAt
17682
+ lastSuccessfulSyncAt
17683
+ lastErrorAt
17684
+ lastErrorMessage
17685
+ createdById
17686
+ createdAt
17687
+ updatedAt
17688
+ }
17689
+ `.trim();
17690
+ var SOURCE_ACTION_SELECTION = `
17691
+ {
17692
+ key
17693
+ displayName
17694
+ inputSchema
17695
+ safetyClass
17696
+ requiresApproval
17697
+ }
17698
+ `.trim();
17699
+ var SOURCE_ACTION_RESULT_SELECTION = `
17700
+ {
17701
+ ok
17702
+ status
17703
+ errorCode
17704
+ errors
17705
+ traceId
17706
+ organizationId
17707
+ categoryKey
17708
+ providerKey
17709
+ sourceId
17710
+ actionKey
17711
+ records
17712
+ pageInfo
17713
+ metadata
17714
+ }
17715
+ `.trim();
17716
+ function invalidParameters(message, details = {}) {
17717
+ return new CliError({
17718
+ message,
17719
+ kind: "invalid_args",
17720
+ status: 400,
17721
+ exitCode: EXIT_CODES.invalidArgs,
17722
+ details
17723
+ });
17724
+ }
17725
+ function parseNonBlank(value, optionName) {
17726
+ const parsed = value.trim();
17727
+ if (!parsed) {
17728
+ throw invalidParameters(`${optionName} must not be blank`);
17729
+ }
17730
+ return parsed;
17731
+ }
17732
+ function parseCategoryKey(value) {
17733
+ return parseNonBlank(value, "category-key");
17734
+ }
17735
+ function secretLikeParameterPath(value, path = []) {
17736
+ if (!value || typeof value !== "object") return null;
17737
+ if (Array.isArray(value)) {
17738
+ for (let index = 0; index < value.length; index += 1) {
17739
+ const nestedPath = secretLikeParameterPath(value[index], [...path, String(index)]);
17740
+ if (nestedPath) return nestedPath;
17741
+ }
17742
+ return null;
17743
+ }
17744
+ for (const [key, nestedValue] of Object.entries(value)) {
17745
+ const keyPath = [...path, key];
17746
+ if (UNSAFE_PARAMETER_KEYS.has(key) || SECRET_LIKE_PARAMETER_KEY.test(key)) {
17747
+ return keyPath.join(".");
17748
+ }
17749
+ const nestedPath = secretLikeParameterPath(nestedValue, keyPath);
17750
+ if (nestedPath) return nestedPath;
17751
+ }
17752
+ return null;
17753
+ }
17754
+ function parseSourceActionParameters(raw) {
17755
+ if (Buffer.byteLength(raw, "utf8") > MAX_PARAMETERS_JSON_BYTES) {
17756
+ throw invalidParameters(
17757
+ `parameters-json must not exceed ${MAX_PARAMETERS_JSON_BYTES} bytes`
17758
+ );
17759
+ }
17760
+ let parsed;
17761
+ try {
17762
+ parsed = JSON.parse(raw);
17763
+ } catch {
17764
+ throw invalidParameters("parameters-json must be a valid JSON object");
17765
+ }
17766
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
17767
+ throw invalidParameters("parameters-json must be a JSON object");
17768
+ }
17769
+ const secretPath = secretLikeParameterPath(parsed);
17770
+ if (secretPath) {
17771
+ throw invalidParameters(
17772
+ `parameters-json contains a secret-like parameter key: ${secretPath}`,
17773
+ { parameterPath: secretPath }
17774
+ );
17775
+ }
17776
+ return parsed;
17777
+ }
17778
+ function isJsonRecord(value) {
17779
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
17780
+ }
17781
+ function sourceActionFailureKind(errorCode, status) {
17782
+ if (errorCode === "AUTH_REQUIRED" || errorCode === "UNAUTHORIZED") return "missing_auth";
17783
+ if (errorCode === "NOT_FOUND") return "not_found";
17784
+ if (errorCode === "PROVIDER_ERROR") return "upstream_error";
17785
+ if (errorCode === "ACTION_NOT_ALLOWED") return "forbidden";
17786
+ if (errorCode === "INVALID_INPUT" || errorCode === "INVALID_SOURCE") {
17787
+ return "validation";
17788
+ }
17789
+ if (status === 403) return "forbidden";
17790
+ if (status === 404) return "not_found";
17791
+ if (status >= 500) return "upstream_error";
17792
+ if (status === 400 || status === 422) return "validation";
17793
+ return "generic_error";
17794
+ }
17795
+ function sourceActionFailureExitCode(kind, status) {
17796
+ if (kind === "missing_auth") return EXIT_CODES.missingOrInvalidAuth;
17797
+ if (kind === "forbidden") return EXIT_CODES.forbidden;
17798
+ if (kind === "not_found") return EXIT_CODES.notFound;
17799
+ if (kind === "validation") return EXIT_CODES.validationFailure;
17800
+ if (kind === "upstream_error" || kind === "malformed_response") {
17801
+ return EXIT_CODES.networkOrUpstream;
17802
+ }
17803
+ return mapStatusToExitCode(status);
17804
+ }
17805
+ function transformSourceActionResult(value) {
17806
+ if (!isJsonRecord(value) || typeof value.ok !== "boolean") {
17807
+ throw new CliError({
17808
+ message: "Data Pipeline source action returned a malformed response",
17809
+ kind: "malformed_response",
17810
+ status: 502,
17811
+ exitCode: EXIT_CODES.networkOrUpstream
17812
+ });
17813
+ }
17814
+ if (value.ok) return value;
17815
+ const status = typeof value.status === "number" && Number.isInteger(value.status) ? value.status : 500;
17816
+ const errorCode = typeof value.errorCode === "string" && value.errorCode.length > 0 ? value.errorCode.toUpperCase() : "SOURCE_ACTION_FAILED";
17817
+ const errors = Array.isArray(value.errors) ? value.errors.filter((error) => typeof error === "string") : [];
17818
+ const traceId = typeof value.traceId === "string" ? value.traceId : null;
17819
+ const kind = sourceActionFailureKind(errorCode, status);
17820
+ throw new CliError({
17821
+ message: errors.find((error) => error.trim().length > 0) ?? "Data Pipeline source action failed",
17822
+ kind,
17823
+ status,
17824
+ exitCode: sourceActionFailureExitCode(kind, status),
17825
+ details: { errorCode, traceId, errors }
17826
+ });
17827
+ }
17828
+ function transformSourceActions(value) {
17829
+ if (!Array.isArray(value)) {
17830
+ throw new CliError({
17831
+ message: "Data Pipeline source action discovery returned a malformed response",
17832
+ kind: "malformed_response",
17833
+ status: 502,
17834
+ exitCode: EXIT_CODES.networkOrUpstream
17835
+ });
17836
+ }
17837
+ for (const action of value) {
17838
+ if (!isJsonRecord(action) || typeof action.key !== "string") {
17839
+ throw new CliError({
17840
+ message: "Data Pipeline source action discovery returned a malformed action",
17841
+ kind: "malformed_response",
17842
+ status: 502,
17843
+ exitCode: EXIT_CODES.networkOrUpstream
17844
+ });
17845
+ }
17846
+ if (action.safetyClass !== "read_only" || action.requiresApproval !== false) {
17847
+ throw new CliError({
17848
+ message: `Data Pipeline source action discovery returned a non-read-only action: ${action.key}`,
17849
+ kind: "malformed_response",
17850
+ status: 502,
17851
+ exitCode: EXIT_CODES.networkOrUpstream,
17852
+ details: {
17853
+ actionKey: action.key,
17854
+ safetyClass: action.safetyClass,
17855
+ requiresApproval: action.requiresApproval
17856
+ }
17857
+ });
17858
+ }
17859
+ }
17860
+ return value;
17861
+ }
17862
+ function registerDataPipelineCommands(program) {
17863
+ const dataPipeline = program.command("data-pipeline").description("Inspect the organization's configured Data Pipeline control plane");
17864
+ dataPipeline.command("overview").description("Read source counts, category status, and available organization plugins").action(async (_opts, cmd) => {
17865
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
17866
+ await runGraphqlQueryCommand({
17867
+ command: "data-pipeline.overview",
17868
+ operationName: "DataPipelineOverview",
17869
+ runtimeOptions: context.runtimeOptions,
17870
+ field: "data_pipeline_overview",
17871
+ variables: {
17872
+ organization_id: resolveOrganizationId(context.organizationId)
17873
+ },
17874
+ variableTypes: ORGANIZATION_VARIABLE_TYPES,
17875
+ isShow: true,
17876
+ selectionSet: OVERVIEW_SELECTION
17877
+ });
17878
+ });
17879
+ dataPipeline.command("sources").description("Read the saved source records configured for one Data Pipeline category").requiredOption(
17880
+ "--category-key <categoryKey>",
17881
+ "Data Pipeline category key from the overview response",
17882
+ parseCategoryKey
17883
+ ).action(async (opts, cmd) => {
17884
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
17885
+ await runGraphqlQueryCommand({
17886
+ command: "data-pipeline.sources",
17887
+ operationName: "DataPipelineSources",
17888
+ runtimeOptions: context.runtimeOptions,
17889
+ field: "data_pipeline_sources",
17890
+ variables: {
17891
+ organization_id: resolveOrganizationId(context.organizationId),
17892
+ category_key: opts.categoryKey
17893
+ },
17894
+ variableTypes: SOURCES_VARIABLE_TYPES,
17895
+ isList: true,
17896
+ selectionSet: SOURCE_SELECTION
17897
+ });
17898
+ });
17899
+ dataPipeline.command("source-actions").description("Read the certified provider actions available for one configured source").requiredOption(
17900
+ "--source-id <sourceId>",
17901
+ "Configured Data Pipeline source ID",
17902
+ (value) => parseNonBlank(value, "source-id")
17903
+ ).action(async (opts, cmd) => {
17904
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
17905
+ await runGraphqlQueryCommand({
17906
+ command: "data-pipeline.source-actions",
17907
+ operationName: "DataPipelineSourceActions",
17908
+ runtimeOptions: context.runtimeOptions,
17909
+ field: "data_pipeline_source_actions",
17910
+ variables: {
17911
+ organization_id: resolveOrganizationId(context.organizationId),
17912
+ source_id: opts.sourceId
17913
+ },
17914
+ variableTypes: SOURCE_ACTIONS_VARIABLE_TYPES,
17915
+ isList: true,
17916
+ transformData: transformSourceActions,
17917
+ selectionSet: SOURCE_ACTION_SELECTION
17918
+ });
17919
+ });
17920
+ dataPipeline.command("execute-source-action").description("Execute one backend-certified read-only action for a configured source").requiredOption(
17921
+ "--category-key <categoryKey>",
17922
+ "Data Pipeline category key",
17923
+ parseCategoryKey
17924
+ ).requiredOption(
17925
+ "--provider-key <providerKey>",
17926
+ "Provider key from the configured source",
17927
+ (value) => parseNonBlank(value, "provider-key")
17928
+ ).requiredOption(
17929
+ "--source-id <sourceId>",
17930
+ "Configured Data Pipeline source ID",
17931
+ (value) => parseNonBlank(value, "source-id")
17932
+ ).requiredOption(
17933
+ "--action-key <actionKey>",
17934
+ "Action key returned by source-actions",
17935
+ (value) => parseNonBlank(value, "action-key")
17936
+ ).option(
17937
+ "--parameters-json <parametersJson>",
17938
+ "Bounded JSON object matching the discovered action input schema",
17939
+ parseSourceActionParameters,
17940
+ {}
17941
+ ).action(async (opts, cmd) => {
17942
+ const context = await resolveCommandContext(cmd.optsWithGlobals());
17943
+ await runGraphqlQueryCommand({
17944
+ command: "data-pipeline.execute-source-action",
17945
+ operationName: "DataPipelineExecuteSourceAction",
17946
+ runtimeOptions: context.runtimeOptions,
17947
+ field: "data_pipeline_execute_source_action",
17948
+ variables: {
17949
+ organization_id: resolveOrganizationId(context.organizationId),
17950
+ category_key: opts.categoryKey,
17951
+ provider_key: opts.providerKey,
17952
+ source_id: opts.sourceId,
17953
+ action_key: opts.actionKey,
17954
+ parameters: opts.parametersJson
17955
+ },
17956
+ variableTypes: EXECUTE_SOURCE_ACTION_VARIABLE_TYPES,
17957
+ isShow: true,
17958
+ transformData: transformSourceActionResult,
17959
+ selectionSet: SOURCE_ACTION_RESULT_SELECTION
17960
+ });
17961
+ });
17346
17962
  }
17347
17963
 
17348
17964
  // src/commands/discovery.ts
@@ -17354,10 +17970,12 @@ var PRIMARY_NAMESPACES = [
17354
17970
  "support",
17355
17971
  "recognition",
17356
17972
  "whiteboards",
17973
+ "sketches",
17357
17974
  "time-tracking",
17358
17975
  "planner",
17359
17976
  "mail",
17360
17977
  "datasheets",
17978
+ "data-pipeline",
17361
17979
  "desktop-context",
17362
17980
  "phantom",
17363
17981
  "tasks",
@@ -17384,9 +18002,7 @@ var ADVANCED_NAMESPACES = [
17384
18002
  "stand-ups",
17385
18003
  "news",
17386
18004
  "questions",
17387
- "pulse",
17388
18005
  "surveys",
17389
- "feedbacks",
17390
18006
  "accountability",
17391
18007
  "kpis",
17392
18008
  "scorecard-groups",
@@ -17446,7 +18062,9 @@ var NAMESPACE_DOCS = {
17446
18062
  description: "Sanitized desktop capture health and recent evidence for Atlas grounding.",
17447
18063
  examples: [
17448
18064
  "wave desktop-context status",
18065
+ "wave desktop-context member-statuses --member-ids 123,456",
17449
18066
  "wave desktop-context recent --limit 20",
18067
+ "wave desktop-context activity --start-at 2026-08-18T08:00:00Z --end-at 2026-08-18T09:00:00Z",
17450
18068
  "wave desktop-context status --member-id 123"
17451
18069
  ],
17452
18070
  schema: {
@@ -17457,7 +18075,28 @@ var NAMESPACE_DOCS = {
17457
18075
  "Does not expose screenshots, raw audio, accessibility trees, clipboard contents, keystrokes, URLs, or filesystem paths.",
17458
18076
  "Cross-member reads remain subject to backend organization policy and every response carries backend trace correlation when available."
17459
18077
  ],
17460
- commands: ["status", "recent"]
18078
+ commands: ["status", "member-statuses", "recent", "activity"]
18079
+ }
18080
+ },
18081
+ "data-pipeline": {
18082
+ name: "data-pipeline",
18083
+ tier: "primary",
18084
+ description: "Organization Data Pipeline configuration, saved sources, and certified provider reads.",
18085
+ examples: [
18086
+ "wave data-pipeline overview",
18087
+ "wave data-pipeline sources --category-key communication_meetings",
18088
+ "wave data-pipeline source-actions --source-id 123",
18089
+ `wave data-pipeline execute-source-action --category-key marketing_analytics --provider-key posthog --source-id 123 --action-key posthog.list_dashboards --parameters-json '{"limit":10,"offset":0}'`
18090
+ ],
18091
+ schema: {
18092
+ output: "json-envelope-default",
18093
+ readOnly: true,
18094
+ safety: [
18095
+ "Reads organization-scoped Data Pipeline configuration and backend-certified provider records only.",
18096
+ "Provider actions are discovered from the backend and remain read-only and approval-free.",
18097
+ "Does not install, enable, disable, or uninstall plugins; manage credentials; or create, update, or delete sources."
18098
+ ],
18099
+ commands: ["overview", "sources", "source-actions", "execute-source-action"]
17461
18100
  }
17462
18101
  },
17463
18102
  phantom: {
@@ -17677,6 +18316,28 @@ var NAMESPACE_DOCS = {
17677
18316
  commands: ["open", "list", "show"]
17678
18317
  }
17679
18318
  },
18319
+ sketches: {
18320
+ name: "sketches",
18321
+ tier: "primary",
18322
+ description: "Sketch metadata, bounded create/update operations, and verified app-route metadata.",
18323
+ examples: [
18324
+ "wave sketches list --page 1 --per 20",
18325
+ "wave sketches show --slug SKT-02",
18326
+ `wave sketches create --data-json '{"name":"Design review","teams_ids":["team-1"],"creation_key":"design-review-1"}'`,
18327
+ `wave sketches update-metadata --id 123 --data-json '{"name":"Design review"}'`,
18328
+ "wave sketches open"
18329
+ ],
18330
+ schema: {
18331
+ output: "json-envelope-default",
18332
+ mutates: true,
18333
+ safety: [
18334
+ "Uses verified GraphQL fields sketches, sketch, createSketch, and updateSketch.",
18335
+ "Create requires a team and an idempotency creation key; update accepts only bounded metadata fields.",
18336
+ "Never accepts or emits native document bytes, collaboration updates, render/export data, embedded files, comments, or tokens."
18337
+ ],
18338
+ commands: ["open", "list", "show", "create", "update-metadata"]
18339
+ }
18340
+ },
17680
18341
  "time-tracking": {
17681
18342
  name: "time-tracking",
17682
18343
  tier: "primary",
@@ -17737,9 +18398,10 @@ var NAMESPACE_DOCS = {
17737
18398
  mail: {
17738
18399
  name: "mail",
17739
18400
  tier: "primary",
17740
- description: "Mail read-only metadata for workspace, accounts, messages, conversations, labels, snippets, settings, sync status, and verified app route metadata.",
18401
+ description: "Mail read-only metadata for workspace, explicitly authorized relay evidence, accounts, messages, conversations, labels, snippets, settings, sync status, and verified app route metadata.",
17741
18402
  examples: [
17742
18403
  "wave mail workspace --page 1 --per 20",
18404
+ "wave mail relay-evidence --account-id 123 --page 1 --per 20",
17743
18405
  "wave mail accounts",
17744
18406
  "wave mail messages --account-id 123 --view inbox --page 1 --per 20",
17745
18407
  "wave mail conversations --account-id 123 --view inbox --page 1 --per 20",
@@ -17761,7 +18423,8 @@ var NAMESPACE_DOCS = {
17761
18423
  "Microsoft Outlook Mail maps to service outlook_mail and Outlook Calendar maps to service outlook_calendar with custom OAuth provider wave-microsoft-outlook.",
17762
18424
  "Uses the verified WAVE-03 safe app route /mail.",
17763
18425
  "Account output is limited to ids, provider/service, status, connection state, sync status, and timestamps.",
17764
- "Message and conversation output omits bodies, subjects, snippets, contacts, attachments, provider payloads, provider ids, raw thread ids, and user-authored mail content.",
18426
+ "Default message and conversation output omits bodies, subjects, snippets, contacts, attachments, provider payloads, provider ids, raw thread ids, and user-authored mail content.",
18427
+ "relay-evidence is an explicit authenticated relay surface limited to mailbox identity plus sender, subject, date, and snippet metadata; it still omits bodies, recipients, attachments, provider ids, and token material.",
17765
18428
  "Label, snippet, settings, and sync-status output omits user label names/colors, snippet title/shortcut/body, signatures, preferences, sync search text, operation reasons, error bodies, and token material.",
17766
18429
  "Does not expose send, reply, reply-all, forward, draft, provider-action, sync/connect/disconnect, mark, archive, trash, star, label/snippet CRUD, export, print, or write commands."
17767
18430
  ],
@@ -17769,6 +18432,7 @@ var NAMESPACE_DOCS = {
17769
18432
  "open",
17770
18433
  "validate-provider",
17771
18434
  "workspace",
18435
+ "relay-evidence",
17772
18436
  "accounts",
17773
18437
  "messages",
17774
18438
  "conversations",
@@ -18365,7 +19029,11 @@ function buildCli(options) {
18365
19029
  "Explicit organization ID override"
18366
19030
  ).option(
18367
19031
  "--config <configPath>",
18368
- "Optional JSON config file (default: WAVE_CONFIG_PATH or ~/.wave/config.json when present)"
19032
+ "Optional JSON config file (default: ~/.wave/config.json when present)"
19033
+ ).addOption(
19034
+ new import_commander2.Option("--auth-home <path>", "Credential storage directory (default: ~/.wave)")
19035
+ ).addOption(
19036
+ new import_commander2.Option("--auth-storage <mode>", "Credential storage mode").choices(["auto", "keychain", "file", "disabled"]).default("auto")
18369
19037
  ).option("--timeout-ms <timeoutMs>", "HTTP timeout in milliseconds").option("--agent-name <agentName>", "Agent name for tracing").option("--agent-run-id <agentRunId>", "Agent run identifier for tracing").option("--request-id <requestId>", "Request identifier").option(
18370
19038
  "--atlas-member-id <memberId>",
18371
19039
  "Atlas ledger member ID (prefer WAVE_ATLAS_MEMBER_ID env var)"
@@ -18397,12 +19065,21 @@ function buildCli(options) {
18397
19065
  "--openapi-version <openapiVersion>",
18398
19066
  "Optional pinned OpenAPI version/hash"
18399
19067
  ).exitOverride();
19068
+ program.hook("preAction", (_thisCommand, actionCommand) => {
19069
+ const runtimeOptions = actionCommand.optsWithGlobals();
19070
+ configureAuthStorage({
19071
+ ...runtimeOptions.authHome ? { home: runtimeOptions.authHome } : {},
19072
+ ...runtimeOptions.config ? { configPath: runtimeOptions.config } : {},
19073
+ ...runtimeOptions.authStorage ? { mode: runtimeOptions.authStorage } : {}
19074
+ });
19075
+ });
18400
19076
  setInternalCliOptions(program, options?.internal);
18401
19077
  registerTaskCommands(program);
18402
19078
  registerProjectCommands(program);
18403
19079
  registerRockCommands(program);
18404
19080
  registerMeetingCommands(program);
18405
19081
  registerMemberCommands(program);
19082
+ registerResourceCommands(program);
18406
19083
  registerSkillCommands(program);
18407
19084
  registerAtlasAuthoringCommands(program);
18408
19085
  registerTeamCommands(program);
@@ -18420,6 +19097,7 @@ function buildCli(options) {
18420
19097
  registerSupportCommands(program);
18421
19098
  registerRecognitionCommands(program);
18422
19099
  registerWhiteboardsCommands(program);
19100
+ registerSketchCommands(program);
18423
19101
  registerTimeTrackingCommands(program);
18424
19102
  registerPlannerCommands(program);
18425
19103
  registerMailCommands(program);
@@ -18427,6 +19105,7 @@ function buildCli(options) {
18427
19105
  registerDatasheetsCommands(program);
18428
19106
  registerSignatureCommands(program);
18429
19107
  registerDesktopContextCommands(program);
19108
+ registerDataPipelineCommands(program);
18430
19109
  registerAuthCommands(program);
18431
19110
  registerDiscoveryCommands(program);
18432
19111
  attachNamespaceDiscovery(program);
@@ -18683,9 +19362,10 @@ function withTrustedMachineAuth(auth, callback) {
18683
19362
  for (const key of Object.keys(process.env)) {
18684
19363
  if (key.startsWith("WAVE_")) delete process.env[key];
18685
19364
  }
18686
- process.env.WAVE_CLI_AUTH_STORAGE = "disabled";
18687
- process.env.WAVE_CLI_HOME = "/dev/null";
18688
- return withMachineRuntimeAuth(auth, callback).finally(() => {
19365
+ return withAuthStorageOptions(
19366
+ { home: "/dev/null", mode: "disabled" },
19367
+ () => withMachineRuntimeAuth(auth, callback)
19368
+ ).finally(() => {
18689
19369
  for (const key of Object.keys(process.env)) {
18690
19370
  if (key.startsWith("WAVE_")) delete process.env[key];
18691
19371
  }
@@ -18892,7 +19572,15 @@ async function maybeRunMachineExecute(argv, program) {
18892
19572
  }
18893
19573
  try {
18894
19574
  await withTrustedMachineAuth(auth, async () => {
18895
- await program.parseAsync([process.execPath, "wave", ...commandArgs(resolved.command, normalizedInput)]);
19575
+ await program.parseAsync([
19576
+ process.execPath,
19577
+ "wave",
19578
+ "--auth-storage",
19579
+ "disabled",
19580
+ "--auth-home",
19581
+ "/dev/null",
19582
+ ...commandArgs(resolved.command, normalizedInput)
19583
+ ]);
18896
19584
  });
18897
19585
  } catch (error) {
18898
19586
  if (isEnvelopeEmittedSignal(error)) return true;
@@ -18953,13 +19641,13 @@ main().catch((error) => {
18953
19641
  });
18954
19642
  return;
18955
19643
  }
18956
- if (error instanceof import_zod21.ZodError || error instanceof import_commander3.InvalidArgumentError) {
19644
+ if (error instanceof import_zod22.ZodError || error instanceof import_commander3.InvalidArgumentError) {
18957
19645
  printCliFailure({
18958
19646
  status: 400,
18959
19647
  code: "invalid_args",
18960
19648
  message: "Invalid command arguments.",
18961
19649
  details: {
18962
- issues: error instanceof import_zod21.ZodError ? error.issues : [{ message: error.message, code: "invalid_argument" }]
19650
+ issues: error instanceof import_zod22.ZodError ? error.issues : [{ message: error.message, code: "invalid_argument" }]
18963
19651
  },
18964
19652
  exitCode: EXIT_CODES.invalidArgs
18965
19653
  });