@validate.qa/runner 1.0.44 → 1.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +112 -46
  2. package/dist/cli.mjs +112 -46
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5243,6 +5243,28 @@ var init_feature_flags = __esm({
5243
5243
  }
5244
5244
  });
5245
5245
 
5246
+ // ../shared/dist/env-flags.js
5247
+ function parseBoolFlag(value, defaultValue = false) {
5248
+ if (value == null)
5249
+ return defaultValue;
5250
+ const v = value.trim().toLowerCase();
5251
+ if (v === "")
5252
+ return defaultValue;
5253
+ if (TRUTHY.has(v))
5254
+ return true;
5255
+ if (FALSY.has(v))
5256
+ return false;
5257
+ return defaultValue;
5258
+ }
5259
+ var TRUTHY, FALSY;
5260
+ var init_env_flags = __esm({
5261
+ "../shared/dist/env-flags.js"() {
5262
+ "use strict";
5263
+ TRUTHY = /* @__PURE__ */ new Set(["true", "1", "yes", "on"]);
5264
+ FALSY = /* @__PURE__ */ new Set(["false", "0", "no", "off"]);
5265
+ }
5266
+ });
5267
+
5246
5268
  // ../shared/dist/index.js
5247
5269
  var dist_exports = {};
5248
5270
  __export(dist_exports, {
@@ -5395,6 +5417,7 @@ __export(dist_exports, {
5395
5417
  normalizeTtsVoiceId: () => normalizeTtsVoiceId,
5396
5418
  otherMobilePlatform: () => otherMobilePlatform,
5397
5419
  parenDepthDelta: () => parenDepthDelta,
5420
+ parseBoolFlag: () => parseBoolFlag,
5398
5421
  pickDisplayRun: () => pickDisplayRun,
5399
5422
  pickLatestHealthRun: () => pickLatestHealthRun,
5400
5423
  placeholderizeRecordedMobileAction: () => placeholderizeRecordedMobileAction,
@@ -5450,6 +5473,7 @@ var init_dist = __esm({
5450
5473
  init_redact_needles();
5451
5474
  init_voice_config();
5452
5475
  init_feature_flags();
5476
+ init_env_flags();
5453
5477
  }
5454
5478
  });
5455
5479
 
@@ -6093,12 +6117,13 @@ var require_global_ai_slot_client = __commonJS({
6093
6117
  exports2.acquireGlobalAiSlot = acquireGlobalAiSlot;
6094
6118
  exports2.releaseGlobalAiSlot = releaseGlobalAiSlot;
6095
6119
  var crypto_1 = require("crypto");
6120
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
6096
6121
  var SERVER_URL = (process.env.SERVER_URL ?? "").replace(/\/$/, "");
6097
6122
  var AUTH_TOKEN = process.env.AUTH_TOKEN || process.env.RUNNER_TOKEN || "";
6098
6123
  var HOLDER = process.env.RUN_ID || `task-${(0, crypto_1.randomUUID)().slice(0, 8)}`;
6099
6124
  var ACQUIRE_HTTP_TIMEOUT_MS = 8e3;
6100
6125
  function isEnabled() {
6101
- return (process.env.GLOBAL_AI_LIMITER_ENABLED ?? "").trim().toLowerCase() === "true" && SERVER_URL.length > 0 && AUTH_TOKEN.length > 0;
6126
+ return (0, shared_1.parseBoolFlag)(process.env.GLOBAL_AI_LIMITER_ENABLED) && SERVER_URL.length > 0 && AUTH_TOKEN.length > 0;
6102
6127
  }
6103
6128
  function maxWaitMs() {
6104
6129
  const raw = process.env.GLOBAL_AI_ACQUIRE_MAX_WAIT_MS;
@@ -67508,6 +67533,7 @@ var require_snapshot_parser = __commonJS({
67508
67533
  exports2.detectSessionState = detectSessionState;
67509
67534
  exports2.detectReadinessSignals = detectReadinessSignals;
67510
67535
  exports2.detectViewportHints = detectViewportHints;
67536
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
67511
67537
  var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
67512
67538
  "textbox",
67513
67539
  "searchbox",
@@ -67688,7 +67714,7 @@ var require_snapshot_parser = __commonJS({
67688
67714
  return e.name;
67689
67715
  }
67690
67716
  function parseSnapshot(snapshotText, options = {}) {
67691
- const richParse = options.richParse ?? process.env.DISCOVERY_SNAPSHOT_RICH_PARSE === "true";
67717
+ const richParse = options.richParse ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_RICH_PARSE);
67692
67718
  const lines = snapshotText.split("\n");
67693
67719
  const elements = [];
67694
67720
  const liveMessages = [];
@@ -68600,6 +68626,7 @@ var require_discover_ai_planner = __commonJS({
68600
68626
  exports2.validateAIPlannerOutput = validateAIPlannerOutput;
68601
68627
  exports2.buildFallbackPlan = buildFallbackPlan;
68602
68628
  exports2.runAIPlanner = runAIPlanner;
68629
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
68603
68630
  var ai_provider_js_1 = require_ai_provider();
68604
68631
  var ai_queue_js_1 = require_ai_queue();
68605
68632
  var ai_retry_js_1 = require_ai_retry();
@@ -69878,7 +69905,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
69878
69905
  async function runAIPlanner(siteMap, evidence, context, options) {
69879
69906
  const logs2 = [];
69880
69907
  const failurePlan = (kind, reason, legacyFallback2) => {
69881
- const noFallback = context.mode === "survey" && process.env.DISCOVERY_PLANNER_NO_FALLBACK === "true";
69908
+ const noFallback = context.mode === "survey" && (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PLANNER_NO_FALLBACK);
69882
69909
  if (noFallback) {
69883
69910
  logs2.push(`Planner ${kind} \u2014 NO-FALLBACK: failing survey cleanly instead of fabricating slug features (${reason})`);
69884
69911
  return {
@@ -70265,7 +70292,7 @@ ${JSON.stringify(gatePlan)}`;
70265
70292
  }
70266
70293
  if (context.mode === "survey" && featureGroups.length === 0 && siteMap.pages.length > 0) {
70267
70294
  const hasGroupWorthyEvidence = siteMap.pages.some((p) => (p.forms?.length ?? 0) > 0 || (p.elements?.length ?? 0) > 0);
70268
- const noFallback = process.env.DISCOVERY_PLANNER_NO_FALLBACK === "true";
70295
+ const noFallback = (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PLANNER_NO_FALLBACK);
70269
70296
  if (noFallback && !hasGroupWorthyEvidence) {
70270
70297
  return {
70271
70298
  scenarios,
@@ -75514,7 +75541,8 @@ var require_browser_config = __commonJS({
75514
75541
  var promises_1 = require("fs/promises");
75515
75542
  var path_1 = require("path");
75516
75543
  var os_1 = require("os");
75517
- exports2.IS_CLOUD = process.env.RUNNER_CLOUD === "true";
75544
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
75545
+ exports2.IS_CLOUD = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
75518
75546
  exports2.CLOUD_ARGS = [
75519
75547
  "--no-sandbox",
75520
75548
  "--disable-setuid-sandbox",
@@ -75656,7 +75684,7 @@ var require_browser_config = __commonJS({
75656
75684
  }
75657
75685
  }
75658
75686
  function isHeadless2() {
75659
- return exports2.IS_CLOUD || process.env.PLAYWRIGHT_HEADLESS === "true" || process.env.NODE_ENV === "production";
75687
+ return exports2.IS_CLOUD || (0, shared_1.parseBoolFlag)(process.env.PLAYWRIGHT_HEADLESS) || process.env.NODE_ENV === "production";
75660
75688
  }
75661
75689
  function getSlowMoMs() {
75662
75690
  const raw = process.env.PLAYWRIGHT_SLOWMO;
@@ -76728,7 +76756,7 @@ var require_playwright_native = __commonJS({
76728
76756
  Object.defineProperty(exports2, "scrubHarRequestBody", { enumerable: true, get: function() {
76729
76757
  return api_call_redaction_js_2.scrubHarRequestBody;
76730
76758
  } });
76731
- var IS_CLOUD2 = process.env.RUNNER_CLOUD === "true";
76759
+ var IS_CLOUD2 = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
76732
76760
  var PACKAGE_DIR = (0, path_1.resolve)(__dirname, "..", "..");
76733
76761
  var RUNS_DIR = process.env.RUNS_DIR || (0, path_1.join)(PACKAGE_DIR, ".qa-runs");
76734
76762
  var PW_CLI = require.resolve("@playwright/test/cli");
@@ -76972,7 +77000,7 @@ test.afterEach(async ({ page }, testInfo) => {
76972
77000
  if (useScopedApiHeaders && resolvedExtraHeaders) {
76973
77001
  await (0, promises_1.writeFile)((0, path_1.join)(runDir, "qa-api-fixtures.ts"), (0, api_auth_headers_js_1.buildOriginScopedApiFixtures)(resolvedExtraHeaders, baseUrl));
76974
77002
  }
76975
- const headless = process.env.PLAYWRIGHT_HEADLESS === "true" || process.env.NODE_ENV === "production" || IS_CLOUD2;
77003
+ const headless = (0, shared_1.parseBoolFlag)(process.env.PLAYWRIGHT_HEADLESS) || process.env.NODE_ENV === "production" || IS_CLOUD2;
76976
77004
  logs2.push(`\u2699\uFE0F Config: baseURL=${JSON.stringify(baseUrl)}, headless=${headless}${isApiTest2 ? ", API mode (no screenshot/video)" : ""}`);
76977
77005
  const absTestDir = runDir.replace(/\\/g, "/");
76978
77006
  const absResultsFile = (0, path_1.join)(runDir, "results.json").replace(/\\/g, "/");
@@ -78678,6 +78706,7 @@ var require_instrumented_context = __commonJS({
78678
78706
  var mcp_1 = require("@playwright/mcp");
78679
78707
  var index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
78680
78708
  var inMemory_js_1 = require("@modelcontextprotocol/sdk/inMemory.js");
78709
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
78681
78710
  var browser_config_js_1 = require_browser_config();
78682
78711
  var health_observer_js_1 = require_health_observer();
78683
78712
  var live_network_collector_js_1 = require_live_network_collector();
@@ -78695,7 +78724,7 @@ var require_instrumented_context = __commonJS({
78695
78724
  var OWNED_BROWSER_CLOSE_TIMEOUT_MS = intEnv("INSTRUMENTED_OWNED_BROWSER_CLOSE_TIMEOUT_MS", 1e4);
78696
78725
  var CLEANUP_TIMEOUT_MS = intEnv("INSTRUMENTED_CLEANUP_TIMEOUT_MS", 1e4);
78697
78726
  function liveCaptureAllowed(mode) {
78698
- if ((process.env.LIVE_NETWORK_COLLECTOR_ENABLED ?? "").toLowerCase() !== "true")
78727
+ if (!(0, shared_1.parseBoolFlag)(process.env.LIVE_NETWORK_COLLECTOR_ENABLED))
78699
78728
  return false;
78700
78729
  if (!mode)
78701
78730
  return false;
@@ -79158,6 +79187,7 @@ var require_snapshot_observation = __commonJS({
79158
79187
  exports2.qualifyElementLabel = qualifyElementLabel;
79159
79188
  exports2.isConsentOverlayElement = isConsentOverlayElement;
79160
79189
  var snapshot_parser_js_1 = require_snapshot_parser();
79190
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
79161
79191
  var GENERIC_LABEL_RE = /^(input field|textbox|button|link|item|field|value|tab)$/i;
79162
79192
  var NOISE_LABEL_RE = /^(skip\s+to|skip\s+nav|back\s+to\s+top|cookie|accept\s+(all\s+)?cookies)$/i;
79163
79193
  var CONSENT_OVERLAY_LABEL_RE = /\bcookies?\b|\bgdpr\b|\bconsent\b|privacy (?:policy|preferences|settings)/i;
@@ -79490,8 +79520,8 @@ var require_snapshot_observation = __commonJS({
79490
79520
  const metrics = page.snapshotMetrics ?? page.snapshotArtifact?.metrics;
79491
79521
  const sourceKind = page.snapshotMeta?.sourceKind ?? page.snapshotArtifact?.sourceKind ?? "missing";
79492
79522
  const artifact = page.snapshotArtifact;
79493
- const richRender = options.richRender ?? process.env.DISCOVERY_SNAPSHOT_RICH_RENDER === "true";
79494
- const rowActionCensus = richRender && options.mode !== "survey" && (options.rowActionCensus ?? process.env.DISCOVERY_SNAPSHOT_ROW_CENSUS === "true");
79523
+ const richRender = options.richRender ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_RICH_RENDER);
79524
+ const rowActionCensus = richRender && options.mode !== "survey" && (options.rowActionCensus ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_ROW_CENSUS));
79495
79525
  const activeScope = inferActiveSnapshotScope(page);
79496
79526
  const ranked = rankSnapshotElements(getScopedSnapshotElements(page, activeScope), withScopeContext({ ...context, richRank: richRender }, activeScope));
79497
79527
  const allInteractive = ranked.filter(({ element }) => isInteractiveCandidate(element)).filter(({ element }) => {
@@ -80373,6 +80403,7 @@ var require_snapshot_context_compactor = __commonJS({
80373
80403
  exports2.compactSnapshotMessages = compactSnapshotMessages;
80374
80404
  exports2.formatSnapshotCompactionLog = formatSnapshotCompactionLog;
80375
80405
  var crypto_1 = require("crypto");
80406
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
80376
80407
  var DEFAULT_MAX_TOOL_RESULT_CHARS = 15e3;
80377
80408
  var DEFAULT_MAX_DUPLICATE_SNAPSHOT_CHARS = 1400;
80378
80409
  var DEFAULT_MAX_TOTAL_SNAPSHOT_CHARS = 45e3;
@@ -80382,7 +80413,7 @@ var require_snapshot_context_compactor = __commonJS({
80382
80413
  maxSnapshotChars: options.maxSnapshotChars ?? DEFAULT_MAX_TOOL_RESULT_CHARS,
80383
80414
  maxDuplicateSnapshotChars: options.maxDuplicateSnapshotChars ?? DEFAULT_MAX_DUPLICATE_SNAPSHOT_CHARS,
80384
80415
  maxTotalSnapshotChars: options.maxTotalSnapshotChars ?? DEFAULT_MAX_TOTAL_SNAPSHOT_CHARS,
80385
- compactStructuredJson: options.compactStructuredJson ?? process.env.DISCOVERY_SNAPSHOT_STRUCTURED_COMPACT !== "false"
80416
+ compactStructuredJson: options.compactStructuredJson ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_STRUCTURED_COMPACT, true)
80386
80417
  };
80387
80418
  }
80388
80419
  function extractSnapshotBlock(content) {
@@ -88423,14 +88454,14 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
88423
88454
  revealedControls,
88424
88455
  // Opt-in additive-contradiction gate (see assertion-strength.ts). On Fargate this
88425
88456
  // env must be dispatcher-forwarded to take effect here; off → byte-identical.
88426
- flagContradictedAdditions: process.env.STRENGTH_ADDITIVE_CONTRADICTION_GATE === "true"
88457
+ flagContradictedAdditions: (0, shared_1.parseBoolFlag)(process.env.STRENGTH_ADDITIVE_CONTRADICTION_GATE)
88427
88458
  });
88428
88459
  } catch (err) {
88429
88460
  logs2.push(` Strength gate errored \u2014 skipping (fail-open): ${String(err)}`);
88430
88461
  }
88431
88462
  const verifyCallsSinceLastFinish = verifyCallCount - verifyCallsAtLastFinishGenerate;
88432
88463
  verifyCallsAtLastFinishGenerate = verifyCallCount;
88433
- const bugWitnessEnabled = process.env.DISCOVERY_BUG_WITNESS_ENABLED === "true";
88464
+ const bugWitnessEnabled = (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_BUG_WITNESS_ENABLED);
88434
88465
  const bugWitnessVerdict = bugWitnessEnabled ? resolveSuspectedBugVerdict(suspectedBugDeclared, bugDescription, verifyCallsSinceLastFinish, strengthVerdict?.signals) : null;
88435
88466
  if (bugWitnessVerdict) {
88436
88467
  strengthVerdict = bugWitnessVerdict;
@@ -305687,11 +305718,12 @@ var require_bootstrap_grok_auth = __commonJS({
305687
305718
  exports2.seedGrokMcpConfigIfNeeded = seedGrokMcpConfigIfNeeded;
305688
305719
  var node_fs_1 = __importDefault(require("fs"));
305689
305720
  var node_path_1 = __importDefault(require("path"));
305721
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
305690
305722
  function seedGrokAuthIfNeeded() {
305691
305723
  const home = process.env.HOME ?? "/home/appuser";
305692
305724
  const authPath = node_path_1.default.join(home, ".grok", "auth.json");
305693
305725
  const b64 = process.env.GROK_AUTH_JSON_B64;
305694
- const force = process.env.GROK_AUTH_FORCE_RESEED === "true" || process.env.GROK_AUTH_FORCE_RESEED === "1";
305726
+ const force = (0, shared_1.parseBoolFlag)(process.env.GROK_AUTH_FORCE_RESEED) || process.env.GROK_AUTH_FORCE_RESEED === "1";
305695
305727
  if (!force && node_fs_1.default.existsSync(authPath)) {
305696
305728
  return;
305697
305729
  }
@@ -307081,7 +307113,7 @@ Output the JSON envelope exactly ONCE as your final message, then exit.`;
307081
307113
  return (0, shared_1.buildSanitizedAgentEnv)({ extra });
307082
307114
  }
307083
307115
  async function runGrokHealSession(opts) {
307084
- const subagentsEnabled = (process.env.GROK_HEAL_SUBAGENTS ?? "").toLowerCase() === "true";
307116
+ const subagentsEnabled = (0, shared_1.parseBoolFlag)(process.env.GROK_HEAL_SUBAGENTS);
307085
307117
  const args = [
307086
307118
  "-p",
307087
307119
  'Read BRIEF.md in this directory. Heal TEST_UNDER_HEAL.spec.ts as instructed. Your FINAL assistant message MUST be ONLY a JSON object \u2014 no prose around it \u2014 with this shape: {"verdict":"fix|app_bug|config_issue|prereq_unmet|state_stale|test_invalid","playwrightCode":"<full file if verdict=fix>","changeDescription":"<one sentence>","reason":"<terse, when not fix>","confidence":"high|medium|low"}',
@@ -312860,6 +312892,7 @@ var require_discover_explorer = __commonJS({
312860
312892
  var ai_provider_js_1 = require_ai_provider();
312861
312893
  var snapshot_parser_js_1 = require_snapshot_parser();
312862
312894
  var scrub_credentials_js_1 = require_scrub_credentials();
312895
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
312863
312896
  var credential_tools_js_1 = require_credential_tools();
312864
312897
  var inbox_tools_js_1 = require_inbox_tools();
312865
312898
  var verification_inbox_js_1 = require_verification_inbox();
@@ -313635,7 +313668,7 @@ ${credentialBlock}${redactedBlock}${inboxBlock}`;
313635
313668
  const collectedPages = [];
313636
313669
  const collectedTransitions = [];
313637
313670
  const observedOriginCounts = /* @__PURE__ */ new Map();
313638
- const captureOriginSignals = (process.env.APP_ORIGIN_RESOLUTION ?? "").toLowerCase() === "true";
313671
+ const captureOriginSignals = (0, shared_1.parseBoolFlag)(process.env.APP_ORIGIN_RESOLUTION);
313639
313672
  const buildObservedOrigins = () => [...observedOriginCounts.entries()].sort((a, b) => b[1] - a[1]).map(([o]) => o);
313640
313673
  logs2.push(`Explorer starting - provider: ${provider}, model: ${agentModel}`);
313641
313674
  logs2.push(`Base URL: ${baseUrl}`);
@@ -313657,7 +313690,7 @@ ${credentialBlock}${redactedBlock}${inboxBlock}`;
313657
313690
  const v3Env = process.env.DISCOVERY_PROMPT_V3;
313658
313691
  const useV3 = v3Env !== "false";
313659
313692
  const useV2 = true;
313660
- const perceptionEnricherEnabled = (process.env.DISCOVERY_PERCEPTION_ENRICHER === "true" || process.env.DISCOVERY_PERCEPTION_ENRICHER === "1") && typeof options?.getPerceptionPage === "function";
313693
+ const perceptionEnricherEnabled = ((0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PERCEPTION_ENRICHER) || process.env.DISCOVERY_PERCEPTION_ENRICHER === "1") && typeof options?.getPerceptionPage === "function";
313661
313694
  const linkFrontierEnabled = (0, survey_link_frontier_js_1.isSurveyLinkFrontierEnabled)() && options?.mode === "survey";
313662
313695
  const linkScope = (0, survey_link_frontier_js_1.deriveLinkScope)(baseUrl);
313663
313696
  let finishRedirects = 0;
@@ -313812,7 +313845,7 @@ ${inboxPromptBlock}`;
313812
313845
  let lastBriefRoute = "";
313813
313846
  let lastBriefIteration = 0;
313814
313847
  const BRIEF_INTERVAL = 5;
313815
- const stuckDetectorEnabled = process.env.DISCOVERY_STUCK_DETECTOR === "1" || process.env.DISCOVERY_STUCK_DETECTOR === "true";
313848
+ const stuckDetectorEnabled = process.env.DISCOVERY_STUCK_DETECTOR === "1" || (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_STUCK_DETECTOR);
313816
313849
  const stuckDetector = stuckDetectorEnabled ? new stuck_detector_js_1.StuckDetector({ repetitionReachesRecovery: !isDeepMode }) : null;
313817
313850
  while (iteration < maxIterations && !explorationComplete) {
313818
313851
  iteration++;
@@ -316319,6 +316352,8 @@ var require_auth_capture_run = __commonJS({
316319
316352
  "../runner-core/dist/services/auth-capture-run.js"(exports2) {
316320
316353
  "use strict";
316321
316354
  Object.defineProperty(exports2, "__esModule", { value: true });
316355
+ exports2.filterLoginCaptureCredentials = filterLoginCaptureCredentials;
316356
+ exports2.buildLoginCaptureCredentials = buildLoginCaptureCredentials;
316322
316357
  exports2.getLoginCaptureMaxIterations = getLoginCaptureMaxIterations;
316323
316358
  exports2.harvestAuthProofLive = harvestAuthProofLive;
316324
316359
  exports2.findCredentialLiteralLeaks = findCredentialLiteralLeaks;
@@ -316334,6 +316369,26 @@ var require_auth_capture_run = __commonJS({
316334
316369
  var playwright_native_js_1 = require_playwright_native();
316335
316370
  var scrub_credentials_js_1 = require_scrub_credentials();
316336
316371
  var credential_tools_js_1 = require_credential_tools();
316372
+ var LOGIN_CAPTURE_CONTROL_VARIABLES = /* @__PURE__ */ new Set([
316373
+ "BASE_URL",
316374
+ "DISCOVERY_SHOULD_REGISTER",
316375
+ "DISCOVERY_AUTH_MODE"
316376
+ ]);
316377
+ function filterLoginCaptureCredentials(variables) {
316378
+ const credentials = {};
316379
+ for (const [key, value] of Object.entries(variables)) {
316380
+ if ((0, auth_recipe_js_1.isReservedRunnerEnvVar)(key) || LOGIN_CAPTURE_CONTROL_VARIABLES.has(key))
316381
+ continue;
316382
+ credentials[key] = value;
316383
+ }
316384
+ return credentials;
316385
+ }
316386
+ function buildLoginCaptureCredentials(variableContext) {
316387
+ return filterLoginCaptureCredentials({
316388
+ ...variableContext.publicTestVariables,
316389
+ ...variableContext.allTestVariables
316390
+ });
316391
+ }
316337
316392
  var DEFAULT_MAX_LOGIN_CAPTURE_ITERATIONS = 12;
316338
316393
  function readPositiveIntEnv2(env, name, fallback) {
316339
316394
  const raw = env[name]?.trim();
@@ -316541,7 +316596,8 @@ ${keyLines || "- (none provided)"}
316541
316596
  return false;
316542
316597
  }
316543
316598
  async function runLoginCaptureRun(args) {
316544
- const { loginBrowser, baseUrl, credentials, projectId, model, onAudit, logs: logs2 } = args;
316599
+ const { loginBrowser, baseUrl, projectId, model, onAudit, logs: logs2 } = args;
316600
+ const credentials = filterLoginCaptureCredentials(args.credentials);
316545
316601
  if ((0, agentic_cli_constants_js_1.getAgenticEngine)(model) !== "native") {
316546
316602
  logs2(` auth-capture skipped: engine for ${model} is not native (V1 is native-engine-only)`);
316547
316603
  return null;
@@ -317999,6 +318055,7 @@ var require_discovery_verify_pool = __commonJS({
317999
318055
  var node_path_1 = require("path");
318000
318056
  var playwright_native_js_1 = require_playwright_native();
318001
318057
  var scrub_credentials_js_1 = require_scrub_credentials();
318058
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
318002
318059
  var discover_generator_js_1 = require_discover_generator();
318003
318060
  var canvas_detector_js_1 = require_canvas_detector();
318004
318061
  var agentic_discovery_prompts_js_1 = require_agentic_discovery_prompts();
@@ -318658,7 +318715,7 @@ var require_discovery_verify_pool = __commonJS({
318658
318715
  log2(`ledger: persisted ${scenarioLedgers.size} ledger file(s) to ${ledgerDir}`);
318659
318716
  }
318660
318717
  function startAuthoredWatcher(args) {
318661
- if (process.env.DISCOVERY_AUTHORED_STREAMING !== "true") {
318718
+ if (!(0, shared_1.parseBoolFlag)(process.env.DISCOVERY_AUTHORED_STREAMING)) {
318662
318719
  return { stop: () => {
318663
318720
  }, count: () => 0 };
318664
318721
  }
@@ -319062,6 +319119,7 @@ var require_grok_discovery_runner = __commonJS({
319062
319119
  var node_fs_1 = require("fs");
319063
319120
  var node_os_1 = require("os");
319064
319121
  var node_path_1 = require("path");
319122
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
319065
319123
  var instrumented_context_js_1 = require_instrumented_context();
319066
319124
  var exploration_parser_js_1 = require_exploration_parser();
319067
319125
  var bootstrap_grok_auth_js_1 = require_bootstrap_grok_auth();
@@ -319092,7 +319150,7 @@ var require_grok_discovery_runner = __commonJS({
319092
319150
  var DEFAULT_TARGET = { min: 6, max: 15 };
319093
319151
  var WATCHER_DEBOUNCE_MS = 500;
319094
319152
  var MAX_PLAN_REVISIONS = 3;
319095
- var LEGACY_PLAN_MODE = process.env.USE_LEGACY_GROK_DISCOVERY === "true";
319153
+ var LEGACY_PLAN_MODE = (0, shared_1.parseBoolFlag)(process.env.USE_LEGACY_GROK_DISCOVERY);
319096
319154
  var SNAPSHOT_EXCERPT_CHARS = 150;
319097
319155
  function isObject(v) {
319098
319156
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -319243,7 +319301,7 @@ var require_grok_discovery_runner = __commonJS({
319243
319301
  return out;
319244
319302
  }
319245
319303
  async function runGrokDiscoveryOnRunner(ctx, callbackOptions, options = {}) {
319246
- if (process.env.USE_GROK_DISCOVERY_V2 === "true") {
319304
+ if ((0, shared_1.parseBoolFlag)(process.env.USE_GROK_DISCOVERY_V2)) {
319247
319305
  return runGrokDiscoveryV2OnRunner(ctx, callbackOptions, options);
319248
319306
  }
319249
319307
  const featureName = ctx.featureName ?? "Untitled Feature";
@@ -321715,6 +321773,7 @@ var require_tool_ledger = __commonJS({
321715
321773
  var promises_1 = require("fs/promises");
321716
321774
  var node_crypto_1 = require("crypto");
321717
321775
  var node_path_1 = require("path");
321776
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
321718
321777
  var OTHER_OUTPUT_PREVIEW_CAP = 1024;
321719
321778
  var DEFAULT_SNAPSHOT_BYTES_CAP = 16 * 1024;
321720
321779
  var KNOWN_CREDENTIAL_BEARING_TOOLS = /* @__PURE__ */ new Set([
@@ -321796,7 +321855,7 @@ var require_tool_ledger = __commonJS({
321796
321855
  let seq = 0;
321797
321856
  let turn = 0;
321798
321857
  let lastNavigateUrl = null;
321799
- const redact = opts.redact ?? process.env.DISCOVERY_LEDGER_REDACT === "true";
321858
+ const redact = opts.redact ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_LEDGER_REDACT);
321800
321859
  const credentialEnvMap = opts.credentialEnvMap ?? /* @__PURE__ */ new Map();
321801
321860
  const maxSnapshotBytes = opts.maxSnapshotBytes ?? DEFAULT_SNAPSHOT_BYTES_CAP;
321802
321861
  const sessionId = (0, node_crypto_1.randomUUID)();
@@ -323417,6 +323476,7 @@ var require_discover_agent = __commonJS({
323417
323476
  var ai_queue_js_1 = require_ai_queue();
323418
323477
  var ai_retry_js_1 = require_ai_retry();
323419
323478
  var strip_json_fences_js_1 = require_strip_json_fences();
323479
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
323420
323480
  var discover_explorer_js_1 = require_discover_explorer();
323421
323481
  var discover_feature_explorer_js_1 = require_discover_feature_explorer();
323422
323482
  var discover_planner_js_1 = require_discover_planner();
@@ -323510,7 +323570,7 @@ var require_discover_agent = __commonJS({
323510
323570
  }
323511
323571
  function describeRunnerRuntime(launchOpts) {
323512
323572
  const browserMode = launchOpts?.headless === true ? "headless" : launchOpts?.headless === false ? "headed" : "default";
323513
- const runtime = process.env.RUNNER_CLOUD === "true" ? "cloud runner" : "local runner";
323573
+ const runtime = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD) ? "cloud runner" : "local runner";
323514
323574
  return `Runtime: ${runtime}, browser mode: ${browserMode}`;
323515
323575
  }
323516
323576
  function formatElapsed(ms) {
@@ -323657,7 +323717,7 @@ Respond with ONLY valid JSON:
323657
323717
  }
323658
323718
  var AUTH_CAPTURE_TIMEOUT_MS = 4 * 60 * 1e3;
323659
323719
  function maybeStartLoginCaptureRun(ctx, callbackOptions, onAICall, pushLog, onObservedOrigins) {
323660
- if (process.env.AUTH_RECIPE_STAMP !== "true")
323720
+ if (!(0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP))
323661
323721
  return null;
323662
323722
  if (ctx.authRecipe) {
323663
323723
  pushLog(`auth-prologue: reusing persisted login recipe ${ctx.authRecipe.recipeHash} \u2014 skipping capture`);
@@ -323680,7 +323740,7 @@ Respond with ONLY valid JSON:
323680
323740
  pushLog("auth-prologue: AUTH_RECIPE_STAMP on + native engine, but no login-browser factory supplied (runner stage 2b) \u2014 skipping producer");
323681
323741
  return null;
323682
323742
  }
323683
- const credentials = ctx.variableContext.allTestVariables ?? ctx.variableContext.publicTestVariables;
323743
+ const credentials = (0, auth_capture_run_js_1.buildLoginCaptureCredentials)(ctx.variableContext);
323684
323744
  const run2 = (async () => {
323685
323745
  let lease = null;
323686
323746
  try {
@@ -323743,7 +323803,7 @@ Respond with ONLY valid JSON:
323743
323803
  if (canvasPreflight.probeRan) {
323744
323804
  ctx.appRenderType = canvasPreflight.renderType;
323745
323805
  }
323746
- const useNativeOverride = process.env.USE_NATIVE_SURVEY === "true";
323806
+ const useNativeOverride = (0, shared_1.parseBoolFlag)(process.env.USE_NATIVE_SURVEY);
323747
323807
  const surveyEngine = (0, agentic_cli_constants_js_1.getAgenticEngine)(ctx.exploreModel);
323748
323808
  if (isSurvey && surveyEngine !== "native" && !useNativeOverride) {
323749
323809
  logs2.push(`exploreModel=${ctx.exploreModel} \u2192 routing to ${surveyEngine} survey runner`);
@@ -323960,8 +324020,8 @@ Explore complete: ${exploreResult.pagesDiscovered} pages, ${exploreResult.elemen
323960
324020
  // Recipe-aware planning: when a verified login recipe is on file, the planner
323961
324021
  // plans @needs-auth (non-auth-flow) scenarios from the authenticated state
323962
324022
  // instead of authoring landing→login steps (which generate would override).
323963
- authRecipeAvailable: process.env.AUTH_RECIPE_STAMP === "true" && !!ctx.authRecipe,
323964
- authRedirectRoute: process.env.AUTH_RECIPE_STAMP === "true" ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324023
+ authRecipeAvailable: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) && !!ctx.authRecipe,
324024
+ authRedirectRoute: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
323965
324025
  testBudget
323966
324026
  }, {
323967
324027
  modelOverride: ctx.planModel ?? ctx.generateModel,
@@ -324268,7 +324328,7 @@ Fatal error: ${msg}`);
324268
324328
  if (canvasPreflight.probeRan) {
324269
324329
  ctx.appRenderType = canvasPreflight.renderType;
324270
324330
  }
324271
- const useNativeDeepOverride = process.env.USE_NATIVE_DEEP === "true";
324331
+ const useNativeDeepOverride = (0, shared_1.parseBoolFlag)(process.env.USE_NATIVE_DEEP);
324272
324332
  const deepEngine = (0, agentic_cli_constants_js_1.getAgenticEngine)(ctx.exploreModel);
324273
324333
  if (deepEngine !== "native" && !useNativeDeepOverride) {
324274
324334
  logs2.push(`exploreModel=${ctx.exploreModel} \u2192 routing to ${deepEngine} deep discovery runner`);
@@ -324539,8 +324599,8 @@ Plan (reused): ${resumeSavedScenarios.length} scenarios from the paused run.`);
324539
324599
  },
324540
324600
  // Recipe-aware planning (feature/deep): plan @needs-auth scenarios from the
324541
324601
  // authenticated state when a verified login recipe is on file for this project.
324542
- authRecipeAvailable: process.env.AUTH_RECIPE_STAMP === "true" && !!ctx.authRecipe,
324543
- authRedirectRoute: process.env.AUTH_RECIPE_STAMP === "true" ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324602
+ authRecipeAvailable: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) && !!ctx.authRecipe,
324603
+ authRedirectRoute: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324544
324604
  testBudget: featureTestBudget
324545
324605
  }, {
324546
324606
  modelOverride: ctx.planModel ?? ctx.generateModel,
@@ -325056,6 +325116,7 @@ var require_resource_governor = __commonJS({
325056
325116
  exports2.getResourceGovernorStatus = getResourceGovernorStatus2;
325057
325117
  var fs_1 = require("fs");
325058
325118
  var os_1 = __importDefault(require("os"));
325119
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
325059
325120
  var DEFAULT_WEIGHTS = {
325060
325121
  run: 1,
325061
325122
  heal: 2.5,
@@ -325202,9 +325263,7 @@ var require_resource_governor = __commonJS({
325202
325263
  }
325203
325264
  function envBool(name, fallback) {
325204
325265
  const raw = process.env[name];
325205
- if (raw == null || raw === "")
325206
- return fallback;
325207
- return raw === "true" || raw === "1" || raw.toLowerCase() === "yes";
325266
+ return (0, shared_1.parseBoolFlag)(raw, fallback);
325208
325267
  }
325209
325268
  function envFloat(name, fallback) {
325210
325269
  const raw = process.env[name];
@@ -337979,9 +338038,9 @@ var require_dist2 = __commonJS({
337979
338038
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
337980
338039
  };
337981
338040
  Object.defineProperty(exports2, "__esModule", { value: true });
337982
- exports2.MAX_ARCHIVE_BYTES = exports2.isUnsafeEntryName = exports2.extractZipSafely = exports2.downloadArchiveCapped = exports2.detectArchiveKind = exports2.acquireRepoForImport = exports2.runFrameworkImportOnRunner = exports2.getAgenticEngine = exports2.resolveRefFromSnapshot = exports2.replayAuthRecipeIntoBrowser = exports2.runRegisterCaptureRun = exports2.runLoginCaptureRun = exports2.isReservedRunnerEnvVar = exports2.RESERVED_RUNNER_ENV_VARS = exports2.AUTH_MARKER_VERSION = exports2.buildHealAuthStamp = exports2.extractAuthRegion = exports2.upsertAuthBlock = exports2.buildAuthRecipe = exports2.commandToReplayStep = exports2.buildReplayPlan = exports2.absoluteRoute = exports2.renderReplaySettleArrow = exports2.renderReplayClickArrow = exports2.renderAuthFn = exports2.canonicalizeRoute = exports2.executeGrokPerBatchHeal = exports2.executeGrokPerTestHeal = exports2.headerVal = exports2.classifyAuthType = exports2.isTextExcerptable = exports2.isStaticAssetByExt = exports2.isApiCall = exports2.buildApiCallSummary = exports2.computeMobileHealOutcome = exports2.detectMobileStepSecretLeak = exports2.redactMobileSecretsFromText = exports2.MOBILE_LIVE_HEAL_SYSTEM_PROMPT = exports2.MOBILE_SCRIPT_HEAL_SYSTEM_PROMPT = exports2.executeMobileLiveHeal = exports2.executeMobileTestWithHealing = exports2.executeMobileScriptDrivenHeal = exports2.prepareMobileScenarioAppState = exports2.runMobileGeneratePhase = exports2.runMobileAIPlanner = exports2.buildMobileSiteMap = exports2.formatMobileEvidenceForPlanner = exports2.MOBILE_SCENARIO_SYSTEM_PROMPT = exports2.MOBILE_SURVEY_SYSTEM_PROMPT = exports2.runMobileExplorePhase = void 0;
337983
- exports2.modelSupportsVision = exports2.decideCanvasStrategy = exports2.decideAppRenderType = exports2.detectCanvasApp = exports2.detectRateLimitBlock = exports2.isSafeCanonicalRedirect = exports2.resolveBaseUrlPreflight = exports2.checkBaseUrlRedirect = exports2.stripJsonFences = exports2.scrubCredentials = exports2.withAIRetry = exports2.snapshotMatchingChildren = exports2.findNewChromiumChildPid = exports2.killProcessTree = exports2.gracefulCloseWithTreeKill = exports2.liveBrowserRegistry = exports2.REPO_SWITCH_REMOVED_FRACTION = exports2.MAX_MANIFEST_FILES = exports2.toDiffSummary = exports2.isLikelyTestFile = exports2.sanitizeRepoRelPath = exports2.sha256Hex = exports2.hashFiles = exports2.enumerateTestFiles = exports2.buildNextManifest = exports2.detectRepoSwitch = exports2.classifyImportDiff = exports2.parseImportManifest = exports2.REPO_ANALYSIS_SCHEMA_VERSION = exports2.validateSourceEndpoints = exports2.validateAuthoredTest = exports2.validateRepoMapFile = exports2.validateRepoMemoryFile = exports2.buildTestingStandardsSection = exports2.buildRepoAuthorSystemRules = exports2.buildRepoAuthorKickoff = exports2.buildRepoAuthorContractMd = exports2.buildRepoMapSystemRules = exports2.buildRepoMapKickoff = exports2.buildRepoMapContractMd = exports2.buildRepoMemorySystemRules = exports2.buildRepoMemoryKickoff = exports2.buildRepoMemoryContractMd = exports2.runRepoAnalysisOnRunner = exports2.IMPORT_SCHEMA_VERSION = exports2.validateImportResultFile = exports2.validateImportedTest = exports2.buildImportSystemRules = exports2.buildImportKickoff = exports2.buildImportContractMd = void 0;
337984
- exports2.UNSUPPORTED_RENDERER_PREFIX = exports2.UnsupportedRendererError = exports2.buildCanvasModeAuthoringAddendum = exports2.buildUnsupportedRendererMessage = void 0;
338041
+ exports2.extractZipSafely = exports2.downloadArchiveCapped = exports2.detectArchiveKind = exports2.acquireRepoForImport = exports2.runFrameworkImportOnRunner = exports2.getAgenticEngine = exports2.resolveRefFromSnapshot = exports2.replayAuthRecipeIntoBrowser = exports2.runRegisterCaptureRun = exports2.runLoginCaptureRun = exports2.filterLoginCaptureCredentials = exports2.buildLoginCaptureCredentials = exports2.isReservedRunnerEnvVar = exports2.RESERVED_RUNNER_ENV_VARS = exports2.AUTH_MARKER_VERSION = exports2.buildHealAuthStamp = exports2.extractAuthRegion = exports2.upsertAuthBlock = exports2.buildAuthRecipe = exports2.commandToReplayStep = exports2.buildReplayPlan = exports2.absoluteRoute = exports2.renderReplaySettleArrow = exports2.renderReplayClickArrow = exports2.renderAuthFn = exports2.canonicalizeRoute = exports2.executeGrokPerBatchHeal = exports2.executeGrokPerTestHeal = exports2.headerVal = exports2.classifyAuthType = exports2.isTextExcerptable = exports2.isStaticAssetByExt = exports2.isApiCall = exports2.buildApiCallSummary = exports2.computeMobileHealOutcome = exports2.detectMobileStepSecretLeak = exports2.redactMobileSecretsFromText = exports2.MOBILE_LIVE_HEAL_SYSTEM_PROMPT = exports2.MOBILE_SCRIPT_HEAL_SYSTEM_PROMPT = exports2.executeMobileLiveHeal = exports2.executeMobileTestWithHealing = exports2.executeMobileScriptDrivenHeal = exports2.prepareMobileScenarioAppState = exports2.runMobileGeneratePhase = exports2.runMobileAIPlanner = exports2.buildMobileSiteMap = exports2.formatMobileEvidenceForPlanner = exports2.MOBILE_SCENARIO_SYSTEM_PROMPT = exports2.MOBILE_SURVEY_SYSTEM_PROMPT = exports2.runMobileExplorePhase = void 0;
338042
+ exports2.decideAppRenderType = exports2.detectCanvasApp = exports2.detectRateLimitBlock = exports2.isSafeCanonicalRedirect = exports2.resolveBaseUrlPreflight = exports2.checkBaseUrlRedirect = exports2.stripJsonFences = exports2.scrubCredentials = exports2.withAIRetry = exports2.snapshotMatchingChildren = exports2.findNewChromiumChildPid = exports2.killProcessTree = exports2.gracefulCloseWithTreeKill = exports2.liveBrowserRegistry = exports2.REPO_SWITCH_REMOVED_FRACTION = exports2.MAX_MANIFEST_FILES = exports2.toDiffSummary = exports2.isLikelyTestFile = exports2.sanitizeRepoRelPath = exports2.sha256Hex = exports2.hashFiles = exports2.enumerateTestFiles = exports2.buildNextManifest = exports2.detectRepoSwitch = exports2.classifyImportDiff = exports2.parseImportManifest = exports2.REPO_ANALYSIS_SCHEMA_VERSION = exports2.validateSourceEndpoints = exports2.validateAuthoredTest = exports2.validateRepoMapFile = exports2.validateRepoMemoryFile = exports2.buildTestingStandardsSection = exports2.buildRepoAuthorSystemRules = exports2.buildRepoAuthorKickoff = exports2.buildRepoAuthorContractMd = exports2.buildRepoMapSystemRules = exports2.buildRepoMapKickoff = exports2.buildRepoMapContractMd = exports2.buildRepoMemorySystemRules = exports2.buildRepoMemoryKickoff = exports2.buildRepoMemoryContractMd = exports2.runRepoAnalysisOnRunner = exports2.IMPORT_SCHEMA_VERSION = exports2.validateImportResultFile = exports2.validateImportedTest = exports2.buildImportSystemRules = exports2.buildImportKickoff = exports2.buildImportContractMd = exports2.MAX_ARCHIVE_BYTES = exports2.isUnsafeEntryName = void 0;
338043
+ exports2.UNSUPPORTED_RENDERER_PREFIX = exports2.UnsupportedRendererError = exports2.buildCanvasModeAuthoringAddendum = exports2.buildUnsupportedRendererMessage = exports2.modelSupportsVision = exports2.decideCanvasStrategy = void 0;
337985
338044
  __exportStar(require_ai_provider(), exports2);
337986
338045
  __exportStar(require_mobile_types(), exports2);
337987
338046
  __exportStar(require_mobile_source_parser(), exports2);
@@ -338130,6 +338189,12 @@ var require_dist2 = __commonJS({
338130
338189
  return auth_recipe_js_1.isReservedRunnerEnvVar;
338131
338190
  } });
338132
338191
  var auth_capture_run_js_1 = require_auth_capture_run();
338192
+ Object.defineProperty(exports2, "buildLoginCaptureCredentials", { enumerable: true, get: function() {
338193
+ return auth_capture_run_js_1.buildLoginCaptureCredentials;
338194
+ } });
338195
+ Object.defineProperty(exports2, "filterLoginCaptureCredentials", { enumerable: true, get: function() {
338196
+ return auth_capture_run_js_1.filterLoginCaptureCredentials;
338197
+ } });
338133
338198
  Object.defineProperty(exports2, "runLoginCaptureRun", { enumerable: true, get: function() {
338134
338199
  return auth_capture_run_js_1.runLoginCaptureRun;
338135
338200
  } });
@@ -338356,7 +338421,7 @@ var require_package4 = __commonJS({
338356
338421
  "package.json"(exports2, module2) {
338357
338422
  module2.exports = {
338358
338423
  name: "@validate.qa/runner",
338359
- version: "1.0.44",
338424
+ version: "1.0.46",
338360
338425
  description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
338361
338426
  bin: {
338362
338427
  "validate-runner": "dist/cli.js"
@@ -338495,6 +338560,7 @@ function authPlanFor(tags, playwrightCode) {
338495
338560
  }
338496
338561
 
338497
338562
  // src/version-check.ts
338563
+ init_dist();
338498
338564
  var RUNNER_NPM_PACKAGE = "@validate.qa/runner";
338499
338565
  var NPM_LATEST_URL = `https://registry.npmjs.org/${encodeURIComponent(RUNNER_NPM_PACKAGE)}/latest`;
338500
338566
  var DEFAULT_TIMEOUT_MS = 8e3;
@@ -338526,10 +338592,10 @@ function isVersionOutdated(current, latest) {
338526
338592
  return cmp === -1;
338527
338593
  }
338528
338594
  function shouldSkipVersionCheck() {
338529
- if (process.env.RUNNER_CLOUD === "true") {
338595
+ if (parseBoolFlag(process.env.RUNNER_CLOUD)) {
338530
338596
  return "cloud runner (RUNNER_CLOUD=true)";
338531
338597
  }
338532
- if (process.env.VALIDATE_RUNNER_ALLOW_OUTDATED === "1" || process.env.VALIDATE_RUNNER_ALLOW_OUTDATED === "true") {
338598
+ if (parseBoolFlag(process.env.VALIDATE_RUNNER_ALLOW_OUTDATED)) {
338533
338599
  return "VALIDATE_RUNNER_ALLOW_OUTDATED is set";
338534
338600
  }
338535
338601
  return null;
@@ -345218,7 +345284,7 @@ function attachMobileDiscoveryNetworkContext(calls, result, appId) {
345218
345284
  }
345219
345285
  var runnerPackage = require_package4();
345220
345286
  var SECRET_VAR_PATTERN = /password|secret|token|api[_]?key|pass\b|credential|bearer|pat\b/i;
345221
- var IS_CLOUD = process.env.RUNNER_CLOUD === "true";
345287
+ var IS_CLOUD = parseBoolFlag(process.env.RUNNER_CLOUD);
345222
345288
  var RUNNER_NAME = runnerPackage.name ?? "@validate.qa/runner";
345223
345289
  var RUNNER_VERSION = runnerPackage.version ?? "0.0.0";
345224
345290
  var RUNNER_BUILD_ID = process.env.VALIDATE_RUNNER_BUILD_ID ?? process.env.RAILWAY_GIT_COMMIT_SHA ?? process.env.GIT_COMMIT_SHA ?? process.env.SOURCE_VERSION;
@@ -348107,9 +348173,9 @@ async function startRunner(opts) {
348107
348173
  log.info(`Project: ${projectId}`);
348108
348174
  log.info(`Mode: \u{1F3AD} Playwright Native${enableMobile ? " + \u{1F4F1} Mobile" : ""}${enableMobile && enableMobileTunnel ? " \u{1F310} Tunnel" : ""}`);
348109
348175
  log.info(`Interval: ${pollIntervalMs}ms`);
348110
- if (process.env.DISCOVERY_PROMPT_V3 === "true") {
348176
+ if (parseBoolFlag(process.env.DISCOVERY_PROMPT_V3)) {
348111
348177
  log.ok("Discovery prompt: V3 (per-turn rebuild) \u2014 DISCOVERY_PROMPT_V3=true");
348112
- } else if (process.env.DISCOVERY_PROMPT_V3 === "false") {
348178
+ } else if (!parseBoolFlag(process.env.DISCOVERY_PROMPT_V3, true)) {
348113
348179
  log.ok("Discovery prompt: V2.5 (full transcript + control brief) \u2014 DISCOVERY_PROMPT_V3=false");
348114
348180
  } else {
348115
348181
  log.ok("Discovery prompt: V3 (per-turn rebuild, default) \u2014 set DISCOVERY_PROMPT_V3=false for V2.5");
@@ -348135,7 +348201,7 @@ async function startRunner(opts) {
348135
348201
  // WebView. Enable at mobile-runner startup even when the emulator is
348136
348202
  // booted later; the feature is driver-scoped and remains dormant on
348137
348203
  // iOS. Operators may explicitly opt out.
348138
- enableChromedriverAutodownload: process.env.VALIDATEQA_CHROMEDRIVER_AUTODOWNLOAD !== "false"
348204
+ enableChromedriverAutodownload: parseBoolFlag(process.env.VALIDATEQA_CHROMEDRIVER_AUTODOWNLOAD, true)
348139
348205
  });
348140
348206
  log.ok("\u{1F4F1} Appium server started");
348141
348207
  } catch (err) {
package/dist/cli.mjs CHANGED
@@ -5248,6 +5248,28 @@ var init_feature_flags = __esm({
5248
5248
  }
5249
5249
  });
5250
5250
 
5251
+ // ../shared/dist/env-flags.js
5252
+ function parseBoolFlag(value, defaultValue = false) {
5253
+ if (value == null)
5254
+ return defaultValue;
5255
+ const v = value.trim().toLowerCase();
5256
+ if (v === "")
5257
+ return defaultValue;
5258
+ if (TRUTHY.has(v))
5259
+ return true;
5260
+ if (FALSY.has(v))
5261
+ return false;
5262
+ return defaultValue;
5263
+ }
5264
+ var TRUTHY, FALSY;
5265
+ var init_env_flags = __esm({
5266
+ "../shared/dist/env-flags.js"() {
5267
+ "use strict";
5268
+ TRUTHY = /* @__PURE__ */ new Set(["true", "1", "yes", "on"]);
5269
+ FALSY = /* @__PURE__ */ new Set(["false", "0", "no", "off"]);
5270
+ }
5271
+ });
5272
+
5251
5273
  // ../shared/dist/index.js
5252
5274
  var dist_exports = {};
5253
5275
  __export(dist_exports, {
@@ -5400,6 +5422,7 @@ __export(dist_exports, {
5400
5422
  normalizeTtsVoiceId: () => normalizeTtsVoiceId,
5401
5423
  otherMobilePlatform: () => otherMobilePlatform,
5402
5424
  parenDepthDelta: () => parenDepthDelta,
5425
+ parseBoolFlag: () => parseBoolFlag,
5403
5426
  pickDisplayRun: () => pickDisplayRun,
5404
5427
  pickLatestHealthRun: () => pickLatestHealthRun,
5405
5428
  placeholderizeRecordedMobileAction: () => placeholderizeRecordedMobileAction,
@@ -5455,6 +5478,7 @@ var init_dist = __esm({
5455
5478
  init_redact_needles();
5456
5479
  init_voice_config();
5457
5480
  init_feature_flags();
5481
+ init_env_flags();
5458
5482
  }
5459
5483
  });
5460
5484
 
@@ -6098,12 +6122,13 @@ var require_global_ai_slot_client = __commonJS({
6098
6122
  exports.acquireGlobalAiSlot = acquireGlobalAiSlot;
6099
6123
  exports.releaseGlobalAiSlot = releaseGlobalAiSlot;
6100
6124
  var crypto_1 = __require("crypto");
6125
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
6101
6126
  var SERVER_URL = (process.env.SERVER_URL ?? "").replace(/\/$/, "");
6102
6127
  var AUTH_TOKEN = process.env.AUTH_TOKEN || process.env.RUNNER_TOKEN || "";
6103
6128
  var HOLDER = process.env.RUN_ID || `task-${(0, crypto_1.randomUUID)().slice(0, 8)}`;
6104
6129
  var ACQUIRE_HTTP_TIMEOUT_MS = 8e3;
6105
6130
  function isEnabled() {
6106
- return (process.env.GLOBAL_AI_LIMITER_ENABLED ?? "").trim().toLowerCase() === "true" && SERVER_URL.length > 0 && AUTH_TOKEN.length > 0;
6131
+ return (0, shared_1.parseBoolFlag)(process.env.GLOBAL_AI_LIMITER_ENABLED) && SERVER_URL.length > 0 && AUTH_TOKEN.length > 0;
6107
6132
  }
6108
6133
  function maxWaitMs() {
6109
6134
  const raw = process.env.GLOBAL_AI_ACQUIRE_MAX_WAIT_MS;
@@ -67513,6 +67538,7 @@ var require_snapshot_parser = __commonJS({
67513
67538
  exports.detectSessionState = detectSessionState;
67514
67539
  exports.detectReadinessSignals = detectReadinessSignals;
67515
67540
  exports.detectViewportHints = detectViewportHints;
67541
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
67516
67542
  var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
67517
67543
  "textbox",
67518
67544
  "searchbox",
@@ -67693,7 +67719,7 @@ var require_snapshot_parser = __commonJS({
67693
67719
  return e.name;
67694
67720
  }
67695
67721
  function parseSnapshot(snapshotText, options = {}) {
67696
- const richParse = options.richParse ?? process.env.DISCOVERY_SNAPSHOT_RICH_PARSE === "true";
67722
+ const richParse = options.richParse ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_RICH_PARSE);
67697
67723
  const lines = snapshotText.split("\n");
67698
67724
  const elements = [];
67699
67725
  const liveMessages = [];
@@ -68605,6 +68631,7 @@ var require_discover_ai_planner = __commonJS({
68605
68631
  exports.validateAIPlannerOutput = validateAIPlannerOutput;
68606
68632
  exports.buildFallbackPlan = buildFallbackPlan;
68607
68633
  exports.runAIPlanner = runAIPlanner;
68634
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
68608
68635
  var ai_provider_js_1 = require_ai_provider();
68609
68636
  var ai_queue_js_1 = require_ai_queue();
68610
68637
  var ai_retry_js_1 = require_ai_retry();
@@ -69883,7 +69910,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
69883
69910
  async function runAIPlanner(siteMap, evidence, context, options) {
69884
69911
  const logs2 = [];
69885
69912
  const failurePlan = (kind, reason, legacyFallback2) => {
69886
- const noFallback = context.mode === "survey" && process.env.DISCOVERY_PLANNER_NO_FALLBACK === "true";
69913
+ const noFallback = context.mode === "survey" && (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PLANNER_NO_FALLBACK);
69887
69914
  if (noFallback) {
69888
69915
  logs2.push(`Planner ${kind} \u2014 NO-FALLBACK: failing survey cleanly instead of fabricating slug features (${reason})`);
69889
69916
  return {
@@ -70270,7 +70297,7 @@ ${JSON.stringify(gatePlan)}`;
70270
70297
  }
70271
70298
  if (context.mode === "survey" && featureGroups.length === 0 && siteMap.pages.length > 0) {
70272
70299
  const hasGroupWorthyEvidence = siteMap.pages.some((p) => (p.forms?.length ?? 0) > 0 || (p.elements?.length ?? 0) > 0);
70273
- const noFallback = process.env.DISCOVERY_PLANNER_NO_FALLBACK === "true";
70300
+ const noFallback = (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PLANNER_NO_FALLBACK);
70274
70301
  if (noFallback && !hasGroupWorthyEvidence) {
70275
70302
  return {
70276
70303
  scenarios,
@@ -75519,7 +75546,8 @@ var require_browser_config = __commonJS({
75519
75546
  var promises_1 = __require("fs/promises");
75520
75547
  var path_1 = __require("path");
75521
75548
  var os_1 = __require("os");
75522
- exports.IS_CLOUD = process.env.RUNNER_CLOUD === "true";
75549
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
75550
+ exports.IS_CLOUD = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
75523
75551
  exports.CLOUD_ARGS = [
75524
75552
  "--no-sandbox",
75525
75553
  "--disable-setuid-sandbox",
@@ -75661,7 +75689,7 @@ var require_browser_config = __commonJS({
75661
75689
  }
75662
75690
  }
75663
75691
  function isHeadless2() {
75664
- return exports.IS_CLOUD || process.env.PLAYWRIGHT_HEADLESS === "true" || process.env.NODE_ENV === "production";
75692
+ return exports.IS_CLOUD || (0, shared_1.parseBoolFlag)(process.env.PLAYWRIGHT_HEADLESS) || process.env.NODE_ENV === "production";
75665
75693
  }
75666
75694
  function getSlowMoMs() {
75667
75695
  const raw = process.env.PLAYWRIGHT_SLOWMO;
@@ -76733,7 +76761,7 @@ var require_playwright_native = __commonJS({
76733
76761
  Object.defineProperty(exports, "scrubHarRequestBody", { enumerable: true, get: function() {
76734
76762
  return api_call_redaction_js_2.scrubHarRequestBody;
76735
76763
  } });
76736
- var IS_CLOUD2 = process.env.RUNNER_CLOUD === "true";
76764
+ var IS_CLOUD2 = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
76737
76765
  var PACKAGE_DIR = (0, path_1.resolve)(__dirname, "..", "..");
76738
76766
  var RUNS_DIR = process.env.RUNS_DIR || (0, path_1.join)(PACKAGE_DIR, ".qa-runs");
76739
76767
  var PW_CLI = __require.resolve("@playwright/test/cli");
@@ -76977,7 +77005,7 @@ test.afterEach(async ({ page }, testInfo) => {
76977
77005
  if (useScopedApiHeaders && resolvedExtraHeaders) {
76978
77006
  await (0, promises_1.writeFile)((0, path_1.join)(runDir, "qa-api-fixtures.ts"), (0, api_auth_headers_js_1.buildOriginScopedApiFixtures)(resolvedExtraHeaders, baseUrl));
76979
77007
  }
76980
- const headless = process.env.PLAYWRIGHT_HEADLESS === "true" || process.env.NODE_ENV === "production" || IS_CLOUD2;
77008
+ const headless = (0, shared_1.parseBoolFlag)(process.env.PLAYWRIGHT_HEADLESS) || process.env.NODE_ENV === "production" || IS_CLOUD2;
76981
77009
  logs2.push(`\u2699\uFE0F Config: baseURL=${JSON.stringify(baseUrl)}, headless=${headless}${isApiTest2 ? ", API mode (no screenshot/video)" : ""}`);
76982
77010
  const absTestDir = runDir.replace(/\\/g, "/");
76983
77011
  const absResultsFile = (0, path_1.join)(runDir, "results.json").replace(/\\/g, "/");
@@ -78683,6 +78711,7 @@ var require_instrumented_context = __commonJS({
78683
78711
  var mcp_1 = __require("@playwright/mcp");
78684
78712
  var index_js_1 = __require("@modelcontextprotocol/sdk/client/index.js");
78685
78713
  var inMemory_js_1 = __require("@modelcontextprotocol/sdk/inMemory.js");
78714
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
78686
78715
  var browser_config_js_1 = require_browser_config();
78687
78716
  var health_observer_js_1 = require_health_observer();
78688
78717
  var live_network_collector_js_1 = require_live_network_collector();
@@ -78700,7 +78729,7 @@ var require_instrumented_context = __commonJS({
78700
78729
  var OWNED_BROWSER_CLOSE_TIMEOUT_MS = intEnv("INSTRUMENTED_OWNED_BROWSER_CLOSE_TIMEOUT_MS", 1e4);
78701
78730
  var CLEANUP_TIMEOUT_MS = intEnv("INSTRUMENTED_CLEANUP_TIMEOUT_MS", 1e4);
78702
78731
  function liveCaptureAllowed(mode) {
78703
- if ((process.env.LIVE_NETWORK_COLLECTOR_ENABLED ?? "").toLowerCase() !== "true")
78732
+ if (!(0, shared_1.parseBoolFlag)(process.env.LIVE_NETWORK_COLLECTOR_ENABLED))
78704
78733
  return false;
78705
78734
  if (!mode)
78706
78735
  return false;
@@ -79163,6 +79192,7 @@ var require_snapshot_observation = __commonJS({
79163
79192
  exports.qualifyElementLabel = qualifyElementLabel;
79164
79193
  exports.isConsentOverlayElement = isConsentOverlayElement;
79165
79194
  var snapshot_parser_js_1 = require_snapshot_parser();
79195
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
79166
79196
  var GENERIC_LABEL_RE = /^(input field|textbox|button|link|item|field|value|tab)$/i;
79167
79197
  var NOISE_LABEL_RE = /^(skip\s+to|skip\s+nav|back\s+to\s+top|cookie|accept\s+(all\s+)?cookies)$/i;
79168
79198
  var CONSENT_OVERLAY_LABEL_RE = /\bcookies?\b|\bgdpr\b|\bconsent\b|privacy (?:policy|preferences|settings)/i;
@@ -79495,8 +79525,8 @@ var require_snapshot_observation = __commonJS({
79495
79525
  const metrics = page.snapshotMetrics ?? page.snapshotArtifact?.metrics;
79496
79526
  const sourceKind = page.snapshotMeta?.sourceKind ?? page.snapshotArtifact?.sourceKind ?? "missing";
79497
79527
  const artifact = page.snapshotArtifact;
79498
- const richRender = options.richRender ?? process.env.DISCOVERY_SNAPSHOT_RICH_RENDER === "true";
79499
- const rowActionCensus = richRender && options.mode !== "survey" && (options.rowActionCensus ?? process.env.DISCOVERY_SNAPSHOT_ROW_CENSUS === "true");
79528
+ const richRender = options.richRender ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_RICH_RENDER);
79529
+ const rowActionCensus = richRender && options.mode !== "survey" && (options.rowActionCensus ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_ROW_CENSUS));
79500
79530
  const activeScope = inferActiveSnapshotScope(page);
79501
79531
  const ranked = rankSnapshotElements(getScopedSnapshotElements(page, activeScope), withScopeContext({ ...context, richRank: richRender }, activeScope));
79502
79532
  const allInteractive = ranked.filter(({ element }) => isInteractiveCandidate(element)).filter(({ element }) => {
@@ -80378,6 +80408,7 @@ var require_snapshot_context_compactor = __commonJS({
80378
80408
  exports.compactSnapshotMessages = compactSnapshotMessages;
80379
80409
  exports.formatSnapshotCompactionLog = formatSnapshotCompactionLog;
80380
80410
  var crypto_1 = __require("crypto");
80411
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
80381
80412
  var DEFAULT_MAX_TOOL_RESULT_CHARS = 15e3;
80382
80413
  var DEFAULT_MAX_DUPLICATE_SNAPSHOT_CHARS = 1400;
80383
80414
  var DEFAULT_MAX_TOTAL_SNAPSHOT_CHARS = 45e3;
@@ -80387,7 +80418,7 @@ var require_snapshot_context_compactor = __commonJS({
80387
80418
  maxSnapshotChars: options.maxSnapshotChars ?? DEFAULT_MAX_TOOL_RESULT_CHARS,
80388
80419
  maxDuplicateSnapshotChars: options.maxDuplicateSnapshotChars ?? DEFAULT_MAX_DUPLICATE_SNAPSHOT_CHARS,
80389
80420
  maxTotalSnapshotChars: options.maxTotalSnapshotChars ?? DEFAULT_MAX_TOTAL_SNAPSHOT_CHARS,
80390
- compactStructuredJson: options.compactStructuredJson ?? process.env.DISCOVERY_SNAPSHOT_STRUCTURED_COMPACT !== "false"
80421
+ compactStructuredJson: options.compactStructuredJson ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_SNAPSHOT_STRUCTURED_COMPACT, true)
80391
80422
  };
80392
80423
  }
80393
80424
  function extractSnapshotBlock(content) {
@@ -88428,14 +88459,14 @@ Do NOT add steps you did not execute. Do NOT skip steps from the recording.${led
88428
88459
  revealedControls,
88429
88460
  // Opt-in additive-contradiction gate (see assertion-strength.ts). On Fargate this
88430
88461
  // env must be dispatcher-forwarded to take effect here; off → byte-identical.
88431
- flagContradictedAdditions: process.env.STRENGTH_ADDITIVE_CONTRADICTION_GATE === "true"
88462
+ flagContradictedAdditions: (0, shared_1.parseBoolFlag)(process.env.STRENGTH_ADDITIVE_CONTRADICTION_GATE)
88432
88463
  });
88433
88464
  } catch (err) {
88434
88465
  logs2.push(` Strength gate errored \u2014 skipping (fail-open): ${String(err)}`);
88435
88466
  }
88436
88467
  const verifyCallsSinceLastFinish = verifyCallCount - verifyCallsAtLastFinishGenerate;
88437
88468
  verifyCallsAtLastFinishGenerate = verifyCallCount;
88438
- const bugWitnessEnabled = process.env.DISCOVERY_BUG_WITNESS_ENABLED === "true";
88469
+ const bugWitnessEnabled = (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_BUG_WITNESS_ENABLED);
88439
88470
  const bugWitnessVerdict = bugWitnessEnabled ? resolveSuspectedBugVerdict(suspectedBugDeclared, bugDescription, verifyCallsSinceLastFinish, strengthVerdict?.signals) : null;
88440
88471
  if (bugWitnessVerdict) {
88441
88472
  strengthVerdict = bugWitnessVerdict;
@@ -305692,11 +305723,12 @@ var require_bootstrap_grok_auth = __commonJS({
305692
305723
  exports.seedGrokMcpConfigIfNeeded = seedGrokMcpConfigIfNeeded;
305693
305724
  var node_fs_1 = __importDefault(__require("fs"));
305694
305725
  var node_path_1 = __importDefault(__require("path"));
305726
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
305695
305727
  function seedGrokAuthIfNeeded() {
305696
305728
  const home = process.env.HOME ?? "/home/appuser";
305697
305729
  const authPath = node_path_1.default.join(home, ".grok", "auth.json");
305698
305730
  const b64 = process.env.GROK_AUTH_JSON_B64;
305699
- const force = process.env.GROK_AUTH_FORCE_RESEED === "true" || process.env.GROK_AUTH_FORCE_RESEED === "1";
305731
+ const force = (0, shared_1.parseBoolFlag)(process.env.GROK_AUTH_FORCE_RESEED) || process.env.GROK_AUTH_FORCE_RESEED === "1";
305700
305732
  if (!force && node_fs_1.default.existsSync(authPath)) {
305701
305733
  return;
305702
305734
  }
@@ -307086,7 +307118,7 @@ Output the JSON envelope exactly ONCE as your final message, then exit.`;
307086
307118
  return (0, shared_1.buildSanitizedAgentEnv)({ extra });
307087
307119
  }
307088
307120
  async function runGrokHealSession(opts) {
307089
- const subagentsEnabled = (process.env.GROK_HEAL_SUBAGENTS ?? "").toLowerCase() === "true";
307121
+ const subagentsEnabled = (0, shared_1.parseBoolFlag)(process.env.GROK_HEAL_SUBAGENTS);
307090
307122
  const args = [
307091
307123
  "-p",
307092
307124
  'Read BRIEF.md in this directory. Heal TEST_UNDER_HEAL.spec.ts as instructed. Your FINAL assistant message MUST be ONLY a JSON object \u2014 no prose around it \u2014 with this shape: {"verdict":"fix|app_bug|config_issue|prereq_unmet|state_stale|test_invalid","playwrightCode":"<full file if verdict=fix>","changeDescription":"<one sentence>","reason":"<terse, when not fix>","confidence":"high|medium|low"}',
@@ -312865,6 +312897,7 @@ var require_discover_explorer = __commonJS({
312865
312897
  var ai_provider_js_1 = require_ai_provider();
312866
312898
  var snapshot_parser_js_1 = require_snapshot_parser();
312867
312899
  var scrub_credentials_js_1 = require_scrub_credentials();
312900
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
312868
312901
  var credential_tools_js_1 = require_credential_tools();
312869
312902
  var inbox_tools_js_1 = require_inbox_tools();
312870
312903
  var verification_inbox_js_1 = require_verification_inbox();
@@ -313640,7 +313673,7 @@ ${credentialBlock}${redactedBlock}${inboxBlock}`;
313640
313673
  const collectedPages = [];
313641
313674
  const collectedTransitions = [];
313642
313675
  const observedOriginCounts = /* @__PURE__ */ new Map();
313643
- const captureOriginSignals = (process.env.APP_ORIGIN_RESOLUTION ?? "").toLowerCase() === "true";
313676
+ const captureOriginSignals = (0, shared_1.parseBoolFlag)(process.env.APP_ORIGIN_RESOLUTION);
313644
313677
  const buildObservedOrigins = () => [...observedOriginCounts.entries()].sort((a, b) => b[1] - a[1]).map(([o]) => o);
313645
313678
  logs2.push(`Explorer starting - provider: ${provider}, model: ${agentModel}`);
313646
313679
  logs2.push(`Base URL: ${baseUrl}`);
@@ -313662,7 +313695,7 @@ ${credentialBlock}${redactedBlock}${inboxBlock}`;
313662
313695
  const v3Env = process.env.DISCOVERY_PROMPT_V3;
313663
313696
  const useV3 = v3Env !== "false";
313664
313697
  const useV2 = true;
313665
- const perceptionEnricherEnabled = (process.env.DISCOVERY_PERCEPTION_ENRICHER === "true" || process.env.DISCOVERY_PERCEPTION_ENRICHER === "1") && typeof options?.getPerceptionPage === "function";
313698
+ const perceptionEnricherEnabled = ((0, shared_1.parseBoolFlag)(process.env.DISCOVERY_PERCEPTION_ENRICHER) || process.env.DISCOVERY_PERCEPTION_ENRICHER === "1") && typeof options?.getPerceptionPage === "function";
313666
313699
  const linkFrontierEnabled = (0, survey_link_frontier_js_1.isSurveyLinkFrontierEnabled)() && options?.mode === "survey";
313667
313700
  const linkScope = (0, survey_link_frontier_js_1.deriveLinkScope)(baseUrl);
313668
313701
  let finishRedirects = 0;
@@ -313817,7 +313850,7 @@ ${inboxPromptBlock}`;
313817
313850
  let lastBriefRoute = "";
313818
313851
  let lastBriefIteration = 0;
313819
313852
  const BRIEF_INTERVAL = 5;
313820
- const stuckDetectorEnabled = process.env.DISCOVERY_STUCK_DETECTOR === "1" || process.env.DISCOVERY_STUCK_DETECTOR === "true";
313853
+ const stuckDetectorEnabled = process.env.DISCOVERY_STUCK_DETECTOR === "1" || (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_STUCK_DETECTOR);
313821
313854
  const stuckDetector = stuckDetectorEnabled ? new stuck_detector_js_1.StuckDetector({ repetitionReachesRecovery: !isDeepMode }) : null;
313822
313855
  while (iteration < maxIterations && !explorationComplete) {
313823
313856
  iteration++;
@@ -316324,6 +316357,8 @@ var require_auth_capture_run = __commonJS({
316324
316357
  "../runner-core/dist/services/auth-capture-run.js"(exports) {
316325
316358
  "use strict";
316326
316359
  Object.defineProperty(exports, "__esModule", { value: true });
316360
+ exports.filterLoginCaptureCredentials = filterLoginCaptureCredentials;
316361
+ exports.buildLoginCaptureCredentials = buildLoginCaptureCredentials;
316327
316362
  exports.getLoginCaptureMaxIterations = getLoginCaptureMaxIterations;
316328
316363
  exports.harvestAuthProofLive = harvestAuthProofLive;
316329
316364
  exports.findCredentialLiteralLeaks = findCredentialLiteralLeaks;
@@ -316339,6 +316374,26 @@ var require_auth_capture_run = __commonJS({
316339
316374
  var playwright_native_js_1 = require_playwright_native();
316340
316375
  var scrub_credentials_js_1 = require_scrub_credentials();
316341
316376
  var credential_tools_js_1 = require_credential_tools();
316377
+ var LOGIN_CAPTURE_CONTROL_VARIABLES = /* @__PURE__ */ new Set([
316378
+ "BASE_URL",
316379
+ "DISCOVERY_SHOULD_REGISTER",
316380
+ "DISCOVERY_AUTH_MODE"
316381
+ ]);
316382
+ function filterLoginCaptureCredentials(variables) {
316383
+ const credentials = {};
316384
+ for (const [key, value] of Object.entries(variables)) {
316385
+ if ((0, auth_recipe_js_1.isReservedRunnerEnvVar)(key) || LOGIN_CAPTURE_CONTROL_VARIABLES.has(key))
316386
+ continue;
316387
+ credentials[key] = value;
316388
+ }
316389
+ return credentials;
316390
+ }
316391
+ function buildLoginCaptureCredentials(variableContext) {
316392
+ return filterLoginCaptureCredentials({
316393
+ ...variableContext.publicTestVariables,
316394
+ ...variableContext.allTestVariables
316395
+ });
316396
+ }
316342
316397
  var DEFAULT_MAX_LOGIN_CAPTURE_ITERATIONS = 12;
316343
316398
  function readPositiveIntEnv2(env, name, fallback) {
316344
316399
  const raw = env[name]?.trim();
@@ -316546,7 +316601,8 @@ ${keyLines || "- (none provided)"}
316546
316601
  return false;
316547
316602
  }
316548
316603
  async function runLoginCaptureRun(args) {
316549
- const { loginBrowser, baseUrl, credentials, projectId, model, onAudit, logs: logs2 } = args;
316604
+ const { loginBrowser, baseUrl, projectId, model, onAudit, logs: logs2 } = args;
316605
+ const credentials = filterLoginCaptureCredentials(args.credentials);
316550
316606
  if ((0, agentic_cli_constants_js_1.getAgenticEngine)(model) !== "native") {
316551
316607
  logs2(` auth-capture skipped: engine for ${model} is not native (V1 is native-engine-only)`);
316552
316608
  return null;
@@ -318004,6 +318060,7 @@ var require_discovery_verify_pool = __commonJS({
318004
318060
  var node_path_1 = __require("path");
318005
318061
  var playwright_native_js_1 = require_playwright_native();
318006
318062
  var scrub_credentials_js_1 = require_scrub_credentials();
318063
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
318007
318064
  var discover_generator_js_1 = require_discover_generator();
318008
318065
  var canvas_detector_js_1 = require_canvas_detector();
318009
318066
  var agentic_discovery_prompts_js_1 = require_agentic_discovery_prompts();
@@ -318663,7 +318720,7 @@ var require_discovery_verify_pool = __commonJS({
318663
318720
  log2(`ledger: persisted ${scenarioLedgers.size} ledger file(s) to ${ledgerDir}`);
318664
318721
  }
318665
318722
  function startAuthoredWatcher(args) {
318666
- if (process.env.DISCOVERY_AUTHORED_STREAMING !== "true") {
318723
+ if (!(0, shared_1.parseBoolFlag)(process.env.DISCOVERY_AUTHORED_STREAMING)) {
318667
318724
  return { stop: () => {
318668
318725
  }, count: () => 0 };
318669
318726
  }
@@ -319067,6 +319124,7 @@ var require_grok_discovery_runner = __commonJS({
319067
319124
  var node_fs_1 = __require("fs");
319068
319125
  var node_os_1 = __require("os");
319069
319126
  var node_path_1 = __require("path");
319127
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
319070
319128
  var instrumented_context_js_1 = require_instrumented_context();
319071
319129
  var exploration_parser_js_1 = require_exploration_parser();
319072
319130
  var bootstrap_grok_auth_js_1 = require_bootstrap_grok_auth();
@@ -319097,7 +319155,7 @@ var require_grok_discovery_runner = __commonJS({
319097
319155
  var DEFAULT_TARGET = { min: 6, max: 15 };
319098
319156
  var WATCHER_DEBOUNCE_MS = 500;
319099
319157
  var MAX_PLAN_REVISIONS = 3;
319100
- var LEGACY_PLAN_MODE = process.env.USE_LEGACY_GROK_DISCOVERY === "true";
319158
+ var LEGACY_PLAN_MODE = (0, shared_1.parseBoolFlag)(process.env.USE_LEGACY_GROK_DISCOVERY);
319101
319159
  var SNAPSHOT_EXCERPT_CHARS = 150;
319102
319160
  function isObject(v) {
319103
319161
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -319248,7 +319306,7 @@ var require_grok_discovery_runner = __commonJS({
319248
319306
  return out;
319249
319307
  }
319250
319308
  async function runGrokDiscoveryOnRunner(ctx, callbackOptions, options = {}) {
319251
- if (process.env.USE_GROK_DISCOVERY_V2 === "true") {
319309
+ if ((0, shared_1.parseBoolFlag)(process.env.USE_GROK_DISCOVERY_V2)) {
319252
319310
  return runGrokDiscoveryV2OnRunner(ctx, callbackOptions, options);
319253
319311
  }
319254
319312
  const featureName = ctx.featureName ?? "Untitled Feature";
@@ -321720,6 +321778,7 @@ var require_tool_ledger = __commonJS({
321720
321778
  var promises_1 = __require("fs/promises");
321721
321779
  var node_crypto_1 = __require("crypto");
321722
321780
  var node_path_1 = __require("path");
321781
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
321723
321782
  var OTHER_OUTPUT_PREVIEW_CAP = 1024;
321724
321783
  var DEFAULT_SNAPSHOT_BYTES_CAP = 16 * 1024;
321725
321784
  var KNOWN_CREDENTIAL_BEARING_TOOLS = /* @__PURE__ */ new Set([
@@ -321801,7 +321860,7 @@ var require_tool_ledger = __commonJS({
321801
321860
  let seq = 0;
321802
321861
  let turn = 0;
321803
321862
  let lastNavigateUrl = null;
321804
- const redact = opts.redact ?? process.env.DISCOVERY_LEDGER_REDACT === "true";
321863
+ const redact = opts.redact ?? (0, shared_1.parseBoolFlag)(process.env.DISCOVERY_LEDGER_REDACT);
321805
321864
  const credentialEnvMap = opts.credentialEnvMap ?? /* @__PURE__ */ new Map();
321806
321865
  const maxSnapshotBytes = opts.maxSnapshotBytes ?? DEFAULT_SNAPSHOT_BYTES_CAP;
321807
321866
  const sessionId = (0, node_crypto_1.randomUUID)();
@@ -323422,6 +323481,7 @@ var require_discover_agent = __commonJS({
323422
323481
  var ai_queue_js_1 = require_ai_queue();
323423
323482
  var ai_retry_js_1 = require_ai_retry();
323424
323483
  var strip_json_fences_js_1 = require_strip_json_fences();
323484
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
323425
323485
  var discover_explorer_js_1 = require_discover_explorer();
323426
323486
  var discover_feature_explorer_js_1 = require_discover_feature_explorer();
323427
323487
  var discover_planner_js_1 = require_discover_planner();
@@ -323515,7 +323575,7 @@ var require_discover_agent = __commonJS({
323515
323575
  }
323516
323576
  function describeRunnerRuntime(launchOpts) {
323517
323577
  const browserMode = launchOpts?.headless === true ? "headless" : launchOpts?.headless === false ? "headed" : "default";
323518
- const runtime = process.env.RUNNER_CLOUD === "true" ? "cloud runner" : "local runner";
323578
+ const runtime = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD) ? "cloud runner" : "local runner";
323519
323579
  return `Runtime: ${runtime}, browser mode: ${browserMode}`;
323520
323580
  }
323521
323581
  function formatElapsed(ms) {
@@ -323662,7 +323722,7 @@ Respond with ONLY valid JSON:
323662
323722
  }
323663
323723
  var AUTH_CAPTURE_TIMEOUT_MS = 4 * 60 * 1e3;
323664
323724
  function maybeStartLoginCaptureRun(ctx, callbackOptions, onAICall, pushLog, onObservedOrigins) {
323665
- if (process.env.AUTH_RECIPE_STAMP !== "true")
323725
+ if (!(0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP))
323666
323726
  return null;
323667
323727
  if (ctx.authRecipe) {
323668
323728
  pushLog(`auth-prologue: reusing persisted login recipe ${ctx.authRecipe.recipeHash} \u2014 skipping capture`);
@@ -323685,7 +323745,7 @@ Respond with ONLY valid JSON:
323685
323745
  pushLog("auth-prologue: AUTH_RECIPE_STAMP on + native engine, but no login-browser factory supplied (runner stage 2b) \u2014 skipping producer");
323686
323746
  return null;
323687
323747
  }
323688
- const credentials = ctx.variableContext.allTestVariables ?? ctx.variableContext.publicTestVariables;
323748
+ const credentials = (0, auth_capture_run_js_1.buildLoginCaptureCredentials)(ctx.variableContext);
323689
323749
  const run2 = (async () => {
323690
323750
  let lease = null;
323691
323751
  try {
@@ -323748,7 +323808,7 @@ Respond with ONLY valid JSON:
323748
323808
  if (canvasPreflight.probeRan) {
323749
323809
  ctx.appRenderType = canvasPreflight.renderType;
323750
323810
  }
323751
- const useNativeOverride = process.env.USE_NATIVE_SURVEY === "true";
323811
+ const useNativeOverride = (0, shared_1.parseBoolFlag)(process.env.USE_NATIVE_SURVEY);
323752
323812
  const surveyEngine = (0, agentic_cli_constants_js_1.getAgenticEngine)(ctx.exploreModel);
323753
323813
  if (isSurvey && surveyEngine !== "native" && !useNativeOverride) {
323754
323814
  logs2.push(`exploreModel=${ctx.exploreModel} \u2192 routing to ${surveyEngine} survey runner`);
@@ -323965,8 +324025,8 @@ Explore complete: ${exploreResult.pagesDiscovered} pages, ${exploreResult.elemen
323965
324025
  // Recipe-aware planning: when a verified login recipe is on file, the planner
323966
324026
  // plans @needs-auth (non-auth-flow) scenarios from the authenticated state
323967
324027
  // instead of authoring landing→login steps (which generate would override).
323968
- authRecipeAvailable: process.env.AUTH_RECIPE_STAMP === "true" && !!ctx.authRecipe,
323969
- authRedirectRoute: process.env.AUTH_RECIPE_STAMP === "true" ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324028
+ authRecipeAvailable: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) && !!ctx.authRecipe,
324029
+ authRedirectRoute: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
323970
324030
  testBudget
323971
324031
  }, {
323972
324032
  modelOverride: ctx.planModel ?? ctx.generateModel,
@@ -324273,7 +324333,7 @@ Fatal error: ${msg}`);
324273
324333
  if (canvasPreflight.probeRan) {
324274
324334
  ctx.appRenderType = canvasPreflight.renderType;
324275
324335
  }
324276
- const useNativeDeepOverride = process.env.USE_NATIVE_DEEP === "true";
324336
+ const useNativeDeepOverride = (0, shared_1.parseBoolFlag)(process.env.USE_NATIVE_DEEP);
324277
324337
  const deepEngine = (0, agentic_cli_constants_js_1.getAgenticEngine)(ctx.exploreModel);
324278
324338
  if (deepEngine !== "native" && !useNativeDeepOverride) {
324279
324339
  logs2.push(`exploreModel=${ctx.exploreModel} \u2192 routing to ${deepEngine} deep discovery runner`);
@@ -324544,8 +324604,8 @@ Plan (reused): ${resumeSavedScenarios.length} scenarios from the paused run.`);
324544
324604
  },
324545
324605
  // Recipe-aware planning (feature/deep): plan @needs-auth scenarios from the
324546
324606
  // authenticated state when a verified login recipe is on file for this project.
324547
- authRecipeAvailable: process.env.AUTH_RECIPE_STAMP === "true" && !!ctx.authRecipe,
324548
- authRedirectRoute: process.env.AUTH_RECIPE_STAMP === "true" ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324607
+ authRecipeAvailable: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) && !!ctx.authRecipe,
324608
+ authRedirectRoute: (0, shared_1.parseBoolFlag)(process.env.AUTH_RECIPE_STAMP) ? ctx.authRecipe?.redirectRoute ?? void 0 : void 0,
324549
324609
  testBudget: featureTestBudget
324550
324610
  }, {
324551
324611
  modelOverride: ctx.planModel ?? ctx.generateModel,
@@ -325061,6 +325121,7 @@ var require_resource_governor = __commonJS({
325061
325121
  exports.getResourceGovernorStatus = getResourceGovernorStatus2;
325062
325122
  var fs_1 = __require("fs");
325063
325123
  var os_1 = __importDefault(__require("os"));
325124
+ var shared_1 = (init_dist(), __toCommonJS(dist_exports));
325064
325125
  var DEFAULT_WEIGHTS = {
325065
325126
  run: 1,
325066
325127
  heal: 2.5,
@@ -325207,9 +325268,7 @@ var require_resource_governor = __commonJS({
325207
325268
  }
325208
325269
  function envBool(name, fallback) {
325209
325270
  const raw = process.env[name];
325210
- if (raw == null || raw === "")
325211
- return fallback;
325212
- return raw === "true" || raw === "1" || raw.toLowerCase() === "yes";
325271
+ return (0, shared_1.parseBoolFlag)(raw, fallback);
325213
325272
  }
325214
325273
  function envFloat(name, fallback) {
325215
325274
  const raw = process.env[name];
@@ -337984,9 +338043,9 @@ var require_dist2 = __commonJS({
337984
338043
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
337985
338044
  };
337986
338045
  Object.defineProperty(exports, "__esModule", { value: true });
337987
- exports.MAX_ARCHIVE_BYTES = exports.isUnsafeEntryName = exports.extractZipSafely = exports.downloadArchiveCapped = exports.detectArchiveKind = exports.acquireRepoForImport = exports.runFrameworkImportOnRunner = exports.getAgenticEngine = exports.resolveRefFromSnapshot = exports.replayAuthRecipeIntoBrowser = exports.runRegisterCaptureRun = exports.runLoginCaptureRun = exports.isReservedRunnerEnvVar = exports.RESERVED_RUNNER_ENV_VARS = exports.AUTH_MARKER_VERSION = exports.buildHealAuthStamp = exports.extractAuthRegion = exports.upsertAuthBlock = exports.buildAuthRecipe = exports.commandToReplayStep = exports.buildReplayPlan = exports.absoluteRoute = exports.renderReplaySettleArrow = exports.renderReplayClickArrow = exports.renderAuthFn = exports.canonicalizeRoute = exports.executeGrokPerBatchHeal = exports.executeGrokPerTestHeal = exports.headerVal = exports.classifyAuthType = exports.isTextExcerptable = exports.isStaticAssetByExt = exports.isApiCall = exports.buildApiCallSummary = exports.computeMobileHealOutcome = exports.detectMobileStepSecretLeak = exports.redactMobileSecretsFromText = exports.MOBILE_LIVE_HEAL_SYSTEM_PROMPT = exports.MOBILE_SCRIPT_HEAL_SYSTEM_PROMPT = exports.executeMobileLiveHeal = exports.executeMobileTestWithHealing = exports.executeMobileScriptDrivenHeal = exports.prepareMobileScenarioAppState = exports.runMobileGeneratePhase = exports.runMobileAIPlanner = exports.buildMobileSiteMap = exports.formatMobileEvidenceForPlanner = exports.MOBILE_SCENARIO_SYSTEM_PROMPT = exports.MOBILE_SURVEY_SYSTEM_PROMPT = exports.runMobileExplorePhase = void 0;
337988
- exports.modelSupportsVision = exports.decideCanvasStrategy = exports.decideAppRenderType = exports.detectCanvasApp = exports.detectRateLimitBlock = exports.isSafeCanonicalRedirect = exports.resolveBaseUrlPreflight = exports.checkBaseUrlRedirect = exports.stripJsonFences = exports.scrubCredentials = exports.withAIRetry = exports.snapshotMatchingChildren = exports.findNewChromiumChildPid = exports.killProcessTree = exports.gracefulCloseWithTreeKill = exports.liveBrowserRegistry = exports.REPO_SWITCH_REMOVED_FRACTION = exports.MAX_MANIFEST_FILES = exports.toDiffSummary = exports.isLikelyTestFile = exports.sanitizeRepoRelPath = exports.sha256Hex = exports.hashFiles = exports.enumerateTestFiles = exports.buildNextManifest = exports.detectRepoSwitch = exports.classifyImportDiff = exports.parseImportManifest = exports.REPO_ANALYSIS_SCHEMA_VERSION = exports.validateSourceEndpoints = exports.validateAuthoredTest = exports.validateRepoMapFile = exports.validateRepoMemoryFile = exports.buildTestingStandardsSection = exports.buildRepoAuthorSystemRules = exports.buildRepoAuthorKickoff = exports.buildRepoAuthorContractMd = exports.buildRepoMapSystemRules = exports.buildRepoMapKickoff = exports.buildRepoMapContractMd = exports.buildRepoMemorySystemRules = exports.buildRepoMemoryKickoff = exports.buildRepoMemoryContractMd = exports.runRepoAnalysisOnRunner = exports.IMPORT_SCHEMA_VERSION = exports.validateImportResultFile = exports.validateImportedTest = exports.buildImportSystemRules = exports.buildImportKickoff = exports.buildImportContractMd = void 0;
337989
- exports.UNSUPPORTED_RENDERER_PREFIX = exports.UnsupportedRendererError = exports.buildCanvasModeAuthoringAddendum = exports.buildUnsupportedRendererMessage = void 0;
338046
+ exports.extractZipSafely = exports.downloadArchiveCapped = exports.detectArchiveKind = exports.acquireRepoForImport = exports.runFrameworkImportOnRunner = exports.getAgenticEngine = exports.resolveRefFromSnapshot = exports.replayAuthRecipeIntoBrowser = exports.runRegisterCaptureRun = exports.runLoginCaptureRun = exports.filterLoginCaptureCredentials = exports.buildLoginCaptureCredentials = exports.isReservedRunnerEnvVar = exports.RESERVED_RUNNER_ENV_VARS = exports.AUTH_MARKER_VERSION = exports.buildHealAuthStamp = exports.extractAuthRegion = exports.upsertAuthBlock = exports.buildAuthRecipe = exports.commandToReplayStep = exports.buildReplayPlan = exports.absoluteRoute = exports.renderReplaySettleArrow = exports.renderReplayClickArrow = exports.renderAuthFn = exports.canonicalizeRoute = exports.executeGrokPerBatchHeal = exports.executeGrokPerTestHeal = exports.headerVal = exports.classifyAuthType = exports.isTextExcerptable = exports.isStaticAssetByExt = exports.isApiCall = exports.buildApiCallSummary = exports.computeMobileHealOutcome = exports.detectMobileStepSecretLeak = exports.redactMobileSecretsFromText = exports.MOBILE_LIVE_HEAL_SYSTEM_PROMPT = exports.MOBILE_SCRIPT_HEAL_SYSTEM_PROMPT = exports.executeMobileLiveHeal = exports.executeMobileTestWithHealing = exports.executeMobileScriptDrivenHeal = exports.prepareMobileScenarioAppState = exports.runMobileGeneratePhase = exports.runMobileAIPlanner = exports.buildMobileSiteMap = exports.formatMobileEvidenceForPlanner = exports.MOBILE_SCENARIO_SYSTEM_PROMPT = exports.MOBILE_SURVEY_SYSTEM_PROMPT = exports.runMobileExplorePhase = void 0;
338047
+ exports.decideAppRenderType = exports.detectCanvasApp = exports.detectRateLimitBlock = exports.isSafeCanonicalRedirect = exports.resolveBaseUrlPreflight = exports.checkBaseUrlRedirect = exports.stripJsonFences = exports.scrubCredentials = exports.withAIRetry = exports.snapshotMatchingChildren = exports.findNewChromiumChildPid = exports.killProcessTree = exports.gracefulCloseWithTreeKill = exports.liveBrowserRegistry = exports.REPO_SWITCH_REMOVED_FRACTION = exports.MAX_MANIFEST_FILES = exports.toDiffSummary = exports.isLikelyTestFile = exports.sanitizeRepoRelPath = exports.sha256Hex = exports.hashFiles = exports.enumerateTestFiles = exports.buildNextManifest = exports.detectRepoSwitch = exports.classifyImportDiff = exports.parseImportManifest = exports.REPO_ANALYSIS_SCHEMA_VERSION = exports.validateSourceEndpoints = exports.validateAuthoredTest = exports.validateRepoMapFile = exports.validateRepoMemoryFile = exports.buildTestingStandardsSection = exports.buildRepoAuthorSystemRules = exports.buildRepoAuthorKickoff = exports.buildRepoAuthorContractMd = exports.buildRepoMapSystemRules = exports.buildRepoMapKickoff = exports.buildRepoMapContractMd = exports.buildRepoMemorySystemRules = exports.buildRepoMemoryKickoff = exports.buildRepoMemoryContractMd = exports.runRepoAnalysisOnRunner = exports.IMPORT_SCHEMA_VERSION = exports.validateImportResultFile = exports.validateImportedTest = exports.buildImportSystemRules = exports.buildImportKickoff = exports.buildImportContractMd = exports.MAX_ARCHIVE_BYTES = exports.isUnsafeEntryName = void 0;
338048
+ exports.UNSUPPORTED_RENDERER_PREFIX = exports.UnsupportedRendererError = exports.buildCanvasModeAuthoringAddendum = exports.buildUnsupportedRendererMessage = exports.modelSupportsVision = exports.decideCanvasStrategy = void 0;
337990
338049
  __exportStar(require_ai_provider(), exports);
337991
338050
  __exportStar(require_mobile_types(), exports);
337992
338051
  __exportStar(require_mobile_source_parser(), exports);
@@ -338135,6 +338194,12 @@ var require_dist2 = __commonJS({
338135
338194
  return auth_recipe_js_1.isReservedRunnerEnvVar;
338136
338195
  } });
338137
338196
  var auth_capture_run_js_1 = require_auth_capture_run();
338197
+ Object.defineProperty(exports, "buildLoginCaptureCredentials", { enumerable: true, get: function() {
338198
+ return auth_capture_run_js_1.buildLoginCaptureCredentials;
338199
+ } });
338200
+ Object.defineProperty(exports, "filterLoginCaptureCredentials", { enumerable: true, get: function() {
338201
+ return auth_capture_run_js_1.filterLoginCaptureCredentials;
338202
+ } });
338138
338203
  Object.defineProperty(exports, "runLoginCaptureRun", { enumerable: true, get: function() {
338139
338204
  return auth_capture_run_js_1.runLoginCaptureRun;
338140
338205
  } });
@@ -338361,7 +338426,7 @@ var require_package4 = __commonJS({
338361
338426
  "package.json"(exports, module) {
338362
338427
  module.exports = {
338363
338428
  name: "@validate.qa/runner",
338364
- version: "1.0.44",
338429
+ version: "1.0.46",
338365
338430
  description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
338366
338431
  bin: {
338367
338432
  "validate-runner": "dist/cli.js"
@@ -338500,6 +338565,7 @@ function authPlanFor(tags, playwrightCode) {
338500
338565
  }
338501
338566
 
338502
338567
  // src/version-check.ts
338568
+ init_dist();
338503
338569
  var RUNNER_NPM_PACKAGE = "@validate.qa/runner";
338504
338570
  var NPM_LATEST_URL = `https://registry.npmjs.org/${encodeURIComponent(RUNNER_NPM_PACKAGE)}/latest`;
338505
338571
  var DEFAULT_TIMEOUT_MS = 8e3;
@@ -338531,10 +338597,10 @@ function isVersionOutdated(current, latest) {
338531
338597
  return cmp === -1;
338532
338598
  }
338533
338599
  function shouldSkipVersionCheck() {
338534
- if (process.env.RUNNER_CLOUD === "true") {
338600
+ if (parseBoolFlag(process.env.RUNNER_CLOUD)) {
338535
338601
  return "cloud runner (RUNNER_CLOUD=true)";
338536
338602
  }
338537
- if (process.env.VALIDATE_RUNNER_ALLOW_OUTDATED === "1" || process.env.VALIDATE_RUNNER_ALLOW_OUTDATED === "true") {
338603
+ if (parseBoolFlag(process.env.VALIDATE_RUNNER_ALLOW_OUTDATED)) {
338538
338604
  return "VALIDATE_RUNNER_ALLOW_OUTDATED is set";
338539
338605
  }
338540
338606
  return null;
@@ -345226,7 +345292,7 @@ function attachMobileDiscoveryNetworkContext(calls, result, appId) {
345226
345292
  }
345227
345293
  var runnerPackage = require_package4();
345228
345294
  var SECRET_VAR_PATTERN = /password|secret|token|api[_]?key|pass\b|credential|bearer|pat\b/i;
345229
- var IS_CLOUD = process.env.RUNNER_CLOUD === "true";
345295
+ var IS_CLOUD = parseBoolFlag(process.env.RUNNER_CLOUD);
345230
345296
  var RUNNER_NAME = runnerPackage.name ?? "@validate.qa/runner";
345231
345297
  var RUNNER_VERSION = runnerPackage.version ?? "0.0.0";
345232
345298
  var RUNNER_BUILD_ID = process.env.VALIDATE_RUNNER_BUILD_ID ?? process.env.RAILWAY_GIT_COMMIT_SHA ?? process.env.GIT_COMMIT_SHA ?? process.env.SOURCE_VERSION;
@@ -348115,9 +348181,9 @@ async function startRunner(opts) {
348115
348181
  log.info(`Project: ${projectId}`);
348116
348182
  log.info(`Mode: \u{1F3AD} Playwright Native${enableMobile ? " + \u{1F4F1} Mobile" : ""}${enableMobile && enableMobileTunnel ? " \u{1F310} Tunnel" : ""}`);
348117
348183
  log.info(`Interval: ${pollIntervalMs}ms`);
348118
- if (process.env.DISCOVERY_PROMPT_V3 === "true") {
348184
+ if (parseBoolFlag(process.env.DISCOVERY_PROMPT_V3)) {
348119
348185
  log.ok("Discovery prompt: V3 (per-turn rebuild) \u2014 DISCOVERY_PROMPT_V3=true");
348120
- } else if (process.env.DISCOVERY_PROMPT_V3 === "false") {
348186
+ } else if (!parseBoolFlag(process.env.DISCOVERY_PROMPT_V3, true)) {
348121
348187
  log.ok("Discovery prompt: V2.5 (full transcript + control brief) \u2014 DISCOVERY_PROMPT_V3=false");
348122
348188
  } else {
348123
348189
  log.ok("Discovery prompt: V3 (per-turn rebuild, default) \u2014 set DISCOVERY_PROMPT_V3=false for V2.5");
@@ -348143,7 +348209,7 @@ async function startRunner(opts) {
348143
348209
  // WebView. Enable at mobile-runner startup even when the emulator is
348144
348210
  // booted later; the feature is driver-scoped and remains dormant on
348145
348211
  // iOS. Operators may explicitly opt out.
348146
- enableChromedriverAutodownload: process.env.VALIDATEQA_CHROMEDRIVER_AUTODOWNLOAD !== "false"
348212
+ enableChromedriverAutodownload: parseBoolFlag(process.env.VALIDATEQA_CHROMEDRIVER_AUTODOWNLOAD, true)
348147
348213
  });
348148
348214
  log.ok("\u{1F4F1} Appium server started");
348149
348215
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@validate.qa/runner",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
5
5
  "bin": {
6
6
  "validate-runner": "dist/cli.js"