@ia-qa/self-healing 1.18.0 → 1.19.1

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 (51) hide show
  1. package/README.md +98 -1
  2. package/TUTORIAL.md +58 -0
  3. package/dist/ai/models.d.ts +12 -0
  4. package/dist/ai/models.js +33 -1
  5. package/dist/ai/models.js.map +1 -1
  6. package/dist/ai/resolver.d.ts +29 -6
  7. package/dist/ai/resolver.js +42 -7
  8. package/dist/ai/resolver.js.map +1 -1
  9. package/dist/cli/args.js +2 -0
  10. package/dist/cli/args.js.map +1 -1
  11. package/dist/cli/diff.js +34 -10
  12. package/dist/cli/diff.js.map +1 -1
  13. package/dist/cli/fix.js +9 -2
  14. package/dist/cli/fix.js.map +1 -1
  15. package/dist/cli/index.js +47 -0
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/map.d.ts +15 -4
  18. package/dist/cli/map.js +66 -13
  19. package/dist/cli/map.js.map +1 -1
  20. package/dist/cli/secret.d.ts +1 -0
  21. package/dist/cli/secret.js +172 -0
  22. package/dist/cli/secret.js.map +1 -0
  23. package/dist/cli/session.d.ts +24 -0
  24. package/dist/cli/session.js +119 -0
  25. package/dist/cli/session.js.map +1 -0
  26. package/dist/cli/skill.d.ts +37 -14
  27. package/dist/cli/skill.js +36 -30
  28. package/dist/cli/skill.js.map +1 -1
  29. package/dist/config.d.ts +23 -2
  30. package/dist/config.js +50 -0
  31. package/dist/config.js.map +1 -1
  32. package/dist/index.d.ts +5 -2
  33. package/dist/index.js +11 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/secretStore.d.ts +49 -0
  36. package/dist/secretStore.js +244 -0
  37. package/dist/secretStore.js.map +1 -0
  38. package/dist/sessionCheck.d.ts +96 -0
  39. package/dist/sessionCheck.js +182 -0
  40. package/dist/sessionCheck.js.map +1 -0
  41. package/dist/unrepaired.d.ts +73 -0
  42. package/dist/unrepaired.js +0 -0
  43. package/dist/unrepaired.js.map +1 -0
  44. package/dist/volatile.d.ts +8 -0
  45. package/dist/volatile.js +24 -7
  46. package/dist/volatile.js.map +1 -1
  47. package/dist/volatileBlindSpot.d.ts +67 -0
  48. package/dist/volatileBlindSpot.js +0 -0
  49. package/dist/volatileBlindSpot.js.map +1 -0
  50. package/package.json +1 -1
  51. package/skills/ia-qa-heal/SKILL.md +29 -3
package/README.md CHANGED
@@ -65,6 +65,7 @@ results rendered, nothing written.
65
65
  | show me the app's structure | `graph --format mermaid\|svg\|json\|markdown` |
66
66
  | is this getting better or worse? | `history` |
67
67
  | let me look and decide myself | `ui` — a local console |
68
+ | where do I put my API key? | `secret set` — the OS store, so it stops living in your environment |
68
69
  | teach my AI agent to drive this | `skill` — installs the agent instructions into `.claude/skills/` |
69
70
 
