@ia-qa/qa-discovery 0.3.0 → 0.5.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 (52) hide show
  1. package/README.md +109 -3
  2. package/ROADMAP.md +37 -4
  3. package/TUTORIAL.md +85 -2
  4. package/dist/ai/classify.d.ts +13 -36
  5. package/dist/ai/classify.js +23 -166
  6. package/dist/ai/classify.js.map +1 -1
  7. package/dist/ai/model.d.ts +93 -0
  8. package/dist/ai/model.js +192 -0
  9. package/dist/ai/model.js.map +1 -0
  10. package/dist/ai/plan.d.ts +224 -0
  11. package/dist/ai/plan.js +0 -0
  12. package/dist/ai/plan.js.map +1 -0
  13. package/dist/cli/args.js +2 -0
  14. package/dist/cli/args.js.map +1 -1
  15. package/dist/cli/generate.d.ts +56 -0
  16. package/dist/cli/generate.js +293 -0
  17. package/dist/cli/generate.js.map +1 -0
  18. package/dist/cli/index.d.ts +1 -1
  19. package/dist/cli/index.js +32 -0
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/skill.d.ts +20 -0
  22. package/dist/cli/skill.js +63 -0
  23. package/dist/cli/skill.js.map +1 -0
  24. package/dist/cli-ai/index.d.ts +3 -2
  25. package/dist/cli-ai/index.js +268 -4
  26. package/dist/cli-ai/index.js.map +1 -1
  27. package/dist/coverage.d.ts +52 -2
  28. package/dist/coverage.js +67 -7
  29. package/dist/coverage.js.map +1 -1
  30. package/dist/coverageView.js +17 -1
  31. package/dist/coverageView.js.map +1 -1
  32. package/dist/generate.d.ts +62 -0
  33. package/dist/generate.js +163 -0
  34. package/dist/generate.js.map +1 -0
  35. package/dist/htmlReport.js +20 -4
  36. package/dist/htmlReport.js.map +1 -1
  37. package/dist/index.d.ts +6 -0
  38. package/dist/index.js +32 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/mcp/server.d.ts +49 -0
  41. package/dist/mcp/server.js +143 -20
  42. package/dist/mcp/server.js.map +1 -1
  43. package/dist/overview.d.ts +9 -0
  44. package/dist/overview.js +9 -4
  45. package/dist/overview.js.map +1 -1
  46. package/dist/overviewFile.js +5 -0
  47. package/dist/overviewFile.js.map +1 -1
  48. package/dist/planView.d.ts +141 -0
  49. package/dist/planView.js +345 -0
  50. package/dist/planView.js.map +1 -0
  51. package/package.json +3 -2
  52. package/skills/ia-qa-discover/SKILL.md +166 -0
