@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 +18 -0
- package/TUTORIAL.md +8 -0
- package/dist/cli/graph.d.ts +1 -0
- package/dist/cli/graph.js +153 -0
- package/dist/cli/graph.js.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/graph/ir.d.ts +72 -0
- package/dist/graph/ir.js +108 -0
- package/dist/graph/ir.js.map +1 -0
- package/package.json +1 -1
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;
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;;AACA,sCAAuC;AACvC,iCAAiC;AACjC,+BAA+B;AAC/B,yCAAyC;AACzC,iCAAiC;AACjC,+BAA+B;AAC/B,qCAAqC;AACrC,+BAA+B;AAC/B,yCAAyC;
|
|
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;
|
package/dist/graph/ir.js
ADDED
|
@@ -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.
|
|
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",
|