@validate.qa/runner 1.0.47 → 1.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +471 -41
- package/dist/cli.mjs +471 -41
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -5046,6 +5046,191 @@ var init_auth_block_detector = __esm({
|
|
|
5046
5046
|
}
|
|
5047
5047
|
});
|
|
5048
5048
|
|
|
5049
|
+
// ../shared/dist/auth-state-freshness.js
|
|
5050
|
+
function isCsrfTokenName(name) {
|
|
5051
|
+
return /csrf|xsrf|forgery|authenticity|requestverification/.test(name.toLowerCase());
|
|
5052
|
+
}
|
|
5053
|
+
function isAuthTokenName(name) {
|
|
5054
|
+
const n = name.toLowerCase();
|
|
5055
|
+
if (isCsrfTokenName(n))
|
|
5056
|
+
return false;
|
|
5057
|
+
if (/session|auth|jwt|credential|identity|login|token/.test(n))
|
|
5058
|
+
return true;
|
|
5059
|
+
if (/(?:^|[^a-z0-9])(?:sid|sess|account|remember)(?:[^a-z0-9]|$)/.test(n))
|
|
5060
|
+
return true;
|
|
5061
|
+
return [
|
|
5062
|
+
"connect.sid",
|
|
5063
|
+
"jsessionid",
|
|
5064
|
+
"phpsessid",
|
|
5065
|
+
"aspnet",
|
|
5066
|
+
"asp.net",
|
|
5067
|
+
"aspxauth",
|
|
5068
|
+
"sb-",
|
|
5069
|
+
"supabase",
|
|
5070
|
+
"amplify",
|
|
5071
|
+
"cognito",
|
|
5072
|
+
"auth0",
|
|
5073
|
+
"okta",
|
|
5074
|
+
"kc-",
|
|
5075
|
+
"li_at",
|
|
5076
|
+
"ltpatoken",
|
|
5077
|
+
"wordpress_logged_in"
|
|
5078
|
+
].some((frag) => n.includes(frag));
|
|
5079
|
+
}
|
|
5080
|
+
function isSessionClassName(name) {
|
|
5081
|
+
const n = name.toLowerCase();
|
|
5082
|
+
if (isCsrfTokenName(n))
|
|
5083
|
+
return false;
|
|
5084
|
+
if (/session|sess/.test(n))
|
|
5085
|
+
return true;
|
|
5086
|
+
if (/(?:^|[^a-z0-9])sid(?:[^a-z0-9]|$)/.test(n))
|
|
5087
|
+
return true;
|
|
5088
|
+
return [
|
|
5089
|
+
"connect.sid",
|
|
5090
|
+
"jsessionid",
|
|
5091
|
+
"phpsessid",
|
|
5092
|
+
"aspxauth",
|
|
5093
|
+
"li_at",
|
|
5094
|
+
"ltpatoken",
|
|
5095
|
+
"wordpress_logged_in"
|
|
5096
|
+
].some((frag) => n.includes(frag));
|
|
5097
|
+
}
|
|
5098
|
+
function decodeBase64UrlToUtf8(segment) {
|
|
5099
|
+
if (typeof atob !== "function")
|
|
5100
|
+
return void 0;
|
|
5101
|
+
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
5102
|
+
const padded = base64.length % 4 === 0 ? base64 : base64 + "=".repeat(4 - base64.length % 4);
|
|
5103
|
+
try {
|
|
5104
|
+
const binary = atob(padded);
|
|
5105
|
+
let percentEncoded = "";
|
|
5106
|
+
for (let i = 0; i < binary.length; i += 1) {
|
|
5107
|
+
percentEncoded += `%${binary.charCodeAt(i).toString(16).padStart(2, "0")}`;
|
|
5108
|
+
}
|
|
5109
|
+
return decodeURIComponent(percentEncoded);
|
|
5110
|
+
} catch {
|
|
5111
|
+
return void 0;
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
function jwtExpiryMs(value) {
|
|
5115
|
+
const parts = value.split(".");
|
|
5116
|
+
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2])
|
|
5117
|
+
return void 0;
|
|
5118
|
+
const json = decodeBase64UrlToUtf8(parts[1]);
|
|
5119
|
+
if (json === void 0)
|
|
5120
|
+
return void 0;
|
|
5121
|
+
try {
|
|
5122
|
+
const payload = JSON.parse(json);
|
|
5123
|
+
const exp = payload?.exp;
|
|
5124
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp > 0 ? exp * 1e3 : void 0;
|
|
5125
|
+
} catch {
|
|
5126
|
+
return void 0;
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
function localStorageAuthExpiryMs(value) {
|
|
5130
|
+
const direct = jwtExpiryMs(value);
|
|
5131
|
+
if (direct !== void 0)
|
|
5132
|
+
return direct;
|
|
5133
|
+
let obj;
|
|
5134
|
+
try {
|
|
5135
|
+
obj = JSON.parse(value);
|
|
5136
|
+
} catch {
|
|
5137
|
+
return void 0;
|
|
5138
|
+
}
|
|
5139
|
+
if (!obj || typeof obj !== "object")
|
|
5140
|
+
return void 0;
|
|
5141
|
+
const record = obj;
|
|
5142
|
+
const nested = record.currentSession ?? record.session;
|
|
5143
|
+
const jwtCandidates = [
|
|
5144
|
+
record.access_token,
|
|
5145
|
+
record.accessToken,
|
|
5146
|
+
record.token,
|
|
5147
|
+
record.id_token,
|
|
5148
|
+
record.idToken,
|
|
5149
|
+
nested?.access_token,
|
|
5150
|
+
nested?.accessToken
|
|
5151
|
+
];
|
|
5152
|
+
for (const candidate of jwtCandidates) {
|
|
5153
|
+
if (typeof candidate === "string") {
|
|
5154
|
+
const exp = jwtExpiryMs(candidate);
|
|
5155
|
+
if (exp !== void 0)
|
|
5156
|
+
return exp;
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
const expiresAt = record.expires_at ?? record.expiresAt ?? nested?.expires_at;
|
|
5160
|
+
if (typeof expiresAt === "number" && Number.isFinite(expiresAt) && expiresAt > 0) {
|
|
5161
|
+
return expiresAt < 1e12 ? expiresAt * 1e3 : expiresAt;
|
|
5162
|
+
}
|
|
5163
|
+
return void 0;
|
|
5164
|
+
}
|
|
5165
|
+
function collectAuthTokens(parsed) {
|
|
5166
|
+
const tokens = [];
|
|
5167
|
+
if (!parsed || typeof parsed !== "object")
|
|
5168
|
+
return tokens;
|
|
5169
|
+
const cookies = parsed.cookies;
|
|
5170
|
+
if (Array.isArray(cookies)) {
|
|
5171
|
+
for (const raw of cookies) {
|
|
5172
|
+
if (!raw || typeof raw !== "object")
|
|
5173
|
+
continue;
|
|
5174
|
+
const name = typeof raw.name === "string" ? raw.name : "";
|
|
5175
|
+
const value = typeof raw.value === "string" ? raw.value : "";
|
|
5176
|
+
if (isCsrfTokenName(name))
|
|
5177
|
+
continue;
|
|
5178
|
+
const jwtExp = value ? jwtExpiryMs(value) : void 0;
|
|
5179
|
+
if (jwtExp !== void 0) {
|
|
5180
|
+
tokens.push({ expiryMs: jwtExp, sessionClass: true });
|
|
5181
|
+
continue;
|
|
5182
|
+
}
|
|
5183
|
+
if (isAuthTokenName(name) && typeof raw.expires === "number" && Number.isFinite(raw.expires) && raw.expires > 0) {
|
|
5184
|
+
tokens.push({ expiryMs: raw.expires * 1e3, sessionClass: isSessionClassName(name) });
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
5188
|
+
const origins = parsed.origins;
|
|
5189
|
+
if (Array.isArray(origins)) {
|
|
5190
|
+
for (const origin of origins) {
|
|
5191
|
+
if (!origin || typeof origin !== "object" || !Array.isArray(origin.localStorage))
|
|
5192
|
+
continue;
|
|
5193
|
+
for (const entry of origin.localStorage) {
|
|
5194
|
+
if (!entry || typeof entry !== "object")
|
|
5195
|
+
continue;
|
|
5196
|
+
const key = typeof entry.name === "string" ? entry.name : "";
|
|
5197
|
+
const value = typeof entry.value === "string" ? entry.value : "";
|
|
5198
|
+
if (!key || !value || isCsrfTokenName(key) || !isAuthTokenName(key))
|
|
5199
|
+
continue;
|
|
5200
|
+
const exp = localStorageAuthExpiryMs(value);
|
|
5201
|
+
if (exp !== void 0)
|
|
5202
|
+
tokens.push({ expiryMs: exp, sessionClass: true });
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
return tokens;
|
|
5207
|
+
}
|
|
5208
|
+
function storageStateExpiredBySkew(stateJson, nowMs, skewMs = AUTH_STATE_EXPIRY_SKEW_MS) {
|
|
5209
|
+
let parsed;
|
|
5210
|
+
try {
|
|
5211
|
+
parsed = JSON.parse(stateJson);
|
|
5212
|
+
} catch {
|
|
5213
|
+
return false;
|
|
5214
|
+
}
|
|
5215
|
+
const tokens = collectAuthTokens(parsed);
|
|
5216
|
+
if (tokens.length === 0)
|
|
5217
|
+
return false;
|
|
5218
|
+
const margin = Number.isFinite(skewMs) ? Math.max(0, skewMs) : AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5219
|
+
const deadline = nowMs + margin;
|
|
5220
|
+
const anyExpired = tokens.some((t) => t.expiryMs <= deadline);
|
|
5221
|
+
if (!anyExpired)
|
|
5222
|
+
return false;
|
|
5223
|
+
const liveSession = tokens.some((t) => t.expiryMs > deadline && t.sessionClass);
|
|
5224
|
+
return !liveSession;
|
|
5225
|
+
}
|
|
5226
|
+
var AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5227
|
+
var init_auth_state_freshness = __esm({
|
|
5228
|
+
"../shared/dist/auth-state-freshness.js"() {
|
|
5229
|
+
"use strict";
|
|
5230
|
+
AUTH_STATE_EXPIRY_SKEW_MS = 3e4;
|
|
5231
|
+
}
|
|
5232
|
+
});
|
|
5233
|
+
|
|
5049
5234
|
// ../shared/dist/skip-coverage-detector.js
|
|
5050
5235
|
function detectSkippedApiCoverage(steps) {
|
|
5051
5236
|
const allSkipped = steps.length > 0 && steps.every((s) => s.status === "skipped");
|
|
@@ -5435,6 +5620,7 @@ __export(dist_exports, {
|
|
|
5435
5620
|
API_AUTH_HEADERS_ENV_KEY: () => API_AUTH_HEADERS_ENV_KEY,
|
|
5436
5621
|
API_PREFIX: () => API_PREFIX,
|
|
5437
5622
|
AUDIO_CHUNK_DURATION_MS: () => AUDIO_CHUNK_DURATION_MS,
|
|
5623
|
+
AUTH_STATE_EXPIRY_SKEW_MS: () => AUTH_STATE_EXPIRY_SKEW_MS,
|
|
5438
5624
|
AUTH_TAG_COOKIE_STATE: () => AUTH_TAG_COOKIE_STATE,
|
|
5439
5625
|
AUTH_TAG_LOGIN_BEARER: () => AUTH_TAG_LOGIN_BEARER,
|
|
5440
5626
|
AUTH_TAG_LOGIN_COOKIE: () => AUTH_TAG_LOGIN_COOKIE,
|
|
@@ -5552,6 +5738,7 @@ __export(dist_exports, {
|
|
|
5552
5738
|
isApiTest: () => isApiTest,
|
|
5553
5739
|
isAppOriginResolutionEnabled: () => isAppOriginResolutionEnabled,
|
|
5554
5740
|
isAuthReadinessGuardEnabled: () => isAuthReadinessGuardEnabled,
|
|
5741
|
+
isAuthTokenName: () => isAuthTokenName,
|
|
5555
5742
|
isBlockedEnvVar: () => isBlockedEnvVar,
|
|
5556
5743
|
isCountedFailure: () => isCountedFailure,
|
|
5557
5744
|
isCreditPackAmountCents: () => isCreditPackAmountCents,
|
|
@@ -5574,6 +5761,7 @@ __export(dist_exports, {
|
|
|
5574
5761
|
isValidSttProvider: () => isValidSttProvider,
|
|
5575
5762
|
isValidTtsModel: () => isValidTtsModel,
|
|
5576
5763
|
isValidTtsVoiceId: () => isValidTtsVoiceId,
|
|
5764
|
+
jwtExpiryMs: () => jwtExpiryMs,
|
|
5577
5765
|
mediumForMobilePlatform: () => mediumForMobilePlatform,
|
|
5578
5766
|
mobileCredentialPlaceholder: () => mobileCredentialPlaceholder,
|
|
5579
5767
|
mobilePlatformFromMedium: () => mobilePlatformFromMedium,
|
|
@@ -5605,6 +5793,7 @@ __export(dist_exports, {
|
|
|
5605
5793
|
stepIsDivergentForPlatform: () => stepIsDivergentForPlatform,
|
|
5606
5794
|
stepsMissingPlatformLocators: () => stepsMissingPlatformLocators,
|
|
5607
5795
|
stepsNeedingReviewForPlatform: () => stepsNeedingReviewForPlatform,
|
|
5796
|
+
storageStateExpiredBySkew: () => storageStateExpiredBySkew,
|
|
5608
5797
|
stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
|
|
5609
5798
|
stripLoginScaffolding: () => stripLoginScaffolding,
|
|
5610
5799
|
sttModelsForProvider: () => sttModelsForProvider,
|
|
@@ -5635,6 +5824,7 @@ var init_dist = __esm({
|
|
|
5635
5824
|
init_origin_domain();
|
|
5636
5825
|
init_auth_plan();
|
|
5637
5826
|
init_auth_block_detector();
|
|
5827
|
+
init_auth_state_freshness();
|
|
5638
5828
|
init_skip_coverage_detector();
|
|
5639
5829
|
init_redact_needles();
|
|
5640
5830
|
init_voice_config();
|
|
@@ -77103,7 +77293,7 @@ var require_discover_ai_planner = __commonJS({
|
|
|
77103
77293
|
"../runner-core/dist/services/discover-ai-planner.js"(exports) {
|
|
77104
77294
|
"use strict";
|
|
77105
77295
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77106
|
-
exports.PLANNER_STRENGTHEN_GATE_PROMPT = exports.SCENARIO_SYSTEM_PROMPT = void 0;
|
|
77296
|
+
exports.PLANNER_STRENGTHEN_GATE_PROMPT = exports.SCENARIO_SYSTEM_PROMPT = exports.SURVEY_SYSTEM_PROMPT = void 0;
|
|
77107
77297
|
exports.getAIPlannerMaxTokens = getAIPlannerMaxTokens;
|
|
77108
77298
|
exports.getSnapshotConfidence = getSnapshotConfidence;
|
|
77109
77299
|
exports.compressSiteMap = compressSiteMap;
|
|
@@ -77639,7 +77829,7 @@ Plan these LOGGED-OUT instead (keep their own establishment steps; do NOT assume
|
|
|
77639
77829
|
}
|
|
77640
77830
|
return sections.join("\n\n");
|
|
77641
77831
|
}
|
|
77642
|
-
|
|
77832
|
+
exports.SURVEY_SYSTEM_PROMPT = `You are a feature analyst for a web application. You receive evidence from an AI explorer that mapped the entire site. Your job is to organize pages into meaningful feature groups.
|
|
77643
77833
|
|
|
77644
77834
|
## Output Discipline
|
|
77645
77835
|
Return ONLY one valid JSON object matching the schema below. Do NOT include <think> blocks, markdown fences, analysis, prose, or any text outside the JSON object. Put any brief explanation only in the JSON "reasoning" field.
|
|
@@ -77659,6 +77849,7 @@ Return ONLY one valid JSON object matching the schema below. Do NOT include <thi
|
|
|
77659
77849
|
6. Do NOT merge pages into one feature just because they serve a similar broader goal. Treat areas as separate features when the evidence shows separate primary navigation destinations (e.g. separate sidebar links), separate route families below the app shell (e.g. /dashboard/documents/* vs /dashboard/reports/* are separate even though both are under /dashboard), or different CRUD entities/forms. Keep pages together when they share one navigational area and operate on the same entity (e.g. /applications, /applications/stats, /applications?filter= all belong together).
|
|
77660
77850
|
7. Feature descriptions MUST reference actual element labels from the evidence
|
|
77661
77851
|
8. Do NOT create standalone features for generic error pages (404, 500, access denied). If a business route is broken or crashes, keep it in its intended feature and note the failure in the description. Error pages do not need their own deep exploration run.
|
|
77852
|
+
9. The Base URL's PATH is the survey's entry scope. When it is non-root (e.g. \`/shop/checkout\`), the operator is auditing that one flow in isolation: do NOT create featureGroups for parent paths, sibling paths, or guessed/nonexistent routes on the same host \u2014 even if the explorer's evidence wandered there. Auth pages the flow itself traverses (its login page, an \`/api/auth/*\` callback) belong INSIDE that flow's group, not in separate groups. When the Base URL path is \`/\`, group the whole app as usual.
|
|
77662
77853
|
|
|
77663
77854
|
## Output JSON Schema
|
|
77664
77855
|
{
|
|
@@ -78411,7 +78602,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
|
|
|
78411
78602
|
const agentModel = options.modelOverride ? (0, ai_provider_js_1.resolveModelForTask)(options.modelOverride, "agent") : (0, ai_provider_js_1.getModel)("agent");
|
|
78412
78603
|
const plannerMaxTokens = getAIPlannerMaxTokens(agentModel);
|
|
78413
78604
|
logs2.push(`AI planner [${context.mode}]: ${siteMap.pages.length} pages, ${evidence.recordedJourneys.length} journeys, budget ${context.testBudget}`);
|
|
78414
|
-
const systemPrompt = options.systemPromptOverride ?? (context.mode === "survey" ? SURVEY_SYSTEM_PROMPT : exports.SCENARIO_SYSTEM_PROMPT);
|
|
78605
|
+
const systemPrompt = options.systemPromptOverride ?? (context.mode === "survey" ? exports.SURVEY_SYSTEM_PROMPT : exports.SCENARIO_SYSTEM_PROMPT);
|
|
78415
78606
|
const userPrompt = options.userPromptOverride ?? formatEvidenceForPlanner(compressed, evidence, context);
|
|
78416
78607
|
logs2.push(`AI planner: ~${Math.ceil(userPrompt.length / 3.5)} input tokens`);
|
|
78417
78608
|
const aiClient = options.aiClient ?? (options.modelOverride ? (0, ai_provider_js_1.getRunnerClientForModel)(options.modelOverride) : (0, ai_provider_js_1.getRunnerAIClient)());
|
|
@@ -321382,6 +321573,168 @@ var require_evidence_harvester = __commonJS({
|
|
|
321382
321573
|
}
|
|
321383
321574
|
});
|
|
321384
321575
|
|
|
321576
|
+
// ../runner-core/dist/services/survey-scope.js
|
|
321577
|
+
var require_survey_scope = __commonJS({
|
|
321578
|
+
"../runner-core/dist/services/survey-scope.js"(exports) {
|
|
321579
|
+
"use strict";
|
|
321580
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
321581
|
+
exports.deriveSurveyPathScope = deriveSurveyPathScope;
|
|
321582
|
+
exports.isAuthFlowRoute = isAuthFlowRoute;
|
|
321583
|
+
exports.buildSurveyScopeBoundary = buildSurveyScopeBoundary;
|
|
321584
|
+
exports.filterFeatureGroupsToPathScope = filterFeatureGroupsToPathScope;
|
|
321585
|
+
var exploration_parser_js_1 = require_exploration_parser();
|
|
321586
|
+
function deriveSurveyPathScope(baseUrl) {
|
|
321587
|
+
const trimmed = (baseUrl ?? "").trim();
|
|
321588
|
+
if (!trimmed)
|
|
321589
|
+
return null;
|
|
321590
|
+
let parsed;
|
|
321591
|
+
try {
|
|
321592
|
+
parsed = new URL(trimmed);
|
|
321593
|
+
} catch {
|
|
321594
|
+
return null;
|
|
321595
|
+
}
|
|
321596
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
321597
|
+
return null;
|
|
321598
|
+
const hashRoute = parsed.hash.startsWith("#/") ? parsed.hash : "";
|
|
321599
|
+
const basePath = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(`${parsed.pathname}${hashRoute}`);
|
|
321600
|
+
if (basePath === "/" || basePath === "/#")
|
|
321601
|
+
return null;
|
|
321602
|
+
return { origin: parsed.origin, basePath };
|
|
321603
|
+
}
|
|
321604
|
+
var AUTH_FLOW_SEGMENTS = /* @__PURE__ */ new Set([
|
|
321605
|
+
"auth",
|
|
321606
|
+
"oauth",
|
|
321607
|
+
"oauth2",
|
|
321608
|
+
"callback",
|
|
321609
|
+
"login",
|
|
321610
|
+
"log-in",
|
|
321611
|
+
"signin",
|
|
321612
|
+
"sign-in",
|
|
321613
|
+
"signup",
|
|
321614
|
+
"sign-up",
|
|
321615
|
+
"register",
|
|
321616
|
+
"logout",
|
|
321617
|
+
"log-out",
|
|
321618
|
+
"signout",
|
|
321619
|
+
"sign-out",
|
|
321620
|
+
"sso",
|
|
321621
|
+
"saml",
|
|
321622
|
+
"oidc"
|
|
321623
|
+
]);
|
|
321624
|
+
function isAuthFlowRoute(route2) {
|
|
321625
|
+
const normalized = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(route2).toLowerCase();
|
|
321626
|
+
return normalized.split(/[/#]/).some((segment) => AUTH_FLOW_SEGMENTS.has(segment));
|
|
321627
|
+
}
|
|
321628
|
+
function routePathForScope(route2, origin) {
|
|
321629
|
+
const trimmed = (route2 ?? "").trim();
|
|
321630
|
+
if (trimmed.startsWith("//")) {
|
|
321631
|
+
try {
|
|
321632
|
+
const parsed = new URL(`https:${trimmed}`);
|
|
321633
|
+
if (parsed.host !== new URL(origin).host)
|
|
321634
|
+
return null;
|
|
321635
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
321636
|
+
} catch {
|
|
321637
|
+
return null;
|
|
321638
|
+
}
|
|
321639
|
+
}
|
|
321640
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
321641
|
+
try {
|
|
321642
|
+
const parsed = new URL(trimmed);
|
|
321643
|
+
if (parsed.origin !== origin)
|
|
321644
|
+
return null;
|
|
321645
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
321646
|
+
} catch {
|
|
321647
|
+
return trimmed;
|
|
321648
|
+
}
|
|
321649
|
+
}
|
|
321650
|
+
if (trimmed.startsWith("/") && trimmed.includes("..")) {
|
|
321651
|
+
try {
|
|
321652
|
+
const resolved = new URL(trimmed, "https://scope.invalid");
|
|
321653
|
+
return `${resolved.pathname}${resolved.search}${resolved.hash}`;
|
|
321654
|
+
} catch {
|
|
321655
|
+
return trimmed;
|
|
321656
|
+
}
|
|
321657
|
+
}
|
|
321658
|
+
return trimmed;
|
|
321659
|
+
}
|
|
321660
|
+
function buildSurveyScopeBoundary(baseUrl) {
|
|
321661
|
+
const scope = deriveSurveyPathScope(baseUrl);
|
|
321662
|
+
const lines = [
|
|
321663
|
+
'- **Never invent a URL.** Navigate only to pages the app presented (links/buttons you can click, per the rule above) or redirects it performs. Do not guess "common" routes and do not probe made-up routes to see what the error page does'
|
|
321664
|
+
];
|
|
321665
|
+
if (scope) {
|
|
321666
|
+
lines.push(`- **The base URL PATH is the entry scope** (\`${scope.basePath}\`) \u2014 this survey audits that flow in ISOLATION. Do not truncate the path to visit a parent, and do not visit or catalog sibling paths on this host that in-scope pages never linked to. Pages the flow itself pushes you through (its login page, an auth/OAuth callback, a post-submit redirect) are in scope`);
|
|
321667
|
+
}
|
|
321668
|
+
return lines.join("\n");
|
|
321669
|
+
}
|
|
321670
|
+
function filterFeatureGroupsToPathScope(featureGroups, baseUrl) {
|
|
321671
|
+
const scope = deriveSurveyPathScope(baseUrl);
|
|
321672
|
+
if (!scope) {
|
|
321673
|
+
return { kept: featureGroups, droppedGroups: [], trimmedRoutes: [], trimmedPages: [], basePath: null };
|
|
321674
|
+
}
|
|
321675
|
+
const withinBase = (route2) => {
|
|
321676
|
+
const path = routePathForScope(route2, scope.origin);
|
|
321677
|
+
if (path === null)
|
|
321678
|
+
return false;
|
|
321679
|
+
if ((0, exploration_parser_js_1.routeIsWithinFocusAreas)(path, [scope.basePath]))
|
|
321680
|
+
return true;
|
|
321681
|
+
const norm = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(path);
|
|
321682
|
+
return norm === `${scope.basePath}#` || norm.startsWith(`${scope.basePath}#/`);
|
|
321683
|
+
};
|
|
321684
|
+
const allowedAuthFlow = (route2) => {
|
|
321685
|
+
const path = routePathForScope(route2, scope.origin);
|
|
321686
|
+
return path !== null && isAuthFlowRoute(path);
|
|
321687
|
+
};
|
|
321688
|
+
const kept = [];
|
|
321689
|
+
const droppedGroups = [];
|
|
321690
|
+
const trimmedRoutes = [];
|
|
321691
|
+
const trimmedPages = [];
|
|
321692
|
+
for (const group of featureGroups) {
|
|
321693
|
+
const routes = Array.isArray(group.routes) ? group.routes : [];
|
|
321694
|
+
const keptRoutes = [];
|
|
321695
|
+
const removedRoutes = [];
|
|
321696
|
+
let anchored = false;
|
|
321697
|
+
for (const route2 of routes) {
|
|
321698
|
+
if (withinBase(route2)) {
|
|
321699
|
+
anchored = true;
|
|
321700
|
+
keptRoutes.push(route2);
|
|
321701
|
+
} else if (allowedAuthFlow(route2)) {
|
|
321702
|
+
keptRoutes.push(route2);
|
|
321703
|
+
} else {
|
|
321704
|
+
removedRoutes.push(route2);
|
|
321705
|
+
}
|
|
321706
|
+
}
|
|
321707
|
+
if (!anchored) {
|
|
321708
|
+
droppedGroups.push({ name: group.name, routes: [...routes] });
|
|
321709
|
+
continue;
|
|
321710
|
+
}
|
|
321711
|
+
let pages = group.pages;
|
|
321712
|
+
const removedPages = [];
|
|
321713
|
+
if (Array.isArray(group.pages)) {
|
|
321714
|
+
const keptPages = [];
|
|
321715
|
+
for (const page of group.pages) {
|
|
321716
|
+
if (withinBase(page.route) || allowedAuthFlow(page.route))
|
|
321717
|
+
keptPages.push(page);
|
|
321718
|
+
else
|
|
321719
|
+
removedPages.push(page.route);
|
|
321720
|
+
}
|
|
321721
|
+
pages = keptPages;
|
|
321722
|
+
}
|
|
321723
|
+
if (removedRoutes.length === 0 && removedPages.length === 0) {
|
|
321724
|
+
kept.push(group);
|
|
321725
|
+
} else {
|
|
321726
|
+
kept.push({ ...group, routes: keptRoutes, ...group.pages !== void 0 ? { pages } : {} });
|
|
321727
|
+
if (removedRoutes.length > 0)
|
|
321728
|
+
trimmedRoutes.push({ name: group.name, routes: removedRoutes });
|
|
321729
|
+
if (removedPages.length > 0)
|
|
321730
|
+
trimmedPages.push({ name: group.name, routes: removedPages });
|
|
321731
|
+
}
|
|
321732
|
+
}
|
|
321733
|
+
return { kept, droppedGroups, trimmedRoutes, trimmedPages, basePath: scope.basePath };
|
|
321734
|
+
}
|
|
321735
|
+
}
|
|
321736
|
+
});
|
|
321737
|
+
|
|
321385
321738
|
// ../runner-core/dist/services/discover-explorer.js
|
|
321386
321739
|
var require_discover_explorer = __commonJS({
|
|
321387
321740
|
"../runner-core/dist/services/discover-explorer.js"(exports) {
|
|
@@ -321423,6 +321776,7 @@ var require_discover_explorer = __commonJS({
|
|
|
321423
321776
|
var evidence_harvester_js_1 = require_evidence_harvester();
|
|
321424
321777
|
var exploration_parser_js_1 = require_exploration_parser();
|
|
321425
321778
|
var survey_link_frontier_js_1 = require_survey_link_frontier();
|
|
321779
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
321426
321780
|
var snapshot_context_compactor_js_2 = require_snapshot_context_compactor();
|
|
321427
321781
|
Object.defineProperty(exports, "formatMCPToolResult", { enumerable: true, get: function() {
|
|
321428
321782
|
return snapshot_context_compactor_js_2.formatMCPToolResult;
|
|
@@ -321850,6 +322204,7 @@ If a snapshot's readiness section exposes \`loading_indicators\`, \`skeleton_con
|
|
|
321850
322204
|
- **Map, do not mutate.** You MAY click buttons that open modals, popups, or dropdowns for the purpose of CATALOGING their contents (capture_page). Do NOT fill forms, submit data, or click destructive buttons (save, delete, submit) - just catalog the elements and close the modal
|
|
321851
322205
|
- **Modals/popups/banners**: If a cookie consent banner, onboarding tour, or overlay appears, dismiss it (click close/X/dismiss/accept) and continue. If it reappears on the next page, dismiss it again - some sites show consent banners on every navigation until accepted
|
|
321852
322206
|
- **Stay on the same origin** as the base URL. Note external links in elements but do not follow them
|
|
322207
|
+
${(0, survey_scope_js_1.buildSurveyScopeBoundary)(baseUrl)}
|
|
321853
322208
|
- **OAuth/SSO**: If login redirects to an external provider (Google, GitHub), do not follow it. Note that the app uses OAuth and explore unauthenticated pages only
|
|
321854
322209
|
- **Auth failure**: If login${isRegisterMode ? " or account registration" : ""} fails after 2 attempts, capture the auth page and explore unauthenticated pages. Note the failure in your \`finish_exploration\` summary
|
|
321855
322210
|
- **Parameterized routes**: /users/1 and /users/2 are the same page template. Visit ONE instance, not all of them
|
|
@@ -325348,6 +325703,8 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325348
325703
|
exports.validateSurveyorOutput = validateSurveyorOutput;
|
|
325349
325704
|
exports.buildSurveyAgentsMd = buildSurveyAgentsMd;
|
|
325350
325705
|
exports.buildSurveyBriefMd = buildSurveyBriefMd;
|
|
325706
|
+
exports.buildClaudeSurveyKickoffPrompt = buildClaudeSurveyKickoffPrompt;
|
|
325707
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
325351
325708
|
var CRITICALITY_VALUES = ["critical", "high", "medium", "low"];
|
|
325352
325709
|
function isString(v) {
|
|
325353
325710
|
return typeof v === "string";
|
|
@@ -325527,9 +325884,40 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325527
325884
|
'- Click "delete" or destructive admin actions.',
|
|
325528
325885
|
"- Leave the baseUrl domain except briefly for OAuth providers.",
|
|
325529
325886
|
"",
|
|
325887
|
+
"## Navigation scope",
|
|
325888
|
+
"",
|
|
325889
|
+
"The Base URL in BRIEF.md is the ENTRY SCOPE \u2014 its full path, not just",
|
|
325890
|
+
"its domain. Open the exact Base URL first. From there, navigate ONLY to:",
|
|
325891
|
+
"",
|
|
325892
|
+
"- URLs the app actually presented to you: a link, button, or form",
|
|
325893
|
+
" visible in a snapshot of an in-scope page. (`browser_navigate` to a",
|
|
325894
|
+
" URL you saw as a link href is fine \u2014 composing one yourself is not.)",
|
|
325895
|
+
"- Redirects the app itself performs during those interactions,",
|
|
325896
|
+
" including login/OAuth/SSO callback routes needed to complete a flow.",
|
|
325897
|
+
"- The Base URL itself, to return to the start of the flow.",
|
|
325898
|
+
"",
|
|
325899
|
+
"NEVER invent a URL. Do NOT:",
|
|
325900
|
+
"- Parent-walk: truncating the Base URL path (base `/shop/checkout` \u2192",
|
|
325901
|
+
" visiting `/shop` or `/`) is out of scope even though it is same-origin.",
|
|
325902
|
+
"- Sibling-walk: do not visit or catalog neighbours of the Base URL path",
|
|
325903
|
+
" that in-scope pages never linked to.",
|
|
325904
|
+
'- Guess "common" routes (`/admin`, `/about`) or probe made-up routes',
|
|
325905
|
+
" (`/nonexistent`) to see what the error handling does. Do not create",
|
|
325906
|
+
" featureGroups for generic error/404 pages unless the app itself",
|
|
325907
|
+
" routes users there as part of a real flow.",
|
|
325908
|
+
"- Any other URL surgery: if the UI did not present it and the app did",
|
|
325909
|
+
" not redirect you to it, it does not exist for this survey.",
|
|
325910
|
+
"",
|
|
325911
|
+
"When the Base URL path is non-root (e.g. `/shop/checkout`, `/portal/billing`),",
|
|
325912
|
+
"the operator is auditing THAT flow in isolation: every featureGroup must",
|
|
325913
|
+
"describe that flow. Auth pages the flow pushes you through belong inside",
|
|
325914
|
+
"that flow's featureGroup \u2014 do not mint separate featureGroups for them.",
|
|
325915
|
+
"When the Base URL is the origin root, survey the whole app \u2014 the",
|
|
325916
|
+
"no-guessing rule still applies: reach pages through the UI.",
|
|
325917
|
+
"",
|
|
325530
325918
|
"## Exploration philosophy",
|
|
325531
325919
|
"",
|
|
325532
|
-
"- Breadth before depth \u2014 map the whole surface before drilling in.",
|
|
325920
|
+
"- Breadth before depth \u2014 map the whole in-scope surface before drilling in.",
|
|
325533
325921
|
"- Authenticated and unauthenticated surfaces are different products;",
|
|
325534
325922
|
" explore both when credentials are available.",
|
|
325535
325923
|
"- Prefer observing over interacting: open a page, snapshot, note the",
|
|
@@ -325624,6 +326012,17 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325624
326012
|
lines.push("");
|
|
325625
326013
|
lines.push(`**Base URL:** ${input.baseUrl}`);
|
|
325626
326014
|
lines.push("");
|
|
326015
|
+
const pathScope = (0, survey_scope_js_1.deriveSurveyPathScope)(input.baseUrl);
|
|
326016
|
+
if (pathScope) {
|
|
326017
|
+
lines.push(`**Entry scope:** \`${pathScope.basePath}\` \u2014 this is a SCOPED survey of one flow.`);
|
|
326018
|
+
lines.push("");
|
|
326019
|
+
lines.push(`Everything you catalog must live under \`${pathScope.basePath}\`, or be a page`);
|
|
326020
|
+
lines.push("this flow itself pushes you through (its own login page, an auth/OAuth");
|
|
326021
|
+
lines.push("callback, a post-submit redirect). Parent and sibling paths on this host");
|
|
326022
|
+
lines.push("are OTHER fixtures/apps and are out of scope \u2014 do not visit them, do not");
|
|
326023
|
+
lines.push("catalog them, do not mint featureGroups for them.");
|
|
326024
|
+
lines.push("");
|
|
326025
|
+
}
|
|
325627
326026
|
if (input.appBrief && input.appBrief.trim().length > 0) {
|
|
325628
326027
|
lines.push("## App brief from the operator");
|
|
325629
326028
|
lines.push("");
|
|
@@ -325693,6 +326092,37 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325693
326092
|
lines.push("");
|
|
325694
326093
|
return lines.join("\n");
|
|
325695
326094
|
}
|
|
326095
|
+
function buildClaudeSurveyKickoffPrompt(resultFilePath) {
|
|
326096
|
+
return [
|
|
326097
|
+
"Read AGENTS.md, then read BRIEF.md.",
|
|
326098
|
+
"",
|
|
326099
|
+
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
326100
|
+
"Follow this procedure exactly:",
|
|
326101
|
+
"",
|
|
326102
|
+
"STEP 1 \u2014 Orient: navigate to the EXACT Base URL from BRIEF.md and",
|
|
326103
|
+
" snapshot it, then open 2-3 pages its UI visibly links to (e.g. a login",
|
|
326104
|
+
" link it presents). Navigate only to URLs the page actually presented \u2014",
|
|
326105
|
+
' never guessed parent, sibling, or "common" routes (see "Navigation',
|
|
326106
|
+
' scope" in AGENTS.md).',
|
|
326107
|
+
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
326108
|
+
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
326109
|
+
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
326110
|
+
" and do NOT explore further until this file exists.",
|
|
326111
|
+
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
326112
|
+
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
326113
|
+
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
326114
|
+
" complete JSON object.",
|
|
326115
|
+
"STEP 4 \u2014 Stop once you have covered the main in-scope pages (around 20",
|
|
326116
|
+
` page visits is plenty) or stop finding new features. Do a final OVERWRITE`,
|
|
326117
|
+
` of ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
326118
|
+
"",
|
|
326119
|
+
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
326120
|
+
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
326121
|
+
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
326122
|
+
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
326123
|
+
"prose in the file \u2014 a single JSON object only."
|
|
326124
|
+
].join("\n");
|
|
326125
|
+
}
|
|
325696
326126
|
}
|
|
325697
326127
|
});
|
|
325698
326128
|
|
|
@@ -326243,6 +326673,9 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
326243
326673
|
const kickoffPrompt = [
|
|
326244
326674
|
"Read AGENTS.md, then read BRIEF.md.",
|
|
326245
326675
|
"Use the playwright MCP tools to explore the site.",
|
|
326676
|
+
'Follow the "Navigation scope" rules in AGENTS.md: start at the exact Base',
|
|
326677
|
+
'URL and never navigate to guessed parent, sibling, or "common" routes \u2014',
|
|
326678
|
+
"only URLs the pages actually present (or redirects the app performs).",
|
|
326246
326679
|
`When done, write your JSON output to ${resultFilePath} as a single JSON object matching the SurveyorOutput schema in AGENTS.md.`,
|
|
326247
326680
|
"Then exit."
|
|
326248
326681
|
].join("\n");
|
|
@@ -329959,32 +330392,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
329959
330392
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
|
|
329960
330393
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
|
|
329961
330394
|
log2("Wrote AGENTS.md + BRIEF.md");
|
|
329962
|
-
const kickoffPrompt =
|
|
329963
|
-
"Read AGENTS.md, then read BRIEF.md.",
|
|
329964
|
-
"",
|
|
329965
|
-
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
329966
|
-
"Follow this procedure exactly:",
|
|
329967
|
-
"",
|
|
329968
|
-
"STEP 1 \u2014 Orient: navigate to the base URL and 2-3 obvious pages (e.g. the",
|
|
329969
|
-
" login page and the main dashboard).",
|
|
329970
|
-
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
329971
|
-
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
329972
|
-
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
329973
|
-
" and do NOT explore further until this file exists.",
|
|
329974
|
-
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
329975
|
-
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
329976
|
-
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
329977
|
-
" complete JSON object.",
|
|
329978
|
-
"STEP 4 \u2014 Stop once you have covered the main pages (around 20 page visits",
|
|
329979
|
-
` is plenty) or stop finding new features. Do a final OVERWRITE of`,
|
|
329980
|
-
` ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
329981
|
-
"",
|
|
329982
|
-
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
329983
|
-
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
329984
|
-
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
329985
|
-
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
329986
|
-
"prose in the file \u2014 a single JSON object only."
|
|
329987
|
-
].join("\n");
|
|
330395
|
+
const kickoffPrompt = (0, agentic_survey_prompts_js_1.buildClaudeSurveyKickoffPrompt)(resultFilePath);
|
|
329988
330396
|
const credentialScrubMap = {};
|
|
329989
330397
|
for (const c of credentials) {
|
|
329990
330398
|
credentialScrubMap[c.email] = "<email>";
|
|
@@ -333996,7 +334404,7 @@ var require_local_auth_state = __commonJS({
|
|
|
333996
334404
|
exports.ensurePrivateDirectory = ensurePrivateDirectory2;
|
|
333997
334405
|
exports.isValidStorageState = isValidStorageState;
|
|
333998
334406
|
exports.isValidStorageStateJson = isValidStorageStateJson;
|
|
333999
|
-
exports.isValidLocalAuthStateFile =
|
|
334407
|
+
exports.isValidLocalAuthStateFile = isValidLocalAuthStateFile2;
|
|
334000
334408
|
exports.cleanupLocalAuthStateFiles = cleanupLocalAuthStateFiles;
|
|
334001
334409
|
exports.cleanupExpiredLocalAuthStateFiles = cleanupExpiredLocalAuthStateFiles2;
|
|
334002
334410
|
exports.localAuthStatePaths = localAuthStatePaths2;
|
|
@@ -334010,6 +334418,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334010
334418
|
var node_fs_1 = __require("fs");
|
|
334011
334419
|
var node_crypto_1 = __require("crypto");
|
|
334012
334420
|
var node_path_1 = __require("path");
|
|
334421
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
334013
334422
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
334014
334423
|
exports.LOCAL_AUTH_STATE_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
334015
334424
|
exports.LOCAL_AUTH_STATE_WAIT_MS = 3 * 60 * 1e3;
|
|
@@ -334139,7 +334548,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334139
334548
|
return false;
|
|
334140
334549
|
return isValidStorageState(value);
|
|
334141
334550
|
}
|
|
334142
|
-
function
|
|
334551
|
+
function isValidLocalAuthStateFile2(path) {
|
|
334143
334552
|
try {
|
|
334144
334553
|
return isStorageStateShape(JSON.parse((0, node_fs_1.readFileSync)(path, "utf8")));
|
|
334145
334554
|
} catch {
|
|
@@ -334197,11 +334606,22 @@ var require_local_auth_state = __commonJS({
|
|
|
334197
334606
|
lockPath: `${cachePath}.lock`
|
|
334198
334607
|
};
|
|
334199
334608
|
}
|
|
334609
|
+
function localAuthStateExpiredByAuthMaterial(path, now) {
|
|
334610
|
+
try {
|
|
334611
|
+
return (0, shared_1.storageStateExpiredBySkew)((0, node_fs_1.readFileSync)(path, "utf8"), now);
|
|
334612
|
+
} catch {
|
|
334613
|
+
return false;
|
|
334614
|
+
}
|
|
334615
|
+
}
|
|
334200
334616
|
function getValidLocalAuthState2(path, now = Date.now(), maxAgeMs = exports.LOCAL_AUTH_STATE_MAX_AGE_MS) {
|
|
334201
334617
|
if (!(0, node_fs_1.existsSync)(path))
|
|
334202
334618
|
return void 0;
|
|
334203
334619
|
try {
|
|
334204
|
-
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !
|
|
334620
|
+
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !isValidLocalAuthStateFile2(path)) {
|
|
334621
|
+
removeFile(path);
|
|
334622
|
+
return void 0;
|
|
334623
|
+
}
|
|
334624
|
+
if (localAuthStateExpiredByAuthMaterial(path, now)) {
|
|
334205
334625
|
removeFile(path);
|
|
334206
334626
|
return void 0;
|
|
334207
334627
|
}
|
|
@@ -334248,7 +334668,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334248
334668
|
removeFile(capturePath);
|
|
334249
334669
|
return false;
|
|
334250
334670
|
}
|
|
334251
|
-
if (!(0, node_fs_1.existsSync)(capturePath) || !
|
|
334671
|
+
if (!(0, node_fs_1.existsSync)(capturePath) || !isValidLocalAuthStateFile2(capturePath)) {
|
|
334252
334672
|
removeFile(capturePath);
|
|
334253
334673
|
return false;
|
|
334254
334674
|
}
|
|
@@ -334262,7 +334682,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334262
334682
|
return false;
|
|
334263
334683
|
}
|
|
334264
334684
|
if ((0, node_fs_1.existsSync)(cachePath)) {
|
|
334265
|
-
if (!replaceExisting &&
|
|
334685
|
+
if (!replaceExisting && isValidLocalAuthStateFile2(cachePath)) {
|
|
334266
334686
|
removeFile(capturePath);
|
|
334267
334687
|
return true;
|
|
334268
334688
|
}
|
|
@@ -334279,7 +334699,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334279
334699
|
}
|
|
334280
334700
|
return true;
|
|
334281
334701
|
} catch {
|
|
334282
|
-
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) &&
|
|
334702
|
+
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) && isValidLocalAuthStateFile2(cachePath);
|
|
334283
334703
|
removeFile(capturePath);
|
|
334284
334704
|
return winnerIsValid;
|
|
334285
334705
|
}
|
|
@@ -346589,9 +347009,9 @@ var require_dist2 = __commonJS({
|
|
|
346589
347009
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
346590
347010
|
};
|
|
346591
347011
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
346592
|
-
exports.
|
|
346593
|
-
exports.
|
|
346594
|
-
exports.UNSUPPORTED_RENDERER_PREFIX = exports.UnsupportedRendererError = exports.buildCanvasModeAuthoringAddendum = exports.buildUnsupportedRendererMessage = exports.modelSupportsVision = exports.decideCanvasStrategy = void 0;
|
|
347012
|
+
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.filterFeatureGroupsToPathScope = exports.isAuthFlowRoute = exports.deriveSurveyPathScope = 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;
|
|
347013
|
+
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 = exports.extractZipSafely = exports.downloadArchiveCapped = exports.detectArchiveKind = void 0;
|
|
347014
|
+
exports.UNSUPPORTED_RENDERER_PREFIX = exports.UnsupportedRendererError = exports.buildCanvasModeAuthoringAddendum = exports.buildUnsupportedRendererMessage = exports.modelSupportsVision = exports.decideCanvasStrategy = exports.decideAppRenderType = exports.detectCanvasApp = exports.detectRateLimitBlock = void 0;
|
|
346595
347015
|
__exportStar(require_ai_provider(), exports);
|
|
346596
347016
|
__exportStar(require_mobile_types(), exports);
|
|
346597
347017
|
__exportStar(require_mobile_source_parser(), exports);
|
|
@@ -346699,6 +347119,16 @@ var require_dist2 = __commonJS({
|
|
|
346699
347119
|
Object.defineProperty(exports, "canonicalizeRoute", { enumerable: true, get: function() {
|
|
346700
347120
|
return exploration_parser_js_1.canonicalizeRoute;
|
|
346701
347121
|
} });
|
|
347122
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
347123
|
+
Object.defineProperty(exports, "deriveSurveyPathScope", { enumerable: true, get: function() {
|
|
347124
|
+
return survey_scope_js_1.deriveSurveyPathScope;
|
|
347125
|
+
} });
|
|
347126
|
+
Object.defineProperty(exports, "isAuthFlowRoute", { enumerable: true, get: function() {
|
|
347127
|
+
return survey_scope_js_1.isAuthFlowRoute;
|
|
347128
|
+
} });
|
|
347129
|
+
Object.defineProperty(exports, "filterFeatureGroupsToPathScope", { enumerable: true, get: function() {
|
|
347130
|
+
return survey_scope_js_1.filterFeatureGroupsToPathScope;
|
|
347131
|
+
} });
|
|
346702
347132
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
346703
347133
|
Object.defineProperty(exports, "renderAuthFn", { enumerable: true, get: function() {
|
|
346704
347134
|
return auth_recipe_js_1.renderAuthFn;
|
|
@@ -346972,7 +347402,7 @@ var require_package4 = __commonJS({
|
|
|
346972
347402
|
"package.json"(exports, module) {
|
|
346973
347403
|
module.exports = {
|
|
346974
347404
|
name: "@validate.qa/runner",
|
|
346975
|
-
version: "1.0.
|
|
347405
|
+
version: "1.0.49",
|
|
346976
347406
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
346977
347407
|
bin: {
|
|
346978
347408
|
"validate-runner": "dist/cli.js"
|
|
@@ -356637,7 +357067,7 @@ ${result2.logs}`);
|
|
|
356637
357067
|
});
|
|
356638
357068
|
} finally {
|
|
356639
357069
|
if (runAuthPath && authPaths) {
|
|
356640
|
-
if ((0, import_runner_core12.
|
|
357070
|
+
if ((0, import_runner_core12.isValidLocalAuthStateFile)(runAuthPath)) {
|
|
356641
357071
|
const releasePromotionLock = releaseAuthLock ? void 0 : await (0, import_runner_core12.acquireLocalAuthStateLock)(authPaths.lockKey, authPaths.lockPath);
|
|
356642
357072
|
try {
|
|
356643
357073
|
const captured = (0, import_runner_core12.promoteLocalAuthStateCapture)(
|