@@ -0,0 +1,224 @@
1
+ import { type AiProvider } from '@ia-qa/self-healing';
2
+ import type { PageCapture, Heading } from '../capture/page';
3
+ import { type CaptureIndex, type Citation, type CitationVerdict } from '../citations';
4
+ import { type ModelOptions } from './model';
5
+ /**
6
+ * The BYOK reading of a page: **what someone comes here to do**, and what they cannot do if
7
+ * it breaks.
8
+ *
9
+ * **Why this is not `classify` with a different prompt.** The deterministic half of this
10
+ * package answers what the app *accepts* — fields, types, required, what moved. `classify`
11
+ * answers what an entry point *is*, against a closed taxonomy. Neither can answer what a
12
+ * human is *trying to do*, and no amount of DOM says it: nothing in a capture states that a
13
+ * declined payment must show a message, or that this form is how a locked-out customer gets
14
+ * back in. That is the axis this file plays, and it is why the two layers are not ranked
15
+ * against each other — neither is a subset of the other.
16
+ *
17
+ * **It sends strictly less than `classify`, and that is a design decision, not an
18
+ * optimisation.** No selectors and no API calls leave for this question: they are the most
19
+ * sensitive half of the payload and they are technical noise for a question that is not
20
+ * technical. `planPayload` below IS what goes, `planEgressNotice` is derived from it, and a
21
+ * field added to one owes a line in the other.
22
+ *
23
+ * **It produces prose, never code.** Test code stays the deterministic generator's job, so
24
+ * that locators come from the contract and healing can repair them. A model sentence that
25
+ * became a locator would be a selector nobody can repair.
26
+ *
27
+ * **It gates nothing, and it ranks nothing.** `coverage` decides the order from what it
28
+ * measured; this adds a labelled line beside each page. A model reading that reordered a
29
+ * measured list would be exactly the confident-and-unfalsifiable number this package spends
30
+ * its design refusing.
31
+ */
32
+ export declare const PLAN_SCHEMA = "qa-discovery-plan@1";
33
+ export declare const PLAN_FILENAME = "plan.json";
34
+ export interface PlanReading {
35
+ page: string;
36
+ /** What someone comes to this page to do, in the words of whoever uses the app. */
37
+ purpose: string;
38
+ /** What that person cannot do if this page breaks. */
39
+ impact: string;
40
+ /** The model's own number, kept and shown. Nothing is discarded on it. */
41
+ confidence: number;
42
+ evidence: Citation[];
43
+ /**
44
+ * The model looked and could not tell what the page is for.
45
+ *
46
+ * A result, never a gap — and never silently dropped. The capture may genuinely not say
47
+ * (a bare dashboard shell, a page whose whole content arrives after a click), and a
48
+ * proposal nobody can anchor is worth reading as long as it is labelled as one.
49
+ */
50
+ unclear?: boolean;
51
+ }
52
+ export interface DroppedReading {
53
+ reading: Partial<PlanReading>;
54
+ reason: string;
55
+ rejected: Array<Extract<CitationVerdict, {
56
+ ok: false;
57
+ }>>;
58
+ }
59
+ export type PageReadingOutcome = {
60
+ status: 'read';
61
+ reading: PlanReading;
62
+ } | {
63
+ status: 'unclear';
64
+ reading: PlanReading;
65
+ } | {
66
+ status: 'dropped';
67
+ dropped: DroppedReading;
68
+ }
69
+ /** The call did not succeed. A fact about the request, never about the app. */
70
+ | {
71
+ status: 'failed';
72
+ reason: string;
73
+ };
74
+ /** Every heading sent. The same cap `classify` uses, for the same reason: a prompt is not a page. */
75
+ export declare const HEADING_LIMIT = 25;
76
+ /**
77
+ * Share of pages a heading must appear on to count as the app's shell rather than this page's
78
+ * content. The same 0.6 `autoLayout` uses, through the same `minPagesForLayout` — including
79
+ * its floor of 2, so on a two-page capture a heading cannot become "shared" by appearing
80
+ * once.
81
+ */
82
+ export declare const SHELL_THRESHOLD = 0.6;
83
+ /**
84
+ * Headings that belong to the shell, not to any page.
85
+ *
86
+ * Measured on a real run: a page whose whole interest was `🗂️ Environment Manager` had its
87
+ * reading cited against `Legal`, `Contact` and `Tools` — the footer. Those citations resolve,
88
+ * so nothing rejected them, and the check that is supposed to anchor the reading was anchoring
89
+ * it to furniture. Removing them from the payload removes the temptation rather than judging
90
+ * it afterwards, which is the same move `offeredPlanPaths` makes for invented paths.
91
+ *
92
+ * This is the heading analogue of `promoteSharedCalls`, and deliberately not a new rule: a
93
+ * third threshold convention in one repo is a third thing to drift.
94
+ */
95
+ export declare function shellHeadings(pages: PageCapture[]): Set<string>;
96
+ /**
97
+ * This page's own headings, with the shell dropped — and never all of them.
98
+ *
99
+ * A page whose every heading is shared keeps them: a payload with no heading at all would be
100
+ * a page the model cannot read, which is a worse outcome than a noisy one. The exclusion is a
101
+ * narrowing of the evidence, not a way to make a page unreadable.
102
+ *
103
+ * **The index is the one in the capture file, not a position in this list.** A citation
104
+ * resolves `pages/x.json#headings[3]` against the real array, so renumbering a filtered list
105
+ * would silently point every citation at a different heading — the kind of error that
106
+ * produces a verified-looking claim about something else entirely.
107
+ */
108
+ export declare function ownHeadings(page: PageCapture, shell: Set<string>): Array<{
109
+ index: number;
110
+ heading: Heading;
111
+ }>;
112
+ export interface PlanPayload {
113
+ page: string;
114
+ url: string;
115
+ /**
116
+ * Carried with their `at` paths, like everything else citable.
117
+ *
118
+ * They were flat strings here, and a real run caught it within minutes: offered as citable
119
+ * but shown pathless, so the model cited `#description` — the shape of the *prompt*, not
120
+ * the shape of the capture, where it lives at `#meta.description`. The reading was dropped
121
+ * as an invented path, which is the right refusal for the wrong reason: the prompt was
122
+ * lying about the data and the model was right to trust it. `classify.ts` documents this
123
+ * exact failure, and this file repeated it. **If a field can be cited, it is shown with the
124
+ * path that addresses it.**
125
+ */
126
+ title: {
127
+ at: string;
128
+ value: string;
129
+ };
130
+ description: {
131
+ at: string;
132
+ value: string;
133
+ };
134
+ headings: Array<{
135
+ at: string;
136
+ level: number;
137
+ text: string;
138
+ }>;
139
+ forms: Array<{
140
+ at: string;
141
+ submits: boolean;
142
+ fields: Record<string, unknown>[];
143
+ }>;
144
+ fields: Record<string, unknown>[];
145
+ /**
146
+ * The names of the other pages in this capture — no URLs, no titles, no content.
147
+ *
148
+ * A page cannot be placed in an app it cannot see: "reset" reads very differently in a
149
+ * capture that also holds `login` and `account` than in one that holds `admin-users`. The
150
+ * cheapest context that answers that, and it is a list of slugs the person already sees in
151
+ * their own capture directory.
152
+ */
153
+ otherPages: string[];
154
+ }
155
+ /**
156
+ * Exactly what is sent for one page. The egress notice is written from this function's
157
+ * output, so what it promises cannot drift from what goes.
158
+ */
159
+ export declare function planPayload(page: PageCapture, otherPages?: string[], shell?: Set<string>): PlanPayload;
160
+ /**
161
+ * Every path the prompt offers, and therefore the only paths a citation may use.
162
+ *
163
+ * The same guardrail `classify` learned the hard way: a model given a shape invents paths
164
+ * that exist in the prompt and nowhere in the capture. Refusing a constructed path removes
165
+ * the class of error instead of catching it afterwards. Note what is NOT here — `apiCalls`,
166
+ * which this verb does not send and therefore may not be cited.
167
+ */
168
+ export declare function offeredPlanPaths(page: PageCapture, shell?: Set<string>): Set<string>;
169
+ /**
170
+ * A page with nothing citable cannot produce a falsifiable reading, so it is never sent.
171
+ *
172
+ * Not a failure and never counted as one: a page that says nothing about itself is a finding
173
+ * about the app, and inventing a purpose for it is the one thing this layer must not do.
174
+ */
175
+ export declare function isReadable(page: PageCapture): boolean;
176
+ /**
177
+ * The citations that actually carry the page's subject: a top-level heading, a form, or a
178
+ * field.
179
+ *
180
+ * `classify` learned that a citation pointing at the thing being classified proves nothing.
181
+ * The sibling failure here is a citation that resolves and supports nothing — a footer link,
182
+ * a `meta.description` shared by the whole site. Measured on a real run: every citation on
183
+ * one page was a heading, and half of them were the footer.
184
+ *
185
+ * So at least one citation must land here. The rule is **conditional on the page having
186
+ * one**: a page whose only headings are level 3 and which takes no input cannot satisfy it,
187
+ * and dropping its reading would punish the page for its own markup. Same shape as the
188
+ * offered-paths check — a rule that cannot be met is not applied.
189
+ */
190
+ export declare function anchorPaths(page: PageCapture, shell?: Set<string>): Set<string>;
191
+ export declare function buildPlanPrompt(page: PageCapture, otherPages?: string[], shell?: Set<string>): string;
192
+ /**
193
+ * What leaves this machine for this verb, said before it leaves.
194
+ *
195
+ * Derived from `planPayload`: every line below is a field that function actually puts in the
196
+ * request, and the two "does NOT leave" lines name what `classify` sends and this does not.
197
+ * That difference is the reason this verb exists as its own notice rather than reusing the
198
+ * other — announcing more than goes is the mirror image of announcing less, and both make
199
+ * the announcement worthless.
200
+ *
201
+ * stderr in every mode, `--json` included: a security announcement, not decoration.
202
+ */
203
+ export declare function planEgressNotice(provider: AiProvider, model: string, pages: number, planned?: boolean, baseUrl?: string): string;
204
+ /**
205
+ * Validate one reading against the capture.
206
+ *
207
+ * The order is the same as `classify`'s and for the same reason: shape first, then the
208
+ * citations. A reply that is not the requested shape is not a reply whose evidence is worth
209
+ * resolving.
210
+ */
211
+ export declare function validateReading(raw: Partial<PlanReading> & Record<string, unknown>, page: PageCapture, index: CaptureIndex, offered?: Set<string>, anchors?: Set<string>): {
212
+ ok: true;
213
+ value: PlanReading;
214
+ } | {
215
+ ok: false;
216
+ dropped: DroppedReading;
217
+ };
218
+ /**
219
+ * One page in, one outcome out. Never throws: this layer is optional by construction, and a
220
+ * bad key must not take down a deterministic capture that already succeeded.
221
+ */
222
+ export declare function readPage(page: PageCapture, index: CaptureIndex, opts: ModelOptions, otherPages?: string[],
223
+ /** Headings the whole app shares. The caller computes it once, over every captured page. */
224
+ shell?: Set<string>): Promise<PageReadingOutcome>;
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/ai/plan.ts"],"names":[],"mappings":"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"}
package/dist/cli/args.js CHANGED
@@ -4,6 +4,7 @@ exports.KNOWN_FLAGS = void 0;
4
4
  exports.rejectUnknownFlags = rejectUnknownFlags;
