@flowriki/agent 0.1.0-beta.42 → 0.1.0-beta.44

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.
@@ -6,7 +6,7 @@ import os from "os";
6
6
  import path from "path";
7
7
  import { createRequire } from "module";
8
8
  import { spawnSync } from "child_process";
9
- var AGENT_VERSION = "0.1.0-beta.42";
9
+ var AGENT_VERSION = "0.1.0-beta.44";
10
10
  async function prepareBrowsers() {
11
11
  if (browsersReady()) {
12
12
  return { ok: true, already: true, message: "chromium is already installed" };
@@ -1008,6 +1008,8 @@ import { z as z42 } from "zod";
1008
1008
  import { z as z5 } from "zod";
1009
1009
  import { z as z6 } from "zod";
1010
1010
  import { z as z7 } from "zod";
1011
+ import { z as z8 } from "zod";
1012
+ import { z as z9 } from "zod";
1011
1013
  var EngineSchema = z4.enum(["chromium", "firefox", "webkit"]);
1012
1014
  var CapabilitySchema = z4.object({
1013
1015
  id: z4.string(),
@@ -1036,18 +1038,44 @@ var ExecutionConfigSchema = z4.object({
1036
1038
  })
1037
1039
  ).default({})
1038
1040
  });
1039
- var FlowOccurrenceSchema = z22.object({
1041
+ var BUSINESS_KEYWORDS = ["Given", "When", "Then", "And", "But"];
1042
+ var BusinessStepSchema = z22.object({
1043
+ keyword: z22.enum(BUSINESS_KEYWORDS),
1044
+ text: z22.string().min(1).max(2e3)
1045
+ }).strict();
1046
+ var TestCaseOriginSchema = z22.object({
1047
+ kind: z22.enum(["import", "assistant"]),
1048
+ at: z22.string(),
1049
+ by: z22.string().default(""),
1050
+ /** The file it was imported from, and its row or id there. */
1051
+ file: z22.string().max(300).optional(),
1052
+ row: z22.string().max(200).optional()
1053
+ }).strict();
1054
+ var KEYWORD = /^\s*(given|when|then|and|but)\b[\s:]*(.*)$/i;
1055
+ var keywordOf = (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
1056
+ function parseGherkin(text) {
1057
+ const lines = text.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).filter((l) => !/^(scenario|scenario outline|feature|background|examples)\s*:/i.test(l) && !l.startsWith("|"));
1058
+ if (!lines.length) return null;
1059
+ const steps = [];
1060
+ for (const line of lines) {
1061
+ const m = KEYWORD.exec(line);
1062
+ if (!m || !m[2].trim()) return null;
1063
+ steps.push({ keyword: keywordOf(m[1]), text: m[2].trim() });
1064
+ }
1065
+ return steps;
1066
+ }
1067
+ var FlowOccurrenceSchema = z32.object({
1040
1068
  /** This copy's own identity. Not the source flow's — a flow added twice is
1041
1069
  * two occurrences, and editing, breakpoints, results and deletion must be
1042
1070
  * able to tell them apart. */
1043
- occurrenceId: z22.string().min(1),
1044
- actorId: z22.string().optional(),
1071
+ occurrenceId: z32.string().min(1),
1072
+ actorId: z32.string().optional(),
1045
1073
  /** Editable, and initially the source flow's name. */
1046
- name: z22.string().min(1),
1074
+ name: z32.string().min(1),
1047
1075
  /** Where this copy starts, when it is told to navigate before running.
1048
1076
  * Absent means continue from wherever the previous row left the browser. */
1049
- startPath: z22.string().optional(),
1050
- baseUrl: z22.string().url().optional(),
1077
+ startPath: z32.string().optional(),
1078
+ baseUrl: z32.string().url().optional(),
1051
1079
  /** GO SOMEWHERE FIRST, or carry on where the last row ended.
1052
1080
  *
1053
1081
  * SUPERSEDED BY `start`, and still read so that every case written before
@@ -1057,7 +1085,7 @@ var FlowOccurrenceSchema = z22.object({
1057
1085
  * Off by default, because a case is a sequence in one browser: re-entering
1058
1086
  * each flow's original starting URL would sign the tester out between rows
1059
1087
  * and is exactly the behaviour composing flows is meant to avoid. */
1060
- navigateFirst: z22.boolean().default(false),
1088
+ navigateFirst: z32.boolean().default(false),
1061
1089
  /** WHICH BROWSER THIS ROW RUNS IN.
1062
1090
  *
1063
1091
  * Two answers, because there are two: carry on in the browser this
@@ -1080,7 +1108,7 @@ var FlowOccurrenceSchema = z22.object({
1080
1108
  * A participant's FIRST row is always fresh in effect: there is nothing to
1081
1109
  * continue from. That is not stored, because it is a fact about the order
1082
1110
  * rather than about the row — moving the row changes the answer. */
1083
- start: z22.enum(["continue", "navigate", "fresh"]).optional(),
1111
+ start: z32.enum(["continue", "navigate", "fresh"]).optional(),
1084
1112
  /** WHETHER THIS COPY DOES ITS OWN SIGNING IN.
1085
1113
  *
1086
1114
  * A flow recorded with "sign in before recording" keeps that sign-in as its
@@ -1099,28 +1127,28 @@ var FlowOccurrenceSchema = z22.object({
1099
1127
  * the two agree on the account and is refused where they do not — so a case
1100
1128
  * written before this keeps its meaning, and a contradiction stays a
1101
1129
  * contradiction until somebody actually resolves it. */
1102
- ownSignIn: z22.enum(["skip", "run"]).optional(),
1103
- steps: z22.array(RecordedStepSchema),
1130
+ ownSignIn: z32.enum(["skip", "run"]).optional(),
1131
+ steps: z32.array(RecordedStepSchema),
1104
1132
  environment: ExecutionEnvironmentSchema.optional(),
1105
1133
  /** Where this copy came from, so the editor can say whether the source has
1106
1134
  * moved on — informational only, never a trigger to rewrite anything. */
1107
- origin: z22.object({
1108
- flowId: z22.string(),
1135
+ origin: z32.object({
1136
+ flowId: z32.string(),
1109
1137
  /** The schema the source was written in, which may be older than today's. */
1110
- schemaVersion: z22.number().int().nonnegative(),
1138
+ schemaVersion: z32.number().int().nonnegative(),
1111
1139
  /** The source's own revision counter at the moment it was copied. */
1112
- revision: z22.number().int().nonnegative(),
1140
+ revision: z32.number().int().nonnegative(),
1113
1141
  /** The commit the copy was taken from, when one was known. */
1114
- commit: z22.string().optional(),
1115
- featureId: z22.string(),
1142
+ commit: z32.string().optional(),
1143
+ featureId: z32.string(),
1116
1144
  /** Names as they were, so an old case still reads correctly after the
1117
1145
  * source is renamed, moved or deleted. */
1118
- featureName: z22.string(),
1119
- flowName: z22.string(),
1146
+ featureName: z32.string(),
1147
+ flowName: z32.string(),
1120
1148
  /** Source step id → the id it was given here. Kept so a later comparison
1121
1149
  * against the source can line the two up; nothing depends on it to run. */
1122
- stepIds: z22.record(z22.string(), z22.string()).default({}),
1123
- copiedAt: z22.string()
1150
+ stepIds: z32.record(z32.string(), z32.string()).default({}),
1151
+ copiedAt: z32.string()
1124
1152
  }),
1125
1153
  /** WHICH OF THIS ROW'S STEPS ARE WHAT RUNS BEFORE ITS FLOW — the flow's
1126
1154
  * sign-in and the prerequisites copied in with it — so the row can be shown
@@ -1131,24 +1159,24 @@ var FlowOccurrenceSchema = z22.object({
1131
1159
  * id, so editing or deleting one of them leaves the rest still grouped.
1132
1160
  * Absent on every row copied before this existed, which simply show flat.
1133
1161
  * Never sent to a machine — see `withoutFolding`. */
1134
- before: z22.object({
1162
+ before: z32.object({
1135
1163
  /** The flow's own sign-in, when the copy brought one. */
1136
- signInStepId: z22.string().optional(),
1137
- flows: z22.array(z22.object({
1138
- flowId: z22.string(),
1139
- name: z22.string(),
1140
- stepIds: z22.array(z22.string())
1164
+ signInStepId: z32.string().optional(),
1165
+ flows: z32.array(z32.object({
1166
+ flowId: z32.string(),
1167
+ name: z32.string(),
1168
+ stepIds: z32.array(z32.string())
1141
1169
  }).strict()).default([])
1142
1170
  }).strict().optional()
1143
1171
  }).strict();
1144
1172
  var CASE_SCHEMA_VERSION = 1;
1145
- var TestCaseSchema = z22.object({
1146
- schemaVersion: z22.literal(CASE_SCHEMA_VERSION),
1147
- id: z22.string().min(1),
1148
- folderId: z22.string().min(1),
1149
- slug: z22.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1150
- name: z22.string().min(1),
1151
- description: z22.string().default(""),
1173
+ var TestCaseSchema = z32.object({
1174
+ schemaVersion: z32.literal(CASE_SCHEMA_VERSION),
1175
+ id: z32.string().min(1),
1176
+ folderId: z32.string().min(1),
1177
+ slug: z32.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1178
+ name: z32.string().min(1),
1179
+ description: z32.string().default(""),
1152
1180
  /** NO LONGER USED, and kept only so that a case written while they were
1153
1181
  * parses.
1154
1182
  *
@@ -1161,19 +1189,25 @@ var TestCaseSchema = z22.object({
1161
1189
  *
1162
1190
  * Every row now starts where its own flow says, which is the same answer
1163
1191
  * whatever the order. */
1164
- startPath: z22.string().default("/"),
1165
- useStartPath: z22.boolean().default(false),
1166
- baseUrl: z22.string().url().optional(),
1192
+ startPath: z32.string().default("/"),
1193
+ useStartPath: z32.boolean().default(false),
1194
+ baseUrl: z32.string().url().optional(),
1167
1195
  environment: ExecutionEnvironmentSchema.optional(),
1168
- actors: z22.array(ActorDefinitionSchema).optional(),
1169
- defaultActorId: z22.string().optional(),
1170
- occurrences: z22.array(FlowOccurrenceSchema).default([]),
1171
- createdAt: z22.string(),
1172
- createdBy: z22.string().default(""),
1173
- updatedAt: z22.string(),
1196
+ actors: z32.array(ActorDefinitionSchema).optional(),
1197
+ defaultActorId: z32.string().optional(),
1198
+ occurrences: z32.array(FlowOccurrenceSchema).default([]),
1199
+ /** WHAT IT CHECKS, IN WORDS: Given / When / Then. Written for a case that is
1200
+ * not automated yet — imported, or written by the assistant — and kept when
1201
+ * it is. Never sent to a machine — see `withoutFolding`. */
1202
+ businessSteps: z32.array(BusinessStepSchema).optional(),
1203
+ /** Where it came from, when not recorded here. */
1204
+ origin: TestCaseOriginSchema.optional(),
1205
+ createdAt: z32.string(),
1206
+ createdBy: z32.string().default(""),
1207
+ updatedAt: z32.string(),
1174
1208
  /** The same optimistic-concurrency counter a flow carries, so an edit made
1175
1209
  * against a stale copy is refused rather than overwriting. */
1176
- revision: z22.number().int().nonnegative().default(0)
1210
+ revision: z32.number().int().nonnegative().default(0)
1177
1211
  }).strict().superRefine((testCase, ctx) => {
1178
1212
  const seen = /* @__PURE__ */ new Set();
1179
1213
  testCase.occurrences.forEach((occurrence, i) => {
@@ -1202,47 +1236,47 @@ var TestCaseSchema = z22.object({
1202
1236
  const { defaultActorId: _gone, ...rest } = testCase;
1203
1237
  return rest;
1204
1238
  });
1205
- var CaseFolderSchema = z22.object({
1206
- schemaVersion: z22.literal(1),
1207
- id: z22.string().min(1),
1208
- slug: z22.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1209
- name: z22.string().min(1),
1210
- description: z22.string().default(""),
1211
- order: z22.number().int().default(0),
1212
- createdAt: z22.string(),
1213
- createdBy: z22.string().default("")
1239
+ var CaseFolderSchema = z32.object({
1240
+ schemaVersion: z32.literal(1),
1241
+ id: z32.string().min(1),
1242
+ slug: z32.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1243
+ name: z32.string().min(1),
1244
+ description: z32.string().default(""),
1245
+ order: z32.number().int().default(0),
1246
+ createdAt: z32.string(),
1247
+ createdBy: z32.string().default("")
1214
1248
  }).strict();
1215
1249
  var SUITE_SCHEMA_VERSION = 1;
1216
- var SuiteEntrySchema = z22.object({
1217
- entryId: z22.string().min(1),
1218
- kind: z22.enum(["flow", "testCase"]),
1250
+ var SuiteEntrySchema = z32.object({
1251
+ entryId: z32.string().min(1),
1252
+ kind: z32.enum(["flow", "testCase"]),
1219
1253
  /** The document's ID — never its name or path, so renaming or moving what it
1220
1254
  * points at cannot break the reference. */
1221
- ref: z22.string().min(1),
1222
- enabled: z22.boolean().default(true),
1223
- order: z22.number().int().nonnegative(),
1255
+ ref: z32.string().min(1),
1256
+ enabled: z32.boolean().default(true),
1257
+ order: z32.number().int().nonnegative(),
1224
1258
  /** What it was called when it was added, so a result stays readable after the
1225
1259
  * source is renamed or deleted. */
1226
- nameSnapshot: z22.string().default("")
1260
+ nameSnapshot: z32.string().default("")
1227
1261
  }).strict();
1228
- var SuiteSchema = z22.object({
1229
- schemaVersion: z22.literal(SUITE_SCHEMA_VERSION),
1230
- id: z22.string().min(1),
1231
- slug: z22.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1232
- name: z22.string().min(1),
1233
- description: z22.string().default(""),
1234
- entries: z22.array(SuiteEntrySchema).default([]),
1235
- defaults: z22.object({
1236
- headless: z22.boolean().optional(),
1262
+ var SuiteSchema = z32.object({
1263
+ schemaVersion: z32.literal(SUITE_SCHEMA_VERSION),
1264
+ id: z32.string().min(1),
1265
+ slug: z32.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1266
+ name: z32.string().min(1),
1267
+ description: z32.string().default(""),
1268
+ entries: z32.array(SuiteEntrySchema).default([]),
1269
+ defaults: z32.object({
1270
+ headless: z32.boolean().optional(),
1237
1271
  /** Carry on through the remaining entries, or stop at the first failure.
1238
1272
  * Continuing is the default: a suite is a list of independent things and
1239
1273
  * one failure rarely invalidates the rest. */
1240
- failurePolicy: z22.enum(["continue", "stop"]).default("continue")
1274
+ failurePolicy: z32.enum(["continue", "stop"]).default("continue")
1241
1275
  }).default({ failurePolicy: "continue" }),
1242
- createdAt: z22.string(),
1243
- createdBy: z22.string().default(""),
1244
- updatedAt: z22.string(),
1245
- revision: z22.number().int().nonnegative().default(0)
1276
+ createdAt: z32.string(),
1277
+ createdBy: z32.string().default(""),
1278
+ updatedAt: z32.string(),
1279
+ revision: z32.number().int().nonnegative().default(0)
1246
1280
  }).strict().superRefine((suite, ctx) => {
1247
1281
  const seen = /* @__PURE__ */ new Set();
1248
1282
  suite.entries.forEach((entry, i) => {
@@ -1433,19 +1467,19 @@ function restoreDebugCase(testCase, owners, steps) {
1433
1467
  }
1434
1468
  return { ...testCase, occurrences };
1435
1469
  }
1436
- var AuthNavigationSchema = z32.discriminatedUnion("kind", [
1470
+ var AuthNavigationSchema = z42.discriminatedUnion("kind", [
1437
1471
  /** Act from wherever the browser already is — a "Log in" link in the header.
1438
1472
  * The only kind that is safe part-way through a journey. */
1439
- z32.object({ kind: z32.literal("continue") }),
1473
+ z42.object({ kind: z42.literal("continue") }),
1440
1474
  /** Open the procedure's own starting page first. Right when signing in is
1441
1475
  * the first thing that happens; it abandons a journey in progress. */
1442
- z32.object({ kind: z32.literal("open"), path: z32.string().min(1) })
1476
+ z42.object({ kind: z42.literal("open"), path: z42.string().min(1) })
1443
1477
  ]);
1444
- var AuthFieldSchema = z32.object({
1478
+ var AuthFieldSchema = z42.object({
1445
1479
  /** The step in the recorded procedure this value is typed into. Where a
1446
1480
  * recording types into the same box more than once, this is the FIRST of
1447
1481
  * them — the one an account's values are keyed by. */
1448
- stepId: z32.string().min(1),
1482
+ stepId: z42.string().min(1),
1449
1483
  /** EVERY step that types into this box, when there is more than one.
1450
1484
  *
1451
1485
  * A login typed twice — a first attempt with a typo, a page that re-rendered
@@ -1457,47 +1491,47 @@ var AuthFieldSchema = z32.object({
1457
1491
  *
1458
1492
  * Empty means the one step in `stepId`, so every profile written before this
1459
1493
  * reads correctly without being migrated. */
1460
- stepIds: z32.array(z32.string().min(1)).default([]),
1494
+ stepIds: z42.array(z42.string().min(1)).default([]),
1461
1495
  /** What it is called where somebody fills it in — the field's own name on
1462
1496
  * the page, so an account form reads "Username" rather than "st_9f2a". */
1463
- label: z32.string().min(1),
1497
+ label: z42.string().min(1),
1464
1498
  /** A secret arrives as a reference and is never written into a document. */
1465
- secret: z32.boolean().default(false),
1499
+ secret: z42.boolean().default(false),
1466
1500
  /** What the recording typed. Empty for a secret, whose value never travels.
1467
1501
  * Kept so the first account can be made from what was recorded, with
1468
1502
  * nothing to fill in. */
1469
- recorded: z32.string().default("")
1503
+ recorded: z42.string().default("")
1470
1504
  }).strict();
1471
1505
  var AUTH_PROFILE_SCHEMA_VERSION = 2;
1472
- var AuthProfileSchema = z32.object({
1473
- schemaVersion: z32.literal(AUTH_PROFILE_SCHEMA_VERSION),
1474
- id: z32.string().min(1),
1475
- slug: z32.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1476
- name: z32.string().min(1),
1477
- description: z32.string().default(""),
1506
+ var AuthProfileSchema = z42.object({
1507
+ schemaVersion: z42.literal(AUTH_PROFILE_SCHEMA_VERSION),
1508
+ id: z42.string().min(1),
1509
+ slug: z42.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1510
+ name: z42.string().min(1),
1511
+ description: z42.string().default(""),
1478
1512
  /** The recorded sign-in. A flow like any other, so it is edited, debugged
1479
1513
  * and replayed by everything that already knows how. */
1480
- flowId: z32.string().min(1),
1514
+ flowId: z42.string().min(1),
1481
1515
  /** Which of the values it types differ per identity. */
1482
- fields: z32.array(AuthFieldSchema).default([]),
1516
+ fields: z42.array(AuthFieldSchema).default([]),
1483
1517
  /** Optional, and its own procedure with its own proof — most profiles will
1484
1518
  * not have one at first. The proof is read off that flow, the same way. */
1485
- signOutFlowId: z32.string().optional(),
1519
+ signOutFlowId: z42.string().optional(),
1486
1520
  /** Descriptive only — "admin", "staff". Never used to decide anything, so
1487
1521
  * two profiles may share a tag without becoming interchangeable. */
1488
- tags: z32.array(z32.string()).default([]),
1489
- createdAt: z32.string(),
1490
- createdBy: z32.string().default(""),
1491
- updatedAt: z32.string(),
1492
- revision: z32.number().int().nonnegative().default(0)
1522
+ tags: z42.array(z42.string()).default([]),
1523
+ createdAt: z42.string(),
1524
+ createdBy: z42.string().default(""),
1525
+ updatedAt: z42.string(),
1526
+ revision: z42.number().int().nonnegative().default(0)
1493
1527
  }).strict();
1494
1528
  var ACCOUNT_BINDING_SCHEMA_VERSION = 3;
1495
- var AccountBindingSchema = z32.object({
1496
- schemaVersion: z32.literal(ACCOUNT_BINDING_SCHEMA_VERSION),
1497
- id: z32.string().min(1),
1498
- slug: z32.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1499
- name: z32.string().min(1),
1500
- profileId: z32.string().min(1),
1529
+ var AccountBindingSchema = z42.object({
1530
+ schemaVersion: z42.literal(ACCOUNT_BINDING_SCHEMA_VERSION),
1531
+ id: z42.string().min(1),
1532
+ slug: z42.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1533
+ name: z42.string().min(1),
1534
+ profileId: z42.string().min(1),
1501
1535
  /** Which environments of the APPLICATION UNDER TEST these credentials work
1502
1536
  * in — never Flowriki's own dev or staging.
1503
1537
  *
@@ -1509,47 +1543,47 @@ var AccountBindingSchema = z32.object({
1509
1543
  * duplicate account — same name, same password, same everything — for each
1510
1544
  * deployment the identity existed in, or a blank "works anywhere" that also
1511
1545
  * claimed environments it had never been created in. Neither was true. */
1512
- environments: z32.array(z32.string().min(1)).default([]),
1546
+ environments: z42.array(z42.string().min(1)).default([]),
1513
1547
  /** Step id → what this identity types there. Ordinary values: a username is
1514
1548
  * not a credential, and keeping it here is what lets somebody read an
1515
1549
  * account and know who it is. */
1516
- values: z32.record(z32.string(), z32.string()).default({}),
1550
+ values: z42.record(z42.string(), z42.string()).default({}),
1517
1551
  /** Step id → secret REFERENCE. The value is sealed in the vault and never
1518
1552
  * enters the repository, whatever form it was typed into. */
1519
- secrets: z32.record(z32.string(), z32.string().regex(/^[a-z][a-z0-9_]*$/i)).default({}),
1553
+ secrets: z42.record(z42.string(), z42.string().regex(/^[a-z][a-z0-9_]*$/i)).default({}),
1520
1554
  /** What this identity should look like once signed in — a displayed name, a
1521
1555
  * tenant. Not secret, and checked so that an already-authenticated browser
1522
1556
  * holding the WRONG account is reported rather than accepted. */
1523
- identity: z32.object({
1524
- label: z32.string().optional(),
1525
- tenant: z32.string().optional()
1557
+ identity: z42.object({
1558
+ label: z42.string().optional(),
1559
+ tenant: z42.string().optional()
1526
1560
  }).default({}),
1527
- createdAt: z32.string(),
1528
- createdBy: z32.string().default(""),
1529
- updatedAt: z32.string(),
1530
- revision: z32.number().int().nonnegative().default(0)
1561
+ createdAt: z42.string(),
1562
+ createdBy: z42.string().default(""),
1563
+ updatedAt: z42.string(),
1564
+ revision: z42.number().int().nonnegative().default(0)
1531
1565
  }).strict();
1532
- var AuthReferenceSchema = z32.object({
1533
- profileId: z32.string().min(1),
1566
+ var AuthReferenceSchema = z42.object({
1567
+ profileId: z42.string().min(1),
1534
1568
  /** Where this use of it begins. See the step's own field. */
1535
- from: z32.enum(["loginPage", "here"]).optional(),
1569
+ from: z42.enum(["loginPage", "here"]).optional(),
1536
1570
  /** Absent means "the only account bound to this profile for the selected
1537
1571
  * environment", which is resolved before a browser opens and refused when
1538
1572
  * it is ambiguous — a silent choice between two identities is the failure
1539
1573
  * this field exists to prevent. */
1540
- accountId: z32.string().optional()
1574
+ accountId: z42.string().optional()
1541
1575
  }).strict();
1542
1576
  var ActorSchema = ActorDefinitionSchema;
1543
- var DeliveredAuthSchema = z32.object({
1544
- profileId: z32.string().min(1),
1545
- accountId: z32.string().min(1),
1546
- name: z32.string(),
1547
- accountName: z32.string(),
1548
- steps: z32.array(RecordedStepSchema),
1577
+ var DeliveredAuthSchema = z42.object({
1578
+ profileId: z42.string().min(1),
1579
+ accountId: z42.string().min(1),
1580
+ name: z42.string(),
1581
+ accountName: z42.string(),
1582
+ steps: z42.array(RecordedStepSchema),
1549
1583
  navigation: AuthNavigationSchema,
1550
- success: z32.array(RecordedAssertionSchema),
1551
- secretRefs: z32.record(z32.string(), z32.string()),
1552
- signOut: z32.object({ steps: z32.array(RecordedStepSchema), success: z32.array(RecordedAssertionSchema) }).optional()
1584
+ success: z42.array(RecordedAssertionSchema),
1585
+ secretRefs: z42.record(z42.string(), z42.string()),
1586
+ signOut: z42.object({ steps: z42.array(RecordedStepSchema), success: z42.array(RecordedAssertionSchema) }).optional()
1553
1587
  }).strict();
1554
1588
  function actorPreparations(actors = []) {
1555
1589
  return actors.flatMap((actor) => actor.startSignedIn ? [{
@@ -1666,8 +1700,8 @@ function expandForRun(flow, lookup) {
1666
1700
  return { ...rest, steps: [...signIn ? [signIn] : [], ...steps, ...flow.steps] };
1667
1701
  }
1668
1702
  var HELPER_SCHEMA_VERSION = 1;
1669
- var SecretRef = z42.string().regex(/^[a-z][a-z0-9_]*$/i);
1670
- var PatternSchema = z42.string().max(500).refine((source) => {
1703
+ var SecretRef = z5.string().regex(/^[a-z][a-z0-9_]*$/i);
1704
+ var PatternSchema = z5.string().max(500).refine((source) => {
1671
1705
  try {
1672
1706
  new RegExp(source);
1673
1707
  return true;
@@ -1675,88 +1709,88 @@ var PatternSchema = z42.string().max(500).refine((source) => {
1675
1709
  return false;
1676
1710
  }
1677
1711
  }, "that is not a valid pattern");
1678
- var MailboxHelperSchema = z42.object({
1679
- kind: z42.literal("mailbox"),
1712
+ var MailboxHelperSchema = z5.object({
1713
+ kind: z5.literal("mailbox"),
1680
1714
  /** IMAP, which every provider offers: Gmail, Outlook, Zoho, Fastmail… */
1681
- host: z42.string().min(1),
1682
- port: z42.number().int().positive().default(993),
1683
- secure: z42.boolean().default(true),
1684
- username: z42.string().min(1),
1715
+ host: z5.string().min(1),
1716
+ port: z5.number().int().positive().default(993),
1717
+ secure: z5.boolean().default(true),
1718
+ username: z5.string().min(1),
1685
1719
  passwordRef: SecretRef,
1686
- folder: z42.string().min(1).default("INBOX"),
1720
+ folder: z5.string().min(1).default("INBOX"),
1687
1721
  /** Which email. All optional; the newest that matches every one given. */
1688
- match: z42.object({
1689
- to: z42.string().default(""),
1690
- from: z42.string().default(""),
1691
- subject: z42.string().default("")
1722
+ match: z5.object({
1723
+ to: z5.string().default(""),
1724
+ from: z5.string().default(""),
1725
+ subject: z5.string().default("")
1692
1726
  }).strict().default({}),
1693
1727
  /** What to take out of it. */
1694
- extract: z42.object({
1695
- take: z42.enum(["code", "link", "subject", "body"]).default("code"),
1728
+ extract: z5.object({
1729
+ take: z5.enum(["code", "link", "subject", "body"]).default("code"),
1696
1730
  /** For a code: the pattern, first group if it has one. Default: 4–8 digits.
1697
1731
  * For a link: only links containing this text. */
1698
- pattern: z42.string().max(500).default("")
1732
+ pattern: z5.string().max(500).default("")
1699
1733
  }).strict().default({}),
1700
1734
  /** How long to wait for the email to arrive. */
1701
- waitSeconds: z42.number().int().min(0).max(300).default(60)
1735
+ waitSeconds: z5.number().int().min(0).max(300).default(60)
1702
1736
  }).strict();
1703
- var TotpHelperSchema = z42.object({
1704
- kind: z42.literal("totp"),
1737
+ var TotpHelperSchema = z5.object({
1738
+ kind: z5.literal("totp"),
1705
1739
  /** The authenticator secret (base32, from the QR code's "manual entry"). */
1706
1740
  secretRef: SecretRef,
1707
- digits: z42.union([z42.literal(6), z42.literal(8)]).default(6),
1708
- period: z42.number().int().min(10).max(120).default(30),
1709
- algorithm: z42.enum(["SHA1", "SHA256", "SHA512"]).default("SHA1")
1741
+ digits: z5.union([z5.literal(6), z5.literal(8)]).default(6),
1742
+ period: z5.number().int().min(10).max(120).default(30),
1743
+ algorithm: z5.enum(["SHA1", "SHA256", "SHA512"]).default("SHA1")
1710
1744
  }).strict();
1711
- var SmsHelperSchema = z42.object({
1712
- kind: z42.literal("sms"),
1713
- provider: z42.literal("twilio").default("twilio"),
1714
- accountSid: z42.string().regex(/^AC[0-9a-f]{32}$/i, "a Twilio account SID starts with AC followed by 32 characters"),
1745
+ var SmsHelperSchema = z5.object({
1746
+ kind: z5.literal("sms"),
1747
+ provider: z5.literal("twilio").default("twilio"),
1748
+ accountSid: z5.string().regex(/^AC[0-9a-f]{32}$/i, "a Twilio account SID starts with AC followed by 32 characters"),
1715
1749
  authTokenRef: SecretRef,
1716
1750
  /** The Twilio number the application texts. */
1717
- to: z42.string().min(3),
1718
- match: z42.object({
1719
- from: z42.string().default(""),
1720
- contains: z42.string().default("")
1751
+ to: z5.string().min(3),
1752
+ match: z5.object({
1753
+ from: z5.string().default(""),
1754
+ contains: z5.string().default("")
1721
1755
  }).strict().default({}),
1722
- extract: z42.object({ pattern: z42.string().max(500).default("") }).strict().default({}),
1723
- waitSeconds: z42.number().int().min(0).max(300).default(60)
1756
+ extract: z5.object({ pattern: z5.string().max(500).default("") }).strict().default({}),
1757
+ waitSeconds: z5.number().int().min(0).max(300).default(60)
1724
1758
  }).strict();
1725
- var HttpHelperSchema = z42.object({
1726
- kind: z42.literal("http"),
1727
- method: z42.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).default("POST"),
1728
- url: z42.string().min(1),
1759
+ var HttpHelperSchema = z5.object({
1760
+ kind: z5.literal("http"),
1761
+ method: z5.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).default("POST"),
1762
+ url: z5.string().min(1),
1729
1763
  /** Plain headers, in the repository. */
1730
- headers: z42.record(z42.string(), z42.string()).default({}),
1764
+ headers: z5.record(z5.string(), z5.string()).default({}),
1731
1765
  /** Header name → vault reference, for tokens and keys. */
1732
- secretHeaders: z42.record(z42.string(), SecretRef).default({}),
1733
- body: z42.string().max(2e4).default(""),
1766
+ secretHeaders: z5.record(z5.string(), SecretRef).default({}),
1767
+ body: z5.string().max(2e4).default(""),
1734
1768
  /** Refused unless the response has this status. 0 means any 2xx. */
1735
- expectStatus: z42.number().int().min(0).max(599).default(0),
1736
- extract: z42.object({
1737
- take: z42.enum(["json", "pattern", "status", "nothing"]).default("nothing"),
1769
+ expectStatus: z5.number().int().min(0).max(599).default(0),
1770
+ extract: z5.object({
1771
+ take: z5.enum(["json", "pattern", "status", "nothing"]).default("nothing"),
1738
1772
  /** For json: a dot path — `data.order.id`, `items.0.code`. */
1739
- path: z42.string().max(300).default(""),
1740
- pattern: z42.string().max(500).default("")
1773
+ path: z5.string().max(300).default(""),
1774
+ pattern: z5.string().max(500).default("")
1741
1775
  }).strict().default({})
1742
1776
  }).strict();
1743
- var HelperConfigSchema = z42.discriminatedUnion("kind", [
1777
+ var HelperConfigSchema = z5.discriminatedUnion("kind", [
1744
1778
  MailboxHelperSchema,
1745
1779
  TotpHelperSchema,
1746
1780
  SmsHelperSchema,
1747
1781
  HttpHelperSchema
1748
1782
  ]);
1749
- var HelperSchema = z42.object({
1750
- schemaVersion: z42.literal(HELPER_SCHEMA_VERSION),
1751
- id: z42.string().min(1),
1752
- slug: z42.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1753
- name: z42.string().min(1).max(120),
1754
- description: z42.string().max(1e3).default(""),
1783
+ var HelperSchema = z5.object({
1784
+ schemaVersion: z5.literal(HELPER_SCHEMA_VERSION),
1785
+ id: z5.string().min(1),
1786
+ slug: z5.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1787
+ name: z5.string().min(1).max(120),
1788
+ description: z5.string().max(1e3).default(""),
1755
1789
  config: HelperConfigSchema,
1756
- createdAt: z42.string(),
1757
- createdBy: z42.string().default(""),
1758
- updatedAt: z42.string(),
1759
- revision: z42.number().int().nonnegative().default(0)
1790
+ createdAt: z5.string(),
1791
+ createdBy: z5.string().default(""),
1792
+ updatedAt: z5.string(),
1793
+ revision: z5.number().int().nonnegative().default(0)
1760
1794
  }).strict().superRefine((helper, ctx) => {
1761
1795
  const patterns = [
1762
1796
  helper.config.kind === "mailbox" && helper.config.extract.take === "code" ? helper.config.extract.pattern : "",
@@ -1769,9 +1803,9 @@ var HelperSchema = z42.object({
1769
1803
  }
1770
1804
  }
1771
1805
  });
1772
- var DeliveredHelperSchema = z42.object({
1773
- id: z42.string().min(1),
1774
- name: z42.string(),
1806
+ var DeliveredHelperSchema = z5.object({
1807
+ id: z5.string().min(1),
1808
+ name: z5.string(),
1775
1809
  config: HelperConfigSchema
1776
1810
  }).strict();
1777
1811
  var LIBRARY_CASE_SCHEMA_VERSION = 1;
@@ -1779,83 +1813,83 @@ var TEST_TYPES = ["functional", "negative", "edge", "regression", "smoke", "acce
1779
1813
  var PRIORITIES = ["P0", "P1", "P2", "P3"];
1780
1814
  var CASE_STATUSES = ["draft", "ready", "deprecated"];
1781
1815
  var AUTOMATION_STATES = ["none", "planned", "automated", "not-automatable"];
1782
- var LibraryStepSchema = z5.object({
1783
- id: z5.string().min(1),
1784
- action: z5.string().min(1),
1816
+ var LibraryStepSchema = z6.object({
1817
+ id: z6.string().min(1),
1818
+ action: z6.string().min(1),
1785
1819
  /** What to type or choose, when the action needs it. */
1786
- data: z5.string().optional(),
1820
+ data: z6.string().optional(),
1787
1821
  /** What should happen. Absent for a step that only gets somewhere. */
1788
- expected: z5.string().optional()
1822
+ expected: z6.string().optional()
1789
1823
  }).strict();
1790
- var AutomationLinkSchema = z5.object({
1791
- automationId: z5.string().min(1),
1792
- caseRevision: z5.number().int().nonnegative(),
1824
+ var AutomationLinkSchema = z6.object({
1825
+ automationId: z6.string().min(1),
1826
+ caseRevision: z6.number().int().nonnegative(),
1793
1827
  /** The automation's revision when the link was made or last confirmed —
1794
1828
  * an automation edited since may no longer check what the case says. */
1795
- automationRevision: z5.number().int().nonnegative().optional(),
1796
- at: z5.string(),
1797
- by: z5.string().default("")
1829
+ automationRevision: z6.number().int().nonnegative().optional(),
1830
+ at: z6.string(),
1831
+ by: z6.string().default("")
1798
1832
  }).strict();
1799
- var CaseOriginSchema = z5.discriminatedUnion("kind", [
1800
- z5.object({ kind: z5.literal("manual") }).strict(),
1801
- z5.object({
1802
- kind: z5.literal("import"),
1833
+ var CaseOriginSchema = z6.discriminatedUnion("kind", [
1834
+ z6.object({ kind: z6.literal("manual") }).strict(),
1835
+ z6.object({
1836
+ kind: z6.literal("import"),
1803
1837
  /** "csv", "xlsx", "testrail", "zephyr", "xray", "text"… */
1804
- format: z5.string().min(1),
1805
- file: z5.string().min(1),
1838
+ format: z6.string().min(1),
1839
+ file: z6.string().min(1),
1806
1840
  /** Row or item in that file, to find it again. */
1807
- row: z5.string().optional()
1841
+ row: z6.string().optional()
1808
1842
  }).strict(),
1809
- z5.object({
1810
- kind: z5.literal("generated"),
1811
- sourceId: z5.string().min(1),
1812
- sourceVersion: z5.number().int().positive(),
1813
- requirementIds: z5.array(z5.string().min(1)).default([])
1843
+ z6.object({
1844
+ kind: z6.literal("generated"),
1845
+ sourceId: z6.string().min(1),
1846
+ sourceVersion: z6.number().int().positive(),
1847
+ requirementIds: z6.array(z6.string().min(1)).default([])
1814
1848
  }).strict()
1815
1849
  ]);
1816
- var TestDataSchema = z5.object({
1817
- name: z5.string().min(1),
1818
- value: z5.string().optional(),
1819
- secretRef: z5.string().regex(/^[a-z][a-z0-9_]*$/i).optional()
1850
+ var TestDataSchema = z6.object({
1851
+ name: z6.string().min(1),
1852
+ value: z6.string().optional(),
1853
+ secretRef: z6.string().regex(/^[a-z][a-z0-9_]*$/i).optional()
1820
1854
  }).strict();
1821
- var LibraryCaseSchema = z5.object({
1822
- schemaVersion: z5.literal(LIBRARY_CASE_SCHEMA_VERSION),
1823
- id: z5.string().regex(/^tcs_[A-Za-z0-9]+$/),
1855
+ var LibraryCaseSchema = z6.object({
1856
+ schemaVersion: z6.literal(LIBRARY_CASE_SCHEMA_VERSION),
1857
+ id: z6.string().regex(/^tcs_[A-Za-z0-9]+$/),
1824
1858
  /** "TC-142": what people say out loud. The id is what links point at. */
1825
- key: z5.string().regex(/^TC-[1-9][0-9]*$/),
1859
+ key: z6.string().regex(/^TC-[1-9][0-9]*$/),
1826
1860
  /** The same features flows are filed under (`f_<slug>`), so one feature
1827
1861
  * holds both what to test and what tests it. */
1828
- featureId: z5.string().min(1),
1829
- slug: z5.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1830
- title: z5.string().min(1).max(300),
1831
- description: z5.string().default(""),
1832
- type: z5.enum(TEST_TYPES).default("functional"),
1833
- priority: z5.enum(PRIORITIES).default("P2"),
1834
- status: z5.enum(CASE_STATUSES).default("draft"),
1835
- preconditions: z5.array(z5.string().min(1)).default([]),
1836
- steps: z5.array(LibraryStepSchema).default([]),
1837
- testData: z5.array(TestDataSchema).default([]),
1838
- tags: z5.array(z5.string().min(1)).default([]),
1862
+ featureId: z6.string().min(1),
1863
+ slug: z6.string().regex(/^[a-z0-9][a-z0-9-]*$/),
1864
+ title: z6.string().min(1).max(300),
1865
+ description: z6.string().default(""),
1866
+ type: z6.enum(TEST_TYPES).default("functional"),
1867
+ priority: z6.enum(PRIORITIES).default("P2"),
1868
+ status: z6.enum(CASE_STATUSES).default("draft"),
1869
+ preconditions: z6.array(z6.string().min(1)).default([]),
1870
+ steps: z6.array(LibraryStepSchema).default([]),
1871
+ testData: z6.array(TestDataSchema).default([]),
1872
+ tags: z6.array(z6.string().min(1)).default([]),
1839
1873
  /** Requirement ids (Flowriki storage). The text is not copied here. */
1840
- covers: z5.array(z5.string().min(1)).default([]),
1841
- automation: z5.object({
1842
- state: z5.enum(AUTOMATION_STATES).default("none"),
1874
+ covers: z6.array(z6.string().min(1)).default([]),
1875
+ automation: z6.object({
1876
+ state: z6.enum(AUTOMATION_STATES).default("none"),
1843
1877
  /** Why it cannot be automated, when it cannot. */
1844
- reason: z5.string().optional(),
1878
+ reason: z6.string().optional(),
1845
1879
  /** The plan for automating it: flows to reuse, flows to record, checks to
1846
1880
  * switch on, accounts and helpers it needs, and what cannot be automated.
1847
1881
  * Written (usually by the assistant) and approved before anything is
1848
1882
  * recorded. */
1849
- plan: z5.string().max(2e4).optional(),
1850
- planApproved: z5.boolean().optional(),
1851
- links: z5.array(AutomationLinkSchema).default([])
1883
+ plan: z6.string().max(2e4).optional(),
1884
+ planApproved: z6.boolean().optional(),
1885
+ links: z6.array(AutomationLinkSchema).default([])
1852
1886
  }).strict().default({}),
1853
1887
  origin: CaseOriginSchema.default({ kind: "manual" }),
1854
- createdAt: z5.string(),
1855
- createdBy: z5.string().default(""),
1856
- updatedAt: z5.string(),
1857
- updatedBy: z5.string().default(""),
1858
- revision: z5.number().int().nonnegative().default(0)
1888
+ createdAt: z6.string(),
1889
+ createdBy: z6.string().default(""),
1890
+ updatedAt: z6.string(),
1891
+ updatedBy: z6.string().default(""),
1892
+ revision: z6.number().int().nonnegative().default(0)
1859
1893
  }).strict().superRefine((doc, ctx) => {
1860
1894
  const seen = /* @__PURE__ */ new Set();
1861
1895
  doc.steps.forEach((step, i) => {
@@ -1874,144 +1908,167 @@ var LibraryCaseSchema = z5.object({
1874
1908
  }
1875
1909
  });
1876
1910
  var SOURCE_KINDS = ["upload", "jira", "figma", "confluence", "linear", "github-issue", "notion", "url"];
1877
- var SourceVersionSchema = z5.object({
1878
- v: z5.number().int().positive(),
1879
- hash: z5.string().min(1),
1880
- extractedText: z5.string(),
1911
+ var SourceVersionSchema = z6.object({
1912
+ v: z6.number().int().positive(),
1913
+ hash: z6.string().min(1),
1914
+ extractedText: z6.string(),
1881
1915
  /** Where an uploaded file WAS kept. Only text is kept since 2026-10-11;
1882
1916
  * read so older records still parse, and cleared at start-up. */
1883
- originalKey: z5.string().optional(),
1884
- mediaType: z5.string().optional(),
1885
- at: z5.string(),
1886
- by: z5.string().default("")
1917
+ originalKey: z6.string().optional(),
1918
+ mediaType: z6.string().optional(),
1919
+ at: z6.string(),
1920
+ by: z6.string().default("")
1887
1921
  }).strict();
1888
- var SourceSchema = z5.object({
1889
- id: z5.string().regex(/^src_[A-Za-z0-9]+$/),
1890
- projectId: z5.string().min(1),
1891
- title: z5.string().min(1).max(300),
1892
- kind: z5.enum(SOURCE_KINDS),
1893
- versions: z5.array(SourceVersionSchema).min(1),
1894
- integrationId: z5.string().optional(),
1895
- externalId: z5.string().optional(),
1896
- externalUrl: z5.string().url().optional(),
1897
- createdAt: z5.string(),
1898
- createdBy: z5.string().default("")
1922
+ var SourceSchema = z6.object({
1923
+ id: z6.string().regex(/^src_[A-Za-z0-9]+$/),
1924
+ projectId: z6.string().min(1),
1925
+ title: z6.string().min(1).max(300),
1926
+ kind: z6.enum(SOURCE_KINDS),
1927
+ versions: z6.array(SourceVersionSchema).min(1),
1928
+ integrationId: z6.string().optional(),
1929
+ externalId: z6.string().optional(),
1930
+ externalUrl: z6.string().url().optional(),
1931
+ createdAt: z6.string(),
1932
+ createdBy: z6.string().default("")
1899
1933
  }).strict();
1900
- var RequirementSchema = z5.object({
1901
- id: z5.string().regex(/^req_[A-Za-z0-9]+$/),
1902
- projectId: z5.string().min(1),
1903
- sourceId: z5.string().min(1),
1904
- sourceVersion: z5.number().int().positive(),
1934
+ var RequirementSchema = z6.object({
1935
+ id: z6.string().regex(/^req_[A-Za-z0-9]+$/),
1936
+ projectId: z6.string().min(1),
1937
+ sourceId: z6.string().min(1),
1938
+ sourceVersion: z6.number().int().positive(),
1905
1939
  /** Where in the source: a heading path, a Jira key, a Figma node. */
1906
- anchor: z5.string().min(1),
1907
- text: z5.string().min(1),
1908
- featureId: z5.string().optional(),
1940
+ anchor: z6.string().min(1),
1941
+ text: z6.string().min(1),
1942
+ featureId: z6.string().optional(),
1909
1943
  /** As of the source's latest version: new in it, changed by it, unchanged
1910
1944
  * ("active"), or gone from it. */
1911
- state: z5.enum(["new", "active", "changed", "removed"]).default("new"),
1912
- history: z5.array(z5.object({
1913
- sourceVersion: z5.number().int().positive(),
1914
- text: z5.string(),
1915
- state: z5.enum(["new", "active", "changed", "removed"])
1945
+ state: z6.enum(["new", "active", "changed", "removed"]).default("new"),
1946
+ history: z6.array(z6.object({
1947
+ sourceVersion: z6.number().int().positive(),
1948
+ text: z6.string(),
1949
+ state: z6.enum(["new", "active", "changed", "removed"])
1916
1950
  }).strict()).default([])
1917
1951
  }).strict();
1918
1952
  var MANUAL_OUTCOMES = ["untested", "passed", "failed", "blocked", "skipped"];
1919
- var EvidenceSchema = z6.object({
1920
- id: z6.string().regex(/^ev_[A-Za-z0-9]+$/),
1953
+ var EvidenceSchema = z7.object({
1954
+ id: z7.string().regex(/^ev_[A-Za-z0-9]+$/),
1921
1955
  /** A file kept in Flowriki's evidence storage, or a link to one elsewhere. */
1922
- kind: z6.enum(["file", "link"]),
1923
- name: z6.string().min(1).max(200),
1924
- mediaType: z6.string().optional(),
1925
- size: z6.number().int().nonnegative().optional(),
1926
- url: z6.string().url().optional(),
1956
+ kind: z7.enum(["file", "link"]),
1957
+ name: z7.string().min(1).max(200),
1958
+ mediaType: z7.string().optional(),
1959
+ size: z7.number().int().nonnegative().optional(),
1960
+ url: z7.string().url().optional(),
1927
1961
  /** The step it shows, when it belongs to one. */
1928
- stepId: z6.string().optional(),
1929
- at: z6.string(),
1930
- by: z6.string().default("")
1962
+ stepId: z7.string().optional(),
1963
+ at: z7.string(),
1964
+ by: z7.string().default("")
1931
1965
  }).strict();
1932
- var StepOutcomeSchema = z6.object({
1933
- stepId: z6.string().min(1),
1934
- outcome: z6.enum(MANUAL_OUTCOMES),
1966
+ var StepOutcomeSchema = z7.object({
1967
+ stepId: z7.string().min(1),
1968
+ outcome: z7.enum(MANUAL_OUTCOMES),
1935
1969
  /** What actually happened, when it was not what was expected. */
1936
- actual: z6.string().max(4e3).optional()
1970
+ actual: z7.string().max(4e3).optional()
1937
1971
  }).strict();
1938
- var ManualResultSchema = z6.object({
1939
- outcome: z6.enum(MANUAL_OUTCOMES),
1940
- steps: z6.array(StepOutcomeSchema).default([]),
1941
- note: z6.string().max(8e3).default(""),
1942
- evidence: z6.array(EvidenceSchema).default([]),
1943
- bugIds: z6.array(z6.string().min(1)).default([]),
1944
- tester: z6.string().default(""),
1945
- at: z6.string()
1972
+ var ManualResultSchema = z7.object({
1973
+ outcome: z7.enum(MANUAL_OUTCOMES),
1974
+ steps: z7.array(StepOutcomeSchema).default([]),
1975
+ note: z7.string().max(8e3).default(""),
1976
+ evidence: z7.array(EvidenceSchema).default([]),
1977
+ bugIds: z7.array(z7.string().min(1)).default([]),
1978
+ tester: z7.string().default(""),
1979
+ at: z7.string()
1946
1980
  }).strict();
1947
- var CycleEntrySchema = z6.object({
1948
- testCaseId: z6.string().min(1),
1949
- key: z6.string().min(1),
1950
- title: z6.string().min(1),
1951
- featureId: z6.string().min(1),
1952
- priority: z6.enum(PRIORITIES),
1981
+ var CycleEntrySchema = z7.object({
1982
+ testCaseId: z7.string().min(1),
1983
+ key: z7.string().min(1),
1984
+ title: z7.string().min(1),
1985
+ featureId: z7.string().min(1),
1986
+ priority: z7.enum(PRIORITIES),
1953
1987
  /** The case revision snapshot, so "the case changed since" is answerable. */
1954
- caseRevision: z6.number().int().nonnegative(),
1955
- preconditions: z6.array(z6.string()).default([]),
1956
- steps: z6.array(z6.object({ id: z6.string(), action: z6.string(), data: z6.string().optional(), expected: z6.string().optional() }).strict()).default([]),
1957
- assignee: z6.string().optional(),
1988
+ caseRevision: z7.number().int().nonnegative(),
1989
+ preconditions: z7.array(z7.string()).default([]),
1990
+ steps: z7.array(z7.object({ id: z7.string(), action: z7.string(), data: z7.string().optional(), expected: z7.string().optional() }).strict()).default([]),
1991
+ assignee: z7.string().optional(),
1958
1992
  result: ManualResultSchema.nullable().default(null),
1959
1993
  /** Earlier results for this case in this cycle, newest last — a retest
1960
1994
  * keeps what the first attempt found. */
1961
- history: z6.array(ManualResultSchema).default([])
1995
+ history: z7.array(ManualResultSchema).default([])
1962
1996
  }).strict();
1963
- var TestCycleSchema = z6.object({
1964
- id: z6.string().regex(/^cyc_[A-Za-z0-9]+$/),
1965
- projectId: z6.string().min(1),
1966
- name: z6.string().min(1).max(200),
1967
- description: z6.string().max(4e3).default(""),
1968
- status: z6.enum(["open", "closed"]).default("open"),
1997
+ var TestCycleSchema = z7.object({
1998
+ id: z7.string().regex(/^cyc_[A-Za-z0-9]+$/),
1999
+ projectId: z7.string().min(1),
2000
+ name: z7.string().min(1).max(200),
2001
+ description: z7.string().max(4e3).default(""),
2002
+ status: z7.enum(["open", "closed"]).default("open"),
1969
2003
  /** Which branch the cases were read from; null for the published tests. */
1970
- changeId: z6.string().nullable().default(null),
1971
- entries: z6.array(CycleEntrySchema).default([]),
1972
- createdAt: z6.string(),
1973
- createdBy: z6.string().default(""),
1974
- updatedAt: z6.string(),
1975
- closedAt: z6.string().nullable().default(null)
2004
+ changeId: z7.string().nullable().default(null),
2005
+ entries: z7.array(CycleEntrySchema).default([]),
2006
+ createdAt: z7.string(),
2007
+ createdBy: z7.string().default(""),
2008
+ updatedAt: z7.string(),
2009
+ closedAt: z7.string().nullable().default(null)
1976
2010
  }).strict();
1977
2011
  var BUG_STATUSES = ["open", "in-progress", "fixed", "verified", "closed", "wont-fix"];
1978
2012
  var SEVERITIES = ["critical", "major", "minor", "trivial"];
1979
- var BugSchema = z6.object({
1980
- id: z6.string().regex(/^bug_[A-Za-z0-9]+$/),
1981
- key: z6.string().regex(/^BUG-[1-9][0-9]*$/),
1982
- projectId: z6.string().min(1),
1983
- title: z6.string().min(1).max(300),
1984
- description: z6.string().max(2e4).default(""),
1985
- severity: z6.enum(SEVERITIES).default("major"),
1986
- status: z6.enum(BUG_STATUSES).default("open"),
1987
- tracker: z6.enum(["flowriki", "jira", "linear", "github"]).default("flowriki"),
1988
- externalKey: z6.string().optional(),
1989
- url: z6.string().url().optional(),
2013
+ var BugSchema = z7.object({
2014
+ id: z7.string().regex(/^bug_[A-Za-z0-9]+$/),
2015
+ key: z7.string().regex(/^BUG-[1-9][0-9]*$/),
2016
+ projectId: z7.string().min(1),
2017
+ title: z7.string().min(1).max(300),
2018
+ description: z7.string().max(2e4).default(""),
2019
+ severity: z7.enum(SEVERITIES).default("major"),
2020
+ status: z7.enum(BUG_STATUSES).default("open"),
2021
+ tracker: z7.enum(["flowriki", "jira", "linear", "github"]).default("flowriki"),
2022
+ externalKey: z7.string().optional(),
2023
+ url: z7.string().url().optional(),
1990
2024
  /** Where it was found: a case, the step in it, the cycle that ran it. */
1991
- testCaseIds: z6.array(z6.string()).default([]),
1992
- cycleIds: z6.array(z6.string()).default([]),
1993
- runIds: z6.array(z6.string()).default([]),
1994
- automationIds: z6.array(z6.string()).default([]),
1995
- foundAt: z6.object({ cycleId: z6.string(), testCaseId: z6.string(), stepId: z6.string().optional() }).strict().optional(),
1996
- createdAt: z6.string(),
1997
- createdBy: z6.string().default(""),
1998
- updatedAt: z6.string()
2025
+ testCaseIds: z7.array(z7.string()).default([]),
2026
+ cycleIds: z7.array(z7.string()).default([]),
2027
+ runIds: z7.array(z7.string()).default([]),
2028
+ automationIds: z7.array(z7.string()).default([]),
2029
+ foundAt: z7.object({ cycleId: z7.string(), testCaseId: z7.string(), stepId: z7.string().optional() }).strict().optional(),
2030
+ createdAt: z7.string(),
2031
+ createdBy: z7.string().default(""),
2032
+ updatedAt: z7.string()
1999
2033
  }).strict();
2000
2034
  var STOP = new Set("a an the and or of to in on for with by is are be as at it this that from user users can should must shall will when then given".split(" "));
2001
- var ConversationSchema = z7.object({
2002
- id: z7.string().regex(/^conv_[A-Za-z0-9]+$/),
2003
- projectId: z7.string().min(1),
2035
+ var ConversationSchema = z8.object({
2036
+ id: z8.string().regex(/^conv_[A-Za-z0-9]+$/),
2037
+ projectId: z8.string().min(1),
2004
2038
  /** Whose: conversations are personal. */
2005
- userId: z7.string().min(1),
2006
- title: z7.string().min(1).max(200),
2007
- mode: z7.enum(["ask", "do"]).default("ask"),
2039
+ userId: z8.string().min(1),
2040
+ title: z8.string().min(1).max(200),
2041
+ mode: z8.enum(["ask", "do"]).default("ask"),
2008
2042
  /** The assistant's own session, to continue where it left off. */
2009
- sessionId: z7.string().optional(),
2043
+ sessionId: z8.string().optional(),
2010
2044
  /** The conversation as the dashboard draws it. Kept as given: the shape
2011
2045
  * belongs to the screen, and the service only stores and returns it. */
2012
- lines: z7.array(z7.unknown()).max(2e3).default([]),
2013
- createdAt: z7.string(),
2014
- updatedAt: z7.string()
2046
+ lines: z8.array(z8.unknown()).max(2e3).default([]),
2047
+ createdAt: z8.string(),
2048
+ updatedAt: z8.string()
2049
+ }).strict();
2050
+ var IMPORT_DRAFT_TTL_MS = 24 * 60 * 60 * 1e3;
2051
+ var ImportDraftCaseSchema = z9.object({
2052
+ name: z9.string().min(1).max(120),
2053
+ description: z9.string().max(4e3).default(""),
2054
+ businessSteps: z9.array(BusinessStepSchema).max(200),
2055
+ /** Its id or row in the file. */
2056
+ row: z9.string().max(200).default("")
2057
+ }).strict();
2058
+ var ImportDraftSchema = z9.object({
2059
+ id: z9.string().regex(/^imp_[A-Za-z0-9]+$/),
2060
+ projectId: z9.string().min(1),
2061
+ userId: z9.string().min(1),
2062
+ file: z9.string().max(300),
2063
+ /** Every sheet, every cell as text. */
2064
+ sheets: z9.array(z9.object({ name: z9.string().max(200), rows: z9.array(z9.array(z9.string())) }).strict()).max(200),
2065
+ status: z9.enum(["waiting", "converting", "done", "failed"]).default("waiting"),
2066
+ /** What the assistant made of it: features, each with its cases. */
2067
+ result: z9.array(z9.object({ feature: z9.string().min(1).max(120), cases: z9.array(ImportDraftCaseSchema) }).strict()).default([]),
2068
+ /** The assistant's word on anything it could not convert. */
2069
+ note: z9.string().max(4e3).default(""),
2070
+ createdAt: z9.string(),
2071
+ updatedAt: z9.string()
2015
2072
  }).strict();
2016
2073
 
2017
2074
  // ../engine-playwright/dist/index.js
@@ -6937,8 +6994,8 @@ async function fieldNames(page) {
6937
6994
  }
6938
6995
 
6939
6996
  // ../results/dist/chunk-LYCTVHPR.js
6940
- import { z as z8 } from "zod";
6941
- var RunStatusSchema = z8.enum([
6997
+ import { z as z10 } from "zod";
6998
+ var RunStatusSchema = z10.enum([
6942
6999
  "queued",
6943
7000
  "running",
6944
7001
  "passed",
@@ -6946,7 +7003,7 @@ var RunStatusSchema = z8.enum([
6946
7003
  "cancelled",
6947
7004
  "errored"
6948
7005
  ]);
6949
- var TaskStatusSchema = z8.enum([
7006
+ var TaskStatusSchema = z10.enum([
6950
7007
  "queued",
6951
7008
  "running",
6952
7009
  "passed",
@@ -6955,7 +7012,7 @@ var TaskStatusSchema = z8.enum([
6955
7012
  "cancelled",
6956
7013
  "errored"
6957
7014
  ]);
6958
- var FailureKindSchema = z8.enum([
7015
+ var FailureKindSchema = z10.enum([
6959
7016
  "not_found",
6960
7017
  "ambiguous",
6961
7018
  "timeout",
@@ -6964,30 +7021,30 @@ var FailureKindSchema = z8.enum([
6964
7021
  "crash",
6965
7022
  "unknown"
6966
7023
  ]);
6967
- var RunCheckSchema = z8.object({
6968
- id: z8.string(),
6969
- assertionId: z8.string().nullable(),
6970
- kind: z8.string(),
6971
- expected: z8.string().nullable(),
6972
- actual: z8.string().nullable(),
6973
- ok: z8.boolean(),
7024
+ var RunCheckSchema = z10.object({
7025
+ id: z10.string(),
7026
+ assertionId: z10.string().nullable(),
7027
+ kind: z10.string(),
7028
+ expected: z10.string().nullable(),
7029
+ actual: z10.string().nullable(),
7030
+ ok: z10.boolean(),
6974
7031
  /** A failed soft check is reported but does not fail its step, so a run can
6975
7032
  * be green and still carry findings. Stored per check rather than derived,
6976
7033
  * because the flow it came from can be edited afterwards and history has to
6977
7034
  * keep saying what actually happened. */
6978
- soft: z8.boolean().default(false),
6979
- detail: z8.string().nullable()
7035
+ soft: z10.boolean().default(false),
7036
+ detail: z10.string().nullable()
6980
7037
  });
6981
- var RunStepSchema = z8.object({
6982
- id: z8.string(),
6983
- ordinal: z8.number().int().nonnegative(),
7038
+ var RunStepSchema = z10.object({
7039
+ id: z10.string(),
7040
+ ordinal: z10.number().int().nonnegative(),
6984
7041
  /** The STABLE document step id — this is what joins runs across time and
6985
7042
  * makes flake-rate a view over existing columns rather than a migration. */
6986
- stepId: z8.string(),
6987
- action: z8.string(),
6988
- targetRole: z8.string().nullable(),
6989
- targetName: z8.string().nullable(),
6990
- targetScope: z8.string().nullable(),
7043
+ stepId: z10.string(),
7044
+ action: z10.string(),
7045
+ targetRole: z10.string().nullable(),
7046
+ targetName: z10.string().nullable(),
7047
+ targetScope: z10.string().nullable(),
6991
7048
  /** What the step typed, chose or pressed.
6992
7049
  *
6993
7050
  * A report that says `fill "Password"` and nothing else cannot tell you
@@ -6996,100 +7053,100 @@ var RunStepSchema = z8.object({
6996
7053
  *
6997
7054
  * NEVER set for a secret — see `secret` below. A run report is the thing
6998
7055
  * people paste into a ticket. */
6999
- value: z8.string().nullable().default(null),
7056
+ value: z10.string().nullable().default(null),
7000
7057
  /** The step typed a secret, so `value` is deliberately absent rather than
7001
7058
  * merely unknown. Stored, because "no value" and "a value withheld" render
7002
7059
  * differently and history has to keep saying which it was. */
7003
- secret: z8.boolean().default(false),
7004
- status: z8.enum(["passed", "failed", "skipped"]),
7060
+ secret: z10.boolean().default(false),
7061
+ status: z10.enum(["passed", "failed", "skipped"]),
7005
7062
  failureKind: FailureKindSchema.nullable(),
7006
- detail: z8.string().nullable(),
7063
+ detail: z10.string().nullable(),
7007
7064
  /** WHICH WAY FOUND IT, when the first way did not.
7008
7065
  *
7009
7066
  * A step carries several routes to its element and takes the first that
7010
7067
  * matches. Passing on a later one is not a failure, but it does mean the
7011
7068
  * page has moved under the step — and a suite that repairs itself quietly
7012
7069
  * drifts away from the application it tests. Null is the ordinary case. */
7013
- foundBy: z8.string().nullable().default(null),
7014
- durationMs: z8.number().int().nonnegative().nullable(),
7070
+ foundBy: z10.string().nullable().default(null),
7071
+ durationMs: z10.number().int().nonnegative().nullable(),
7015
7072
  /** Where the browser was when this step ran. Recorded on failure, and
7016
7073
  * frequently the whole answer — the element is missing because a step
7017
7074
  * before it navigated somewhere unexpected, not because it was renamed. */
7018
- pageUrl: z8.string().nullable().default(null),
7019
- pageTitle: z8.string().nullable().default(null),
7020
- checks: z8.array(RunCheckSchema).default([])
7075
+ pageUrl: z10.string().nullable().default(null),
7076
+ pageTitle: z10.string().nullable().default(null),
7077
+ checks: z10.array(RunCheckSchema).default([])
7021
7078
  });
7022
- var RunTaskSchema = z8.object({
7023
- id: z8.string(),
7024
- ordinal: z8.number().int().nonnegative(),
7025
- caseName: z8.string(),
7026
- rowId: z8.string().nullable(),
7079
+ var RunTaskSchema = z10.object({
7080
+ id: z10.string(),
7081
+ ordinal: z10.number().int().nonnegative(),
7082
+ caseName: z10.string(),
7083
+ rowId: z10.string().nullable(),
7027
7084
  capability: CapabilitySchema,
7028
- provider: z8.string(),
7029
- attempt: z8.number().int().positive().default(1),
7030
- maxAttempts: z8.number().int().positive().default(1),
7085
+ provider: z10.string(),
7086
+ attempt: z10.number().int().positive().default(1),
7087
+ maxAttempts: z10.number().int().positive().default(1),
7031
7088
  status: TaskStatusSchema,
7032
- workerId: z8.string().nullable(),
7089
+ workerId: z10.string().nullable(),
7033
7090
  /** Cloud provider's own session, so a failure is one click from their video. */
7034
- sessionId: z8.string().nullable(),
7035
- sessionUrl: z8.string().nullable(),
7036
- detail: z8.string().nullable(),
7037
- stepsRun: z8.number().int().nonnegative().default(0),
7038
- stepsTotal: z8.number().int().nonnegative().default(0),
7039
- durationMs: z8.number().int().nonnegative().nullable(),
7040
- steps: z8.array(RunStepSchema).default([])
7091
+ sessionId: z10.string().nullable(),
7092
+ sessionUrl: z10.string().nullable(),
7093
+ detail: z10.string().nullable(),
7094
+ stepsRun: z10.number().int().nonnegative().default(0),
7095
+ stepsTotal: z10.number().int().nonnegative().default(0),
7096
+ durationMs: z10.number().int().nonnegative().nullable(),
7097
+ steps: z10.array(RunStepSchema).default([])
7041
7098
  });
7042
- var ArtifactKindSchema = z8.enum(["screenshot", "video", "trace", "console", "har"]);
7043
- var ArtifactSchema = z8.object({
7044
- id: z8.string(),
7045
- runId: z8.string(),
7046
- runStepId: z8.string().nullable(),
7099
+ var ArtifactKindSchema = z10.enum(["screenshot", "video", "trace", "console", "har"]);
7100
+ var ArtifactSchema = z10.object({
7101
+ id: z10.string(),
7102
+ runId: z10.string(),
7103
+ runStepId: z10.string().nullable(),
7047
7104
  kind: ArtifactKindSchema,
7048
- relPath: z8.string(),
7049
- bytes: z8.number().int().nonnegative().nullable(),
7050
- masked: z8.boolean().default(false),
7051
- createdAt: z8.string()
7105
+ relPath: z10.string(),
7106
+ bytes: z10.number().int().nonnegative().nullable(),
7107
+ masked: z10.boolean().default(false),
7108
+ createdAt: z10.string()
7052
7109
  });
7053
- var RunSummarySchema = z8.object({
7054
- id: z8.string(),
7055
- projectId: z8.string(),
7110
+ var RunSummarySchema = z10.object({
7111
+ id: z10.string(),
7112
+ projectId: z10.string(),
7056
7113
  /** What the run was FOR.
7057
7114
  *
7058
7115
  * `flake` is a deliberate repetition of one flow to measure how often it
7059
7116
  * passes. It is kept out of pass-rate statistics: a 98/100 flakiness check is
7060
7117
  * a useful finding, not a failing suite, and counting it as one would make
7061
7118
  * measuring reliability look like losing it. */
7062
- kind: z8.enum(["smoke", "test", "adhoc", "flake"]),
7063
- trigger: z8.enum(["ui", "cli", "ci"]),
7119
+ kind: z10.enum(["smoke", "test", "adhoc", "flake"]),
7120
+ trigger: z10.enum(["ui", "cli", "ci"]),
7064
7121
  status: RunStatusSchema,
7065
- flowId: z8.string().nullable(),
7066
- flowName: z8.string().nullable(),
7067
- gitSha: z8.string().nullable(),
7068
- gitBranch: z8.string().nullable(),
7069
- gitDirty: z8.boolean().default(false),
7070
- env: z8.string().nullable(),
7071
- concurrency: z8.number().int().positive().nullable(),
7072
- tasksTotal: z8.number().int().nonnegative().default(0),
7073
- tasksPassed: z8.number().int().nonnegative().default(0),
7074
- tasksFailed: z8.number().int().nonnegative().default(0),
7122
+ flowId: z10.string().nullable(),
7123
+ flowName: z10.string().nullable(),
7124
+ gitSha: z10.string().nullable(),
7125
+ gitBranch: z10.string().nullable(),
7126
+ gitDirty: z10.boolean().default(false),
7127
+ env: z10.string().nullable(),
7128
+ concurrency: z10.number().int().positive().nullable(),
7129
+ tasksTotal: z10.number().int().nonnegative().default(0),
7130
+ tasksPassed: z10.number().int().nonnegative().default(0),
7131
+ tasksFailed: z10.number().int().nonnegative().default(0),
7075
7132
  /** Rolled up from the run's tasks rather than stored on the run, so they
7076
7133
  * cannot drift from the step rows they describe. "9 of 12" in a list is
7077
7134
  * what tells a reader where a run died; "1 of 1 tasks" tells them nothing
7078
7135
  * until there is more than one browser in play. */
7079
- stepsRun: z8.number().int().nonnegative().default(0),
7080
- stepsTotal: z8.number().int().nonnegative().default(0),
7081
- queuedAt: z8.string(),
7082
- startedAt: z8.string().nullable(),
7083
- finishedAt: z8.string().nullable(),
7084
- durationMs: z8.number().int().nonnegative().nullable()
7136
+ stepsRun: z10.number().int().nonnegative().default(0),
7137
+ stepsTotal: z10.number().int().nonnegative().default(0),
7138
+ queuedAt: z10.string(),
7139
+ startedAt: z10.string().nullable(),
7140
+ finishedAt: z10.string().nullable(),
7141
+ durationMs: z10.number().int().nonnegative().nullable()
7085
7142
  });
7086
7143
  var RunDetailSchema = RunSummarySchema.extend({
7087
- errorMessage: z8.string().nullable(),
7088
- artifactsDir: z8.string().nullable(),
7089
- tasks: z8.array(RunTaskSchema).default([]),
7144
+ errorMessage: z10.string().nullable(),
7145
+ artifactsDir: z10.string().nullable(),
7146
+ tasks: z10.array(RunTaskSchema).default([]),
7090
7147
  /** Screenshots and the like, addressed by `runStepId`. Kept flat rather than
7091
7148
  * nested inside each step: an artifact can belong to the run as a whole. */
7092
- artifacts: z8.array(ArtifactSchema).default([]),
7149
+ artifacts: z10.array(ArtifactSchema).default([]),
7093
7150
  /** The document as it was executed — a flow, or a test case with the copies
7094
7151
  * it held that day.
7095
7152
  *
@@ -7098,7 +7155,7 @@ var RunDetailSchema = RunSummarySchema.extend({
7098
7155
  * edited, and without surfacing it the promise was only half kept: the bytes
7099
7156
  * were there and nothing could reach them. Null for runs recorded before a
7100
7157
  * snapshot was taken. */
7101
- flowSnapshot: z8.unknown().nullable().default(null)
7158
+ flowSnapshot: z10.unknown().nullable().default(null)
7102
7159
  });
7103
7160
 
7104
7161
  // ../results/dist/chunk-IW3PJWP6.js
@@ -11370,6 +11427,7 @@ var ASK_MODE_TOOLS = [
11370
11427
  "project_brief",
11371
11428
  "knowledge_search",
11372
11429
  "knowledge_read",
11430
+ "read_test_cases",
11373
11431
  "list_my_branches"
11374
11432
  ];
11375
11433
  function buildAskArgs(opts) {
@@ -12040,6 +12098,7 @@ export {
12040
12098
  connect,
12041
12099
  RecordedStepSchema,
12042
12100
  mirrorCheckTargets,
12101
+ parseGherkin,
12043
12102
  runtimeValue,
12044
12103
  authenticationResolver,
12045
12104
  checkAssertion,