@ia-qa/self-healing 1.25.0 → 1.27.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.
package/README.md CHANGED
@@ -152,7 +152,16 @@ npx ia-qa-heal login # opens a real browser; you log in however the app asks
152
152
  npx ia-qa-heal map # reuses that session
153
153
  ```
154
154
 
155
- **The session is checked before it is saved.** Once you say you are logged in, `login` reopens
155
+ **Nothing to confirm in the terminal.** `login` watches the window and finishes by itself the
156
+ moment the session it carries genuinely opens the app — "press Enter when you are done" was
157
+ the last place this verb took somebody's word for a fact about the world, and it mostly went
158
+ unanswered while the person got on with their day. What counts as done is a definition rather
159
+ than a guess: a clean browser carrying only the captured session has to reach somewhere the
160
+ logged-out one could not, so a magic-link login page with no password field on it is never
161
+ mistaken for success. `--wait 0` restores the press-Enter flow for an app whose login cannot
162
+ be observed from outside; `--wait <seconds>` changes how long to watch.
163
+
164
+ **The session is checked before it is saved.** `login` reopens
156
165
  the same page in a clean browser carrying nothing but the captured session. Only a session that
157
166
  lands on the app is saved and reported as good. A session that carries nothing is **not
158
167
  written at all** — it could log nobody in, and writing it would replace a session that worked.
package/TUTORIAL.md CHANGED
@@ -278,9 +278,23 @@ npx ia-qa-heal login # a real browser window opens at your first configured
278
278
  npx ia-qa-heal map # reuses that session; no "auth" block needed
279
279
  ```
280
280
 
281
- **It checks the session before saving it, and tells you which file now holds what.** When you
282
- say you are logged in, the session is replayed in a clean browser: same page, nothing but the
283
- captured cookies and local storage.
281
+ **You do not have to come back and confirm anything.** The window is watched: the moment the
282
+ session it carries genuinely opens the app, it is saved and the command finishes on its own.
283
+ That replaces "press Enter when you are done", which was the last place this verb took a
284
+ human's word for a fact about the world — and which failed in the most ordinary way there is,
285
+ by being left unanswered while the person went back to work.
286
+
287
+ What counts as done is a definition, not a guess: **a clean browser carrying only the captured
288
+ session has to reach somewhere the logged-out one could not.** Reading "no password field on
289
+ screen" as success instead would call a magic-link or passkey login page a finished login.
290
+
291
+ If your app's login cannot be seen from the outside at all, `--wait 0` restores the plain
292
+ press-Enter flow, and `--wait <seconds>` sets how long to watch (default 10 minutes). Running
293
+ out of time is **not** a refusal: whatever the browser holds is checked and reported anyway.
294
+
295
+ **It checks the session before saving it, and tells you which file now holds what.** The
296
+ session is replayed in a clean browser: same page, nothing but the captured cookies and local
297
+ storage.
284
298
 
285
299
  | what the replay shows | what happens | exit |
286
300
  |---|---|---|
