@ia-qa/self-healing 1.4.1 → 1.4.2

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
@@ -176,6 +176,24 @@ Run again with --apply to add the uncovered pages to config.pages.
176
176
 
177
177
  Then `ia-qa-heal map` captures their contracts as usual. Discovery never maps, heals, or edits a test — it only ever edits `config.json`, and only with `--apply`.
178
178
 
179
+ ## Visualize the app — `ia-qa-heal graph`
180
+
181
+ Turn the mappings you already have into a **navigation graph** (page → page, derived from the `href` on each page's links — the same engine `map` uses for `_overview.md`). Read-only: it never rewrites your mapping files, it just renders them.
182
+
183
+ ```bash
184
+ ia-qa-heal graph # Mermaid on stdout — paste into a PR comment or mermaid.live
185
+ ia-qa-heal graph --format json # ia-qa-graph@1 intermediate: { nodes[], edges[], meta }
186
+ ia-qa-heal graph --format markdown --out nav-kb.md # one card per page — a RAG chunk / Confluence page
187
+ ia-qa-heal graph --format svg --out nav.svg # the same SVG map writes as _navigation.svg
188
+ ia-qa-heal graph --format json | your-agent # hand the graph to an agent to analyze
189
+ ```
190
+
191
+ `--format` is one of `mermaid` (default) · `svg` · `json` · `markdown`; `--out <file>` writes to a file instead of stdout; `--open` opens it. `mermaid` and `svg` are the same views `map` already writes to `_navigation.md`/`_navigation.svg` — offered here for stdout/pipe.
192
+
193
+ The **`json`** form is the portable `ia-qa-graph@1` IR — nodes carry `{ url, elementCount, entry, isolated }`, and `meta` carries the coverage gap (`unmapped`), collapsed hubs (`fans`), any `mesh`, and `entries`. It matches the node/edge shape the ia-qa.com Graph tool consumes, so it drops into other viewers (D3, Reagraph) without conversion.
194
+
195
+ The **`markdown`** form linearizes the graph into one section per page — *what it is, where it links, what reaches it* — so a page is a self-contained chunk you can index in a **RAG knowledge base** (split on the `##` headings) or push to **Confluence** (`create_confluence_page` on the ia-qa MCP). It carries the navigation *relations* the per-page `map` contracts don't, and ends with a **Coverage gaps** list of linked-but-unmapped destinations.
196
+
179
197
  ## The one-verb loop: `ia-qa-heal run`
180
198
 
181
199
  `run` chains the whole loop and stops where a human belongs:
package/TUTORIAL.md CHANGED
@@ -268,6 +268,14 @@ Plus, for the whole app:
268
268
  sentence, not 144 arrows). If your app is a pure catalogue, you get no graph and a note
269
269
  saying so, which is the honest answer.
270
270
 
271
+ > 🕸️ **Want the graph on demand, or in another format?** `ia-qa-heal graph` re-emits it from
272
+ > your mappings without re-mapping — `--format mermaid|svg|json|markdown` (default mermaid on
273
+ > stdout, so it pipes into a PR comment or mermaid.live; `--out <file>` / `--open`). `json` is
274
+ > the portable `ia-qa-graph@1` graph (`{nodes,edges,meta}`) for D3 / Reagraph or an agent;
275
+ > **`markdown` gives one card per page** — a ready-made **RAG chunk** or **Confluence section**
276
+ > (`create_confluence_page` on the ia-qa MCP), carrying the page-to-page relations the per-page
277
+ > `.md` contracts don't. Read-only: it never rewrites the files above.
278
+
271
279
  Commit them.
272
280
 
273
281
  ---