70
71
  `ia-qa-heal <verb> --help` for flags. On a slow suite, note that `run` runs it **twice** (once
@@ -76,6 +77,12 @@ one of them. `ia-qa-heal-mcp` exposes `map_app`, `diff_mappings`, `fix_tests`, `
76
77
  `audit_suite`, `explain_failure`, `check_app`, `heal_history` and `suggest_heal`. `login` and
77
78
  `ui` are deliberately not tools: both wait for a person.
78
79
 
80
+ **Any provider that speaks the OpenAI API** — `openai`, `anthropic`, `google`, or
81
+ `openai-compatible` with a `baseUrl`: DeepSeek, Groq, Mistral, OpenRouter, Together, vLLM,
82
+ or Ollama on your own machine, where the call never leaves it. `ia-qa-heal-ai models` lists
83
+ the URLs. The egress notice always names the host it will really reach, and refuses to
84
+ announce anything when a compatible endpoint has no URL configured.
85
+
79
86
  **Optional, with your own key** — `ia-qa-heal-ai` (`init`, `models`, `suggest`) proposes a match
80
87
  for the rows deterministic matching gave up on. It is a suggestion a human confirms, and it
81
88
  never touches the verdict.
@@ -175,6 +182,74 @@ session", which would capture the login page under your pages' names.
175
182
  `login` needs a terminal and refuses under CI. There, use `auth` (a form fill, secrets from
176
183
  env/SSM — see **Configuration**) or capture-during-run, where your own suite logs itself in.
177
184
 
185
+ ### Where the API key lives — `ia-qa-heal secret`
186
+
187
+ A key exported in your shell is inherited by **everything you launch from it**, an AI agent
188
+ included. Measured: a spawned process read the whole 164-character key straight out of
189
+ `process.env`. Putting it in the machine's credential store stops it being ambient.
190
+
191
+ ```bash
192
+ ia-qa-heal secret set OPENAI_KEY # asks for the value; never an argument, never echoed
193
+ ia-qa-heal secret check OPENAI_KEY # does it resolve? yes or no — never the value
194
+ ia-qa-heal secret list # the names it holds
195
+ ```
196
+
197
+ Then the config holds a reference, exactly like `env`:
198
+
199
+ ```json
200
+ apiKey: { source: keychain, key: OPENAI_KEY }
201
+ ```
202
+
203
+ | | |
204
+ |---|---|
205
+ | macOS | the keychain (`security`) |
206
+ | Windows | DPAPI — encrypted for **this user account, on this machine** |
207
+ | Linux | the desktop keyring (`secret-tool`) |
208
+ | anywhere else, or no `secret-tool` | it **refuses** and points at `env` — no home-made vault |
209
+
210
+ There is deliberately no `secret get`: a verb that prints a secret puts it in a scrollback, a
211
+ log or an agent transcript, which is what this exists to avoid. `set` refuses without a
212
+ terminal — a person types the value, an agent cannot do it for them. **In CI keep `env`**:
213
+ there is no store and no person there, and the runner already holds the secret.
214
+
215
+ **What it does not do**, said plainly: it is not a barrier against an agent that decides to
216
+ read the key — it can run the same OS command. What changes is that the value stops being
217
+ ambient, so obtaining it becomes an explicit, visible act instead of an inheritance.
218
+
219
+ ### Is the session still good? — `ia-qa-heal session --check`
220
+
221
+ A wall has three possible causes, and "expired, rotated, or never covering this domain" is a
222
+ list, not an answer. One of them means *log in again*; another means your `baseUrl` and your
223
+ session are about **different applications**, which logging in will never fix.
224
+
225
+ ```bash
226
+ npx ia-qa-heal session --check # 0 it holds · 1 it does not · 2 could not tell
227
+ npx ia-qa-heal session --check --offline # answer from the file alone, open nothing
228
+ ```
229
+
230
+ **Two of the three need no browser**, because a cookie carries its own expiry and its own
231
+ domain:
232
+
233
+ ```
234
+ 🔑 .ia-qa/session.json
235
+ 1 cookie, 0 origins with local storage · staging.other.test
236
+ First cookie expires in 24 hours
237
+
238
+ ❌ Nothing in this session is scoped to app.example.com — its cookies are for staging.other.test.
239
+ The session and the baseUrl are about different applications, so logging in again will
240
+ produce the same file.
241
+ ```
242
+
243
+ So the browser opens only for the question a request is the only witness to: the file is
244
+ valid, correctly scoped and unexpired, and the app answers with a login anyway — the server
245
+ dropped it. A navigation that fails is reported as **could not tell** (exit 2), never as a
246
+ dead session: that distinction is the whole point of having the verb.
247
+
248
+ Run it before a long `map`. And **`map` itself now stops at the first login wall when a
249
+ session is in use** — a session is one credential for the whole app, so walking the remaining
250
+ pages into the same wall only spends the run re-proving it. The pages it did not attempt keep
251
+ their previous contracts and read `stale` in the next diff: not measured, not unchanged.
252
+
178
253
  ### Start from the failure — `ia-qa-heal explain`
179
254
 
180
255
  Every other verb starts from a contract. You start from a red build.
@@ -560,7 +635,7 @@ Everything else is optional:
560
635
  |---|---|
561
636
  | `session` | a Playwright `storageState` to reuse instead of logging in |
562
637
  | `locale` | accessible names are language-dependent — set it if your app is not the system default |
563
- | `volatile` | content that rotates by design (feed links, promos). Never enters a contract, so churn cannot read as drift |
638
+ | `volatile` | content that rotates by design (feed links, promos). Never enters a contract, so churn cannot read as drift — and `map` names any excluded element your tests still use, with `file:line` (see below) |
564
639
  | `nameMask` | labels carrying a counter or a clock (`"Cart (*)"`). Only the **label** stops being compared; role, selector and href still gate |
565
640
  | `layouts` / `autoLayout` | shared shell extracted to `_layouts/`, diffed once instead of per page |
566
641
  | `ai` | the BYOK add-on (see below) |
@@ -569,6 +644,28 @@ Everything else is optional:
569
644
  monorepo. Every field is documented in full in the tutorial
570
645
  (`TUTORIAL.md`, shipped in this package).
571
646
 
647
+ ### When a declaration hides something your tests use
648
+
649
+ `volatile` is the most destructive thing you can declare: a matching element never enters a
650
+ contract at all, so **nothing will ever report it moving**. That is correct for a rotating
651
+ feed item and a permanent blind spot for anything else — and a count (`40 volatile excluded`)
652
+ cannot tell the two apart.
653
+
654
+ So `map` crosses its own exclusions with the locator inventory `ingest` wrote:
655
+
656
+ ```
657
+ ⚠ 1 element excluded by "volatile" is referenced by your tests:
658
+ button "Save" — excluded by `name:Save`, located by name
659
+ pom/MiniCartHeader.ts:14
660
+ A volatile element never enters a contract, so you will NEVER be told when one of
661
+ these moves, is renamed or disappears — the gate stays green and the test goes red.
662
+ ```
663
+
664
+ It is silent when nothing overlaps, and — deliberately — it does **not** claim your tests are
665
+ safe when there is no `usage.json`: with no inventory it says the overlap was *not measured*,
666
+ which is a different sentence from *none*. Nothing is refused; the exclusion may be exactly
667
+ what you wanted. The line exists so that it is a decision rather than a surprise.
668
+
572
669
  ## The console — `ia-qa-heal ui`
573
670
 
574
671
  [![The ia-qa-heal console: a BLOCK verdict, the one element the tool refused to guess, the verbs as buttons, the history as charts](https://www.ia-qa.com/media/heal-ui-poster.png)](https://www.ia-qa.com/media/heal-ui.mp4)
package/TUTORIAL.md CHANGED
@@ -308,6 +308,33 @@ for a person — twice: at the browser, then at the keyboard), and it is **not a
308
308
  pipeline, use `auth` (secrets from env/SSM) or capture-during-run (Step 6.7), where your own suite
309
309
  logs itself in. An AI agent driving the CLI cannot perform this step — it will hand it to you.
310
310
 
311
+ ### Step 5.2a-bis — "It says login wall. But I *did* log in." — `session --check`
312
+
313
+ Before you log in again, find out whether that would help. A session can fail three ways, and
314
+ only one of them is fixed by logging in:
315
+
316
+ ```bash
317
+ ia-qa-heal session --check
318
+ ```
319
+
320
+ | What it says | What it means | What to do |
321
+ |---|---|---|
322
+ | `expired` | every cookie's date is in the past | log in again — nothing is wrong with your setup |
323
+ | `wrong-host` | nothing in the file is scoped to your `baseUrl` | **logging in again produces the identical file.** Your session and your `baseUrl` are about different applications — fix one of them |
324
+ | `rotated` | the file is valid and the app still answers a login | the server dropped it: a deploy, a rotation, a forced logout. Log in again |
325
+ | *could not tell* (exit 2) | the app could not be opened | a fact about the network, not about your session |
326
+
327
+ **The first two need no browser at all** — a cookie carries its own expiry and its own domain,
328
+ so the answer is already in the file. Add `--offline` to stay entirely local. `www.` and the
329
+ apex count as one host, and the port is ignored, so `localhost:3000` is never mistaken for
330
+ another app.
331
+
332
+ One consequence worth knowing: when a session is in use, `map` now **stops at the first login
333
+ wall** instead of walking every remaining page into it. A session is one credential for the
334
+ whole app — the second page would only re-prove what the first showed. You will see `N of M
335
+ pages mapped`, and the pages it did not attempt keep their previous contracts: `stale` in the
336
+ next diff, which means *not measured*, never *unchanged*.
337
+
311
338
 
312
339
 
313
340
  ### Step 5.2b — (optional) Find the pages you're *not* testing: `discover`
@@ -545,6 +572,20 @@ npx ia-qa-heal fix .ia-qa/baseline/checkout.json .ia-qa/mapping/checkout.json te
545
572
  npx ia-qa-heal fix .ia-qa/baseline/checkout.json .ia-qa/mapping/checkout.json tests/
546
573
  ```
547
574
 
575
+ **If it repairs nothing, read which of three sentences it printed** — they are not the same
576
+ news:
577
+
578
+ | What it says | What it means |
579
+ |---|---|
580
+ | "…and your tests reference none of it" | it looked, and your suite does not use these elements |
581
+ | "…**but your tests DO reference** N of these elements" | each one is listed with `file:line` and **why** it could not be repaired — two candidates share the name, the element is gone, the selector now reaches a different element. These need you; the tool can say what changed, not which element you meant |
582
+ | "Whether your tests reference any of these is **NOT measured**" | there is no `usage.json`. Run `ia-qa-heal ingest` and this becomes one of the two answers above |
583
+
584
+ The middle one is the case that used to be reported as the first — "no test file referenced
585
+ any of the drifted selectors", printed over a Page Object that contained the selector
586
+ verbatim. Absence of evidence is not evidence of absence, and the three states exist so the
587
+ two can never be confused again.
588
+
548
589
  ### Step 6.5b — Stop fixing the same test twice (`--locators`)
549
590
 
550
591
  A repaired `nth-of-type(2)` is still an `nth-of-type(2)`: correct today, and wrong again the day someone inserts a button above it. If your suite is Playwright in `.js`/`.ts`, add `--locators`:
@@ -906,6 +947,23 @@ Two things it refuses to do, out loud:
906
947
 
907
948
  Rule of thumb: **`nameMask` when the label rotates, `volatile` when the element does.**
908
949
 
950
+ **And `map` tells you when a `volatile` pattern is hiding something your tests use.** The
951
+ pattern you write to silence a feed can match more than you meant — the element leaves the
952
+ contract completely, so nothing will ever report it moving again. `map` crosses its own
953
+ exclusions with the locators `ingest` inventoried and names the overlap:
954
+
955
+ ```
956
+ ⚠ 1 element excluded by "volatile" is referenced by your tests:
957
+ button "Save" — excluded by `name:Save`, located by name
958
+ pom/MiniCartHeader.ts:14
959
+ A volatile element never enters a contract, so you will NEVER be told when one of
960
+ these moves, is renamed or disappears — the gate stays green and the test goes red.
961
+ ```
962
+
963
+ Nothing is refused: the exclusion may be exactly what you wanted, and the message says so.
964
+ It is silent when nothing overlaps — and when you have never run `ingest`, it says the
965
+ overlap was **not measured** rather than pretending it found none.
966
+
909
967
  ---
910
968
 
911
969
  ## 11. FAQ
@@ -20,8 +20,20 @@ export interface AiProviderInfo {
20
20
  /** Default env var the picker suggests for this provider's key (BYOK). */
21
21
  keyEnv: string;
22
22
  models: AiModelInfo[];
23
+ /**
24
+ * This provider has no fixed host: the project says where it lives (`ai.baseUrl`).
25
+ *
26
+ * The picker and every caller branch on this rather than on the id, so a second
27
+ * configurable provider needs no second special case.
28
+ */
29
+ needsBaseUrl?: true;
23
30
  }
24
31
  export declare const AI_PROVIDERS: AiProviderInfo[];
32
+ /** The URL each well-known compatible endpoint serves — a hint for a picker, never a default. */
33
+ export declare const COMPATIBLE_EXAMPLES: Array<{
34
+ label: string;
35
+ baseUrl: string;
36
+ }>;
25
37
  export declare function findProvider(id: string): AiProviderInfo | undefined;
26
38
  /** Default env var name for a provider's key (falls back to a generic name). */
27
39
  export declare function defaultKeyEnv(provider: AiProvider): string;
package/dist/ai/models.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AI_PROVIDERS = void 0;
3
+ exports.COMPATIBLE_EXAMPLES = exports.AI_PROVIDERS = void 0;
4
4
  exports.findProvider = findProvider;
5
5
  exports.defaultKeyEnv = defaultKeyEnv;
6
6
  exports.renderModelList = renderModelList;
@@ -42,6 +42,30 @@ exports.AI_PROVIDERS = [
42
42
  { id: 'gemini-1.5-pro', label: 'Gemini 1.5 Pro' },
43
43
  ],
44
44
  },