@@ -304,7 +318,7 @@ rather than quietly mapping the login page under your dashboard's name.
304
318
  playwright/.auth/user.json` (or `IAQA_SESSION=…`, or `"session"` in `.ia-qa/config.json`).
305
319
 
306
320
  Two things it deliberately will not do: it **refuses without a terminal and under CI** (it waits
307
- for a person — twice: at the browser, then at the keyboard), and it is **not a CI mechanism**. In a
321
+ for a person at a browser), and it is **not a CI mechanism**. In a
308
322
  pipeline, use `auth` (secrets from env/SSM) or capture-during-run (Step 6.7), where your own suite
309
323
  logs itself in. An AI agent driving the CLI cannot perform this step — it will hand it to you.
310
324
 
package/dist/cli/args.js CHANGED
@@ -17,7 +17,7 @@ exports.rejectUnknownFlags = rejectUnknownFlags;
17
17
  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
- login: ['--url', '--session'],
20
+ login: ['--url', '--session', '--wait'],
21
21
  secret: ['--json'],
22
22
  session: ['--check', '--offline', '--url', '--session', '--json'],
23
23
  map: ['--screenshots', '--session', '--deep', '--depth', '--deep-budget', '--fix-redirects'],
@@ -1 +1 @@
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,EAAE,iBAAiB,CAAC;IAC5F,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,EAAE,QAAQ,CAAC;IACvC,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,EAAE,iBAAiB,CAAC;IAC5F,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,4 +1,4 @@
1
- import type { Browser } from 'playwright';
1
+ import type { Browser, BrowserContext, Page } from 'playwright';
2
2
  /**
3
3
  * `ia-qa-heal login` — open a browser, let a human log in, keep the session.
4
4
  *
@@ -26,7 +26,56 @@ import type { Browser } from 'playwright';
26
26
  * with your own suite's login) remain the two paths. A saved session is a local artefact
27
27
  * with a shelf life — when it expires, `map` hits the wall again and says to re-run this.
28
28
  */
29
- export declare function runLogin(args: string[]): Promise<void>;
29
+ /**
30
+ * What the verb achieved, for a caller that is not a shell.
31
+ *
32
+ * `ok` is the same thing the exit code says — a session that was **replayed** and opened the
33
+ * app — so an orchestrator cannot read success more loosely than the terminal does. The exit
34
+ * code is still set, because this is a CLI verb first.
35
+ */
36
+ export interface LoginResult {
37
+ ok: boolean;
38
+ /** Where the session was written, when anything was written at all. */
39
+ file?: string;
40
+ }
41
+ export declare function runLogin(args: string[]): Promise<LoginResult>;
42
+ /**
43
+ * The login itself: open a window, watch it, prove the session, write it — once, for every
44
+ * package that has a login wall.
45
+ *
46
+ * **Why this is shared rather than reimplemented**, which is the whole point of the export.
47
+ * `@ia-qa/qa-discovery` had its own 167-line twin, and it was this verb *before* its two
48
+ * corrections: it asked "Logged in? press Enter", then called `storageState({ path })`,
49
+ * which writes before anything is checked, and printed `✅ Session saved — N cookies`. Both
50
+ * defects are recorded in this repo as fixed, and both were live in the sibling — including
51
+ * the one that overwrites a session that worked with an empty one, for an app whose token a
52
+ * session file cannot hold. Its comment even argued the case: *"saved as-is, on the human's
53
+ * word … claiming otherwise would be the false green"*, which is the reasoning this verb had
54
+ * to invert. A doctrine repaired in one copy and left in the other is not a doctrine.
55
+ *
56
+ * The packages stay separate — that was measured and it holds. What must not be duplicated
57
+ * is the question "does this session open the app", because it is the *same* question on
58
+ * both sides, unlike the narrower jobs their other same-named files do. Same shape as
59
+ * `createSkillVerb`: one implementation, parameterised by the caller's paths and name.
60
+ *
61
+ * Everything the doctrine requires is in here rather than in the wrappers, so neither caller
62
+ * can forget it: the secret's path announced **before** the browser opens, the confirm, the
63
+ * watch, the replay, and a write that only ever happens through `sessionDecision`.
64
+ */
65
+ export interface PerformLoginOptions {
66
+ /** How the caller is invoked, for the messages: `ia-qa-heal login`. */
67
+ verb: string;
68
+ /** The page to open — where an unauthenticated browser lands is what a login must beat. */
69
+ target: string;
70
+ /** Where a proven session is written. */
71
+ file: string;
72
+ /** The gitignore this package keeps, named in the announcement. */
73
+ gitignore: string;
74
+ writeGitignore: () => void;
75
+ contextOptions?: Record<string, unknown>;
76
+ waitSeconds?: number;
77
+ }
78
+ export declare function performLogin(opts: PerformLoginOptions): Promise<LoginResult>;
30
79
  export interface SessionReplay {
31
80
  landed: string;
32
81
  wall: boolean;
@@ -58,6 +107,78 @@ export interface SessionReplay {
58
107
  * says nothing when the browser is not even on the app any more.
59
108
  */
60
109
  export declare function replaySession(browser: Browser, state: Awaited<ReturnType<Awaited<ReturnType<Browser['newContext']>>['storageState']>>, target: string, contextOptions?: Record<string, unknown>): Promise<SessionReplay>;
110
+ /** Why the watch stopped. Only `verified` means the session was proven from a clean context. */
111
+ export type LoginEnd = 'verified' | 'confirmed' | 'closed' | 'timeout';
112
+ export interface LoginWatch {
113
+ end: LoginEnd;
114
+ /** The verification that ended the watch, when one did. */
115
+ replay?: SessionReplay;
116
+ /**
117
+ * The state that `replay` was taken from — never a later one.
118
+ *
119
+ * They travel together because they must: verifying state S1 and then writing an S2 taken
120
+ * a moment later reports a proof about a file that was never the file. That is this
121
+ * verb's own bug in a new place, and the pair makes it unrepresentable.
122
+ */
123
+ state?: Awaited<ReturnType<BrowserContext['storageState']>>;
124
+ }
125
+ /**
126
+ * Is this state, replayed in a clean context, evidence that somebody logged in?
127
+ *
128
+ * One rule, and it is the definition rather than a heuristic: **a login worked when a clean
129
+ * context reaches somewhere the unauthenticated browser could not.** `startedAt` is where
130
+ * the very first navigation landed — the wall — so a replay that lands back there gained
131
+ * nothing, whatever it shows.
132
+ *
133
+ * Reading "no password field" as success instead is the trap this avoids, and it is not
134
+ * theoretical: a magic-link or passkey login page has no password field at all, so the
135
+ * cheap signal says *logged in* from the first second, and the watch would save a state
136
+ * that opens nothing and call it ✅ — the exact false green this verb was rewritten to stop.
137
+ */
138
+ export declare function loginProven(replay: SessionReplay, startedAt: string): boolean;
139
+ /**
140
+ * Watch a visible browser until the person is logged in — instead of asking them to say so.
141
+ *
142
+ * The prompt this replaces was the last place in the verb that trusted a human's word, and
143
+ * the verb's whole history is about not doing that: `storageState({ path })` wrote on that
144
+ * word and printed `✅ Session saved — 0 cookies` over a file that logged nobody in. Asking
145
+ * "are you done?" has the same shape — it is a question about the world answered by
146
+ * someone who is looking at a browser, not at the cookie jar. And it fails in the most
147
+ * ordinary way there is: the person logs in, goes back to what they were doing, and the
148
+ * terminal sits on an unanswered prompt. It was reported by the person who wrote it.
149
+ *
150
+ * So the watch asks the browser, on a loop, and the evidence it accepts is the one the rest
151
+ * of this file already accepts: a **clean context** carrying only the captured state,
152
+ * reaching somewhere the unauthenticated browser could not (`loginProven`).
153
+ *
154
+ * Three restraints:
155
+ *
156
+ * - **It never gives up early.** A verification that fails means *not yet* — a multi-step
157
+ * login, a consent screen still to come — never *this will not work*. After a few failed
158
+ * attempts it explains the one case that genuinely cannot succeed (a token in IndexedDB
159
+ * leaves a session file empty) and keeps watching, because the alternative is telling
160
+ * somebody their login failed while they are still typing.
161
+ * - **The keyboard still works.** `confirmed` is the escape hatch for every app whose
162
+ * login this cannot observe, and whichever finishes first wins. Nothing that worked
163
+ * before stops working.
164
+ * - **Replaying is not free**, so the cheap gate runs first: on the app's own site, no
165
+ * password field in any frame, and something in the cookie jar. A clean context is
166
+ * opened only once that holds, and then only when the live page has moved again or
167
+ * enough time has passed.
168
+ */
169
+ export declare function watchForLogin(opts: {
170
+ browser: Browser;
171
+ context: BrowserContext;
172
+ page: Page;
173
+ target: string;
174
+ /** Where the FIRST navigation landed: the wall, and the thing a replay must beat. */
175
+ startedAt: string;
176
+ contextOptions?: Record<string, unknown>;
177
+ confirmed: Promise<void>;
178
+ timeoutMs?: number;
179
+ now?: () => number;
180
+ note?: (line: string) => void;
181
+ }): Promise<LoginWatch>;
61
182
  export interface SessionDecision {
62
183
  ok: boolean;
63
184
  action: 'write' | 'quarantine' | 'none';
package/dist/cli/login.js CHANGED
@@ -37,7 +37,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.runLogin = runLogin;
40
+ exports.performLogin = performLogin;
40
41
  exports.replaySession = replaySession;
42
+ exports.loginProven = loginProven;
43
+ exports.watchForLogin = watchForLogin;
41
44
  exports.sessionDecision = sessionDecision;
42
45
  const fs = __importStar(require("fs"));
43
46
  const path = __importStar(require("path"));
@@ -46,33 +49,7 @@ const launcher_1 = require("../launcher");
46
49
  const map_1 = require("./map");
47
50
  const sessionCheck_1 = require("../sessionCheck");
48
51
  const config_1 = require("../config");
49
- /**
50
- * `ia-qa-heal login` — open a browser, let a human log in, keep the session.
51
- *
52
- * `config.auth` fills a form: a username field, a password field, a submit button. That
53
- * describes *one shape of login*, and every app whose login is not that shape is out of
54
- * reach — federated SSO, MFA, a consent screen, a magic link, a device check, a captcha.
55
- * No selector list gets through any of them, so "add an auth block" is the wrong answer
56
- * to most walls, and `map` was left mapping a login form under the name `dashboard`.
57
- *
58
- * This verb models nothing at all, which is why it is the general one: the human performs
59
- * whatever the app asks, and the resulting session is saved in Playwright's `storageState`
60
- * shape and reused by `map`. It cannot know *how* your app authenticates, and never needs to.
61
- *
62
- * Deliberately not automatic, and never part of a gate:
63
- * - It is the only caller that opens a **visible** browser (`headed`) — everything that
64
- * produces a contract stays headless, because a window in CI is a hung build.
65
- * - It refuses without a TTY and under CI: it waits for a person twice over (at the
66
- * browser, then at the keyboard), and a pipeline that runs it just hangs.
67
- * - What it writes is a **secret** — live cookies, i.e. whoever holds the file is logged
68
- * in as that user. So it announces the path before opening anything, and writes
69
- * `.ia-qa/.gitignore` so a commit cannot carry it. The file never leaves the machine:
70
- * nothing in this package uploads it.
71
- *
72
- * For CI, `config.auth` (reproducible, no human) and capture-during-run (`IAQA_CAPTURE=1`
73
- * with your own suite's login) remain the two paths. A saved session is a local artefact
74
- * with a shelf life — when it expires, `map` hits the wall again and says to re-run this.
75
- */
52
+ const sessionCheck_2 = require("../sessionCheck");
76
53
  async function runLogin(args) {
77
54
  if (process.env.CI) {
78
55
  console.error(`❌ Refusing to open a login browser under CI.\n\n` +
@@ -81,14 +58,14 @@ async function runLogin(args) {
81
58
  ` "auth" in .ia-qa/config.json fills a login form from env/SSM secrets\n` +
82
59
  ` IAQA_CAPTURE=1 + testCommand your own suite logs in; map rides along`);
83
60
  process.exitCode = 2;
84
- return;
61
+ return { ok: false };
85
62
  }
86
63
  if (!process.stdin.isTTY) {
87
64
  console.error(`❌ \`ia-qa-heal login\` needs a terminal: it opens a browser, then waits for you to say\n` +