@@ -0,0 +1 @@
1
+ export declare function runGraph(args: string[]): Promise<void>;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runGraph = runGraph;
37
+ const fs = __importStar(require("fs"));
38
+ const config_1 = require("../config");
39
+ const layout_1 = require("../layout");
40
+ const overview_1 = require("../overview");
41
+ const ir_1 = require("../graph/ir");
42
+ const diff_1 = require("./diff");
43
+ const summary_1 = require("./summary");
44
+ /**
45
+ * `ia-qa-heal graph` — turn the mapped app into a navigation graph.
46
+ *
47
+ * Read-only: it loads `.ia-qa/mapping/*.json`, reuses the same overview engine
48
+ * `map` uses (`buildOverview` → `navigationGraph`), and emits the graph. It never
49
+ * rewrites `_overview.md`/`_navigation.*` — those belong to `map`; `graph` only
50
+ * shares the renderers. Default is Mermaid on stdout, so it pipes straight into a
51
+ * file, mermaid.live, or a PR comment (GitHub renders it).
52
+ *
53
+ * `mermaid`/`svg` are the same views `map` already writes to `_navigation.md`/`.svg`
54
+ * — offered here for stdout/pipe. `json` is the portable `ia-qa-graph@1` IR for
55
+ * D3/Reagraph/agents. `markdown` linearizes it into one card per page — a RAG
56
+ * chunk / Confluence section, carrying the navigation relations the per-page
57
+ * `map` contracts don't.
58
+ *
59
+ * --format mermaid|svg|json|markdown Output format (default mermaid)
60
+ * --out <file> Write to a file instead of stdout
61
+ * --open Open the output in the browser (implies a file)
62
+ * --kind navigation Graph kind (only navigation for now)
63
+ */
64
+ const FORMATS = ['mermaid', 'svg', 'json', 'markdown'];
65
+ const DEFAULT_EXT = {
66
+ mermaid: 'md',
67
+ svg: 'svg',
68
+ json: 'json',
69
+ markdown: 'md',
70
+ };
71
+ async function runGraph(args) {
72
+ const opts = parseArgs(args);
73
+ const config = (0, config_1.loadConfig)();
74
+ const pages = (0, layout_1.collectPageMappings)((0, config_1.mappingDir)());
75
+ if (pages.length === 0) {
76
+ throw new Error('No mappings found in .ia-qa/mapping/. Run `ia-qa-heal map` first.');
77
+ }
78
+ const overview = (0, overview_1.buildOverview)(config, pages, (0, overview_1.collectLayouts)((0, config_1.layoutDir)()));
79
+ const graph = (0, overview_1.navigationGraph)(overview);
80
+ const ir = (0, ir_1.toGraphIR)(overview, graph);
81
+ const output = render(opts.format, ir, overview);
82
+ const hasDrawing = graph.nodes.length > 0;
83
+ // --open needs a file to point a browser at; default one when only --open is given.
84
+ const dest = opts.out ?? (opts.open ? `ia-qa-heal-graph.${DEFAULT_EXT[opts.format]}` : undefined);
85
+ if (dest) {
86
+ fs.writeFileSync(dest, output, 'utf8');
87
+ console.log(`✍ Wrote ${opts.format} graph → ${dest}`);
88
+ if (opts.open)
89
+ (0, diff_1.openInBrowser)(dest);
90
+ }
91
+ else {
92
+ process.stdout.write(output + '\n');
93
+ }
94
+ const drawn = graph.nodes.length;
95
+ const detail = [
96
+ `${ir.nodes.length} pages · ${ir.edges.length} links`,
97
+ hasDrawing ? `${drawn} drawn` : 'nothing selective to draw',
98
+ ir.meta.unmapped.length ? `${ir.meta.unmapped.length} uncovered` : null,
99
+ ].filter(Boolean);
100
+ (0, summary_1.summaryLine)('graph', 'ok', `${opts.format} navigation graph`, detail);
101
+ }
102
+ function render(format, ir, overview) {
103
+ switch (format) {
104
+ case 'mermaid':
105
+ // renderNavigation self-handles the empty case with an explanation.
106
+ return (0, overview_1.renderNavigation)(overview);
107
+ case 'svg':
108
+ return (0, overview_1.renderNavigationSvg)(overview);
109
+ case 'json':
110
+ return JSON.stringify(ir, null, 2);
111
+ case 'markdown':
112
+ return (0, ir_1.renderMarkdown)(ir);
113
+ }
114
+ }
115
+ function parseArgs(args) {
116
+ const opts = { format: 'mermaid', kind: 'navigation', open: false };
117
+ for (let i = 0; i < args.length; i++) {
118
+ const a = args[i];
119
+ switch (a) {
120
+ case '--format': {
121
+ const value = args[++i];
122
+ if (!value || !FORMATS.includes(value)) {
123
+ throw new Error(`--format needs one of ${FORMATS.join('|')}, got "${value ?? ''}".`);
124
+ }
125
+ opts.format = value;
126
+ break;
127
+ }
128
+ case '--kind': {
129
+ const value = args[++i];
130
+ if (value !== 'navigation') {
131
+ throw new Error(`--kind only supports "navigation" for now, got "${value ?? ''}".`);
132
+ }
133
+ opts.kind = value;
134
+ break;
135
+ }
136
+ case '--out': {
137
+ const value = args[++i];
138
+ if (!value || value.startsWith('-')) {
139
+ throw new Error('--out needs a file path, e.g. --out .ia-qa/graph.json.');
140
+ }
141
+ opts.out = value;
142
+ break;
143
+ }
144
+ case '--open':
145
+ opts.open = true;
146
+ break;
147
+ default:
148
+ throw new Error(`Unknown option "${a}" for \`graph\`. See \`ia-qa-heal help\`.`);
149
+ }
150
+ }
151
+ return opts;
152
+ }
153
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/cli/graph.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -10,6 +10,7 @@ const fix_1 = require("./fix");
10
10
  const ingest_1 = require("./ingest");
