@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,360 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.HELP = exports.CLASSIFICATION_FILENAME = exports.CLASSIFICATION_SCHEMA = void 0;
38
+ exports.main = main;
39
+ exports.runClassify = runClassify;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const self_healing_1 = require("@ia-qa/self-healing");
43
+ const config_1 = require("../config");
44
+ const citations_1 = require("../citations");
45
+ const classify_1 = require("../ai/classify");
46
+ Object.defineProperty(exports, "CLASSIFICATION_FILENAME", { enumerable: true, get: function () { return classify_1.CLASSIFICATION_FILENAME; } });
47
+ Object.defineProperty(exports, "CLASSIFICATION_SCHEMA", { enumerable: true, get: function () { return classify_1.CLASSIFICATION_SCHEMA; } });
48
+ const taxonomy_1 = require("../taxonomy");
49
+ const overviewFile_1 = require("../overviewFile");
50
+ /**
51
+ * `ia-qa-discover-ai` — the optional, BYOK classification layer.
52
+ *
53
+ * A separate binary for the same reason `ia-qa-heal-ai` is one: the
54
+ * deterministic verbs must behave identically whether or not anyone has a key,
55
+ * and a flag on `scan` would blur that. `scan` never calls a model; this reads
56
+ * what `scan` already wrote, offline, and adds a layer a human reviews.
57
+ *
58
+ * It produces no verdict and gates nothing. Every claim it keeps cites a path
59
+ * into the capture that was resolved and checked; every claim it drops says why.
60
+ */
61
+ const VERSION = require('../../package.json').version;
62
+ const HELP = `ia-qa-discover-ai — optional BYOK classification for a discovery capture
63
+
64
+ What each entry point your app exposes is FOR, and how sensitive what it handles
65
+ is. Reads .ia-qa-discovery/capture/ offline — it never opens a browser and never
66
+ touches your application. Your key, your model, your machine.
67
+
68
+ Every classification carries a sentence you read and a path into the capture that
69
+ this tool resolves and checks before keeping it. A claim that cites nothing, cites
70
+ something that does not exist, or misdescribes what it cites, is DROPPED and the
71
+ drop is reported. That check proves the premise, never the conclusion: only you
72
+ can say whether the reading follows.
73
+
74
+ Nothing here is a gate. \`ia-qa-discover\` works fully without a key.
75
+
76
+ Usage:
77
+ ia-qa-discover-ai classify Classify every entry point in the capture.
78
+ --page <name> just this page
79
+ --json machine-readable output
80
+ --dry-run show what would be sent, call nothing
81
+ ia-qa-discover-ai models List the providers and models you can configure
82
+ ia-qa-discover-ai version Print the installed version
83
+ ia-qa-discover-ai help Show this help
84
+
85
+ Configure it in ${config_1.CONFIG_DIR}/config.json:
86
+
87
+ "ai": {
88
+ "provider": "anthropic",
89
+ "model": "claude-haiku-4-5",
90
+ "apiKey": { "source": "env", "key": "ANTHROPIC_API_KEY" }
91
+ }
92
+
93
+ The key itself never goes in that file — only the name of the variable holding it.
94
+
95
+ Global:
96
+ --config <dir> Resolve ${config_1.CONFIG_DIR}/ under <dir> instead of the current directory
97
+ `;
98
+ exports.HELP = HELP;
99
+ /**
100
+ * Read the `ai` block and resolve its key. Returns null — having already
101
+ * explained itself and set exit code 2 — rather than throwing, because every
102
+ * failure here is a configuration problem the user can act on.
103
+ */
104
+ async function resolveAi() {
105
+ if (!(0, config_1.configExists)()) {
106
+ console.error(`❌ No ${config_1.CONFIG_DIR}/config.json here.\n` +
107
+ ` Run \`ia-qa-discover scan <url> --save\` first: this tool classifies a capture,\n` +
108
+ ` it does not make one.`);
109
+ process.exitCode = 2;
110
+ return null;
111
+ }
112
+ const ai = (0, config_1.loadConfig)().ai;
113
+ if (!ai) {
114
+ console.error(`❌ No "ai" block in ${config_1.CONFIG_DIR}/config.json, so there is no model to call.\n\n` +
115
+ ` Add one:\n` +
116
+ ` "ai": { "provider": "anthropic", "model": "claude-haiku-4-5",\n` +
117
+ ` "apiKey": { "source": "env", "key": "ANTHROPIC_API_KEY" } }\n\n` +
118
+ ` \`ia-qa-discover-ai models\` lists what you can put there.\n` +
119
+ ` The deterministic \`ia-qa-discover\` works fully without any of this.`);
120
+ process.exitCode = 2;
121
+ return null;
122
+ }
123
+ const provider = (0, self_healing_1.findProvider)(ai.provider ?? '');
124
+ if (!provider) {
125
+ console.error(`❌ Unknown ai.provider "${ai.provider}". Use one of: ${self_healing_1.AI_PROVIDERS.map((p) => p.id).join(', ')}.\n` +
126
+ ` Run \`ia-qa-discover-ai models\` to see them with their models.`);
127
+ process.exitCode = 2;
128
+ return null;
129
+ }
130
+ if (!ai.model) {
131
+ console.error(`❌ ai.model is required — pin one, so two runs are comparable. See \`ia-qa-discover-ai models\`.`);
132
+ process.exitCode = 2;
133
+ return null;
134
+ }
135
+ if (!ai.apiKey) {
136
+ console.error(`❌ ai.apiKey is required. It is a REFERENCE, never the key itself:\n` +
137
+ ` "apiKey": { "source": "env", "key": "${provider.keyEnv}" }`);
138
+ process.exitCode = 2;
139
+ return null;
140
+ }
141
+ // The common case — an env var — is handled here rather than delegated,
142
+ // because `resolveSecret`'s own message is written for the other package: it
143
+ // names `ia-qa-heal`, its CLI path and `.ia-qa/config.json`, and sending
144
+ // someone here to a different tool's config is worse than no help at all.
145
+ // Everything else (AWS SSM) still delegates: one secret path, not two.
146
+ if (ai.apiKey.source === 'env' && !process.env[ai.apiKey.key]) {
147
+ console.error(`❌ Environment variable "${ai.apiKey.key}" is not set, so there is no key to call ${provider.label} with.\n\n` +
148
+ ` This CLI reads process.env only — it never loads .env files, so a key that lives\n` +
149
+ ` only in .env will not be seen. Put it in the environment first:\n` +
150
+ ` npx dotenv-cli -- ia-qa-discover-ai classify\n\n` +
151
+ ` The value never belongs in ${config_1.CONFIG_DIR}/config.json, which holds references only.`);
152
+ process.exitCode = 2;
153
+ return null;
154
+ }
155
+ try {
156
+ const apiKey = await (0, self_healing_1.resolveSecret)(ai.apiKey);
157
+ return { provider: provider.id, model: ai.model, apiKey };
158
+ }
159
+ catch (e) {
160
+ console.error(`❌ ${e instanceof Error ? e.message : String(e)}`);
161
+ process.exitCode = 2;
162
+ return null;
163
+ }
164
+ }
165
+ function flag(args, name) {
166
+ const i = args.indexOf(name);
167
+ if (i === -1)
168
+ return undefined;
169
+ const next = args[i + 1];
170
+ if (!next || next.startsWith('-'))
171
+ throw new Error(`${name} needs a value.`);
172
+ return next;
173
+ }
174
+ async function runClassify(args) {
175
+ const json = args.includes('--json');
176
+ const dryRun = args.includes('--dry-run');
177
+ const only = flag(args, '--page');
178
+ const index = (0, citations_1.loadCaptureIndex)();
179
+ if (index.pages.size === 0) {
180
+ console.error(`❌ No capture in ${path.relative(process.cwd(), (0, config_1.captureDir)()) || (0, config_1.captureDir)()}.\n` +
181
+ ` Run \`ia-qa-discover scan\` first.`);
182
+ process.exitCode = 2;
183
+ return;
184
+ }
185
+ const pages = [...index.pages.values()].filter((p) => !only || p.page === only);
186
+ if (pages.length === 0) {
187
+ console.error(`❌ No page "${only}" in the capture. Have: ${[...index.pages.keys()].join(', ')}`);
188
+ process.exitCode = 2;
189
+ return;
190
+ }
191
+ const withEntryPoints = pages.filter((p) => (0, classify_1.entryPointsOf)(p).length > 0);
192
+ if (dryRun) {
193
+ // What would be sent, and to whom — before any key is even resolved.
194
+ console.log(`Would classify ${withEntryPoints.length} page(s) with entry points, of ${pages.length} captured:`);
195
+ for (const p of withEntryPoints)
196
+ console.log(` ${p.page} — ${(0, classify_1.entryPointsOf)(p).length} entry point(s)`);
197
+ const skipped = pages.length - withEntryPoints.length;
198
+ if (skipped > 0)
199
+ console.log(` (${skipped} page(s) take no input and would not be sent at all)`);
200
+ // Naming the destination is the whole point of a dry run: someone runs it to
201
+ // decide whether these strings may go, and "to whom" is half that decision.
202
+ const declared = ((0, config_1.configExists)() ? (0, config_1.loadConfig)().ai : undefined) ?? {};
203
+ const provider = (0, self_healing_1.findProvider)(declared.provider ?? '');
204
+ if (provider)
205
+ console.log((0, classify_1.egressNotice)(provider.id, declared.model ?? '(no model set)', withEntryPoints.length, true));
206
+ console.log(`Nothing was called. Drop --dry-run to run it.`);
207
+ return;
208
+ }
209
+ const ai = await resolveAi();
210
+ if (!ai)
211
+ return;
212
+ if (!json) {
213
+ console.log(`🤖 ${ai.provider}/${ai.model} · ${withEntryPoints.length} page(s) with entry points · ${taxonomy_1.TAXONOMY_VERSION}`);
214
+ console.log(` Reading the capture offline. Your app is not touched.`);
215
+ }
216
+ // "Offline" above means no browser, and on its own it reads as "nothing leaves".
217
+ // stderr in every mode, `--json` included — a security announcement, not decoration.
218
+ console.error((0, classify_1.egressNotice)(ai.provider, ai.model, withEntryPoints.length));
219
+ const perPage = {};
220
+ for (const page of withEntryPoints) {
221
+ const result = await (0, classify_1.classifyPage)(page, index, { provider: ai.provider, model: ai.model, apiKey: ai.apiKey });
222
+ perPage[page.page] = result;
223
+ if (!json) {
224
+ if (result.failed) {
225
+ console.log(` ${page.page.padEnd(22)} ✘ ${result.failed.reason}`);
226
+ }
227
+ else {
228
+ const bits = [`${result.kept.length} classified`];
229
+ if (result.refused.length > 0)
230
+ bits.push(`${result.refused.length} refused`);
231
+ if (result.dropped.length > 0)
232
+ bits.push(`${result.dropped.length} dropped`);
233
+ console.log(` ${page.page.padEnd(22)} ${bits.join(' · ')}`);
234
+ }
235
+ }
236
+ }
237
+ // A call that did not happen is not a page with nothing on it. Reported before
238
+ // any total, and it sets a non-zero exit: with an invalid key this used to
239
+ // print "0 classified · 0 refused · 0 dropped", exit 0, and write a file —
240
+ // indistinguishable from an app that genuinely has nothing to classify.
241
+ const failures = Object.entries(perPage).filter(([, r]) => r.failed);
242
+ if (failures.length > 0) {
243
+ console.error(`\n❌ ${failures.length} of ${withEntryPoints.length} page(s) could not be classified at all:`);
244
+ for (const [name, r] of failures.slice(0, 5))
245
+ console.error(` ${name}: ${r.failed.reason}`);
246
+ if (failures.length > 5)
247
+ console.error(` …and ${failures.length - 5} more.`);
248
+ console.error(` Nothing is wrong with your app or your capture — the model call did not succeed.`);
249
+ process.exitCode = 2;
250
+ if (failures.length === withEntryPoints.length) {
251
+ // Nothing to WRITE — a document of failures would overwrite a previous good
252
+ // classification with the record of a bad key. But not writing is not a
253
+ // reason to say nothing: `--json` promised stdout a document, and an empty
254
+ // stdout with exit 2 is indistinguishable from a crashed process. So the
255
+ // failures go out on stdout, and only the file is skipped.
256
+ if (json) {
257
+ console.log(JSON.stringify({ schema: classify_1.CLASSIFICATION_SCHEMA, taxonomyVersion: taxonomy_1.TAXONOMY_VERSION, classifiedAt: new Date().toISOString(), model: `${ai.provider}/${ai.model}`, totals: { kept: 0, refused: 0, dropped: 0 }, pages: perPage, written: false }, null, 2));
258
+ }
259
+ return;
260
+ }
261
+ }
262
+ const kept = Object.values(perPage).flatMap((r) => r.kept);
263
+ const refused = Object.values(perPage).flatMap((r) => r.refused);
264
+ const dropped = Object.values(perPage).flatMap((r) => r.dropped);
265
+ const document = {
266
+ schema: classify_1.CLASSIFICATION_SCHEMA,
267
+ taxonomyVersion: taxonomy_1.TAXONOMY_VERSION,
268
+ classifiedAt: new Date().toISOString(),
269
+ model: `${ai.provider}/${ai.model}`,
270
+ totals: { kept: kept.length, refused: refused.length, dropped: dropped.length },
271
+ pages: perPage,
272
+ };
273
+ const file = path.join((0, config_1.baseDir)(), config_1.CONFIG_DIR, classify_1.CLASSIFICATION_FILENAME);
274
+ fs.mkdirSync(path.dirname(file), { recursive: true });
275
+ fs.writeFileSync(file, JSON.stringify(document, null, 2) + '\n', 'utf8');
276
+ // `classification.json` is not where anyone looks. `_overview.md` is, and
277
+ // `scan` wrote it before this classification existed — so it is rewritten
278
+ // here, which is also the only moment the classification is NOT stale.
279
+ // A refusal is reported, never swallowed: an overview silently left at its
280
+ // previous content is a report that disagrees with the file beside it.
281
+ const refreshed = (0, overviewFile_1.refreshOverview)();
282
+ if (!refreshed.ok)
283
+ console.error(`\n⚠ _overview.md was not updated: ${refreshed.reason}`);
284
+ if (json) {
285
+ console.log(JSON.stringify({ ...document, overview: refreshed.ok ? refreshed.file : null }, null, 2));
286
+ return;
287
+ }
288
+ console.log(`\n${kept.length} classified · ${refused.length} refused · ${dropped.length} dropped`);
289
+ // The security work this unlocks, deterministically — the point of classifying
290
+ // at all. Deduplicated across entry points: one tool per reason, not per field.
291
+ const tools = new Map();
292
+ for (const k of kept) {
293
+ for (const t of k.securityTools ?? []) {
294
+ if (!tools.has(t.tool))
295
+ tools.set(t.tool, new Set());
296
+ tools.get(t.tool).add(k.entryPoint.split('#')[0].replace(/^pages\//, '').replace(/\.json$/, ''));
297
+ }
298
+ }
299
+ if (tools.size > 0) {
300
+ console.log(`\n🔐 Security checks this selects (they already exist on the ia-qa.com MCP):`);
301
+ for (const [tool, pagesFor] of tools) {
302
+ console.log(` ${tool.padEnd(24)} for ${[...pagesFor].join(', ')}`);
303
+ }
304
+ }
305
+ if (refused.length > 0) {
306
+ console.log(`\n${refused.length} entry point(s) the model would not label. That is an answer, not a gap —` +
307
+ `\nthe evidence did not support any category. They need a person, not a retry.`);
308
+ }
309
+ if (dropped.length > 0) {
310
+ console.log(`\n${dropped.length} classification(s) dropped because their evidence did not check out:`);
311
+ for (const d of dropped.slice(0, 5))
312
+ console.log(` ${(d.classification.entryPoint ?? '?')} — ${d.reason}`);
313
+ if (dropped.length > 5)
314
+ console.log(` …and ${dropped.length - 5} more (see the JSON).`);
315
+ }
316
+ console.log(`\nWritten to ${file}`);
317
+ console.log(`Every kept claim cites the capture. Read the "why" and the evidence before acting on it.`);
318
+ }
319
+ async function main() {
320
+ const argv = process.argv.slice(2);
321
+ const ci = argv.indexOf('--config');
322
+ if (ci !== -1) {
323
+ const dir = argv[ci + 1];
324
+ if (!dir || dir.startsWith('-'))
325
+ throw new Error('--config needs a directory argument.');
326
+ (0, config_1.setBaseDir)(dir);
327
+ argv.splice(ci, 2);
328
+ }
329
+ const [command, ...rest] = argv;
330
+ switch (command) {
331
+ case 'classify':
332
+ await runClassify(rest);
333
+ break;
334
+ case 'models':
335
+ console.log((0, self_healing_1.renderModelList)());
336
+ break;
337
+ case 'version':
338
+ case '--version':
339
+ case '-v':
340
+ console.log(VERSION);
341
+ break;
342
+ case 'help':
343
+ case '--help':
344
+ case '-h':
345
+ case undefined:
346
+ console.log(HELP);
347
+ break;
348
+ default:
349
+ console.error(`Unknown command "${command}".\n\n${HELP}`);
350
+ process.exit(1);
351
+ }
352
+ }
353
+ /** Only when this file IS the process — so the dispatch stays importable, and testable. */
354
+ if (require.main === module) {
355
+ main().catch((err) => {
356
+ console.error(`\n❌ ${err instanceof Error ? err.message : String(err)}`);
357
+ process.exit(1);
358
+ });
359
+ }
360
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli-ai/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ import type { SecretRef } from '@ia-qa/self-healing';
2
+ /**
3
+ * Configuration for `@ia-qa/qa-discovery` — `.ia-qa-discovery/config.json`.
4
+ *
5
+ * Deliberately a SIBLING of `@ia-qa/self-healing`'s `.ia-qa/`, never nested
6
+ * inside it: the two tools' local state never overlaps, so a project can run
7
+ * both without either one reading the other's files by accident.
8
+ */
9
+ export interface CaptureConfig {
10
+ /** Observe API/network calls per page. Default true. */
11
+ network?: boolean;
12
+ /** Fraction of pages (0-1) a call must appear on to be promoted as shared. Default 0.6. */
13
+ networkThreshold?: number;
14
+ /** Click one level of disclosures per page and capture what they reveal. Default false. */
15
+ deep?: boolean;
16
+ /** Query param names whose VALUE is kept when normalizing a captured API call. Everything else keeps only the key name. */
17
+ safeQueryParams?: string[];
18
+ }
19
+ /**
20
+ * A page the user declares, because a crawl cannot find it.
21
+ *
22
+ * Discovery follows `<a href>`. An app that navigates programmatically (React
23
+ * Router's `useNavigate()`, a button with an onClick handler) exposes no href,
24
+ * so a crawl reaches exactly the entry URL — measured on a real app: 11 routes,
25
+ * zero `<Link>`, one page found. Declaring the routes is the deterministic way
26
+ * out, and they are usually sitting in the router file in plain sight.
27
+ *
28
+ * Declared pages are scanned IN ADDITION to whatever the crawl finds, deduped
29
+ * by path — so declaring some does not turn the crawl off.
30
+ */
31
+ export interface DeclaredPage {
32
+ /** Filename for the capture. Defaults to a slug of the URL path. */
33
+ name?: string;
34
+ /** Path or absolute URL, resolved against `baseUrl`. */
35
+ url: string;
36
+ }
37
+ export interface DiscoveryConfig {
38
+ baseUrl: string;
39
+ /** Routes a crawl cannot discover on its own. See `DeclaredPage`. */
40
+ pages?: DeclaredPage[];
41
+ /** Path to an existing Playwright storageState file (e.g. from self-healing's `login`, or a project's own globalSetup). Never written by this package. */
42
+ session?: string;
43
+ locale?: string;
44
+ crawl?: {
45
+ maxDepth?: number;
46
+ maxPages?: number;
47
+ reveal?: boolean;
48
+ strictHost?: boolean;
49
+ /** Read sitemap.xml (robots.txt fallback) as a page source. Default true. */
50
+ sitemap?: boolean;
51
+ };
52
+ capture?: CaptureConfig;
53
+ /**
54
+ * Optional BYOK config for . Its absence means the AI layer
55
+ * is inert and every deterministic verb behaves exactly as it does today.
56
+ * is a REFERENCE (env var name / SSM parameter), never the value:
57
+ * config.json is meant to be committed.
58
+ */
59
+ ai?: {
60
+ provider: string;
61
+ /** Pinned, so two runs are comparable. */
62
+ model: string;
63
+ apiKey: SecretRef;
64
+ };
65
+ }
66
+ export declare const CONFIG_DIR = ".ia-qa-discovery";
67
+ export declare const CAPTURE_DIRNAME = "capture";
68
+ export declare const HISTORY_FILENAME = "history.jsonl";
69
+ /**
70
+ * A browser session saved by `ia-qa-discover login`, in Playwright
71
+ * `storageState` shape. It holds live cookies: whoever has this file is logged
72
+ * in as that user. It is the one artefact in `.ia-qa-discovery/` that is a
73
+ * secret — never uploaded anywhere, and `login` writes
74
+ * `.ia-qa-discovery/.gitignore` so a commit cannot carry it.
75
+ */
76
+ export declare const SESSION_FILENAME = "session.json";
77
+ /** Set the base dir (the `--config <dir>` flag). `null` clears it back to the default. */
78
+ export declare function setBaseDir(dir: string | null): void;
79
+ export declare function baseDir(): string;
80
+ export declare function configPath(cwd?: string): string;
81
+ export declare function captureDir(cwd?: string): string;
82
+ export declare function historyPath(cwd?: string): string;
83
+ export declare function loadConfig(cwd?: string): DiscoveryConfig;
84
+ export declare function saveConfig(config: DiscoveryConfig, cwd?: string): string;
85
+ export declare function configExists(cwd?: string): boolean;
86
+ export declare function sessionPath(cwd?: string): string;
87
+ export type SessionSource = 'flag' | 'env' | 'config' | 'login';
88
+ export interface SessionChoice {
89
+ file: string;
90
+ source: SessionSource;
91
+ }
92
+ /**
93
+ * Which session file to *write* — `login`'s target. Same precedence as
94
+ * reading, minus the existence check: pointing `session` at a path is also a
95
+ * way of saying where you want it kept, so `login` refreshes THAT file rather
96
+ * than leaving a second one beside it for `scan` to have to choose between.
97
+ */
98
+ export declare function sessionTarget(config: Pick<DiscoveryConfig, 'session'> | undefined, explicit?: string, cwd?: string): SessionChoice;
99
+ /**
100
+ * The session to *read*, or null when there is none to read.
101
+ *
102
+ * A session the user NAMED — a flag, an env var, a config field — that cannot
103
+ * be used is a hard error, never a silent fall-through. Ignoring it would
104
+ * capture the login page under the names of their real pages and exit 0, which
105
+ * is the false green this whole package must avoid. The default location is
106
+ * different: absent simply means nobody has run `login` yet.
107
+ *
108
+ * The shape check is deliberately shallow — `cookies` is enough to tell a
109
+ * storageState from a config file pasted by mistake. The file is a secret: it
110
+ * is never read for anything else, never logged, never sent anywhere.
111
+ */
112
+ export declare function resolveSession(config: Pick<DiscoveryConfig, 'session'> | undefined, explicit?: string, cwd?: string): SessionChoice | null;