5
5
  /** Flag validation for the hand-rolled CLI parser — mirrors `@ia-qa/self-healing`'s `cli/args.ts`. */
6
6
  exports.KNOWN_FLAGS = {
7
+ skill: ["--install", "--user", "--dir", "--print", "--force"],
7
8
  scan: [
8
9
  '--depth',
9
10
  '--max',
@@ -23,6 +24,7 @@ exports.KNOWN_FLAGS = {
23
24
  login: ['--url', '--session'],
24
25
  history: ['--json', '--limit'],
25
26
  coverage: ['--json', '--report', '--open'],
27
+ generate: ['--json', '--out', '--force'],
26
28
  };
27
29
  function rejectUnknownFlags(command, args) {
28
30
  const known = exports.KNOWN_FLAGS[command];
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;AAuBA,gDAQC;AA/BD,sGAAsG;AACzF,QAAA,WAAW,GAAsC;IAC5D,IAAI,EAAE;QACJ,SAAS;QACT,OAAO;QACP,aAAa;QACb,eAAe;QACf,WAAW;QACX,cAAc;QACd,cAAc;QACd,QAAQ;QACR,eAAe;QACf,qBAAqB;QACrB,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,QAAQ;KACT;IACD,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7B,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC;CAC3C,CAAC;AAEF,SAAgB,kBAAkB,CAAC,OAAe,EAAE,IAAc;IAChE,MAAM,KAAK,GAAG,mBAAW,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAChC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,yBAAyB,OAAO,kDAAkD,CAAC,CAAC;IACxH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;AAyBA,gDAQC;AAjCD,sGAAsG;AACzF,QAAA,WAAW,GAAsC;IAC5D,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;IAC7D,IAAI,EAAE;QACJ,SAAS;QACT,OAAO;QACP,aAAa;QACb,eAAe;QACf,WAAW;QACX,cAAc;QACd,cAAc;QACd,QAAQ;QACR,eAAe;QACf,qBAAqB;QACrB,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,QAAQ;KACT;IACD,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7B,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC;IAC1C,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;CACzC,CAAC;AAEF,SAAgB,kBAAkB,CAAC,OAAe,EAAE,IAAc;IAChE,MAAM,KAAK,GAAG,mBAAW,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAChC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,SAAS;QAChC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,yBAAyB,OAAO,kDAAkD,CAAC,CAAC;IACxH,CAAC;AACH,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { PageMapping } from '@ia-qa/self-healing';
2
+ /**
3
+ * `ia-qa-discover generate` — a starting suite for the pages nothing tests.
4
+ *
5
+ * **Why it lives here and not in `@ia-qa/self-healing`.** It needs both halves: the contract,
6
+ * to name elements the way healing will repair them, and the capture, to know which fields a
7
+ * page takes and which of them carry a durable identity. Discovery already depends on
8
+ * healing; the reverse would invert a publish order that exists to be enforced. So the
9
+ * package that already holds both is the one that gets the verb.
10
+ *
11
+ * **What it proposes, never applies.** Files land in their own directory and an existing one
12
+ * is never overwritten without `--force` — the same restraint as `discover --apply` and
13
+ * `heal skill`. A generated test is a proposal a human reads, and nothing here adds it to
14
+ * anyone's suite.
15
+ *
16
+ * **Default target is the gap, not the app.** With no arguments it generates for the pages
17
+ * the coverage map says nothing tests, because generating over pages already covered is how
18
+ * a suite doubles in size without covering one more thing. Named pages override that.
19
+ */
20
+ export declare const GENERATED_DIRNAME = "generated";
21
+ export declare function generatedDir(cwd?: string): string;
22
+ export declare function runGenerate(args: string[]): Promise<void>;
23
+ /**
24
+ * Whether healing would ever read what was just written.
25
+ *
26
+ * This fires on the default, and that is the point. Measured on a real project: the specs
27
+ * landed in `.ia-qa-discovery/generated/` while healing's `testPaths` was `["tests/"]`, so
28
+ * `ingest` inventoried nothing from them — no name drift would escalate, `fix` would never
29
+ * rewrite them, and "born already maintained" was simply false. The first check of it looked
30
+ * green for the wrong reason: the placeholders were in `usage.json` because the project's own
31
+ * suite already used them, and every recorded site was in `tests/`.
32
+ *
33
+ * Writing into someone's suite by default would be the other error — this verb produces
34
+ * proposals, and a proposal does not install itself. So the default stays out of the way and
35
+ * says so, with both remedies, only when it is actually out of reach.
36
+ */
37
+ export declare function healingReach(outDir: string, cwd?: string): {
38
+ covered: boolean;
39
+ why: string;
40
+ };
41
+ /**
42
+ * The contract for a captured page, by name and then by URL.
43
+ *
44
+ * The URL fallback is not belt-and-braces, it is the ordinary case on a configured project.
45
+ * Both packages resolve a page name through the same `pageNameFromUrl`, but healing's
46
+ * `config.pages` may *declare* a name, and that declaration wins there and is invisible here:
47
+ * measured on a real app, discovery captured `/` as `home` while the contract for the very
48
+ * same URL was filed as `login`. Matching on the name alone found nothing, so the generator
49
+ * fell back to the page's own placeholder text — a locator that works, but not the one the
50
+ * contract holds and therefore not one healing will rewrite. Silently producing the weaker
51
+ * form is exactly the failure this whole feature is built to avoid.
52
+ *
53
+ * A page with no contract at all is still generated, from its capture alone — thinner, and
54
+ * never fatal.
55
+ */
56
+ export declare function contractOf(name: string, url: string, mappingPath: string): PageMapping | null;
@@ -0,0 +1,293 @@
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.GENERATED_DIRNAME = void 0;
37
+ exports.generatedDir = generatedDir;
38
+ exports.runGenerate = runGenerate;
39
+ exports.healingReach = healingReach;
40
+ exports.contractOf = contractOf;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const self_healing_1 = require("@ia-qa/self-healing");
44
+ const config_1 = require("../config");
45
+ const coverage_1 = require("../coverage");
46
+ const generate_1 = require("../generate");
47
+ /** `--out <dir>`, and the remaining arguments with it removed. */
48
+ function takeValueFlag(args, flag, fallback) {
49
+ const at = args.indexOf(flag);
50
+ if (at === -1)
51
+ return { value: fallback, rest: args };
52
+ const value = args[at + 1];
53
+ if (value === undefined || value.startsWith('-')) {
54
+ throw new Error(`${flag} needs a directory, e.g. \`${flag} tests/generated\`.`);
55
+ }
56
+ return { value: path.resolve(process.cwd(), value), rest: [...args.slice(0, at), ...args.slice(at + 2)] };
57
+ }
58
+ /**
59
+ * `ia-qa-discover generate` — a starting suite for the pages nothing tests.
60
+ *
61
+ * **Why it lives here and not in `@ia-qa/self-healing`.** It needs both halves: the contract,
62
+ * to name elements the way healing will repair them, and the capture, to know which fields a
63
+ * page takes and which of them carry a durable identity. Discovery already depends on
64
+ * healing; the reverse would invert a publish order that exists to be enforced. So the
65
+ * package that already holds both is the one that gets the verb.
66
+ *
67
+ * **What it proposes, never applies.** Files land in their own directory and an existing one
68
+ * is never overwritten without `--force` — the same restraint as `discover --apply` and
69
+ * `heal skill`. A generated test is a proposal a human reads, and nothing here adds it to
70
+ * anyone's suite.
71
+ *
72
+ * **Default target is the gap, not the app.** With no arguments it generates for the pages
73
+ * the coverage map says nothing tests, because generating over pages already covered is how
74
+ * a suite doubles in size without covering one more thing. Named pages override that.
75
+ */
76
+ exports.GENERATED_DIRNAME = 'generated';
77
+ function generatedDir(cwd = (0, config_1.baseDir)()) {
78
+ return path.join(cwd, '.ia-qa-discovery', exports.GENERATED_DIRNAME);
79
+ }
80
+ async function runGenerate(args) {
81
+ const json = args.includes('--json');
82
+ const force = args.includes('--force');
83
+ const { value: outDir, rest } = takeValueFlag(args, '--out', generatedDir());
84
+ const named = rest.filter((a) => !a.startsWith('-'));
85
+ const surface = (0, coverage_1.loadSurface)((0, config_1.captureDir)());
86
+ if (!surface) {
87
+ return refuse(json, 'No capture to generate from.', ['Run `ia-qa-discover scan` first — a test cannot be written for a page nobody has looked at.']);
88
+ }
89
+ const byName = new Map(surface.pages.map((p) => [p.page, p]));
90
+ let targets;
91
+ if (named.length > 0) {
92
+ const unknown = named.filter((n) => !byName.has(n));
93
+ if (unknown.length > 0) {
94
+ return refuse(json, `Not in this capture: ${unknown.join(', ')}.`, [
95
+ `Pages captured: ${[...byName.keys()].join(', ')}`,
96
+ ]);
97
+ }
98
+ targets = named;
99
+ }
100
+ else {
101
+ const config = (() => {
102
+ try {
103
+ return (0, config_1.loadConfig)();
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ })();
109
+ const coverage = (0, coverage_1.computeCoverage)({
110
+ captureDirPath: (0, config_1.captureDir)(),
111
+ healingDirPath: path.join((0, config_1.baseDir)(), coverage_1.HEALING_DIR),
112
+ scope: config?.outOfScope,
113
+ });
114
+ if (!coverage.ok) {
115
+ // Generating for every captured page instead would bury the pages that need a test
116
+ // under the ones already covered — a bigger suite, not a better one. The refusal names
117
+ // the measurement that is missing, and the pages remain reachable by name.
118
+ return refuse(json, `Cannot tell which pages are untested: ${coverage.refusal.message}`, [
119
+ ...coverage.refusal.available,
120
+ `Or name the pages yourself: ia-qa-discover generate <page…>`,
121
+ ]);
122
+ }
123
+ targets = coverage.map.uncovered.map((u) => u.page);
124
+ if (targets.length === 0) {
125
+ return refuse(json, 'Every page this scan reached is already visited by your suite.', [
126
+ `Name a page to generate for it anyway: ia-qa-discover generate <page…>`,
127
+ ]);
128
+ }
129
+ }
130
+ const mappingPath = path.join((0, config_1.baseDir)(), coverage_1.HEALING_DIR, 'mapping');
131
+ const specs = targets.map((name) => {
132
+ const captured = byName.get(name);
133
+ return (0, generate_1.buildSpec)({ page: captured, contract: contractOf(name, captured.url, mappingPath) });
134
+ });
135
+ const written = [];
136
+ const kept = [];
137
+ fs.mkdirSync(outDir, { recursive: true });
138
+ for (const spec of specs) {
139
+ const file = path.join(outDir, `${spec.page}.spec.js`);
140
+ if (fs.existsSync(file) && !force) {
141
+ kept.push(path.relative(process.cwd(), file) || file);
142
+ continue;
143
+ }
144
+ fs.writeFileSync(file, spec.code, 'utf8');
145
+ written.push({
146
+ page: spec.page,
147
+ file: path.relative(process.cwd(), file) || file,
148
+ locators: spec.locators.length,
149
+ skipped: spec.skipped.length,
150
+ });
151
+ }
152
+ if (json) {
153
+ console.log(JSON.stringify({ written, kept, specs: specs.map(({ code, ...rest }) => rest) }, null, 2));
154
+ return;
155
+ }
156
+ console.log(`\n✍️ Generated ${written.length} spec${written.length === 1 ? '' : 's'} → ${path.relative(process.cwd(), outDir) || outDir}`);
157
+ for (const w of written) {
158
+ const skipped = w.skipped > 0 ? ` · ${w.skipped} field${w.skipped === 1 ? '' : 's'} left out` : '';
159
+ console.log(` · ${w.page} — ${w.locators} locator${w.locators === 1 ? '' : 's'}${skipped}`);
160
+ }
161
+ if (kept.length > 0) {
162
+ console.log(`\n Left untouched (already there, --force to replace):`);
163
+ for (const k of kept)
164
+ console.log(` · ${k}`);
165
+ }
166
+ const totalSkipped = specs.reduce((n, s) => n + s.skipped.length, 0);
167
+ if (totalSkipped > 0) {
168
+ console.log(`\n ${totalSkipped} field(s) were not generated — each says why at the top of its file.\n` +
169
+ ` Most often: no test id, id or name, so the only selector is positional. That is a\n` +
170
+ ` finding about the app, not about this tool: such a field cannot be tested reliably\n` +
171
+ ` by anyone, and healing could not repair it either.`);
172
+ }
173
+ const reach = healingReach(outDir);
174
+ if (written.length > 0 && !reach.covered) {
175
+ console.log(`\n ⚠ Healing cannot see these files, so it will never repair them.\n` +
176
+ ` ${reach.why}\n` +
177
+ ` The whole point of generating them this way is that a label change is REWRITTEN\n` +
178
+ ` instead of turning the suite red — and that only happens for files \`ingest\`\n` +
179
+ ` inventories. Either write them where your suite lives:\n` +
180
+ ` ia-qa-discover generate --out <a path under your testPaths>\n` +
181
+ ` or add this directory to "testPaths" in .ia-qa/config.json, then run:\n` +
182
+ ` ia-qa-heal ingest`);
183
+ }
184
+ console.log(`\n These are proposals. Nothing was added to your suite, and the assertions are yours:\n` +
185
+ ` the navigation and the actions are generated, what the app should DO is a TODO in\n` +
186
+ ` each file. An app declares what it accepts, never what it promises.`);
187
+ }
188
+ /**
189
+ * Whether healing would ever read what was just written.
190
+ *
191
+ * This fires on the default, and that is the point. Measured on a real project: the specs
192
+ * landed in `.ia-qa-discovery/generated/` while healing's `testPaths` was `["tests/"]`, so
193
+ * `ingest` inventoried nothing from them — no name drift would escalate, `fix` would never
194
+ * rewrite them, and "born already maintained" was simply false. The first check of it looked
195
+ * green for the wrong reason: the placeholders were in `usage.json` because the project's own
196
+ * suite already used them, and every recorded site was in `tests/`.
197
+ *
198
+ * Writing into someone's suite by default would be the other error — this verb produces
199
+ * proposals, and a proposal does not install itself. So the default stays out of the way and
200
+ * says so, with both remedies, only when it is actually out of reach.
201
+ */
202
+ function healingReach(outDir, cwd = (0, config_1.baseDir)()) {
203
+ let testPaths;
204
+ try {
205
+ // Healing's own resolver, never a copy of its rule: it resolves against the project root
206
+ // rather than the config directory, and getting that wrong points the check at a
207
+ // directory nobody has.
208
+ testPaths = (0, self_healing_1.configuredTestPaths)(cwd);
209
+ }
210
+ catch (err) {
211
+ return { covered: false, why: `Healing's config could not be read (${err.message}).` };
212
+ }
213
+ if (testPaths.length === 0) {
214
+ return { covered: false, why: `Healing declares no "testPaths", so \`ingest\` reads nothing.` };
215
+ }
216
+ const target = path.resolve(outDir);
217
+ const covered = testPaths.some((abs) => {
218
+ const rel = path.relative(abs, target);
219
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
220
+ });
221
+ return {
222
+ covered,
223
+ why: covered
224
+ ? ''
225
+ : `They are outside "testPaths" (${testPaths.map((p) => path.relative(cwd, p) || p).join(', ')}), which is all \`ingest\` reads.`,
226
+ };
227
+ }
228
+ /**
229
+ * The contract for a captured page, by name and then by URL.
230
+ *
231
+ * The URL fallback is not belt-and-braces, it is the ordinary case on a configured project.
232
+ * Both packages resolve a page name through the same `pageNameFromUrl`, but healing's
233
+ * `config.pages` may *declare* a name, and that declaration wins there and is invisible here:
234
+ * measured on a real app, discovery captured `/` as `home` while the contract for the very
235
+ * same URL was filed as `login`. Matching on the name alone found nothing, so the generator
236
+ * fell back to the page's own placeholder text — a locator that works, but not the one the
237
+ * contract holds and therefore not one healing will rewrite. Silently producing the weaker
238
+ * form is exactly the failure this whole feature is built to avoid.
239
+ *
240
+ * A page with no contract at all is still generated, from its capture alone — thinner, and
241
+ * never fatal.
242
+ */
243
+ function contractOf(name, url, mappingPath) {
244
+ try {
245
+ return (0, self_healing_1.loadMapping)(name, mappingPath);
246
+ }
247
+ catch {
248
+ /* not filed under this name — try the URL */
249
+ }
250
+ const target = normalizeUrl(url);
251
+ if (!target)
252
+ return null;
253
+ let files;
254
+ try {
255
+ files = fs.readdirSync(mappingPath).filter((f) => f.endsWith('.json') && !f.startsWith('_'));
256
+ }
257
+ catch {
258
+ return null;
259
+ }
260
+ for (const file of files) {
261
+ try {
262
+ const mapping = JSON.parse(fs.readFileSync(path.join(mappingPath, file), 'utf8'));
263
+ if (normalizeUrl(mapping.url) === target)
264
+ return mapping;
265
+ }
266
+ catch {
267
+ // One unreadable contract costs one candidate, never the generation.
268
+ }
269
+ }
270
+ return null;
271
+ }
272
+ /** Host and path only: a trailing slash or a query string does not make it another page. */
273
+ function normalizeUrl(raw) {
274
+ if (!raw)
275
+ return null;
276
+ try {
277
+ const u = new URL(raw);
278
+ return `${u.host.replace(/^www\./, '')}${u.pathname.replace(/\/$/, '')}`;
279
+ }
280
+ catch {
281
+ return null;
282
+ }
283
+ }
284
+ function refuse(json, message, available) {
285
+ if (json) {
286
+ console.log(JSON.stringify({ generated: false, reason: message, available }, null, 2));
287
+ return;
288
+ }
289
+ console.log(`\nℹ️ ${message}`);
290
+ for (const a of available)
291
+ console.log(`\n ${a}`);
292
+ }
293
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"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"}