11
11
  const run_1 = require("./run");
12
12
  const discover_1 = require("./discover");
13
+ const graph_1 = require("./graph");
13
14
  // dist/cli/ → package root; npm ships package.json in every tarball.
14
15
  const VERSION = require('../../package.json').version;
15
16
  const HELP = `ia-qa-heal — self-healing E2E toolkit (MVP)
@@ -42,6 +43,16 @@ Usage:
42
43
  _navigation.md/.svg (the nav graph, when there is
43
44
  selective structure to draw — a mesh or a fan is stated
44
45
  in the overview instead)
46
+ ia-qa-heal graph Turn the mapped app into a navigation graph (page→page,
47
+ derived from href — the same engine map uses). Read-only:
48
+ never rewrites _overview.md/_navigation.*
49
+ --format mermaid|svg|json|markdown default mermaid (stdout;
50
+ GitHub/mermaid.live render it). mermaid/svg are the
51
+ views map already writes; json = ia-qa-graph@1 IR
52
+ (for D3/Reagraph/agents); markdown = one card per
53
+ page (a RAG chunk / Confluence section)
54
+ --out <file> write to a file instead of stdout
55
+ --open open the output in the browser (implies a file)
45
56
  ia-qa-heal baseline Promote .ia-qa/mapping/ → .ia-qa/baseline/, the reference
46
57
  diff compares against. Commit it. Drift needs two
47
58
  moments: without this there is only one, and a diff
@@ -145,6 +156,9 @@ async function main() {
145
156
  case 'ingest':
146
157
  await (0, ingest_1.runIngest)(rest);
147
158
  break;
159
+ case 'graph':
160
+ await (0, graph_1.runGraph)(rest);
161
+ break;
148
162
  case 'run':
149
163
  await (0, run_1.runRun)(rest);
150
164
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import type { AppOverview, NavigationGraph, HubFan, NavMesh, OffMapDestination } from '../overview';
2
+ /**
3
+ * `ia-qa-graph@1` — a portable intermediate graph, `{ nodes, edges }`.
4
+ *
5
+ * It invents nothing: it projects the `AppOverview` + `NavigationGraph` that
6
+ * `overview.ts` already computes into one JSON shape that adapts to Mermaid,
7
+ * Graphviz/DOT, D3, Reagraph — and matches the node/edge shape the web
8
+ * `/devtools/graph` viewer consumes (`{id,type,label,meta}` / `{id,from,to,type}`),
9
+ * so a future "import graph JSON" needs no conversion.
10
+ *
11
+ * `nodes`/`edges` carry the *full* navigation (every mapped page, every deduped
12
+ * page→page link). The pruning `navigationGraph()` does for a readable drawing —
13
+ * collapsed fans, a mesh, isolated/entry pages — is not thrown away: it lives in
14
+ * `meta`, so a consumer can redraw the whole thing or honour the collapse, exactly
15
+ * as the Mermaid/SVG renderers do.
16
+ */
17
+ export interface GraphNode {
18
+ id: string;
19
+ type: 'page';
20
+ label: string;
21
+ meta: {
22
+ url: string;
23
+ elementCount: number;
24
+ contract: string;
25
+ entry: boolean;
26
+ isolated: boolean;
27
+ };
28
+ }
29
+ export interface GraphEdge {
30
+ id: string;
31
+ from: string;
32
+ to: string;
33
+ type: 'nav';
34
+ label?: string;
35
+ }
36
+ export interface GraphIR {
37
+ schema: 'ia-qa-graph@1';
38
+ kind: 'navigation';
39
+ generatedAt: string;
40
+ baseUrl: string;
41
+ nodes: GraphNode[];
42
+ edges: GraphEdge[];
43
+ meta: {
44
+ /** Fans collapsed out of the drawing (a hub linking to N link-nowhere pages). */
45
+ fans: HubFan[];
46
+ /** Set when the survivors are a mesh, not a structure — else null. */
47
+ mesh: NavMesh | null;
48
+ /** Pages linked to nothing at all. */
49
+ isolated: string[];
50
+ /** Connected pages nothing links to — the way in (login, home). */
51
+ entries: string[];
52
+ /** Same-origin links to paths absent from config.pages — the coverage gap. */
53
+ unmapped: OffMapDestination[];
54
+ /** Cross-origin links, grouped by destination origin. */
55
+ external: OffMapDestination[];
56
+ /** App-wide role tally, most common first. */
57
+ roleCounts: Array<{
58
+ role: string;
59
+ count: number;
60
+ }>;
61
+ };
62
+ }
63
+ /** Project the overview + pruned graph into the canonical IR. Pure, no I/O. */
64
+ export declare function toGraphIR(overview: AppOverview, graph: NavigationGraph): GraphIR;
65
+ /**
66
+ * Linearize the IR into markdown — one section per page: what it is, where it links,
67
+ * and what reaches it. A page = one self-contained chunk, so it drops into a RAG
68
+ * index (split on the `##` headings) or a Confluence page as-is. This is the layer
69
+ * the raw JSON is not: a big JSON blob is a poor chunk; a page card is a good one.
70
+ * It carries the navigation relations the per-page `map` contracts don't.
71
+ */
72
+ export declare function renderMarkdown(ir: GraphIR): string;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toGraphIR = toGraphIR;
4
+ exports.renderMarkdown = renderMarkdown;
5
+ const NODE_PREFIX = 'page:';
6
+ const nodeId = (name) => NODE_PREFIX + name;
7
+ const slug = (name) => name.replace(/[^a-zA-Z0-9._-]+/g, '-');
8
+ /** Project the overview + pruned graph into the canonical IR. Pure, no I/O. */
9
+ function toGraphIR(overview, graph) {
10
+ const entries = new Set(graph.entries);
11
+ const isolated = new Set(graph.isolated);
12
+ const nodes = overview.pages.map((p) => ({
13
+ id: nodeId(p.name),
14
+ type: 'page',
15
+ label: p.name,
16
+ meta: {
17
+ url: p.url,
18
+ elementCount: p.elements,
19
+ contract: p.contract,
20
+ entry: entries.has(p.name),
21
+ isolated: isolated.has(p.name),
22
+ },
23
+ }));
24
+ const edges = overview.edges.map((e) => ({
25
+ id: `e:${slug(e.from)}>${slug(e.to)}`,
26
+ from: nodeId(e.from),
27
+ to: nodeId(e.to),
28
+ type: 'nav',
29
+ }));
30
+ return {
31
+ schema: 'ia-qa-graph@1',
32
+ kind: 'navigation',
33
+ generatedAt: overview.generatedAt,
34
+ baseUrl: overview.baseUrl,
35
+ nodes,
36
+ edges,
37
+ meta: {
38
+ fans: graph.fans,
39
+ mesh: graph.mesh ?? null,
40
+ isolated: graph.isolated,
41
+ entries: graph.entries,
42
+ unmapped: overview.unmapped,
43
+ external: overview.external,
44
+ roleCounts: overview.roleCounts,
45
+ },
46
+ };
47
+ }
48
+ /**
49
+ * Linearize the IR into markdown — one section per page: what it is, where it links,
50
+ * and what reaches it. A page = one self-contained chunk, so it drops into a RAG
51
+ * index (split on the `##` headings) or a Confluence page as-is. This is the layer
52
+ * the raw JSON is not: a big JSON blob is a poor chunk; a page card is a good one.
53
+ * It carries the navigation relations the per-page `map` contracts don't.
54
+ */
55
+ function renderMarkdown(ir) {
56
+ const bare = (id) => id.replace(/^page:/, '');
57
+ const out = new Map();
58
+ const into = new Map();
59
+ for (const n of ir.nodes) {
60
+ out.set(n.label, []);
61
+ into.set(n.label, []);
62
+ }
63
+ for (const e of ir.edges) {
64
+ const f = bare(e.from);
65
+ const t = bare(e.to);
66
+ out.get(f)?.push(t);
67
+ into.get(t)?.push(f);
68
+ }
69
+ const lines = [
70
+ `# Navigation knowledge — ${ir.baseUrl}`,
71
+ '',
72
+ `> ${ir.nodes.length} pages · ${ir.edges.length} links · ${ir.meta.entries.length} entry points · ` +
73
+ `${ir.meta.unmapped.length} uncovered · generated ${ir.generatedAt}`,
74
+ '',
75
+ '_One section per page — what it is, where it links, and what reaches it. A page is one RAG chunk._',
76
+ '',
77
+ ];
78
+ for (const n of ir.nodes) {
79
+ const tags = [
80
+ `${n.meta.elementCount} interactive elements`,
81
+ n.meta.entry ? 'entry point (nothing links in)' : null,
82
+ n.meta.isolated ? 'isolated (no page links)' : null,
83
+ ]
84
+ .filter(Boolean)
85
+ .join(' · ');
86
+ const links = out.get(n.label) ?? [];
87
+ const from = into.get(n.label) ?? [];
88
+ lines.push(`## ${n.label}`);
89
+ lines.push(`URL: ${n.meta.url} · ${tags}`);
90
+ lines.push(`Links to: ${links.length ? links.join(', ') : '—'}`);
91
+ lines.push(`Reached from: ${from.length ? from.join(', ') : '—'}`);
92
+ lines.push('');
93
+ }
94
+ if (ir.meta.unmapped.length) {
95
+ lines.push('## Coverage gaps — linked but never mapped');
96
+ lines.push('');
97
+ lines.push('Same-origin destinations the suite links to but no page contract covers ' +
98
+ '(candidates for `ia-qa-heal discover`):');
99
+ lines.push('');
100
+ for (const d of [...ir.meta.unmapped].sort((a, b) => b.links - a.links)) {
101
+ lines.push(`- ${d.target} — ${d.links} link${d.links === 1 ? '' : 's'} from ` +
102
+ `${d.pages.length} page${d.pages.length === 1 ? '' : 's'}`);
103
+ }
104
+ lines.push('');
105
+ }
106
+ return lines.join('\n');
107
+ }
108
+ //# sourceMappingURL=ir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ir.js","sourceRoot":"","sources":["../../src/graph/ir.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.4.1",
3
+ "version": "1.4.2",
4
4
  "description": "Local-first self-healing for UI tests: a local MCP server + CLI that map your app's pages to a role/name/selector contract, diff selector drift (PASS/FIX/BLOCK), and apply deterministic fixes to Cypress/Playwright/Selenium tests. Runs on your machine — nothing leaves it.",
5
5
  "keywords": [
6
6
  "self-healing",