@validate.qa/runner 1.0.92 → 1.0.94

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 +319 -34
  2. package/dist/cli.mjs +319 -34
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8555,6 +8555,162 @@ var require_scrub_credentials = __commonJS({
8555
8555
  }
8556
8556
  });
8557
8557
 
8558
+ // ../runner-core/dist/services/google-signin.js
8559
+ var require_google_signin = __commonJS({
8560
+ "../runner-core/dist/services/google-signin.js"(exports2) {
8561
+ "use strict";
8562
+ Object.defineProperty(exports2, "__esModule", { value: true });
8563
+ exports2.GOOGLE_SIGNIN_ENV_KEYS = exports2.GOOGLE_SIGNIN_PASSWORD_KEY = void 0;
8564
+ exports2.loadGoogleSignInConfig = loadGoogleSignInConfig;
8565
+ exports2.mergeGoogleSignInSecrets = mergeGoogleSignInSecrets;
8566
+ exports2.googleSignInGuidanceOpts = googleSignInGuidanceOpts;
8567
+ exports2.googleSignInAllowedEmails = googleSignInAllowedEmails;
8568
+ exports2.collectGoogleSignInEnv = collectGoogleSignInEnv;
8569
+ exports2.isGoogleAccountsUrl = isGoogleAccountsUrl;
8570
+ exports2.googleSignInCredentialMismatch = googleSignInCredentialMismatch;
8571
+ exports2.generateTotp = generateTotp;
8572
+ exports2.buildGoogleSignInPromptSection = buildGoogleSignInPromptSection;
8573
+ var node_crypto_1 = require("crypto");
8574
+ exports2.GOOGLE_SIGNIN_PASSWORD_KEY = "GOOGLE_SIGNIN_PASSWORD";
8575
+ var APP_REGISTER_CREDENTIAL_KEYS = /^(TEST_|E2E_|QA_)?(USER_?EMAIL|USER_?PASSWORD|USER_?NAME|USERNAME)$/i;
8576
+ exports2.GOOGLE_SIGNIN_ENV_KEYS = [
8577
+ "GOOGLE_SIGNIN_PASSWORD",
8578
+ "GOOGLE_SIGNIN_EMAIL",
8579
+ "GOOGLE_SIGNIN_TOTP_SECRET"
8580
+ ];
8581
+ function trimEnv(env, name) {
8582
+ const value = env[name]?.trim();
8583
+ return value ? value : void 0;
8584
+ }
8585
+ function loadGoogleSignInConfig(env = process.env) {
8586
+ const password = trimEnv(env, "GOOGLE_SIGNIN_PASSWORD");
8587
+ if (!password)
8588
+ return null;
8589
+ const email = (trimEnv(env, "GOOGLE_SIGNIN_EMAIL") ?? trimEnv(env, "VERIFICATION_INBOX_ADDRESS"))?.toLowerCase();
8590
+ if (!email || !email.includes("@"))
8591
+ return null;
8592
+ const totpSecret = trimEnv(env, "GOOGLE_SIGNIN_TOTP_SECRET");
8593
+ return {
8594
+ email,
8595
+ password,
8596
+ passwordKey: exports2.GOOGLE_SIGNIN_PASSWORD_KEY,
8597
+ totpSecret,
8598
+ totpAvailable: !!totpSecret
8599
+ };
8600
+ }
8601
+ function mergeGoogleSignInSecrets(credentials, env = process.env) {
8602
+ const cfg = loadGoogleSignInConfig(env);
8603
+ if (!cfg)
8604
+ return credentials;
8605
+ if (credentials[exports2.GOOGLE_SIGNIN_PASSWORD_KEY])
8606
+ return credentials;
8607
+ return { ...credentials, [exports2.GOOGLE_SIGNIN_PASSWORD_KEY]: cfg.password };
8608
+ }
8609
+ function googleSignInGuidanceOpts(env = process.env) {
8610
+ const cfg = loadGoogleSignInConfig(env);
8611
+ if (!cfg)
8612
+ return void 0;
8613
+ return {
8614
+ googleEmail: cfg.email,
8615
+ googlePasswordKey: cfg.passwordKey,
8616
+ googleTotpAvailable: cfg.totpAvailable
8617
+ };
8618
+ }
8619
+ function googleSignInAllowedEmails(env = process.env) {
8620
+ const cfg = loadGoogleSignInConfig(env);
8621
+ return cfg ? [cfg.email] : [];
8622
+ }
8623
+ function collectGoogleSignInEnv(env = process.env) {
8624
+ const out = {};
8625
+ for (const key of exports2.GOOGLE_SIGNIN_ENV_KEYS) {
8626
+ const value = env[key]?.trim();
8627
+ if (value)
8628
+ out[key] = value;
8629
+ }
8630
+ return out;
8631
+ }
8632
+ function isGoogleAccountsUrl(url) {
8633
+ if (!url)
8634
+ return false;
8635
+ try {
8636
+ const host = new URL(url).hostname.toLowerCase();
8637
+ return host === "accounts.google.com" || host.endsWith(".google.com") && host.includes("accounts");
8638
+ } catch {
8639
+ return /accounts\.google\.com/i.test(url);
8640
+ }
8641
+ }
8642
+ function googleSignInCredentialMismatch(pageUrl, credentialKey, opts) {
8643
+ const configured = opts?.configured ?? !!loadGoogleSignInConfig(opts?.env);
8644
+ if (!configured)
8645
+ return null;
8646
+ const onGoogle = isGoogleAccountsUrl(pageUrl);
8647
+ if (onGoogle) {
8648
+ if (credentialKey === exports2.GOOGLE_SIGNIN_PASSWORD_KEY)
8649
+ return null;
8650
+ if (APP_REGISTER_CREDENTIAL_KEYS.test(credentialKey)) {
8651
+ return `fill_credential: this is Google account login (accounts.google.com), not app email signup. Do not use ${credentialKey}. Type the BARE Google email with browser_type, then fill_credential with credentialKey ${exports2.GOOGLE_SIGNIN_PASSWORD_KEY}. Do not click Continue with phone / SMS OTP when Continue with Google is available.`;
8652
+ }
8653
+ return null;
8654
+ }
8655
+ if (credentialKey === exports2.GOOGLE_SIGNIN_PASSWORD_KEY) {
8656
+ return `fill_credential: ${exports2.GOOGLE_SIGNIN_PASSWORD_KEY} is only for accounts.google.com. Click Continue with Google first (not Continue with phone). Phone / "Mobile or email" is not app email signup.`;
8657
+ }
8658
+ return null;
8659
+ }
8660
+ function generateTotp(secret, atMs = Date.now(), stepSeconds = 30, digits = 6) {
8661
+ const key = decodeBase32(secret);
8662
+ const counter = Math.floor(atMs / 1e3 / stepSeconds);
8663
+ const buf = Buffer.alloc(8);
8664
+ buf.writeUInt32BE(Math.floor(counter / 4294967296), 0);
8665
+ buf.writeUInt32BE(counter >>> 0, 4);
8666
+ const hmac = (0, node_crypto_1.createHmac)("sha1", key).update(buf).digest();
8667
+ const offset = hmac[hmac.length - 1] & 15;
8668
+ const bin = (hmac[offset] & 127) << 24 | hmac[offset + 1] << 16 | hmac[offset + 2] << 8 | hmac[offset + 3];
8669
+ const otp = bin % 10 ** digits;
8670
+ return String(otp).padStart(digits, "0");
8671
+ }
8672
+ function decodeBase32(input) {
8673
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
8674
+ const cleaned = input.toUpperCase().replace(/[\s=-]+/g, "");
8675
+ let bits = 0;
8676
+ let value = 0;
8677
+ const out = [];
8678
+ for (const ch of cleaned) {
8679
+ const idx = alphabet.indexOf(ch);
8680
+ if (idx < 0)
8681
+ continue;
8682
+ value = value << 5 | idx;
8683
+ bits += 5;
8684
+ if (bits >= 8) {
8685
+ bits -= 8;
8686
+ out.push(value >>> bits & 255);
8687
+ }
8688
+ }
8689
+ return Buffer.from(out);
8690
+ }
8691
+ function buildGoogleSignInPromptSection(opts, variant) {
8692
+ const totpNative = opts.googleTotpAvailable ? " If Google asks for a 2-step / Authenticator code, call `provision_google_totp` and type the 6-digit `code` it returns (do not invent a code)." : " If Google asks for 2-step verification and you have no authenticator code tool, STOP and report Google SSO as BLOCKED (2FA not configured on this runner).";
8693
+ const totpCli = opts.googleTotpAvailable ? " If Google asks for a 2-step / Authenticator code, call `inbox_google_totp` and type the 6-digit `code` it returns." : " If Google asks for 2-step verification, STOP and report Google SSO as BLOCKED (2FA not configured on this runner).";
8694
+ const totp = variant === "cli" ? totpCli : totpNative;
8695
+ const fill = variant === "cli" ? `fill_credential with credentialKey \`${opts.googlePasswordKey}\`` : `\`fill_credential\` (credentialKey \`${opts.googlePasswordKey}\`)`;
8696
+ const plainProvision = variant === "cli" ? "`inbox_provision_identity` with `plain: true`" : "`provision_identity` with `plain: true`";
8697
+ return `
8698
+ Google / Gmail SSO (use this when the APP has no Create-account email form):
8699
+ - App email+password SIGNUP means a form ON THIS APP to create an account (Sign up / Create account / Register, including after "Sign up with email"). That is FIRST. Do not use Google if that form exists.
8700
+ - These are NOT app email signup \u2014 do not treat them as the email playbook, and do not fill TEST_USER_EMAIL / TEST_USER_PASSWORD into them when Continue with Google is available:
8701
+ - "Continue with phone" / SMS / OTP
8702
+ - "Mobile or email" / phone-number identity on a Sign in page
8703
+ - Google's own email and password fields on accounts.google.com
8704
+ - If Sign in offers Continue with Google (and there is no app Create-account email form): click Continue with Google. Do NOT click Continue with phone for this registration.
8705
+ - If a Google popup or tab opens, switch to it. On accounts.google.com, type the BARE Google account email \`${opts.googleEmail}\` (no plus-tag) with browser_type, click Next, then fill the Google password with ${fill}. NEVER type the Google password as text, NEVER use TEST_USER_PASSWORD here, NEVER use the IMAP app password.
8706
+ - Click Next.${totp}
8707
+ - Click Continue / Allow on any consent screen, then return to the app tab.
8708
+ - If the app then emails a verification code/link, first call ${plainProvision} (Google SSO uses the bare inbox address, not the +tag), then complete it with the inbox tools as usual.
8709
+ - Register / Google-sign-in ONCE per run. If Google says the account is already used on this app, that is success \u2014 continue as the logged-in user.`;
8710
+ }
8711
+ }
8712
+ });
8713
+
8558
8714
  // ../runner-core/dist/services/credential-tools.js
