@ted-galago/wave-cli 0.1.5 → 0.1.7
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/README.md +166 -2
- package/dist/index.cjs +3290 -319
- package/dist/index.js +3288 -317
- package/package.json +2 -1
- package/scripts/benchmark-cli.mjs +626 -0
- package/scripts/verify-dev-api.mjs +417 -27
|
@@ -47,17 +47,39 @@ function firstId(parsed, field) {
|
|
|
47
47
|
return undefined;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
function firstListRow(parsed, fields) {
|
|
51
|
+
for (const field of fields) {
|
|
52
|
+
const row = parsed?.data?.[field]?.data?.[0];
|
|
53
|
+
if (row && typeof row === "object") {
|
|
54
|
+
return row;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
function classify(result) {
|
|
51
61
|
if (!result.parsed) {
|
|
52
62
|
return { ok: false, reason: "non_json_output" };
|
|
53
63
|
}
|
|
64
|
+
const embeddedError = findFirstEmbeddedErrors(result.parsed);
|
|
54
65
|
if (result.parsed.ok === true) {
|
|
66
|
+
if (embeddedError) {
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
reason: "embedded_errors",
|
|
70
|
+
details: { path: embeddedError.path, sample: embeddedError.sample }
|
|
71
|
+
};
|
|
72
|
+
}
|
|
55
73
|
return { ok: true, reason: "ok" };
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
const code = result.parsed?.error?.code ?? "unknown";
|
|
59
77
|
const message = result.parsed?.error?.message ?? "";
|
|
60
78
|
const details = JSON.stringify(result.parsed?.error?.details ?? {});
|
|
79
|
+
const output = `${result.stdout}\n${result.stderr}`;
|
|
80
|
+
if (/unpermitted parameter/i.test(output) || /unpermitted parameter/i.test(details)) {
|
|
81
|
+
return { ok: false, reason: "unpermitted_parameter" };
|
|
82
|
+
}
|
|
61
83
|
const hardFailures = [
|
|
62
84
|
"network_error",
|
|
63
85
|
"missing_auth",
|
|
@@ -83,10 +105,124 @@ function classify(result) {
|
|
|
83
105
|
return { ok: true, reason: `reachable_${code}` };
|
|
84
106
|
}
|
|
85
107
|
|
|
108
|
+
function isNonEmptyErrorsValue(value) {
|
|
109
|
+
if (value === null || value === undefined) return false;
|
|
110
|
+
if (Array.isArray(value)) {
|
|
111
|
+
if (value.length === 0) return false;
|
|
112
|
+
return value.some((entry) => {
|
|
113
|
+
if (entry === null || entry === undefined) return false;
|
|
114
|
+
if (typeof entry === "string") return entry.trim().length > 0;
|
|
115
|
+
if (typeof entry === "object") return Object.keys(entry).length > 0;
|
|
116
|
+
return true;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (typeof value === "string") return value.trim().length > 0;
|
|
120
|
+
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function summarizeValue(value) {
|
|
125
|
+
try {
|
|
126
|
+
if (typeof value === "string") return value.slice(0, 160);
|
|
127
|
+
const serialized = JSON.stringify(value);
|
|
128
|
+
if (typeof serialized !== "string") return String(value);
|
|
129
|
+
return serialized.slice(0, 300);
|
|
130
|
+
} catch {
|
|
131
|
+
return String(value);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function findFirstEmbeddedErrors(input) {
|
|
136
|
+
const queue = [{ value: input, path: "$", depth: 0 }];
|
|
137
|
+
const maxDepth = 12;
|
|
138
|
+
const maxNodes = 2000;
|
|
139
|
+
let visited = 0;
|
|
140
|
+
|
|
141
|
+
while (queue.length > 0) {
|
|
142
|
+
const current = queue.shift();
|
|
143
|
+
if (!current) break;
|
|
144
|
+
visited += 1;
|
|
145
|
+
if (visited > maxNodes) break;
|
|
146
|
+
|
|
147
|
+
const { value, path, depth } = current;
|
|
148
|
+
if (!value || typeof value !== "object") continue;
|
|
149
|
+
|
|
150
|
+
if (Array.isArray(value)) {
|
|
151
|
+
if (depth >= maxDepth) continue;
|
|
152
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
153
|
+
queue.push({ value: value[i], path: `${path}[${i}]`, depth: depth + 1 });
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
159
|
+
const nextPath = `${path}.${key}`;
|
|
160
|
+
if (key === "errors" && isNonEmptyErrorsValue(nested)) {
|
|
161
|
+
return { path: nextPath, sample: summarizeValue(nested) };
|
|
162
|
+
}
|
|
163
|
+
if (depth < maxDepth && nested && typeof nested === "object") {
|
|
164
|
+
queue.push({ value: nested, path: nextPath, depth: depth + 1 });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
86
172
|
function payload(root, attrs) {
|
|
87
173
|
return JSON.stringify({ [root]: attrs });
|
|
88
174
|
}
|
|
89
175
|
|
|
176
|
+
function sleepMs(ms) {
|
|
177
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function extractListIds(parsed, field) {
|
|
181
|
+
const rows = parsed?.data?.[field]?.data;
|
|
182
|
+
if (!Array.isArray(rows)) return [];
|
|
183
|
+
return rows
|
|
184
|
+
.map((row) => (row?.id ? String(row.id) : ""))
|
|
185
|
+
.filter((id) => id.length > 0);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function readPath(input, segments) {
|
|
189
|
+
let current = input;
|
|
190
|
+
for (const segment of segments) {
|
|
191
|
+
if (!current || typeof current !== "object") {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
current = current[segment];
|
|
195
|
+
}
|
|
196
|
+
return current;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function firstDefinedValue(input, paths) {
|
|
200
|
+
for (const path of paths) {
|
|
201
|
+
const value = readPath(input, path);
|
|
202
|
+
if (value !== undefined && value !== null) {
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function verifySubissueDeleteWithPolling(env, issueId, subIssueId) {
|
|
210
|
+
const attempts = [];
|
|
211
|
+
for (let i = 1; i <= 5; i += 1) {
|
|
212
|
+
const listRes = runWave(["subissues", "list", "--issue-id", issueId], env);
|
|
213
|
+
const ids = extractListIds(listRes.parsed, "sub_issues");
|
|
214
|
+
const deleted = !ids.includes(String(subIssueId));
|
|
215
|
+
attempts.push({ index: i, ids, result: listRes });
|
|
216
|
+
if (deleted) {
|
|
217
|
+
return { ok: true, attempts, tries: i };
|
|
218
|
+
}
|
|
219
|
+
if (i < 5) {
|
|
220
|
+
sleepMs(500);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return { ok: false, attempts, tries: 5 };
|
|
224
|
+
}
|
|
225
|
+
|
|
90
226
|
const root = process.cwd();
|
|
91
227
|
const envFile = resolve(root, ".env");
|
|
92
228
|
const dot = loadDotEnv(envFile);
|
|
@@ -138,6 +274,23 @@ for (const [key, args] of listSeeds) {
|
|
|
138
274
|
if (res.parsed?.ok) {
|
|
139
275
|
const field = args[0] === "foundation" ? args[1].replace(/-([a-z])/g, (_, c) => c.toUpperCase()) : args[0].replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
140
276
|
idLookup[key] = firstId(res.parsed, field);
|
|
277
|
+
if (key === "kpis") {
|
|
278
|
+
const firstKpi = firstListRow(res.parsed, ["smart_kpis", "smartKpis", "kpis"]);
|
|
279
|
+
if (firstKpi && typeof firstKpi === "object") {
|
|
280
|
+
const attributes = firstKpi.attributes;
|
|
281
|
+
if (attributes && typeof attributes === "object") {
|
|
282
|
+
const attr = attributes;
|
|
283
|
+
idLookup.kpiSmartKpiViewId =
|
|
284
|
+
typeof attr.smart_kpi_view_id === "string"
|
|
285
|
+
? attr.smart_kpi_view_id
|
|
286
|
+
: typeof attr.smartKpiViewId === "string"
|
|
287
|
+
? attr.smartKpiViewId
|
|
288
|
+
: undefined;
|
|
289
|
+
idLookup.kpiCreateName =
|
|
290
|
+
typeof attr.name === "string" && attr.name.trim().length > 0 ? attr.name : undefined;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
141
294
|
}
|
|
142
295
|
}
|
|
143
296
|
|
|
@@ -164,12 +317,57 @@ const surveyId = idLookup.surveys;
|
|
|
164
317
|
const feedbackId = idLookup.feedbacks;
|
|
165
318
|
const responsibilityId = idLookup.accountability;
|
|
166
319
|
const kpiId = idLookup.kpis;
|
|
320
|
+
const kpiSmartKpiViewId = idLookup.kpiSmartKpiViewId;
|
|
321
|
+
const kpiCreateName = idLookup.kpiCreateName;
|
|
167
322
|
const measurableGroupId = idLookup.scorecardGroups;
|
|
168
323
|
const measurableId = idLookup.scorecards;
|
|
169
324
|
const customerId = idLookup.customers;
|
|
170
325
|
const contactId = idLookup.contacts;
|
|
171
326
|
const annualObjectiveId = idLookup.annualObjectives;
|
|
172
327
|
const quarterlyObjectiveId = idLookup.quarterlyObjectives;
|
|
328
|
+
const verifyStamp = String(Date.now());
|
|
329
|
+
const orgWorkspaceNameVerify = `Wave Verify ${verifyStamp}`;
|
|
330
|
+
const orgMetaOneSentenceSummaryVerify = `Verify Title ${verifyStamp}`;
|
|
331
|
+
const keyMetricRevenueVerify = String(1000 + Number(verifyStamp.slice(-3)));
|
|
332
|
+
const questionNameVerify = `CLI Verify Question Update ${verifyStamp}`;
|
|
333
|
+
const surveyDueDateVerify = "2026-12-31";
|
|
334
|
+
const feedbackQuarterVerify = "q3";
|
|
335
|
+
const accountabilityNameVerify = `CLI Verify Responsibility Update ${verifyStamp}`;
|
|
336
|
+
const organizationMetaProfileSeed = runWave(
|
|
337
|
+
["organizations", "meta-profile", "show", "--id", orgId],
|
|
338
|
+
env
|
|
339
|
+
);
|
|
340
|
+
results.push(organizationMetaProfileSeed);
|
|
341
|
+
const organizationMetaProfileId =
|
|
342
|
+
firstId(organizationMetaProfileSeed.parsed, "organization_meta_profile") ?? orgId;
|
|
343
|
+
const keyMetricMetaProfileSeed = runWave(
|
|
344
|
+
["organizations", "key-metric-meta-profile", "show", "--id", orgId],
|
|
345
|
+
env
|
|
346
|
+
);
|
|
347
|
+
results.push(keyMetricMetaProfileSeed);
|
|
348
|
+
const keyMetricMetaProfileId =
|
|
349
|
+
firstId(keyMetricMetaProfileSeed.parsed, "key_metric_meta_profile") ?? orgId;
|
|
350
|
+
const meetingCreatePayload = teamId
|
|
351
|
+
? {
|
|
352
|
+
name: "CLI Verify Meeting",
|
|
353
|
+
type: "TeamMeeting",
|
|
354
|
+
member_id: memberId,
|
|
355
|
+
date: "2026-04-18",
|
|
356
|
+
start_time: 700,
|
|
357
|
+
end_time: 760,
|
|
358
|
+
repeats: "never",
|
|
359
|
+
status: "upcoming",
|
|
360
|
+
teams_ids: [teamId]
|
|
361
|
+
}
|
|
362
|
+
: {
|
|
363
|
+
name: "CLI Verify Meeting",
|
|
364
|
+
type: "OneOnOneMeeting",
|
|
365
|
+
member_id: memberId,
|
|
366
|
+
date: "2026-04-18",
|
|
367
|
+
start_time: 700,
|
|
368
|
+
repeats: "never",
|
|
369
|
+
status: "upcoming"
|
|
370
|
+
};
|
|
173
371
|
|
|
174
372
|
const probes = [
|
|
175
373
|
["projects", "show", "--id", projectId],
|
|
@@ -213,16 +411,16 @@ const probes = [
|
|
|
213
411
|
["rocks", "create", "--data-json", payload("rock", { name: "CLI Verify Rock", rock_collection_id: rockCollectionId, status: "on_track", priority: "no_priority", rock_type: "individual" })],
|
|
214
412
|
["rocks", "update", "--id", rockId, "--data-json", payload("rock", { description: "verify-update" })],
|
|
215
413
|
["meetings", "notes", "--id", meetingId, "--content", "CLI verify notes"],
|
|
216
|
-
["meetings", "create", "--data-json", payload("meeting",
|
|
414
|
+
["meetings", "create", "--data-json", payload("meeting", meetingCreatePayload)],
|
|
217
415
|
["meetings", "update", "--id", meetingId, "--data-json", payload("meeting", { notes: "verify-update" })],
|
|
218
416
|
["members", "create", "--data-json", payload("member", { email: `cli.verify.${Date.now()}@example.com` })],
|
|
219
417
|
["members", "update", "--id", memberId, "--data-json", payload("member", { first_name: "CLI" })],
|
|
220
418
|
["teams", "create", "--data-json", payload("team", { name: `CLI Verify Team ${Date.now()}` })],
|
|
221
419
|
["teams", "update", "--id", teamId, "--data-json", payload("team", { name: `CLI Verify Team Update ${Date.now()}` })],
|
|
222
|
-
["organizations", "update", "--id", orgId, "--data-json", payload("organization", { workspace_name:
|
|
223
|
-
["organizations", "meta-profile", "update", "--id",
|
|
224
|
-
["organizations", "key-metric-meta-profile", "update", "--id",
|
|
225
|
-
["issues", "create", "--issue-group-id", issueGroupId, "--name", "CLI Verify Issue", "--issue-type", "
|
|
420
|
+
["organizations", "update", "--id", orgId, "--data-json", payload("organization", { organization_detail_attributes: { workspace_name: orgWorkspaceNameVerify } })],
|
|
421
|
+
["organizations", "meta-profile", "update", "--id", organizationMetaProfileId, "--data-json", payload("organization_meta_profile", { profile: { company_identity: { one_sentence_summary: orgMetaOneSentenceSummaryVerify } } })],
|
|
422
|
+
["organizations", "key-metric-meta-profile", "update", "--id", keyMetricMetaProfileId, "--data-json", payload("key_metric_meta_profile", { profile: { financial: { revenue: keyMetricRevenueVerify } } })],
|
|
423
|
+
["issues", "create", "--issue-group-id", issueGroupId, "--name", "CLI Verify Issue", "--issue-type", "short_term"],
|
|
226
424
|
["issues", "update", "--id", issueId, "--data-json", payload("issue", { description: "verify-update" })],
|
|
227
425
|
["lists", "create", "--data-json", payload("list", { name: "CLI Verify List", status: "in_progress", priority: "no_priority" })],
|
|
228
426
|
["lists", "update", "--id", listId, "--data-json", payload("list", { description: "verify-update" })],
|
|
@@ -232,42 +430,42 @@ const probes = [
|
|
|
232
430
|
["issue-groups", "update", "--id", issueGroupId, "--data-json", payload("issue_group", { description: "verify-update" })],
|
|
233
431
|
["todo-groups", "create", "--data-json", payload("todo_group", { name: "CLI Verify Todo Group", status: "in_progress", priority: "no_priority" })],
|
|
234
432
|
["todo-groups", "update", "--id", todoGroupId, "--data-json", payload("todo_group", { description: "verify-update" })],
|
|
235
|
-
["todos", "create", "--data-json", payload("todo", { todo_group_id: todoGroupId, name: "CLI Verify Todo", status: "
|
|
433
|
+
["todos", "create", "--data-json", payload("todo", { todo_group_id: todoGroupId, name: "CLI Verify Todo", status: "open", priority: "no_priority" })],
|
|
236
434
|
["todos", "update", "--id", todoId, "--data-json", payload("todo", { description: "verify-update" })],
|
|
237
435
|
["rock-collections", "create", "--data-json", payload("rock_collection", { name: "CLI Verify Rock Collection", status: "in_progress", priority: "no_priority" })],
|
|
238
436
|
["rock-collections", "update", "--id", rockCollectionId, "--data-json", payload("rock_collection", { description: "verify-update" })],
|
|
239
|
-
["knowledge", "create", "--data-json", payload("content", {
|
|
437
|
+
["knowledge", "create", "--data-json", payload("content", { content_type: "process", status: "draft", name: "CLI Verify Doc", member_id: memberId })],
|
|
240
438
|
["knowledge", "update", "--id", contentId, "--data-json", payload("content", { name: "CLI Verify Doc Update" })],
|
|
241
439
|
["stand-ups", "create", "--data-json", payload("stand_up", { member_id: memberId, completed_date: "2026-04-06" })],
|
|
242
440
|
["stand-ups", "update", "--id", standUpId, "--data-json", payload("stand_up", { blockers: "verify-update" })],
|
|
243
|
-
["news", "create", "--data-json", payload("headline", { summary: "CLI Verify Headline", status: "
|
|
441
|
+
["news", "create", "--data-json", payload("headline", { summary: "CLI Verify Headline", member_id: memberId, status: "active", headline_type: "org_wide" })],
|
|
244
442
|
["news", "update", "--id", headlineId, "--data-json", payload("headline", { description: "verify-update" })],
|
|
245
|
-
["questions", "create", "--data-json", payload("question", {
|
|
246
|
-
["questions", "update", "--id", questionId, "--data-json", payload("question", {
|
|
247
|
-
["pulse", "create", "--data-json", payload("health_update", {
|
|
443
|
+
["questions", "create", "--data-json", payload("question", { name: "CLI Verify Question", member_id: memberId })],
|
|
444
|
+
["questions", "update", "--id", questionId, "--data-json", payload("question", { name: questionNameVerify, description: "verify-update" })],
|
|
445
|
+
["pulse", "create", "--data-json", payload("health_update", { health_updatable_id: projectId, health_updatable_type: "Project", member_id: memberId, value: "on_track", status: "on_track" })],
|
|
248
446
|
["pulse", "update", "--id", pulseId, "--data-json", payload("health_update", { value: "verify-update" })],
|
|
249
|
-
["surveys", "create", "--data-json", payload("survey", {
|
|
250
|
-
["surveys", "update", "--id", surveyId, "--data-json", payload("survey", {
|
|
251
|
-
["feedbacks", "create", "--data-json", payload("feedback", {
|
|
252
|
-
["feedbacks", "update", "--id", feedbackId, "--data-json", payload("feedback", {
|
|
253
|
-
["accountability", "create", "--data-json", payload("responsibility", {
|
|
254
|
-
["accountability", "update", "--id", responsibilityId, "--data-json", payload("responsibility", {
|
|
255
|
-
["kpis", "create", "--data-json", payload("smart_kpi", {
|
|
447
|
+
["surveys", "create", "--data-json", payload("survey", { name: "engagement", recipient_type: "org_wide" })],
|
|
448
|
+
["surveys", "update", "--id", surveyId, "--data-json", payload("survey", { name: "engagement", recipient_type: "org_wide", due_date: surveyDueDateVerify })],
|
|
449
|
+
["feedbacks", "create", "--data-json", payload("feedback", { name: "company_culture", quarter: "q2", year: "2026" })],
|
|
450
|
+
["feedbacks", "update", "--id", feedbackId, "--data-json", payload("feedback", { name: "roadmap_and_strategy", quarter: feedbackQuarterVerify, year: "2026" })],
|
|
451
|
+
["accountability", "create", "--data-json", payload("responsibility", { name: "CLI Verify Responsibility", member_id: memberId })],
|
|
452
|
+
["accountability", "update", "--id", responsibilityId, "--data-json", payload("responsibility", { name: accountabilityNameVerify })],
|
|
453
|
+
["kpis", "create", "--data-json", payload("smart_kpi", { smart_kpi_view_id: kpiSmartKpiViewId, name: kpiCreateName })],
|
|
256
454
|
["kpis", "update", "--id", kpiId, "--data-json", payload("smart_kpi", { name: "CLI Verify KPI Update" })],
|
|
257
455
|
["scorecard-groups", "create", "--data-json", payload("measurable_group", { name: "CLI Verify Scorecard Group" })],
|
|
258
456
|
["scorecard-groups", "update", "--id", measurableGroupId, "--data-json", payload("measurable_group", { name: "CLI Verify Scorecard Group Update" })],
|
|
259
|
-
["scorecards", "create", "--data-json", payload("measurable", { measurable_group_id: measurableGroupId, name: "CLI Verify Scorecard" })],
|
|
457
|
+
["scorecards", "create", "--data-json", payload("measurable", { measurable_group_id: measurableGroupId, name: "CLI Verify Scorecard", interval: "weekly", trend: "average" })],
|
|
260
458
|
["scorecards", "update", "--id", measurableId, "--data-json", payload("measurable", { name: "CLI Verify Scorecard Update" })],
|
|
261
459
|
["customers", "create", "--data-json", payload("customer", { name: "CLI Verify Customer" })],
|
|
262
460
|
["customers", "update", "--id", customerId, "--data-json", payload("customer", { name: "CLI Verify Customer Update" })],
|
|
263
461
|
["contacts", "create", "--data-json", payload("contact", { customer_id: customerId, name: "CLI Verify Contact" })],
|
|
264
462
|
["contacts", "update", "--id", contactId, "--data-json", payload("contact", { name: "CLI Verify Contact Update" })],
|
|
265
|
-
["foundation", "strategic-plans", "update", "--id", orgId, "--data-json", payload("strategic_plan", {
|
|
266
|
-
["foundation", "strategic-objectives", "update", "--id", orgId, "--data-json", payload("strategic_objective", {
|
|
267
|
-
["foundation", "annual-objectives", "create", "--data-json", payload("annual_objective", { strategic_objective_id: annualObjectiveId || orgId,
|
|
268
|
-
["foundation", "annual-objectives", "update", "--id", annualObjectiveId, "--data-json", payload("annual_objective", {
|
|
269
|
-
["foundation", "quarterly-objectives", "create", "--data-json", payload("quarterly_objective", { strategic_objective_id: annualObjectiveId || orgId, annual_objective_id: annualObjectiveId || orgId,
|
|
270
|
-
["foundation", "quarterly-objectives", "update", "--id", quarterlyObjectiveId, "--data-json", payload("quarterly_objective", {
|
|
463
|
+
["foundation", "strategic-plans", "update", "--id", orgId, "--data-json", payload("strategic_plan", { published_at: "2026-04-18T17:00:00Z" })],
|
|
464
|
+
["foundation", "strategic-objectives", "update", "--id", orgId, "--data-json", payload("strategic_objective", { summary: "CLI Verify Strategic Objective" })],
|
|
465
|
+
["foundation", "annual-objectives", "create", "--data-json", payload("annual_objective", { strategic_objective_id: annualObjectiveId || orgId, name: "CLI Verify Annual Objective" })],
|
|
466
|
+
["foundation", "annual-objectives", "update", "--id", annualObjectiveId, "--data-json", payload("annual_objective", { name: "CLI Verify Annual Objective Update" })],
|
|
467
|
+
["foundation", "quarterly-objectives", "create", "--data-json", payload("quarterly_objective", { strategic_objective_id: annualObjectiveId || orgId, annual_objective_id: annualObjectiveId || orgId, name: "CLI Verify Quarterly Objective" })],
|
|
468
|
+
["foundation", "quarterly-objectives", "update", "--id", quarterlyObjectiveId, "--data-json", payload("quarterly_objective", { name: "CLI Verify Quarterly Objective Update" })]
|
|
271
469
|
];
|
|
272
470
|
|
|
273
471
|
for (const args of probes) {
|
|
@@ -286,6 +484,184 @@ for (const args of probes) {
|
|
|
286
484
|
results.push(runWave(args, env));
|
|
287
485
|
}
|
|
288
486
|
|
|
487
|
+
let deleteVerifyLine = "";
|
|
488
|
+
let deleteVerifyFailure = 0;
|
|
489
|
+
if (issueId) {
|
|
490
|
+
const subissueCreate = runWave(
|
|
491
|
+
[
|
|
492
|
+
"subissues",
|
|
493
|
+
"create",
|
|
494
|
+
"--data-json",
|
|
495
|
+
payload("sub_issue", {
|
|
496
|
+
issue_id: issueId,
|
|
497
|
+
name: `CLI Verify Subissue ${Date.now()}`
|
|
498
|
+
})
|
|
499
|
+
],
|
|
500
|
+
env
|
|
501
|
+
);
|
|
502
|
+
results.push(subissueCreate);
|
|
503
|
+
const subIssueId = subissueCreate?.parsed?.data?.create_sub_issue?.data?.data?.id
|
|
504
|
+
? String(subissueCreate.parsed.data.create_sub_issue.data.data.id)
|
|
505
|
+
: "";
|
|
506
|
+
if (subIssueId) {
|
|
507
|
+
const destroyRes = runWave(["subissues", "destroy", "--id", subIssueId], env);
|
|
508
|
+
results.push(destroyRes);
|
|
509
|
+
const verifyRes = verifySubissueDeleteWithPolling(env, issueId, subIssueId);
|
|
510
|
+
deleteVerifyLine = `${verifyRes.ok ? "PASS" : "FAIL"} | status=${verifyRes.ok ? 200 : 500} | err=${
|
|
511
|
+
verifyRes.ok ? "none" : "delete_not_observed"
|
|
512
|
+
} | subissues destroy verify --issue-id ${issueId} --id ${subIssueId} --tries ${verifyRes.tries}`;
|
|
513
|
+
if (!verifyRes.ok) {
|
|
514
|
+
deleteVerifyFailure = 1;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const postUpdateVerificationLines = [];
|
|
520
|
+
let postUpdateVerificationFailures = 0;
|
|
521
|
+
|
|
522
|
+
function hasSuccessfulCommand(commandPrefix) {
|
|
523
|
+
return results.some((res) => {
|
|
524
|
+
if (!Array.isArray(res.args)) return false;
|
|
525
|
+
if (res.args.length < commandPrefix.length) return false;
|
|
526
|
+
for (let i = 0; i < commandPrefix.length; i += 1) {
|
|
527
|
+
if (res.args[i] !== commandPrefix[i]) {
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return res.parsed?.ok === true;
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function verifyFieldWrite({ label, showArgs, expectedValue, candidatePaths, requiredSuccessPrefix }) {
|
|
536
|
+
if (requiredSuccessPrefix && !hasSuccessfulCommand(requiredSuccessPrefix)) {
|
|
537
|
+
postUpdateVerificationLines.push(`PASS | status=n/a | err=skipped_prereq_not_ok | ${label}`);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (showArgs.includes(undefined)) {
|
|
542
|
+
postUpdateVerificationLines.push(`PASS | status=n/a | err=skipped_missing_id | ${label}`);
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
const showRes = runWave(showArgs, env);
|
|
547
|
+
const status = showRes.parsed?.status ?? "n/a";
|
|
548
|
+
const errCode = showRes.parsed?.error?.code ?? "none";
|
|
549
|
+
|
|
550
|
+
if (!showRes.parsed?.ok) {
|
|
551
|
+
postUpdateVerificationLines.push(
|
|
552
|
+
`FAIL | status=${status} | err=${errCode} | ${label} (${showArgs.join(" ")})`
|
|
553
|
+
);
|
|
554
|
+
postUpdateVerificationFailures += 1;
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const actual = firstDefinedValue(showRes.parsed, candidatePaths);
|
|
559
|
+
const ok = String(actual ?? "") === String(expectedValue);
|
|
560
|
+
postUpdateVerificationLines.push(
|
|
561
|
+
`${ok ? "PASS" : "FAIL"} | status=${status} | err=${
|
|
562
|
+
ok ? "none" : "read_after_write_mismatch"
|
|
563
|
+
} | ${label} expected=${JSON.stringify(expectedValue)} actual=${JSON.stringify(actual ?? null)}`
|
|
564
|
+
);
|
|
565
|
+
if (!ok) {
|
|
566
|
+
postUpdateVerificationFailures += 1;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
verifyFieldWrite({
|
|
571
|
+
label: "organizations.update verify workspace_name",
|
|
572
|
+
showArgs: ["organizations", "show", "--id", orgId],
|
|
573
|
+
expectedValue: orgWorkspaceNameVerify,
|
|
574
|
+
requiredSuccessPrefix: ["organizations", "update"],
|
|
575
|
+
candidatePaths: [
|
|
576
|
+
["data", "organization", "organizationDetail", "workspaceName"],
|
|
577
|
+
["data", "organization", "organization_detail", "workspace_name"],
|
|
578
|
+
["data", "organization", "attributes", "organizationDetail", "workspaceName"],
|
|
579
|
+
["data", "organization", "attributes", "organization_detail_attributes", "workspace_name"]
|
|
580
|
+
]
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
verifyFieldWrite({
|
|
584
|
+
label: "organizations.meta-profile.update verify one_sentence_summary",
|
|
585
|
+
showArgs: ["organizations", "meta-profile", "show", "--id", organizationMetaProfileId],
|
|
586
|
+
expectedValue: orgMetaOneSentenceSummaryVerify,
|
|
587
|
+
requiredSuccessPrefix: ["organizations", "meta-profile", "update"],
|
|
588
|
+
candidatePaths: [
|
|
589
|
+
[
|
|
590
|
+
"data",
|
|
591
|
+
"organization_meta_profile",
|
|
592
|
+
"attributes",
|
|
593
|
+
"profile",
|
|
594
|
+
"companyIdentity",
|
|
595
|
+
"oneSentenceSummary"
|
|
596
|
+
],
|
|
597
|
+
[
|
|
598
|
+
"data",
|
|
599
|
+
"organization_meta_profile",
|
|
600
|
+
"attributes",
|
|
601
|
+
"profile",
|
|
602
|
+
"company_identity",
|
|
603
|
+
"one_sentence_summary"
|
|
604
|
+
],
|
|
605
|
+
[
|
|
606
|
+
"data",
|
|
607
|
+
"organizationMetaProfile",
|
|
608
|
+
"attributes",
|
|
609
|
+
"profile",
|
|
610
|
+
"companyIdentity",
|
|
611
|
+
"oneSentenceSummary"
|
|
612
|
+
]
|
|
613
|
+
]
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
verifyFieldWrite({
|
|
617
|
+
label: "organizations.key-metric-meta-profile.update verify financial.revenue",
|
|
618
|
+
showArgs: ["organizations", "key-metric-meta-profile", "show", "--id", keyMetricMetaProfileId],
|
|
619
|
+
expectedValue: keyMetricRevenueVerify,
|
|
620
|
+
requiredSuccessPrefix: ["organizations", "key-metric-meta-profile", "update"],
|
|
621
|
+
candidatePaths: [
|
|
622
|
+
["data", "key_metric_meta_profile", "attributes", "profile", "financial", "revenue"],
|
|
623
|
+
["data", "keyMetricMetaProfile", "attributes", "profile", "financial", "revenue"]
|
|
624
|
+
]
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
verifyFieldWrite({
|
|
628
|
+
label: "questions.update verify name",
|
|
629
|
+
showArgs: ["questions", "show", "--id", questionId],
|
|
630
|
+
expectedValue: questionNameVerify,
|
|
631
|
+
requiredSuccessPrefix: ["questions", "update"],
|
|
632
|
+
candidatePaths: [
|
|
633
|
+
["data", "question", "attributes", "name"],
|
|
634
|
+
["data", "question", "attributes", "summary"]
|
|
635
|
+
]
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
verifyFieldWrite({
|
|
639
|
+
label: "surveys.update verify due_date",
|
|
640
|
+
showArgs: ["surveys", "show", "--id", surveyId],
|
|
641
|
+
expectedValue: surveyDueDateVerify,
|
|
642
|
+
requiredSuccessPrefix: ["surveys", "update"],
|
|
643
|
+
candidatePaths: [
|
|
644
|
+
["data", "survey", "attributes", "dueDate"],
|
|
645
|
+
["data", "survey", "attributes", "due_date"]
|
|
646
|
+
]
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
verifyFieldWrite({
|
|
650
|
+
label: "feedbacks.update verify quarter",
|
|
651
|
+
showArgs: ["feedbacks", "show", "--id", feedbackId],
|
|
652
|
+
expectedValue: feedbackQuarterVerify,
|
|
653
|
+
requiredSuccessPrefix: ["feedbacks", "update"],
|
|
654
|
+
candidatePaths: [["data", "feedback", "attributes", "quarter"]]
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
verifyFieldWrite({
|
|
658
|
+
label: "accountability.update verify name",
|
|
659
|
+
showArgs: ["accountability", "show", "--id", responsibilityId],
|
|
660
|
+
expectedValue: accountabilityNameVerify,
|
|
661
|
+
requiredSuccessPrefix: ["accountability", "update"],
|
|
662
|
+
candidatePaths: [["data", "responsibility", "attributes", "name"]]
|
|
663
|
+
});
|
|
664
|
+
|
|
289
665
|
const lines = [];
|
|
290
666
|
let failures = 0;
|
|
291
667
|
for (const res of results) {
|
|
@@ -293,10 +669,24 @@ for (const res of results) {
|
|
|
293
669
|
const cmd = res.args.join(" ");
|
|
294
670
|
const status = res.parsed?.status ?? "n/a";
|
|
295
671
|
const errCode = res.parsed?.error?.code ?? "none";
|
|
296
|
-
|
|
672
|
+
const reasonDetail = verdict.details ? ` (${JSON.stringify(verdict.details)})` : "";
|
|
673
|
+
lines.push(
|
|
674
|
+
`${verdict.ok ? "PASS" : "FAIL"} | status=${status} | err=${errCode} | reason=${verdict.reason}${reasonDetail} | ${cmd}`
|
|
675
|
+
);
|
|
297
676
|
if (!verdict.ok) failures += 1;
|
|
298
677
|
}
|
|
299
678
|
|
|
679
|
+
if (deleteVerifyLine) {
|
|
680
|
+
lines.push(deleteVerifyLine);
|
|
681
|
+
}
|
|
682
|
+
failures += deleteVerifyFailure;
|
|
683
|
+
if (postUpdateVerificationLines.length > 0) {
|
|
684
|
+
lines.push(...postUpdateVerificationLines);
|
|
685
|
+
}
|
|
686
|
+
failures += postUpdateVerificationFailures;
|
|
687
|
+
|
|
300
688
|
console.log(lines.join("\n"));
|
|
301
|
-
|
|
689
|
+
const extraChecksCount =
|
|
690
|
+
(deleteVerifyLine ? 1 : 0) + postUpdateVerificationLines.length;
|
|
691
|
+
console.log(`\nSUMMARY total=${results.length + extraChecksCount} failures=${failures}`);
|
|
302
692
|
if (failures > 0) process.exit(1);
|