@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.js
CHANGED
|
@@ -5041,6 +5041,191 @@ var init_auth_block_detector = __esm({
|
|
|
5041
5041
|
}
|
|
5042
5042
|
});
|
|
5043
5043
|
|
|
5044
|
+
// ../shared/dist/auth-state-freshness.js
|
|
5045
|
+
function isCsrfTokenName(name) {
|
|
5046
|
+
return /csrf|xsrf|forgery|authenticity|requestverification/.test(name.toLowerCase());
|
|
5047
|
+
}
|
|
5048
|
+
function isAuthTokenName(name) {
|
|
5049
|
+
const n = name.toLowerCase();
|
|
5050
|
+
if (isCsrfTokenName(n))
|
|
5051
|
+
return false;
|
|
5052
|
+
if (/session|auth|jwt|credential|identity|login|token/.test(n))
|
|
5053
|
+
return true;
|
|
5054
|
+
if (/(?:^|[^a-z0-9])(?:sid|sess|account|remember)(?:[^a-z0-9]|$)/.test(n))
|
|
5055
|
+
return true;
|
|
5056
|
+
return [
|
|
5057
|
+
"connect.sid",
|
|
5058
|
+
"jsessionid",
|
|
5059
|
+
"phpsessid",
|
|
5060
|
+
"aspnet",
|
|
5061
|
+
"asp.net",
|
|
5062
|
+
"aspxauth",
|
|
5063
|
+
"sb-",
|
|
5064
|
+
"supabase",
|
|
5065
|
+
"amplify",
|
|
5066
|
+
"cognito",
|
|
5067
|
+
"auth0",
|
|
5068
|
+
"okta",
|
|
5069
|
+
"kc-",
|
|
5070
|
+
"li_at",
|
|
5071
|
+
"ltpatoken",
|
|
5072
|
+
"wordpress_logged_in"
|
|
5073
|
+
].some((frag) => n.includes(frag));
|
|
5074
|
+
}
|
|
5075
|
+
function isSessionClassName(name) {
|
|
5076
|
+
const n = name.toLowerCase();
|
|
5077
|
+
if (isCsrfTokenName(n))
|
|
5078
|
+
return false;
|
|
5079
|
+
if (/session|sess/.test(n))
|
|
5080
|
+
return true;
|
|
5081
|
+
if (/(?:^|[^a-z0-9])sid(?:[^a-z0-9]|$)/.test(n))
|
|
5082
|
+
return true;
|
|
5083
|
+
return [
|
|
5084
|
+
"connect.sid",
|
|
5085
|
+
"jsessionid",
|
|
5086
|
+
"phpsessid",
|
|
5087
|
+
"aspxauth",
|
|
5088
|
+
"li_at",
|
|
5089
|
+
"ltpatoken",
|
|
5090
|
+
"wordpress_logged_in"
|
|
5091
|
+
].some((frag) => n.includes(frag));
|
|
5092
|
+
}
|
|
5093
|
+
function decodeBase64UrlToUtf8(segment) {
|
|
5094
|
+
if (typeof atob !== "function")
|
|
5095
|
+
return void 0;
|
|
5096
|
+
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
5097
|
+
const padded = base64.length % 4 === 0 ? base64 : base64 + "=".repeat(4 - base64.length % 4);
|
|
5098
|
+
try {
|
|
5099
|
+
const binary = atob(padded);
|
|
5100
|
+
let percentEncoded = "";
|
|
5101
|
+
for (let i = 0; i < binary.length; i += 1) {
|
|
5102
|
+
percentEncoded += `%${binary.charCodeAt(i).toString(16).padStart(2, "0")}`;
|
|
5103
|
+
}
|
|
5104
|
+
return decodeURIComponent(percentEncoded);
|
|
5105
|
+
} catch {
|
|
5106
|
+
return void 0;
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
function jwtExpiryMs(value) {
|
|
5110
|
+
const parts = value.split(".");
|
|
5111
|
+
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2])
|
|
5112
|
+
return void 0;
|
|
5113
|
+
const json = decodeBase64UrlToUtf8(parts[1]);
|
|
5114
|
+
if (json === void 0)
|
|
5115
|
+
return void 0;
|
|
5116
|
+
try {
|
|
5117
|
+
const payload = JSON.parse(json);
|
|
5118
|
+
const exp = payload?.exp;
|
|
5119
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp > 0 ? exp * 1e3 : void 0;
|
|
5120
|
+
} catch {
|
|
5121
|
+
return void 0;
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
function localStorageAuthExpiryMs(value) {
|
|
5125
|
+
const direct = jwtExpiryMs(value);
|
|
5126
|
+
if (direct !== void 0)
|
|
5127
|
+
return direct;
|
|
5128
|
+
let obj;
|
|
5129
|
+
try {
|
|
5130
|
+
obj = JSON.parse(value);
|
|
5131
|
+
} catch {
|
|
5132
|
+
return void 0;
|
|
5133
|
+
}
|
|
5134
|
+
if (!obj || typeof obj !== "object")
|
|
5135
|
+
return void 0;
|
|
5136
|
+
const record = obj;
|
|
5137
|
+
const nested = record.currentSession ?? record.session;
|
|
5138
|
+
const jwtCandidates = [
|
|
5139
|
+
record.access_token,
|
|
5140
|
+
record.accessToken,
|
|
5141
|
+
record.token,
|
|
5142
|
+
record.id_token,
|
|
5143
|
+
record.idToken,
|
|
5144
|
+
nested?.access_token,
|
|
5145
|
+
nested?.accessToken
|
|
5146
|
+
];
|
|
5147
|
+
for (const candidate of jwtCandidates) {
|
|
5148
|
+
if (typeof candidate === "string") {
|
|
5149
|
+
const exp = jwtExpiryMs(candidate);
|
|
5150
|
+
if (exp !== void 0)
|
|
5151
|
+
return exp;
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
const expiresAt = record.expires_at ?? record.expiresAt ?? nested?.expires_at;
|
|
5155
|
+
if (typeof expiresAt === "number" && Number.isFinite(expiresAt) && expiresAt > 0) {
|
|
5156
|
+
return expiresAt < 1e12 ? expiresAt * 1e3 : expiresAt;
|
|
5157
|
+
}
|
|
5158
|
+
return void 0;
|
|
5159
|
+
}
|
|
5160
|
+
function collectAuthTokens(parsed) {
|
|
5161
|
+
const tokens = [];
|
|
5162
|
+
if (!parsed || typeof parsed !== "object")
|
|
5163
|
+
return tokens;
|
|
5164
|
+
const cookies = parsed.cookies;
|
|
5165
|
+
if (Array.isArray(cookies)) {
|
|
5166
|
+
for (const raw of cookies) {
|
|
5167
|
+
if (!raw || typeof raw !== "object")
|
|
5168
|
+
continue;
|
|
5169
|
+
const name = typeof raw.name === "string" ? raw.name : "";
|
|
5170
|
+
const value = typeof raw.value === "string" ? raw.value : "";
|
|
5171
|
+
if (isCsrfTokenName(name))
|
|
5172
|
+
continue;
|
|
5173
|
+
const jwtExp = value ? jwtExpiryMs(value) : void 0;
|
|
5174
|
+
if (jwtExp !== void 0) {
|
|
5175
|
+
tokens.push({ expiryMs: jwtExp, sessionClass: true });
|
|
5176
|
+
continue;
|
|
5177
|
+
}
|
|
5178
|
+
if (isAuthTokenName(name) && typeof raw.expires === "number" && Number.isFinite(raw.expires) && raw.expires > 0) {
|
|
5179
|
+
tokens.push({ expiryMs: raw.expires * 1e3, sessionClass: isSessionClassName(name) });
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
const origins = parsed.origins;
|
|
5184
|
+
if (Array.isArray(origins)) {
|
|
5185
|
+
for (const origin of origins) {
|
|
5186
|
+
if (!origin || typeof origin !== "object" || !Array.isArray(origin.localStorage))
|
|
5187
|
+
continue;
|
|
5188
|
+
for (const entry of origin.localStorage) {
|
|
5189
|
+
if (!entry || typeof entry !== "object")
|
|
5190
|
+
continue;
|
|
5191
|
+
const key = typeof entry.name === "string" ? entry.name : "";
|
|
5192
|
+
const value = typeof entry.value === "string" ? entry.value : "";
|
|
5193
|
+
if (!key || !value || isCsrfTokenName(key) || !isAuthTokenName(key))
|
|
5194
|
+
continue;
|
|
5195
|
+
const exp = localStorageAuthExpiryMs(value);
|
|
5196
|
+
if (exp !== void 0)
|
|
5197
|
+
tokens.push({ expiryMs: exp, sessionClass: true });
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
return tokens;
|
|
5202
|
+
}
|
|
5203
|
+
function storageStateExpiredBySkew(stateJson, nowMs, skewMs = AUTH_STATE_EXPIRY_SKEW_MS) {
|
|
5204
|
+
let parsed;
|
|
5205
|
+
try {
|
|
5206
|
+
parsed = JSON.parse(stateJson);
|
|
5207
|
+
} catch {
|
|
5208
|
+
return false;
|
|
5209
|
+
}
|
|
5210
|
+
const tokens = collectAuthTokens(parsed);
|
|
5211
|
+
if (tokens.length === 0)
|
|
5212
|
+
return false;
|
|
5213
|
+
const margin = Number.isFinite(skewMs) ? Math.max(0, skewMs) : AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5214
|
+
const deadline = nowMs + margin;
|
|
5215
|
+
const anyExpired = tokens.some((t) => t.expiryMs <= deadline);
|
|
5216
|
+
if (!anyExpired)
|
|
5217
|
+
return false;
|
|
5218
|
+
const liveSession = tokens.some((t) => t.expiryMs > deadline && t.sessionClass);
|
|
5219
|
+
return !liveSession;
|
|
5220
|
+
}
|
|
5221
|
+
var AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5222
|
+
var init_auth_state_freshness = __esm({
|
|
5223
|
+
"../shared/dist/auth-state-freshness.js"() {
|
|
5224
|
+
"use strict";
|
|
5225
|
+
AUTH_STATE_EXPIRY_SKEW_MS = 3e4;
|
|
5226
|
+
}
|
|
5227
|
+
});
|
|
5228
|
+
|
|
5044
5229
|
// ../shared/dist/skip-coverage-detector.js
|
|
5045
5230
|
function detectSkippedApiCoverage(steps) {
|
|
5046
5231
|
const allSkipped = steps.length > 0 && steps.every((s) => s.status === "skipped");
|
|
@@ -5430,6 +5615,7 @@ __export(dist_exports, {
|
|
|
5430
5615
|
API_AUTH_HEADERS_ENV_KEY: () => API_AUTH_HEADERS_ENV_KEY,
|
|
5431
5616
|
API_PREFIX: () => API_PREFIX,
|
|
5432
5617
|
AUDIO_CHUNK_DURATION_MS: () => AUDIO_CHUNK_DURATION_MS,
|
|
5618
|
+
AUTH_STATE_EXPIRY_SKEW_MS: () => AUTH_STATE_EXPIRY_SKEW_MS,
|
|
5433
5619
|
AUTH_TAG_COOKIE_STATE: () => AUTH_TAG_COOKIE_STATE,
|
|
5434
5620
|
AUTH_TAG_LOGIN_BEARER: () => AUTH_TAG_LOGIN_BEARER,
|
|
5435
5621
|
AUTH_TAG_LOGIN_COOKIE: () => AUTH_TAG_LOGIN_COOKIE,
|
|
@@ -5547,6 +5733,7 @@ __export(dist_exports, {
|
|
|
5547
5733
|
isApiTest: () => isApiTest,
|
|
5548
5734
|
isAppOriginResolutionEnabled: () => isAppOriginResolutionEnabled,
|
|
5549
5735
|
isAuthReadinessGuardEnabled: () => isAuthReadinessGuardEnabled,
|
|
5736
|
+
isAuthTokenName: () => isAuthTokenName,
|
|
5550
5737
|
isBlockedEnvVar: () => isBlockedEnvVar,
|
|
5551
5738
|
isCountedFailure: () => isCountedFailure,
|
|
5552
5739
|
isCreditPackAmountCents: () => isCreditPackAmountCents,
|
|
@@ -5569,6 +5756,7 @@ __export(dist_exports, {
|
|
|
5569
5756
|
isValidSttProvider: () => isValidSttProvider,
|
|
5570
5757
|
isValidTtsModel: () => isValidTtsModel,
|
|
5571
5758
|
isValidTtsVoiceId: () => isValidTtsVoiceId,
|
|
5759
|
+
jwtExpiryMs: () => jwtExpiryMs,
|
|
5572
5760
|
mediumForMobilePlatform: () => mediumForMobilePlatform,
|
|
5573
5761
|
mobileCredentialPlaceholder: () => mobileCredentialPlaceholder,
|
|
5574
5762
|
mobilePlatformFromMedium: () => mobilePlatformFromMedium,
|
|
@@ -5600,6 +5788,7 @@ __export(dist_exports, {
|
|
|
5600
5788
|
stepIsDivergentForPlatform: () => stepIsDivergentForPlatform,
|
|
5601
5789
|
stepsMissingPlatformLocators: () => stepsMissingPlatformLocators,
|
|
5602
5790
|
stepsNeedingReviewForPlatform: () => stepsNeedingReviewForPlatform,
|
|
5791
|
+
storageStateExpiredBySkew: () => storageStateExpiredBySkew,
|
|
5603
5792
|
stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
|
|
5604
5793
|
stripLoginScaffolding: () => stripLoginScaffolding,
|
|
5605
5794
|
sttModelsForProvider: () => sttModelsForProvider,
|
|
@@ -5630,6 +5819,7 @@ var init_dist = __esm({
|
|
|
5630
5819
|
init_origin_domain();
|
|
5631
5820
|
init_auth_plan();
|
|
5632
5821
|
init_auth_block_detector();
|
|
5822
|
+
init_auth_state_freshness();
|
|
5633
5823
|
init_skip_coverage_detector();
|
|
5634
5824
|
init_redact_needles();
|
|
5635
5825
|
init_voice_config();
|
|
@@ -77098,7 +77288,7 @@ var require_discover_ai_planner = __commonJS({
|
|
|
77098
77288
|
"../runner-core/dist/services/discover-ai-planner.js"(exports2) {
|
|
77099
77289
|
"use strict";
|
|
77100
77290
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77101
|
-
exports2.PLANNER_STRENGTHEN_GATE_PROMPT = exports2.SCENARIO_SYSTEM_PROMPT = void 0;
|
|
77291
|
+
exports2.PLANNER_STRENGTHEN_GATE_PROMPT = exports2.SCENARIO_SYSTEM_PROMPT = exports2.SURVEY_SYSTEM_PROMPT = void 0;
|
|
77102
77292
|
exports2.getAIPlannerMaxTokens = getAIPlannerMaxTokens;
|
|
77103
77293
|
exports2.getSnapshotConfidence = getSnapshotConfidence;
|
|
77104
77294
|
exports2.compressSiteMap = compressSiteMap;
|
|
@@ -77634,7 +77824,7 @@ Plan these LOGGED-OUT instead (keep their own establishment steps; do NOT assume
|
|
|
77634
77824
|
}
|
|
77635
77825
|
return sections.join("\n\n");
|
|
77636
77826
|
}
|
|
77637
|
-
|
|
77827
|
+
exports2.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.
|
|
77638
77828
|
|
|
77639
77829
|
## Output Discipline
|
|
77640
77830
|
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.
|
|
@@ -77654,6 +77844,7 @@ Return ONLY one valid JSON object matching the schema below. Do NOT include <thi
|
|
|
77654
77844
|
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).
|
|
77655
77845
|
7. Feature descriptions MUST reference actual element labels from the evidence
|
|
77656
77846
|
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.
|
|
77847
|
+
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.
|
|
77657
77848
|
|
|
77658
77849
|
## Output JSON Schema
|
|
77659
77850
|
{
|
|
@@ -78406,7 +78597,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
|
|
|
78406
78597
|
const agentModel = options.modelOverride ? (0, ai_provider_js_1.resolveModelForTask)(options.modelOverride, "agent") : (0, ai_provider_js_1.getModel)("agent");
|
|
78407
78598
|
const plannerMaxTokens = getAIPlannerMaxTokens(agentModel);
|
|
78408
78599
|
logs2.push(`AI planner [${context.mode}]: ${siteMap.pages.length} pages, ${evidence.recordedJourneys.length} journeys, budget ${context.testBudget}`);
|
|
78409
|
-
const systemPrompt = options.systemPromptOverride ?? (context.mode === "survey" ? SURVEY_SYSTEM_PROMPT : exports2.SCENARIO_SYSTEM_PROMPT);
|
|
78600
|
+
const systemPrompt = options.systemPromptOverride ?? (context.mode === "survey" ? exports2.SURVEY_SYSTEM_PROMPT : exports2.SCENARIO_SYSTEM_PROMPT);
|
|
78410
78601
|
const userPrompt = options.userPromptOverride ?? formatEvidenceForPlanner(compressed, evidence, context);
|
|
78411
78602
|
logs2.push(`AI planner: ~${Math.ceil(userPrompt.length / 3.5)} input tokens`);
|
|
78412
78603
|
const aiClient = options.aiClient ?? (options.modelOverride ? (0, ai_provider_js_1.getRunnerClientForModel)(options.modelOverride) : (0, ai_provider_js_1.getRunnerAIClient)());
|
|
@@ -321377,6 +321568,168 @@ var require_evidence_harvester = __commonJS({
|
|
|
321377
321568
|
}
|
|
321378
321569
|
});
|
|
321379
321570
|
|
|
321571
|
+
// ../runner-core/dist/services/survey-scope.js
|
|
321572
|
+
var require_survey_scope = __commonJS({
|
|
321573
|
+
"../runner-core/dist/services/survey-scope.js"(exports2) {
|
|
321574
|
+
"use strict";
|
|
321575
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
321576
|
+
exports2.deriveSurveyPathScope = deriveSurveyPathScope;
|
|
321577
|
+
exports2.isAuthFlowRoute = isAuthFlowRoute;
|
|
321578
|
+
exports2.buildSurveyScopeBoundary = buildSurveyScopeBoundary;
|
|
321579
|
+
exports2.filterFeatureGroupsToPathScope = filterFeatureGroupsToPathScope;
|
|
321580
|
+
var exploration_parser_js_1 = require_exploration_parser();
|
|
321581
|
+
function deriveSurveyPathScope(baseUrl) {
|
|
321582
|
+
const trimmed = (baseUrl ?? "").trim();
|
|
321583
|
+
if (!trimmed)
|
|
321584
|
+
return null;
|
|
321585
|
+
let parsed;
|
|
321586
|
+
try {
|
|
321587
|
+
parsed = new URL(trimmed);
|
|
321588
|
+
} catch {
|
|
321589
|
+
return null;
|
|
321590
|
+
}
|
|
321591
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
321592
|
+
return null;
|
|
321593
|
+
const hashRoute = parsed.hash.startsWith("#/") ? parsed.hash : "";
|
|
321594
|
+
const basePath = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(`${parsed.pathname}${hashRoute}`);
|
|
321595
|
+
if (basePath === "/" || basePath === "/#")
|
|
321596
|
+
return null;
|
|
321597
|
+
return { origin: parsed.origin, basePath };
|
|
321598
|
+
}
|
|
321599
|
+
var AUTH_FLOW_SEGMENTS = /* @__PURE__ */ new Set([
|
|
321600
|
+
"auth",
|
|
321601
|
+
"oauth",
|
|
321602
|
+
"oauth2",
|
|
321603
|
+
"callback",
|
|
321604
|
+
"login",
|
|
321605
|
+
"log-in",
|
|
321606
|
+
"signin",
|
|
321607
|
+
"sign-in",
|
|
321608
|
+
"signup",
|
|
321609
|
+
"sign-up",
|
|
321610
|
+
"register",
|
|
321611
|
+
"logout",
|
|
321612
|
+
"log-out",
|
|
321613
|
+
"signout",
|
|
321614
|
+
"sign-out",
|
|
321615
|
+
"sso",
|
|
321616
|
+
"saml",
|
|
321617
|
+
"oidc"
|
|
321618
|
+
]);
|
|
321619
|
+
function isAuthFlowRoute(route2) {
|
|
321620
|
+
const normalized = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(route2).toLowerCase();
|
|
321621
|
+
return normalized.split(/[/#]/).some((segment) => AUTH_FLOW_SEGMENTS.has(segment));
|
|
321622
|
+
}
|
|
321623
|
+
function routePathForScope(route2, origin) {
|
|
321624
|
+
const trimmed = (route2 ?? "").trim();
|
|
321625
|
+
if (trimmed.startsWith("//")) {
|
|
321626
|
+
try {
|
|
321627
|
+
const parsed = new URL(`https:${trimmed}`);
|
|
321628
|
+
if (parsed.host !== new URL(origin).host)
|
|
321629
|
+
return null;
|
|
321630
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
321631
|
+
} catch {
|
|
321632
|
+
return null;
|
|
321633
|
+
}
|
|
321634
|
+
}
|
|
321635
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
321636
|
+
try {
|
|
321637
|
+
const parsed = new URL(trimmed);
|
|
321638
|
+
if (parsed.origin !== origin)
|
|
321639
|
+
return null;
|
|
321640
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
321641
|
+
} catch {
|
|
321642
|
+
return trimmed;
|
|
321643
|
+
}
|
|
321644
|
+
}
|
|
321645
|
+
if (trimmed.startsWith("/") && trimmed.includes("..")) {
|
|
321646
|
+
try {
|
|
321647
|
+
const resolved = new URL(trimmed, "https://scope.invalid");
|
|
321648
|
+
return `${resolved.pathname}${resolved.search}${resolved.hash}`;
|
|
321649
|
+
} catch {
|
|
321650
|
+
return trimmed;
|
|
321651
|
+
}
|
|
321652
|
+
}
|
|
321653
|
+
return trimmed;
|
|
321654
|
+
}
|
|
321655
|
+
function buildSurveyScopeBoundary(baseUrl) {
|
|
321656
|
+
const scope = deriveSurveyPathScope(baseUrl);
|
|
321657
|
+
const lines = [
|
|
321658
|
+
'- **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'
|
|
321659
|
+
];
|
|
321660
|
+
if (scope) {
|
|
321661
|
+
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`);
|
|
321662
|
+
}
|
|
321663
|
+
return lines.join("\n");
|
|
321664
|
+
}
|
|
321665
|
+
function filterFeatureGroupsToPathScope(featureGroups, baseUrl) {
|
|
321666
|
+
const scope = deriveSurveyPathScope(baseUrl);
|
|
321667
|
+
if (!scope) {
|
|
321668
|
+
return { kept: featureGroups, droppedGroups: [], trimmedRoutes: [], trimmedPages: [], basePath: null };
|
|
321669
|
+
}
|
|
321670
|
+
const withinBase = (route2) => {
|
|
321671
|
+
const path = routePathForScope(route2, scope.origin);
|
|
321672
|
+
if (path === null)
|
|
321673
|
+
return false;
|
|
321674
|
+
if ((0, exploration_parser_js_1.routeIsWithinFocusAreas)(path, [scope.basePath]))
|
|
321675
|
+
return true;
|
|
321676
|
+
const norm = (0, exploration_parser_js_1.normalizeRouteForFocusScope)(path);
|
|
321677
|
+
return norm === `${scope.basePath}#` || norm.startsWith(`${scope.basePath}#/`);
|
|
321678
|
+
};
|
|
321679
|
+
const allowedAuthFlow = (route2) => {
|
|
321680
|
+
const path = routePathForScope(route2, scope.origin);
|
|
321681
|
+
return path !== null && isAuthFlowRoute(path);
|
|
321682
|
+
};
|
|
321683
|
+
const kept = [];
|
|
321684
|
+
const droppedGroups = [];
|
|
321685
|
+
const trimmedRoutes = [];
|
|
321686
|
+
const trimmedPages = [];
|
|
321687
|
+
for (const group of featureGroups) {
|
|
321688
|
+
const routes = Array.isArray(group.routes) ? group.routes : [];
|
|
321689
|
+
const keptRoutes = [];
|
|
321690
|
+
const removedRoutes = [];
|
|
321691
|
+
let anchored = false;
|
|
321692
|
+
for (const route2 of routes) {
|
|
321693
|
+
if (withinBase(route2)) {
|
|
321694
|
+
anchored = true;
|
|
321695
|
+
keptRoutes.push(route2);
|
|
321696
|
+
} else if (allowedAuthFlow(route2)) {
|
|
321697
|
+
keptRoutes.push(route2);
|
|
321698
|
+
} else {
|
|
321699
|
+
removedRoutes.push(route2);
|
|
321700
|
+
}
|
|
321701
|
+
}
|
|
321702
|
+
if (!anchored) {
|
|
321703
|
+
droppedGroups.push({ name: group.name, routes: [...routes] });
|
|
321704
|
+
continue;
|
|
321705
|
+
}
|
|
321706
|
+
let pages = group.pages;
|
|
321707
|
+
const removedPages = [];
|
|
321708
|
+
if (Array.isArray(group.pages)) {
|
|
321709
|
+
const keptPages = [];
|
|
321710
|
+
for (const page of group.pages) {
|
|
321711
|
+
if (withinBase(page.route) || allowedAuthFlow(page.route))
|
|
321712
|
+
keptPages.push(page);
|
|
321713
|
+
else
|
|
321714
|
+
removedPages.push(page.route);
|
|
321715
|
+
}
|
|
321716
|
+
pages = keptPages;
|
|
321717
|
+
}
|
|
321718
|
+
if (removedRoutes.length === 0 && removedPages.length === 0) {
|
|
321719
|
+
kept.push(group);
|
|
321720
|
+
} else {
|
|
321721
|
+
kept.push({ ...group, routes: keptRoutes, ...group.pages !== void 0 ? { pages } : {} });
|
|
321722
|
+
if (removedRoutes.length > 0)
|
|
321723
|
+
trimmedRoutes.push({ name: group.name, routes: removedRoutes });
|
|
321724
|
+
if (removedPages.length > 0)
|
|
321725
|
+
trimmedPages.push({ name: group.name, routes: removedPages });
|
|
321726
|
+
}
|
|
321727
|
+
}
|
|
321728
|
+
return { kept, droppedGroups, trimmedRoutes, trimmedPages, basePath: scope.basePath };
|
|
321729
|
+
}
|
|
321730
|
+
}
|
|
321731
|
+
});
|
|
321732
|
+
|
|
321380
321733
|
// ../runner-core/dist/services/discover-explorer.js
|
|
321381
321734
|
var require_discover_explorer = __commonJS({
|
|
321382
321735
|
"../runner-core/dist/services/discover-explorer.js"(exports2) {
|
|
@@ -321418,6 +321771,7 @@ var require_discover_explorer = __commonJS({
|
|
|
321418
321771
|
var evidence_harvester_js_1 = require_evidence_harvester();
|
|
321419
321772
|
var exploration_parser_js_1 = require_exploration_parser();
|
|
321420
321773
|
var survey_link_frontier_js_1 = require_survey_link_frontier();
|
|
321774
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
321421
321775
|
var snapshot_context_compactor_js_2 = require_snapshot_context_compactor();
|
|
321422
321776
|
Object.defineProperty(exports2, "formatMCPToolResult", { enumerable: true, get: function() {
|
|
321423
321777
|
return snapshot_context_compactor_js_2.formatMCPToolResult;
|
|
@@ -321845,6 +322199,7 @@ If a snapshot's readiness section exposes \`loading_indicators\`, \`skeleton_con
|
|
|
321845
322199
|
- **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
|
|
321846
322200
|
- **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
|
|
321847
322201
|
- **Stay on the same origin** as the base URL. Note external links in elements but do not follow them
|
|
322202
|
+
${(0, survey_scope_js_1.buildSurveyScopeBoundary)(baseUrl)}
|
|
321848
322203
|
- **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
|
|
321849
322204
|
- **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
|
|
321850
322205
|
- **Parameterized routes**: /users/1 and /users/2 are the same page template. Visit ONE instance, not all of them
|
|
@@ -325343,6 +325698,8 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325343
325698
|
exports2.validateSurveyorOutput = validateSurveyorOutput;
|
|
325344
325699
|
exports2.buildSurveyAgentsMd = buildSurveyAgentsMd;
|
|
325345
325700
|
exports2.buildSurveyBriefMd = buildSurveyBriefMd;
|
|
325701
|
+
exports2.buildClaudeSurveyKickoffPrompt = buildClaudeSurveyKickoffPrompt;
|
|
325702
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
325346
325703
|
var CRITICALITY_VALUES = ["critical", "high", "medium", "low"];
|
|
325347
325704
|
function isString(v) {
|
|
325348
325705
|
return typeof v === "string";
|
|
@@ -325522,9 +325879,40 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325522
325879
|
'- Click "delete" or destructive admin actions.',
|
|
325523
325880
|
"- Leave the baseUrl domain except briefly for OAuth providers.",
|
|
325524
325881
|
"",
|
|
325882
|
+
"## Navigation scope",
|
|
325883
|
+
"",
|
|
325884
|
+
"The Base URL in BRIEF.md is the ENTRY SCOPE \u2014 its full path, not just",
|
|
325885
|
+
"its domain. Open the exact Base URL first. From there, navigate ONLY to:",
|
|
325886
|
+
"",
|
|
325887
|
+
"- URLs the app actually presented to you: a link, button, or form",
|
|
325888
|
+
" visible in a snapshot of an in-scope page. (`browser_navigate` to a",
|
|
325889
|
+
" URL you saw as a link href is fine \u2014 composing one yourself is not.)",
|
|
325890
|
+
"- Redirects the app itself performs during those interactions,",
|
|
325891
|
+
" including login/OAuth/SSO callback routes needed to complete a flow.",
|
|
325892
|
+
"- The Base URL itself, to return to the start of the flow.",
|
|
325893
|
+
"",
|
|
325894
|
+
"NEVER invent a URL. Do NOT:",
|
|
325895
|
+
"- Parent-walk: truncating the Base URL path (base `/shop/checkout` \u2192",
|
|
325896
|
+
" visiting `/shop` or `/`) is out of scope even though it is same-origin.",
|
|
325897
|
+
"- Sibling-walk: do not visit or catalog neighbours of the Base URL path",
|
|
325898
|
+
" that in-scope pages never linked to.",
|
|
325899
|
+
'- Guess "common" routes (`/admin`, `/about`) or probe made-up routes',
|
|
325900
|
+
" (`/nonexistent`) to see what the error handling does. Do not create",
|
|
325901
|
+
" featureGroups for generic error/404 pages unless the app itself",
|
|
325902
|
+
" routes users there as part of a real flow.",
|
|
325903
|
+
"- Any other URL surgery: if the UI did not present it and the app did",
|
|
325904
|
+
" not redirect you to it, it does not exist for this survey.",
|
|
325905
|
+
"",
|
|
325906
|
+
"When the Base URL path is non-root (e.g. `/shop/checkout`, `/portal/billing`),",
|
|
325907
|
+
"the operator is auditing THAT flow in isolation: every featureGroup must",
|
|
325908
|
+
"describe that flow. Auth pages the flow pushes you through belong inside",
|
|
325909
|
+
"that flow's featureGroup \u2014 do not mint separate featureGroups for them.",
|
|
325910
|
+
"When the Base URL is the origin root, survey the whole app \u2014 the",
|
|
325911
|
+
"no-guessing rule still applies: reach pages through the UI.",
|
|
325912
|
+
"",
|
|
325525
325913
|
"## Exploration philosophy",
|
|
325526
325914
|
"",
|
|
325527
|
-
"- Breadth before depth \u2014 map the whole surface before drilling in.",
|
|
325915
|
+
"- Breadth before depth \u2014 map the whole in-scope surface before drilling in.",
|
|
325528
325916
|
"- Authenticated and unauthenticated surfaces are different products;",
|
|
325529
325917
|
" explore both when credentials are available.",
|
|
325530
325918
|
"- Prefer observing over interacting: open a page, snapshot, note the",
|
|
@@ -325619,6 +326007,17 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325619
326007
|
lines.push("");
|
|
325620
326008
|
lines.push(`**Base URL:** ${input.baseUrl}`);
|
|
325621
326009
|
lines.push("");
|
|
326010
|
+
const pathScope = (0, survey_scope_js_1.deriveSurveyPathScope)(input.baseUrl);
|
|
326011
|
+
if (pathScope) {
|
|
326012
|
+
lines.push(`**Entry scope:** \`${pathScope.basePath}\` \u2014 this is a SCOPED survey of one flow.`);
|
|
326013
|
+
lines.push("");
|
|
326014
|
+
lines.push(`Everything you catalog must live under \`${pathScope.basePath}\`, or be a page`);
|
|
326015
|
+
lines.push("this flow itself pushes you through (its own login page, an auth/OAuth");
|
|
326016
|
+
lines.push("callback, a post-submit redirect). Parent and sibling paths on this host");
|
|
326017
|
+
lines.push("are OTHER fixtures/apps and are out of scope \u2014 do not visit them, do not");
|
|
326018
|
+
lines.push("catalog them, do not mint featureGroups for them.");
|
|
326019
|
+
lines.push("");
|
|
326020
|
+
}
|
|
325622
326021
|
if (input.appBrief && input.appBrief.trim().length > 0) {
|
|
325623
326022
|
lines.push("## App brief from the operator");
|
|
325624
326023
|
lines.push("");
|
|
@@ -325688,6 +326087,37 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325688
326087
|
lines.push("");
|
|
325689
326088
|
return lines.join("\n");
|
|
325690
326089
|
}
|
|
326090
|
+
function buildClaudeSurveyKickoffPrompt(resultFilePath) {
|
|
326091
|
+
return [
|
|
326092
|
+
"Read AGENTS.md, then read BRIEF.md.",
|
|
326093
|
+
"",
|
|
326094
|
+
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
326095
|
+
"Follow this procedure exactly:",
|
|
326096
|
+
"",
|
|
326097
|
+
"STEP 1 \u2014 Orient: navigate to the EXACT Base URL from BRIEF.md and",
|
|
326098
|
+
" snapshot it, then open 2-3 pages its UI visibly links to (e.g. a login",
|
|
326099
|
+
" link it presents). Navigate only to URLs the page actually presented \u2014",
|
|
326100
|
+
' never guessed parent, sibling, or "common" routes (see "Navigation',
|
|
326101
|
+
' scope" in AGENTS.md).',
|
|
326102
|
+
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
326103
|
+
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
326104
|
+
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
326105
|
+
" and do NOT explore further until this file exists.",
|
|
326106
|
+
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
326107
|
+
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
326108
|
+
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
326109
|
+
" complete JSON object.",
|
|
326110
|
+
"STEP 4 \u2014 Stop once you have covered the main in-scope pages (around 20",
|
|
326111
|
+
` page visits is plenty) or stop finding new features. Do a final OVERWRITE`,
|
|
326112
|
+
` of ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
326113
|
+
"",
|
|
326114
|
+
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
326115
|
+
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
326116
|
+
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
326117
|
+
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
326118
|
+
"prose in the file \u2014 a single JSON object only."
|
|
326119
|
+
].join("\n");
|
|
326120
|
+
}
|
|
325691
326121
|
}
|
|
325692
326122
|
});
|
|
325693
326123
|
|
|
@@ -326238,6 +326668,9 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
326238
326668
|
const kickoffPrompt = [
|
|
326239
326669
|
"Read AGENTS.md, then read BRIEF.md.",
|
|
326240
326670
|
"Use the playwright MCP tools to explore the site.",
|
|
326671
|
+
'Follow the "Navigation scope" rules in AGENTS.md: start at the exact Base',
|
|
326672
|
+
'URL and never navigate to guessed parent, sibling, or "common" routes \u2014',
|
|
326673
|
+
"only URLs the pages actually present (or redirects the app performs).",
|
|
326241
326674
|
`When done, write your JSON output to ${resultFilePath} as a single JSON object matching the SurveyorOutput schema in AGENTS.md.`,
|
|
326242
326675
|
"Then exit."
|
|
326243
326676
|
].join("\n");
|
|
@@ -329954,32 +330387,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
329954
330387
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
|
|
329955
330388
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
|
|
329956
330389
|
log2("Wrote AGENTS.md + BRIEF.md");
|
|
329957
|
-
const kickoffPrompt =
|
|
329958
|
-
"Read AGENTS.md, then read BRIEF.md.",
|
|
329959
|
-
"",
|
|
329960
|
-
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
329961
|
-
"Follow this procedure exactly:",
|
|
329962
|
-
"",
|
|
329963
|
-
"STEP 1 \u2014 Orient: navigate to the base URL and 2-3 obvious pages (e.g. the",
|
|
329964
|
-
" login page and the main dashboard).",
|
|
329965
|
-
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
329966
|
-
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
329967
|
-
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
329968
|
-
" and do NOT explore further until this file exists.",
|
|
329969
|
-
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
329970
|
-
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
329971
|
-
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
329972
|
-
" complete JSON object.",
|
|
329973
|
-
"STEP 4 \u2014 Stop once you have covered the main pages (around 20 page visits",
|
|
329974
|
-
` is plenty) or stop finding new features. Do a final OVERWRITE of`,
|
|
329975
|
-
` ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
329976
|
-
"",
|
|
329977
|
-
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
329978
|
-
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
329979
|
-
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
329980
|
-
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
329981
|
-
"prose in the file \u2014 a single JSON object only."
|
|
329982
|
-
].join("\n");
|
|
330390
|
+
const kickoffPrompt = (0, agentic_survey_prompts_js_1.buildClaudeSurveyKickoffPrompt)(resultFilePath);
|
|
329983
330391
|
const credentialScrubMap = {};
|
|
329984
330392
|
for (const c of credentials) {
|
|
329985
330393
|
credentialScrubMap[c.email] = "<email>";
|
|
@@ -333991,7 +334399,7 @@ var require_local_auth_state = __commonJS({
|
|
|
333991
334399
|
exports2.ensurePrivateDirectory = ensurePrivateDirectory2;
|
|
333992
334400
|
exports2.isValidStorageState = isValidStorageState;
|
|
333993
334401
|
exports2.isValidStorageStateJson = isValidStorageStateJson;
|
|
333994
|
-
exports2.isValidLocalAuthStateFile =
|
|
334402
|
+
exports2.isValidLocalAuthStateFile = isValidLocalAuthStateFile2;
|
|
333995
334403
|
exports2.cleanupLocalAuthStateFiles = cleanupLocalAuthStateFiles;
|
|
333996
334404
|
exports2.cleanupExpiredLocalAuthStateFiles = cleanupExpiredLocalAuthStateFiles2;
|
|
333997
334405
|
exports2.localAuthStatePaths = localAuthStatePaths2;
|
|
@@ -334005,6 +334413,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334005
334413
|
var node_fs_1 = require("fs");
|
|
334006
334414
|
var node_crypto_1 = require("crypto");
|
|
334007
334415
|
var node_path_1 = require("path");
|
|
334416
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
334008
334417
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
334009
334418
|
exports2.LOCAL_AUTH_STATE_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
334010
334419
|
exports2.LOCAL_AUTH_STATE_WAIT_MS = 3 * 60 * 1e3;
|
|
@@ -334134,7 +334543,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334134
334543
|
return false;
|
|
334135
334544
|
return isValidStorageState(value);
|
|
334136
334545
|
}
|
|
334137
|
-
function
|
|
334546
|
+
function isValidLocalAuthStateFile2(path) {
|
|
334138
334547
|
try {
|
|
334139
334548
|
return isStorageStateShape(JSON.parse((0, node_fs_1.readFileSync)(path, "utf8")));
|
|
334140
334549
|
} catch {
|
|
@@ -334192,11 +334601,22 @@ var require_local_auth_state = __commonJS({
|
|
|
334192
334601
|
lockPath: `${cachePath}.lock`
|
|
334193
334602
|
};
|
|
334194
334603
|
}
|
|
334604
|
+
function localAuthStateExpiredByAuthMaterial(path, now) {
|
|
334605
|
+
try {
|
|
334606
|
+
return (0, shared_1.storageStateExpiredBySkew)((0, node_fs_1.readFileSync)(path, "utf8"), now);
|
|
334607
|
+
} catch {
|
|
334608
|
+
return false;
|
|
334609
|
+
}
|
|
334610
|
+
}
|
|
334195
334611
|
function getValidLocalAuthState2(path, now = Date.now(), maxAgeMs = exports2.LOCAL_AUTH_STATE_MAX_AGE_MS) {
|
|
334196
334612
|
if (!(0, node_fs_1.existsSync)(path))
|
|
334197
334613
|
return void 0;
|
|
334198
334614
|
try {
|
|
334199
|
-
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !
|
|
334615
|
+
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !isValidLocalAuthStateFile2(path)) {
|
|
334616
|
+
removeFile(path);
|
|
334617
|
+
return void 0;
|
|
334618
|
+
}
|
|
334619
|
+
if (localAuthStateExpiredByAuthMaterial(path, now)) {
|
|
334200
334620
|
removeFile(path);
|
|
334201
334621
|
return void 0;
|
|
334202
334622
|
}
|
|
@@ -334243,7 +334663,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334243
334663
|
removeFile(capturePath);
|
|
334244
334664
|
return false;
|
|
334245
334665
|
}
|
|
334246
|
-
if (!(0, node_fs_1.existsSync)(capturePath) || !
|
|
334666
|
+
if (!(0, node_fs_1.existsSync)(capturePath) || !isValidLocalAuthStateFile2(capturePath)) {
|
|
334247
334667
|
removeFile(capturePath);
|
|
334248
334668
|
return false;
|
|
334249
334669
|
}
|
|
@@ -334257,7 +334677,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334257
334677
|
return false;
|
|
334258
334678
|
}
|
|
334259
334679
|
if ((0, node_fs_1.existsSync)(cachePath)) {
|
|
334260
|
-
if (!replaceExisting &&
|
|
334680
|
+
if (!replaceExisting && isValidLocalAuthStateFile2(cachePath)) {
|
|
334261
334681
|
removeFile(capturePath);
|
|
334262
334682
|
return true;
|
|
334263
334683
|
}
|
|
@@ -334274,7 +334694,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334274
334694
|
}
|
|
334275
334695
|
return true;
|
|
334276
334696
|
} catch {
|
|
334277
|
-
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) &&
|
|
334697
|
+
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) && isValidLocalAuthStateFile2(cachePath);
|
|
334278
334698
|
removeFile(capturePath);
|
|
334279
334699
|
return winnerIsValid;
|
|
334280
334700
|
}
|
|
@@ -346584,9 +347004,9 @@ var require_dist2 = __commonJS({
|
|
|
346584
347004
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
346585
347005
|
};
|
|
346586
347006
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
346587
|
-
exports2.
|
|
346588
|
-
exports2.
|
|
346589
|
-
exports2.UNSUPPORTED_RENDERER_PREFIX = exports2.UnsupportedRendererError = exports2.buildCanvasModeAuthoringAddendum = exports2.buildUnsupportedRendererMessage = exports2.modelSupportsVision = exports2.decideCanvasStrategy = void 0;
|
|
347007
|
+
exports2.acquireRepoForImport = exports2.runFrameworkImportOnRunner = exports2.getAgenticEngine = exports2.resolveRefFromSnapshot = exports2.replayAuthRecipeIntoBrowser = exports2.runRegisterCaptureRun = exports2.runLoginCaptureRun = exports2.filterLoginCaptureCredentials = exports2.buildLoginCaptureCredentials = exports2.isReservedRunnerEnvVar = exports2.RESERVED_RUNNER_ENV_VARS = exports2.AUTH_MARKER_VERSION = exports2.buildHealAuthStamp = exports2.extractAuthRegion = exports2.upsertAuthBlock = exports2.buildAuthRecipe = exports2.commandToReplayStep = exports2.buildReplayPlan = exports2.absoluteRoute = exports2.renderReplaySettleArrow = exports2.renderReplayClickArrow = exports2.renderAuthFn = exports2.filterFeatureGroupsToPathScope = exports2.isAuthFlowRoute = exports2.deriveSurveyPathScope = exports2.canonicalizeRoute = exports2.executeGrokPerBatchHeal = exports2.executeGrokPerTestHeal = exports2.headerVal = exports2.classifyAuthType = exports2.isTextExcerptable = exports2.isStaticAssetByExt = exports2.isApiCall = exports2.buildApiCallSummary = exports2.computeMobileHealOutcome = exports2.detectMobileStepSecretLeak = exports2.redactMobileSecretsFromText = exports2.MOBILE_LIVE_HEAL_SYSTEM_PROMPT = exports2.MOBILE_SCRIPT_HEAL_SYSTEM_PROMPT = exports2.executeMobileLiveHeal = exports2.executeMobileTestWithHealing = exports2.executeMobileScriptDrivenHeal = exports2.prepareMobileScenarioAppState = exports2.runMobileGeneratePhase = exports2.runMobileAIPlanner = exports2.buildMobileSiteMap = exports2.formatMobileEvidenceForPlanner = exports2.MOBILE_SCENARIO_SYSTEM_PROMPT = exports2.MOBILE_SURVEY_SYSTEM_PROMPT = exports2.runMobileExplorePhase = void 0;
|
|
347008
|
+
exports2.isSafeCanonicalRedirect = exports2.resolveBaseUrlPreflight = exports2.checkBaseUrlRedirect = exports2.stripJsonFences = exports2.scrubCredentials = exports2.withAIRetry = exports2.snapshotMatchingChildren = exports2.findNewChromiumChildPid = exports2.killProcessTree = exports2.gracefulCloseWithTreeKill = exports2.liveBrowserRegistry = exports2.REPO_SWITCH_REMOVED_FRACTION = exports2.MAX_MANIFEST_FILES = exports2.toDiffSummary = exports2.isLikelyTestFile = exports2.sanitizeRepoRelPath = exports2.sha256Hex = exports2.hashFiles = exports2.enumerateTestFiles = exports2.buildNextManifest = exports2.detectRepoSwitch = exports2.classifyImportDiff = exports2.parseImportManifest = exports2.REPO_ANALYSIS_SCHEMA_VERSION = exports2.validateSourceEndpoints = exports2.validateAuthoredTest = exports2.validateRepoMapFile = exports2.validateRepoMemoryFile = exports2.buildTestingStandardsSection = exports2.buildRepoAuthorSystemRules = exports2.buildRepoAuthorKickoff = exports2.buildRepoAuthorContractMd = exports2.buildRepoMapSystemRules = exports2.buildRepoMapKickoff = exports2.buildRepoMapContractMd = exports2.buildRepoMemorySystemRules = exports2.buildRepoMemoryKickoff = exports2.buildRepoMemoryContractMd = exports2.runRepoAnalysisOnRunner = exports2.IMPORT_SCHEMA_VERSION = exports2.validateImportResultFile = exports2.validateImportedTest = exports2.buildImportSystemRules = exports2.buildImportKickoff = exports2.buildImportContractMd = exports2.MAX_ARCHIVE_BYTES = exports2.isUnsafeEntryName = exports2.extractZipSafely = exports2.downloadArchiveCapped = exports2.detectArchiveKind = void 0;
|
|
347009
|
+
exports2.UNSUPPORTED_RENDERER_PREFIX = exports2.UnsupportedRendererError = exports2.buildCanvasModeAuthoringAddendum = exports2.buildUnsupportedRendererMessage = exports2.modelSupportsVision = exports2.decideCanvasStrategy = exports2.decideAppRenderType = exports2.detectCanvasApp = exports2.detectRateLimitBlock = void 0;
|
|
346590
347010
|
__exportStar(require_ai_provider(), exports2);
|
|
346591
347011
|
__exportStar(require_mobile_types(), exports2);
|
|
346592
347012
|
__exportStar(require_mobile_source_parser(), exports2);
|
|
@@ -346694,6 +347114,16 @@ var require_dist2 = __commonJS({
|
|
|
346694
347114
|
Object.defineProperty(exports2, "canonicalizeRoute", { enumerable: true, get: function() {
|
|
346695
347115
|
return exploration_parser_js_1.canonicalizeRoute;
|
|
346696
347116
|
} });
|
|
347117
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
347118
|
+
Object.defineProperty(exports2, "deriveSurveyPathScope", { enumerable: true, get: function() {
|
|
347119
|
+
return survey_scope_js_1.deriveSurveyPathScope;
|
|
347120
|
+
} });
|
|
347121
|
+
Object.defineProperty(exports2, "isAuthFlowRoute", { enumerable: true, get: function() {
|
|
347122
|
+
return survey_scope_js_1.isAuthFlowRoute;
|
|
347123
|
+
} });
|
|
347124
|
+
Object.defineProperty(exports2, "filterFeatureGroupsToPathScope", { enumerable: true, get: function() {
|
|
347125
|
+
return survey_scope_js_1.filterFeatureGroupsToPathScope;
|
|
347126
|
+
} });
|
|
346697
347127
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
346698
347128
|
Object.defineProperty(exports2, "renderAuthFn", { enumerable: true, get: function() {
|
|
346699
347129
|
return auth_recipe_js_1.renderAuthFn;
|
|
@@ -346967,7 +347397,7 @@ var require_package4 = __commonJS({
|
|
|
346967
347397
|
"package.json"(exports2, module2) {
|
|
346968
347398
|
module2.exports = {
|
|
346969
347399
|
name: "@validate.qa/runner",
|
|
346970
|
-
version: "1.0.
|
|
347400
|
+
version: "1.0.49",
|
|
346971
347401
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
346972
347402
|
bin: {
|
|
346973
347403
|
"validate-runner": "dist/cli.js"
|
|
@@ -356629,7 +357059,7 @@ ${result2.logs}`);
|
|
|
356629
357059
|
});
|
|
356630
357060
|
} finally {
|
|
356631
357061
|
if (runAuthPath && authPaths) {
|
|
356632
|
-
if ((0, import_runner_core12.
|
|
357062
|
+
if ((0, import_runner_core12.isValidLocalAuthStateFile)(runAuthPath)) {
|
|
356633
357063
|
const releasePromotionLock = releaseAuthLock ? void 0 : await (0, import_runner_core12.acquireLocalAuthStateLock)(authPaths.lockKey, authPaths.lockPath);
|
|
356634
357064
|
try {
|
|
356635
357065
|
const captured = (0, import_runner_core12.promoteLocalAuthStateCapture)(
|