8559
8715
  var require_credential_tools = __commonJS({
8560
8716
  "../runner-core/dist/services/credential-tools.js"(exports2) {
@@ -8573,17 +8729,18 @@ var require_credential_tools = __commonJS({
8573
8729
  exports2.mcpResultIsError = mcpResultIsError;
8574
8730
  exports2.aggressiveScrubCredentials = aggressiveScrubCredentials;
8575
8731
  var scrub_credentials_js_1 = require_scrub_credentials();
8732
+ var google_signin_js_1 = require_google_signin();
8576
8733
  exports2.FILL_CREDENTIAL_TOOL = {
8577
8734
  type: "function",
8578
8735
  function: {
8579
8736
  name: "fill_credential",
8580
- description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. The list of available credential keys is in the system prompt.',
8737
+ description: 'Fill a stored credential VALUE into a form field. ALWAYS use this instead of `browser_type` for ANY email/password/token/auth field. You pass the variable KEY (e.g. "TEST_USER_EMAIL") and the runner injects the real value server-side \u2014 you never see the secret. On accounts.google.com use GOOGLE_SIGNIN_PASSWORD (never TEST_USER_PASSWORD). The list of available credential keys is in the system prompt.',
8581
8738
  parameters: {
8582
8739
  type: "object",
8583
8740
  properties: {
8584
8741
  credentialKey: {
8585
8742
  type: "string",
8586
- description: 'The credential variable name (e.g. "TEST_USER_EMAIL", "TEST_USER_PASSWORD", "TEST_ADMIN_EMAIL"). Must be one of the keys listed in the Test Credentials section of the prompt.'
8743
+ description: 'The credential variable name (e.g. "TEST_USER_EMAIL", "TEST_USER_PASSWORD", "GOOGLE_SIGNIN_PASSWORD"). Must be one of the keys listed in the Test Credentials section of the prompt.'
8587
8744
  },
8588
8745
  element: {
8589
8746
  type: "string",
@@ -8739,6 +8896,22 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
8739
8896
  return entries.map(([k, v]) => `- **${k}**: \`${v}\``).join("\n");
8740
8897
  }
8741
8898
  var DEFAULT_MAX_RESULT_CHARS = 15e3;
8899
+ var PAGE_URL_RE = /Page URL:\s*(\S+)/i;
8900
+ async function peekPageUrl(mcpClient) {
8901
+ try {
8902
+ const mcpResult = await mcpClient.callTool({ name: "browser_snapshot", arguments: {} });
8903
+ const { text } = parseMcpContent(mcpResult);
8904
+ const match = text.match(PAGE_URL_RE);
8905
+ return match?.[1]?.replace(/[),.;]+$/, "");
8906
+ } catch {
8907
+ return void 0;
8908
+ }
8909
+ }
8910
+ function googleFillBlocked(pageUrl, credentialKey, credentials) {
8911
+ return (0, google_signin_js_1.googleSignInCredentialMismatch)(pageUrl, credentialKey, {
8912
+ configured: !!credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]
8913
+ });
8914
+ }
8742
8915
  async function handleFillCredential(toolArgs, ctx) {
8743
8916
  const key = typeof toolArgs.credentialKey === "string" ? toolArgs.credentialKey : "";
8744
8917
  const element = typeof toolArgs.element === "string" ? toolArgs.element : "";
@@ -8760,6 +8933,13 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
8760
8933
  didMutate: false
8761
8934
  };
8762
8935
  }
8936
+ if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
8937
+ const pageUrl = await peekPageUrl(ctx.mcpClient);
8938
+ const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
8939
+ if (blocked) {
8940
+ return { content: JSON.stringify({ error: blocked }), didMutate: false };
8941
+ }
8942
+ }
8763
8943
  const underlyingArgs = { element, ref, text: value, submit };
8764
8944
  const mcpResult = await ctx.mcpClient.callTool({ name: "browser_type", arguments: underlyingArgs });
8765
8945
  const mcpFailed = mcpResultIsError(mcpResult);
@@ -8798,6 +8978,16 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
8798
8978
  }
8799
8979
  resolved.push({ field, value });
8800
8980
  }
8981
+ if (ctx.credentials[google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY]) {
8982
+ const pageUrl = await peekPageUrl(ctx.mcpClient);
8983
+ for (const f of fields) {
8984
+ const key = typeof f.credentialKey === "string" ? f.credentialKey : typeof f.key === "string" ? f.key : "";
8985
+ const blocked = googleFillBlocked(pageUrl, key, ctx.credentials);
8986
+ if (blocked) {
8987
+ return { content: JSON.stringify({ error: blocked }), didMutate: false };
8988
+ }
8989
+ }
8990
+ }
8801
8991
  if (missing.length > 0) {
8802
8992
  const available = Object.keys(ctx.credentials).filter((k) => ctx.credentials[k]).join(", ") || "(none configured)";
8803
8993
  return {
@@ -8849,6 +9039,14 @@ CREDENTIAL ROTATION (required when the STORED user's secret changes \u2014 read
8849
9039
  didMutate: false
8850
9040
  };
8851
9041
  }
9042
+ if (key === google_signin_js_1.GOOGLE_SIGNIN_PASSWORD_KEY) {
9043
+ return {
9044
+ content: JSON.stringify({
9045
+ error: "set_credential: GOOGLE_SIGNIN_PASSWORD is a runner-operator secret and cannot be persisted to project Test Data"
9046
+ }),
9047
+ didMutate: false
9048
+ };
9049
+ }
8852
9050
  if (!(key in ctx.credentials)) {
8853
9051
  const available = Object.keys(ctx.credentials).filter((k) => ctx.credentials[k]).join(", ") || "(none configured)";
8854
9052
  return {
@@ -74110,7 +74308,7 @@ var require_inbox_tools = __commonJS({
74110
74308
  "../runner-core/dist/services/inbox-tools.js"(exports2) {
74111
74309
  "use strict";
74112
74310
  Object.defineProperty(exports2, "__esModule", { value: true });
74113
- exports2.EMAIL_VERIFICATION_UNAVAILABLE_OVERRIDE_BLOCK = exports2.INBOX_TOOL_NAMES = exports2.INBOX_TOOLS = exports2.OPEN_VERIFICATION_LINK_TOOL = exports2.GET_VERIFICATION_LINK_TOOL = exports2.EXTRACT_VERIFICATION_CODE_TOOL = exports2.READ_VERIFICATION_EMAIL_TOOL = exports2.WAIT_FOR_VERIFICATION_TOOL = exports2.CHECK_INBOX_TOOL = exports2.PROVISION_IDENTITY_TOOL = void 0;
74311
+ exports2.EMAIL_VERIFICATION_UNAVAILABLE_OVERRIDE_BLOCK = exports2.INBOX_TOOL_NAMES = exports2.INBOX_TOOLS = exports2.PROVISION_GOOGLE_TOTP_TOOL = exports2.OPEN_VERIFICATION_LINK_TOOL = exports2.GET_VERIFICATION_LINK_TOOL = exports2.EXTRACT_VERIFICATION_CODE_TOOL = exports2.READ_VERIFICATION_EMAIL_TOOL = exports2.WAIT_FOR_VERIFICATION_TOOL = exports2.CHECK_INBOX_TOOL = exports2.PROVISION_IDENTITY_TOOL = void 0;
74114
74312
  exports2.createInboxRunState = createInboxRunState;
74115
74313
  exports2.dispatchInboxTool = dispatchInboxTool;
74116
74314
  exports2.isPublicHttpUrl = isPublicHttpUrl;
@@ -74125,6 +74323,7 @@ var require_inbox_tools = __commonJS({
74125
74323
  exports2.clearThrowawayRegisterSeed = clearThrowawayRegisterSeed;
74126
74324
  exports2.buildInboxAgentsGuidance = buildInboxAgentsGuidance;
74127
74325
  var verification_inbox_js_1 = require_verification_inbox();
74326
+ var google_signin_js_1 = require_google_signin();
74128
74327
  function createInboxRunState(config, opts = {}) {
74129
74328
  const baseEmail = config.address;
74130
74329
  const tag = opts.tag !== void 0 ? opts.tag : opts.tagSeed ? (0, verification_inbox_js_1.deriveProjectInboxTag)(opts.tagSeed, opts.projectScope) : null;
@@ -74246,6 +74445,14 @@ var require_inbox_tools = __commonJS({
74246
74445
  }
74247
74446
  }
74248
74447
  };
74448
+ exports2.PROVISION_GOOGLE_TOTP_TOOL = {
74449
+ type: "function",
74450
+ function: {
74451
+ name: "provision_google_totp",
74452
+ description: "Return a one-time 6-digit Authenticator code for the operator Google account. Call this ONLY when Google Sign-In shows a 2-step / Authenticator challenge after you submitted the Google password. Type the returned code into the Google prompt. Do not invent a code.",
74453
+ parameters: { type: "object", properties: {} }
74454
+ }
74455
+ };
74249
74456
  exports2.INBOX_TOOLS = [
74250
74457
  exports2.PROVISION_IDENTITY_TOOL,
74251
74458
  exports2.CHECK_INBOX_TOOL,
@@ -74253,7 +74460,8 @@ var require_inbox_tools = __commonJS({
74253
74460
  exports2.READ_VERIFICATION_EMAIL_TOOL,
74254
74461
  exports2.EXTRACT_VERIFICATION_CODE_TOOL,
74255
74462
  exports2.GET_VERIFICATION_LINK_TOOL,
74256
- exports2.OPEN_VERIFICATION_LINK_TOOL
74463
+ exports2.OPEN_VERIFICATION_LINK_TOOL,
74464
+ exports2.PROVISION_GOOGLE_TOTP_TOOL
74257
74465
  ];
74258
74466
  exports2.INBOX_TOOL_NAMES = new Set(exports2.INBOX_TOOLS.map((t) => t.function.name));
74259
74467
  var DEFAULT_MAX_RESULT_CHARS = 8e3;
@@ -74265,7 +74473,7 @@ var require_inbox_tools = __commonJS({
74265
74473
  }
74266
74474
  var INBOX_AUTH_DEAD_GUIDANCE = "the inbox authentication is PERMANENTLY rejected (revoked/wrong app password) \u2014 STOP calling inbox tools; none of them can succeed this run. Treat email verification as UNAVAILABLE: hard-stop at any emailed code/link wall, NEVER type a guessed code, and report verification-gated flows as BLOCKED (blockedReason: inbox authentication failed). Continue with publicly reachable coverage.";
74267
74475
  async function dispatchInboxTool(toolName, toolArgs, ctx) {
74268
- if (ctx.state.authDead) {
74476
+ if (ctx.state.authDead && toolName !== "provision_google_totp") {
74269
74477
  return err(`${toolName} skipped: ${INBOX_AUTH_DEAD_GUIDANCE}`);
74270
74478
  }
74271
74479
  try {
@@ -74284,6 +74492,8 @@ var require_inbox_tools = __commonJS({
74284
74492
  return await handleGetLink(toolArgs, ctx);
74285
74493
  case "open_verification_link":
74286
74494
  return await handleOpenLink(toolArgs, ctx);
74495
+ case "provision_google_totp":
74496
+ return handleProvisionGoogleTotp();
74287
74497
  default:
74288
74498
  return err(`inbox dispatch: unknown tool "${toolName}"`);
74289
74499
  }
@@ -74459,6 +74669,20 @@ var require_inbox_tools = __commonJS({
74459
74669
  didMutate: !failed
74460
74670
  };
74461
74671
  }
74672
+ function handleProvisionGoogleTotp(env = process.env) {
74673
+ const cfg = (0, google_signin_js_1.loadGoogleSignInConfig)(env);
74674
+ if (!cfg) {
74675
+ return err("Google SSO is not configured on this runner (GOOGLE_SIGNIN_PASSWORD unset). Prefer email-field signup, or report Google SSO as BLOCKED.");
74676
+ }
74677
+ if (!cfg.totpSecret) {
74678
+ return err("Google Authenticator 2FA is not configured on this runner (GOOGLE_SIGNIN_TOTP_SECRET unset). STOP and report Google SSO as BLOCKED (2FA not configured).");
74679
+ }
74680
+ return ok({
74681
+ code: (0, google_signin_js_1.generateTotp)(cfg.totpSecret),
74682
+ digits: 6,
74683
+ instructions: "Type this 6-digit code into the Google 2-step / Authenticator prompt. Do not reuse it later \u2014 call this tool again if Google asks for another code."
74684
+ });
74685
+ }
74462
74686
  function requireProvisioned(ctx) {
74463
74687
  if (ctx.state.provisioned)
74464
74688
  return null;
@@ -74593,7 +74817,7 @@ var require_inbox_tools = __commonJS({
74593
74817
  ${where} You register using ONE real, monitored email (\`${opts.email}\`) and can complete email-verification (OTP code or confirmation link) end-to-end. This OVERRIDES the general "do not submit forms" rule for the signup/registration form ONLY.
74594
74818
 
74595
74819
  Steps:
74596
- 1. Navigate to the Sign Up / Register page (click the link in the UI).
74820
+ 1. Navigate to the Sign Up / Register / Sign in page (click the link in the UI). FIRST look for an app Create-account email+password form (including after "Sign up with email").${opts.googleEmail && opts.googlePasswordKey ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
74597
74821
  2. Call \`provision_identity\` \u2192 it returns the email to register with (\`${opts.email}\`). The \`+\` part is a normal sub-address that still lands in our inbox.
74598
74822
  3. Fill the signup form: type that email into the email field with \`browser_type\` (this generated inbox email is intentionally visible and is allowed for registration); fill the password field with single-field \`fill_credential\` (credentialKey \`${opts.passwordKey}\`); fill any name/other required fields with simple test values. Do NOT use \`fill_credential_form\` for registration.
74599
74823
  - If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`provision_identity\` again with \`plain: true\` and use the bare address it returns instead.
@@ -74611,6 +74835,11 @@ Rules:
74611
74835
  - The provisioned email is reused for this project; if signup says it is ALREADY registered, the account already exists \u2014 log in with that email + the \`${opts.passwordKey}\` password instead of registering again.
74612
74836
  - You register ONCE per run. After you submit the signup form in step 4, NEVER submit it again and NEVER create a second account \u2014 even if verification is slow, even if a later login attempt fails. Recover by re-polling \`wait_for_verification\` (and at most one "Resend"), not by re-registering.
74613
74837
  - Only call the verification tools AFTER submitting the signup form, and pass the site as \`senderMatch\` so you read YOUR verification email (the inbox is shared).
74838
+ ${opts.googleEmail && opts.googlePasswordKey ? (0, google_signin_js_1.buildGoogleSignInPromptSection)({
74839
+ googleEmail: opts.googleEmail,
74840
+ googlePasswordKey: opts.googlePasswordKey,
74841
+ googleTotpAvailable: opts.googleTotpAvailable
74842
+ }, "native") : ""}
74614
74843
  `;
74615
74844
  }
74616
74845
  exports2.EMAIL_VERIFICATION_UNAVAILABLE_OVERRIDE_BLOCK = `## EMAIL VERIFICATION UNAVAILABLE \u2014 FINAL OVERRIDE (supersedes any instruction above)
@@ -74765,11 +74994,12 @@ This project asked to REGISTER a new account, but this runner CANNOT receive ema
74765
74994
  }
74766
74995
  return false;
74767
74996
  }
74768
- function buildInboxAgentsGuidance(email, passwordKey) {
74997
+ function buildInboxAgentsGuidance(email, passwordKey, google) {
74998
+ const googleBlock = google ? (0, google_signin_js_1.buildGoogleSignInPromptSection)(google, "cli") : "";
74769
74999
  return `## Account registration & email verification (ENABLED)
74770
75000
  This run registers a new account using our ONE real, monitored inbox (the address \`${email}\` \u2014 the "+" part is a normal sub-address that still lands in our inbox) and can complete email verification end-to-end. This overrides any "do not submit forms" guidance for the signup form only.
74771
75001
 
74772
- 1. Go to the Sign Up / Register page.
75002
+ 1. Go to the Sign Up / Register / Sign in page. FIRST look for an app Create-account email+password form (including after "Sign up with email").${google ? ' "Continue with phone", SMS OTP, and "Mobile or email" on a Sign in page are NOT that form \u2014 if Continue with Google is offered and there is no app Create-account email form, use the Google / Gmail SSO playbook below (do not click Continue with phone).' : ""}
74773
75003
  2. Call \`inbox_provision_identity\` \u2192 it returns the email to register with (\`${email}\`). Type that email into the email field.
74774
75004
  - If the form REJECTS the email (says "invalid email" / will not accept the "+"), call \`inbox_provision_identity\` with \`plain: true\` and use the bare address it returns instead.
74775
75005
  3. Fill the password with the \`${passwordKey}\` credential (use fill_credential). Submit the signup form.
@@ -74780,6 +75010,7 @@ This run registers a new account using our ONE real, monitored inbox (the addres
74780
75010
  - If it returns BOTH, try the code first; if the app insists on the link, open it, then enter the code if the page it lands on asks for one.
74781
75011
  - Otherwise call \`inbox_read_email\` to read the body.
74782
75012
  5. NEVER invent an email address \u2014 always use exactly what \`inbox_provision_identity\` returns. The address is reused for this project; if signup says it is already registered, log in with it + \`${passwordKey}\` instead. Register ONCE per run \u2014 never submit signup twice or make a second account; if verification is slow, re-poll \`inbox_wait_for_verification\` (at most one Resend) instead of re-registering.
75013
+ ${googleBlock}
74783
75014
  `;
74784
75015
  }
74785
75016
  }
@@ -88614,6 +88845,7 @@ var require_browser_config = __commonJS({
88614
88845
  var path_1 = require("path");
88615
88846
  var os_1 = require("os");
88616
88847
  var shared_1 = (init_dist(), __toCommonJS(dist_exports));
88848
+ var google_signin_js_1 = require_google_signin();
88617
88849
  exports2.IS_CLOUD = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
88618
88850
  exports2.CLOUD_ARGS = [
88619
88851
  "--no-sandbox",
@@ -88719,6 +88951,10 @@ var require_browser_config = __commonJS({
88719
88951
  (document.head || document.documentElement).appendChild(style);
88720
88952
 
88721
88953
  // Layer 2: Web Animations API - make instant (preserves completion callbacks)
88954
+ try {
88955
+ Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
88956
+ } catch {}
88957
+
88722
88958
  const origAnimate = Element.prototype.animate;
88723
88959
  Element.prototype.animate = function(keyframes, options) {
88724
88960
  if (typeof options === 'object' && options !== null) {
@@ -88825,6 +89061,20 @@ var require_browser_config = __commonJS({
88825
89061
  return null;
88826
89062
  }
88827
89063
  }
89064
+ function googleSsoCloudLaunch(env = process.env) {
89065
+ if (!(0, shared_1.parseBoolFlag)(env.RUNNER_CLOUD))
89066
+ return null;
89067
+ if (!(0, google_signin_js_1.loadGoogleSignInConfig)(env))
89068
+ return null;
89069
+ const executablePath = getFullChromiumPath();
89070
+ if (!executablePath)
89071
+ return null;
89072
+ return {
89073
+ executablePath,
89074
+ extraArgs: ["--headless=new"],
89075
+ ignoreDefaultArgs: ["--enable-automation"]
89076
+ };
89077
+ }
88828
89078
  function getMCPBrowserConfig2(opts) {
88829
89079
  const userDataDir = opts?.forceIsolated ? null : getTestUserDataDir2();
88830
89080
  const headless = isHeadless2();
@@ -88848,15 +89098,21 @@ var require_browser_config = __commonJS({
88848
89098
  };
88849
89099
  }
88850
89100
  const headlessShellPath = getHeadlessShellPath();
88851
- const useHeadlessShell = headless && headlessShellPath && !opts?.harPath;
89101
+ const googleLaunch = googleSsoCloudLaunch();
89102
+ const useHeadlessShell = headless && headlessShellPath && !opts?.harPath && !googleLaunch;
89103
+ const cloud = (0, shared_1.parseBoolFlag)(process.env.RUNNER_CLOUD);
89104
+ const args = [
89105
+ ...cloud ? exports2.CLOUD_ARGS : ["--disable-blink-features=AutomationControlled"],
89106
+ ...googleLaunch?.extraArgs ?? []
89107
+ ];
88852
89108
  return {
88853
89109
  browserName: "chromium",
88854
89110
  isolated: true,
88855
89111
  launchOptions: {
88856
- headless,
88857
- ...useHeadlessShell ? { executablePath: headlessShellPath } : {},
89112
+ headless: googleLaunch ? false : headless,
89113
+ ...googleLaunch ? { executablePath: googleLaunch.executablePath, ignoreDefaultArgs: googleLaunch.ignoreDefaultArgs } : useHeadlessShell ? { executablePath: headlessShellPath } : {},
88858
89114
  channel: "",
88859
- args: exports2.IS_CLOUD ? exports2.CLOUD_ARGS : ["--disable-blink-features=AutomationControlled"],
89115
+ args,
88860
89116
  ...slowMo > 0 ? { slowMo } : {}
88861
89117
  },
88862
89118
  contextOptions: {
@@ -88869,15 +89125,21 @@ var require_browser_config = __commonJS({
88869
89125
  function getPlaywrightLaunchOptions2(withProfile = false, extraArgs) {
88870
89126
  const headless = isHeadless2();
88871
89127
  const slowMo = getSlowMoMs();
89128
+ const googleLaunch = googleSsoCloudLaunch();
88872
89129
  const baseArgs = exports2.IS_CLOUD ? exports2.CLOUD_ARGS : [
88873
89130
  "--disable-blink-features=AutomationControlled"
88874
89131
  ];
88875
- const mergedArgs = extraArgs && extraArgs.length > 0 ? [...baseArgs, ...extraArgs] : [...baseArgs];
89132
+ const mergedArgs = [
89133
+ ...baseArgs,
89134
+ ...googleLaunch?.extraArgs ?? [],
89135
+ ...extraArgs && extraArgs.length > 0 ? extraArgs : []
89136
+ ];
88876
89137
  return {
88877
- headless,
89138
+ headless: googleLaunch ? false : headless,
88878
89139
  // Use Chrome channel only when a real Chrome user profile is being loaded.
88879
89140
  // In isolated mode, bundled Chromium avoids hard dependency on Chrome installation.
88880
89141
  ...exports2.IS_CLOUD || !withProfile ? {} : { channel: "chrome" },
89142
+ ...googleLaunch ? { executablePath: googleLaunch.executablePath, ignoreDefaultArgs: googleLaunch.ignoreDefaultArgs } : {},
88881
89143
  args: mergedArgs,
88882
89144
  ...slowMo > 0 ? { slowMo } : {}
88883
89145
  };
@@ -320219,6 +320481,7 @@ var require_playwright_mcp_config = __commonJS({
320219
320481
  var promises_1 = require("fs/promises");
320220
320482
  var node_path_1 = require("path");
320221
320483
  var browser_config_js_1 = require_browser_config();
320484
+ var google_signin_js_1 = require_google_signin();
320222
320485
  var PLAYWRIGHT_MCP_VERSION = "0.0.68";
320223
320486
  var INBOX_SECRET_ENV_KEYS = [
320224
320487
  "VERIFICATION_INBOX_HOST",
@@ -320228,7 +320491,10 @@ var require_playwright_mcp_config = __commonJS({
320228
320491
  "VERIFICATION_INBOX_PASSWORD",
320229
320492
  "VERIFICATION_INBOX_ADDRESS",
320230
320493
  "VERIFICATION_INBOX_MAILBOX",
320231
- "VERIFICATION_INBOX_EXTRA_MAILBOXES"
320494
+ "VERIFICATION_INBOX_EXTRA_MAILBOXES",
320495
+ "GOOGLE_SIGNIN_PASSWORD",
320496
+ "GOOGLE_SIGNIN_EMAIL",
320497
+ "GOOGLE_SIGNIN_TOTP_SECRET"
320232
320498
  ];
320233
320499
  function collectInboxSecretEnv() {
320234
320500
  const out = {};
@@ -320269,12 +320535,13 @@ var require_playwright_mcp_config = __commonJS({
320269
320535
  const body = cfg.format === "json" ? buildJsonConfig(cfg) : buildTomlConfig(cfg);
320270
320536
  await (0, promises_1.writeFile)(cfg.configPath, body, { encoding: "utf8", mode: 384 });
320271
320537
  if (!cfg.cdpEndpoint && browser_config_js_1.IS_CLOUD) {
320538
+ const launchOptions = (0, browser_config_js_1.getMCPBrowserConfig)({ forceIsolated: true }).launchOptions ?? {
320539
+ headless: true,
320540
+ args: [...browser_config_js_1.CLOUD_ARGS]
320541
+ };
320272
320542
  const browserConfig = {
320273
320543
  browser: {
320274
- launchOptions: {
320275
- headless: true,
320276
- args: [...browser_config_js_1.CLOUD_ARGS]
320277
- }
320544
+ launchOptions
320278
320545
  }
320279
320546
  };
320280
320547
  await (0, promises_1.writeFile)(mcpBrowserConfigPath(cfg.configPath), JSON.stringify(browserConfig, null, 2) + "\n", { encoding: "utf8", mode: 384 });
@@ -320298,7 +320565,11 @@ var require_playwright_mcp_config = __commonJS({
320298
320565
  ];
320299
320566
  if (cfg.includeCredentialServer && cfg.cdpEndpoint) {
320300
320567
  const serverJs = (0, node_path_1.join)(__dirname, "credential-mcp-server.js");
320301
- blocks.push("[mcp_servers.validateqa_credentials]", 'command = "node"', `args = ["${tomlEscape(serverJs)}"]`, "enabled = true", "startup_timeout_sec = 30", "tool_timeout_sec = 60", "", "[mcp_servers.validateqa_credentials.env]", `CDP_ENDPOINT = "${tomlEscape(cfg.cdpEndpoint)}"`, "");
320568
+ blocks.push("[mcp_servers.validateqa_credentials]", 'command = "node"', `args = ["${tomlEscape(serverJs)}"]`, "enabled = true", "startup_timeout_sec = 30", "tool_timeout_sec = 60", "", "[mcp_servers.validateqa_credentials.env]", `CDP_ENDPOINT = "${tomlEscape(cfg.cdpEndpoint)}"`);
320569
+ for (const [k, v] of Object.entries((0, google_signin_js_1.collectGoogleSignInEnv)())) {
320570
+ blocks.push(`${k} = "${tomlEscape(v)}"`);
320571
+ }
320572
+ blocks.push("");
320302
320573
  }
320303
320574
  if (cfg.includeDiscoveryServer) {
320304
320575
  if (!cfg.runDir) {
@@ -320346,7 +320617,7 @@ var require_playwright_mcp_config = __commonJS({
320346
320617
  type: "stdio",
320347
320618
  command: "node",
320348
320619
  args: [serverJs],
320349
- env: { CDP_ENDPOINT: cfg.cdpEndpoint }
320620
+ env: { CDP_ENDPOINT: cfg.cdpEndpoint, ...(0, google_signin_js_1.collectGoogleSignInEnv)() }
320350
320621
  };
320351
320622
  }
320352
320623
  if (cfg.includeDiscoveryServer) {
@@ -328553,6 +328824,7 @@ var require_discover_explorer = __commonJS({
328553
328824
  var credential_tools_js_1 = require_credential_tools();
328554
328825
  var inbox_tools_js_1 = require_inbox_tools();
328555
328826
  var verification_inbox_js_1 = require_verification_inbox();
328827
+ var google_signin_js_1 = require_google_signin();
328556
328828
  var discover_planner_js_1 = require_discover_planner();
328557
328829
  var exploration_prompt_builder_js_1 = require_exploration_prompt_builder();
328558
328830
  var ai_queue_js_1 = require_ai_queue();
@@ -328957,7 +329229,8 @@ NEVER assert: user-specific text (names, emails), counts/numbers, timestamps, ma
328957
329229
  };
328958
329230
  function buildSystemPrompt(baseUrl, variableContext, existingSiteMap, existingTestNames, options) {
328959
329231
  const browserCredentials = variableContext.allTestVariables ?? variableContext.publicTestVariables;
328960
- const { secrets: explorerSecretVars, publics: explorerPublicVarsRaw } = (0, credential_tools_js_1.partitionTestVariables)(browserCredentials);
329232
+ const { secrets: explorerSecretVarsRaw, publics: explorerPublicVarsRaw } = (0, credential_tools_js_1.partitionTestVariables)(browserCredentials);
329233
+ const explorerSecretVars = options?.inboxPrompt ? (0, google_signin_js_1.mergeGoogleSignInSecrets)(explorerSecretVarsRaw) : explorerSecretVarsRaw;
328961
329234
  const hasCredentials = Object.keys(explorerSecretVars).length > 0;
328962
329235
  const { DISCOVERY_SHOULD_REGISTER: _omitRegisterFlag, ...explorerPublicVars } = explorerPublicVarsRaw;
328963
329236
  const explorerPublicLines = (0, credential_tools_js_1.renderPublicVariablesBlock)(explorerPublicVars);
@@ -329574,10 +329847,12 @@ ${inbox_tools_js_1.EMAIL_VERIFICATION_UNAVAILABLE_OVERRIDE_BLOCK}` : ""}`;
329574
329847
  if (emailVerificationUnavailable) {
329575
329848
  logs2.push("Email verification unavailable \u2014 the agent will ATTEMPT registration once; any flow requiring an emailed code/link will be reported BLOCKED.");
329576
329849
  }
329850
+ const googleGuidance = (0, google_signin_js_1.googleSignInGuidanceOpts)();
329577
329851
  const inboxPromptBlock = inboxState ? (0, inbox_tools_js_1.buildInboxPromptBlock)({
329578
329852
  email: inboxState.email,
329579
329853
  passwordKey: inboxState.passwordKey ?? "TEST_USER_PASSWORD",
329580
- context: options?.mode
329854
+ context: options?.mode,
329855
+ ...googleGuidance
329581
329856
  }) : "";
329582
329857
  try {
329583
329858
  const { tools: mcpTools } = await mcpClient.listTools();
@@ -329598,7 +329873,8 @@ ${inbox_tools_js_1.EMAIL_VERIFICATION_UNAVAILABLE_OVERRIDE_BLOCK}` : ""}`;
329598
329873
  }
329599
329874
  const browserCredsForTools = variableContext.allTestVariables ?? variableContext.publicTestVariables;
329600
329875
  const { secrets: explorerToolSecrets } = (0, credential_tools_js_1.partitionTestVariables)(browserCredsForTools);
329601
- if (Object.keys(explorerToolSecrets).length > 0) {
329876
+ const explorerToolSecretsWithGoogle = inboxState ? (0, google_signin_js_1.mergeGoogleSignInSecrets)(explorerToolSecrets) : explorerToolSecrets;
329877
+ if (Object.keys(explorerToolSecretsWithGoogle).length > 0) {
329602
329878
  openaiTools.push(credential_tools_js_1.FILL_CREDENTIAL_TOOL, credential_tools_js_1.FILL_CREDENTIAL_FORM_TOOL);
329603
329879
  if (options?.onCredentialUpdate) {
329604
329880
  openaiTools.push(credential_tools_js_1.SET_CREDENTIAL_TOOL);
@@ -330238,8 +330514,12 @@ ${currentSummary}`;
330238
330514
  let finishBouncedThisBatch = false;
330239
330515
  let finishStreakCountedThisBatch = false;
330240
330516
  const fullVarMapForGuard = variableContext.allTestVariables ?? variableContext.publicTestVariables;
330241
- const { secrets: secretsOnlyForGuard } = (0, credential_tools_js_1.partitionTestVariables)(fullVarMapForGuard);
330242
- const allowedCredentialValues = inboxState ? [inboxState.email] : [];
330517
+ const { secrets: partitionedSecretsForGuard } = (0, credential_tools_js_1.partitionTestVariables)(fullVarMapForGuard);
330518
+ const secretsOnlyForGuard = inboxState ? (0, google_signin_js_1.mergeGoogleSignInSecrets)(partitionedSecretsForGuard) : partitionedSecretsForGuard;
330519
+ const allowedCredentialValues = [...new Set([
330520
+ ...inboxState ? [inboxState.email, inboxState.baseEmail] : [],
330521
+ ...inboxState ? (0, google_signin_js_1.googleSignInAllowedEmails)() : []
330522
+ ].filter((value) => !!value))];
330243
330523
  const secretsForLogging = Object.fromEntries(Object.entries(secretsOnlyForGuard).filter(([, value]) => !allowedCredentialValues.includes(value)));
330244
330524
  for (const toolCall of assistantMessage.tool_calls) {
330245
330525
  const toolName = toolCall.function.name;
@@ -331090,8 +331370,9 @@ Exploration complete: ${summary}`);
331090
331370
  }
331091
331371
  const fullVarMap = variableContext.allTestVariables ?? variableContext.publicTestVariables;
331092
331372
  const { secrets: dispatchSecrets } = (0, credential_tools_js_1.partitionTestVariables)(fullVarMap);
331373
+ const fillSecrets = inboxState ? (0, google_signin_js_1.mergeGoogleSignInSecrets)(dispatchSecrets) : dispatchSecrets;
331093
331374
  try {
331094
- const result = toolName === "fill_credential" ? await (0, credential_tools_js_1.handleFillCredential)(toolArgs, { mcpClient, credentials: dispatchSecrets, maxResultChars: MAX_TOOL_RESULT_CHARS }) : await (0, credential_tools_js_1.handleFillCredentialForm)(toolArgs, { mcpClient, credentials: dispatchSecrets, maxResultChars: MAX_TOOL_RESULT_CHARS });
331375
+ const result = toolName === "fill_credential" ? await (0, credential_tools_js_1.handleFillCredential)(toolArgs, { mcpClient, credentials: fillSecrets, maxResultChars: MAX_TOOL_RESULT_CHARS }) : await (0, credential_tools_js_1.handleFillCredentialForm)(toolArgs, { mcpClient, credentials: fillSecrets, maxResultChars: MAX_TOOL_RESULT_CHARS });
331095
331376
  if (result.didMutate) {
331096
331377
  lastSnapshotText = null;
331097
331378
  const codeLines = (0, exploration_parser_js_1.extractCodeLines)(result.content);
@@ -333131,7 +333412,7 @@ ${keyLines || "- (none provided)"}
333131
333412
  ## EXACTLY what to do
333132
333413
  1. Navigate to ${baseUrl} and take a \`browser_snapshot\`.
333133
333414
  2. Find the Sign Up / Register / Create account affordance (match by PURPOSE, in the app's own language) and open the signup form. If a reveal button hides the fields ("Sign up with Email"), click it first.
333134
- 3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit.
333415
+ 3. Follow the "Account Registration (verification inbox is ENABLED)" steps below EXACTLY: call \`provision_identity\` for the email, type that email, fill the password with \`fill_credential\`, fill any other required fields with simple test values, and submit. If there is no app Create-account email form (phone / "Mobile or email" / SMS do not count) and Sign in offers "Continue with Google", follow the Google / Gmail SSO playbook (bare Google account email, \`fill_credential\` with \`GOOGLE_SIGNIN_PASSWORD\` on accounts.google.com, never TEST_USER_PASSWORD, never Continue with phone).
333135
333416
  4. Complete email verification using the inbox tools (\`wait_for_verification\` \u2192 enter the code or \`open_verification_link\`). Re-poll if the email is slow; resend AT MOST once; NEVER register a second account.
333136
333417
  5. Confirm you are signed in \u2014 a redirect to an authenticated route, or an in-place change to authenticated content. Take a \`browser_snapshot\`.
333137
333418
  6. \`capture_page\` the authenticated landing page in its DEFAULT state, then call \`finish_exploration\`. Do this the MOMENT the account is verified and you are signed in.
@@ -333685,6 +333966,7 @@ var require_grok_survey_runner = __commonJS({
333685
333966
  var grok_cli_js_1 = require_grok_cli();
333686
333967
  var playwright_mcp_config_js_1 = require_playwright_mcp_config();
333687
333968
  var inbox_tools_js_1 = require_inbox_tools();
333969
+ var google_signin_js_1 = require_google_signin();
333688
333970
  var exploration_parser_js_1 = require_exploration_parser();
333689
333971
  var scrub_credentials_js_1 = require_scrub_credentials();
333690
333972
  var agentic_survey_prompts_js_1 = require_agentic_survey_prompts();
@@ -334209,7 +334491,7 @@ var require_grok_survey_runner = __commonJS({
334209
334491
  };
334210
334492
  const surveyAgentsMd = inboxReg ? `${(0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)()}
334211
334493
 
334212
- ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey)}` : (0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)();
334494
+ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey, (0, google_signin_js_1.googleSignInGuidanceOpts)())}` : (0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)();
334213
334495
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
334214
334496
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
334215
334497
  log2("Wrote AGENTS.md + BRIEF.md");
@@ -335616,6 +335898,7 @@ var require_grok_discovery_runner = __commonJS({
335616
335898
  var playwright_native_js_1 = require_playwright_native();
335617
335899
  var playwright_mcp_config_js_1 = require_playwright_mcp_config();
335618
335900
  var inbox_tools_js_1 = require_inbox_tools();
335901
+ var google_signin_js_1 = require_google_signin();
335619
335902
  var scrub_credentials_js_1 = require_scrub_credentials();
335620
335903
  var grok_survey_runner_js_1 = require_grok_survey_runner();
335621
335904
  var agentic_discovery_prompts_js_1 = require_agentic_discovery_prompts();
@@ -335909,7 +336192,7 @@ var require_grok_discovery_runner = __commonJS({
335909
336192
  };
335910
336193
  const discoveryAgentsMd = inboxReg ? `${(0, agentic_discovery_prompts_js_1.buildDiscoveryAgentsMd)()}
335911
336194
 
335912
- ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey)}` : (0, agentic_discovery_prompts_js_1.buildDiscoveryAgentsMd)();
336195
+ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey, (0, google_signin_js_1.googleSignInGuidanceOpts)())}` : (0, agentic_discovery_prompts_js_1.buildDiscoveryAgentsMd)();
335913
336196
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), discoveryAgentsMd, "utf8");
335914
336197
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_discovery_prompts_js_1.buildDiscoveryBriefMd)(briefInput), "utf8");
335915
336198
  await (0, promises_1.mkdir)(testsDirPath, { recursive: true });
@@ -336862,7 +337145,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
336862
337145
 
336863
337146
  ---
336864
337147
 
336865
- ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxRegV2.email, inboxRegV2.passwordKey)}` : "");
337148
+ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxRegV2.email, inboxRegV2.passwordKey, (0, google_signin_js_1.googleSignInGuidanceOpts)())}` : "");
336866
337149
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), agentsMd, "utf8");
336867
337150
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_discovery_prompts_js_1.buildDiscoveryBriefMd)(briefInput), "utf8");
336868
337151
  await (0, promises_1.mkdir)(testsDirPath, { recursive: true });
@@ -337834,6 +338117,7 @@ var require_claude_survey_runner = __commonJS({
337834
338117
  var claude_stream_parser_js_1 = require_claude_stream_parser();
337835
338118
  var playwright_mcp_config_js_1 = require_playwright_mcp_config();
337836
338119
  var inbox_tools_js_1 = require_inbox_tools();
338120
+ var google_signin_js_1 = require_google_signin();
337837
338121
  var scrub_credentials_js_1 = require_scrub_credentials();
337838
338122
  var agentic_cli_constants_js_1 = require_agentic_cli_constants();
337839
338123
  var grok_survey_runner_js_1 = require_grok_survey_runner();
@@ -337934,7 +338218,7 @@ ${preview}`);
337934
338218
  };
337935
338219
  const surveyAgentsMd = inboxReg ? `${(0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)({ canvasMode })}
337936
338220
 
337937
- ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey)}` : (0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)({ canvasMode });
338221
+ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey, (0, google_signin_js_1.googleSignInGuidanceOpts)())}` : (0, agentic_survey_prompts_js_1.buildSurveyAgentsMd)({ canvasMode });
337938
338222
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
337939
338223
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
337940
338224
  log2("Wrote AGENTS.md + BRIEF.md");
@@ -338644,6 +338928,7 @@ var require_claude_discovery_runner = __commonJS({
338644
338928
  var claude_cli_js_1 = require_claude_cli();
338645
338929
  var playwright_mcp_config_js_1 = require_playwright_mcp_config();
338646
338930
  var inbox_tools_js_1 = require_inbox_tools();
338931
+ var google_signin_js_1 = require_google_signin();
338647
338932
  var coverage_examples_content_js_1 = require_coverage_examples_content();
338648
338933
  var scrub_credentials_js_1 = require_scrub_credentials();
338649
338934
  var agentic_cli_constants_js_1 = require_agentic_cli_constants();
@@ -338812,7 +339097,7 @@ var require_claude_discovery_runner = __commonJS({
338812
339097
  };
338813
339098
  const explorerContractMd = inboxReg ? `${(0, agentic_discovery_prompts_js_1.buildExplorerContractMd)(contractInput)}
338814
339099
 
338815
- ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey)}` : (0, agentic_discovery_prompts_js_1.buildExplorerContractMd)(contractInput);
339100
+ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwordKey, (0, google_signin_js_1.googleSignInGuidanceOpts)())}` : (0, agentic_discovery_prompts_js_1.buildExplorerContractMd)(contractInput);
338816
339101
  await (0, promises_1.writeFile)(claudeMdPath, explorerContractMd, "utf8");
338817
339102
  await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_discovery_prompts_js_1.buildDiscoveryBriefMd)(briefInput), "utf8");
338818
339103
  await (0, promises_1.mkdir)(testsDirPath, { recursive: true });
@@ -356069,7 +356354,7 @@ var require_package4 = __commonJS({
356069
356354
  "package.json"(exports2, module2) {
356070
356355
  module2.exports = {
356071
356356
  name: "@validate.qa/runner",
356072
- version: "1.0.92",
356357
+ version: "1.0.94",
356073
356358
  description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
356074
356359
  bin: {
356075
356360
  "validate-runner": "dist/cli.js"