45
+ {
46
+ // A shape, not a vendor. DeepSeek, Groq, Mistral, OpenRouter, Together, vLLM and Ollama
47
+ // all serve `/v1/chat/completions`, so one entry reaches every one of them — and a model
48
+ // running on the user's own machine, where nothing leaves it at all.
49
+ //
50
+ // No model list on purpose: this endpoint's catalogue belongs to whoever runs it, and a
51
+ // list here would be wrong for most of them. The user pins the id, as they already can
52
+ // for the other three.
53
+ id: 'openai-compatible',
54
+ label: 'OpenAI-compatible endpoint (DeepSeek, Groq, Mistral, OpenRouter, Ollama, vLLM…)',
55
+ keyEnv: 'LLM_API_KEY',
56
+ needsBaseUrl: true,
57
+ models: [],
58
+ },
59
+ ];
60
+ /** The URL each well-known compatible endpoint serves — a hint for a picker, never a default. */
61
+ exports.COMPATIBLE_EXAMPLES = [
62
+ { label: 'DeepSeek', baseUrl: 'https://api.deepseek.com/v1' },
63
+ { label: 'Groq', baseUrl: 'https://api.groq.com/openai/v1' },
64
+ { label: 'Mistral', baseUrl: 'https://api.mistral.ai/v1' },
65
+ { label: 'OpenRouter', baseUrl: 'https://openrouter.ai/api/v1' },
66
+ { label: 'Together', baseUrl: 'https://api.together.xyz/v1' },
67
+ { label: 'Ollama (on this machine)', baseUrl: 'http://localhost:11434/v1' },
68
+ { label: 'vLLM (on this machine)', baseUrl: 'http://localhost:8000/v1' },
45
69
  ];