88
65
  ` you are logged in. With stdin closed it would wait forever.\n` +
89
66
  ` Run it in your own shell — an agent cannot do this step for you.`);
90
67
  process.exitCode = 2;
91
- return;
68
+ return { ok: false };
92
69
  }
93
70
  const config = (0, config_1.loadConfig)();
94
71
  const urlIdx = args.indexOf('--url');
@@ -96,7 +73,7 @@ async function runLogin(args) {
96
73
  if (urlIdx !== -1 && (!wanted || wanted.startsWith('-'))) {
97
74
  console.error('❌ --url needs a URL or a path (e.g. --url /dashboard).');
98
75
  process.exitCode = 2;
99
- return;
76
+ return { ok: false };
100
77
  }
101
78
  const target = new URL(wanted || config.pages[0]?.url || '/', config.baseUrl).toString();
102
79
  // Written where this project keeps its session, not always the default: someone who
@@ -107,46 +84,117 @@ async function runLogin(args) {
107
84
  if (sessionIdx !== -1 && (!explicit || explicit.startsWith('-'))) {
108
85
  console.error('❌ --session needs a file path.');
109
86
  process.exitCode = 2;
110
- return;
87
+ return { ok: false };
111
88
  }
112
89
  const file = (0, config_1.sessionTarget)(config, explicit).file;
113
- console.log(`\n🔑 ia-qa-heal login`);
90
+ // How long to watch the window before falling back to "tell me what is in there".
91
+ // `--wait 0` turns the watch off and restores the plain press-Enter flow, which is the
92
+ // escape hatch for an app whose login cannot be observed from the outside at all.
93
+ const waitIdx = args.indexOf('--wait');
94
+ const waitSeconds = waitIdx !== -1 ? Number(args[waitIdx + 1]) : 600;
95
+ if (waitIdx !== -1 && (!Number.isFinite(waitSeconds) || waitSeconds < 0)) {
96
+ console.error('❌ --wait needs a number of seconds (0 turns the watch off).');
97
+ process.exitCode = 2;
98
+ return { ok: false };
99
+ }
100
+ return performLogin({
101
+ verb: 'ia-qa-heal login',
102
+ target,
103
+ file,
104
+ gitignore: `${config_1.CONFIG_DIR}/.gitignore`,
105
+ writeGitignore: writeSessionGitignore,
106
+ contextOptions: config.locale || process.env.IAQA_LOCALE ? { locale: config.locale || process.env.IAQA_LOCALE } : {},
107
+ waitSeconds,
108
+ });
109
+ }
110
+ async function performLogin(opts) {
111
+ const { verb, target, file } = opts;
112
+ const contextOptions = opts.contextOptions ?? {};
113
+ const waitSeconds = opts.waitSeconds ?? 600;
114
+ console.log(`\n🔑 ${verb}`);
114
115
  console.log(` Opens a visible browser at ${target}.`);
115
116
  console.log(` Log in there however your app asks — SSO, MFA, a consent screen, all of it.`);
116
117
  console.log(` Nothing is typed for you, and no credential is read or stored by this tool.\n`);
117
- console.log(` When you say you are done, the browser session is saved to:`);
118
+ console.log(` Once the session actually opens the app, it is saved to:`);
118
119
  console.log(` ${file}`);
119
120
  console.log(` That file holds live session cookies: anyone who has it is logged in as you.`);
120
- console.log(` It stays on this machine — nothing here uploads it — and \`.ia-qa/.gitignore\``);
121
+ console.log(` It stays on this machine — nothing here uploads it — and \`${opts.gitignore}\``);
121
122
  console.log(` is written so a commit cannot carry it.\n`);
122
123
  const go = await (0, prompts_1.default)({ type: 'confirm', name: 'ok', message: 'Open the browser now?', initial: true }, { onCancel: () => ({ ok: false }) });
123
124
  if (!go.ok) {
124
125
  console.log('Nothing opened, nothing written.');
125
126
  process.exitCode = 1;
126
- return;
127
+ return { ok: false };
127
128
  }
128
129
  const { browser, using } = await (0, launcher_1.launchBrowser)({ headed: true });
129
130
  console.log(`🌐 Using ${using} (visible window)`);
130
131
  try {
131
- const contextOptions = config.locale || process.env.IAQA_LOCALE ? { locale: config.locale || process.env.IAQA_LOCALE } : {};
132
132
  const context = await browser.newContext(contextOptions);
133
133
  const page = await context.newPage();
134
134
  await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 60000 });
135
- await (0, prompts_1.default)({
136
- type: 'confirm',
137
- name: 'done',
138
- message: 'Logged in? (leave the browser open — press Enter here when the app is showing)',
139
- initial: true,
140
- }, { onCancel: () => ({ done: true }) });
135
+ // Where an UNauthenticated browser lands is the thing a real login has to beat, so it
136
+ // is read before anything else happens.
137
+ const startedAt = page.url();
138
+ console.log(waitSeconds > 0
139
+ ? `\n👀 Log in in the browser window. I am watching it — when the session actually opens\n` +
140
+ ` the app, I save it and carry on by myself. Nothing to come back and confirm here.\n` +
141
+ ` (Press Enter if you would rather stop the wait now.)`
142
+ : `\n👀 Log in in the browser window, then press Enter here.`);
143
+ const enter = waitForEnter();
144
+ let watch;
145
+ try {
146
+ watch =
147
+ waitSeconds > 0
148
+ ? await watchForLogin({
149
+ browser,
150
+ context,
151
+ page,
152
+ target,
153
+ startedAt,
154
+ contextOptions,
155
+ confirmed: enter.promise,
156
+ timeoutMs: waitSeconds * 1000,
157
+ })
158
+ : (await enter.promise, { end: 'confirmed' });
159
+ }
160
+ finally {
161
+ enter.cancel();
162
+ }
163
+ // A timeout is **not** a refusal. It only means nobody told us the login finished, so
164
+ // the question becomes the one this verb always answers: what does the browser actually
165
+ // hold right now? `sessionDecision` says it honestly — an empty state writes nothing and
166
+ // keeps the file that worked, a wall goes beside it, neither is ever a ✅. Returning
167
+ // early instead would throw away a session somebody really did obtain, just because the
168
+ // watch could not see the app from the outside.
169
+ if (watch.end === 'timeout') {
170
+ console.log(`\n⏳ Nothing that looks like a login happened in ${(0, sessionCheck_2.describeAge)(waitSeconds)}. Checking what the\n` +
171
+ ` browser holds anyway — whatever it is, it is reported rather than assumed.`);
172
+ }
141
173
  // Taken in memory, written only once it has been replayed. `storageState({ path })`
142
174
  // wrote first and asked nothing, so an empty state — an app keeping its token in
143
175
  // IndexedDB, or a login that never completed — printed a green "Session saved" *and*
144
176
  // overwrote a session that worked. Two failures in one line: a false green, and the
145
177
  // destruction of the good file it replaced.
146
- const takenOn = page.url();
147
- const state = await context.storageState();
148
- console.log(`\n🔁 Checking the session actually holds reopening ${target} with it, in a clean browser.`);
149
- const replay = await replaySession(browser, state, target, contextOptions);
178
+ //
179
+ // A closed window is not a special case: whatever the context held when it went is what
180
+ // gets judged, and `sessionDecision` says the honest thing about it.
181
+ const takenOn = page.isClosed() ? startedAt : page.url();
182
+ // The state and the proof about it travel together — writing a state taken *after* the
183
+ // verification would report a proof about a file that was never the file.
184
+ //
185
+ // Which pair, though, depends on how the watch ended. `verified` is the watch's own, by
186
+ // definition. A **closed** window leaves no way to take another, so the last attempt is
187
+ // all there is. But `confirmed` must be re-checked: pressing Enter means *look now*, and
188
+ // the person very often finishes the login and only then reaches for the keyboard — the
189
+ // last failed attempt would be a verdict about the moment before they succeeded.
190
+ const reusable = watch.end === 'verified' || (watch.end === 'closed' && watch.state);
191
+ let state = reusable ? watch.state : undefined;
192
+ let replay = reusable ? watch.replay : undefined;
193
+ if (!state || !replay) {
194
+ state = await context.storageState().catch(() => ({ cookies: [], origins: [] }));
195
+ console.log(`\n🔁 Checking the session actually holds — reopening ${target} with it, in a clean browser.`);
196
+ replay = await replaySession(browser, state, target, contextOptions);
197
+ }
150
198
  const decision = sessionDecision({
151
199
  cookies: state.cookies.length,
152
200
  origins: state.origins?.length || 0,
@@ -161,17 +209,43 @@ async function runLogin(args) {
161
209
  if (decision.action !== 'none') {
162
210
  fs.mkdirSync(path.dirname(decision.target), { recursive: true });
163
211
  fs.writeFileSync(decision.target, JSON.stringify(state, null, 2), 'utf8');
164
- writeSessionGitignore();
212
+ opts.writeGitignore();
165
213
  }
166
214
  for (const line of decision.lines)
167
215
  (decision.ok ? console.log : console.error)(line);
168
216
  if (!decision.ok)
169
217
  process.exitCode = 1;
218
+ return { ok: decision.ok, ...(decision.action !== 'none' ? { file: decision.target } : {}) };
170
219
  }
171
220
  finally {
172
221
  await browser.close();
173
222
  }
174
223
  }
224
+ /**
225
+ * "Press Enter" as a *cancellable* promise, which `prompts` cannot be.
226
+ *
227
+ * The watch and the keyboard race each other, so the loser has to be taken back: a `prompts`
228
+ * question left open keeps stdin resumed and the process alive long after the browser has
229
+ * closed and the session has been written. Raw stdin gives back a `cancel` that removes the
230
+ * listener and pauses the stream, which is the whole reason for not reusing `prompts` here.
231
+ */
232
+ function waitForEnter() {
233
+ let done = () => { };
234
+ const promise = new Promise((resolve) => {
235
+ done = resolve;
236
+ });
237
+ const onData = () => {
238
+ cancel();
239
+ done();
240
+ };
241
+ const cancel = () => {
242
+ process.stdin.off('data', onData);
243
+ process.stdin.pause();
244
+ };
245
+ process.stdin.resume();
246
+ process.stdin.on('data', onData);
247
+ return { promise, cancel };
248
+ }
175
249
  /**
176
250
  * `.ia-qa/.gitignore`, scoped to the one file in there that is a secret.
177
251
  *
@@ -230,6 +304,117 @@ async function replaySession(browser, state, target, contextOptions = {}) {
230
304
  await context.close();
231
305
  }
232
306
  }
307
+ /**
308
+ * Is this state, replayed in a clean context, evidence that somebody logged in?
309
+ *
310
+ * One rule, and it is the definition rather than a heuristic: **a login worked when a clean
311
+ * context reaches somewhere the unauthenticated browser could not.** `startedAt` is where
312
+ * the very first navigation landed — the wall — so a replay that lands back there gained
313
+ * nothing, whatever it shows.
314
+ *
315
+ * Reading "no password field" as success instead is the trap this avoids, and it is not
316
+ * theoretical: a magic-link or passkey login page has no password field at all, so the
317
+ * cheap signal says *logged in* from the first second, and the watch would save a state
318
+ * that opens nothing and call it ✅ — the exact false green this verb was rewritten to stop.
319
+ */
320
+ function loginProven(replay, startedAt) {
321
+ if (replay.error || replay.wall || replay.offSite)
322
+ return false;
323
+ if (!replay.landed)
324
+ return false;
325
+ return !(0, map_1.samePath)(replay.landed, startedAt);
326
+ }
327
+ /**
328
+ * Watch a visible browser until the person is logged in — instead of asking them to say so.
329
+ *
330
+ * The prompt this replaces was the last place in the verb that trusted a human's word, and
331
+ * the verb's whole history is about not doing that: `storageState({ path })` wrote on that
332
+ * word and printed `✅ Session saved — 0 cookies` over a file that logged nobody in. Asking
333
+ * "are you done?" has the same shape — it is a question about the world answered by
334
+ * someone who is looking at a browser, not at the cookie jar. And it fails in the most
335
+ * ordinary way there is: the person logs in, goes back to what they were doing, and the
336
+ * terminal sits on an unanswered prompt. It was reported by the person who wrote it.
337
+ *
338
+ * So the watch asks the browser, on a loop, and the evidence it accepts is the one the rest
339
+ * of this file already accepts: a **clean context** carrying only the captured state,
340
+ * reaching somewhere the unauthenticated browser could not (`loginProven`).
341
+ *
342
+ * Three restraints:
343
+ *
344
+ * - **It never gives up early.** A verification that fails means *not yet* — a multi-step
345
+ * login, a consent screen still to come — never *this will not work*. After a few failed
346
+ * attempts it explains the one case that genuinely cannot succeed (a token in IndexedDB
347
+ * leaves a session file empty) and keeps watching, because the alternative is telling
348
+ * somebody their login failed while they are still typing.
349
+ * - **The keyboard still works.** `confirmed` is the escape hatch for every app whose
350
+ * login this cannot observe, and whichever finishes first wins. Nothing that worked
351
+ * before stops working.
352
+ * - **Replaying is not free**, so the cheap gate runs first: on the app's own site, no
353
+ * password field in any frame, and something in the cookie jar. A clean context is
354
+ * opened only once that holds, and then only when the live page has moved again or
355
+ * enough time has passed.
356
+ */
357
+ async function watchForLogin(opts) {
358
+ const note = opts.note ?? ((line) => console.log(line));
359
+ const now = opts.now ?? Date.now;
360
+ const deadline = now() + (opts.timeoutMs ?? 10 * 60 * 1000);
361
+ let confirmed = false;
362
+ void opts.confirmed.then(() => {
363
+ confirmed = true;
364
+ });
365
+ let lastVerifiedUrl = '';
366
+ let lastVerifiedAt = 0;
367
+ let attempts = 0;
368
+ // The last attempt, kept as a pair. It is offered on a `confirmed`/`closed` ending only
369
+ // because it is a true statement about a state we still hold; it is never a success.
370
+ let last;
371
+ for (;;) {
372
+ if (confirmed)
373
+ return { end: 'confirmed', ...last };
374
+ if (opts.page.isClosed())
375
+ return { end: 'closed', ...last };
376
+ if (now() >= deadline)
377
+ return { end: 'timeout', ...last };
378
+ let url = '';
379
+ let cookies = 0;
380
+ try {
381
+ url = opts.page.url();
382
+ cookies = (await opts.context.cookies()).length;
383
+ }
384
+ catch {
385
+ // The context went away under us — the person closed the window.
386
+ return { end: 'closed', ...last };
387
+ }
388
+ const worthVerifying = cookies > 0 &&
389
+ (0, sessionCheck_1.sameSite)(url, opts.target) &&
390
+ !(0, map_1.samePath)(url, opts.startedAt) &&
391
+ !(await (0, map_1.hasPasswordField)(opts.page, 0)) &&
392
+ (url !== lastVerifiedUrl || now() - lastVerifiedAt > 8000);
393
+ if (worthVerifying) {
394
+ lastVerifiedUrl = url;
395
+ lastVerifiedAt = now();
396
+ attempts++;
397
+ let state;
398
+ try {
399
+ state = await opts.context.storageState();
400
+ }
401
+ catch {
402
+ return { end: 'closed', ...last };
403
+ }
404
+ const replay = await replaySession(opts.browser, state, opts.target, opts.contextOptions ?? {});
405
+ last = { replay, state };
406
+ if (loginProven(replay, opts.startedAt))
407
+ return { end: 'verified', replay, state };
408
+ if (attempts === 3) {
409
+ note(`\n ⏳ You look logged in, but the session I can carry does not open the app on its own yet.\n` +
410
+ ` Still watching — a multi-step login is normal here. If your app keeps its token in\n` +
411
+ ` IndexedDB, in memory or in a service worker, a session file can never hold it:\n` +
412
+ ` press Enter and I will tell you exactly that instead of waiting.`);
413
+ }
414
+ }
415
+ await new Promise((r) => setTimeout(r, 1200));
416
+ }
417
+ }
233
418
  /**
234
419
  * What to do with a session that has just been replayed — and above all, what never to do.
235
420
  *
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"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"}
@@ -21,4 +21,44 @@ export interface SessionCheck {
21
21
  facts: SessionFacts;
22
22
  verdict: SessionVerdict;
23
23
  }
24
+ /**
25
+ * The same check, for a caller that is not a terminal.
26
+ *
27
+ * Exported because an orchestrator has a reason to ask this *before* it spends minutes on a
28
+ * SUT — a session is one credential for the whole app, so a dead one makes every page of a
29
+ * tour fail in turn, and the field has watched exactly that happen for eighteen minutes.
30
+ * It is the verdict `session --check` prints, not a second opinion: rebuilding it from
31
+ * `readFacts` and a navigation is the CLI/MCP dispatch split in another costume.
32
+ *
33
+ * `present: false` is not a failure — a project with no session file is the ordinary case
34
+ * for a public app or one using `config.auth`, and calling that "broken" would be a wrong
35
+ * verdict on a healthy project.
36
+ */
37
+ export interface SessionProbe {
38
+ present: boolean;
39
+ file?: string;
40
+ source?: string;
41
+ facts?: SessionFacts;
42
+ verdict?: SessionVerdict;
43
+ /** The file exists but could not be read or parsed. */
44
+ unreadable?: string;
45
+ }
46
+ export declare function probeSession(opts?: {
47
+ url?: string;
48
+ session?: string;
49
+ offline?: boolean;
50
+ }): Promise<SessionProbe>;
51
+ /**
52
+ * The same probe against a session file the caller names.
53
+ *
54
+ * Exported for the sibling package, which keeps its own session in its own directory: the
55
+ * question "does this file open that app" has nothing to do with whose config pointed at it,
56
+ * and a second implementation of it is how two tools end up disagreeing about one session.
57
+ */
58
+ export declare function probeSessionFile(opts: {
59
+ file: string;
60
+ url: string;
61
+ offline?: boolean;
62
+ source?: string;
63
+ }): Promise<SessionProbe>;
24
64
  export declare function runSessionCheck(args: string[]): Promise<void>;
@@ -33,12 +33,53 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.probeSession = probeSession;
37
+ exports.probeSessionFile = probeSessionFile;
36
38
  exports.runSessionCheck = runSessionCheck;
37
39
  const fs = __importStar(require("fs"));
38
40
  const config_1 = require("../config");
39
41
  const launcher_1 = require("../launcher");
40
42
  const login_1 = require("./login");
41
43
  const sessionCheck_1 = require("../sessionCheck");
44
+ async function probeSession(opts = {}) {
45
+ const config = (0, config_1.loadConfig)();
46
+ const choice = (0, config_1.resolveSession)(config, opts.session);
47
+ if (!choice)
48
+ return { present: false };
49
+ return probeSessionFile({ file: choice.file, url: opts.url ?? config.baseUrl, offline: opts.offline, source: choice.source });
50
+ }
51
+ /**
52
+ * The same probe against a session file the caller names.
53
+ *
54
+ * Exported for the sibling package, which keeps its own session in its own directory: the
55
+ * question "does this file open that app" has nothing to do with whose config pointed at it,
56
+ * and a second implementation of it is how two tools end up disagreeing about one session.
57
+ */
58
+ async function probeSessionFile(opts) {
59
+ const source = opts.source ?? 'flag';
60
+ if (!fs.existsSync(opts.file))
61
+ return { present: false };
62
+ let state;
63
+ try {
64
+ state = JSON.parse(fs.readFileSync(opts.file, 'utf8'));
65
+ }
66
+ catch (err) {
67
+ return { present: true, file: opts.file, source, unreadable: err instanceof Error ? err.message : String(err) };
68
+ }
69
+ const facts = (0, sessionCheck_1.readFacts)(state, opts.url);
70
+ const offlineVerdict = (0, sessionCheck_1.judgeSession)(facts);
71
+ if (offlineVerdict.cause !== 'unknown' || opts.offline) {
72
+ return { present: true, file: opts.file, source, facts, verdict: offlineVerdict };
73
+ }
74
+ const { browser } = await (0, launcher_1.launchBrowser)();
75
+ try {
76
+ const replay = await (0, login_1.replaySession)(browser, state, opts.url);
77
+ return { present: true, file: opts.file, source, facts, verdict: (0, sessionCheck_1.judgeSession)(facts, replay) };
78
+ }
79
+ finally {
80
+ await browser.close();
81
+ }
82
+ }
42
83
  /**
43
84
  * The causes that mean *could not tell*, as opposed to *does not hold*.
44
85
  *
@@ -74,9 +115,11 @@ async function runSessionCheck(args) {
74
115
  const wantedUrl = urlIdx !== -1 ? args[urlIdx + 1] : undefined;
75
116
  const sessionIdx = args.indexOf('--session');
76
117
  const wantedSession = sessionIdx !== -1 ? args[sessionIdx + 1] : undefined;
77
- const config = (0, config_1.loadConfig)();
78
- const choice = (0, config_1.resolveSession)(config, wantedSession);
79
- if (!choice) {
118
+ // Every fact and every verdict comes from `probeSession`; this function only renders and
119
+ // picks the exit code. An orchestrator asking the same question in process therefore gets
120
+ // the identical answer, which is the point of having extracted it.
121
+ const probe = await probeSession({ url: wantedUrl, session: wantedSession, offline });
122
+ if (!probe.present) {
80
123
  // Not a failure: a project with no session is the ordinary case for a public app or one
81
124
  // using `config.auth`. Saying "no session is broken" would be a wrong verdict.
82
125
  const message = `No session file to check.\n` +
@@ -88,33 +131,13 @@ async function runSessionCheck(args) {
88
131
  console.log(`\nℹ️ ${message}`);
89
132
  return;
90
133
  }
91
- let state;
92
- try {
93
- state = JSON.parse(fs.readFileSync(choice.file, 'utf8'));
94
- }
95
- catch (err) {
96
- console.error(`❌ ${choice.file} could not be read: ${err instanceof Error ? err.message : String(err)}`);
134
+ if (probe.unreadable || !probe.facts || !probe.verdict) {
135
+ console.error(`❌ ${probe.file} could not be read: ${probe.unreadable ?? 'no verdict'}`);
97
136
  process.exitCode = 2;
98
137
  return;
99
138
  }
100
- const target = wantedUrl ?? config.baseUrl;
101
- const facts = (0, sessionCheck_1.readFacts)(state, target);
102
- // The offline causes are conclusive, so the browser is not opened to re-confirm an expiry
103
- // date — the cheapest honest answer, not a degraded one.
104
- const offlineVerdict = (0, sessionCheck_1.judgeSession)(facts);
105
- const decidedOffline = offlineVerdict.cause !== 'unknown';
106
- let verdict = offlineVerdict;
107
- if (!decidedOffline && !offline) {
108
- const { browser } = await (0, launcher_1.launchBrowser)();
109
- try {
110
- const replay = await (0, login_1.replaySession)(browser, state, target);
111
- verdict = (0, sessionCheck_1.judgeSession)(facts, replay);
112
- }
113
- finally {
114
- await browser.close();
115
- }
116
- }
117
- const check = { file: choice.file, source: choice.source, facts, verdict };
139
+ const check = { file: probe.file, source: probe.source, facts: probe.facts, verdict: probe.verdict };
140
+ const verdict = probe.verdict;
118
141
  if (json) {
119
142
  console.log(JSON.stringify({ schema: 'ia-qa-heal/session@1', present: true, ...check }, null, 2));
120
143
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/cli/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/cli/session.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,oCAKC;AASD,4CA6BC;AAmCD,0CAyCC;AA5KD,uCAAyB;AACzB,sCAAuD;AACvD,0CAA4C;AAC5C,mCAAwC;AACxC,kDAAmI;AAiD5H,KAAK,UAAU,YAAY,CAAC,OAA8D,EAAE;IACjG,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACvC,OAAO,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AAChI,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,gBAAgB,CAAC,IAKtC;IACC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;IACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAEzD,IAAI,KAAoB,CAAC;IACzB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAkB,CAAC;IAC1E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAClH,CAAC;IAED,MAAM,KAAK,GAAG,IAAA,wBAAS,EAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,IAAA,2BAAY,EAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,cAAc,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;IACpF,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAA,wBAAa,GAAE,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,OAAO,EAAE,KAAc,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAA,2BAAY,EAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;IACjG,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY,CAAC,KAA8B;IAClD,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,UAAU,CAAC;AACrD,CAAC;AAED,SAAS,MAAM,CAAC,KAAmB;IACjC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3E,MAAM,KAAK,GAAG;QACZ,QAAQ,KAAK,CAAC,IAAI,EAAE;QACpB,MAAM,KAAK,CAAC,OAAO,UAAU,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,OAAO,UAC3E,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC7B,sBAAsB,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;KAC3F,CAAC;IACF,sFAAsF;IACtF,0EAA0E;IAC1E,IAAI,KAAK,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,gBAAgB,IAAI,CAAC;YACzB,CAAC,CAAC,8BAA8B,IAAA,0BAAW,EAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;YACrE,CAAC,CAAC,cAAc,IAAA,0BAAW,EAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAC5D,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,IAAc;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,yFAAyF;IACzF,0FAA0F;IAC1F,mEAAmE;IACnE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;IAEtF,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,wFAAwF;QACxF,+EAA+E;QAC/E,MAAM,OAAO,GACX,6BAA6B;YAC7B,sFAAsF;YACtF,2DAA2D,CAAC;QAC9D,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;YACvG,OAAO,CAAC,GAAG,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,uBAAuB,KAAK,CAAC,UAAU,IAAI,YAAY,EAAE,CAAC,CAAC;QACxF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IACrH,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpG,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,yFAAyF;IACzF,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC"}
package/dist/index.d.ts CHANGED
@@ -36,6 +36,11 @@ export { configuredTestPaths } from './config';
36
36
  export { runMap, LoginWallError } from './cli/map';
37
37
  export type { MapResult, MapFailure, MapPageStat } from './cli/map';
38
38
  export { runBaseline } from './cli/baseline';
39
+ export { probeSession, probeSessionFile } from './cli/session';
40
+ export type { SessionProbe } from './cli/session';
41
+ export { runLogin, performLogin } from './cli/login';
42
+ export type { LoginResult, PerformLoginOptions } from './cli/login';
43
+ export { sessionPath } from './config';
39
44
  export { dirDiffAggregate } from './cli/diff';
40
45
  export type { DirReport, DirDiffCollection } from './cli/diff';
41
46
  export type { RouteChange } from './routeDrift';
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.globToRegex = exports.readTestDepth = exports.collectUnattributable = exports.computePageDepth = exports.computeTestDepth = exports.saveExercised = exports.EXERCISED_FILENAME = exports.contractPageNames = exports.exercisedPath = exports.loadExercised = exports.usagePath = exports.usageFiles = exports.loadUsage = exports.saveUsage = exports.ingestPaths = exports.scanText = exports.crawlApp = exports.sitemapsFromRobots = exports.isSitemapIndex = exports.extractLocs = exports.discoverFromSitemap = exports.UNSAFE_URL_RE = exports.mergePages = exports.toCandidate = exports.normalizedPath = exports.isSafeCandidateUrl = exports.resolvePageName = exports.pageNameFromUrl = exports.mapUrl = exports.markdownPath = exports.saveMarkdown = exports.renderPageContract = exports.saveMapping = exports.loadMapping = exports.extractInteractiveElements = exports.COMPATIBLE_EXAMPLES = exports.renderModelList = exports.defaultKeyEnv = exports.findProvider = exports.AI_PROVIDERS = exports.parseModelJson = exports.buildPrompt = exports.prefilter = exports.aiResolve = exports.PROVIDER_HOST = exports.egressHost = exports.createAiResolver = exports.llmResolverStub = exports.aiFill = exports.aiClick = void 0;
4
- exports.renderNavigation = exports.renderOverview = exports.buildOverview = exports.minPagesForLayout = exports.stripLayoutFromPages = exports.extractLayout = exports.isWebAddress = exports.readSitemap = exports.writeSetup = exports.planSetup = exports.listShape = exports.groupListChurn = exports.maskDigits = exports.groupNumericLabelDrift = exports.detectTestCommand = exports.auditProject = exports.runFix = exports.HISTORY_FILENAME = exports.historyPath = exports.WIDE_RUN_SHARE = exports.pageChurn = exports.readHistory = exports.checkCounts = exports.checkHeadline = exports.checkVerdict = exports.checkProject = exports.dirDiffAggregate = exports.runBaseline = exports.LoginWallError = exports.runMap = exports.configuredTestPaths = exports.baselineDir = exports.mappingDir = exports.setBaseDir = exports.LAYOUT_DIRNAME = exports.layoutPath = exports.layoutDir = exports.maskSecret = exports.looksLikeSecret = exports.resolveSecret = exports.loadConfig = exports.replaceQuoted = exports.collectFiles = exports.applyRewrites = exports.computeRewrites = exports.launchBrowser = exports.CAPTURE_DIRNAME = exports.captureDir = exports.unionElements = exports.mergeCaptures = void 0;
5
- exports.createSkillVerb = exports.NAVIGATION_SVG_FILENAME = exports.NAVIGATION_FILENAME = exports.OVERVIEW_FILENAME = exports.navigationSvgPath = exports.navigationPath = exports.overviewPath = exports.writeOverview = exports.navigationGraph = exports.layoutGraph = exports.renderNavigationSvg = void 0;
4
+ exports.extractLayout = exports.isWebAddress = exports.readSitemap = exports.writeSetup = exports.planSetup = exports.listShape = exports.groupListChurn = exports.maskDigits = exports.groupNumericLabelDrift = exports.detectTestCommand = exports.auditProject = exports.runFix = exports.HISTORY_FILENAME = exports.historyPath = exports.WIDE_RUN_SHARE = exports.pageChurn = exports.readHistory = exports.checkCounts = exports.checkHeadline = exports.checkVerdict = exports.checkProject = exports.dirDiffAggregate = exports.sessionPath = exports.performLogin = exports.runLogin = exports.probeSessionFile = exports.probeSession = exports.runBaseline = exports.LoginWallError = exports.runMap = exports.configuredTestPaths = exports.baselineDir = exports.mappingDir = exports.setBaseDir = exports.LAYOUT_DIRNAME = exports.layoutPath = exports.layoutDir = exports.maskSecret = exports.looksLikeSecret = exports.resolveSecret = exports.loadConfig = exports.replaceQuoted = exports.collectFiles = exports.applyRewrites = exports.computeRewrites = exports.launchBrowser = exports.CAPTURE_DIRNAME = exports.captureDir = exports.unionElements = exports.mergeCaptures = void 0;
5
+ exports.createSkillVerb = exports.NAVIGATION_SVG_FILENAME = exports.NAVIGATION_FILENAME = exports.OVERVIEW_FILENAME = exports.navigationSvgPath = exports.navigationPath = exports.overviewPath = exports.writeOverview = exports.navigationGraph = exports.layoutGraph = exports.renderNavigationSvg = exports.renderNavigation = exports.renderOverview = exports.buildOverview = exports.minPagesForLayout = exports.stripLayoutFromPages = void 0;
6
6
  var healer_1 = require("./playwright/healer");
7
7
  Object.defineProperty(exports, "aiClick", { enumerable: true, get: function () { return healer_1.aiClick; } });
8
8
  Object.defineProperty(exports, "aiFill", { enumerable: true, get: function () { return healer_1.aiFill; } });
@@ -112,6 +112,26 @@ Object.defineProperty(exports, "runMap", { enumerable: true, get: function () {
112
112
  Object.defineProperty(exports, "LoginWallError", { enumerable: true, get: function () { return map_1.LoginWallError; } });
113
113
  var baseline_1 = require("./cli/baseline");
114
114
  Object.defineProperty(exports, "runBaseline", { enumerable: true, get: function () { return baseline_1.runBaseline; } });
115
+ // The session half an orchestrator needs BEFORE it spends minutes on a SUT. A session is one
116
+ // credential for the whole app, so a dead one makes every page fail in turn — the field has
117
+ // watched that run for eighteen minutes. `probeSession` is the verdict `session --check`
118
+ // prints, not a second opinion; `runLogin` is the one step that needs a person, exported so
119
+ // an orchestrator can hand the browser over instead of printing a command to copy. It still
120
+ // refuses without a TTY and under CI, which is what keeps it out of an agent's reach.
121
+ var session_1 = require("./cli/session");
122
+ Object.defineProperty(exports, "probeSession", { enumerable: true, get: function () { return session_1.probeSession; } });
123
+ Object.defineProperty(exports, "probeSessionFile", { enumerable: true, get: function () { return session_1.probeSessionFile; } });
124
+ // `performLogin` is the login itself, parameterised by the caller's paths — the sibling
125
+ // package had a hand-written twin of it that was this verb *before* both of its corrections
126
+ // (saved on the human's word, and wrote before checking). "Does this session open the app"
127
+ // is the same question on both sides, so it gets one implementation, like `createSkillVerb`.
128
+ var login_1 = require("./cli/login");
129
+ Object.defineProperty(exports, "runLogin", { enumerable: true, get: function () { return login_1.runLogin; } });
130
+ Object.defineProperty(exports, "performLogin", { enumerable: true, get: function () { return login_1.performLogin; } });
131
+ // The session file heal keeps, so a sibling can fall back to it instead of asking the same
132
+ // person to log into the same app a second time.
133
+ var config_3 = require("./config");
134
+ Object.defineProperty(exports, "sessionPath", { enumerable: true, get: function () { return config_3.sessionPath; } });
115
135
  var diff_1 = require("./cli/diff");
116
136
  Object.defineProperty(exports, "dirDiffAggregate", { enumerable: true, get: function () { return diff_1.dirDiffAggregate; } });
117
137
  var check_1 = require("./cli/check");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ia-qa/self-healing",
3
- "version": "1.25.0",
3
+ "version": "1.27.0",
4
4
  "description": "Your Playwright, Cypress or Selenium tests break when a selector moves — this finds the element again and rewrites the test. Deterministic: no LLM decides whether your build passes. Runs entirely on your machine, with a local MCP server for agents.",
5
5
  "keywords": [
6
6
  "self-healing",
@@ -174,7 +174,11 @@ established which element the test meant.
174
174
  report those as pages that failed. For everything a form cannot answer there is exactly one step, and it
175
175
  belongs to the human: `ia-qa-heal login` opens a visible browser, they log in once, and the
176
176
  session is reused by `map`. It refuses without a TTY and under CI — that refusal is aimed at
177
- you. Never ask for their password, never put a credential in `config.json` (it holds `secrets`
177
+ you. Tell them there is **nothing to confirm afterwards**: the verb watches the window and
178
+ saves the session the moment it genuinely opens the app, so the old "press Enter when done"
179
+ step is gone. Do not tell them to run it with `--wait 0` unless their login cannot be
180
+ observed from outside at all — that flag restores the manual step you would be asking them
181
+ to remember. Never ask for their password, never put a credential in `config.json` (it holds `secrets`
178
182
  *references* to env/SSM, never values), and never commit `.ia-qa/session.json` — it is a live
179
183
  session, gitignored on creation. For CI, the reproducible paths are `auth` and capture-during-
180
184
  run (`IAQA_CAPTURE=1` + `testCommand`), never a saved session.