@validate.qa/runner 1.0.100 → 1.0.101

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.
@@ -3304,7 +3304,7 @@ function unescapeQuotedBody(raw) {
3304
3304
  return raw.replace(/\\(['"`\\])/g, "$1");
3305
3305
  }
3306
3306
  function extractRoleNameValue(line) {
3307
- const m = line.match(new RegExp(`getByRole\\s*\\([^,]+,\\s*\\{[^}]*name\\s*:\\s*(?:${QUOTED_BODY}|\\/([^/]*?)\\/)`, "i"));
3307
+ const m = line.match(new RegExp(`getByRole\\s*\\([^,]{1,200},\\s*\\{[^}]{0,200}?name\\s*:\\s*(?:${QUOTED_BODY}|\\/([^/]*?)\\/)`, "i"));
3308
3308
  if (!m)
3309
3309
  return null;
3310
3310
  const raw = m[1] ?? m[2] ?? m[3];
@@ -4012,6 +4012,8 @@ function stripCoverageComments(code) {
4012
4012
  let copyFrom = 0;
4013
4013
  let i = 0;
4014
4014
  let quote = null;
4015
+ let prev = "";
4016
+ let noRegexBefore = 0;
4015
4017
  while (i < code.length) {
4016
4018
  const ch = code[i];
4017
4019
  if (quote) {
@@ -4019,12 +4021,24 @@ function stripCoverageComments(code) {
4019
4021
  i += 2;
4020
4022
  continue;
4021
4023
  }
4022
- if (ch === quote || ch === "\n" && quote !== "`")
4024
+ if (ch === quote || ch === "\n" && quote !== "`") {
4023
4025
  quote = null;
4026
+ prev = ch === "\n" ? prev : ch;
4027
+ }
4024
4028
  i++;
4025
4029
  continue;
4026
4030
  }
4027
4031
  const next = code[i + 1];
4032
+ if (ch === "/" && next !== "*" && next !== "/" && i >= noRegexBefore && (prev === "" || REGEX_PRECEDER2.includes(prev))) {
4033
+ const end = regexLiteralEnd3(code, i);
4034
+ if (end > 0) {
4035
+ i = end;
4036
+ prev = "a";
4037
+ continue;
4038
+ }
4039
+ const eol = code.indexOf("\n", i);
4040
+ noRegexBefore = eol === -1 ? code.length : eol;
4041
+ }
4028
4042
  if (ch === "/" && next === "*") {
4029
4043
  const end = code.indexOf("*/", i + 2);
4030
4044
  const stop = end === -1 ? code.length : end + 2;
@@ -4043,11 +4057,39 @@ function stripCoverageComments(code) {
4043
4057
  }
4044
4058
  if (ch === '"' || ch === "'" || ch === "`")
4045
4059
  quote = ch;
4060
+ if (ch !== " " && ch !== " " && ch !== "\n" && ch !== "\r")
4061
+ prev = ch;
4046
4062
  i++;
4047
4063
  }
4048
4064
  out.push(code.slice(copyFrom));
4049
4065
  return out.join("");
4050
4066
  }
4067
+ function regexLiteralEnd3(code, start) {
4068
+ let inClass = false;
4069
+ for (let j = start + 1; j < code.length; j++) {
4070
+ const c = code[j];
4071
+ if (c === "\n")
4072
+ return -1;
4073
+ if (c === "\\") {
4074
+ j++;
4075
+ continue;
4076
+ }
4077
+ if (inClass) {
4078
+ if (c === "]")
4079
+ inClass = false;
4080
+ continue;
4081
+ }
4082
+ if (c === "[")
4083
+ inClass = true;
4084
+ else if (c === "/") {
4085
+ let k = j + 1;
4086
+ while (k < code.length && isIdentChar(code[k]))
4087
+ k++;
4088
+ return k;
4089
+ }
4090
+ }
4091
+ return -1;
4092
+ }
4051
4093
  function isIdentChar(ch) {
4052
4094
  if (!ch)
4053
4095
  return false;
@@ -4705,7 +4747,7 @@ function assessTitleCoverage(title, code) {
4705
4747
  const repeatedHit = [...repeated].some((term) => hay.includes(term));
4706
4748
  return { covered: hit >= needed || repeatedHit, missingTerms };
4707
4749
  }
4708
- var COVERAGE_STOP_WORDS, MAX_ASSERTION_JOIN_CHARS, MAX_COVERAGE_LINE_CHARS, BLOCK_SCAFFOLD, cachedAssertionInput, cachedAssertionSource, LOCAL_BINDING, ASSERTED_STATUS_RE, MAX_RESOLVED_NAMES_PER_LINE, WORD_CHAR_RE, NOT_CONTAIN_TEXT_RE, PLACE_PHRASE_RE, PLACE_WORD_MIN_CHARS, PLACE_FUNCTION_WORDS, HIDDEN_STATE_TERMS, HIDDEN_ELEMENT_LINE_RE, HIDDEN_LINE_RE, MAX_SHOWN_EARLIER_LINES, SHOWN_EARLIER_LITERAL_RE, SHARED_PREFIX_MIN_CHARS, MAX_SHOWN_EARLIER_LITERALS, VALUE_SHAPE_RE, VALUE_SHAPE_ALL_RE, TITLE_TERM_MIN;
4750
+ var COVERAGE_STOP_WORDS, MAX_ASSERTION_JOIN_CHARS, MAX_COVERAGE_LINE_CHARS, REGEX_PRECEDER2, BLOCK_SCAFFOLD, cachedAssertionInput, cachedAssertionSource, LOCAL_BINDING, ASSERTED_STATUS_RE, MAX_RESOLVED_NAMES_PER_LINE, WORD_CHAR_RE, NOT_CONTAIN_TEXT_RE, PLACE_PHRASE_RE, PLACE_WORD_MIN_CHARS, PLACE_FUNCTION_WORDS, HIDDEN_STATE_TERMS, HIDDEN_ELEMENT_LINE_RE, HIDDEN_LINE_RE, MAX_SHOWN_EARLIER_LINES, SHOWN_EARLIER_LITERAL_RE, SHARED_PREFIX_MIN_CHARS, MAX_SHOWN_EARLIER_LITERALS, VALUE_SHAPE_RE, VALUE_SHAPE_ALL_RE, TITLE_TERM_MIN;
4709
4751
  var init_expected_outcome_coverage = __esm({
4710
4752
  "../shared/dist/expected-outcome-coverage.js"() {
4711
4753
  "use strict";
@@ -4742,6 +4784,7 @@ var init_expected_outcome_coverage = __esm({
4742
4784
  ]);
4743
4785
  MAX_ASSERTION_JOIN_CHARS = 8e3;
4744
4786
  MAX_COVERAGE_LINE_CHARS = 2e3;
4787
+ REGEX_PRECEDER2 = "(,=:[!&|?{};+-*%<>~^";
4745
4788
  BLOCK_SCAFFOLD = /=>|\b(?:test|describe|it|beforeEach|afterEach|beforeAll|afterAll|function)\b/;
4746
4789
  cachedAssertionInput = null;
4747
4790
  cachedAssertionSource = { raw: "", normalized: "", bindings: /* @__PURE__ */ new Map(), bindingRefs: /* @__PURE__ */ new Map() };
@@ -5192,7 +5235,7 @@ function detectsErrorBannerAssertion(code) {
5192
5235
  const cleaned = stripCommentsAndLogs(stripLoginScaffolding(code));
5193
5236
  const lines = cleaned.split("\n");
5194
5237
  const candidates = [];
5195
- const positive = (stmt) => !NEGATED_ASSERT.test(stmt) && !ABSENCE_MATCHER.test(stmt);
5238
+ const positive = (stmt) => !claimsAbsence(stmt);
5196
5239
  const statements = liveExpectStatements(cleaned).map((s) => s.stmt);
5197
5240
  for (const stmt of statements) {
5198
5241
  if (positive(stmt))
@@ -5321,6 +5364,12 @@ function detectsObservedFailureAsExpected(code) {
5321
5364
  return FAILURE_STATUS_ASSERT.some((re) => re.test(stmt)) || hasFailedListener && FAILED_LIST_ASSERT.test(stmt);
5322
5365
  });
5323
5366
  }
5367
+ function claimsAbsence(stmt) {
5368
+ const negated = NEGATED_ASSERT_NOT.test(stmt);
5369
+ const bare = negated ? stmt.replace(NOT_BEFORE_MATCHER, ".") : stmt;
5370
+ const absenceMatcher = /\.toBeHidden\s*\(|\.toHaveCount\s*\(\s*0\s*\)/.test(bare) || VALUE_ABSENCE.test(bare) || OPTION_ABSENCE.test(bare);
5371
+ return negated !== absenceMatcher;
5372
+ }
5324
5373
  function isVacuousErrorAbsence(stmt, presence) {
5325
5374
  if (!ABSENCE_MATCHER.test(stmt))
5326
5375
  return false;
@@ -5336,19 +5385,53 @@ function isChromeTarget(stmt) {
5336
5385
  return CHROME_LOCATOR.test(stmt) && !CONTENT_ROLE.test(stmt) && !/getByText\s*\(/.test(stmt);
5337
5386
  }
5338
5387
  function countsAsContentText(stmt) {
5339
- if (!TEXT_CONTENT_MATCHER.test(stmt))
5388
+ if (!TEXT_CONTENT_MATCHER.test(stmt) || NEGATED_ASSERT.test(stmt))
5340
5389
  return false;
5341
5390
  if (isSymbolOnlyArgument(stmt, TEXT_CONTENT_MATCHER))
5342
5391
  return false;
5343
- if (!isChromeTarget(stmt))
5392
+ return onContentTarget(stmt);
5393
+ }
5394
+ function onContentTarget(stmt) {
5395
+ return !isChromeTarget(stmt) || /getByRole\s*\(\s*['"`]main['"`]/i.test(stmt);
5396
+ }
5397
+ function provesTextRemoved(stmt, presence) {
5398
+ const m = stmt.match(NEGATED_TEXT);
5399
+ if (!m || !onContentTarget(stmt))
5400
+ return false;
5401
+ const text = m[1] ?? m[2];
5402
+ if (text === void 0)
5344
5403
  return true;
5345
- return /getByRole\s*\(\s*['"`]main['"`]/i.test(stmt);
5404
+ if (!/[\p{L}\p{N}]/u.test(text))
5405
+ return false;
5406
+ return !ERROR_TEXT_WORDS.test(text) || presence().includes(text);
5346
5407
  }
5347
5408
  function isDataContentRole(stmt) {
5348
5409
  return CONTENT_ROLE.test(stmt) && !ANNOUNCE_ROLE.test(stmt);
5349
5410
  }
5411
+ function destructuresRequest(code) {
5412
+ let readTo = -1;
5413
+ for (const m of code.matchAll(ASYNC_DESTRUCTURE_OPEN)) {
5414
+ const start = m.index + m[0].length;
5415
+ if (start <= readTo)
5416
+ continue;
5417
+ let end = start;
5418
+ while (end < code.length && code[end] !== "}" && code[end] !== ")")
5419
+ end++;
5420
+ readTo = end;
5421
+ if (end === code.length)
5422
+ return false;
5423
+ if (code[end] !== "}" || !REQUEST_WORD.test(code.slice(start, end)))
5424
+ continue;
5425
+ let close = end + 1;
5426
+ while (close < code.length && /\s/.test(code[close]))
5427
+ close++;
5428
+ if (code[close] === ")")
5429
+ return true;
5430
+ }
5431
+ return false;
5432
+ }
5350
5433
  function isApiTest(code) {
5351
- const usesRequestFixture = /async\s*\(\s*\{[^})]*\brequest\b[^})]*\}\s*\)/.test(code) || /\brequest\.(get|post|put|patch|delete|head|fetch)\s*\(/.test(code);
5434
+ const usesRequestFixture = destructuresRequest(code) || /\brequest\.(get|post|put|patch|delete|head|fetch)\s*\(/.test(code);
5352
5435
  if (!usesRequestFixture)
5353
5436
  return false;
5354
5437
  const drivesUi = /\bpage\.(getBy\w+|locator|click|fill|goto|waitForURL|reload)\s*\(/.test(code) || /\.(click|fill|check|uncheck|selectOption|pressSequentially)\s*\(/.test(code);
@@ -5607,6 +5690,9 @@ function hasOnlyConstantAssertions(code) {
5607
5690
  const { constant, real } = constantAssertions(code);
5608
5691
  return constant.length > 0 && real === 0;
5609
5692
  }
5693
+ function envValueKey(name) {
5694
+ return `\0env:${name}`;
5695
+ }
5610
5696
  function enteredValues(stmts) {
5611
5697
  const values = /* @__PURE__ */ new Map();
5612
5698
  const navLines = [];
@@ -5615,24 +5701,55 @@ function enteredValues(stmts) {
5615
5701
  navLines.push(startLine);
5616
5702
  let m;
5617
5703
  ENTERED_VALUE.lastIndex = 0;
5618
- while (m = ENTERED_VALUE.exec(stmt)) {
5619
- const value = (m[1] ?? m[2] ?? m[3]).toLowerCase();
5620
- if (!values.has(value))
5621
- values.set(value, startLine);
5622
- }
5704
+ const add = (value) => {
5705
+ const lines = values.get(value);
5706
+ if (!lines)
5707
+ values.set(value, [startLine]);
5708
+ else if (lines[lines.length - 1] !== startLine)
5709
+ lines.push(startLine);
5710
+ };
5711
+ while (m = ENTERED_VALUE.exec(stmt))
5712
+ add((m[1] ?? m[2] ?? m[3]).toLowerCase());
5713
+ ENTERED_ENV.lastIndex = 0;
5714
+ while (m = ENTERED_ENV.exec(stmt))
5715
+ add(envValueKey(m[1] ?? m[2] ?? m[3] ?? m[4]));
5623
5716
  }
5624
5717
  return { values, navLines };
5625
5718
  }
5626
- function isEnteredValueEcho(stmt, entered, startLine) {
5719
+ function countBelow(lines, line) {
5720
+ let lo = 0;
5721
+ let hi = lines.length;
5722
+ while (lo < hi) {
5723
+ const mid = lo + hi >> 1;
5724
+ if (lines[mid] < line)
5725
+ lo = mid + 1;
5726
+ else
5727
+ hi = mid;
5728
+ }
5729
+ return lo;
5730
+ }
5731
+ function enteredLinesOf(stmt, entered) {
5627
5732
  const m = stmt.match(/\.toHaveValue\s*\(\s*(['"`])((?:(?!\1).)+)\1/);
5628
- if (!m)
5733
+ if (m)
5734
+ return entered.values.get(m[2].toLowerCase());
5735
+ const env = stmt.match(HAVE_VALUE_ENV);
5736
+ return env ? entered.values.get(envValueKey(env[1] ?? env[2])) : void 0;
5737
+ }
5738
+ function typedSinceLastNav(stmt, entered, startLine, lines = enteredLinesOf(stmt, entered)) {
5739
+ if (!lines || startLine === void 0)
5740
+ return false;
5741
+ const before = countBelow(lines, startLine);
5742
+ if (before === 0)
5629
5743
  return false;
5630
- const enteredAt = entered.values.get(m[2].toLowerCase());
5631
- if (enteredAt === void 0)
5744
+ return countBelow(entered.navLines, startLine) === countBelow(entered.navLines, lines[before - 1] + 1);
5745
+ }
5746
+ function isEnteredValueEcho(stmt, entered, startLine) {
5747
+ const lines = enteredLinesOf(stmt, entered);
5748
+ if (!lines)
5632
5749
  return false;
5633
- if (startLine === void 0)
5750
+ if (startLine === void 0 || lines[0] >= startLine)
5634
5751
  return true;
5635
- return !entered.navLines.some((n) => n > enteredAt && n < startLine);
5752
+ return typedSinceLastNav(stmt, entered, startLine, lines);
5636
5753
  }
5637
5754
  function isAnyValueMatcher(stmt) {
5638
5755
  if (/\.not\.toHaveValue\s*\(\s*(?:['"`]{2}|\/\^?\$?\/)/.test(stmt))
@@ -5722,6 +5839,43 @@ function hasAttributeTransition(stmts) {
5722
5839
  return true;
5723
5840
  return false;
5724
5841
  }
5842
+ function comparesWithItself(subject, tail) {
5843
+ const m = SELF_COMPARE_MATCHER.exec(tail);
5844
+ if (!m)
5845
+ return false;
5846
+ const args = balancedArguments(tail, m[0].length, MATCHER_ARGS_MAX);
5847
+ if (args === null)
5848
+ return false;
5849
+ const squash2 = (x) => x.replace(/^\s*await\s+/, "").replace(/\s+/g, "");
5850
+ const expected = squash2(args);
5851
+ return expected === squash2(m[1] === "toHaveCount" ? `${subject}.count()` : subject);
5852
+ }
5853
+ function asPlainAssertion(s) {
5854
+ const { stmt } = s;
5855
+ if (COUNT_AT_LEAST_ZERO.test(stmt))
5856
+ return [];
5857
+ const subject = extractExpectSubject(stmt);
5858
+ if (subject === null)
5859
+ return [s];
5860
+ const plain = subject.replace(/^await\s+/, "").trim();
5861
+ const subjectAt = stmt.indexOf(subject, stmt.search(EXPECT_CALL_RE));
5862
+ const tail = stmt.slice(subjectAt + subject.length).trimStart();
5863
+ const as = (rewritten) => [{ ...s, stmt: rewritten }];
5864
+ if (LOCATOR_EXPR.test(plain) && !LOCATOR_VALUE_READ.test(plain) && ALWAYS_TRUE_ON_OBJECT.test(tail))
5865
+ return [];
5866
+ if (DEFINED_VALUE_READ.test(plain) && ALWAYS_DEFINED.test(tail))
5867
+ return [];
5868
+ if (comparesWithItself(plain, tail))
5869
+ return [];
5870
+ const visible = /^(.+)\.\s*isVisible\s*\(\s*\)$/s.exec(plain);
5871
+ if (visible && IS_VISIBLE_TRUE.test(tail))
5872
+ return as(`await expect(${visible[1]}).toBeVisible();`);
5873
+ if (/^page\s*\.\s*(?:url|title)\s*\(\s*\)$/.test(plain) && PAGE_VALUE_MATCHER.test(tail)) {
5874
+ const matcher = plain.includes("url") ? "toHaveURL" : "toHaveTitle";
5875
+ return as(`await expect(page)${tail.replace(/^\)\s*\.\s*\w+\s*\(/, `.${matcher}(`)}`);
5876
+ }
5877
+ return [s];
5878
+ }
5725
5879
  function creditsOutcomeAlways(stmt, entered, startLine) {
5726
5880
  if (!OUTCOME_ALWAYS.some((re) => re.test(stmt)))
5727
5881
  return false;
@@ -5795,6 +5949,8 @@ function classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstM
5795
5949
  continue;
5796
5950
  if (isVacuousErrorAbsence(stmt, presence))
5797
5951
  continue;
5952
+ if (COUNT_ONE.test(stmt) && quotedAssertedStrings(stmt).some((t) => clicked.has(t.toLowerCase())))
5953
+ continue;
5798
5954
  if (creditsOutcomeAlways(stmt, entered, startLine))
5799
5955
  return { kind: "durable" };
5800
5956
  if (mutated && !NEGATED_ASSERT.test(stmt) && MESSAGE_SURFACE.test(stmt) && OUTCOME_TEXT.test(assertedText(stmt))) {
@@ -5804,12 +5960,15 @@ function classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstM
5804
5960
  else
5805
5961
  return { kind: "durable" };
5806
5962
  }
5807
- if (STATE_MATCHER.test(stmt) && (persistence && startLine !== void 0 ? reopenedAfterSave(startLine, persistence, persistence.reloadCalls) : reloaded))
5963
+ const retyped = typedSinceLastNav(stmt, entered, startLine);
5964
+ if (!retyped && STATE_MATCHER.test(stmt) && (persistence && startLine !== void 0 ? reopenedAfterSave(startLine, persistence, persistence.reloadCalls) : reloaded))
5808
5965
  return { kind: "durable" };
5809
- if (provesStoredControlValue(stmt, startLine, persistence))
5966
+ if (!retyped && provesStoredControlValue(stmt, startLine, persistence))
5810
5967
  return { kind: "durable" };
5811
5968
  if (countsAsContentText(stmt))
5812
5969
  return { kind: "durable" };
5970
+ if (provesTextRemoved(stmt, presence))
5971
+ return { kind: "durable" };
5813
5972
  if (mutated && VISIBILITY_MATCHER.test(stmt)) {
5814
5973
  const revealsText = GET_BY_TEXT.test(stmt) || HAS_TEXT_FILTER.test(stmt) || CONTENT_ROLE.test(stmt);
5815
5974
  if (revealsText && !isChromeTarget(stmt)) {
@@ -5876,7 +6035,7 @@ function detectOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstMut
5876
6035
  function validateAssertionStrength(code, opts = {}) {
5877
6036
  const body = stripLoginScaffolding(code);
5878
6037
  const lines = body.split("\n");
5879
- const stmts = liveExpectStatements(stripCoverageComments(body));
6038
+ const stmts = liveExpectStatements(stripCoverageComments(body)).flatMap(asPlainAssertion);
5880
6039
  const base2 = (extra) => ({
5881
6040
  apiTest: false,
5882
6041
  interacted: false,
@@ -6082,7 +6241,7 @@ function validateAssertionStrength(code, opts = {}) {
6082
6241
  signals
6083
6242
  };
6084
6243
  }
6085
- var ERROR_BANNER, OUTCOME_ALWAYS, FORM_INPUT, ANY_CLICK, NAV_LOCATOR, URL_PROOF, RELOAD, EXPECT_STMT, BLOCK_SCAFFOLD2, TEST_BLOCK_OPEN, LOCATOR_BINDING, EXPECT_OPEN, STATE_MATCHER, CHROME_LOCATOR, CONTENT_ROLE, GET_BY_TEXT, BARE_CONTAINER_ROLE, HAS_TEXT_FILTER, OUTCOME_TEXT, SUCCESS_NOTICE_TEXT, NOT_A_SUCCESS_NOTICE, ANNOUNCE_ROLE, MESSAGE_SURFACE, TEXT_CONTENT_MATCHER, VISIBILITY_MATCHER, ADDITIVE_AFFORDANCE, EXCLUDE_AFFORDANCE, EMPTY_STATE_TEXT, AUTH_START, AUTH_END, LOGIN_CALL_LINE, INBOX_START, INBOX_END, NEGATED_ASSERT, CONST_CHAIN_MAX_DEPTH, TYPED_INPUT, TITLE_LINE, FAILURE_STATUS_ASSERT, FAILED_LIST_ASSERT, ENDPOINT_DOWN, NAVIGATION_RESPONSE_VAR, DIRECT_REQUEST_VAR, CATCH_ALL_PATTERN, GUARD_HANDLER, ABSENCE_MATCHER, ERROR_TEXT_WORDS, TEXT_REGEX_ARG, ROLE_NAME_RE, INTERACT_VERB, ROLE_SIG_RE, TRANSIENT_CONTROL_ROLES, POLL_CALLBACK, CONSTANT_WORD, CONSTANT_GLUE_CHARS, WORD_CHAR, MATCHER_ARGS_MAX, MATCHER_OPEN, ENTERED_VALUE, PAGE_NAV, IN_FLIGHT_TEXT, FORM_CONTROL_LOCATOR, CONTROL_VALUE_MATCHER, COPY_CONTROL, COPIED_NOTICE, SEND_CONTROL, SEND_NOTICE, MARK_READ_CONTROL, APP_DATA_FIELD;
6244
+ var ERROR_BANNER, OUTCOME_ALWAYS, FORM_INPUT, ANY_CLICK, NAV_LOCATOR, URL_PROOF, RELOAD, EXPECT_STMT, BLOCK_SCAFFOLD2, TEST_BLOCK_OPEN, LOCATOR_BINDING, EXPECT_OPEN, STATE_MATCHER, CHROME_LOCATOR, CONTENT_ROLE, GET_BY_TEXT, BARE_CONTAINER_ROLE, HAS_TEXT_FILTER, OUTCOME_TEXT, SUCCESS_NOTICE_TEXT, NOT_A_SUCCESS_NOTICE, ANNOUNCE_ROLE, MESSAGE_SURFACE, TEXT_CONTENT_MATCHER, VISIBILITY_MATCHER, ADDITIVE_AFFORDANCE, EXCLUDE_AFFORDANCE, EMPTY_STATE_TEXT, AUTH_START, AUTH_END, LOGIN_CALL_LINE, INBOX_START, INBOX_END, NEGATED_ASSERT, NEGATED_ASSERT_NOT, CONST_CHAIN_MAX_DEPTH, TYPED_INPUT, TITLE_LINE, FAILURE_STATUS_ASSERT, FAILED_LIST_ASSERT, ENDPOINT_DOWN, NAVIGATION_RESPONSE_VAR, DIRECT_REQUEST_VAR, CATCH_ALL_PATTERN, GUARD_HANDLER, ABSENCE_MATCHER, VALUE_ABSENCE, OPTION_ABSENCE, NOT_BEFORE_MATCHER, ERROR_TEXT_WORDS, TEXT_REGEX_ARG, NEGATED_TEXT, ASYNC_DESTRUCTURE_OPEN, REQUEST_WORD, ROLE_NAME_RE, INTERACT_VERB, ROLE_SIG_RE, TRANSIENT_CONTROL_ROLES, POLL_CALLBACK, CONSTANT_WORD, CONSTANT_GLUE_CHARS, WORD_CHAR, MATCHER_ARGS_MAX, MATCHER_OPEN, ENTERED_VALUE, PAGE_NAV, ENV_READ, ENTERED_ENV, HAVE_VALUE_ENV, IN_FLIGHT_TEXT, LOCATOR_VALUE_READ, LOCATOR_EXPR, ALWAYS_TRUE_ON_OBJECT, COUNT_AT_LEAST_ZERO, DEFINED_VALUE_READ, ALWAYS_DEFINED, SELF_COMPARE_MATCHER, IS_VISIBLE_TRUE, PAGE_VALUE_MATCHER, COUNT_ONE, FORM_CONTROL_LOCATOR, CONTROL_VALUE_MATCHER, COPY_CONTROL, COPIED_NOTICE, SEND_CONTROL, SEND_NOTICE, MARK_READ_CONTROL, APP_DATA_FIELD;
6086
6245
  var init_assertion_strength = __esm({
6087
6246
  "../shared/dist/assertion-strength.js"() {
6088
6247
  "use strict";
@@ -6107,8 +6266,8 @@ var init_assertion_strength = __esm({
6107
6266
  // form field value
6108
6267
  /\.toMatch\s*\(/,
6109
6268
  // string/regex content match (e.g. textContent() vs /[2-9] selected/)
6110
- /\.toBeDisabled\s*\(/,
6111
- // a control became DISABLED — a gating/validation outcome
6269
+ /(?<!\.not\s*)\.\s*toBeDisabled\s*\(/,
6270
+ // a control became DISABLED — a gating/validation outcome (not.toBeDisabled is the toBeEnabled twin)
6112
6271
  /\.not\.toBeVisible\s*\(/,
6113
6272
  /\.toBeHidden\s*\(/
6114
6273
  // something the action removed/closed (disappearance proof)
@@ -6116,7 +6275,7 @@ var init_assertion_strength = __esm({
6116
6275
  FORM_INPUT = /\.(fill|selectOption|setInputFiles|check|uncheck|setChecked|pressSequentially)\s*\(|keyboard\.type\s*\(/;
6117
6276
  ANY_CLICK = /\.click\s*\(/;
6118
6277
  NAV_LOCATOR = /getByRole\s*\(\s*['"`](?:link|menuitem)['"`]/i;
6119
- URL_PROOF = /\.toHaveURL\s*\(|\.waitForURL\s*\(/;
6278
+ URL_PROOF = /\.toHaveURL\s*\(|\.waitForURL\s*\(|\bexpect\s*\(\s*(?:await\s+)?page\s*\.\s*url\s*\(\s*\)\s*\)|\bexpect\s*\.\s*poll\s*\(\s*(?:async\s*)?\(\s*\)\s*=>\s*(?:\{\s*return\s+)?page\s*\.\s*url\s*\(\s*\)/;
6120
6279
  RELOAD = /\.reload\s*\(/;
6121
6280
  EXPECT_STMT = /\bexpect\s*[.(]/;
6122
6281
  BLOCK_SCAFFOLD2 = /=>|\b(?:test|describe|it|beforeEach|afterEach|beforeAll|afterAll|function)\b/;
@@ -6145,6 +6304,7 @@ var init_assertion_strength = __esm({
6145
6304
  INBOX_START = /^\s*\/\/\s*>>>\s*VALIDATE_QA_INBOX/;
6146
6305
  INBOX_END = /^\s*\/\/\s*<<<\s*VALIDATE_QA_INBOX/;
6147
6306
  NEGATED_ASSERT = /\.not\s*\.\s*to[A-Z]\w*|\.toBeHidden\s*\(/;
6307
+ NEGATED_ASSERT_NOT = /\.not\s*\.\s*to[A-Z]/;
6148
6308
  CONST_CHAIN_MAX_DEPTH = 5;
6149
6309
  TYPED_INPUT = /\.(fill|type|pressSequentially|setInputFiles)\s*\(/;
6150
6310
  TITLE_LINE = /^\s*(?:test|describe)(?:\.\w+)?\s*\(/;
@@ -6160,8 +6320,14 @@ var init_assertion_strength = __esm({
6160
6320
  CATCH_ALL_PATTERN = /^(['"`])\*\*(?:\/\*)?\1$|^\/\.\*\/[a-z]*$/;
6161
6321
  GUARD_HANDLER = /\bMUTATING\.has\s*\(|blockedbyclient|Read-only guard/;
6162
6322
  ABSENCE_MATCHER = /\.not\.toBeVisible\s*\(|\.toBeHidden\s*\(|\.toHaveCount\s*\(\s*0\s*\)/;
6323
+ VALUE_ABSENCE = /\.(?:count\s*\(\s*\)[\s)]{0,10}\.(?:(?:toBe|toEqual|toStrictEqual)\s*\(\s*0\s*\)|toBeLessThan\s*\(\s*1\s*\))|isVisible\s*\(\s*\)[\s)]{0,10}\.(?:(?:toBe|toEqual|toStrictEqual)\s*\(\s*false\s*\)|toBeFalsy\s*\()|isHidden\s*\(\s*\)[\s)]{0,10}\.(?:(?:toBe|toEqual|toStrictEqual)\s*\(\s*true\s*\)|toBeTruthy\s*\())/;
6324
+ OPTION_ABSENCE = /\.(?:toBeVisible\s*\(\s*\{[^{}()]{0,200}\bvisible|toBeAttached\s*\(\s*\{[^{}()]{0,200}\battached)\s*:\s*false\b/;
6325
+ NOT_BEFORE_MATCHER = /\.not\s*\.\s*(?=to[A-Z])/g;
6163
6326
  ERROR_TEXT_WORDS = /error|fail|wrong|try again|unable|could ?n.?t|can.?t|problem|invalid|unavailable/i;
6164
6327
  TEXT_REGEX_ARG = /(?:getByText|hasText|getByRole\([^)]{0,200}name)\s*[:(]\s*(\/(?:\\.|[^/\\\n])+\/[a-z]*)/;
6328
+ NEGATED_TEXT = /\.not\s*\.\s*(?:toHaveText|toContainText)\s*\(\s*(?:['"`]([^'"`]*)['"`]|\/((?:\\.|[^/\\\n])+)\/)?/;
6329
+ ASYNC_DESTRUCTURE_OPEN = /async\s*\(\s*\{/g;
6330
+ REQUEST_WORD = /\brequest\b/;
6165
6331
  ROLE_NAME_RE = /getByRole\s*\(\s*['"`][a-z]+['"`]\s*,\s*\{[^}]*?name\s*:\s*(?:['"`]([^'"`]+)['"`]|\/([^/]+)\/)/gi;
6166
6332
  INTERACT_VERB = /\.(click|fill|check|uncheck|setChecked|selectOption|pressSequentially)\s*\(/;
6167
6333
  ROLE_SIG_RE = /getByRole\s*\(\s*['"`]([a-z]+)['"`]\s*,\s*\{[^}]*?name\s*:\s*(?:['"`]([^'"`]+)['"`]|\/([^/]+)\/)/gi;
@@ -6182,7 +6348,20 @@ var init_assertion_strength = __esm({
6182
6348
  MATCHER_OPEN = /\s*(?:\.\s*(?:not|resolves|rejects)\s*)*\.\s*[A-Za-z_$][\w$]*\s*\(/y;
6183
6349
  ENTERED_VALUE = /\.(?:fill|pressSequentially)\s*\(\s*['"`]([^'"`]+)['"`]|keyboard\.type\s*\(\s*['"`]([^'"`]+)['"`]|\.selectOption\s*\(\s*(?:\[\s*)?(?:\{\s*(?:label|value)\s*:\s*)?['"`]([^'"`]+)['"`]/g;
6184
6350
  PAGE_NAV = /\.(?:goto|reload)\s*\(/;
6351
+ ENV_READ = String.raw`process\.env(?:(?:\?\.|\.)([A-Za-z_]\w*)|(?:\?\.)?\[\s*['"]([A-Za-z_]\w*)['"]\s*\])`;
6352
+ ENTERED_ENV = new RegExp(String.raw`\.(?:fill|pressSequentially)\s*\(\s*${ENV_READ}|keyboard\.type\s*\(\s*${ENV_READ}`, "g");
6353
+ HAVE_VALUE_ENV = new RegExp(String.raw`\.toHaveValue\s*\(\s*${ENV_READ}`);
6185
6354
  IN_FLIGHT_TEXT = /^(?:(?:sending|saving|loading|searching|checking|processing|submitting|preparing|updating|please wait|working|one moment)\b[^.]{0,40}\.{2,3}|\.{3}|…)$/i;
6355
+ LOCATOR_VALUE_READ = /\.(?:count|textContent|innerText|innerHTML|inputValue|getAttribute|isVisible|isHidden|isChecked|isEnabled|isDisabled|isEditable|allTextContents|allInnerTexts|evaluate|evaluateAll|boundingBox|all)\s*\(/;
6356
+ LOCATOR_EXPR = /^(?:this\.)?page\s*\.\s*(?:getBy\w+|locator)\s*\(/;
6357
+ ALWAYS_TRUE_ON_OBJECT = /^\)\s*\.\s*(?:toBeTruthy|toBeDefined|not\s*\.\s*(?:toBeNull|toBeUndefined|toBeFalsy))\s*\(/;
6358
+ COUNT_AT_LEAST_ZERO = /\.(?:count\s*\(\s*\)|length)[\s)]{0,10}\.(?:toBeGreaterThanOrEqual\s*\(\s*0\s*\)|toBeGreaterThan\s*\(\s*-\s*1\s*\))/;
6359
+ DEFINED_VALUE_READ = /\.\s*(?:count|textContent|innerText|innerHTML|inputValue|getAttribute|title|url|isVisible|isHidden|isChecked|isEnabled|isDisabled|isEditable|allTextContents|allInnerTexts)\s*\([^()]*\)$/;
6360
+ ALWAYS_DEFINED = /^\)\s*\.\s*(?:toBeDefined|not\s*\.\s*toBeUndefined)\s*\(/;
6361
+ SELF_COMPARE_MATCHER = /^\)\s*\.\s*(toBe|toEqual|toStrictEqual|toHaveCount)\s*\(/;
6362
+ IS_VISIBLE_TRUE = /^\)*\s*\.\s*(?:toBe\s*\(\s*true\s*\)|toBeTruthy\s*\(\s*\))/;
6363
+ PAGE_VALUE_MATCHER = /^\)\s*\.\s*(?:toBe|toEqual|toStrictEqual|toMatch|toContain)\s*\(/;
6364
+ COUNT_ONE = /\.\s*toHaveCount\s*\(\s*1\s*\)/;
6186
6365
  FORM_CONTROL_LOCATOR = /getByRole\s*\(\s*['"`](?:combobox|switch|checkbox|radio|textbox|searchbox|spinbutton|slider)['"`]|getByLabel\s*\(|getByPlaceholder\s*\(/;
6187
6366
  CONTROL_VALUE_MATCHER = /\.(?:toHaveValue|toHaveText|toContainText)\s*\(|\.toHaveAttribute\s*\(\s*['"`]aria-checked['"`]/;
6188
6367
  COPY_CONTROL = /\bcopy\b/i;
@@ -6391,7 +6570,7 @@ function reportedBugWhere() {
6391
6570
  function bugReviewStatus(status) {
6392
6571
  return status === "QUARANTINED" ? "confirmed" : "needs-review";
6393
6572
  }
6394
- var USER_CANCELLED_RUN_ERROR, HEAL_PATCH_HELD_RUN_ERROR_PREFIX, RUNNER_INTERRUPT_ERROR_PREFIX, SERVER_INTERRUPT_ERROR_PREFIX, RUN_LOST_ERROR_PREFIX, RUN_INTERRUPTED_ERROR_PREFIXES, RUN_INTERRUPTION_RETRIED_MARKER, RUN_INTERRUPTION_NOT_RETRIED_MARKERS, BUG_ASSERTION_TAG, UNEXPECTED_PASS_ERROR_PREFIX, BUG_TEST_BROKEN_ERROR_PREFIX, BUG_TEST_BROKEN_REASON, EMAIL_NOT_RECEIVED_PREFIXES, ENVIRONMENTAL_ERROR_PREFIXES, ENVIRONMENTAL_ERROR_STORED_PREFIXES, BUG_SURFACE_SUPPRESSING_TAGS, QUARANTINE_CLOSE_TAGS, BUG_CANDIDATE_TAG, BUG_TEST_BROKEN_TAG;
6573
+ var USER_CANCELLED_RUN_ERROR, HEAL_PATCH_HELD_RUN_ERROR_PREFIX, RUNNER_INTERRUPT_ERROR_PREFIX, SERVER_INTERRUPT_ERROR_PREFIX, RUN_LOST_ERROR_PREFIX, RUN_INTERRUPTED_ERROR_PREFIXES, RUN_INTERRUPTION_RETRIED_MARKER, RUN_INTERRUPTION_NOT_RETRIED_MARKERS, BUG_ASSERTION_TAG, UNEXPECTED_PASS_ERROR_PREFIX, BUG_TEST_BROKEN_ERROR_PREFIX, BUG_TEST_BROKEN_REASON, TEST_DID_NOT_RUN_ERROR, EMAIL_NOT_RECEIVED_PREFIXES, ENVIRONMENTAL_ERROR_PREFIXES, ENVIRONMENTAL_ERROR_STORED_PREFIXES, BUG_SURFACE_SUPPRESSING_TAGS, QUARANTINE_CLOSE_TAGS, BUG_CANDIDATE_TAG, BUG_TEST_BROKEN_TAG;
6395
6574
  var init_run_classification = __esm({
6396
6575
  "../shared/dist/run-classification.js"() {
6397
6576
  "use strict";
@@ -6411,6 +6590,7 @@ var init_run_classification = __esm({
6411
6590
  UNEXPECTED_PASS_ERROR_PREFIX = "UNEXPECTED_PASS:";
6412
6591
  BUG_TEST_BROKEN_ERROR_PREFIX = "BUG_TEST_BROKEN:";
6413
6592
  BUG_TEST_BROKEN_REASON = "bug test broken (not a bug verdict)";
6593
+ TEST_DID_NOT_RUN_ERROR = "Test did not run (a dependency failed or the run was interrupted)";
6414
6594
  EMAIL_NOT_RECEIVED_PREFIXES = [
6415
6595
  "VERIFICATION_EMAIL_NOT_RECEIVED:",
6416
6596
  "VERIFICATION_EMAIL_HAS_NO_CODE:",
@@ -9152,6 +9332,23 @@ var init_auth_block_detector = __esm({
9152
9332
  }
9153
9333
  });
9154
9334
 
9335
+ // ../shared/dist/auth-session-stamp.js
9336
+ function parseAuthSessionStamp(value) {
9337
+ if (!value || typeof value !== "object" || Array.isArray(value))
9338
+ return null;
9339
+ const { shared, role, generation } = value;
9340
+ if (shared !== true || role !== "producer" && role !== "follower")
9341
+ return null;
9342
+ return typeof generation === "string" && AUTH_SESSION_GENERATION_RE.test(generation) ? { shared: true, role, generation } : { shared: true, role };
9343
+ }
9344
+ var AUTH_SESSION_GENERATION_RE;
9345
+ var init_auth_session_stamp = __esm({
9346
+ "../shared/dist/auth-session-stamp.js"() {
9347
+ "use strict";
9348
+ AUTH_SESSION_GENERATION_RE = /^[0-9a-z]{1,16}$/;
9349
+ }
9350
+ });
9351
+
9155
9352
  // ../shared/dist/auth-state-freshness.js
9156
9353
  function isCsrfTokenName(name) {
9157
9354
  return /csrf|xsrf|forgery|authenticity|requestverification/.test(name.toLowerCase());
@@ -10380,7 +10577,7 @@ var init_agentic_cli_runtime = __esm({
10380
10577
  GROK_CLI_DEFAULT_MODEL = "grok-4.7";
10381
10578
  GROK_CLI_DEFAULT_REASONING_EFFORT = "high";
10382
10579
  CLAUDE_CLI_DEFAULT_MODEL = "claude-sonnet-5-5";
10383
- CLAUDE_CLI_DEFAULT_EFFORT = "max";
10580
+ CLAUDE_CLI_DEFAULT_EFFORT = "high";
10384
10581
  MUSE_CLI_DEFAULT_MODEL = "muse-spark-1.3-contributor";
10385
10582
  MUSE_CLI_DEFAULT_EFFORT = "high";
10386
10583
  CODEX_CLI_DEFAULT_MODEL = "gpt-6.1-sol";
@@ -10431,9 +10628,25 @@ function isOpenCodeGoModelId(id) {
10431
10628
  function hasOpenCodeGoPrefix(id) {
10432
10629
  return (id?.trim() ?? "").startsWith(OPENCODE_GO_PREFIX);
10433
10630
  }
10631
+ function hasOpenCodeGo2Prefix(id) {
10632
+ return (id?.trim() ?? "").startsWith(OPENCODE_GO_2_PREFIX);
10633
+ }
10434
10634
  function openCodeGoWireModel(id) {
10435
10635
  const trimmed = id?.trim() ?? "";
10436
- return isOpenCodeGoModelId(trimmed) ? trimmed.slice(OPENCODE_GO_PREFIX.length) : null;
10636
+ if (!isOpenCodeGoModelId(trimmed))
10637
+ return null;
10638
+ return trimmed.slice((hasOpenCodeGo2Prefix(trimmed) ? OPENCODE_GO_2_PREFIX : OPENCODE_GO_PREFIX).length);
10639
+ }
10640
+ function isZaiModelId(id) {
10641
+ const trimmed = id?.trim() ?? "";
10642
+ return ZAI_MODEL_PATTERN.test(trimmed) && !trimmed.includes("..");
10643
+ }
10644
+ function hasZaiPrefix(id) {
10645
+ return (id?.trim() ?? "").startsWith(ZAI_PREFIX);
10646
+ }
10647
+ function zaiWireModel(id) {
10648
+ const trimmed = id?.trim() ?? "";
10649
+ return isZaiModelId(trimmed) ? trimmed.slice(ZAI_PREFIX.length) : null;
10437
10650
  }
10438
10651
  function isEngineId(value) {
10439
10652
  return CLI_ENGINE_MODEL_IDS.includes(value);
@@ -10531,7 +10744,7 @@ function museCliContributorMode(env = process.env) {
10531
10744
  const raw = (env.MUSE_CLI_CONTRIBUTOR_MODE ?? "").trim().toLowerCase();
10532
10745
  return raw === "off" || raw === "false" || raw === "0" || raw === "no" ? "off" : "on";
10533
10746
  }
10534
- var CLI_ENGINE_MODEL_IDS, BROWSER_CLI_ENGINE_IDS, PIPELINE_STEPS, CLI_ENGINE_RULES, ENGINE_NAMES, OPENROUTER_PREFIX, OPENROUTER_MODEL_PATTERN, OPENCODE_GO_PREFIX, OPENCODE_GO_MODEL_PATTERN;
10747
+ var CLI_ENGINE_MODEL_IDS, BROWSER_CLI_ENGINE_IDS, PIPELINE_STEPS, CLI_ENGINE_RULES, ENGINE_NAMES, OPENROUTER_PREFIX, OPENROUTER_MODEL_PATTERN, OPENCODE_GO_PREFIX, OPENCODE_GO_2_PREFIX, OPENCODE_GO_MODEL_PATTERN, ZAI_PREFIX, ZAI_MODEL_PATTERN;
10535
10748
  var init_engine_spec = __esm({
10536
10749
  "../shared/dist/engine-spec.js"() {
10537
10750
  "use strict";
@@ -10590,7 +10803,10 @@ var init_engine_spec = __esm({
10590
10803
  OPENROUTER_PREFIX = "openrouter:";
10591
10804
  OPENROUTER_MODEL_PATTERN = /^openrouter:[a-z0-9][a-z0-9._-]{0,40}\/[A-Za-z0-9._:-]{1,100}$/;
10592
10805
  OPENCODE_GO_PREFIX = "opencode-go:";
10593
- OPENCODE_GO_MODEL_PATTERN = /^opencode-go:[a-z0-9][a-z0-9._-]{0,100}$/;
10806
+ OPENCODE_GO_2_PREFIX = "opencode-go-2:";
10807
+ OPENCODE_GO_MODEL_PATTERN = /^opencode-go(?:-2)?:[a-z0-9][a-z0-9._-]{0,100}$/;
10808
+ ZAI_PREFIX = "zai:";
10809
+ ZAI_MODEL_PATTERN = /^zai:glm-[a-z0-9][a-z0-9._-]{0,60}$/;
10594
10810
  }
10595
10811
  });
10596
10812
 
@@ -10875,6 +11091,8 @@ var init_api_model_catalog = __esm({
10875
11091
  authCaptureModel: "Login capture",
10876
11092
  plannerModel: "Scenario Planner",
10877
11093
  plannerGateModel: "Planner Gate",
11094
+ pwAgentsHealerModel: "Test Healer (Playwright agents)",
11095
+ pwAgentsReviewModel: "Plan Review (Playwright agents)",
10878
11096
  generationModel: "Code Generation",
10879
11097
  reviewModel: "Code Review",
10880
11098
  apiTestModel: "API Test Generator",
@@ -10899,11 +11117,6 @@ var init_api_model_catalog = __esm({
10899
11117
  });
10900
11118
 
10901
11119
  // ../shared/dist/provider-chains.js
10902
- function isClaudeModel(id) {
10903
- if (/claude|anthropic/i.test(id))
10904
- return true;
10905
- return API_MODEL_CATALOG.some((m) => m.provider === "anthropic" && (m.id === id || m.apiModel === id));
10906
- }
10907
11120
  function chainKey(modelId) {
10908
11121
  const id = canonicalModelId(modelId);
10909
11122
  if (!id)
@@ -10911,34 +11124,83 @@ function chainKey(modelId) {
10911
11124
  const entry = API_MODEL_CATALOG.find((m) => m.id === id || m.apiModel === id);
10912
11125
  return entry?.id ?? id;
10913
11126
  }
11127
+ function has(map2, key) {
11128
+ return Object.prototype.hasOwnProperty.call(map2, key);
11129
+ }
10914
11130
  function providerChainFor(modelId) {
10915
11131
  const key = chainKey(modelId);
10916
- if (!key || isClaudeModel(key))
10917
- return [];
10918
- return Object.prototype.hasOwnProperty.call(PROVIDER_CHAINS, key) ? PROVIDER_CHAINS[key] : [];
11132
+ return key && has(PROVIDER_CHAINS, key) ? PROVIDER_CHAINS[key] : [];
11133
+ }
11134
+ function providerChainLeadsFor(modelId) {
11135
+ const key = chainKey(modelId);
11136
+ return key && has(PROVIDER_CHAIN_LEADS, key) ? PROVIDER_CHAIN_LEADS[key] : [];
11137
+ }
11138
+ function allChains() {
11139
+ return [...Object.entries(PROVIDER_CHAINS), ...Object.entries(PROVIDER_CHAIN_LEADS)];
10919
11140
  }
10920
11141
  function isProviderChainHopId(modelId) {
10921
11142
  const id = modelId ?? "";
10922
- return id !== "" && Object.values(PROVIDER_CHAINS).some((hops) => hops.includes(id));
11143
+ return id !== "" && allChains().some(([, hops]) => hops.includes(id));
10923
11144
  }
10924
11145
  function providerChainPrimariesForHop(hopId) {
10925
11146
  const id = hopId ?? "";
10926
11147
  if (!id)
10927
11148
  return [];
10928
- return Object.entries(PROVIDER_CHAINS).filter(([, hops]) => hops.includes(id)).map(([primary]) => primary);
11149
+ return allChains().filter(([, hops]) => hops.includes(id)).map(([primary]) => primary);
11150
+ }
11151
+ function providerChainHostOf(value, modelValue) {
11152
+ if (value === modelValue)
11153
+ return "own";
11154
+ if (hasZaiPrefix(value))
11155
+ return "zai";
11156
+ if (hasOpenCodeGo2Prefix(value))
11157
+ return "opencode-go-2";
11158
+ if (hasOpenCodeGoPrefix(value))
11159
+ return "opencode-go";
11160
+ if (hasOpenRouterPrefix(value))
11161
+ return "openrouter";
11162
+ return "own";
11163
+ }
11164
+ function providerHostPlan(modelId) {
11165
+ const key = chainKey(modelId);
11166
+ if (!key)
11167
+ return [];
11168
+ const own = { host: hasOpenRouterPrefix(key) ? "openrouter" : "own", value: key };
11169
+ const steps = [
11170
+ ...providerChainLeadsFor(key).map((value) => ({ host: providerChainHostOf(value, key), value })),
11171
+ own,
11172
+ ...providerChainFor(key).map((value) => ({ host: providerChainHostOf(value, key), value }))
11173
+ ];
11174
+ const notOffered = Object.prototype.hasOwnProperty.call(PROVIDER_HOST_NOT_OFFERED, key) ? PROVIDER_HOST_NOT_OFFERED[key] : {};
11175
+ for (const [host, reason] of Object.entries(notOffered)) {
11176
+ const at = steps.findIndex((step) => step === own) + 1;
11177
+ steps.splice(at, 0, { host, value: null, notOffered: reason });
11178
+ }
11179
+ return steps;
10929
11180
  }
10930
- var PROVIDER_CHAINS;
11181
+ var PROVIDER_CHAINS, PROVIDER_CHAIN_LEADS, PROVIDER_HOST_NOT_OFFERED;
10931
11182
  var init_provider_chains = __esm({
10932
11183
  "../shared/dist/provider-chains.js"() {
10933
11184
  "use strict";
10934
11185
  init_api_model_catalog();
11186
+ init_engine_spec();
10935
11187
  PROVIDER_CHAINS = {
10936
- "minimax-m3": ["openrouter:minimax/minimax-m3", "opencode-go:minimax-m3"],
10937
- "minimax-m3.1-flash": ["openrouter:minimax/minimax-m3.1-flash", "opencode-go:minimax-m3.1-flash"],
11188
+ "minimax-m3": ["opencode-go:minimax-m3", "openrouter:minimax/minimax-m3"],
11189
+ "minimax-m3.1-flash": ["opencode-go:minimax-m3.1-flash", "openrouter:minimax/minimax-m3.1-flash"],
10938
11190
  "muse-spark-1.3-contributor": ["openrouter:meta/muse-spark-1.3-contributor"],
10939
- "openrouter:z-ai/glm-5.3-flash": ["opencode-go:glm-5.3-flash"],
10940
- "openrouter:z-ai/glm-5.3": ["opencode-go:glm-5.3"],
10941
- "openrouter:z-ai/glm-5.2": ["opencode-go:glm-5.2"]
11191
+ "claude-haiku-5-5": ["opencode-go:claude-haiku-5-5", "openrouter:anthropic/claude-haiku-5.5"],
11192
+ "gemini-3.1-pro-preview": ["openrouter:google/gemini-3.1-pro-preview"],
11193
+ "deepseek-flash": ["opencode-go-2:deepseek-v4.1-flash", "opencode-go:deepseek-v4.1-flash", "openrouter:deepseek/deepseek-v4.1-flash"],
11194
+ "deepseek-v4-pro": ["opencode-go-2:deepseek-v4-pro", "opencode-go:deepseek-v4-pro", "openrouter:deepseek/deepseek-v4-pro"]
11195
+ };
11196
+ PROVIDER_CHAIN_LEADS = {
11197
+ "openrouter:z-ai/glm-5.3-flash": ["zai:glm-5.3-flash", "opencode-go-2:glm-5.3-flash", "opencode-go:glm-5.3-flash"],
11198
+ "openrouter:z-ai/glm-5.3": ["zai:glm-5.3", "opencode-go-2:glm-5.3", "opencode-go:glm-5.3"],
11199
+ "openrouter:z-ai/glm-5.2": ["zai:glm-5.2", "opencode-go-2:glm-5.2", "opencode-go:glm-5.2"]
11200
+ };
11201
+ PROVIDER_HOST_NOT_OFFERED = {
11202
+ "muse-spark-1.3-contributor": { "opencode-go": "OpenCode Go serves Muse only on its Responses API" },
11203
+ "gemini-3.1-pro-preview": { "opencode-go": "OpenCode Go does not serve Gemini" }
10942
11204
  };
10943
11205
  }
10944
11206
  });
@@ -12897,7 +13159,7 @@ function stateLiteralsOf(line) {
12897
13159
  const out = [];
12898
13160
  for (const m of line.matchAll(STRING_LITERAL_RE)) {
12899
13161
  const text = m[1] ?? m[2] ?? m[3] ?? "";
12900
- if (text.includes("placeholder="))
13162
+ if (PLACEHOLDER_ATTR_RE.test(text))
12901
13163
  continue;
12902
13164
  if (PLACEHOLDER_CALL_TAIL_RE.test(line.slice(Math.max(0, m.index - 40), m.index)))
12903
13165
  continue;
@@ -12993,7 +13255,7 @@ function formatReadinessPollAdvisory(findings) {
12993
13255
  const where = findings.length === 1 ? "One place" : `${findings.length} places`;
12994
13256
  return `${where} re-check a background state once and assert the finished state at once (${short(first.line, 90)} then ${short(first.assertion, 90)}). ${first.reason}`;
12995
13257
  }
12996
- var READINESS_POLL_MAX_CODE_CHARS, MAX_LINE_CHARS, MAX_FINDINGS, ASSERTION_WINDOW_LINES, MAX_BLOCK_CHARS, MAX_HEAD_CHARS, STRING_LITERAL_RE, RECHECK_NAME_RE, RETRY_NAME_RE, PENDING_STATE_RE, LOCATOR_LINE_RE, CLICK_RE, RELOAD_RE, GOTO_RE, ACTION_RE, EXPECT_RE, NEGATED_RE, PENDING_ENDED_RE, POSITIVE_MATCHER_RE, ZERO_COUNT_RE, TEST_END_RE, TEST_START_RE, POLL_OPEN_RE, PLACEHOLDER_CALL_TAIL_RE, POLL_SHAPE;
13258
+ var READINESS_POLL_MAX_CODE_CHARS, MAX_LINE_CHARS, MAX_FINDINGS, ASSERTION_WINDOW_LINES, MAX_BLOCK_CHARS, MAX_HEAD_CHARS, STRING_LITERAL_RE, RECHECK_NAME_RE, RETRY_NAME_RE, PENDING_STATE_RE, LOCATOR_LINE_RE, CLICK_RE, RELOAD_RE, GOTO_RE, ACTION_RE, EXPECT_RE, NEGATED_RE, PENDING_ENDED_RE, POSITIVE_MATCHER_RE, ZERO_COUNT_RE, TEST_END_RE, TEST_START_RE, POLL_OPEN_RE, PLACEHOLDER_ATTR_RE, PLACEHOLDER_CALL_TAIL_RE, POLL_SHAPE;
12997
13259
  var init_readiness_poll = __esm({
12998
13260
  "../shared/dist/readiness-poll.js"() {
12999
13261
  "use strict";
@@ -13006,7 +13268,7 @@ var init_readiness_poll = __esm({
13006
13268
  STRING_LITERAL_RE = /'((?:\\.|[^'\\\n]){0,300})'|"((?:\\.|[^"\\\n]){0,300})"|`((?:\\.|[^`\\\n]){0,300})`/g;
13007
13269
  RECHECK_NAME_RE = /^\s{0,10}(?:check again|check (?:status|availability|now|for updates|progress)|re-?check(?: status)?|update status|see (?:latest|updates))\s{0,10}(?:\.\.\.|…)?\s{0,10}$/i;
13008
13270
  RETRY_NAME_RE = /^\s{0,10}(?:refresh(?: (?:status|list|page|results|now))?|reload(?: (?:page|results|list))?|try again|retry|load (?:again|latest))\s{0,10}(?:\.\.\.|…)?\s{0,10}$/i;
13009
- PENDING_STATE_RE = /\b(?:searching|checking|sending|pending|processing|queued|in progress|loading|generating|calculating|preparing|verifying|syncing|refreshing|not ready|please wait|waiting)\b|\b[a-z]{3,40}(?<!th)ing(?:\s{1,3}[a-z]{1,20}){0,2}\s{0,3}(?:\.\.\.|…)\s{0,10}$/i;
13271
+ PENDING_STATE_RE = /\b(?:searching|checking|sending|pending|processing|queued|in progress|loading|generating|calculating|preparing|verifying|syncing|refreshing|not ready|please wait|waiting)\b|\b(?:saving|uploading|downloading|signing|logging|submitting|creating|updating|deleting|importing|exporting|publishing|connecting|redirecting|authenticating|installing|retrieving|fetching|analy[sz]ing|running|rendering|restarting|building|compiling|booting|provisioning|deploying|indexing|migrating|launching|initiali[sz]ing|optimi[sz]ing|converting|processing)(?:\s{1,3}[a-z]{1,20}){0,2}\s{0,3}(?:\.\.\.|…)\s{0,10}$|^\s{0,10}(?:starting|scanning|working|applying|finishing)(?:\s{1,3}[a-z]{1,20}){0,2}\s{0,3}(?:\.\.\.|…)\s{0,10}$|^\s{0,10}[a-z]{3,40}(?<!th)ing\s{0,3}(?:\.\.\.|…)\s{0,10}$/i;
13010
13272
  LOCATOR_LINE_RE = /\.(?:getBy[A-Z]\w{0,30}|locator|toHaveText|toContainText)\s{0,20}\(/;
13011
13273
  CLICK_RE = /\.(?:click|dblclick|tap)\s{0,20}\(/;
13012
13274
  RELOAD_RE = /\bpage\.reload\s{0,20}\(/;
@@ -13020,6 +13282,7 @@ var init_readiness_poll = __esm({
13020
13282
  TEST_END_RE = /^\s{0,20}\}\s{0,20}\)\s{0,20};?\s{0,20}$/;
13021
13283
  TEST_START_RE = /\btest(?:\.\w{1,20})?\s{0,20}\(/;
13022
13284
  POLL_OPEN_RE = /\bexpect(?:\.soft)?\s{0,20}\(\s{0,20}async\b|\bexpect\.poll\s{0,20}\(|\bfor\s{0,20}\(|\bwhile\s{0,20}\(|\bdo\s{0,20}\{/g;
13285
+ PLACEHOLDER_ATTR_RE = /placeholder\s{0,4}[*^$~|]?=/;
13023
13286
  PLACEHOLDER_CALL_TAIL_RE = /getByPlaceholder\s{0,20}\(\s{0,20}$/;
13024
13287
  POLL_SHAPE = "await expect(async () => { await page.reload(); await expect(<the finished state>).toBeVisible({ timeout: 1500 }); }).toPass({ timeout: 20000 });";
13025
13288
  }
@@ -13421,6 +13684,15 @@ function computes(line) {
13421
13684
  const code = line.replace(STRING_RE, '""').replace(REGEX_LITERAL_RE, "$1RX").replace(LITERAL_ARITH_RE, "N");
13422
13685
  return COMPUTE_RE.test(code) || RELATIONAL_RE.test(line);
13423
13686
  }
13687
+ function identifiersIn(line) {
13688
+ const code = line.replace(STRING_RE, '""').replace(REGEX_LITERAL_RE, "$1RX");
13689
+ return [code, ...[...line.matchAll(TEMPLATE_EXPR_RE)].map((m) => m[1])].flatMap((part) => part.match(IDENTIFIER_RE) ?? []);
13690
+ }
13691
+ function addTyped(typed, value) {
13692
+ const d = digitsOf(value);
13693
+ if (/\d/.test(d))
13694
+ typed.add(d);
13695
+ }
13424
13696
  function reasonFor4(kind, label, value) {
13425
13697
  const what = kind === "derived-value-shape-only" ? `The ${label} is checked only for its shape, so any amount passes, including a wrongly computed one.` : `The ${label} is checked against a number written into the test (${value}). That number was read off the page, so when the page computes it wrong the check still passes.`;
13426
13698
  return `${what} Instead, ${COMPUTE_SHAPE} If the number is not computed from other values (a list price, an id, a fixed fee), leave it as it is. Keep the existing checks.`;
@@ -13432,25 +13704,32 @@ function analyzeDerivedValues(rawCode) {
13432
13704
  for (const body of testBodies(rawCode)) {
13433
13705
  if (findings.length >= MAX_FINDINGS4)
13434
13706
  break;
13435
- if (body.some(computes))
13436
- continue;
13437
13707
  const typed = /* @__PURE__ */ new Set();
13438
13708
  const definitions = /* @__PURE__ */ new Map();
13709
+ const computed = /* @__PURE__ */ new Set();
13710
+ const usesComputed = (text) => identifiersIn(text).some((id) => computed.has(id));
13439
13711
  for (const line of body) {
13440
13712
  if (FILL_RE2.test(line) && !EXPECT_RE3.test(line)) {
13441
- for (const m of line.matchAll(/['"`]([^'"`\n]{0,40})['"`]/g)) {
13442
- const d = digitsOf(m[1]);
13443
- if (/\d/.test(d))
13444
- typed.add(d);
13445
- }
13713
+ for (const m of line.matchAll(QUOTED_RE))
13714
+ addTyped(typed, m[1]);
13715
+ const arg = FILL_ARG_RE.exec(line)?.[1];
13716
+ const literal = arg === void 0 ? null : LITERAL_VALUE_RE.exec(definitions.get(arg) ?? "");
13717
+ const value = literal?.slice(1).find((v) => v !== void 0);
13718
+ if (value !== void 0)
13719
+ addTyped(typed, value);
13446
13720
  }
13447
13721
  const def = DEFINITION_RE.exec(line);
13448
- if (def)
13722
+ if (def) {
13449
13723
  definitions.set(def[1], def[2]);
13724
+ if (computes(def[2]) || usesComputed(def[2]))
13725
+ computed.add(def[1]);
13726
+ }
13450
13727
  }
13451
13728
  for (const line of body) {
13452
13729
  if (!EXPECT_RE3.test(line) || !VALUE_MATCHER_RE2.test(line) || /\.not\s{0,20}\./.test(line))
13453
13730
  continue;
13731
+ if (computes(line) || usesComputed(line))
13732
+ continue;
13454
13733
  const subject = EXPECT_SUBJECT_RE.exec(line)?.[1];
13455
13734
  const label = DERIVED_WORD_RE.exec(`${line} ${(subject && definitions.get(subject)) ?? ""}`)?.[0];
13456
13735
  if (!label)
@@ -13480,7 +13759,7 @@ function formatDerivedValueAdvisory(findings) {
13480
13759
  const where = findings.length === 1 ? "One computed value is" : `${findings.length} computed values are`;
13481
13760
  return `${where} checked against a copied number or only its shape (${short4(first.line, 90)}). ${first.reason}`;
13482
13761
  }
13483
- var MAX_FINDINGS4, EXPECT_RE3, DERIVED_WORD_RE, VALUE_MATCHER_RE2, MONEY_TOKEN_RE, SHAPE_ARG_RE, FILL_RE2, EXPECT_MESSAGE_RE, STRING_RE, REGEX_LITERAL_RE, COMPUTE_RE, RELATIONAL_RE, DEFINITION_RE, EXPECT_SUBJECT_RE, LITERAL_ARITH_RE, COMPUTE_SHAPE;
13762
+ var MAX_FINDINGS4, EXPECT_RE3, DERIVED_WORD_RE, VALUE_MATCHER_RE2, MONEY_TOKEN_RE, SHAPE_ARG_RE, FILL_RE2, EXPECT_MESSAGE_RE, STRING_RE, REGEX_LITERAL_RE, COMPUTE_RE, RELATIONAL_RE, DEFINITION_RE, EXPECT_SUBJECT_RE, LITERAL_ARITH_RE, TEMPLATE_EXPR_RE, IDENTIFIER_RE, QUOTED_RE, FILL_ARG_RE, LITERAL_VALUE_RE, COMPUTE_SHAPE;
13484
13763
  var init_derived_value_check = __esm({
13485
13764
  "../shared/dist/derived-value-check.js"() {
13486
13765
  "use strict";
@@ -13500,6 +13779,11 @@ var init_derived_value_check = __esm({
13500
13779
  DEFINITION_RE = /\b(?:const|let)\s{1,10}([\w$]{1,60})\s{0,10}=\s{0,10}([^\n]{0,300})/;
13501
13780
  EXPECT_SUBJECT_RE = /\bexpect(?:\.soft)?\s{0,20}\(\s{0,20}([\w$]{1,60})/;
13502
13781
  LITERAL_ARITH_RE = /\b\d[\d_.]{0,15}(?:\s{0,5}[*/+-]\s{0,5}\d[\d_.]{0,15}){1,8}\b/g;
13782
+ TEMPLATE_EXPR_RE = /\$\{([^{}\n]{0,200})\}/g;
13783
+ IDENTIFIER_RE = /[A-Za-z_$][\w$]{0,60}/g;
13784
+ QUOTED_RE = /['"`]([^'"`\n]{0,40})['"`]/g;
13785
+ FILL_ARG_RE = /\.(?:fill|type|pressSequentially|selectOption)\s{0,20}\(\s{0,20}([A-Za-z_$][\w$]{0,60})\s{0,20}[,)]/;
13786
+ LITERAL_VALUE_RE = /^\s{0,10}(?:'([^'\n]{0,40})'|"([^"\n]{0,40})"|`([^`$\n]{0,40})`|(\d[\d_,]{0,15}(?:\.\d{1,4})?))\s{0,10};?\s{0,10}$/;
13503
13787
  COMPUTE_SHAPE = "compute the expected value in the test from its inputs (the values the test typed, or each input read from the page) and compare: const toNumber = (s) => Number(s.replace(/[^\\d.-]/g, '')); const unit = toNumber(await <unit price locator>.innerText()); then expect(toNumber(await <shown value locator>.innerText())).toBeCloseTo(unit * quantity, 2); for several lines, read them all and sum them with reduce. For a comma-decimal price like \u20AC1.234,56, drop the dots and turn the comma into a point before Number, since the replace above would read it as 1.23456.";
13504
13788
  }
13505
13789
  });
@@ -15534,6 +15818,99 @@ function formatStaleAfterSubmitAdvisory(rawCode) {
15534
15818
  const more = described.length > 3 ? ` (+${described.length - 3} more)` : "";
15535
15819
  return `stale-after-submit: ${described.slice(0, 3).join("; ")}${more}; these pass before the request lands and still pass if the server rejects or ignores the save. Wait for the result instead: page.waitForResponse around the click, or assert something the submit creates (the new row, the confirmation message, a path with an end anchor such as /\\/orders\\/\\d+$/)`;
15536
15820
  }
15821
+ function regexLiteralEnd4(text, at) {
15822
+ let inClass = false;
15823
+ for (let i = at + 1; i < text.length; i++) {
15824
+ const ch = text[i];
15825
+ if (ch === "\n")
15826
+ return -1;
15827
+ if (ch === "\\") {
15828
+ i++;
15829
+ continue;
15830
+ }
15831
+ if (inClass) {
15832
+ if (ch === "]")
15833
+ inClass = false;
15834
+ continue;
15835
+ }
15836
+ if (ch === "[") {
15837
+ inClass = true;
15838
+ continue;
15839
+ }
15840
+ if (ch === "/")
15841
+ return i + 1;
15842
+ }
15843
+ return -1;
15844
+ }
15845
+ function startsWithRegexLiteral(text) {
15846
+ const t = text.trimStart();
15847
+ return t[0] === "/" && t[1] !== "/" && t[1] !== "*" && regexLiteralEnd4(t, 0) !== -1;
15848
+ }
15849
+ function afterFirstArg(args) {
15850
+ let depth = 0;
15851
+ let quote = null;
15852
+ for (let i = 0; i < args.length; i++) {
15853
+ const ch = args[i];
15854
+ if (quote) {
15855
+ if (ch === "\\") {
15856
+ i++;
15857
+ continue;
15858
+ }
15859
+ if (ch === quote)
15860
+ quote = null;
15861
+ continue;
15862
+ }
15863
+ if (ch === '"' || ch === "'" || ch === "`") {
15864
+ quote = ch;
15865
+ continue;
15866
+ }
15867
+ if (ch === "(" || ch === "[" || ch === "{")
15868
+ depth++;
15869
+ else if (ch === ")" || ch === "]" || ch === "}")
15870
+ depth--;
15871
+ else if (ch === "," && depth === 0)
15872
+ return args.slice(i + 1);
15873
+ }
15874
+ return "";
15875
+ }
15876
+ function analyzeRegexMatchers(rawCode) {
15877
+ if (!rawCode || typeof rawCode !== "string")
15878
+ return [];
15879
+ const code = stripComments2(rawCode.slice(0, MAX_LINT_INPUT));
15880
+ const out = [];
15881
+ const re = /\bexpect(?:\.soft)?\s{0,20}\(/g;
15882
+ let m;
15883
+ let examined = 0;
15884
+ let line = 1;
15885
+ let lineAt2 = 0;
15886
+ while ((m = re.exec(code)) !== null && examined++ < MAX_CALLS && out.length < MAX_REGEX_MATCHER_FINDINGS) {
15887
+ const subj = readBalanced(code, m.index + m[0].length);
15888
+ if (!subj)
15889
+ continue;
15890
+ const mm = /^\s{0,20}(\.\s{0,20}not)?\s{0,20}\.\s{0,20}(\w{1,40})\s{0,20}\(/.exec(code.slice(subj.end + 1, subj.end + 1 + 80));
15891
+ if (!mm || !REGEX_EQUALITY_MATCHERS.has(mm[2]))
15892
+ continue;
15893
+ const args = readBalanced(code, subj.end + 1 + mm[0].length);
15894
+ if (!args)
15895
+ continue;
15896
+ const expected = mm[2] === "toHaveJSProperty" ? afterFirstArg(args.text) : args.text;
15897
+ if (!startsWithRegexLiteral(expected))
15898
+ continue;
15899
+ if (mm[2] !== "toHaveJSProperty" && mm[2] !== "toContain" && (startsWithRegexLiteral(subj.text) || /^new\s+RegExp\b/.test(subj.text.trim())))
15900
+ continue;
15901
+ for (let i = code.indexOf("\n", lineAt2); i !== -1 && i < m.index; i = code.indexOf("\n", i + 1)) {
15902
+ line++;
15903
+ lineAt2 = i + 1;
15904
+ }
15905
+ out.push({ line, matcher: mm[2], negated: mm[1] !== void 0 });
15906
+ }
15907
+ return out;
15908
+ }
15909
+ function formatRegexMatcherNote(findings) {
15910
+ const lines = findings.map((f) => `Line ${f.line}: .${f.negated ? "not." : ""}${f.matcher}(\u2026 /regex/ \u2026) ${f.negated ? "always passes (a regex never equals the value), so it checks nothing" : "can never pass: this matcher compares by equality and a regex never equals a value"}.`);
15911
+ return `${lines.join("\n")}
15912
+ A regex only works in toMatch, toHaveText, toContainText, toHaveValue and similar text matchers. For a DOM property read it first: expect(await loc.evaluate((n) => n.<prop>)).toMatch(/re/). Or give toHaveJSProperty the exact string (or boolean) the page shows. Keep every other line as-is.`;
15913
+ }
15537
15914
  function lintTestQuality(rawCode, opts = {}) {
15538
15915
  if (!rawCode || typeof rawCode !== "string")
15539
15916
  return [];
@@ -15541,6 +15918,10 @@ function lintTestQuality(rawCode, opts = {}) {
15541
15918
  return lintTestData(rawCode, { pageContacts: opts.pageContacts });
15542
15919
  if (opts.only === "test-data-blocking")
15543
15920
  return analyzeTestData(rawCode, { pageContacts: opts.pageContacts }).blocking;
15921
+ if (opts.only === "regex-matcher") {
15922
+ const found = analyzeRegexMatchers(rawCode);
15923
+ return found.length > 0 ? [formatRegexMatcherNote(found)] : [];
15924
+ }
15544
15925
  const warnings = [];
15545
15926
  if (rawCode.length > MAX_LINT_INPUT) {
15546
15927
  warnings.push(`The code is ${Math.round(rawCode.length / 1024)} KB; the quality lint checked only the first ${MAX_LINT_INPUT / 1e3} KB. Split it into smaller tests (one behaviour per test).`);
@@ -15815,7 +16196,7 @@ function specItemsFromTestPlans(testPlans) {
15815
16196
  }
15816
16197
  return [...new Set(out)].slice(0, 200);
15817
16198
  }
15818
- var READ_ONLY_TAGS, PRODUCTION_READ_ONLY_GUARD_TEMPLATE, HOST_AGNOSTIC_URL_TEMPLATE, TEST_QUALITY_CONVENTIONS, NON_PROD_HOST_LABEL, NON_PROD_HOST_TOKEN, TRANSIENT_TEXT, STRING_LITERAL, FIRST_LITERAL, GET_BY_TEXT_LITERAL2, ROLE_NAME_LITERAL2, MAX_LINT_INPUT, MAX_BALANCED_SCAN, MAX_CALLS, MAX_SEEN_SCAN, ACTION_CALL, BY_NAME_LOCATOR, ACTION_AFTER, MAX_CONTACTS, MAX_SNAPSHOT_SCAN, PHONE_IN_TEXT, EMAIL_IN_TEXT, TEL_HREF, MAILTO_HREF, FIELD_LINE, INBOX_EMAIL_READ, MAIL_READ_CALL, RESERVED_EMAIL_TLD, PHONE_LABEL, NON_PHONE_NUMBER_LABEL, IDENTITY_LABEL, LOOKUP_LABEL, NON_NAME_SUFFIX_LABEL, DATE_LIKE, SIGNUP_ACTION_NAME, SIGNUP_SUBMIT_NAME, LOGIN_ACTION_NAME, SIGNUP_GOTO, LOGIN_GOTO, MINTED_INBOX_ALIAS, STAMP_EVAL, RECORDING_VALUE_PLACEHOLDERS, NEGATIVE_TEST_TITLE, NEGATIVE_SIGNUP_ASSERT, STORED_LOGIN_RE, CONFIRM_CLICK_RE, SAVE_UPDATE_RE, NOT_A_CONFIRM_RE, ENTITY_WORDS, CREATE_ENTITY_CLICK_RE, RESTORE_CLICK_RE, MAX_ACCOUNT_ACTIONS, MAX_TRY_BLOCKS, MAX_STATEMENT_LOOKBACK, MAX_FINDINGS5, MAX_TRY_BODY, AUTH_REGION_START, AUTH_REGION_END, INBOX_REGION_START, INBOX_REGION_END, ACCOUNT_ROUTE_RE, ENTITY_WORD_RES, PERSIST_CALL_RE, FILL_IDENT_ARG_RE, PERSIST_ARGS_RE, HOST_IN_URL_ARG, URL_WAIT_TOKEN, GLOB_ESCAPED, URL_WAIT_MAX_PATH, URL_WAIT_MAX_GLOB_STARS, UNREACHED_MAX_PATHS, UNREACHED_MATCH_BUDGET, STALE_TOKEN, RESULT_WAIT, WRITE_CALL_PRESENT, SUBMIT_CALL_PRESENT, TEST_CALL, VALUE_WRITE_CALLS, SUBMIT_CALLS, DISTINCT_PAGE_CALLS, OWN_CONTROL_MATCHERS, OUTCOME_CONTENT_MATCHERS, OUTCOME_STATE_MATCHERS, ANY_CONTENT_ARG, ROOT_SUBJECT, LITERAL_SUBJECT, MATCHER_AFTER_EXPECT, STALE_MAX_EVENTS, CHECKED, UNCHECKED, squash, NOT_JUDGED, STALE_REASON_TEXT, LIVE_WRITE_NAME, BUNDLED_CHECKS_BEFORE_WRITE, STOP, SYNONYMS, AREA_TOKENS;
16199
+ var READ_ONLY_TAGS, PRODUCTION_READ_ONLY_GUARD_TEMPLATE, HOST_AGNOSTIC_URL_TEMPLATE, TEST_QUALITY_CONVENTIONS, NON_PROD_HOST_LABEL, NON_PROD_HOST_TOKEN, TRANSIENT_TEXT, STRING_LITERAL, FIRST_LITERAL, GET_BY_TEXT_LITERAL2, ROLE_NAME_LITERAL2, MAX_LINT_INPUT, MAX_BALANCED_SCAN, MAX_CALLS, MAX_SEEN_SCAN, ACTION_CALL, BY_NAME_LOCATOR, ACTION_AFTER, MAX_CONTACTS, MAX_SNAPSHOT_SCAN, PHONE_IN_TEXT, EMAIL_IN_TEXT, TEL_HREF, MAILTO_HREF, FIELD_LINE, INBOX_EMAIL_READ, MAIL_READ_CALL, RESERVED_EMAIL_TLD, PHONE_LABEL, NON_PHONE_NUMBER_LABEL, IDENTITY_LABEL, LOOKUP_LABEL, NON_NAME_SUFFIX_LABEL, DATE_LIKE, SIGNUP_ACTION_NAME, SIGNUP_SUBMIT_NAME, LOGIN_ACTION_NAME, SIGNUP_GOTO, LOGIN_GOTO, MINTED_INBOX_ALIAS, STAMP_EVAL, RECORDING_VALUE_PLACEHOLDERS, NEGATIVE_TEST_TITLE, NEGATIVE_SIGNUP_ASSERT, STORED_LOGIN_RE, CONFIRM_CLICK_RE, SAVE_UPDATE_RE, NOT_A_CONFIRM_RE, ENTITY_WORDS, CREATE_ENTITY_CLICK_RE, RESTORE_CLICK_RE, MAX_ACCOUNT_ACTIONS, MAX_TRY_BLOCKS, MAX_STATEMENT_LOOKBACK, MAX_FINDINGS5, MAX_TRY_BODY, AUTH_REGION_START, AUTH_REGION_END, INBOX_REGION_START, INBOX_REGION_END, ACCOUNT_ROUTE_RE, ENTITY_WORD_RES, PERSIST_CALL_RE, FILL_IDENT_ARG_RE, PERSIST_ARGS_RE, HOST_IN_URL_ARG, URL_WAIT_TOKEN, GLOB_ESCAPED, URL_WAIT_MAX_PATH, URL_WAIT_MAX_GLOB_STARS, UNREACHED_MAX_PATHS, UNREACHED_MATCH_BUDGET, STALE_TOKEN, RESULT_WAIT, WRITE_CALL_PRESENT, SUBMIT_CALL_PRESENT, TEST_CALL, VALUE_WRITE_CALLS, SUBMIT_CALLS, DISTINCT_PAGE_CALLS, OWN_CONTROL_MATCHERS, OUTCOME_CONTENT_MATCHERS, OUTCOME_STATE_MATCHERS, ANY_CONTENT_ARG, ROOT_SUBJECT, LITERAL_SUBJECT, MATCHER_AFTER_EXPECT, STALE_MAX_EVENTS, CHECKED, UNCHECKED, squash, NOT_JUDGED, STALE_REASON_TEXT, LIVE_WRITE_NAME, BUNDLED_CHECKS_BEFORE_WRITE, MAX_REGEX_MATCHER_FINDINGS, REGEX_EQUALITY_MATCHERS, STOP, SYNONYMS, AREA_TOKENS;
15819
16200
  var init_test_authoring_quality = __esm({
15820
16201
  "../shared/dist/test-authoring-quality.js"() {
15821
16202
  "use strict";
@@ -16047,6 +16428,8 @@ var init_test_authoring_quality = __esm({
16047
16428
  };
16048
16429
  LIVE_WRITE_NAME = /\b(?:submit|place|book|reserve|confirm|pay|send|checkout|order|register|sign\s?up|create account)\b/i;
16049
16430
  BUNDLED_CHECKS_BEFORE_WRITE = 5;
16431
+ MAX_REGEX_MATCHER_FINDINGS = 10;
16432
+ REGEX_EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual", "toContain", "toHaveJSProperty"]);
16050
16433
  STOP = /* @__PURE__ */ new Set([
16051
16434
  "a",
16052
16435
  "an",
@@ -16275,6 +16658,19 @@ var init_fence_runs = __esm({
16275
16658
  }
16276
16659
  });
16277
16660
 
16661
+ // ../shared/dist/trailing-slashes.js
16662
+ function stripTrailingSlashes(value) {
16663
+ let end = value.length;
16664
+ while (end > 0 && value.charCodeAt(end - 1) === 47)
16665
+ end--;
16666
+ return end === value.length ? value : value.slice(0, end);
16667
+ }
16668
+ var init_trailing_slashes = __esm({
16669
+ "../shared/dist/trailing-slashes.js"() {
16670
+ "use strict";
16671
+ }
16672
+ });
16673
+
16278
16674
  // ../shared/dist/survey-bug-signature.js
16279
16675
  function normalizeWords(text) {
16280
16676
  return text.toLowerCase().replace(UUID, " id ").replace(PREFIXED_ID, " id ").replace(HEX_RUN, (run) => /\d/.test(run) ? " id " : run).replace(NUMBER_RUN, " # ").replace(/[^\p{L}\p{N}#]+/gu, " ").replace(/\s+/g, " ").trim();
@@ -16285,7 +16681,7 @@ function normalizeBugPath(route) {
16285
16681
  if (hash >= 0 && path[hash + 1] !== "/")
16286
16682
  path = path.slice(0, hash);
16287
16683
  const segments = path.toLowerCase().split("/").map((segment) => /\d/.test(segment) ? ":id" : segment);
16288
- const joined = segments.join("/").replace(/\/+$/, "");
16684
+ const joined = stripTrailingSlashes(segments.join("/"));
16289
16685
  return joined || (path.startsWith("/") ? "/" : "");
16290
16686
  }
16291
16687
  function isGenericConsoleMessage(message) {
@@ -16419,6 +16815,7 @@ var SIGNATURE_SOURCE_MAX_CHARS, UUID, PREFIXED_ID, HEX_RUN, NUMBER_RUN, GENERIC_
16419
16815
  var init_survey_bug_signature = __esm({
16420
16816
  "../shared/dist/survey-bug-signature.js"() {
16421
16817
  "use strict";
16818
+ init_trailing_slashes();
16422
16819
  SIGNATURE_SOURCE_MAX_CHARS = 800;
16423
16820
  UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g;
16424
16821
  PREFIXED_ID = /\b[a-z]{1,8}[-_]\d+\b/g;
@@ -17699,9 +18096,9 @@ function lastLocatorLabels(chain) {
17699
18096
  if (t)
17700
18097
  labels.push(t[1]);
17701
18098
  }
17702
- const has = optionText(last.args, HAS_TEXT_OPTION_RE);
17703
- if (has !== null)
17704
- labels.push(has);
18099
+ const has2 = optionText(last.args, HAS_TEXT_OPTION_RE);
18100
+ if (has2 !== null)
18101
+ labels.push(has2);
17705
18102
  }
17706
18103
  return labels.map((l) => l.replace(/^[\s^(?:]+/, "").trim());
17707
18104
  }
@@ -18458,14 +18855,17 @@ var init_promotion_quality_gate = __esm({
18458
18855
  SOURCE_RANK = { generator: 0, classifier: 0, healer: 1, human: 2 };
18459
18856
  strengthCheck = {
18460
18857
  id: "assertion-strength",
18461
- run({ code, strengthGate, flagContradictedAdditions }) {
18858
+ run({ code, tags, strengthGate, flagContradictedAdditions }) {
18462
18859
  const verdict = validateAssertionStrength(code, { flagContradictedAdditions: flagContradictedAdditions === true });
18463
18860
  if (verdict.severity === "route-bug")
18464
18861
  return [{ check: "route-bug" }];
18465
- if (verdict.severity !== "block")
18862
+ const authDowngrade = verdict.severity === "downgrade" && tags.some((t) => t.toLowerCase() === "@auth");
18863
+ if (verdict.severity !== "block" && !authDowngrade)
18466
18864
  return [];
18467
18865
  const revealed = strengthGate?.severity === "none" && strengthGate.revealEvidence === "revealed" && strengthGate.source !== "heal";
18468
- return revealed ? [] : [{ check: "strength-block" }];
18866
+ if (revealed)
18867
+ return [];
18868
+ return [{ check: authDowngrade ? "strength-downgrade-auth" : "strength-block" }];
18469
18869
  }
18470
18870
  };
18471
18871
  STRING_CONST = /\b(?:const|let|var)\s{1,20}([A-Za-z_$][\w$]{0,60})\s{0,20}=\s{0,20}(?:'([^'\\\n]{0,300})'|"([^"\\\n]{0,300})"|`([^`\\$\n]{0,300})`)\s{0,20}[;\n]/g;
@@ -18872,6 +19272,7 @@ __export(dist_exports, {
18872
19272
  AUDIO_CHUNK_DURATION_MS: () => AUDIO_CHUNK_DURATION_MS,
18873
19273
  AUTH_PATH_SIGNATURE: () => AUTH_PATH_SIGNATURE,
18874
19274
  AUTH_PROVIDER_HOST_SIGNATURES: () => AUTH_PROVIDER_HOST_SIGNATURES,
19275
+ AUTH_SESSION_GENERATION_RE: () => AUTH_SESSION_GENERATION_RE,
18875
19276
  AUTH_STATE_EXPIRY_SKEW_MS: () => AUTH_STATE_EXPIRY_SKEW_MS,
18876
19277
  AUTH_TAG_COOKIE_STATE: () => AUTH_TAG_COOKIE_STATE,
18877
19278
  AUTH_TAG_LOGIN_BEARER: () => AUTH_TAG_LOGIN_BEARER,
@@ -19004,6 +19405,8 @@ __export(dist_exports, {
19004
19405
  LIVE_FRAME_STALE_MS: () => LIVE_FRAME_STALE_MS,
19005
19406
  LIVE_FRAME_UNFOCUSED_INTERVAL_MS: () => LIVE_FRAME_UNFOCUSED_INTERVAL_MS,
19006
19407
  LIVE_THUMBNAIL_MAX_BASE64_BYTES: () => LIVE_THUMBNAIL_MAX_BASE64_BYTES,
19408
+ MAX_BALANCED_SCAN: () => MAX_BALANCED_SCAN,
19409
+ MAX_CALLS: () => MAX_CALLS,
19007
19410
  MAX_CREDIT_TOPUP_CENTS: () => MAX_CREDIT_TOPUP_CENTS,
19008
19411
  MAX_DEEPLINK_LENGTH: () => MAX_DEEPLINK_LENGTH,
19009
19412
  MAX_EMAIL_ADDRESS_LENGTH: () => MAX_EMAIL_ADDRESS_LENGTH,
@@ -19048,6 +19451,7 @@ __export(dist_exports, {
19048
19451
  MUSE_ENGINE_DEFAULT_MODEL: () => MUSE_ENGINE_DEFAULT_MODEL,
19049
19452
  MUSE_ENGINE_MODELS: () => MUSE_ENGINE_MODELS,
19050
19453
  NOREPLY_EMAIL: () => NOREPLY_EMAIL,
19454
+ OPENCODE_GO_2_PREFIX: () => OPENCODE_GO_2_PREFIX,
19051
19455
  OPENCODE_GO_MODEL_PATTERN: () => OPENCODE_GO_MODEL_PATTERN,
19052
19456
  OPENCODE_GO_PREFIX: () => OPENCODE_GO_PREFIX,
19053
19457
  OPENROUTER_MAX_CALL_COST_USD: () => OPENROUTER_MAX_CALL_COST_USD,
@@ -19083,6 +19487,8 @@ __export(dist_exports, {
19083
19487
  PROMOTION_GATE_MAX_CODE_CHARS: () => PROMOTION_GATE_MAX_CODE_CHARS,
19084
19488
  PROMOTION_QUALITY_CHECKS: () => PROMOTION_QUALITY_CHECKS,
19085
19489
  PROVIDER_CHAINS: () => PROVIDER_CHAINS,
19490
+ PROVIDER_CHAIN_LEADS: () => PROVIDER_CHAIN_LEADS,
19491
+ PROVIDER_HOST_NOT_OFFERED: () => PROVIDER_HOST_NOT_OFFERED,
19086
19492
  PUBLIC_PLANS: () => PUBLIC_PLANS,
19087
19493
  QUARANTINE_CLOSE_TAGS: () => QUARANTINE_CLOSE_TAGS,
19088
19494
  READINESS_POLL_MAX_CODE_CHARS: () => READINESS_POLL_MAX_CODE_CHARS,
@@ -19121,6 +19527,7 @@ __export(dist_exports, {
19121
19527
  SURVEY_NOTES_RENDER_MAX_CHARS: () => SURVEY_NOTES_RENDER_MAX_CHARS,
19122
19528
  SURVEY_NOTE_KEYS: () => SURVEY_NOTE_KEYS,
19123
19529
  SUSPICIOUS_PASS_TAG: () => SUSPICIOUS_PASS_TAG,
19530
+ TEST_DID_NOT_RUN_ERROR: () => TEST_DID_NOT_RUN_ERROR,
19124
19531
  TEST_QUALITY_CONVENTIONS: () => TEST_QUALITY_CONVENTIONS,
19125
19532
  TEST_USER_ENV_KEYS: () => TEST_USER_ENV_KEYS,
19126
19533
  TEST_VARIABLE_SECRET_KEY_PATTERN: () => TEST_VARIABLE_SECRET_KEY_PATTERN,
@@ -19136,6 +19543,8 @@ __export(dist_exports, {
19136
19543
  VOICE_PREVIEW_SAMPLE: () => VOICE_PREVIEW_SAMPLE,
19137
19544
  WEB_PROXY_CHAIN_HEADER: () => WEB_PROXY_CHAIN_HEADER,
19138
19545
  WITHHELD_CREDENTIAL_TEXT: () => WITHHELD_CREDENTIAL_TEXT,
19546
+ ZAI_MODEL_PATTERN: () => ZAI_MODEL_PATTERN,
19547
+ ZAI_PREFIX: () => ZAI_PREFIX,
19139
19548
  accumulateStatements: () => accumulateStatements,
19140
19549
  adoptBrokerFailover: () => adoptBrokerFailover,
19141
19550
  aiCostToCreditCents: () => aiCostToCreditCents,
@@ -19144,6 +19553,7 @@ __export(dist_exports, {
19144
19553
  analyzeMobileSelectorQuality: () => analyzeMobileSelectorQuality,
19145
19554
  analyzePersistenceReread: () => analyzePersistenceReread,
19146
19555
  analyzeReadinessPolling: () => analyzeReadinessPolling,
19556
+ analyzeRegexMatchers: () => analyzeRegexMatchers,
19147
19557
  analyzeSharedAccountUse: () => analyzeSharedAccountUse,
19148
19558
  analyzeStaleAfterSubmit: () => analyzeStaleAfterSubmit,
19149
19559
  analyzeTestData: () => analyzeTestData,
@@ -19307,6 +19717,7 @@ __export(dist_exports, {
19307
19717
  formatPersistenceRereadAdvisory: () => formatPersistenceRereadAdvisory,
19308
19718
  formatPoolBudgetLine: () => formatPoolBudgetLine,
19309
19719
  formatReadinessPollAdvisory: () => formatReadinessPollAdvisory,
19720
+ formatRegexMatcherNote: () => formatRegexMatcherNote,
19310
19721
  formatStaleAfterSubmitAdvisory: () => formatStaleAfterSubmitAdvisory,
19311
19722
  formatSuspiciousExpectation: () => formatSuspiciousExpectation,
19312
19723
  formatUrlWaitAdvisory: () => formatUrlWaitAdvisory,
@@ -19345,12 +19756,14 @@ __export(dist_exports, {
19345
19756
  hasEncodedRequestBody: () => hasEncodedRequestBody,
19346
19757
  hasEngineSpecParts: () => hasEngineSpecParts,
19347
19758
  hasOnlyConstantAssertions: () => hasOnlyConstantAssertions,
19759
+ hasOpenCodeGo2Prefix: () => hasOpenCodeGo2Prefix,
19348
19760
  hasOpenCodeGoPrefix: () => hasOpenCodeGoPrefix,
19349
19761
  hasOpenRouterPrefix: () => hasOpenRouterPrefix,
19350
19762
  hasPlatformLocator: () => hasPlatformLocator,
19351
19763
  hasReadOnlyMarker: () => hasReadOnlyMarker,
19352
19764
  hasSurveyNotes: () => hasSurveyNotes,
19353
19765
  hasTestFailContract: () => hasTestFailContract,
19766
+ hasZaiPrefix: () => hasZaiPrefix,
19354
19767
  healMobileTestSteps: () => healMobileTestSteps,
19355
19768
  healthRunWhere: () => healthRunWhere,
19356
19769
  heldCodeRecord: () => heldCodeRecord,
@@ -19454,6 +19867,7 @@ __export(dist_exports, {
19454
19867
  isValidSttProvider: () => isValidSttProvider,
19455
19868
  isValidTtsModel: () => isValidTtsModel,
19456
19869
  isValidTtsVoiceId: () => isValidTtsVoiceId,
19870
+ isZaiModelId: () => isZaiModelId,
19457
19871
  jsEscapedForms: () => jsEscapedForms,
19458
19872
  jsonStructureRefusalOf: () => jsonStructureRefusalOf,
19459
19873
  jsonStructureVerify: () => jsonStructureVerify,
@@ -19502,6 +19916,7 @@ __export(dist_exports, {
19502
19916
  parseApiCardModelUpdate: () => parseApiCardModelUpdate,
19503
19917
  parseAppTimezone: () => parseAppTimezone,
19504
19918
  parseAuditGroupScopeId: () => parseAuditGroupScopeId,
19919
+ parseAuthSessionStamp: () => parseAuthSessionStamp,
19505
19920
  parseBoolFlag: () => parseBoolFlag,
19506
19921
  parseDbPoolSize: () => parseDbPoolSize,
19507
19922
  parseDeepgramListenResponse: () => parseDeepgramListenResponse,
@@ -19545,7 +19960,11 @@ __export(dist_exports, {
19545
19960
  profileKeyRoute: () => profileKeyRoute,
19546
19961
  projectAppHosts: () => projectAppHosts,
19547
19962
  providerChainFor: () => providerChainFor,
19963
+ providerChainHostOf: () => providerChainHostOf,
19964
+ providerChainLeadsFor: () => providerChainLeadsFor,
19548
19965
  providerChainPrimariesForHop: () => providerChainPrimariesForHop,
19966
+ providerHostPlan: () => providerHostPlan,
19967
+ readBalanced: () => readBalanced,
19549
19968
  readChatFailover: () => readChatFailover,
19550
19969
  readChatReasoningTokens: () => readChatReasoningTokens,
19551
19970
  readChatUsage: () => readChatUsage,
@@ -19628,6 +20047,7 @@ __export(dist_exports, {
19628
20047
  stripCoverageComments: () => stripCoverageComments,
19629
20048
  stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
19630
20049
  stripLoginScaffolding: () => stripLoginScaffolding,
20050
+ stripTrailingSlashes: () => stripTrailingSlashes,
19631
20051
  strongerNeedsReviewSource: () => strongerNeedsReviewSource,
19632
20052
  sttModelsForProvider: () => sttModelsForProvider,
19633
20053
  summarizeHealth: () => summarizeHealth,
@@ -19655,7 +20075,8 @@ __export(dist_exports, {
19655
20075
  withReviewSource: () => withReviewSource,
19656
20076
  withoutNotChargedClaim: () => withoutNotChargedClaim,
19657
20077
  withoutServerOnlySpendFields: () => withoutServerOnlySpendFields,
19658
- withoutSurveyNotes: () => withoutSurveyNotes
20078
+ withoutSurveyNotes: () => withoutSurveyNotes,
20079
+ zaiWireModel: () => zaiWireModel
19659
20080
  });
19660
20081
  var init_dist = __esm({
19661
20082
  "../shared/dist/index.js"() {
@@ -19697,6 +20118,7 @@ var init_dist = __esm({
19697
20118
  init_admin_view_return_to();
19698
20119
  init_auth_plan();
19699
20120
  init_auth_block_detector();
20121
+ init_auth_session_stamp();
19700
20122
  init_auth_state_freshness();
19701
20123
  init_skip_coverage_detector();
19702
20124
  init_feature_coverage();
@@ -19753,6 +20175,7 @@ var init_dist = __esm({
19753
20175
  init_promotion_quality_gate();
19754
20176
  init_regex_alternation();
19755
20177
  init_page_evidence();
20178
+ init_trailing_slashes();
19756
20179
  }
19757
20180
  });
19758
20181
 
@@ -22892,11 +23315,13 @@ var require_proc_table = __commonJS({
22892
23315
  "../runner-core/dist/utils/proc-table.js"(exports2) {
22893
23316
  "use strict";
22894
23317
  Object.defineProperty(exports2, "__esModule", { value: true });
23318
+ exports2.PS_MAX_BUFFER = void 0;
22895
23319
  exports2.isMissingBinaryError = isMissingBinaryError;
22896
23320
  exports2.parseProcStat = parseProcStat;
22897
23321
  exports2.readProcRssKb = readProcRssKb;
22898
23322
  exports2.readProcTable = readProcTable;
22899
23323
  var node_fs_1 = require("fs");
23324
+ exports2.PS_MAX_BUFFER = 32 * 1024 * 1024;
22900
23325
  var CLOCK_TICKS_PER_SECOND = 100;
22901
23326
  function isMissingBinaryError(error2) {
22902
23327
  return error2?.code === "ENOENT";
@@ -22982,14 +23407,13 @@ var require_kill_tree = __commonJS({
22982
23407
  var proc_table_js_1 = require_proc_table();
22983
23408
  var execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
22984
23409
  var PS_TIMEOUT_MS = 2e3;
22985
- var PS_BUFFER = 1024 * 1024;
22986
23410
  async function listProcessRows(timeoutMs = PS_TIMEOUT_MS) {
22987
23411
  const controller = new AbortController();
22988
23412
  const timer = setTimeout(() => controller.abort(), timeoutMs);
22989
23413
  timer.unref?.();
22990
23414
  try {
22991
23415
  const { stdout } = await execFileAsync("ps", ["-A", "-o", "pid=,ppid=,command="], {
22992
- maxBuffer: PS_BUFFER,
23416
+ maxBuffer: proc_table_js_1.PS_MAX_BUFFER,
22993
23417
  signal: controller.signal
22994
23418
  });
22995
23419
  const rows = [];
@@ -23026,7 +23450,7 @@ var require_kill_tree = __commonJS({
23026
23450
  timer.unref?.();
23027
23451
  try {
23028
23452
  const { stdout } = await execFileAsync("ps", ["-A", "-o", "pid=,ppid=,pgid=,stat="], {
23029
- maxBuffer: PS_BUFFER,
23453
+ maxBuffer: proc_table_js_1.PS_MAX_BUFFER,
23030
23454
  signal: controller.signal
23031
23455
  });
23032
23456
  const tree = /* @__PURE__ */ new Map();
@@ -23136,15 +23560,15 @@ var require_kill_tree = __commonJS({
23136
23560
  const rows = await listProcessRows(timeoutMs);
23137
23561
  return new Set(rows.filter((row) => row.ppid === parentPid && commandRegex.test(row.command)).map((row) => row.pid));
23138
23562
  } catch {
23139
- return /* @__PURE__ */ new Set();
23563
+ return null;
23140
23564
  }
23141
23565
  }
23142
23566
  var chromiumLaunchTail = Promise.resolve();
23143
23567
  async function launchWithChromiumRootPid(launch, options = {}) {
23144
23568
  const run = async () => {
23145
- const prior = await snapshotMatchingChildren(process.pid, options.commandRegex, options.timeoutMs).catch(() => /* @__PURE__ */ new Set());
23569
+ const prior = await snapshotMatchingChildren(process.pid, options.commandRegex, options.timeoutMs).catch(() => null);
23146
23570
  const value = await launch();
23147
- const rootPid = await findNewChromiumChildPid(process.pid, prior, options).catch(() => null);
23571
+ const rootPid = prior ? await findNewChromiumChildPid(process.pid, prior, options).catch(() => null) : null;
23148
23572
  return { value, rootPid };
23149
23573
  };
23150
23574
  const turn = chromiumLaunchTail.then(run);
@@ -76648,7 +77072,7 @@ var require_he = __commonJS({
76648
77072
  var stringFromCharCode2 = String.fromCharCode;
76649
77073
  var object = {};
76650
77074
  var hasOwnProperty = object.hasOwnProperty;
76651
- var has = function(object2, propertyName) {
77075
+ var has2 = function(object2, propertyName) {
76652
77076
  return hasOwnProperty.call(object2, propertyName);
76653
77077
  };
76654
77078
  var contains = function(array, value) {
@@ -76668,7 +77092,7 @@ var require_he = __commonJS({
76668
77092
  var result = {};
76669
77093
  var key2;
76670
77094
  for (key2 in defaults) {
76671
- result[key2] = has(options, key2) ? options[key2] : defaults[key2];
77095
+ result[key2] = has2(options, key2) ? options[key2] : defaults[key2];
76672
77096
  }
76673
77097
  return result;
76674
77098
  };
@@ -76680,7 +77104,7 @@ var require_he = __commonJS({
76680
77104
  }
76681
77105
  return "\uFFFD";
76682
77106
  }
76683
- if (has(decodeMapNumeric, codePoint)) {
77107
+ if (has2(decodeMapNumeric, codePoint)) {
76684
77108
  if (strict) {
76685
77109
  parseError("disallowed character reference");
76686
77110
  }
@@ -76721,7 +77145,7 @@ var require_he = __commonJS({
76721
77145
  };
76722
77146
  if (encodeEverything) {
76723
77147
  string = string.replace(regexAsciiWhitelist, function(symbol) {
76724
- if (useNamedReferences && has(encodeMap, symbol)) {
77148
+ if (useNamedReferences && has2(encodeMap, symbol)) {
76725
77149
  return "&" + encodeMap[symbol] + ";";
76726
77150
  }
76727
77151
  return escapeBmpSymbol(symbol);
@@ -76846,7 +77270,7 @@ var require_he = __commonJS({
76846
77270
  freeModule.exports = he;
76847
77271
  } else {
76848
77272
  for (var key in he) {
76849
- has(he, key) && (freeExports[key] = he[key]);
77273
+ has2(he, key) && (freeExports[key] = he[key]);
76850
77274
  }
76851
77275
  }
76852
77276
  } else {