@sudobility/testomniac_runner_service 0.1.36 → 0.1.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/api/client.d.ts +60 -1
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +21 -2
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/crawler/link-extractor.d.ts +8 -0
  6. package/dist/crawler/link-extractor.d.ts.map +1 -0
  7. package/dist/crawler/link-extractor.js +37 -0
  8. package/dist/crawler/link-extractor.js.map +1 -0
  9. package/dist/crawler/url-normalizer.d.ts +4 -0
  10. package/dist/crawler/url-normalizer.d.ts.map +1 -0
  11. package/dist/crawler/url-normalizer.js +27 -0
  12. package/dist/crawler/url-normalizer.js.map +1 -0
  13. package/dist/expertise/accessibility-expertise.d.ts +11 -0
  14. package/dist/expertise/accessibility-expertise.d.ts.map +1 -0
  15. package/dist/expertise/accessibility-expertise.js +131 -0
  16. package/dist/expertise/accessibility-expertise.js.map +1 -0
  17. package/dist/expertise/content-expertise.d.ts +10 -0
  18. package/dist/expertise/content-expertise.d.ts.map +1 -0
  19. package/dist/expertise/content-expertise.js +102 -0
  20. package/dist/expertise/content-expertise.js.map +1 -0
  21. package/dist/expertise/index.d.ts +3 -0
  22. package/dist/expertise/index.d.ts.map +1 -1
  23. package/dist/expertise/index.js +9 -4
  24. package/dist/expertise/index.js.map +1 -1
  25. package/dist/expertise/ui-expertise.d.ts +10 -0
  26. package/dist/expertise/ui-expertise.d.ts.map +1 -0
  27. package/dist/expertise/ui-expertise.js +76 -0
  28. package/dist/expertise/ui-expertise.js.map +1 -0
  29. package/dist/orchestrator/decomposition.d.ts.map +1 -1
  30. package/dist/orchestrator/decomposition.js +300 -65
  31. package/dist/orchestrator/decomposition.js.map +1 -1
  32. package/dist/orchestrator/direct-navigation.d.ts +4 -0
  33. package/dist/orchestrator/direct-navigation.d.ts.map +1 -0
  34. package/dist/orchestrator/direct-navigation.js +47 -0
  35. package/dist/orchestrator/direct-navigation.js.map +1 -0
  36. package/dist/orchestrator/discovery.d.ts +10 -0
  37. package/dist/orchestrator/discovery.d.ts.map +1 -0
  38. package/dist/orchestrator/discovery.js +77 -0
  39. package/dist/orchestrator/discovery.js.map +1 -0
  40. package/dist/orchestrator/expertise.d.ts +5 -0
  41. package/dist/orchestrator/expertise.d.ts.map +1 -0
  42. package/dist/orchestrator/expertise.js +157 -0
  43. package/dist/orchestrator/expertise.js.map +1 -0
  44. package/dist/orchestrator/orchestrator.d.ts.map +1 -1
  45. package/dist/orchestrator/orchestrator.js +63 -37
  46. package/dist/orchestrator/orchestrator.js.map +1 -1
  47. package/dist/orchestrator/page-capture.d.ts +22 -0
  48. package/dist/orchestrator/page-capture.d.ts.map +1 -0
  49. package/dist/orchestrator/page-capture.js +102 -0
  50. package/dist/orchestrator/page-capture.js.map +1 -0
  51. package/dist/orchestrator/test-execution.d.ts.map +1 -1
  52. package/dist/orchestrator/test-execution.js +17 -32
  53. package/dist/orchestrator/test-execution.js.map +1 -1
  54. package/dist/orchestrator/types.d.ts +10 -0
  55. package/dist/orchestrator/types.d.ts.map +1 -1
  56. package/package.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct-navigation.js","sourceRoot":"","sources":["../../src/orchestrator/direct-navigation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAEpD,KAAK,UAAU,2BAA2B,CACxC,GAAc,EACd,MAAkB,EAClB,MAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,sBAAsB,CAAC,CAAC;IAC9E,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE;QACvD,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,gDAAgD;QAC7D,YAAY,EAAE,GAAG;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAC,mBAAmB,CAAC;KAC3B,CAAC,CAAC;IACV,MAAM,CAAC,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACrE,OAAO,KAAK,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,GAAc,EACd,MAAkB,EAClB,MAAwB,EACxB,YAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,2BAA2B,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,cAAc,CACvC,MAAM,CAAC,QAAQ,EACf;QACE,KAAK,EAAE,eAAe,YAAY,IAAI,GAAG,EAAE;QAC3C,IAAI,EAAE,YAAY;QAClB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,CAAC,mBAAmB,CAAC;QACjC,YAAY,EAAE,YAAY,IAAI,GAAG;QACjC,KAAK,EAAE,EAAE;QACT,kBAAkB,EAAE,EAAE;KAChB,EACR,OAAO,CACR,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,MAAM,GAAG,CAAC,gBAAgB,CAAC;QACzB,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,SAAS,EAAE,CAAC;QACZ,UAAU,EAAE,gBAAgB,CAAC,IAAI;QACjC,IAAI,EAAE,YAAY,IAAI,GAAG;QACzB,cAAc,EAAE,oBAAoB,YAAY,IAAI,GAAG,KAAK;QAC5D,WAAW,EAAE,eAAe,YAAY,IAAI,GAAG,EAAE;QACjD,YAAY,EAAE,EAAE;QAChB,iBAAiB,EAAE,KAAK;KACzB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { BrowserAdapter } from "../adapter";
