@ia-qa/qa-discovery 0.1.0

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 (84) hide show
  1. package/README.md +378 -0
  2. package/ROADMAP.md +321 -0
  3. package/dist/ai/classify.d.ts +170 -0
  4. package/dist/ai/classify.js +431 -0
  5. package/dist/ai/classify.js.map +1 -0
  6. package/dist/browser/extractPage.d.ts +41 -0
  7. package/dist/browser/extractPage.js +427 -0
  8. package/dist/browser/extractPage.js.map +1 -0
  9. package/dist/browser/openables.d.ts +19 -0
  10. package/dist/browser/openables.js +127 -0
  11. package/dist/browser/openables.js.map +1 -0
  12. package/dist/capture/page.d.ts +128 -0
  13. package/dist/capture/page.js +78 -0
  14. package/dist/capture/page.js.map +1 -0
  15. package/dist/citations.d.ts +80 -0
  16. package/dist/citations.js +197 -0
  17. package/dist/citations.js.map +1 -0
  18. package/dist/classificationView.d.ts +118 -0
  19. package/dist/classificationView.js +178 -0
  20. package/dist/classificationView.js.map +1 -0
  21. package/dist/cli/args.d.ts +3 -0
  22. package/dist/cli/args.js +38 -0
  23. package/dist/cli/args.js.map +1 -0
  24. package/dist/cli/history.d.ts +1 -0
  25. package/dist/cli/history.js +35 -0
  26. package/dist/cli/history.js.map +1 -0
  27. package/dist/cli/index.d.ts +5 -0
  28. package/dist/cli/index.js +172 -0
  29. package/dist/cli/index.js.map +1 -0
  30. package/dist/cli/login.d.ts +29 -0
  31. package/dist/cli/login.js +179 -0
  32. package/dist/cli/login.js.map +1 -0
  33. package/dist/cli/scan.d.ts +11 -0
  34. package/dist/cli/scan.js +246 -0
  35. package/dist/cli/scan.js.map +1 -0
  36. package/dist/cli-ai/index.d.ts +7 -0
  37. package/dist/cli-ai/index.js +360 -0
  38. package/dist/cli-ai/index.js.map +1 -0
  39. package/dist/config.d.ts +112 -0
  40. package/dist/config.js +178 -0
  41. package/dist/config.js.map +1 -0
  42. package/dist/diff.d.ts +12 -0
  43. package/dist/diff.js +43 -0
  44. package/dist/diff.js.map +1 -0
  45. package/dist/explore.d.ts +59 -0
  46. package/dist/explore.js +119 -0
  47. package/dist/explore.js.map +1 -0
  48. package/dist/healingLink.d.ts +30 -0
  49. package/dist/healingLink.js +127 -0
  50. package/dist/healingLink.js.map +1 -0
  51. package/dist/history.d.ts +38 -0
  52. package/dist/history.js +120 -0
  53. package/dist/history.js.map +1 -0
  54. package/dist/htmlReport.d.ts +2 -0
  55. package/dist/htmlReport.js +371 -0
  56. package/dist/htmlReport.js.map +1 -0
  57. package/dist/index.d.ts +24 -0
  58. package/dist/index.js +65 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/mcp/sandbox.d.ts +9 -0
  61. package/dist/mcp/sandbox.js +82 -0
  62. package/dist/mcp/sandbox.js.map +1 -0
  63. package/dist/mcp/server.d.ts +120 -0
  64. package/dist/mcp/server.js +315 -0
  65. package/dist/mcp/server.js.map +1 -0
  66. package/dist/network.d.ts +60 -0
  67. package/dist/network.js +99 -0
  68. package/dist/network.js.map +1 -0
  69. package/dist/overview.d.ts +40 -0
  70. package/dist/overview.js +370 -0
  71. package/dist/overview.js.map +1 -0
  72. package/dist/overviewFile.d.ts +31 -0
  73. package/dist/overviewFile.js +101 -0
  74. package/dist/overviewFile.js.map +1 -0
  75. package/dist/scan.d.ts +159 -0
  76. package/dist/scan.js +402 -0
  77. package/dist/scan.js.map +1 -0
  78. package/dist/sharedCalls.d.ts +28 -0
  79. package/dist/sharedCalls.js +61 -0
  80. package/dist/sharedCalls.js.map +1 -0
  81. package/dist/taxonomy.d.ts +77 -0
  82. package/dist/taxonomy.js +153 -0
  83. package/dist/taxonomy.js.map +1 -0
  84. package/package.json +61 -0
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HISTORY_LIMIT = void 0;
37
+ exports.historyPath = historyPath;
38
+ exports.appendHistory = appendHistory;
39
+ exports.readHistory = readHistory;
40
+ exports.gitStamp = gitStamp;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const config_1 = require("./config");
44
+ /**
45
+ * Append-only run history โ€” `.ia-qa-discovery/history.jsonl`. Mirrors
46
+ * `@ia-qa/self-healing`'s `history.ts`: small, deterministic, safe to commit,
47
+ * never influences anything (F1 produces no verdict to influence), a write
48
+ * failure is swallowed (a full disk must not crash a `scan`).
49
+ */
50
+ exports.HISTORY_LIMIT = 500;
51
+ function historyPath(cwd = (0, config_1.baseDir)()) {
52
+ return path.join(cwd, config_1.CONFIG_DIR, config_1.HISTORY_FILENAME);
53
+ }
54
+ function appendHistory(entry) {
55
+ const file = historyPath();
56
+ const full = { ts: entry.ts ?? new Date().toISOString(), ...entry };
57
+ try {
58
+ fs.mkdirSync(path.dirname(file), { recursive: true });
59
+ fs.appendFileSync(file, JSON.stringify(full) + '\n', 'utf8');
60
+ truncate(file);
61
+ }
62
+ catch {
63
+ /* history is a courtesy, never a gate */
64
+ }
65
+ }
66
+ function truncate(file) {
67
+ try {
68
+ const lines = fs.readFileSync(file, 'utf8').split('\n').filter(Boolean);
69
+ if (lines.length <= exports.HISTORY_LIMIT + 100)
70
+ return;
71
+ fs.writeFileSync(file, lines.slice(-exports.HISTORY_LIMIT).join('\n') + '\n', 'utf8');
72
+ }
73
+ catch {
74
+ /* as above */
75
+ }
76
+ }
77
+ /** Read the history, oldest first. A malformed line is skipped, not fatal. */
78
+ function readHistory(limit = exports.HISTORY_LIMIT, cwd) {
79
+ const file = cwd ? path.join(cwd, config_1.CONFIG_DIR, config_1.HISTORY_FILENAME) : historyPath();
80
+ let raw;
81
+ try {
82
+ raw = fs.readFileSync(file, 'utf8');
83
+ }
84
+ catch {
85
+ return [];
86
+ }
87
+ const out = [];
88
+ for (const line of raw.split('\n')) {
89
+ if (!line.trim())
90
+ continue;
91
+ try {
92
+ const parsed = JSON.parse(line);
93
+ if (parsed && typeof parsed.ts === 'string' && parsed.verb === 'scan')
94
+ out.push(parsed);
95
+ }
96
+ catch {
97
+ /* skip */
98
+ }
99
+ }
100
+ return out.slice(-limit);
101
+ }
102
+ /**
103
+ * Best-effort git stamp โ€” never throws, never blocks. No git, no repo,
104
+ * detached HEAD: the entry is written without it.
105
+ */
106
+ function gitStamp() {
107
+ const { execFileSync } = require('child_process');
108
+ const run = (args) => {
109
+ try {
110
+ const out = execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 2000 });
111
+ const v = out.trim();
112
+ return v === '' ? undefined : v;
113
+ }
114
+ catch {
115
+ return undefined;
116
+ }
117
+ };
118
+ return { commit: run(['rev-parse', '--short', 'HEAD']), branch: run(['rev-parse', '--abbrev-ref', 'HEAD']) };
119
+ }
120
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { OverviewInput } from './overview';
2
+ export declare function renderScanReport(input: OverviewInput): string;
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderScanReport = renderScanReport;
4
+ const classificationView_1 = require("./classificationView");
5
+ /**
6
+ * A branded, self-contained HTML report for one discovery scan.
7
+ *
8
+ * Adapted from `@ia-qa/self-healing`'s report, NOT copied: that one is built
9
+ * around a verdict (PASS/FIX/BLOCK) and rows waiting on a human decision.
10
+ * Discovery produces no verdict โ€” it is reconnaissance โ€” so the shape here is
11
+ * an **app dossier**: what was reached, what was NOT reached (first, because a
12
+ * page count is not coverage), the entry points, the API surface, and the
13
+ * testability of what a suite would have to locate.
14
+ *
15
+ * Zero-dependency, pure string: no browser, no network, nothing leaves the
16
+ * machine. CSS and links are inline, so the file is shareable as-is.
17
+ */
18
+ const BRAND = {
19
+ home: 'https://www.ia-qa.com',
20
+ method: 'https://www.ia-qa.com/method',
21
+ tools: 'https://www.ia-qa.com/all-tools',
22
+ };
23
+ function esc(s) {
24
+ return String(s == null ? '' : s)
25
+ .replace(/&/g, '&amp;')
26
+ .replace(/</g, '&lt;')
27
+ .replace(/>/g, '&gt;')
28
+ .replace(/"/g, '&quot;')
29
+ .replace(/'/g, '&#039;');
30
+ }
31
+ function submitTarget(form) {
32
+ if (form.action === null && form.method === null)
33
+ return 'not stated โ€” JS-handled submit';
34
+ const method = form.method ? form.method.toUpperCase() : 'GET (default)';
35
+ const action = form.action ? `<code>${esc(form.action)}</code>` : 'the page itself';
36
+ return `${method} โ†’ ${action}`;
37
+ }
38
+ const REPORT_CSS = `
39
+ :root{--bg:#09090b;--surface:#18181b;--surface2:#111113;--border:#27272a;--text:#e4e4e7;--muted:#a1a1aa;
40
+ --orange:#f97316;--orange2:#fb923c;--pass:#10b981;--fail:#ef4444;--warn:#f59e0b;--info:#8b5cf6;}
41
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
42
+ body{background:var(--bg);color:var(--text);font-family:'Inter',system-ui,-apple-system,sans-serif;line-height:1.5;min-height:100vh;display:flex;flex-direction:column}
43
+ a{color:var(--orange2);text-decoration:none}a:hover{text-decoration:underline}
44
+ code{font-family:'JetBrains Mono','Fira Code',ui-monospace,monospace;font-size:12px}
45
+ .wrap{width:100%;max-width:980px;margin:0 auto;padding:0 20px}
46
+ header{background:linear-gradient(135deg,#7c2d12 0%,#ea580c 55%,#f97316 100%);padding:28px 0 26px;border-bottom:1px solid var(--border)}
47
+ .brand{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px}
48
+ .logo{display:inline-flex;align-items:center;gap:9px;font-weight:800;letter-spacing:.02em;font-size:19px;color:#fff}
49
+ .logo .mark{background:#fff;color:#ea580c;border-radius:8px;padding:3px 9px;font-size:15px;letter-spacing:.08em}
50
+ .logo:hover{text-decoration:none;opacity:.92}
51
+ .cta{background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.35);color:#fff;padding:8px 15px;border-radius:99px;font-size:13px;font-weight:600}
52
+ .cta:hover{background:rgba(255,255,255,.26);text-decoration:none}
53
+ .title{color:#fff;margin-top:20px}
54
+ .title h1{font-size:24px;font-weight:700}
55
+ .title .meta{color:rgba(255,255,255,.85);font-size:12.5px;margin-top:8px}
56
+ .title .meta code{color:#fff;background:rgba(0,0,0,.28);padding:1px 7px;border-radius:6px}
57
+ main{flex:1;padding:28px 0 40px}
58
+ section{background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:20px;margin-bottom:18px}
59
+ section>h2{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin-bottom:14px;font-weight:700}
60
+ .hero{border-left:3px solid var(--orange);display:flex;flex-direction:column;gap:14px}
61
+ .lede{color:var(--muted);font-size:13.5px;line-height:1.6;max-width:78ch}
62
+ .lede code{background:var(--surface2);border:1px solid var(--border);border-radius:6px;padding:1px 6px;color:var(--orange2)}
63
+ .stats{display:flex;flex-wrap:wrap;gap:10px}
64
+ .stat{background:var(--surface2);border:1px solid var(--border);border-radius:10px;padding:10px 14px;min-width:112px}
65
+ .stat .n{font-size:21px;font-weight:700;line-height:1.2}
66
+ .stat .l{font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);margin-top:3px;font-weight:600}
67
+ .callout{background:var(--surface2);border:1px solid var(--border);border-left:3px solid var(--warn);border-radius:10px;padding:14px 16px;font-size:13.5px;line-height:1.65;max-width:82ch}
68
+ .callout.bad{border-left-color:var(--fail)}
69
+ .callout .cl-label{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--warn);font-weight:700;margin-bottom:6px}
70
+ .callout.bad .cl-label{color:var(--fail)}
71
+ .callout code{background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:1px 6px;color:var(--orange2)}
72
+ .ok-note{color:var(--pass);font-size:13px}
73
+ table{width:100%;border-collapse:collapse;font-size:13px}
74
+ th{text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);font-weight:700;padding:7px 10px;border-bottom:1px solid var(--border)}
75
+ td{padding:8px 10px;border-bottom:1px solid var(--surface2);vertical-align:top}
76
+ tr:last-child td{border-bottom:none}
77
+ .scroll{overflow-x:auto}
78
+ .pill{display:inline-block;padding:1px 8px;border-radius:99px;font-size:11px;font-weight:700;border:1px solid}
79
+ .pill.pass{color:var(--pass);border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.1)}
80
+ .pill.warn{color:var(--warn);border-color:rgba(245,158,11,.4);background:rgba(245,158,11,.1)}
81
+ .pill.fail{color:var(--fail);border-color:rgba(239,68,68,.4);background:rgba(239,68,68,.1)}
82
+ .pill.info{color:var(--info);border-color:rgba(139,92,246,.4);background:rgba(139,92,246,.1)}
83
+ .muted{color:var(--muted)}
84
+ .form-card{background:var(--surface2);border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin-bottom:12px}
85
+ .form-card h3{font-size:14px;font-weight:700;margin-bottom:6px}
86
+ .form-card .fmeta{font-size:12.5px;color:var(--muted);margin-bottom:10px}
87
+ .note{font-size:12.5px;color:var(--muted);line-height:1.6;margin-top:10px;max-width:82ch}
88
+ footer{border-top:1px solid var(--border);padding:18px 0 26px;color:var(--muted);font-size:12px}
89
+ footer a{color:var(--orange2)}
90
+ `;
91
+ function renderScanReport(input) {
92
+ const { manifest, pages, shared, loginWall, session, hrefBlind, droppedByCap, sitemapDeclared, classification } = input;
93
+ const formCount = pages.reduce((n, p) => n + p.forms.length, 0);
94
+ const fields = pages.flatMap((p) => [...p.forms.flatMap((f) => f.fields), ...p.looseFields]);
95
+ const unstable = fields.filter((f) => !f.stableSelector);
96
+ const pageCalls = pages.reduce((n, p) => n + p.apiCalls.length, 0);
97
+ const parts = [];
98
+ parts.push(`<!doctype html><html lang="en"><head><meta charset="utf-8">
99
+ <meta name="viewport" content="width=device-width,initial-scale=1">
100
+ <title>Discovery โ€” ${esc(manifest.baseUrl)}</title>
101
+ <style>${REPORT_CSS}</style></head><body>`);
102
+ parts.push(`<header><div class="wrap">
103
+ <div class="brand">
104
+ <a class="logo" href="${BRAND.home}"><span class="mark">IA-QA</span> qa-discovery</a>
105
+ <a class="cta" href="${BRAND.method}">Testing methods โ†’</a>
106
+ </div>
107
+ <div class="title">
108
+ <h1>App surface โ€” ${esc(manifest.baseUrl)}</h1>
109
+ <div class="meta">Captured <code>${esc(manifest.capturedAt)}</code>${session ? ' ยท with a saved session' : ' ยท anonymous'}</div>
110
+ </div>
111
+ </div></header><main><div class="wrap">`);
112
+ // โ”€โ”€ Hero: what this is, and the coverage caveat FIRST โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
113
+ parts.push(`<section class="hero">
114
+ <div class="lede">This is <strong>reconnaissance, not a test plan and not a verdict</strong>. Every figure below traces to
115
+ something observed in the DOM or on the network by a local headless browser โ€” nothing was inferred, and nothing
116
+ left this machine. Regenerate with <code>ia-qa-discover scan</code>.</div>
117
+ <div class="stats">
118
+ <div class="stat"><div class="n">${manifest.pagesCaptured}</div><div class="l">Pages captured</div></div>
119
+ <div class="stat"><div class="n">${formCount}</div><div class="l">Forms</div></div>
120
+ <div class="stat"><div class="n">${fields.length}</div><div class="l">Input fields</div></div>
121
+ <div class="stat"><div class="n">${pageCalls + shared.calls.length}</div><div class="l">API calls</div></div>
122
+ <div class="stat"><div class="n">${manifest.origins.length}</div><div class="l">Origins called</div></div>
123
+ </div>`);
124
+ const openable = pages.reduce((n, p) => n + (p.exploration?.openable ?? 0), 0);
125
+ const explored = pages.some((p) => p.exploration?.explored);
126
+ const revealedTotal = pages.reduce((n, p) => n + (p.exploration?.revealed ?? 0), 0);
127
+ const collidedTotal = pages.reduce((n, p) => n + (p.exploration?.collided ?? 0), 0);
128
+ if (!explored && openable > 0) {
129
+ parts.push(`<div class="callout"><span class="cl-label">Coverage โ€” the loaded state only</span>
130
+ These pages carry <strong>${openable} control(s) that can reveal more</strong> โ€” menus, tabs, accordions, a button that
131
+ opens a dialog. Only what the page shows on load was captured, so the ${fields.length} field(s) counted above are the
132
+ input surface <em>at rest</em>, not the whole one. On one measured app a single page had 64 such controls and 2
133
+ visible fields.<br>
134
+ Run <code>ia-qa-discover scan --deep</code> to open them and capture what they reveal.</div>`);
135
+ }
136
+ else if (explored) {
137
+ parts.push(`<div class="ok-note">๐Ÿ” <code>--deep</code> opened ${openable} control(s) and found <strong>${revealedTotal}
138
+ field(s) not visible at load</strong>${collidedTotal > 0 ? ` ยท โš  ${collidedTotal} reached but not captured (their selector already named another element in a different state)` : ''}.</div>`);
139
+ }
140
+ if (droppedByCap && droppedByCap > 0) {
141
+ parts.push(`<div class="callout"><span class="cl-label">Coverage โ€” the page cap was reached</span>
142
+ <strong>${droppedByCap} more page(s) were known and not visited</strong>, because <code>--max</code> stopped the run at
143
+ ${manifest.pagesCaptured}.${sitemapDeclared ? ` The sitemap alone declared ${sitemapDeclared}.` : ''}
144
+ The count above is a budget, not a census โ€” raise <code>--max</code> to cover more.</div>`);
145
+ }
146
+ if (hrefBlind) {
147
+ parts.push(`<div class="callout bad"><span class="cl-label">Coverage โ€” discovery could not see past the entry URL</span>
148
+ <strong>No internal links were found.</strong> Discovery follows <code>&lt;a href&gt;</code>; an app that navigates
149
+ programmatically โ€” React Router's <code>useNavigate()</code>, a button with an onClick handler โ€” exposes no href for a
150
+ crawl to follow. So โ€œ${manifest.pagesCaptured} of ${manifest.pagesFound} foundโ€ above describes <strong>one page</strong>,
151
+ not the application: the denominator is what the crawl could reach, not what exists.<br>
152
+ Declare the routes you know in <code>.ia-qa-discovery/config.json</code> โ†’ <code>"pages"</code>, then scan again.</div>`);
153
+ }
154
+ else if (loginWall.length > 1) {
155
+ parts.push(`<div class="callout bad"><span class="cl-label">Coverage โ€” you are probably looking at the login wall</span>
156
+ ${loginWall.length} of ${manifest.pagesCaptured} captured pages still show a login form
157
+ (${loginWall.map((p) => `<code>${esc(p)}</code>`).join(', ')}). An app whose catch-all route renders the login page
158
+ answers HTTP&nbsp;200 at <em>every</em> URL, so the page count above looks like success while the same wall was
159
+ captured several times. <strong>A page count is not coverage.</strong><br>
160
+ ${session
161
+ ? 'The saved session did not get past it โ€” it may have expired. Re-run <code>ia-qa-discover login</code>.'
162
+ : 'Run <code>ia-qa-discover login</code> to log in by hand once, then scan again.'}</div>`);
163
+ }
164
+ else if (loginWall.length === 1 && !session) {
165
+ parts.push(`<div class="callout"><span class="cl-label">Coverage โ€” public surface only</span>
166
+ This app has a login (<code>${esc(loginWall[0])}</code>) and no session was used, so whatever is behind it was
167
+ never reached. What follows describes the <strong>public surface</strong>.<br>
168
+ Run <code>ia-qa-discover login</code> to log in by hand once, then scan again.</div>`);
169
+ }
170
+ else if (session) {
171
+ parts.push(`<div class="ok-note">๐Ÿ”“ Scanned with a saved session โ€” authenticated pages were reachable.</div>`);
172
+ }
173
+ if (manifest.pagesFailed > 0) {
174
+ parts.push(`<div class="callout"><span class="cl-label">Incomplete</span>
175
+ ${manifest.pagesFailed} page(s) could not be captured, so this describes ${manifest.pagesCaptured} of
176
+ ${manifest.pagesFound} pages found.</div>`);
177
+ }
178
+ parts.push(`</section>`);
179
+ // โ”€โ”€ Pages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
180
+ parts.push(`<section><h2>Pages (${pages.length})</h2><div class="scroll"><table>
181
+ <thead><tr><th>Page</th><th>Path</th><th>Title</th><th>Headings</th><th>Forms</th><th>Fields</th><th>API calls</th></tr></thead><tbody>`);
182
+ for (const p of pages) {
183
+ let pathname = p.url;
184
+ try {
185
+ pathname = new URL(p.url).pathname;
186
+ }
187
+ catch { /* keep raw */ }
188
+ const formed = p.forms.reduce((n, f) => n + f.fields.length, 0);
189
+ const fieldCell = formed + p.looseFields.length + (p.looseFields.length > 0 ? ` <span class="muted">(${p.looseFields.length} loose)</span>` : '');
190
+ parts.push(`<tr><td><strong>${esc(p.page)}</strong></td><td><code>${esc(pathname)}</code></td>
191
+ <td>${esc(p.meta.title || 'โ€”')}</td><td>${p.headings.length}</td><td>${p.forms.length}</td><td>${fieldCell}</td><td>${p.apiCalls.length}</td></tr>`);
192
+ }
193
+ parts.push(`</tbody></table></div>`);
194
+ const distinctTitles = new Set(pages.map((p) => p.meta.title).filter(Boolean));
195
+ if (pages.length > 2 && distinctTitles.size === 1) {
196
+ parts.push(`<div class="callout"><span class="cl-label">All ${pages.length} pages share one title</span>
197
+ Every captured page reports <code>${esc([...distinctTitles][0])}</code>. The browser tab, the history entry and a
198
+ screen reader announcing a route change cannot tell these pages apart.</div>`);
199
+ }
200
+ parts.push(`</section>`);
201
+ // โ”€โ”€ Forms โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
202
+ if (formCount > 0) {
203
+ parts.push(`<section><h2>Entry points โ€” forms (${formCount})</h2>
204
+ <div class="note">Where this app takes input: where a suite starts, and where validation, auth and payment
205
+ behaviour live. <strong>Locatable</strong> says whether a test could target the field reliably โ€” it is a fact
206
+ about the app, not about this scan.</div>`);
207
+ for (const p of pages) {
208
+ for (const form of p.forms) {
209
+ const required = form.fields.filter((f) => f.required).length;
210
+ parts.push(`<div class="form-card">
211
+ <h3>${esc(p.page)} <span class="muted">โ€” ${form.fields.length} field${form.fields.length === 1 ? '' : 's'}${required > 0 ? `, ${required} required` : ''}</span></h3>
212
+ <div class="fmeta">Selector <code>${esc(form.selector)}</code> ยท Submits to ${submitTarget(form)} ยท
213
+ Submit control ${form.hasSubmit ? 'present' : '<strong>absent</strong>'}</div>`);
214
+ if (form.fields.length > 0) {
215
+ parts.push(`<div class="scroll"><table><thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Selector</th><th>Locatable</th></tr></thead><tbody>`);
216
+ for (const f of form.fields) {
217
+ const pill = f.ambiguousSelector
218
+ ? '<span class="pill fail">ambiguous</span>'
219
+ : f.stableSelector
220
+ ? '<span class="pill pass">stable</span>'
221
+ : '<span class="pill warn">positional</span>';
222
+ parts.push(`<tr><td>${esc(f.name || '(unnamed)')}</td><td>${esc(f.type)}</td>
223
+ <td>${f.required ? 'yes' : 'no'}</td><td><code>${esc(f.selector)}</code></td><td>${pill}</td></tr>`);
224
+ }
225
+ parts.push(`</tbody></table></div>`);
226
+ }
227
+ parts.push(`</div>`);
228
+ }
229
+ }
230
+ parts.push(`</section>`);
231
+ }
232
+ // โ”€โ”€ Loose fields โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
233
+ const looseTotal = pages.reduce((n, p) => n + p.looseFields.length, 0);
234
+ if (looseTotal > 0) {
235
+ parts.push(`<section><h2>Input fields outside a form (${looseTotal})</h2>
236
+ <div class="note">Inputs this app takes <strong>without</strong> a <code>&lt;form&gt;</code> wrapper โ€” submission is handled
237
+ in JS. They are entry points all the same, and for most React/Vue apps they are the <em>only</em> ones.</div>`);
238
+ for (const p of pages) {
239
+ if (p.looseFields.length === 0)
240
+ continue;
241
+ parts.push(`<div class="form-card">
242
+ <h3>${esc(p.page)} <span class="muted">โ€” ${p.looseFields.length} field${p.looseFields.length === 1 ? '' : 's'}</span></h3>
243
+ <div class="scroll"><table><thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Where / how to reach</th><th>Selector</th><th>Locatable</th></tr></thead><tbody>`);
244
+ for (const f of p.looseFields) {
245
+ const pill = f.ambiguousSelector
246
+ ? '<span class="pill fail">ambiguous</span>'
247
+ : f.stableSelector
248
+ ? '<span class="pill pass">stable</span>'
249
+ : '<span class="pill warn">positional</span>';
250
+ parts.push(`<tr><td>${esc(f.name || '(unnamed)')}</td><td>${esc(f.type)}</td><td>${f.required ? 'yes' : 'no'}</td>
251
+ <td>${f.via?.length ? `๐Ÿ” click ${f.via.map((v) => `โ€œ${esc(v)}โ€`).join(' โ€บ ')}` : esc(f.context || 'โ€”')}</td><td><code>${esc(f.selector)}</code></td><td>${pill}</td></tr>`);
252
+ }
253
+ parts.push(`</tbody></table></div></div>`);
254
+ }
255
+ parts.push(`</section>`);
256
+ }
257
+ // โ”€โ”€ API surface โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
258
+ parts.push(`<section><h2>API surface</h2>`);
259
+ if (manifest.origins.length === 0) {
260
+ parts.push(`<div class="note">No XHR/fetch traffic was observed โ€” either the app makes none, or this scan ran with <code>--no-network</code>.</div>`);
261
+ }
262
+ else {
263
+ parts.push(`<div class="scroll"><table><thead><tr><th>Origin</th><th>Calls</th><th>Pages</th><th>Same-origin as the app</th></tr></thead><tbody>`);
264
+ for (const o of manifest.origins) {
265
+ parts.push(`<tr><td><code>${esc(o.origin)}</code></td><td>${o.calls}</td><td>${o.pages}</td>
266
+ <td>${o.sameOrigin ? '<span class="pill pass">yes</span>' : '<span class="pill info">no</span>'}</td></tr>`);
267
+ }
268
+ parts.push(`</tbody></table></div>
269
+ <div class="note"><strong>โ€œSame-origin: noโ€ is not the same as third-party.</strong> An app whose API lives on its
270
+ own separate host (an <code>api.*</code> subdomain, a platform backend) has every one of its <em>own</em> calls listed
271
+ here as cross-origin, right next to any analytics or ad host. Deciding which of these are first-party is a judgment
272
+ this stage does not make โ€” nothing in the DOM states it.</div>`);
273
+ }
274
+ if (shared.calls.length > 0) {
275
+ const minPages = Math.max(2, Math.ceil(shared.threshold * shared.sourcePages));
276
+ parts.push(`<h2 style="margin-top:22px">Shared calls โ€” on โ‰ฅ ${minPages} of ${shared.sourcePages} pages</h2>
277
+ <div class="note">Cross-cutting traffic: session refresh, telemetry, feature flags. Promoted out of the per-page
278
+ captures so one analytics beacon does not read as N page-specific calls.</div>
279
+ <div class="scroll"><table><thead><tr><th>Method</th><th>URL</th><th>Status</th><th>Pages</th></tr></thead><tbody>`);
280
+ for (const c of shared.calls) {
281
+ parts.push(`<tr><td>${esc(c.method)}</td><td><code>${esc(c.urlPattern)}</code></td><td>${c.status}</td><td>${c.count}</td></tr>`);
282
+ }
283
+ parts.push(`</tbody></table></div>`);
284
+ }
285
+ const perPage = pages.filter((p) => p.apiCalls.length > 0);
286
+ if (perPage.length > 0) {
287
+ parts.push(`<h2 style="margin-top:22px">Page-specific calls</h2><div class="scroll"><table>
288
+ <thead><tr><th>Page</th><th>Method</th><th>URL</th><th>Status</th></tr></thead><tbody>`);
289
+ for (const p of perPage) {
290
+ for (const c of p.apiCalls) {
291
+ parts.push(`<tr><td>${esc(p.page)}</td><td>${esc(c.method)}</td><td><code>${esc(c.urlPattern)}</code></td><td>${c.status}</td></tr>`);
292
+ }
293
+ }
294
+ parts.push(`</tbody></table></div>`);
295
+ }
296
+ parts.push(`</section>`);
297
+ // โ”€โ”€ Model-classified entry points โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
298
+ // Its own section, its own label, its own ink. Everything above is a literal
299
+ // observation; this is a reading of one, and a shared table would lend it a
300
+ // credibility it has not earned.
301
+ if (classification) {
302
+ const c = classification;
303
+ parts.push(`<section><h2>๐Ÿค– What these entry points are FOR <span class="pill info">model-classified</span></h2>
304
+ <div class="meta">${esc((0, classificationView_1.classificationHeadline)(c))} ยท <code>${esc(c.model)}</code> ยท <code>${esc(c.taxonomyVersion)}</code> ยท classified <code>${esc(c.classifiedAt)}</code></div>
305
+ <div class="note">${esc(classificationView_1.CLASSIFICATION_CAVEAT)}</div>`);
306
+ if (c.staleCount > 0) {
307
+ parts.push(`<div class="callout"><span class="cl-label">${c.staleCount} page${c.staleCount === 1 ? '' : 's'} below ${c.staleCount === 1 ? 'is' : 'are'} stale</span>${esc(classificationView_1.STALE_CAVEAT)}</div>`);
308
+ }
309
+ for (const p of c.pages) {
310
+ if (p.failed) {
311
+ parts.push(`<h3 style="margin-top:22px"><code>${esc(p.page)}</code> <span class="pill warn">not classified</span></h3>
312
+ <div class="note">The model call did not succeed: ${esc(p.failed)} Nothing is wrong with this page.</div>`);
313
+ continue;
314
+ }
315
+ if (p.kept.length === 0 && p.refused.length === 0)
316
+ continue;
317
+ parts.push(`<h3 style="margin-top:22px"><code>${esc(p.page)}</code>${p.stale ? ' <span class="pill warn">stale</span>' : ''}</h3>
318
+ <div class="scroll"><table><thead><tr><th>Entry point</th><th>Intent</th><th>Handles</th><th>Confidence</th><th>Why</th></tr></thead><tbody>`);
319
+ for (const k of p.kept) {
320
+ parts.push(`<tr><td><code>${esc(k.entryPoint.split('#')[1] ?? k.entryPoint)}</code></td><td><strong>${esc(k.intent)}</strong></td><td>${esc(k.sensitivity)}</td><td>${k.confidence.toFixed(2)}</td><td>${esc(k.why)}</td></tr>`);
321
+ }
322
+ // A refusal is an answer, shown as one โ€” never dropped, never styled as a failure.
323
+ for (const r of p.refused) {
324
+ parts.push(`<tr><td><code>${esc(r.entryPoint.split('#')[1] ?? r.entryPoint)}</code></td><td class="muted"><em>declined</em></td><td class="muted">โ€”</td><td>${r.confidence.toFixed(2)}</td><td>${esc(r.why)}</td></tr>`);
325
+ }
326
+ parts.push(`</tbody></table></div>`);
327
+ if (p.dropped > 0) {
328
+ parts.push(`<div class="note">${p.dropped} classification${p.dropped === 1 ? '' : 's'} on this page ${p.dropped === 1 ? 'was' : 'were'} dropped: the evidence did not check out. See <code>classification.json</code>.</div>`);
329
+ }
330
+ }
331
+ if (c.securityTools.length > 0) {
332
+ parts.push(`<h3 style="margin-top:22px">Security checks this selects</h3>
333
+ <div class="note">Chosen deterministically by the taxonomy from the intent above โ€” never by the model. Available on the ia-qa.com MCP server.</div>
334
+ <div class="scroll"><table><thead><tr><th>Tool</th><th>For</th></tr></thead><tbody>`);
335
+ for (const t of c.securityTools) {
336
+ parts.push(`<tr><td><code>${esc(t.tool)}</code></td><td>${t.pages.map((p) => `<code>${esc(p)}</code>`).join(' ')}</td></tr>`);
337
+ }
338
+ parts.push(`</tbody></table></div>`);
339
+ }
340
+ // The honesty counter, in the same place the deterministic sections put theirs.
341
+ if (c.unclassified.length > 0) {
342
+ parts.push(`<div class="callout"><span class="cl-label">${c.unclassified.length} page${c.unclassified.length === 1 ? '' : 's'} with entry points carry no classification</span>
343
+ Either they were not sent, or their call failed: ${c.unclassified.map((p) => `<code>${esc(p)}</code>`).join(' ')}. The counts above describe what was classified, not the app.</div>`);
344
+ }
345
+ if (c.noEntryPoints > 0) {
346
+ parts.push(`<div class="note">${c.noEntryPoints} captured page${c.noEntryPoints === 1 ? '' : 's'} take no input at all, so there was nothing on them to classify.</div>`);
347
+ }
348
+ parts.push(`</section>`);
349
+ }
350
+ // โ”€โ”€ Testability โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
351
+ if (unstable.length > 0) {
352
+ parts.push(`<section><h2>Testability</h2>
353
+ <div class="callout"><span class="cl-label">${unstable.length} of ${fields.length} field${fields.length === 1 ? '' : 's'} cannot be located durably</span>
354
+ They carry no <code>data-testid</code>, no <code>id</code> and no <code>name</code>, so the selectors above for them are
355
+ positional: they resolve today and break the moment a field is inserted above them. Adding a
356
+ <code>data-testid</code> to each is the cheapest durable fix โ€” and it is worth doing <em>before</em> a suite is written
357
+ against them, not after.</div></section>`);
358
+ }
359
+ parts.push(`</div></main><footer><div class="wrap">
360
+ Generated by <a href="${BRAND.home}">IA-QA</a> <code>qa-discovery</code> โ€” ${
361
+ // "no LLM" is true of the capture and false of this document the moment a
362
+ // classification section is in it. A footer that keeps saying it either way
363
+ // is the smallest possible version of the lie this package is built against.
364
+ classification
365
+ ? `capture deterministic and local; the classified section came from <code>${esc(classification.model)}</code>.`
366
+ : 'deterministic, local, no LLM.'}
367
+ ยท <a href="${BRAND.method}">Methods</a> ยท <a href="${BRAND.tools}">Tools</a>
368
+ </div></footer></body></html>`);
369
+ return parts.join('\n');
370
+ }
371
+ //# sourceMappingURL=htmlReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"htmlReport.js","sourceRoot":"","sources":["../src/htmlReport.ts"],"names":[],"mappings":";;AA8FA,4CAwSC;AArYD,6DAAmG;AAGnG;;;;;;;;;;;;GAYG;AAEH,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,uBAAuB;IAC7B,MAAM,EAAE,8BAA8B;IACtC,KAAK,EAAE,iCAAiC;CACzC,CAAC;AAEF,SAAS,GAAG,CAAC,CAAU;IACrB,OAAO,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SAC9B,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,YAAY,CAAC,IAAkB;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,gCAAgC,CAAC;IAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC;IACzE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACpF,OAAO,GAAG,MAAM,MAAM,MAAM,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDlB,CAAC;AAEF,SAAgB,gBAAgB,CAAC,KAAoB;IACnD,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;IAExH,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAEnE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC;;qBAEQ,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;SACjC,UAAU,uBAAuB,CAAC,CAAC;IAE1C,KAAK,CAAC,IAAI,CAAC;;4BAEe,KAAK,CAAC,IAAI;2BACX,KAAK,CAAC,MAAM;;;wBAGf,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;uCACN,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,cAAc;;wCAErF,CAAC,CAAC;IAExC,4EAA4E;IAC5E,KAAK,CAAC,IAAI,CAAC;;;;;uCAK0B,QAAQ,CAAC,aAAa;uCACtB,SAAS;uCACT,MAAM,CAAC,MAAM;uCACb,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;uCAC/B,QAAQ,CAAC,OAAO,CAAC,MAAM;SACrD,CAAC,CAAC;IAET,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpF,IAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC;gCACiB,QAAQ;4EACoC,MAAM,CAAC,MAAM;;;iGAGQ,CAAC,CAAC;IACjG,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,sDAAsD,QAAQ,iCAAiC,aAAa;2CAChF,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,aAAa,+FAA+F,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACjM,CAAC;IAED,IAAI,YAAY,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC;cACD,YAAY;MACpB,QAAQ,CAAC,aAAa,IAAI,eAAe,CAAC,CAAC,CAAC,+BAA+B,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;8FACV,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC;;;2BAGY,QAAQ,CAAC,aAAa,OAAO,QAAQ,CAAC,UAAU;;4HAEiD,CAAC,CAAC;IAC5H,CAAC;SAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC;MACT,SAAS,CAAC,MAAM,OAAO,QAAQ,CAAC,aAAa;OAC5C,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;MAG1D,OAAO;YACP,CAAC,CAAC,wGAAwG;YAC1G,CAAC,CAAC,gFAAgF,QAAQ,CAAC,CAAC;IAChG,CAAC;SAAM,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC;kCACmB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;;yFAEsC,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;IACjH,CAAC;IAED,IAAI,QAAQ,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC;MACT,QAAQ,CAAC,WAAW,qDAAqD,QAAQ,CAAC,aAAa;MAC/F,QAAQ,CAAC,UAAU,qBAAqB,CAAC,CAAC;IAC9C,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEzB,4EAA4E;IAC5E,KAAK,CAAC,IAAI,CAAC,uBAAuB,KAAK,CAAC,MAAM;0IAC0F,CAAC,CAAC;IAC1I,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC;YAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,SAAS,GACb,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,WAAW,CAAC,MAAM,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClI,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,GAAG,CAAC,QAAQ,CAAC;UAC3E,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,SAAS,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,CAAC;IACvJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAErC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/E,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,mDAAmD,KAAK,CAAC,MAAM;wCACtC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;iFACc,CAAC,CAAC;IACjF,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEzB,4EAA4E;IAC5E,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,sCAAsC,SAAS;;;8CAGhB,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;gBAC9D,KAAK,CAAC,IAAI,CAAC;cACL,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,IAAI,CAAC,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,WAAW,CAAC,CAAC,CAAC,EAAE;4CACpH,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,wBAAwB,YAAY,CAAC,IAAI,CAAC;yBAC/E,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,yBAAyB,QAAQ,CAAC,CAAC;gBACjF,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,KAAK,CAAC,IAAI,CAAC,2IAA2I,CAAC,CAAC;oBACxJ,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,iBAAiB;4BAC9B,CAAC,CAAC,0CAA0C;4BAC5C,CAAC,CAAC,CAAC,CAAC,cAAc;gCAChB,CAAC,CAAC,uCAAuC;gCACzC,CAAC,CAAC,2CAA2C,CAAC;wBAClD,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;kBACjE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,kBAAkB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,IAAI,YAAY,CAAC,CAAC;oBACvG,CAAC;oBACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;gBACvC,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC;IAED,4EAA4E;IAC5E,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvE,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,6CAA6C,UAAU;;kHAE4C,CAAC,CAAC;QAChH,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YACzC,KAAK,CAAC,IAAI,CAAC;YACL,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,WAAW,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;6KAC0D,CAAC,CAAC;YACzK,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,iBAAiB;oBAC9B,CAAC,CAAC,0CAA0C;oBAC5C,CAAC,CAAC,CAAC,CAAC,cAAc;wBAChB,CAAC,CAAC,uCAAuC;wBACzC,CAAC,CAAC,2CAA2C,CAAC;gBAClD,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;cACtG,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,IAAI,YAAY,CAAC,CAAC;YAC/K,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC5C,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,yIAAyI,CAAC,CAAC;IACxJ,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,sIAAsI,CAAC,CAAC;QACnJ,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACjC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,KAAK;YAChF,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,mCAAmC,YAAY,CAAC,CAAC;QAC/G,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;;;;mEAIoD,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAC/E,KAAK,CAAC,IAAI,CAAC,mDAAmD,QAAQ,OAAO,MAAM,CAAC,WAAW;;;uHAGoB,CAAC,CAAC;QACrH,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC;QACpI,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC;2FAC4E,CAAC,CAAC;QACzF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC3B,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC;YACxI,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEzB,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,iCAAiC;IACjC,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,cAAc,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC;wBACS,GAAG,CAAC,IAAA,2CAAsB,EAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,8BAA8B,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC;wBAChJ,GAAG,CAAC,0CAAqB,CAAC,QAAQ,CAAC,CAAC;QAExD,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,UAAU,QAAQ,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,gBAAgB,GAAG,CAAC,iCAAY,CAAC,QAAQ,CAAC,CAAC;QACnM,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,qCAAqC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;4DACP,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;gBAC5G,SAAS;YACX,CAAC;YACD,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAC5D,KAAK,CAAC,IAAI,CAAC,qCAAqC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,uCAAuC,CAAC,CAAC,CAAC,EAAE;mJACkB,CAAC,CAAC;YAC/I,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,2BAA2B,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACnO,CAAC;YACD,mFAAmF;YACnF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,mFAAmF,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC3N,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACrC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,uFAAuF,CAAC,CAAC;YACjO,CAAC;QACH,CAAC;QAED,IAAI,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC;;0FAEyE,CAAC,CAAC;YACtF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;gBAChC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAChI,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACvC,CAAC;QAED,gFAAgF;QAChF,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,YAAY,CAAC,MAAM,QAAQ,CAAC,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;yDAC1E,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;QACzL,CAAC;QACD,IAAI,CAAC,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,aAAa,iBAAiB,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,wEAAwE,CAAC,CAAC;QAC5K,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3B,CAAC;IAED,4EAA4E;IAC5E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC;kDACmC,QAAQ,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG;;;;6CAI/E,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC;0BACa,KAAK,CAAC,IAAI,2CAA2C;IAC3E,0EAA0E;IAC1E,4EAA4E;IAC5E,6EAA6E;IAC7E,cAAc;QACZ,CAAC,CAAC,2EAA2E,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,UAAU;QAChH,CAAC,CAAC,+BACN;eACa,KAAK,CAAC,MAAM,4BAA4B,KAAK,CAAC,KAAK;8BACpC,CAAC,CAAC;IAE9B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,24 @@
1
+ export { scanApp } from './scan';
2
+ export type { ScanOptions, ScanResult, SurfaceManifest } from './scan';
3
+ export { SURFACE_SCHEMA } from './scan';
4
+ export { readHistory, appendHistory, historyPath, HISTORY_LIMIT } from './history';
5
+ export type { ScanHistoryEntry } from './history';
6
+ export { capturePage, PAGE_CAPTURE_SCHEMA } from './capture/page';
7
+ export type { PageCapture, PageMeta, Heading, CapturedForm, FormField } from './capture/page';
8
+ export { SHARED_CALLS_SCHEMA } from './sharedCalls';
9
+ export type { SharedCallsFile } from './sharedCalls';
10
+ export { compareCaptures } from './diff';
11
+ export type { CaptureDiff } from './diff';
12
+ export { renderOverview, OVERVIEW_FILENAME } from './overview';
13
+ export type { OverviewInput } from './overview';
14
+ export { renderScanReport } from './htmlReport';
15
+ export { loadConfig, saveConfig, configExists, baseDir, setBaseDir, captureDir, configPath, sessionPath, sessionTarget, resolveSession, CONFIG_DIR, SESSION_FILENAME, } from './config';
16
+ export type { DiscoveryConfig, CaptureConfig, SessionChoice, SessionSource } from './config';
17
+ export { normalizeApiUrl, apiCallFingerprint, DEFAULT_SAFE_QUERY_PARAMS } from './network';
18
+ export type { ApiCall } from './network';
19
+ export { verifyCitation, verifyClaim, loadCaptureIndex, SHARED_REF } from './citations';
20
+ export type { Citation, CitationVerdict, CitationFailure, CaptureIndex, VerifiedClaim } from './citations';
21
+ export { INTENTS, SENSITIVITIES, INTENT_IDS, SENSITIVITY_IDS, UNKNOWN_INTENT, TAXONOMY_VERSION, isIntent, isSensitivity, securityToolsFor, taxonomyForPrompt } from './taxonomy';
22
+ export type { IntentDef, SensitivityDef, ToolTrigger } from './taxonomy';
23
+ export { classifyPage, entryPointsOf, buildPrompt, parseClassifications, validate, collect } from './ai/classify';
24
+ export type { ClassifyOptions, ClassifyResult, Classification, DroppedClassification, EntryPoint } from './ai/classify';