@nanonets/graft 0.10.0 → 0.12.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 +34 -13
- package/dist/ai/crux.d.ts.map +1 -1
- package/dist/ai/crux.js +7 -6
- package/dist/ai/crux.js.map +1 -1
- package/dist/ai/failure.d.ts +49 -0
- package/dist/ai/failure.d.ts.map +1 -0
- package/dist/ai/failure.js +74 -0
- package/dist/ai/failure.js.map +1 -0
- package/dist/ai/llm/anthropic.d.ts.map +1 -1
- package/dist/ai/llm/anthropic.js +4 -1
- package/dist/ai/llm/anthropic.js.map +1 -1
- package/dist/ai/llm/claude-cli.d.ts +60 -0
- package/dist/ai/llm/claude-cli.d.ts.map +1 -0
- package/dist/ai/llm/claude-cli.js +417 -0
- package/dist/ai/llm/claude-cli.js.map +1 -0
- package/dist/ai/llm/openai.d.ts.map +1 -1
- package/dist/ai/llm/openai.js +2 -0
- package/dist/ai/llm/openai.js.map +1 -1
- package/dist/ai/llm/types.d.ts +9 -0
- package/dist/ai/llm/types.d.ts.map +1 -1
- package/dist/ai/llm/types.js +12 -1
- package/dist/ai/llm/types.js.map +1 -1
- package/dist/ask/ask.d.ts.map +1 -1
- package/dist/ask/ask.js +39 -45
- package/dist/ask/ask.js.map +1 -1
- package/dist/ask/fuse.d.ts +83 -46
- package/dist/ask/fuse.d.ts.map +1 -1
- package/dist/ask/fuse.js +165 -67
- package/dist/ask/fuse.js.map +1 -1
- package/dist/blast/blast-cli.d.ts +30 -0
- package/dist/blast/blast-cli.d.ts.map +1 -0
- package/dist/blast/blast-cli.js +163 -0
- package/dist/blast/blast-cli.js.map +1 -0
- package/dist/blast/blast.d.ts +119 -0
- package/dist/blast/blast.d.ts.map +1 -0
- package/dist/blast/blast.js +383 -0
- package/dist/blast/blast.js.map +1 -0
- package/dist/blast/diff.d.ts +53 -0
- package/dist/blast/diff.d.ts.map +1 -0
- package/dist/blast/diff.js +193 -0
- package/dist/blast/diff.js.map +1 -0
- package/dist/blast/modules.d.ts +33 -0
- package/dist/blast/modules.d.ts.map +1 -0
- package/dist/blast/modules.js +83 -0
- package/dist/blast/modules.js.map +1 -0
- package/dist/blast/name.d.ts +61 -0
- package/dist/blast/name.d.ts.map +1 -0
- package/dist/blast/name.js +233 -0
- package/dist/blast/name.js.map +1 -0
- package/dist/blast/render.d.ts +37 -0
- package/dist/blast/render.d.ts.map +1 -0
- package/dist/blast/render.js +300 -0
- package/dist/blast/render.js.map +1 -0
- package/dist/blast/viz.d.ts +17 -0
- package/dist/blast/viz.d.ts.map +1 -0
- package/dist/blast/viz.js +324 -0
- package/dist/blast/viz.js.map +1 -0
- package/dist/claude/hooks.d.ts +13 -0
- package/dist/claude/hooks.d.ts.map +1 -1
- package/dist/claude/hooks.js +44 -4
- package/dist/claude/hooks.js.map +1 -1
- package/dist/claude/shim-template.d.ts.map +1 -1
- package/dist/claude/shim-template.js +45 -15
- package/dist/claude/shim-template.js.map +1 -1
- package/dist/claude/state.d.ts +5 -0
- package/dist/claude/state.d.ts.map +1 -1
- package/dist/claude/state.js.map +1 -1
- package/dist/cli-picker.d.ts +44 -5
- package/dist/cli-picker.d.ts.map +1 -1
- package/dist/cli-picker.js +73 -26
- package/dist/cli-picker.js.map +1 -1
- package/dist/cli.js +270 -14
- package/dist/cli.js.map +1 -1
- package/dist/context/build.d.ts +8 -0
- package/dist/context/build.d.ts.map +1 -1
- package/dist/context/build.js +57 -9
- package/dist/context/build.js.map +1 -1
- package/dist/context/check.d.ts.map +1 -1
- package/dist/context/check.js +7 -6
- package/dist/context/check.js.map +1 -1
- package/dist/context/node-file.d.ts.map +1 -1
- package/dist/context/node-file.js +9 -2
- package/dist/context/node-file.js.map +1 -1
- package/dist/graph/bindings.d.ts.map +1 -1
- package/dist/graph/bindings.js +245 -2
- package/dist/graph/bindings.js.map +1 -1
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +36 -16
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/check.d.ts +4 -0
- package/dist/graph/check.d.ts.map +1 -1
- package/dist/graph/check.js +8 -1
- package/dist/graph/check.js.map +1 -1
- package/dist/graph/container.d.ts +63 -0
- package/dist/graph/container.d.ts.map +1 -0
- package/dist/graph/container.js +185 -0
- package/dist/graph/container.js.map +1 -0
- package/dist/graph/enrich.d.ts +18 -0
- package/dist/graph/enrich.d.ts.map +1 -1
- package/dist/graph/enrich.js +55 -2
- package/dist/graph/enrich.js.map +1 -1
- package/dist/graph/extract.d.ts +8 -1
- package/dist/graph/extract.d.ts.map +1 -1
- package/dist/graph/extract.js +401 -12
- package/dist/graph/extract.js.map +1 -1
- package/dist/graph/generic.d.ts +34 -1
- package/dist/graph/generic.d.ts.map +1 -1
- package/dist/graph/generic.js +176 -6
- package/dist/graph/generic.js.map +1 -1
- package/dist/graph/invariants.d.ts +32 -0
- package/dist/graph/invariants.d.ts.map +1 -0
- package/dist/graph/invariants.js +49 -0
- package/dist/graph/invariants.js.map +1 -0
- package/dist/graph/queries/clojure.scm +58 -0
- package/dist/graph/resolve.d.ts.map +1 -1
- package/dist/graph/resolve.js +249 -23
- package/dist/graph/resolve.js.map +1 -1
- package/dist/graph/scopes.d.ts +2 -2
- package/dist/graph/scopes.d.ts.map +1 -1
- package/dist/graph/scopes.js +8 -6
- package/dist/graph/scopes.js.map +1 -1
- package/dist/graph/source-files.d.ts +13 -4
- package/dist/graph/source-files.d.ts.map +1 -1
- package/dist/graph/source-files.js +35 -12
- package/dist/graph/source-files.js.map +1 -1
- package/dist/graph/types.d.ts +3 -1
- package/dist/graph/types.d.ts.map +1 -1
- package/dist/graph/workspace-cli.d.ts +2 -0
- package/dist/graph/workspace-cli.d.ts.map +1 -1
- package/dist/graph/workspace-cli.js +10 -4
- package/dist/graph/workspace-cli.js.map +1 -1
- package/dist/graph/workspace.d.ts +11 -6
- package/dist/graph/workspace.d.ts.map +1 -1
- package/dist/graph/workspace.js +24 -13
- package/dist/graph/workspace.js.map +1 -1
- package/dist/graph/write.d.ts.map +1 -1
- package/dist/graph/write.js +25 -2
- package/dist/graph/write.js.map +1 -1
- package/dist/hosts/antigravity.d.ts +7 -0
- package/dist/hosts/antigravity.d.ts.map +1 -0
- package/dist/hosts/antigravity.js +42 -0
- package/dist/hosts/antigravity.js.map +1 -0
- package/dist/hosts/codex-hooks.d.ts +3 -3
- package/dist/hosts/codex-hooks.d.ts.map +1 -1
- package/dist/hosts/codex-hooks.js +27 -21
- package/dist/hosts/codex-hooks.js.map +1 -1
- package/dist/hosts/init.d.ts.map +1 -1
- package/dist/hosts/init.js +6 -1
- package/dist/hosts/init.js.map +1 -1
- package/dist/hosts/mcp-config.d.ts.map +1 -1
- package/dist/hosts/mcp-config.js +7 -0
- package/dist/hosts/mcp-config.js.map +1 -1
- package/dist/hosts/plan.d.ts +1 -1
- package/dist/hosts/plan.d.ts.map +1 -1
- package/dist/hosts/plan.js +2 -0
- package/dist/hosts/plan.js.map +1 -1
- package/dist/hosts/registry.d.ts.map +1 -1
- package/dist/hosts/registry.js +13 -0
- package/dist/hosts/registry.js.map +1 -1
- package/dist/ingest/fs.d.ts +9 -2
- package/dist/ingest/fs.d.ts.map +1 -1
- package/dist/ingest/fs.js +100 -16
- package/dist/ingest/fs.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +45 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/telemetry/contract.d.ts +90 -0
- package/dist/telemetry/contract.d.ts.map +1 -0
- package/dist/telemetry/contract.js +203 -0
- package/dist/telemetry/contract.js.map +1 -0
- package/dist/telemetry/flush.d.ts +21 -0
- package/dist/telemetry/flush.d.ts.map +1 -0
- package/dist/telemetry/flush.js +84 -0
- package/dist/telemetry/flush.js.map +1 -0
- package/dist/telemetry/gate.d.ts +16 -0
- package/dist/telemetry/gate.d.ts.map +1 -0
- package/dist/telemetry/gate.js +64 -0
- package/dist/telemetry/gate.js.map +1 -0
- package/dist/telemetry/identity.d.ts +33 -0
- package/dist/telemetry/identity.d.ts.map +1 -0
- package/dist/telemetry/identity.js +80 -0
- package/dist/telemetry/identity.js.map +1 -0
- package/dist/telemetry/index.d.ts +18 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +16 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/key.d.ts +21 -0
- package/dist/telemetry/key.d.ts.map +1 -0
- package/dist/telemetry/key.js +49 -0
- package/dist/telemetry/key.js.map +1 -0
- package/dist/telemetry/notice.d.ts +19 -0
- package/dist/telemetry/notice.d.ts.map +1 -0
- package/dist/telemetry/notice.js +90 -0
- package/dist/telemetry/notice.js.map +1 -0
- package/dist/telemetry/queue.d.ts +35 -0
- package/dist/telemetry/queue.d.ts.map +1 -0
- package/dist/telemetry/queue.js +162 -0
- package/dist/telemetry/queue.js.map +1 -0
- package/dist/telemetry/send.d.ts +19 -0
- package/dist/telemetry/send.d.ts.map +1 -0
- package/dist/telemetry/send.js +84 -0
- package/dist/telemetry/send.js.map +1 -0
- package/dist/telemetry/sessions.d.ts +8 -0
- package/dist/telemetry/sessions.d.ts.map +1 -0
- package/dist/telemetry/sessions.js +81 -0
- package/dist/telemetry/sessions.js.map +1 -0
- package/dist/telemetry/track.d.ts +43 -0
- package/dist/telemetry/track.d.ts.map +1 -0
- package/dist/telemetry/track.js +108 -0
- package/dist/telemetry/track.js.map +1 -0
- package/dist/upkeep-run.d.ts +15 -0
- package/dist/upkeep-run.d.ts.map +1 -0
- package/dist/upkeep-run.js +60 -0
- package/dist/upkeep-run.js.map +1 -0
- package/dist/upkeep.d.ts +114 -0
- package/dist/upkeep.d.ts.map +1 -0
- package/dist/upkeep.js +232 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/util/num.d.ts +3 -0
- package/dist/util/num.d.ts.map +1 -0
- package/dist/util/num.js +20 -0
- package/dist/util/num.js.map +1 -0
- package/dist/util/state.d.ts +11 -4
- package/dist/util/state.d.ts.map +1 -1
- package/dist/util/state.js +9 -0
- package/dist/util/state.js.map +1 -1
- package/dist/viewer/app.js +1 -1
- package/dist/viewer/index.html +1 -0
- package/dist/viewer/style.css +23 -2
- package/dist/viz/assemble.d.ts +33 -0
- package/dist/viz/assemble.d.ts.map +1 -1
- package/dist/viz/assemble.js.map +1 -1
- package/dist/viz/export.d.ts +39 -0
- package/dist/viz/export.d.ts.map +1 -0
- package/dist/viz/export.js +98 -0
- package/dist/viz/export.js.map +1 -0
- package/package.json +15 -5
- package/scripts/stamp-telemetry-key.mjs +53 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { GraphV1 } from "../graph/types.js";
|
|
2
|
+
import { type ModuleIndex } from "./modules.js";
|
|
3
|
+
import type { ChangedFile } from "./diff.js";
|
|
4
|
+
export interface BlastOptions {
|
|
5
|
+
/** BFS depth over incoming edges; `Infinity` for the full closure. */
|
|
6
|
+
depth: number;
|
|
7
|
+
/** Concept/directory labels. Built from the context dir when omitted. */
|
|
8
|
+
modules?: ModuleIndex;
|
|
9
|
+
}
|
|
10
|
+
/** A changed symbol the walk started from. */
|
|
11
|
+
export interface Seed {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
kind: string;
|
|
15
|
+
path: string;
|
|
16
|
+
span: string;
|
|
17
|
+
/** True for a whole-file seed (an added file, or a change outside any symbol). */
|
|
18
|
+
wholeFile: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** One dependent symbol, and how the walk reached it. */
|
|
21
|
+
export interface Impacted {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
kind: string;
|
|
25
|
+
path: string;
|
|
26
|
+
span: string;
|
|
27
|
+
relation: string;
|
|
28
|
+
depth: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Where a cluster's label came from — the rungs of the naming ladder.
|
|
32
|
+
*
|
|
33
|
+
* `concept` — a concept node from a `--deep` build claims every file in the cluster.
|
|
34
|
+
* `named` — `graft blast --name` asked a model to name this cluster (see name.ts).
|
|
35
|
+
* `symbol` — the deterministic backstop: the cluster's most significant symbol.
|
|
36
|
+
*
|
|
37
|
+
* A bare directory is never a label. The whole point of the picture is that a
|
|
38
|
+
* reviewer reads what is affected, and `src/graph/` tells them nothing they could
|
|
39
|
+
* not get from the diff — but it must never be replaced by a guess either, so the
|
|
40
|
+
* backstop names a real symbol rather than inventing a feature name.
|
|
41
|
+
*/
|
|
42
|
+
export type LabelSource = "concept" | "named" | "symbol";
|
|
43
|
+
/** Dependents grouped for the diagram: the unit a reviewer actually thinks in. */
|
|
44
|
+
export interface ImpactedModule {
|
|
45
|
+
label: string;
|
|
46
|
+
labelSource: LabelSource;
|
|
47
|
+
/** Stable identity for the cluster, independent of its label: the concept name
|
|
48
|
+
* or the directory it was grouped by. Naming and its cache key hang off this. */
|
|
49
|
+
key: string;
|
|
50
|
+
files: string[];
|
|
51
|
+
symbols: Impacted[];
|
|
52
|
+
/** Changed files whose edges reached this module — the diagram's arrows. */
|
|
53
|
+
from: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether the diff brought its tests along.
|
|
57
|
+
*
|
|
58
|
+
* `changed` — a test file that reaches this area was edited in this PR.
|
|
59
|
+
* `stale` — tests reach it and the diff left every one of them alone.
|
|
60
|
+
* `none` — nothing under `test/` reaches it at all.
|
|
61
|
+
* `na` — no function, method or class changed here, so there is nothing to
|
|
62
|
+
* ask the question of: a types-only file, or config and wiring.
|
|
63
|
+
*/
|
|
64
|
+
export type TestSignal = "changed" | "stale" | "none" | "na";
|
|
65
|
+
/** One area of the diff: the changed files a reviewer thinks of as one thing. */
|
|
66
|
+
export interface ChangedArea {
|
|
67
|
+
label: string;
|
|
68
|
+
labelSource: LabelSource;
|
|
69
|
+
/** The directory the cluster was grouped by — see {@link ImpactedModule.key}. */
|
|
70
|
+
key: string;
|
|
71
|
+
/** Changed, indexed, non-test files grouped under this label. */
|
|
72
|
+
files: string[];
|
|
73
|
+
/** Changed symbols seeded from those files. */
|
|
74
|
+
seeds: number;
|
|
75
|
+
tests: TestSignal;
|
|
76
|
+
/** Test files with an edge into this area, and those of them the diff changed. */
|
|
77
|
+
testFiles: string[];
|
|
78
|
+
changedTestFiles: string[];
|
|
79
|
+
/** Test reach, over the area's exported functions/methods/classes only. */
|
|
80
|
+
reached: number;
|
|
81
|
+
behavioural: number;
|
|
82
|
+
/** Names of the behavioural symbols no test reaches, for the collapsed detail. */
|
|
83
|
+
unreached: string[];
|
|
84
|
+
/** Changed symbol names, behaviour first — the backstop label and the naming
|
|
85
|
+
* prompt both read from this. */
|
|
86
|
+
seedNames: string[];
|
|
87
|
+
}
|
|
88
|
+
export interface BlastReport {
|
|
89
|
+
basis: string;
|
|
90
|
+
depth: number;
|
|
91
|
+
changed: ChangedFile[];
|
|
92
|
+
/** Changed paths the graph has no node for: unsupported language, or deleted. */
|
|
93
|
+
unindexed: string[];
|
|
94
|
+
/** Changed paths that were deleted, called out because their dependents are
|
|
95
|
+
* unknowable from a graph built at the post-change commit. */
|
|
96
|
+
deleted: string[];
|
|
97
|
+
seeds: Seed[];
|
|
98
|
+
impacted: Impacted[];
|
|
99
|
+
modules: ImpactedModule[];
|
|
100
|
+
/** The diff itself, grouped: the left-hand side of the diagram. */
|
|
101
|
+
areas: ChangedArea[];
|
|
102
|
+
/** Test-only dependents, kept out of `modules` so they cannot crowd it out. */
|
|
103
|
+
testModules: ImpactedModule[];
|
|
104
|
+
}
|
|
105
|
+
/** Compute the blast radius of `changed` against `graph`. */
|
|
106
|
+
export declare function blastRadius(graph: GraphV1, changed: ChangedFile[], basis: string, opts: BlastOptions): BlastReport;
|
|
107
|
+
/** Convenience wrapper: build the module index from a context dir. */
|
|
108
|
+
export declare function blastRadiusIn(graph: GraphV1, contextDir: string, changed: ChangedFile[], basis: string, depth: number): BlastReport;
|
|
109
|
+
/**
|
|
110
|
+
* The deterministic backstop label: the cluster's most significant symbol.
|
|
111
|
+
*
|
|
112
|
+
* Reached with no concept, no cache and no API key, so this is what guarantees a
|
|
113
|
+
* circle never carries a bare directory. It is a fact rather than a guess — the
|
|
114
|
+
* reviewer can grep the name — which is why it beats borrowing a neighbouring
|
|
115
|
+
* concept: on graft's own graph that borrowing labelled the freshness gate
|
|
116
|
+
* "Graph Extraction and Loading", which misleads worse than any path.
|
|
117
|
+
*/
|
|
118
|
+
export declare function hubLabel(names: string[], fallback: string): string;
|
|
119
|
+
//# sourceMappingURL=blast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blast.d.ts","sourceRoot":"","sources":["../../src/blast/blast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blast radius of a diff: what else in the repo depends on the lines this change
|
|
3
|
+
* touched.
|
|
4
|
+
*
|
|
5
|
+
* The whole command is a join between two things graft already has — git's changed
|
|
6
|
+
* line ranges (`diff.ts`) and the wiring graph's incoming edges (`traverse.ts`) —
|
|
7
|
+
* so there is no new graph logic here, only the seeding rule:
|
|
8
|
+
*
|
|
9
|
+
* changed line → the innermost symbol whose span contains it → seed
|
|
10
|
+
*
|
|
11
|
+
* Seeding by SYMBOL rather than by file is what makes the answer worth reading: a
|
|
12
|
+
* 400-line file with a one-line edit reports the dependents of that one function,
|
|
13
|
+
* not of everything the file happens to define. The file node is seeded too, so
|
|
14
|
+
* importers (whose edge targets the file, not the symbol) are still found.
|
|
15
|
+
*/
|
|
16
|
+
import { impactOfMany } from "../graph/traverse.js";
|
|
17
|
+
import { dirLabel, moduleIndex, parentDir, shortLabel } from "./modules.js";
|
|
18
|
+
const SPAN_RE = /^L(\d+)-L(\d+)$/;
|
|
19
|
+
function spanBounds(span) {
|
|
20
|
+
const m = SPAN_RE.exec(span);
|
|
21
|
+
return m ? { start: Number(m[1]), end: Number(m[2]) } : null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The innermost symbols whose spans overlap any changed range in `path`.
|
|
25
|
+
*
|
|
26
|
+
* "Innermost" matters for a method: a changed line inside `Cache.get` overlaps both
|
|
27
|
+
* the class span and the method span, and seeding the class would report everyone
|
|
28
|
+
* who touches any part of `Cache`. Nesting is resolved by keeping, for each range,
|
|
29
|
+
* only symbols that contain no other matched symbol.
|
|
30
|
+
*/
|
|
31
|
+
function seedsForFile(graph, path, ranges) {
|
|
32
|
+
const symbols = [];
|
|
33
|
+
for (const n of graph.nodes) {
|
|
34
|
+
if (n.kind === "file" || n.path !== path)
|
|
35
|
+
continue;
|
|
36
|
+
const b = spanBounds(n.span);
|
|
37
|
+
if (b)
|
|
38
|
+
symbols.push({ node: n, ...b });
|
|
39
|
+
}
|
|
40
|
+
if (symbols.length === 0)
|
|
41
|
+
return [];
|
|
42
|
+
const hit = new Map();
|
|
43
|
+
for (const r of ranges) {
|
|
44
|
+
const overlapping = symbols.filter((s) => s.start <= r.end && s.end >= r.start);
|
|
45
|
+
// Drop any symbol that strictly contains another overlapping one (the class
|
|
46
|
+
// around a changed method), keeping the tightest description of the edit.
|
|
47
|
+
for (const s of overlapping) {
|
|
48
|
+
const containsAnother = overlapping.some((o) => o !== s && o.start >= s.start && o.end <= s.end);
|
|
49
|
+
if (!containsAnother)
|
|
50
|
+
hit.set(s.node.id, s.node);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return [...hit.values()];
|
|
54
|
+
}
|
|
55
|
+
/** Compute the blast radius of `changed` against `graph`. */
|
|
56
|
+
export function blastRadius(graph, changed, basis, opts) {
|
|
57
|
+
const fileNodes = new Map();
|
|
58
|
+
for (const n of graph.nodes)
|
|
59
|
+
if (n.kind === "file")
|
|
60
|
+
fileNodes.set(n.path, n);
|
|
61
|
+
const seeds = [];
|
|
62
|
+
const unindexed = [];
|
|
63
|
+
const deleted = [];
|
|
64
|
+
/** Seed nodes per changed file, kept for the area grouping and the test signal. */
|
|
65
|
+
const seedNodes = new Map();
|
|
66
|
+
/** Merged dependents, keyed by node id, at the shallowest depth any file reached
|
|
67
|
+
* them — plus which changed files did the reaching. */
|
|
68
|
+
const merged = new Map();
|
|
69
|
+
for (const file of changed) {
|
|
70
|
+
if (file.status === "deleted") {
|
|
71
|
+
deleted.push(file.path);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const fileNode = fileNodes.get(file.path);
|
|
75
|
+
if (!fileNode) {
|
|
76
|
+
unindexed.push(file.path);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
// No hunk ranges (a rename with no content change, a mode change) or an added
|
|
80
|
+
// file: the unit of change is the file itself.
|
|
81
|
+
const symbolSeeds = file.ranges.length > 0 ? seedsForFile(graph, file.path, file.ranges) : [];
|
|
82
|
+
for (const node of symbolSeeds) {
|
|
83
|
+
seeds.push({ id: node.id, name: node.name, kind: node.kind, path: node.path, span: node.span, wholeFile: false });
|
|
84
|
+
}
|
|
85
|
+
if (symbolSeeds.length === 0) {
|
|
86
|
+
seeds.push({
|
|
87
|
+
id: fileNode.id, name: fileNode.name, kind: fileNode.kind,
|
|
88
|
+
path: fileNode.path, span: fileNode.span, wholeFile: true,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// One walk PER CHANGED FILE, not one walk over every seed at once. A combined
|
|
92
|
+
// walk records the depth a node was first reached at but not by which seed, so
|
|
93
|
+
// the diagram could only draw "every changed file reaches every module" — a
|
|
94
|
+
// cross-product that tells a reviewer nothing. Walking per file costs one
|
|
95
|
+
// adjacency build each (cheap: the graph is already in memory) and buys arrows
|
|
96
|
+
// that are true.
|
|
97
|
+
//
|
|
98
|
+
// The FILE node is a seed only when no symbol matched. `imports` edges target
|
|
99
|
+
// the file id, so seeding it alongside symbols would pull in every importer of
|
|
100
|
+
// the file — a one-line edit to one function would report every module that
|
|
101
|
+
// imports the module, which is the noise this command exists to avoid. With no
|
|
102
|
+
// symbol seeds (a change to a top-level constant, a new import, a file with no
|
|
103
|
+
// extracted symbols) the file IS the unit of change, and its importers are the
|
|
104
|
+
// only dependents there are.
|
|
105
|
+
const walkSeeds = symbolSeeds.length > 0 ? symbolSeeds : [fileNode];
|
|
106
|
+
seedNodes.set(file.path, walkSeeds);
|
|
107
|
+
const hits = impactOfMany(graph, walkSeeds, opts.depth, "in");
|
|
108
|
+
for (const h of hits) {
|
|
109
|
+
if (!hasNode(h))
|
|
110
|
+
continue;
|
|
111
|
+
const hit = toImpacted(h);
|
|
112
|
+
const prev = merged.get(hit.id);
|
|
113
|
+
if (!prev)
|
|
114
|
+
merged.set(hit.id, { hit, from: new Set([file.path]) });
|
|
115
|
+
else {
|
|
116
|
+
prev.from.add(file.path);
|
|
117
|
+
// Keep the shallowest reach: a symbol two hops from one changed file and one
|
|
118
|
+
// hop from another is one hop away from this PR.
|
|
119
|
+
if (hit.depth < prev.hit.depth)
|
|
120
|
+
prev.hit = hit;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const impacted = [...merged.values()].map((m) => m.hit);
|
|
125
|
+
const origins = new Map([...merged].map(([id, m]) => [id, m.from]));
|
|
126
|
+
const index = opts.modules ?? emptyIndex();
|
|
127
|
+
const grouped = groupByModule(impacted, changed, origins, index);
|
|
128
|
+
return {
|
|
129
|
+
basis,
|
|
130
|
+
depth: opts.depth,
|
|
131
|
+
changed,
|
|
132
|
+
unindexed,
|
|
133
|
+
deleted,
|
|
134
|
+
seeds,
|
|
135
|
+
impacted,
|
|
136
|
+
modules: grouped.modules,
|
|
137
|
+
testModules: grouped.testModules,
|
|
138
|
+
areas: changedAreas(graph, changed, seedNodes, index, grouped.modules),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Group the changed files into areas, and work out whether each one's tests moved.
|
|
143
|
+
*
|
|
144
|
+
* The diff's own side of the diagram used to be one box per changed file, which can
|
|
145
|
+
* never fit: a 24-file PR drew ten arbitrary paths. Grouped by the same concept
|
|
146
|
+
* labels the dependents use, the same PR is three or four circles — and once the
|
|
147
|
+
* files are grouped, "did a test that reaches this move too?" is one question per
|
|
148
|
+
* circle instead of per file.
|
|
149
|
+
*/
|
|
150
|
+
function changedAreas(graph, changed, seedNodes, index, modules) {
|
|
151
|
+
const changedTests = new Set(changed.filter((c) => TEST_PATH.test(c.path)).map((c) => c.path));
|
|
152
|
+
const nodeById = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
153
|
+
/** How many edges point AT each node — how central it is in the graph. */
|
|
154
|
+
const inDegree = new Map();
|
|
155
|
+
for (const e of graph.edges)
|
|
156
|
+
inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);
|
|
157
|
+
/** Incoming edge sources per node id, resolved to the source's file path. */
|
|
158
|
+
const incoming = new Map();
|
|
159
|
+
for (const e of graph.edges) {
|
|
160
|
+
const path = nodeById.get(e.source)?.path;
|
|
161
|
+
if (!path || !TEST_PATH.test(path))
|
|
162
|
+
continue;
|
|
163
|
+
const at = incoming.get(e.target) ?? new Set();
|
|
164
|
+
at.add(path);
|
|
165
|
+
incoming.set(e.target, at);
|
|
166
|
+
}
|
|
167
|
+
// Group by DIRECTORY, not by concept. Concepts in a well-summarised repo are
|
|
168
|
+
// near-file-grained — graft's own PR produced nine of them, one file each — so
|
|
169
|
+
// grouping the diff by concept groups nothing: the left side was nine circles
|
|
170
|
+
// with near-identical truncated names. A directory is the coarser unit reviewers
|
|
171
|
+
// already use, and a concept name is only worth borrowing when one concept
|
|
172
|
+
// happens to claim the whole group.
|
|
173
|
+
const groups = new Map();
|
|
174
|
+
for (const path of seedNodes.keys()) {
|
|
175
|
+
// A changed test file is the signal, not the source of a blast radius. Drawing
|
|
176
|
+
// it as an area would put "your tests changed" on both sides of the arrow.
|
|
177
|
+
if (TEST_PATH.test(path))
|
|
178
|
+
continue;
|
|
179
|
+
const dir = dirLabel(path);
|
|
180
|
+
groups.set(dir, [...(groups.get(dir) ?? []), path]);
|
|
181
|
+
}
|
|
182
|
+
coarsen(groups, MAX_AREAS);
|
|
183
|
+
const byKey = new Map();
|
|
184
|
+
/** Hub candidates per area, ranked once every seed has been seen. */
|
|
185
|
+
const candidates = new Map();
|
|
186
|
+
for (const [dir, paths] of groups) {
|
|
187
|
+
const area = {
|
|
188
|
+
label: dir, labelSource: "symbol", key: dir,
|
|
189
|
+
files: [], seeds: 0, tests: "none", testFiles: [], changedTestFiles: [],
|
|
190
|
+
reached: 0, behavioural: 0, unreached: [], seedNames: [],
|
|
191
|
+
};
|
|
192
|
+
byKey.set(dir, area);
|
|
193
|
+
for (const path of paths) {
|
|
194
|
+
const nodes = seedNodes.get(path) ?? [];
|
|
195
|
+
area.files.push(path);
|
|
196
|
+
area.seeds += nodes.length;
|
|
197
|
+
for (const node of nodes) {
|
|
198
|
+
// Reach is measured over behaviour only. Counting interfaces and type aliases
|
|
199
|
+
// would sink every ratio: nothing "calls" a type, so a fully tested area of
|
|
200
|
+
// typed code would report a third of its symbols as unreached.
|
|
201
|
+
const behavioural = node.kind === "function" || node.kind === "method" || node.kind === "class";
|
|
202
|
+
const from = incoming.get(node.id) ?? new Set();
|
|
203
|
+
for (const t of from) {
|
|
204
|
+
if (!area.testFiles.includes(t))
|
|
205
|
+
area.testFiles.push(t);
|
|
206
|
+
if (changedTests.has(t) && !area.changedTestFiles.includes(t))
|
|
207
|
+
area.changedTestFiles.push(t);
|
|
208
|
+
}
|
|
209
|
+
candidates.set(area, [
|
|
210
|
+
...(candidates.get(area) ?? []),
|
|
211
|
+
{ name: node.name, behavioural, degree: inDegree.get(node.id) ?? 0 },
|
|
212
|
+
]);
|
|
213
|
+
if (!behavioural)
|
|
214
|
+
continue;
|
|
215
|
+
area.behavioural++;
|
|
216
|
+
if (from.size > 0)
|
|
217
|
+
area.reached++;
|
|
218
|
+
else
|
|
219
|
+
area.unreached.push(node.name);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const area of byKey.values()) {
|
|
224
|
+
// The hub is the most-depended-on function in the area, not whichever symbol the
|
|
225
|
+
// file walk happened to end on: `LlmFailureGate` rather than `transportRetries`.
|
|
226
|
+
// Behaviour outranks types, since nothing calls an interface.
|
|
227
|
+
area.seedNames = (candidates.get(area) ?? [])
|
|
228
|
+
.sort((a, b) => Number(b.behavioural) - Number(a.behavioural) || b.degree - a.degree || a.name.localeCompare(b.name))
|
|
229
|
+
.map((c) => c.name);
|
|
230
|
+
const concept = sharedConcept(area.files, index);
|
|
231
|
+
area.label = concept ?? hubLabel(area.seedNames, area.key);
|
|
232
|
+
area.labelSource = concept ? "concept" : "symbol";
|
|
233
|
+
area.files.sort();
|
|
234
|
+
area.testFiles.sort();
|
|
235
|
+
area.changedTestFiles.sort();
|
|
236
|
+
area.tests =
|
|
237
|
+
area.behavioural === 0 ? "na"
|
|
238
|
+
: area.changedTestFiles.length > 0 ? "changed"
|
|
239
|
+
: area.testFiles.length > 0 ? "stale"
|
|
240
|
+
: "none";
|
|
241
|
+
}
|
|
242
|
+
// Ordered by how much each area actually reaches, because the diagram caps this
|
|
243
|
+
// list and folds the rest into one circle. Ordered by size instead, the fold ends
|
|
244
|
+
// up holding the best-connected areas and the tail circle collects every arrow —
|
|
245
|
+
// the same mistake, one level up, as capping changed FILES in diff order.
|
|
246
|
+
const reach = (a) => modules.filter((m) => m.from.some((f) => a.files.includes(f))).length;
|
|
247
|
+
return [...byKey.values()].sort((a, b) => reach(b) - reach(a) || b.files.length - a.files.length || a.label.localeCompare(b.label));
|
|
248
|
+
}
|
|
249
|
+
/** Convenience wrapper: build the module index from a context dir. */
|
|
250
|
+
export function blastRadiusIn(graph, contextDir, changed, basis, depth) {
|
|
251
|
+
return blastRadius(graph, changed, basis, { depth, modules: moduleIndex(contextDir) });
|
|
252
|
+
}
|
|
253
|
+
function hasNode(h) {
|
|
254
|
+
// Unresolved endpoints (an import module string no node exists for) carry no
|
|
255
|
+
// location, so they can neither be grouped nor opened — dropped rather than
|
|
256
|
+
// rendered as a box with no file behind it.
|
|
257
|
+
return h.node !== null;
|
|
258
|
+
}
|
|
259
|
+
function toImpacted(h) {
|
|
260
|
+
return {
|
|
261
|
+
id: h.node.id, name: h.node.name, kind: h.node.kind,
|
|
262
|
+
path: h.node.path, span: h.node.span, relation: h.relation, depth: h.depth,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function emptyIndex() {
|
|
266
|
+
return { hasConcepts: false, labelOf: (p) => p, conceptOf: () => null };
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* The concept claiming EVERY file in a cluster, or null when they disagree.
|
|
270
|
+
*
|
|
271
|
+
* Unanimity is the point: a concept that covers three of five files describes
|
|
272
|
+
* something narrower than the cluster, and stamping its name on the whole thing is
|
|
273
|
+
* how a diagram starts lying about what it drew.
|
|
274
|
+
*/
|
|
275
|
+
function sharedConcept(paths, index) {
|
|
276
|
+
const concepts = new Set(paths.map((p) => index.conceptOf(p)));
|
|
277
|
+
const [only] = concepts;
|
|
278
|
+
return concepts.size === 1 && only ? shortLabel(only) : null;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The deterministic backstop label: the cluster's most significant symbol.
|
|
282
|
+
*
|
|
283
|
+
* Reached with no concept, no cache and no API key, so this is what guarantees a
|
|
284
|
+
* circle never carries a bare directory. It is a fact rather than a guess — the
|
|
285
|
+
* reviewer can grep the name — which is why it beats borrowing a neighbouring
|
|
286
|
+
* concept: on graft's own graph that borrowing labelled the freshness gate
|
|
287
|
+
* "Graph Extraction and Loading", which misleads worse than any path.
|
|
288
|
+
*/
|
|
289
|
+
export function hubLabel(names, fallback) {
|
|
290
|
+
const [head] = names.filter(Boolean);
|
|
291
|
+
// The hub alone, with no "+8" tail: how many symbols came with it is already the
|
|
292
|
+
// circle's second line and the table's own column, and repeating it in the label
|
|
293
|
+
// turned "writeGraph" into "writeGraph +8", which reads as a version number.
|
|
294
|
+
return head ? shortLabel(head) : fallback;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Group dependents into modules. `origins` carries, per dependent, the changed
|
|
298
|
+
* files whose walk actually reached it — so a module's `from` is the real arrow
|
|
299
|
+
* set, not every changed file in the PR.
|
|
300
|
+
*/
|
|
301
|
+
function groupByModule(impacted, changed, origins, modules) {
|
|
302
|
+
const changedPaths = new Set(changed.map((c) => c.path));
|
|
303
|
+
const byKey = new Map();
|
|
304
|
+
for (const hit of impacted) {
|
|
305
|
+
// A dependent inside a file the PR already changes is not "reach" — it is the
|
|
306
|
+
// diff. Reviewers see it in the diff itself; repeating it as blast radius is
|
|
307
|
+
// what makes these comments feel like noise.
|
|
308
|
+
if (changedPaths.has(hit.path))
|
|
309
|
+
continue;
|
|
310
|
+
// Cluster by concept where one exists, else by directory. Clustering and
|
|
311
|
+
// LABELLING are separate steps now: the key only has to be stable, while the
|
|
312
|
+
// label goes through the ladder below and may end up naming a symbol.
|
|
313
|
+
const key = modules.conceptOf(hit.path) ?? dirLabel(hit.path);
|
|
314
|
+
let mod = byKey.get(key);
|
|
315
|
+
if (!mod) {
|
|
316
|
+
mod = { label: key, labelSource: "symbol", key, files: [], symbols: [], from: [] };
|
|
317
|
+
byKey.set(key, mod);
|
|
318
|
+
}
|
|
319
|
+
mod.symbols.push(hit);
|
|
320
|
+
if (!mod.files.includes(hit.path))
|
|
321
|
+
mod.files.push(hit.path);
|
|
322
|
+
}
|
|
323
|
+
for (const mod of byKey.values()) {
|
|
324
|
+
const from = new Set();
|
|
325
|
+
for (const s of mod.symbols)
|
|
326
|
+
for (const p of origins.get(s.id) ?? [])
|
|
327
|
+
from.add(p);
|
|
328
|
+
mod.from = [...from].sort();
|
|
329
|
+
mod.files.sort();
|
|
330
|
+
mod.symbols.sort((a, b) => a.depth - b.depth || a.path.localeCompare(b.path));
|
|
331
|
+
// Shallowest symbol first after that sort, so it is the cluster's hub: the
|
|
332
|
+
// thing one hop from the diff rather than an arbitrary member.
|
|
333
|
+
const concept = sharedConcept(mod.files, modules);
|
|
334
|
+
mod.label = concept ?? hubLabel(mod.symbols.map((s) => s.name), mod.key);
|
|
335
|
+
mod.labelSource = concept ? "concept" : "symbol";
|
|
336
|
+
}
|
|
337
|
+
// Test-only modules are separated, not just sorted last. On a repo with a test
|
|
338
|
+
// per module they are the majority of the graph's dependents — graft's own 24-file
|
|
339
|
+
// PR produced 31 modules, 24 of them a single test file — so leaving them in the
|
|
340
|
+
// same list means they crowd out every module a reviewer needs whatever the caps
|
|
341
|
+
// are. "Your tests reference the thing you changed" is one line, not 24 sections.
|
|
342
|
+
const bySize = (a, b) => b.symbols.length - a.symbols.length || a.label.localeCompare(b.label);
|
|
343
|
+
const all = [...byKey.values()];
|
|
344
|
+
return {
|
|
345
|
+
modules: all.filter((m) => !isTestOnly(m)).sort(bySize),
|
|
346
|
+
testModules: all.filter(isTestOnly).sort(bySize),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Directory groups the diff is folded down to before anything is drawn.
|
|
351
|
+
*
|
|
352
|
+
* Kept here rather than in the renderer because it is a statement about the diff,
|
|
353
|
+
* not about the picture: five areas is roughly what a reviewer holds in their head,
|
|
354
|
+
* and the renderer then draws all of them.
|
|
355
|
+
*/
|
|
356
|
+
const MAX_AREAS = 5;
|
|
357
|
+
/**
|
|
358
|
+
* Fold directory groups into their parents until there are at most `max`.
|
|
359
|
+
*
|
|
360
|
+
* The deepest group goes first, and only into a parent that already exists, so
|
|
361
|
+
* `src/ai/llm/` joins `src/ai/` rather than everything collapsing towards the repo
|
|
362
|
+
* root. When no group has an existing parent, one is created — but never at the top
|
|
363
|
+
* level, since a single `(root)` area is no grouping at all.
|
|
364
|
+
*/
|
|
365
|
+
function coarsen(groups, max) {
|
|
366
|
+
const depth = (dir) => dir.split("/").length;
|
|
367
|
+
while (groups.size > max) {
|
|
368
|
+
const keys = [...groups.keys()].sort((a, b) => depth(b) - depth(a) || (groups.get(a).length - groups.get(b).length));
|
|
369
|
+
const pick = keys.find((k) => groups.has(parentDir(k)) && parentDir(k) !== "") ??
|
|
370
|
+
keys.find((k) => parentDir(k) !== "");
|
|
371
|
+
if (!pick)
|
|
372
|
+
return;
|
|
373
|
+
const parent = parentDir(pick);
|
|
374
|
+
groups.set(parent, [...(groups.get(parent) ?? []), ...groups.get(pick)]);
|
|
375
|
+
groups.delete(pick);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
const TEST_PATH = /(^|\/)(tests?|specs?|__tests__)\/|\.(test|spec)\.[cm]?[jt]sx?$|_test\.(go|py|rb)$/i;
|
|
379
|
+
/** True when every file in the module is a test file. */
|
|
380
|
+
function isTestOnly(mod) {
|
|
381
|
+
return mod.files.length > 0 && mod.files.every((f) => TEST_PATH.test(f));
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=blast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blast.js","sourceRoot":"","sources":["../../src/blast/blast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ChangeStatus = "added" | "modified" | "deleted" | "renamed";
|
|
2
|
+
/** A contiguous run of changed lines, in POST-image (new file) line numbers. */
|
|
3
|
+
export interface LineRange {
|
|
4
|
+
start: number;
|
|
5
|
+
end: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* One line git reported inside a hunk.
|
|
9
|
+
*
|
|
10
|
+
* `n` is the POST-image number, so it is the number a reviewer sees in the file
|
|
11
|
+
* on disk — a deleted line has none.
|
|
12
|
+
*/
|
|
13
|
+
export interface DiffLine {
|
|
14
|
+
n: number | null;
|
|
15
|
+
sign: "+" | "-";
|
|
16
|
+
text: string;
|
|
17
|
+
}
|
|
18
|
+
/** A hunk's range and the lines in it. `ranges` on the file mirrors these. */
|
|
19
|
+
export interface Hunk extends LineRange {
|
|
20
|
+
lines: DiffLine[];
|
|
21
|
+
/** Lines dropped by the per-hunk cap — a generated file is not worth holding. */
|
|
22
|
+
dropped: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ChangedFile {
|
|
25
|
+
/** Repo-relative posix path, post-image (the new name for a rename). */
|
|
26
|
+
path: string;
|
|
27
|
+
status: ChangeStatus;
|
|
28
|
+
/** Pre-image path, renames only. */
|
|
29
|
+
oldPath?: string;
|
|
30
|
+
/** Post-image changed line ranges. Empty for a pure delete or a mode-only change. */
|
|
31
|
+
ranges: LineRange[];
|
|
32
|
+
/** The same hunks, carrying their text: what a panel shows so a reader sees the
|
|
33
|
+
* change rather than a line number they have to go look up. One per range. */
|
|
34
|
+
hunks: Hunk[];
|
|
35
|
+
}
|
|
36
|
+
export interface DiffResult {
|
|
37
|
+
/** Human label for what was compared, e.g. "origin/main...HEAD". */
|
|
38
|
+
basis: string;
|
|
39
|
+
files: ChangedFile[];
|
|
40
|
+
}
|
|
41
|
+
/** True when `ref` names something git can resolve — checked before diffing so
|
|
42
|
+
* an unknown `--base` fails with a caller-facing message, not a git stack. */
|
|
43
|
+
export declare function refExists(root: string, ref: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Changed files + post-image line ranges.
|
|
46
|
+
*
|
|
47
|
+
* With no `base` this reports the working tree against HEAD (the local
|
|
48
|
+
* "what am I about to push" case), falling back to the last commit when the
|
|
49
|
+
* tree is clean — so the command answers something useful when run by hand,
|
|
50
|
+
* and CI passes `--base` for the real PR range.
|
|
51
|
+
*/
|
|
52
|
+
export declare function changedFiles(root: string, base?: string): DiffResult | null;
|
|
53
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/blast/diff.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAExE,gFAAgF;AAChF,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,WAAW,IAAK,SAAQ,SAAS;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB;kFAC8E;IAC9E,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAsBD;8EAC8E;AAC9E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE5D;AAcD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAe3E"}
|