46
70
  function findProvider(id) {
47
71
  return exports.AI_PROVIDERS.find((p) => p.id === id);
@@ -58,6 +82,14 @@ function renderModelList() {
58
82
  for (const m of p.models) {
59
83
  lines.push(` - ${m.id}${m.note ? ` — ${m.note}` : ''}`);
60
84
  }
85
+ if (p.needsBaseUrl) {
86
+ // An empty model list would otherwise read as "nothing supported here". What this
87
+ // provider needs is the URL, and the models are whatever that endpoint serves.
88
+ lines.push(' needs "baseUrl" — the endpoint decides the models, not this list:');
89
+ for (const e of exports.COMPATIBLE_EXAMPLES)
90
+ lines.push(` - ${e.label.padEnd(26)} ${e.baseUrl}`);
91
+ lines.push(' A localhost URL means the call never leaves this machine.');
92
+ }
61
93
  lines.push('');
62
94
  }
63
95
  return lines.join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/ai/models.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/ai/models.ts"],"names":[],"mappings":"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"}
@@ -32,16 +32,37 @@ export interface AiResolveResult {
32
32
  confidence: number;
33
33
  candidateIndex: number;
34
34
  }
35
- export type AiProvider = 'anthropic' | 'openai' | 'google';
35
+ /**
36
+ * `openai-compatible` is the fourth, and it is a *shape*, not a vendor: DeepSeek, Groq,
37
+ * Mistral, OpenRouter, Together, vLLM and Ollama all speak `/v1/chat/completions`. One entry
38
+ * opens the layer to every one of them — and to a model running on the user's own machine,
39
+ * which for a tool that calls itself local-first is not a detail.
40
+ */
41
+ export type AiProvider = 'anthropic' | 'openai' | 'google' | 'openai-compatible';
36
42
  /**
37
43
  * Where each provider's request actually goes.
38
44
  *
39
- * Exported because the CLI must NAME the host before it sends anything — the
40
- * announcement and the request have to read the same constant. Two lists would be
41
- * a fourth transcription surface, and the one that drifts is the announcement:
42
- * a notice naming a host the code no longer calls is worse than no notice at all.
45
+ * Exported because the CLI must NAME the host before it sends anything — the announcement and
46
+ * the request have to read the same source. Two lists would be another transcription surface,
47
+ * and the one that drifts is the announcement: a notice naming a host the code no longer calls
48
+ * is worse than no notice at all.
49
+ *
50
+ * `null` means *the project configures it*, and it is deliberately not an empty string: every
51
+ * reader has to handle the case rather than concatenate nothing. `Record<AiProvider, …>` still
52
+ * makes a new provider a compile error, which is the guarantee this constant exists for —
53
+ * `egressHost` below is what keeps it once the host stops being a constant.
54
+ */
55
+ export declare const PROVIDER_HOST: Record<AiProvider, string | null>;
56
+ /**
57
+ * The host this call will really reach — refusing rather than guessing.
58
+ *
59
+ * The compile-time guarantee used to be "every provider has a stated host". With a
60
+ * configurable one it becomes "every call has a stated host, or it does not happen": a
61
+ * provider that needs a `baseUrl` and was given none throws here, *before* any request and
62
+ * before any announcement. An egress notice that printed `undefined` would be worse than
63
+ * none, because it would read as a checked fact.
43
64
  */
44
- export declare const PROVIDER_HOST: Record<AiProvider, string>;
65
+ export declare function egressHost(provider: AiProvider, baseUrl?: string): string;
45
66
  export interface AiResolveOptions {
46
67
  provider: AiProvider;
47
68
  /** Pinned model id (determinism). */
@@ -54,6 +75,8 @@ export interface AiResolveOptions {
54
75
  topN?: number;
55
76
  /** Abort the request after this many ms. Default 15000. */
56
77
  timeoutMs?: number;
78
+ /** Required for `openai-compatible`: where that endpoint lives (e.g. `https://api.deepseek.com/v1`). */
79
+ baseUrl?: string;
57
80
  /** Pinned to 0 by default. */
58
81
  temperature?: number;
59
82
  /** Injected in tests so no real network is hit. Defaults to global fetch. */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROVIDER_HOST = void 0;
4
+ exports.egressHost = egressHost;
4
5
  exports.aiResolve = aiResolve;
5
6
  exports.prefilter = prefilter;
6
7
  exports.buildPrompt = buildPrompt;
@@ -9,16 +10,46 @@ const match_1 = require("../browser/match");
9
10
  /**
10
11
  * Where each provider's request actually goes.
11
12
  *
12
- * Exported because the CLI must NAME the host before it sends anything — the
13
- * announcement and the request have to read the same constant. Two lists would be
14
- * a fourth transcription surface, and the one that drifts is the announcement:
15
- * a notice naming a host the code no longer calls is worse than no notice at all.
13
+ * Exported because the CLI must NAME the host before it sends anything — the announcement and
14
+ * the request have to read the same source. Two lists would be another transcription surface,
15
+ * and the one that drifts is the announcement: a notice naming a host the code no longer calls
16
+ * is worse than no notice at all.
17
+ *
18
+ * `null` means *the project configures it*, and it is deliberately not an empty string: every
19
+ * reader has to handle the case rather than concatenate nothing. `Record<AiProvider, …>` still
20
+ * makes a new provider a compile error, which is the guarantee this constant exists for —
21
+ * `egressHost` below is what keeps it once the host stops being a constant.
16
22
  */
17
23
  exports.PROVIDER_HOST = {
18
24
  anthropic: 'api.anthropic.com',
19
25
  openai: 'api.openai.com',
20
26
  google: 'generativelanguage.googleapis.com',
27
+ 'openai-compatible': null,
21
28
  };
29
+ /**
30
+ * The host this call will really reach — refusing rather than guessing.
31
+ *
32
+ * The compile-time guarantee used to be "every provider has a stated host". With a
33
+ * configurable one it becomes "every call has a stated host, or it does not happen": a
34
+ * provider that needs a `baseUrl` and was given none throws here, *before* any request and
35
+ * before any announcement. An egress notice that printed `undefined` would be worse than
36
+ * none, because it would read as a checked fact.
37
+ */
38
+ function egressHost(provider, baseUrl) {
39
+ const fixed = exports.PROVIDER_HOST[provider];
40
+ if (fixed)
41
+ return fixed;
42
+ if (!baseUrl) {
43
+ throw new Error(`Provider "${provider}" has no fixed host: it needs "baseUrl" in the ai config, ` +
44
+ `e.g. "https://api.deepseek.com/v1" or "http://localhost:11434/v1".`);
45
+ }
46
+ try {
47
+ return new URL(baseUrl).host;
48
+ }
49
+ catch {
50
+ throw new Error(`ai.baseUrl is not a URL: ${baseUrl}`);
51
+ }
52
+ }
22
53
  const DEFAULTS = { minConfidence: 0.7, topN: 15, timeoutMs: 15000, temperature: 0 };
23
54
  /**
24
55
  * Resolve a broken `target` to one of the live `candidates`, or null.
@@ -121,7 +152,7 @@ async function callModel(prompt, opts) {
121
152
  }
122
153
  /** One hardened round-trip. Returns the Response (even non-2xx, so the caller can see 400), or null on network/timeout. */
123
154
  async function attempt(fetchFn, opts, prompt, temperature, timeoutMs) {
124
- const req = buildRequest(opts.provider, opts.model, opts.apiKey, prompt, temperature);
155
+ const req = buildRequest(opts.provider, opts.model, opts.apiKey, prompt, temperature, opts.baseUrl);
125
156
  const controller = new AbortController();
126
157
  const timer = setTimeout(() => controller.abort(), timeoutMs);
127
158
  try {
@@ -134,7 +165,7 @@ async function attempt(fetchFn, opts, prompt, temperature, timeoutMs) {
134
165
  clearTimeout(timer);
135
166
  }
136
167
  }
137
- function buildRequest(provider, model, apiKey, prompt, temperature) {
168
+ function buildRequest(provider, model, apiKey, prompt, temperature, baseUrl) {
138
169
  if (provider === 'anthropic') {
139
170
  const body = { model, max_tokens: 512, messages: [{ role: 'user', content: prompt }] };
140
171
  if (temperature !== undefined)
@@ -160,11 +191,15 @@ function buildRequest(provider, model, apiKey, prompt, temperature) {
160
191
  if (temperature !== undefined)
161
192
  body.temperature = temperature;
162
193
  return {
163
- url: `https://${exports.PROVIDER_HOST.openai}/v1/chat/completions`,
194
+ // The same shape serves OpenAI and every compatible endpoint. `baseUrl` is taken as
195
+ // given — trailing slash trimmed and nothing else invented — because a gateway that
196
+ // does not end in `/v1` is a real configuration, not a mistake to correct.
197
+ url: provider === 'openai-compatible' ? `${trimSlash(baseUrl)}/chat/completions` : `https://${exports.PROVIDER_HOST.openai}/v1/chat/completions`,
164
198
  headers: { 'content-type': 'application/json', authorization: `Bearer ${apiKey}` },
165
199
  body,
166
200
  };
167
201
  }
202
+ const trimSlash = (u) => u.replace(/\/+$/, '');
168
203
  function extractText(provider, data) {
169
204
  if (provider === 'anthropic') {
170
205
  const block = Array.isArray(data?.content) ? data.content.find((b) => b?.type === 'text') : null;
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/ai/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/ai/resolver.ts"],"names":[],"mappings":"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"}
package/dist/cli/args.js CHANGED
@@ -18,6 +18,8 @@ exports.KNOWN_FLAGS = {
18
18
  init: ['--yes', '--base-url', '--pages', '--discover', '--tests', '--test-command', '--bootstrap'],
19
19
  discover: ['--sitemap', '--crawl', '--no-reveal', '--strict-host', '--apply', '--max', '--depth', '--session'],
20
20
  login: ['--url', '--session'],
21
+ secret: ['--json'],
22
+ session: ['--check', '--offline', '--url', '--session', '--json'],
21
23
  map: ['--screenshots', '--session', '--deep', '--depth', '--deep-budget'],
22
24
  baseline: ['--dry-run'],
23
25
  diff: ['--strict', '--json', '--junit', '--dir', '--report', '--open'],
@@ -1 +1 @@
1
- {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;AAgCA,gDAeC;AA/CD;;;;;;;;;;;GAWG;AACU,QAAA,WAAW,GAAsC;IAC5D,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAClG,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC;IAC9G,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7B,GAAG,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC;IACzE,QAAQ,EAAE,CAAC,WAAW,CAAC;IACvB,IAAI,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC;IACtE,GAAG,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC;IACnD,MAAM,EAAE,CAAC,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC7B,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAC;IACvD,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,CAAC;IAC3D,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;IAChD,GAAG,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACtF,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;IAC7D,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9B,YAAY,EAAE,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC;CACnF,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,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,eAAe,OAAO,0FAA0F;gBAC9G,4GAA4G;gBAC5G,8FAA8F,CACjG,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,qBAAqB,OAAO,8CAA8C,CAAC,CAAC;IAChH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":";;;AAkCA,gDAeC;AAjDD;;;;;;;;;;;GAWG;AACU,QAAA,WAAW,GAAsC;IAC5D,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,CAAC;IAClG,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC;IAC9G,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IAC7B,MAAM,EAAE,CAAC,QAAQ,CAAC;IAClB,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC;IACjE,GAAG,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC;IACzE,QAAQ,EAAE,CAAC,WAAW,CAAC;IACvB,IAAI,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC;IACtE,GAAG,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC;IACnD,MAAM,EAAE,CAAC,QAAQ,CAAC;IAClB,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC7B,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAC;IACvD,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,CAAC;IAC3D,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;IAChD,GAAG,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACtF,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;IAC7D,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC9B,YAAY,EAAE,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC;CACnF,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,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,eAAe,OAAO,0FAA0F;gBAC9G,4GAA4G;gBAC5G,8FAA8F,CACjG,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,qBAAqB,OAAO,8CAA8C,CAAC,CAAC;IAChH,CAAC;AACH,CAAC"}
package/dist/cli/diff.js CHANGED
@@ -596,17 +596,41 @@ function printSystemic(outcome) {
596
596
  ` the state it was read under did. The elements stay in the contract.`);
597
597
  return;
598
598
  }
599
- // Still red, and the reader has to arbitrate. Both causes are named because the
600
- // rows cannot tell them apart, and saying only one would be a guess wearing a
601
- // verdict's clothes.
602
- console.log(outcome.state === 'unknown'
603
- ? `\n Still in the verdict the baseline predates capture-state fingerprints, so\n` +
604
- ` "your app removed these" and "these captures ran in different browser state"\n` +
605
- ` cannot be told apart here. Two ways out:\n` +
606
- ` · they really are gone → fix or delete the tests that name them\n` +
607
- ` · a banner/flag/tour differs → re-map and re-baseline; the next diff can tell`
599
+ // The conclusion has to follow the DIRECTION of the groups.
600
+ //
601
+ // It did not, and a real tour caught it: six `contentinfo`/`navigation`/footer-heading
602
+ // groups came back **new on 142/142 pages**, and the block told the reader "the app itself
603
+ // no longer renders these. Fix or delete the tests that name them." Backwards, and
604
+ // destructive it advises deleting tests over elements that just appeared. The per-group
605
+ // lines said `new on` correctly; only the paragraph under them was written for one case.
606
+ const added = outcome.groups.filter((g) => g.kind === 'added').length;
607
+ const lost = outcome.groups.length - added;
608
+ const allAdded = lost === 0;
609
+ if (outcome.state === 'unknown') {
610
+ console.log(`\n Still in the verdict — the baseline predates capture-state fingerprints, so\n` +
611
+ ` "the app changed" and "these captures ran in different browser state" cannot be\n` +
612
+ ` told apart here. Two ways out:\n` +
613
+ (allAdded
614
+ ? ` · the app really added them → re-baseline, then the next diff is clean\n` +
615
+ ` · a banner/flag/tour differs → re-map and re-baseline; the next diff can tell`
616
+ : ` · they really are gone → fix or delete the tests that name them\n` +
617
+ ` · a banner/flag/tour differs → re-map and re-baseline; the next diff can tell`));
618
+ return;
619
+ }
620
+ console.log(allAdded
621
+ ? `\n Still in the verdict — both captures ran under the same browser state, so these\n` +
622
+ ` elements are genuinely on every page now and were on none before. An element\n` +
623
+ ` appearing everywhere at once is usually a shared shell (a nav, a footer) that\n` +
624
+ ` the baseline predates — including a baseline captured before this tool started\n` +
625
+ ` contracting headings, landmarks and live regions. Nothing in your tests is\n` +
626
+ ` broken by it: re-baseline once and the next diff is clean.\n` +
627
+ ` npx -p @ia-qa/pal ia-qa-pal rebaseline --all (preview; --yes applies)`
608
628
  : `\n Still in the verdict — both captures ran under the same browser state, so the\n` +
609
- ` app itself no longer renders these. Fix or delete the tests that name them.`);
629
+ ` app itself no longer renders these. Fix or delete the tests that name them.` +
630
+ (added > 0
631
+ ? `\n (${added} of these groups APPEARED rather than disappeared — those need a\n` +
632
+ ` re-baseline, not a test edit.)`
633
+ : ''));
610
634
  }
611
635
  function printNameMasks(outcome) {
612
636
  if (!outcome)