2
+ import type { ApiClient } from "../api/client";
3
+ import type { ScanConfig, ScanEventHandler } from "./types";
4
+ export interface DiscoveryResult {
5
+ pageIdsByPath: Map<string, number>;
6
+ visitedPaths: Set<string>;
7
+ capturedPaths: Set<string>;
8
+ }
9
+ export declare function discoverPublicPages(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler): Promise<DiscoveryResult>;
10
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/orchestrator/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAc5D,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,eAAe,CAAC,CAkF1B"}
@@ -0,0 +1,77 @@
1
+ import { ensureDirectNavigationCase } from "./direct-navigation";
2
+ import { extractSameOriginLinks } from "../crawler/link-extractor";
3
+ import { toRelativePath } from "../crawler/url-normalizer";
4
+ import { captureCurrentPage } from "./page-capture";
5
+ const LOG = (...args) => console.warn("[discovery]", ...args);
6
+ const MAX_DISCOVERY_PAGES = 25;
7
+ function checkAbort(signal) {
8
+ if (signal?.aborted)
9
+ throw new Error("Scan aborted");
10
+ }
11
+ export async function discoverPublicPages(adapter, config, api, events) {
12
+ const queue = [config.scanUrl];
13
+ const visitedPaths = new Set();
14
+ const pageIdsByPath = new Map();
15
+ const capturedPaths = new Set();
16
+ while (queue.length > 0 && visitedPaths.size < MAX_DISCOVERY_PAGES) {
17
+ checkAbort(config.signal);
18
+ const nextUrl = queue.shift();
19
+ if (!nextUrl)
20
+ break;
21
+ LOG(`Visiting ${nextUrl}`);
22
+ try {
23
+ await adapter.goto(nextUrl, { waitUntil: "networkidle0" });
24
+ }
25
+ catch (error) {
26
+ const relativePath = toRelativePath(nextUrl);
27
+ if (config.testEnvironmentId) {
28
+ await api.createPageVisit({
29
+ testRunId: config.scanId,
30
+ testEnvironmentId: config.testEnvironmentId,
31
+ relativePath,
32
+ status: "failed",
33
+ errorMessage: error instanceof Error ? error.message : "Navigation failed",
34
+ });
35
+ }
36
+ continue;
37
+ }
38
+ const currentUrl = await adapter.getUrl();
39
+ const relativePath = toRelativePath(currentUrl);
40
+ if (visitedPaths.has(relativePath)) {
41
+ continue;
42
+ }
43
+ visitedPaths.add(relativePath);
44
+ const page = await api.findOrCreatePage(config.runnerId, relativePath);
45
+ pageIdsByPath.set(relativePath, page.id);
46
+ await ensureDirectNavigationCase(api, config, events, relativePath);
47
+ const captureResult = await captureCurrentPage(adapter, config, api, events, {
48
+ testRunId: config.scanId,
49
+ markDiscovered: true,
50
+ captureState: relativePath !== toRelativePath(config.scanUrl),
51
+ createDecompositionJob: relativePath !== toRelativePath(config.scanUrl),
52
+ });
53
+ if (captureResult?.createdNewState) {
54
+ capturedPaths.add(relativePath);
55
+ }
56
+ const discoveredLinks = await extractSameOriginLinks(adapter, config.baseUrl);
57
+ LOG(`Discovered ${discoveredLinks.length} links on ${relativePath}`);
58
+ if (config.testEnvironmentId && discoveredLinks.length > 0) {
59
+ await api.createDiscoveredPages({
60
+ testEnvironmentId: config.testEnvironmentId,
61
+ pages: discoveredLinks.map(link => ({
62
+ relativePath: link.relativePath,
63
+ sourcePagePath: relativePath,
64
+ sourceLabel: link.label,
65
+ isPublic: true,
66
+ })),
67
+ });
68
+ }
69
+ for (const link of discoveredLinks) {
70
+ if (!visitedPaths.has(link.relativePath)) {
71
+ queue.push(link.url);
72
+ }
73
+ }
74
+ }
75
+ return { pageIdsByPath, visitedPaths, capturedPaths };
76
+ }
77
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/orchestrator/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { BrowserAdapter } from "../adapter";
2
+ import type { ApiClient } from "../api/client";
3
+ import type { ScanConfig, ScanEventHandler } from "./types";
4
+ export declare function executePageExpertises(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler, pageStateId: number, pageId: number, relativePath: string): Promise<void>;
5
+ //# sourceMappingURL=expertise.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expertise.d.ts","sourceRoot":"","sources":["../../src/orchestrator/expertise.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAmG5D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA4Gf"}
@@ -0,0 +1,157 @@
1
+ import { ExpectationType } from "../domain/types";
2
+ import { createDefaultExpertises } from "../expertise";
3
+ import { detectScaffoldRegions } from "../scanner/component-detector";
4
+ import { detectPatternsWithInstances } from "../scanner/pattern-detector";
5
+ const EXPERTISE_PREFIX = "Expertise:";
6
+ function buildDefaultExpectations() {
7
+ return [
8
+ {
9
+ expectationType: ExpectationType.PageLoaded,
10
+ description: "Page should load successfully",
11
+ },
12
+ {
13
+ expectationType: ExpectationType.NoConsoleErrors,
14
+ description: "Page should not produce console errors",
15
+ },
16
+ {
17
+ expectationType: ExpectationType.NoNetworkErrors,
18
+ description: "Page should not produce network errors",
19
+ },
20
+ ];
21
+ }
22
+ function normalizeOutcomes(outcomes) {
23
+ const expectedOutcome = outcomes.length > 0
24
+ ? outcomes.map(item => item.expected).join("\n")
25
+ : undefined;
26
+ const observedOutcome = outcomes.length > 0
27
+ ? outcomes.map(item => `[${item.result}] ${item.observed}`).join("\n")
28
+ : undefined;
29
+ const hasErrors = outcomes.some(item => item.result === "error");
30
+ return {
31
+ expectedOutcome,
32
+ observedOutcome,
33
+ status: hasErrors ? "failed" : "completed",
34
+ };
35
+ }
36
+ async function ensureExpertiseSuite(api, config, events, expertiseName) {
37
+ const title = `${EXPERTISE_PREFIX} ${expertiseName}`;
38
+ const suites = await api.getTestSuitesByRunner(config.runnerId);
39
+ const existing = suites.find(suite => suite.title === title);
40
+ if (existing) {
41
+ return existing.id;
42
+ }
43
+ const created = await api.insertTestSuite(config.runnerId, {
44
+ title,
45
+ description: `Auto-generated expertise suite for ${expertiseName} findings`,
46
+ startingPath: "/",
47
+ sizeClass: config.sizeClass,
48
+ priority: 2,
49
+ suite_tags: ["expertise", expertiseName],
50
+ });
51
+ events.onTestSuiteCreated({ suiteId: created.id, title: created.title });
52
+ return created.id;
53
+ }
54
+ async function ensureExpertiseCase(api, config, suiteId, expertiseName, pageStateId, pageId, relativePath) {
55
+ const testCase = await api.insertTestCase(config.runnerId, {
56
+ title: `${expertiseName}: ${relativePath || "/"}`,
57
+ type: "render",
58
+ sizeClass: config.sizeClass,
59
+ suite_tags: ["expertise", expertiseName],
60
+ page_id: pageId,
61
+ priority: 2,
62
+ startingPageStateId: pageStateId,
63
+ startingPath: relativePath || "/",
64
+ steps: [],
65
+ globalExpectations: [],
66
+ }, suiteId);
67
+ return testCase.id;
68
+ }
69
+ export async function executePageExpertises(adapter, config, api, events, pageStateId, pageId, relativePath) {
70
+ const html = await adapter.content();
71
+ const scaffolds = await detectScaffoldRegions(adapter);
72
+ const patterns = await detectPatternsWithInstances(adapter);
73
+ const context = {
74
+ html,
75
+ scaffolds,
76
+ patterns,
77
+ consoleLogs: [],
78
+ networkLogs: [],
79
+ expectations: buildDefaultExpectations(),
80
+ };
81
+ const expertises = createDefaultExpertises();
82
+ for (const expertise of expertises) {
83
+ const suiteId = await ensureExpertiseSuite(api, config, events, expertise.name);
84
+ const testCaseId = await ensureExpertiseCase(api, config, suiteId, expertise.name, pageStateId, pageId, relativePath);
85
+ const testCaseRun = await api.createTestCaseRun({ testCaseId });
86
+ const testRun = await api.createTestRun({
87
+ runnerId: config.runnerId,
88
+ testCaseRunId: testCaseRun.id,
89
+ testEnvironmentId: config.testEnvironmentId,
90
+ parentTestRunId: config.scanId,
91
+ rootTestRunId: config.scanId,
92
+ sizeClass: config.sizeClass,
93
+ runnerInstanceId: config.runnerInstanceId,
94
+ runnerInstanceName: config.runnerInstanceName,
95
+ });
96
+ const startedAt = Date.now();
97
+ try {
98
+ const outcomes = expertise.evaluate(context);
99
+ const { expectedOutcome, observedOutcome, status } = normalizeOutcomes(outcomes);
100
+ for (const outcome of outcomes) {
101
+ if (outcome.result === "warning" || outcome.result === "error") {
102
+ await api.createTestRunFinding({
103
+ testCaseRunId: testCaseRun.id,
104
+ type: outcome.result === "error" ? "error" : "warning",
105
+ title: `[${expertise.name}] ${outcome.expected}`,
106
+ description: outcome.observed,
107
+ });
108
+ events.onFindingCreated({
109
+ type: outcome.result,
110
+ title: `[${expertise.name}] ${outcome.expected}`,
111
+ });
112
+ }
113
+ }
114
+ await api.completeTestCaseRun(testCaseRun.id, {
115
+ status,
116
+ durationMs: Date.now() - startedAt,
117
+ expectedOutcome,
118
+ observedOutcome,
119
+ });
120
+ await api.completeTestRun(testRun.id, {
121
+ status,
122
+ totalDurationMs: Date.now() - startedAt,
123
+ });
124
+ events.onTestRunCompleted({
125
+ testRunId: testRun.id,
126
+ passed: status !== "failed",
127
+ });
128
+ }
129
+ catch (error) {
130
+ const message = error instanceof Error ? error.message : "Expertise evaluation failed";
131
+ await api.completeTestCaseRun(testCaseRun.id, {
132
+ status: "failed",
133
+ durationMs: Date.now() - startedAt,
134
+ errorMessage: message,
135
+ });
136
+ await api.completeTestRun(testRun.id, {
137
+ status: "failed",
138
+ totalDurationMs: Date.now() - startedAt,
139
+ });
140
+ await api.createTestRunFinding({
141
+ testCaseRunId: testCaseRun.id,
142
+ type: "error",
143
+ title: `[${expertise.name}] expertise execution failed`,
144
+ description: message,
145
+ });
146
+ events.onFindingCreated({
147
+ type: "error",
148
+ title: `[${expertise.name}] expertise execution failed`,
149
+ });
150
+ events.onTestRunCompleted({
151
+ testRunId: testRun.id,
152
+ passed: false,
153
+ });
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=expertise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expertise.js","sourceRoot":"","sources":["../../src/orchestrator/expertise.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAQxE,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,UAAU,CAAC,CAgLrB"}
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA6CxE,wBAAsB,OAAO,CAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,YAAY,EAAE,gBAAgB,GAC7B,OAAO,CAAC,UAAU,CAAC,CA2LrB"}
@@ -1,14 +1,38 @@
1
+ import { discoverPublicPages } from "./discovery";
1
2
  import { processDecompositionJob } from "./decomposition";
2
3
  import { executeTestCases } from "./test-execution";
3
- import { computeHashes } from "../browser/page-utils";
4
- import { extractActionableItems } from "../extractors";
4
+ import { captureCurrentPage, resetCapturedPagePaths } from "./page-capture";
5
5
  const LOG = (...args) => console.warn("[orchestrator]", ...args);
6
+ function buildAiSummary(pagesFound, pageStatesFound, testRunsCompleted, findingsFound, expertiseSummary) {
7
+ const expertiseLines = Object.entries(expertiseSummary)
8
+ .sort(([left], [right]) => left.localeCompare(right))
9
+ .map(([name, counts]) => {
10
+ const parts = [];
11
+ if (counts.errors > 0)
12
+ parts.push(`${counts.errors} error${counts.errors === 1 ? "" : "s"}`);
13
+ if (counts.warnings > 0) {
14
+ parts.push(`${counts.warnings} warning${counts.warnings === 1 ? "" : "s"}`);
15
+ }
16
+ return parts.length > 0
17
+ ? `${name}: ${parts.join(", ")}`
18
+ : `${name}: no findings`;
19
+ });
20
+ const headline = findingsFound === 0
21
+ ? `Scan completed with no findings across ${pagesFound} page${pagesFound === 1 ? "" : "s"}.`
22
+ : `Scan completed with ${findingsFound} finding${findingsFound === 1 ? "" : "s"} across ${pagesFound} page${pagesFound === 1 ? "" : "s"}.`;
23
+ const detail = `Captured ${pageStatesFound} page state${pageStatesFound === 1 ? "" : "s"} and completed ${testRunsCompleted} test run${testRunsCompleted === 1 ? "" : "s"}.`;
24
+ if (expertiseLines.length === 0) {
25
+ return `${headline} ${detail}`;
26
+ }
27
+ return `${headline} ${detail} Findings by expertise: ${expertiseLines.join("; ")}.`;
28
+ }
6
29
  export async function runScan(adapter, config, api, eventHandler) {
7
30
  const startTime = Date.now();
8
31
  let pagesFound = 0;
9
32
  let pageStatesFound = 0;
10
33
  let testRunsCompleted = 0;
11
34
  let findingsFound = 0;
35
+ const expertiseSummary = {};
12
36
  const wrappedHandler = {
13
37
  ...eventHandler,
14
38
  onPageFound(page) {
@@ -28,6 +52,21 @@ export async function runScan(adapter, config, api, eventHandler) {
28
52
  },
29
53
  onFindingCreated(finding) {
30
54
  findingsFound++;
55
+ const match = /^\[([^\]]+)\]/.exec(finding.title);
56
+ if (match?.[1]) {
57
+ const expertiseName = match[1];
58
+ const counts = expertiseSummary[expertiseName] ?? {
59
+ warnings: 0,
60
+ errors: 0,
61
+ };
62
+ if (finding.type === "error") {
63
+ counts.errors += 1;
64
+ }
65
+ else if (finding.type === "warning") {
66
+ counts.warnings += 1;
67
+ }
68
+ expertiseSummary[expertiseName] = counts;
69
+ }
31
70
  eventHandler.onFindingCreated(finding);
32
71
  emitStats();
33
72
  },
@@ -41,42 +80,23 @@ export async function runScan(adapter, config, api, eventHandler) {
41
80
  });
42
81
  }
43
82
  try {
44
- // 1. Navigate to scan URL, capture initial page state
45
- LOG(`Step 1: Navigating to ${config.scanUrl}`);
83
+ resetCapturedPagePaths();
84
+ // 1. Crawl the site from the scan URL to inventory public pages
85
+ LOG(`Step 1: Discovering pages from ${config.scanUrl}`);
86
+ await discoverPublicPages(adapter, config, api, wrappedHandler);
87
+ // 2. Navigate back to scan URL and capture initial page state
88
+ LOG(`Step 2: Navigating to ${config.scanUrl}`);
46
89
  await adapter.goto(config.scanUrl, { waitUntil: "networkidle0" });
47
- const initialHtml = await adapter.content();
48
- LOG(`Page HTML length: ${initialHtml.length}`);
49
- // Compute relative path from scanUrl and baseUrl
50
- const scanUrlObj = new URL(config.scanUrl);
51
- const relativePath = scanUrlObj.pathname;
52
- const page = await api.findOrCreatePage(config.runnerId, relativePath);
53
- LOG(`Page created/found: id=${page.id}, path=${relativePath}`);
54
- wrappedHandler.onPageFound({ relativePath, pageId: page.id });
55
- // Extract actionable items and compute hashes
56
- const items = await extractActionableItems(adapter);
57
- LOG(`Extracted ${items.length} actionable items from page`);
58
- const hashes = await computeHashes(initialHtml, items);
59
- LOG(`Computed hashes:`, hashes);
60
- const initialPageState = await api.createPageState({
61
- pageId: page.id,
62
- sizeClass: config.sizeClass,
63
- hashes,
64
- screenshotPath: undefined,
65
- contentText: initialHtml.slice(0, 5000),
66
- });
67
- LOG(`Created page state: id=${initialPageState.id}`);
68
- wrappedHandler.onPageStateCreated({
69
- pageStateId: initialPageState.id,
70
- pageId: page.id,
71
- });
72
- // 2. Create initial AI Decomposition Job
73
- const initialJob = await api.createDecompositionJob(config.scanId, initialPageState.id);
74
- LOG(`Created decomposition job: id=${initialJob.id}`);
75
- wrappedHandler.onDecompositionJobCreated({
76
- jobId: initialJob.id,
77
- pageStateId: initialPageState.id,
90
+ const initialCapture = await captureCurrentPage(adapter, config, api, wrappedHandler, {
91
+ testRunId: config.scanId,
92
+ markDiscovered: false,
93
+ createDecompositionJob: true,
78
94
  });
79
- // 3. Generate/Run loop
95
+ if (!initialCapture?.pageStateId) {
96
+ throw new Error("Failed to capture initial page state");
97
+ }
98
+ LOG(`Captured initial page state ${initialCapture.pageStateId} for ${initialCapture.relativePath}`);
99
+ // 4. Generate/Run loop
80
100
  let iteration = 0;
81
101
  const MAX_ITERATIONS = 50;
82
102
  while (iteration < MAX_ITERATIONS) {
@@ -113,10 +133,12 @@ export async function runScan(adapter, config, api, eventHandler) {
113
133
  }
114
134
  LOG("New pages discovered — continuing to next iteration");
115
135
  }
116
- // 4. Complete test run
136
+ // 5. Complete test run
117
137
  const durationMs = Date.now() - startTime;
138
+ const aiSummary = buildAiSummary(pagesFound, pageStatesFound, testRunsCompleted, findingsFound, expertiseSummary);
118
139
  await api.completeTestRun(config.scanId, {
119
140
  status: "completed",
141
+ aiSummary,
120
142
  totalDurationMs: durationMs,
121
143
  pagesFound,
122
144
  pageStatesFound,
@@ -129,11 +151,15 @@ export async function runScan(adapter, config, api, eventHandler) {
129
151
  testRunsCompleted,
130
152
  findingsFound,
131
153
  durationMs,
154
+ aiSummary,
155
+ expertiseSummary,
132
156
  };
133
157
  wrappedHandler.onScanComplete({
134
158
  totalPages: pagesFound,
135
159
  totalFindings: findingsFound,
136
160
  durationMs,
161
+ aiSummary,
162
+ expertiseSummary,
137
163
  });
138
164
  return result;
139
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { BrowserAdapter } from "../adapter";
2
+ import type { ApiClient } from "../api/client";
3
+ import type { ScanConfig, ScanEventHandler } from "./types";
4
+ export interface CapturePageOptions {
5
+ testRunId?: number;
6
+ markDiscovered?: boolean;
7
+ captureState?: boolean;
8
+ createDecompositionJob?: boolean;
9
+ }
10
+ export interface CapturePageResult {
11
+ pageId: number;
12
+ relativePath: string;
13
+ pageStateId?: number;
14
+ decompositionJobId?: number;
15
+ createdNewState: boolean;
16
+ matchedExistingState: boolean;
17
+ }
18
+ export declare function resetCapturedPagePaths(): void;
19
+ export declare function seedCapturedPagePath(relativePath: string): void;
20
+ export declare function hasCapturedPagePath(relativePath: string): boolean;
21
+ export declare function captureCurrentPage(adapter: BrowserAdapter, config: ScanConfig, api: ApiClient, events: ScanEventHandler, options?: CapturePageOptions): Promise<CapturePageResult | null>;
22
+ //# sourceMappingURL=page-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-capture.d.ts","sourceRoot":"","sources":["../../src/orchestrator/page-capture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM5D,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAID,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAgHnC"}
@@ -0,0 +1,102 @@
1
+ import { computeHashes } from "../browser/page-utils";
2
+ import { toRelativePath } from "../crawler/url-normalizer";
3
+ import { extractActionableItems } from "../extractors";
4
+ import { executePageExpertises } from "./expertise";
5
+ const capturedPagePaths = new Set();
6
+ export function resetCapturedPagePaths() {
7
+ capturedPagePaths.clear();
8
+ }
9
+ export function seedCapturedPagePath(relativePath) {
10
+ capturedPagePaths.add(relativePath);
11
+ }
12
+ export function hasCapturedPagePath(relativePath) {
13
+ return capturedPagePaths.has(relativePath);
14
+ }
15
+ export async function captureCurrentPage(adapter, config, api, events, options = {}) {
16
+ const currentUrl = await adapter.getUrl();
17
+ const current = new URL(currentUrl);
18
+ const base = new URL(config.baseUrl);
19
+ if (current.origin !== base.origin) {
20
+ return null;
21
+ }
22
+ const relativePath = toRelativePath(currentUrl);
23
+ const page = await api.findOrCreatePage(config.runnerId, relativePath);
24
+ if (options.markDiscovered) {
25
+ events.onPageFound({ relativePath, pageId: page.id });
26
+ if (config.testEnvironmentId) {
27
+ await api.createDiscoveredPages({
28
+ testEnvironmentId: config.testEnvironmentId,
29
+ pages: [{ relativePath, isPublic: true }],
30
+ });
31
+ }
32
+ if (config.testEnvironmentId && options.testRunId) {
33
+ await api.createPageVisit({
34
+ testRunId: options.testRunId,
35
+ testEnvironmentId: config.testEnvironmentId,
36
+ relativePath,
37
+ status: "visited",
38
+ });
39
+ }
40
+ }
41
+ if (hasCapturedPagePath(relativePath)) {
42
+ return {
43
+ pageId: page.id,
44
+ relativePath,
45
+ createdNewState: false,
46
+ matchedExistingState: false,
47
+ };
48
+ }
49
+ if (options.captureState === false) {
50
+ return {
51
+ pageId: page.id,
52
+ relativePath,
53
+ createdNewState: false,
54
+ matchedExistingState: false,
55
+ };
56
+ }
57
+ const html = await adapter.content();
58
+ const items = await extractActionableItems(adapter);
59
+ const hashes = await computeHashes(html, items);
60
+ const existingState = await api.findMatchingPageState(page.id, hashes, config.sizeClass);
61
+ if (existingState) {
62
+ seedCapturedPagePath(relativePath);
63
+ return {
64
+ pageId: page.id,
65
+ relativePath,
66
+ pageStateId: existingState.id,
67
+ createdNewState: false,
68
+ matchedExistingState: true,
69
+ };
70
+ }
71
+ const pageState = await api.createPageState({
72
+ pageId: page.id,
73
+ sizeClass: config.sizeClass,
74
+ hashes,
75
+ contentText: html.slice(0, 5000),
76
+ createdByTestRunId: options.testRunId,
77
+ });
78
+ seedCapturedPagePath(relativePath);
79
+ events.onPageStateCreated({
80
+ pageStateId: pageState.id,
81
+ pageId: page.id,
82
+ });
83
+ await executePageExpertises(adapter, config, api, events, pageState.id, page.id, relativePath);
84
+ let decompositionJobId;
85
+ if (options.createDecompositionJob) {
86
+ const job = await api.createDecompositionJob(config.scanId, pageState.id);
87
+ decompositionJobId = job.id;
88
+ events.onDecompositionJobCreated({
89
+ jobId: job.id,
90
+ pageStateId: pageState.id,
91
+ });
92
+ }
93
+ return {
94
+ pageId: page.id,
95
+ relativePath,
96
+ pageStateId: pageState.id,
97
+ decompositionJobId,
98
+ createdNewState: true,
99
+ matchedExistingState: false,
100
+ };
101
+ }
102
+ //# sourceMappingURL=page-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-capture.js","sourceRoot":"","sources":["../../src/orchestrator/page-capture.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"test-execution.d.ts","sourceRoot":"","sources":["../../src/orchestrator/test-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAkJ5D,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CA2NlB"}
1
+ {"version":3,"file":"test-execution.d.ts","sourceRoot":"","sources":["../../src/orchestrator/test-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAiI5D,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,gBAAgB,EACxB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,OAAO,CAAC,CA0NlB"}