@validate.qa/runner 1.0.48 → 1.0.50
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 +266 -34
- package/dist/cli.mjs +266 -34
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -77288,7 +77288,7 @@ var require_discover_ai_planner = __commonJS({
|
|
|
77288
77288
|
"../runner-core/dist/services/discover-ai-planner.js"(exports2) {
|
|
77289
77289
|
"use strict";
|
|
77290
77290
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77291
|
-
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;
|
|
77292
77292
|
exports2.getAIPlannerMaxTokens = getAIPlannerMaxTokens;
|
|
77293
77293
|
exports2.getSnapshotConfidence = getSnapshotConfidence;
|
|
77294
77294
|
exports2.compressSiteMap = compressSiteMap;
|
|
@@ -77824,7 +77824,7 @@ Plan these LOGGED-OUT instead (keep their own establishment steps; do NOT assume
|
|
|
77824
77824
|
}
|
|
77825
77825
|
return sections.join("\n\n");
|
|
77826
77826
|
}
|
|
77827
|
-
|
|
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.
|
|
77828
77828
|
|
|
77829
77829
|
## Output Discipline
|
|
77830
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.
|
|
@@ -77844,6 +77844,7 @@ Return ONLY one valid JSON object matching the schema below. Do NOT include <thi
|
|
|
77844
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).
|
|
77845
77845
|
7. Feature descriptions MUST reference actual element labels from the evidence
|
|
77846
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.
|
|
77847
77848
|
|
|
77848
77849
|
## Output JSON Schema
|
|
77849
77850
|
{
|
|
@@ -78596,7 +78597,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
|
|
|
78596
78597
|
const agentModel = options.modelOverride ? (0, ai_provider_js_1.resolveModelForTask)(options.modelOverride, "agent") : (0, ai_provider_js_1.getModel)("agent");
|
|
78597
78598
|
const plannerMaxTokens = getAIPlannerMaxTokens(agentModel);
|
|
78598
78599
|
logs2.push(`AI planner [${context.mode}]: ${siteMap.pages.length} pages, ${evidence.recordedJourneys.length} journeys, budget ${context.testBudget}`);
|
|
78599
|
-
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);
|
|
78600
78601
|
const userPrompt = options.userPromptOverride ?? formatEvidenceForPlanner(compressed, evidence, context);
|
|
78601
78602
|
logs2.push(`AI planner: ~${Math.ceil(userPrompt.length / 3.5)} input tokens`);
|
|
78602
78603
|
const aiClient = options.aiClient ?? (options.modelOverride ? (0, ai_provider_js_1.getRunnerClientForModel)(options.modelOverride) : (0, ai_provider_js_1.getRunnerAIClient)());
|
|
@@ -321567,6 +321568,168 @@ var require_evidence_harvester = __commonJS({
|
|
|
321567
321568
|
}
|
|
321568
321569
|
});
|
|
321569
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
|
+
|
|
321570
321733
|
// ../runner-core/dist/services/discover-explorer.js
|
|
321571
321734
|
var require_discover_explorer = __commonJS({
|
|
321572
321735
|
"../runner-core/dist/services/discover-explorer.js"(exports2) {
|
|
@@ -321608,6 +321771,7 @@ var require_discover_explorer = __commonJS({
|
|
|
321608
321771
|
var evidence_harvester_js_1 = require_evidence_harvester();
|
|
321609
321772
|
var exploration_parser_js_1 = require_exploration_parser();
|
|
321610
321773
|
var survey_link_frontier_js_1 = require_survey_link_frontier();
|
|
321774
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
321611
321775
|
var snapshot_context_compactor_js_2 = require_snapshot_context_compactor();
|
|
321612
321776
|
Object.defineProperty(exports2, "formatMCPToolResult", { enumerable: true, get: function() {
|
|
321613
321777
|
return snapshot_context_compactor_js_2.formatMCPToolResult;
|
|
@@ -322035,6 +322199,7 @@ If a snapshot's readiness section exposes \`loading_indicators\`, \`skeleton_con
|
|
|
322035
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
|
|
322036
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
|
|
322037
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)}
|
|
322038
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
|
|
322039
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
|
|
322040
322205
|
- **Parameterized routes**: /users/1 and /users/2 are the same page template. Visit ONE instance, not all of them
|
|
@@ -325533,6 +325698,8 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325533
325698
|
exports2.validateSurveyorOutput = validateSurveyorOutput;
|
|
325534
325699
|
exports2.buildSurveyAgentsMd = buildSurveyAgentsMd;
|
|
325535
325700
|
exports2.buildSurveyBriefMd = buildSurveyBriefMd;
|
|
325701
|
+
exports2.buildClaudeSurveyKickoffPrompt = buildClaudeSurveyKickoffPrompt;
|
|
325702
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
325536
325703
|
var CRITICALITY_VALUES = ["critical", "high", "medium", "low"];
|
|
325537
325704
|
function isString(v) {
|
|
325538
325705
|
return typeof v === "string";
|
|
@@ -325712,9 +325879,40 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325712
325879
|
'- Click "delete" or destructive admin actions.',
|
|
325713
325880
|
"- Leave the baseUrl domain except briefly for OAuth providers.",
|
|
325714
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
|
+
"",
|
|
325715
325913
|
"## Exploration philosophy",
|
|
325716
325914
|
"",
|
|
325717
|
-
"- 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.",
|
|
325718
325916
|
"- Authenticated and unauthenticated surfaces are different products;",
|
|
325719
325917
|
" explore both when credentials are available.",
|
|
325720
325918
|
"- Prefer observing over interacting: open a page, snapshot, note the",
|
|
@@ -325809,6 +326007,17 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325809
326007
|
lines.push("");
|
|
325810
326008
|
lines.push(`**Base URL:** ${input.baseUrl}`);
|
|
325811
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
|
+
}
|
|
325812
326021
|
if (input.appBrief && input.appBrief.trim().length > 0) {
|
|
325813
326022
|
lines.push("## App brief from the operator");
|
|
325814
326023
|
lines.push("");
|
|
@@ -325878,6 +326087,37 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325878
326087
|
lines.push("");
|
|
325879
326088
|
return lines.join("\n");
|
|
325880
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
|
+
}
|
|
325881
326121
|
}
|
|
325882
326122
|
});
|
|
325883
326123
|
|
|
@@ -326428,6 +326668,9 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
326428
326668
|
const kickoffPrompt = [
|
|
326429
326669
|
"Read AGENTS.md, then read BRIEF.md.",
|
|
326430
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).",
|
|
326431
326674
|
`When done, write your JSON output to ${resultFilePath} as a single JSON object matching the SurveyorOutput schema in AGENTS.md.`,
|
|
326432
326675
|
"Then exit."
|
|
326433
326676
|
].join("\n");
|
|
@@ -330144,32 +330387,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
330144
330387
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
|
|
330145
330388
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
|
|
330146
330389
|
log2("Wrote AGENTS.md + BRIEF.md");
|
|
330147
|
-
const kickoffPrompt =
|
|
330148
|
-
"Read AGENTS.md, then read BRIEF.md.",
|
|
330149
|
-
"",
|
|
330150
|
-
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
330151
|
-
"Follow this procedure exactly:",
|
|
330152
|
-
"",
|
|
330153
|
-
"STEP 1 \u2014 Orient: navigate to the base URL and 2-3 obvious pages (e.g. the",
|
|
330154
|
-
" login page and the main dashboard).",
|
|
330155
|
-
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
330156
|
-
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
330157
|
-
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
330158
|
-
" and do NOT explore further until this file exists.",
|
|
330159
|
-
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
330160
|
-
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
330161
|
-
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
330162
|
-
" complete JSON object.",
|
|
330163
|
-
"STEP 4 \u2014 Stop once you have covered the main pages (around 20 page visits",
|
|
330164
|
-
` is plenty) or stop finding new features. Do a final OVERWRITE of`,
|
|
330165
|
-
` ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
330166
|
-
"",
|
|
330167
|
-
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
330168
|
-
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
330169
|
-
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
330170
|
-
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
330171
|
-
"prose in the file \u2014 a single JSON object only."
|
|
330172
|
-
].join("\n");
|
|
330390
|
+
const kickoffPrompt = (0, agentic_survey_prompts_js_1.buildClaudeSurveyKickoffPrompt)(resultFilePath);
|
|
330173
330391
|
const credentialScrubMap = {};
|
|
330174
330392
|
for (const c of credentials) {
|
|
330175
330393
|
credentialScrubMap[c.email] = "<email>";
|
|
@@ -346786,9 +347004,9 @@ var require_dist2 = __commonJS({
|
|
|
346786
347004
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
346787
347005
|
};
|
|
346788
347006
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
346789
|
-
exports2.
|
|
346790
|
-
exports2.
|
|
346791
|
-
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;
|
|
346792
347010
|
__exportStar(require_ai_provider(), exports2);
|
|
346793
347011
|
__exportStar(require_mobile_types(), exports2);
|
|
346794
347012
|
__exportStar(require_mobile_source_parser(), exports2);
|
|
@@ -346896,6 +347114,16 @@ var require_dist2 = __commonJS({
|
|
|
346896
347114
|
Object.defineProperty(exports2, "canonicalizeRoute", { enumerable: true, get: function() {
|
|
346897
347115
|
return exploration_parser_js_1.canonicalizeRoute;
|
|
346898
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
|
+
} });
|
|
346899
347127
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
346900
347128
|
Object.defineProperty(exports2, "renderAuthFn", { enumerable: true, get: function() {
|
|
346901
347129
|
return auth_recipe_js_1.renderAuthFn;
|
|
@@ -347169,7 +347397,7 @@ var require_package4 = __commonJS({
|
|
|
347169
347397
|
"package.json"(exports2, module2) {
|
|
347170
347398
|
module2.exports = {
|
|
347171
347399
|
name: "@validate.qa/runner",
|
|
347172
|
-
version: "1.0.
|
|
347400
|
+
version: "1.0.50",
|
|
347173
347401
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
347174
347402
|
bin: {
|
|
347175
347403
|
"validate-runner": "dist/cli.js"
|
|
@@ -348091,6 +348319,8 @@ async function typeText(sessionPath, value, bounds) {
|
|
|
348091
348319
|
} catch (err) {
|
|
348092
348320
|
if (isAppiumDriverDeadError(err)) throw err;
|
|
348093
348321
|
}
|
|
348322
|
+
} else if (bounds === void 0) {
|
|
348323
|
+
throw new Error("No focused element available for TYPE. Tap an input field first.");
|
|
348094
348324
|
}
|
|
348095
348325
|
await sendKeysToFocusedInput(sessionPath, value);
|
|
348096
348326
|
}
|
|
@@ -348121,6 +348351,8 @@ async function clearField(sessionPath, bounds) {
|
|
|
348121
348351
|
} catch (err) {
|
|
348122
348352
|
if (isAppiumDriverDeadError(err)) throw err;
|
|
348123
348353
|
}
|
|
348354
|
+
} else if (bounds === void 0) {
|
|
348355
|
+
throw new Error("No focused element available for CLEAR. Tap an input field first.");
|
|
348124
348356
|
}
|
|
348125
348357
|
try {
|
|
348126
348358
|
await appiumRequest(`${sessionPath}/keys`, {
|
package/dist/cli.mjs
CHANGED
|
@@ -77293,7 +77293,7 @@ var require_discover_ai_planner = __commonJS({
|
|
|
77293
77293
|
"../runner-core/dist/services/discover-ai-planner.js"(exports) {
|
|
77294
77294
|
"use strict";
|
|
77295
77295
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77296
|
-
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;
|
|
77297
77297
|
exports.getAIPlannerMaxTokens = getAIPlannerMaxTokens;
|
|
77298
77298
|
exports.getSnapshotConfidence = getSnapshotConfidence;
|
|
77299
77299
|
exports.compressSiteMap = compressSiteMap;
|
|
@@ -77829,7 +77829,7 @@ Plan these LOGGED-OUT instead (keep their own establishment steps; do NOT assume
|
|
|
77829
77829
|
}
|
|
77830
77830
|
return sections.join("\n\n");
|
|
77831
77831
|
}
|
|
77832
|
-
|
|
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.
|
|
77833
77833
|
|
|
77834
77834
|
## Output Discipline
|
|
77835
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.
|
|
@@ -77849,6 +77849,7 @@ Return ONLY one valid JSON object matching the schema below. Do NOT include <thi
|
|
|
77849
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).
|
|
77850
77850
|
7. Feature descriptions MUST reference actual element labels from the evidence
|
|
77851
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.
|
|
77852
77853
|
|
|
77853
77854
|
## Output JSON Schema
|
|
77854
77855
|
{
|
|
@@ -78601,7 +78602,7 @@ Keep the exact JSON schema { "featureGroups":[...], "scenarios":[...], "reasonin
|
|
|
78601
78602
|
const agentModel = options.modelOverride ? (0, ai_provider_js_1.resolveModelForTask)(options.modelOverride, "agent") : (0, ai_provider_js_1.getModel)("agent");
|
|
78602
78603
|
const plannerMaxTokens = getAIPlannerMaxTokens(agentModel);
|
|
78603
78604
|
logs2.push(`AI planner [${context.mode}]: ${siteMap.pages.length} pages, ${evidence.recordedJourneys.length} journeys, budget ${context.testBudget}`);
|
|
78604
|
-
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);
|
|
78605
78606
|
const userPrompt = options.userPromptOverride ?? formatEvidenceForPlanner(compressed, evidence, context);
|
|
78606
78607
|
logs2.push(`AI planner: ~${Math.ceil(userPrompt.length / 3.5)} input tokens`);
|
|
78607
78608
|
const aiClient = options.aiClient ?? (options.modelOverride ? (0, ai_provider_js_1.getRunnerClientForModel)(options.modelOverride) : (0, ai_provider_js_1.getRunnerAIClient)());
|
|
@@ -321572,6 +321573,168 @@ var require_evidence_harvester = __commonJS({
|
|
|
321572
321573
|
}
|
|
321573
321574
|
});
|
|
321574
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
|
+
|
|
321575
321738
|
// ../runner-core/dist/services/discover-explorer.js
|
|
321576
321739
|
var require_discover_explorer = __commonJS({
|
|
321577
321740
|
"../runner-core/dist/services/discover-explorer.js"(exports) {
|
|
@@ -321613,6 +321776,7 @@ var require_discover_explorer = __commonJS({
|
|
|
321613
321776
|
var evidence_harvester_js_1 = require_evidence_harvester();
|
|
321614
321777
|
var exploration_parser_js_1 = require_exploration_parser();
|
|
321615
321778
|
var survey_link_frontier_js_1 = require_survey_link_frontier();
|
|
321779
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
321616
321780
|
var snapshot_context_compactor_js_2 = require_snapshot_context_compactor();
|
|
321617
321781
|
Object.defineProperty(exports, "formatMCPToolResult", { enumerable: true, get: function() {
|
|
321618
321782
|
return snapshot_context_compactor_js_2.formatMCPToolResult;
|
|
@@ -322040,6 +322204,7 @@ If a snapshot's readiness section exposes \`loading_indicators\`, \`skeleton_con
|
|
|
322040
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
|
|
322041
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
|
|
322042
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)}
|
|
322043
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
|
|
322044
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
|
|
322045
322210
|
- **Parameterized routes**: /users/1 and /users/2 are the same page template. Visit ONE instance, not all of them
|
|
@@ -325538,6 +325703,8 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325538
325703
|
exports.validateSurveyorOutput = validateSurveyorOutput;
|
|
325539
325704
|
exports.buildSurveyAgentsMd = buildSurveyAgentsMd;
|
|
325540
325705
|
exports.buildSurveyBriefMd = buildSurveyBriefMd;
|
|
325706
|
+
exports.buildClaudeSurveyKickoffPrompt = buildClaudeSurveyKickoffPrompt;
|
|
325707
|
+
var survey_scope_js_1 = require_survey_scope();
|
|
325541
325708
|
var CRITICALITY_VALUES = ["critical", "high", "medium", "low"];
|
|
325542
325709
|
function isString(v) {
|
|
325543
325710
|
return typeof v === "string";
|
|
@@ -325717,9 +325884,40 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325717
325884
|
'- Click "delete" or destructive admin actions.',
|
|
325718
325885
|
"- Leave the baseUrl domain except briefly for OAuth providers.",
|
|
325719
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
|
+
"",
|
|
325720
325918
|
"## Exploration philosophy",
|
|
325721
325919
|
"",
|
|
325722
|
-
"- 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.",
|
|
325723
325921
|
"- Authenticated and unauthenticated surfaces are different products;",
|
|
325724
325922
|
" explore both when credentials are available.",
|
|
325725
325923
|
"- Prefer observing over interacting: open a page, snapshot, note the",
|
|
@@ -325814,6 +326012,17 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325814
326012
|
lines.push("");
|
|
325815
326013
|
lines.push(`**Base URL:** ${input.baseUrl}`);
|
|
325816
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
|
+
}
|
|
325817
326026
|
if (input.appBrief && input.appBrief.trim().length > 0) {
|
|
325818
326027
|
lines.push("## App brief from the operator");
|
|
325819
326028
|
lines.push("");
|
|
@@ -325883,6 +326092,37 @@ var require_agentic_survey_prompts = __commonJS({
|
|
|
325883
326092
|
lines.push("");
|
|
325884
326093
|
return lines.join("\n");
|
|
325885
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
|
+
}
|
|
325886
326126
|
}
|
|
325887
326127
|
});
|
|
325888
326128
|
|
|
@@ -326433,6 +326673,9 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
326433
326673
|
const kickoffPrompt = [
|
|
326434
326674
|
"Read AGENTS.md, then read BRIEF.md.",
|
|
326435
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).",
|
|
326436
326679
|
`When done, write your JSON output to ${resultFilePath} as a single JSON object matching the SurveyorOutput schema in AGENTS.md.`,
|
|
326437
326680
|
"Then exit."
|
|
326438
326681
|
].join("\n");
|
|
@@ -330149,32 +330392,7 @@ ${(0, inbox_tools_js_1.buildInboxAgentsGuidance)(inboxReg.email, inboxReg.passwo
|
|
|
330149
330392
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "AGENTS.md"), surveyAgentsMd, "utf8");
|
|
330150
330393
|
await (0, promises_1.writeFile)((0, node_path_1.join)(runDir, "BRIEF.md"), (0, agentic_survey_prompts_js_1.buildSurveyBriefMd)(briefInput), "utf8");
|
|
330151
330394
|
log2("Wrote AGENTS.md + BRIEF.md");
|
|
330152
|
-
const kickoffPrompt =
|
|
330153
|
-
"Read AGENTS.md, then read BRIEF.md.",
|
|
330154
|
-
"",
|
|
330155
|
-
`Your deliverable is a SurveyorOutput JSON file at ${resultFilePath}.`,
|
|
330156
|
-
"Follow this procedure exactly:",
|
|
330157
|
-
"",
|
|
330158
|
-
"STEP 1 \u2014 Orient: navigate to the base URL and 2-3 obvious pages (e.g. the",
|
|
330159
|
-
" login page and the main dashboard).",
|
|
330160
|
-
`STEP 2 \u2014 IMMEDIATELY use the Write tool to save a first COMPLETE draft of`,
|
|
330161
|
-
` the SurveyorOutput JSON to ${resultFilePath}, based on what you have seen`,
|
|
330162
|
-
" so far. featureGroups must be a non-empty array. Do NOT skip this step",
|
|
330163
|
-
" and do NOT explore further until this file exists.",
|
|
330164
|
-
"STEP 3 \u2014 Continue exploring breadth-first. Visit each remaining page AT",
|
|
330165
|
-
" MOST ONCE \u2014 never re-navigate to or re-snapshot a page already seen.",
|
|
330166
|
-
` After every 3-4 new pages, OVERWRITE ${resultFilePath} with an updated,`,
|
|
330167
|
-
" complete JSON object.",
|
|
330168
|
-
"STEP 4 \u2014 Stop once you have covered the main pages (around 20 page visits",
|
|
330169
|
-
` is plenty) or stop finding new features. Do a final OVERWRITE of`,
|
|
330170
|
-
` ${resultFilePath} with the complete SurveyorOutput, then exit.`,
|
|
330171
|
-
"",
|
|
330172
|
-
"Budget: about 40 tool calls total. If you ever sense you are running low,",
|
|
330173
|
-
`immediately overwrite ${resultFilePath} with your best current JSON and`,
|
|
330174
|
-
"exit \u2014 a complete-but-shallow file always beats no file. Never write an",
|
|
330175
|
-
"empty featureGroups array and never omit the key. No markdown fences, no",
|
|
330176
|
-
"prose in the file \u2014 a single JSON object only."
|
|
330177
|
-
].join("\n");
|
|
330395
|
+
const kickoffPrompt = (0, agentic_survey_prompts_js_1.buildClaudeSurveyKickoffPrompt)(resultFilePath);
|
|
330178
330396
|
const credentialScrubMap = {};
|
|
330179
330397
|
for (const c of credentials) {
|
|
330180
330398
|
credentialScrubMap[c.email] = "<email>";
|
|
@@ -346791,9 +347009,9 @@ var require_dist2 = __commonJS({
|
|
|
346791
347009
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
346792
347010
|
};
|
|
346793
347011
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
346794
|
-
exports.
|
|
346795
|
-
exports.
|
|
346796
|
-
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;
|
|
346797
347015
|
__exportStar(require_ai_provider(), exports);
|
|
346798
347016
|
__exportStar(require_mobile_types(), exports);
|
|
346799
347017
|
__exportStar(require_mobile_source_parser(), exports);
|
|
@@ -346901,6 +347119,16 @@ var require_dist2 = __commonJS({
|
|
|
346901
347119
|
Object.defineProperty(exports, "canonicalizeRoute", { enumerable: true, get: function() {
|
|
346902
347120
|
return exploration_parser_js_1.canonicalizeRoute;
|
|
346903
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
|
+
} });
|
|
346904
347132
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
346905
347133
|
Object.defineProperty(exports, "renderAuthFn", { enumerable: true, get: function() {
|
|
346906
347134
|
return auth_recipe_js_1.renderAuthFn;
|
|
@@ -347174,7 +347402,7 @@ var require_package4 = __commonJS({
|
|
|
347174
347402
|
"package.json"(exports, module) {
|
|
347175
347403
|
module.exports = {
|
|
347176
347404
|
name: "@validate.qa/runner",
|
|
347177
|
-
version: "1.0.
|
|
347405
|
+
version: "1.0.50",
|
|
347178
347406
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
347179
347407
|
bin: {
|
|
347180
347408
|
"validate-runner": "dist/cli.js"
|
|
@@ -348096,6 +348324,8 @@ async function typeText(sessionPath, value, bounds) {
|
|
|
348096
348324
|
} catch (err) {
|
|
348097
348325
|
if (isAppiumDriverDeadError(err)) throw err;
|
|
348098
348326
|
}
|
|
348327
|
+
} else if (bounds === void 0) {
|
|
348328
|
+
throw new Error("No focused element available for TYPE. Tap an input field first.");
|
|
348099
348329
|
}
|
|
348100
348330
|
await sendKeysToFocusedInput(sessionPath, value);
|
|
348101
348331
|
}
|
|
@@ -348126,6 +348356,8 @@ async function clearField(sessionPath, bounds) {
|
|
|
348126
348356
|
} catch (err) {
|
|
348127
348357
|
if (isAppiumDriverDeadError(err)) throw err;
|
|
348128
348358
|
}
|
|
348359
|
+
} else if (bounds === void 0) {
|
|
348360
|
+
throw new Error("No focused element available for CLEAR. Tap an input field first.");
|
|
348129
348361
|
}
|
|
348130
348362
|
try {
|
|
348131
348363
|
await appiumRequest(`${sessionPath}/keys`, {
|
package/package.json
CHANGED