@intentius/chant 0.8.2 → 0.10.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/dist/cli/handlers/graph.d.ts +2 -1
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +8 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/graph-detail.d.ts +21 -0
- package/dist/graph-detail.d.ts.map +1 -0
- package/dist/graph-dot.d.ts +12 -0
- package/dist/graph-dot.d.ts.map +1 -0
- package/dist/graph-ir.d.ts +78 -0
- package/dist/graph-ir.d.ts.map +1 -0
- package/dist/graph-layout.d.ts +39 -0
- package/dist/graph-layout.d.ts.map +1 -0
- package/dist/graph-lens.d.ts +30 -0
- package/dist/graph-lens.d.ts.map +1 -0
- package/dist/graph-mermaid.d.ts +17 -0
- package/dist/graph-mermaid.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/provenance.d.ts +8 -1
- package/dist/provenance.d.ts.map +1 -1
- package/dist/reconcile.d.ts +147 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/cli/handlers/graph.test.ts +166 -48
- package/src/cli/handlers/graph.ts +86 -1
- package/src/cli/main.test.ts +16 -0
- package/src/cli/main.ts +14 -1
- package/src/cli/registry.ts +8 -0
- package/src/discovery/collect.ts +2 -2
- package/src/graph-detail.test.ts +79 -0
- package/src/graph-detail.ts +149 -0
- package/src/graph-dot.test.ts +68 -0
- package/src/graph-dot.ts +58 -0
- package/src/graph-ir.test.ts +122 -0
- package/src/graph-ir.ts +285 -0
- package/src/graph-layout.ts +104 -0
- package/src/graph-lens.test.ts +80 -0
- package/src/graph-lens.ts +127 -0
- package/src/graph-mermaid.test.ts +61 -0
- package/src/graph-mermaid.ts +85 -0
- package/src/index.ts +6 -0
- package/src/provenance.ts +9 -1
- package/src/reconcile.test.ts +224 -0
- package/src/reconcile.ts +346 -0
|
@@ -2,7 +2,8 @@ import type { CommandContext } from "../registry.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* `chant graph` — the Op dependency graph by default; `--stacks` renders the
|
|
4
4
|
* cross-stack apply-ordering graph (edges, order, waves) chant computes from
|
|
5
|
-
* cross-lexicon references
|
|
5
|
+
* cross-lexicon references; `--format ir|mermaid` emits the lint-gated
|
|
6
|
+
* entity-graph IR (or a Mermaid flowchart of it) for diagrams (#493/#496).
|
|
6
7
|
*/
|
|
7
8
|
export declare function runGraph(ctx: CommandContext): Promise<number>;
|
|
8
9
|
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/graph.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/graph.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAOnE"}
|
package/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAe9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAe9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA6IpD"}
|
package/dist/cli/registry.d.ts
CHANGED
|
@@ -56,6 +56,14 @@ export interface ParsedArgs {
|
|
|
56
56
|
env?: string;
|
|
57
57
|
/** `chant graph --stacks` — render the cross-stack apply-ordering graph */
|
|
58
58
|
stacks?: boolean;
|
|
59
|
+
/** `chant graph --format ir --detail <0..3>` — graph IR detail tier */
|
|
60
|
+
detail?: number;
|
|
61
|
+
/** `chant graph --lens <kind>:<target>` — focus the graph IR on a slice */
|
|
62
|
+
lens?: string;
|
|
63
|
+
/** `chant graph --lens blast:<node> --up` — include upstream producers */
|
|
64
|
+
up?: boolean;
|
|
65
|
+
/** `chant graph --lens blast:<node> --down` — include downstream dependents */
|
|
66
|
+
down?: boolean;
|
|
59
67
|
/** `chant lifecycle affected --base <ref>` — base git ref to diff against */
|
|
60
68
|
base?: string;
|
|
61
69
|
/** `chant lifecycle affected --head <ref>` — head git ref (default: working tree) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GraphIR } from "./graph-ir.js";
|
|
2
|
+
/**
|
|
3
|
+
* Detail tiers — the diagram "detail dial". Each level is a pure IR → IR
|
|
4
|
+
* transform over the base graph IR (no re-discovery), so every emitter and the
|
|
5
|
+
* painter get them for free. See issue #494 / epic #492.
|
|
6
|
+
*
|
|
7
|
+
* - 0 STACKS — one node per lexicon; edges are cross-lexicon dependencies
|
|
8
|
+
* - 1 COMPOSITES — composite instances collapsed to a single node each
|
|
9
|
+
* - 2 DECLARABLES — every resource (the base produced by buildGraphIr)
|
|
10
|
+
* - 3 ATTRIBUTES — declarables plus the producer attribute on each edge
|
|
11
|
+
*/
|
|
12
|
+
export type DetailLevel = 0 | 1 | 2 | 3;
|
|
13
|
+
export declare const DETAIL: {
|
|
14
|
+
readonly STACKS: 0;
|
|
15
|
+
readonly COMPOSITES: 1;
|
|
16
|
+
readonly DECLARABLES: 2;
|
|
17
|
+
readonly ATTRIBUTES: 3;
|
|
18
|
+
};
|
|
19
|
+
/** Apply a detail tier to the base (declarable-level) IR. */
|
|
20
|
+
export declare function applyDetail(ir: GraphIR, level: DetailLevel): GraphIR;
|
|
21
|
+
//# sourceMappingURL=graph-detail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-detail.d.ts","sourceRoot":"","sources":["../src/graph-detail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAExC,eAAO,MAAM,MAAM;;;;;CAKT,CAAC;AAEX,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAYpE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GraphIR } from "./graph-ir.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render the graph IR as Graphviz DOT. Pure text — no `dot` needed to produce
|
|
4
|
+
* it. Two consumers: render directly with `dot -Tsvg` (mingrammer-style), or
|
|
5
|
+
* feed it to a layout engine for node positions that a custom painter draws
|
|
6
|
+
* (the rackattack pattern; see {@link toLayout}). See issue #497 / epic #492.
|
|
7
|
+
*
|
|
8
|
+
* Consumes whatever IR it is given, so `--detail` (and future `--lens`) flow
|
|
9
|
+
* through for free.
|
|
10
|
+
*/
|
|
11
|
+
export declare function toDot(ir: GraphIR): string;
|
|
12
|
+
//# sourceMappingURL=graph-dot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-dot.d.ts","sourceRoot":"","sources":["../src/graph-dot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CA2BzC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type Declarable } from "./declarable.js";
|
|
2
|
+
/**
|
|
3
|
+
* Graph IR — the engine-neutral, lint-gated representation of a project's
|
|
4
|
+
* resolved infrastructure graph. Painters (mermaid, graphviz, custom SVG) and
|
|
5
|
+
* the agentic diagrammer consume this; it is a pure function of lint-clean
|
|
6
|
+
* source. Every node traces to the file that declared it; every edge is a real
|
|
7
|
+
* cross-resource reference (AttrRef).
|
|
8
|
+
*
|
|
9
|
+
* Emitted by `chant graph --format ir`. See issue #493 / epic #492.
|
|
10
|
+
*/
|
|
11
|
+
/** Where in the source a node came from. Entity-level (file), not a line map. */
|
|
12
|
+
export interface SourceLoc {
|
|
13
|
+
/** Path of the declaring file, relative to the project root when possible. */
|
|
14
|
+
file: string;
|
|
15
|
+
/**
|
|
16
|
+
* Line number, when available. Provenance is entity-level today, so this is
|
|
17
|
+
* usually absent — reserved for a future source map.
|
|
18
|
+
*/
|
|
19
|
+
line?: number;
|
|
20
|
+
}
|
|
21
|
+
/** A reference in an attribute projection: `<producer>.<attribute>`. */
|
|
22
|
+
export interface AttrRefEnvelope {
|
|
23
|
+
$ref: string;
|
|
24
|
+
}
|
|
25
|
+
/** One resource in the graph. */
|
|
26
|
+
export interface IRNode {
|
|
27
|
+
/** Logical name (the export name, or composite-expanded name). */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Resource type, e.g. "GkeCluster". */
|
|
30
|
+
kind: string;
|
|
31
|
+
/** Lexicon the resource belongs to, e.g. "gcp". */
|
|
32
|
+
lexicon: string;
|
|
33
|
+
/**
|
|
34
|
+
* Name of the composite *type* that expanded this node, when it came from one
|
|
35
|
+
* (e.g. "CockroachDbCluster").
|
|
36
|
+
*/
|
|
37
|
+
compositeParent?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The composite *instance* (export name) this node belongs to — shared by every
|
|
40
|
+
* node from the same composite call. Detail tiers collapse on this (#494).
|
|
41
|
+
*/
|
|
42
|
+
compositeInstance?: string;
|
|
43
|
+
/** Literal/const/ref-resolved props. References appear as `{ $ref }`. */
|
|
44
|
+
attrs: Record<string, unknown>;
|
|
45
|
+
/** Where the node was declared. */
|
|
46
|
+
sourceLoc?: SourceLoc;
|
|
47
|
+
}
|
|
48
|
+
/** A directed dependency: `from` references an attribute of `to`. */
|
|
49
|
+
export interface IREdge {
|
|
50
|
+
from: string;
|
|
51
|
+
to: string;
|
|
52
|
+
/** "ref" for an AttrRef-derived edge. */
|
|
53
|
+
kind: "ref";
|
|
54
|
+
/** The consumer-side property the reference flows through, when derivable. */
|
|
55
|
+
viaAttr?: string;
|
|
56
|
+
/** The producer-side attribute referenced (e.g. "id"). Added at detail T3. */
|
|
57
|
+
toAttr?: string;
|
|
58
|
+
}
|
|
59
|
+
/** Grouping metadata for cluster/subgraph rendering. Maps group name -> node ids. */
|
|
60
|
+
export interface IRGroups {
|
|
61
|
+
byLexicon?: Record<string, string[]>;
|
|
62
|
+
byComposite?: Record<string, string[]>;
|
|
63
|
+
/** Reserved for stack grouping (#494). */
|
|
64
|
+
byStack?: Record<string, string[]>;
|
|
65
|
+
}
|
|
66
|
+
/** The full graph IR for a project at the default (declarable) detail level. */
|
|
67
|
+
export interface GraphIR {
|
|
68
|
+
nodes: IRNode[];
|
|
69
|
+
edges: IREdge[];
|
|
70
|
+
groups: IRGroups;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build the graph IR from resolved entities (the output of `discover`). Pure and
|
|
74
|
+
* deterministic: nodes and edges are sorted, so the same source yields identical
|
|
75
|
+
* IR. `projectPath` relativizes source-file paths for portable output.
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildGraphIr(entities: Map<string, Declarable>, projectPath?: string): GraphIR;
|
|
78
|
+
//# sourceMappingURL=graph-ir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-ir.d.ts","sourceRoot":"","sources":["../src/graph-ir.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAgB,MAAM,cAAc,CAAC;AAK7D;;;;;;;;GAQG;AAEH,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,iCAAiC;AACjC,MAAM,WAAW,MAAM;IACrB,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,mCAAmC;IACnC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,qEAAqE;AACrE,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,IAAI,EAAE,KAAK,CAAC;IACZ,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACpC;AAED,gFAAgF;AAChF,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAyID;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAmDT"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout-position export — node coordinates a custom painter consumes (the
|
|
3
|
+
* rackattack pattern: Graphviz lays out, the painter draws). Graphviz is used
|
|
4
|
+
* for LAYOUT ONLY; its rendering is discarded. See issue #497 / epic #492.
|
|
5
|
+
*
|
|
6
|
+
* The {@link LayoutEngine} interface exists so a pure-JS engine (elkjs/dagre)
|
|
7
|
+
* can drop in later for a zero-native-dependency path — closing the install gap
|
|
8
|
+
* so a painter can run without `dot`.
|
|
9
|
+
*/
|
|
10
|
+
/** A laid-out position in the engine's coordinate space. */
|
|
11
|
+
export interface Point {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}
|
|
15
|
+
/** Node positions plus the overall canvas size a painter needs. */
|
|
16
|
+
export interface Layout {
|
|
17
|
+
/** Canvas width in the engine's coordinate space. */
|
|
18
|
+
width: number;
|
|
19
|
+
/** Canvas height in the engine's coordinate space. */
|
|
20
|
+
height: number;
|
|
21
|
+
/** Each node's centre position, ordered by id for deterministic output. */
|
|
22
|
+
nodes: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
} & Point>;
|
|
25
|
+
}
|
|
26
|
+
/** Turns DOT into node positions. The painter consumes the result; it never
|
|
27
|
+
* asks the engine to paint. */
|
|
28
|
+
export interface LayoutEngine {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
layout(dot: string): Promise<Layout>;
|
|
31
|
+
}
|
|
32
|
+
/** Layout via `dot -Tjson`. Requires Graphviz (`brew install graphviz`). */
|
|
33
|
+
export declare class GraphvizLayout implements LayoutEngine {
|
|
34
|
+
readonly name = "graphviz";
|
|
35
|
+
layout(dot: string): Promise<Layout>;
|
|
36
|
+
}
|
|
37
|
+
/** Parse `dot -Tjson` output into a {@link Layout}. Pure; exported for testing. */
|
|
38
|
+
export declare function parseDotJson(json: string): Layout;
|
|
39
|
+
//# sourceMappingURL=graph-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-layout.d.ts","sourceRoot":"","sources":["../src/graph-layout.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,mEAAmE;AACnE,MAAM,WAAW,MAAM;IACrB,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,CAAC,CAAC;CACtC;AAED;+BAC+B;AAC/B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,4EAA4E;AAC5E,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,cAAc;IAErB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAG3C;AAsCD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBjD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { GraphIR } from "./graph-ir.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lenses — focus the graph IR on a slice without touching the source. Pure
|
|
4
|
+
* IR → IR filters, composable with detail tiers (apply a lens, then view the
|
|
5
|
+
* result at any `--detail`). See issue #495 / epic #492.
|
|
6
|
+
*
|
|
7
|
+
* - `lexicon:<name>` — only nodes in a lexicon
|
|
8
|
+
* - `stack:<name>` — only one stack's nodes (stacks map to lexicon partitions today)
|
|
9
|
+
* - `blast:<nodeId>` — the transitive neighbourhood of a node: what it depends
|
|
10
|
+
* on (`--up`), what depends on it (`--down`), or both (default)
|
|
11
|
+
*
|
|
12
|
+
* Every lens drops edges that would dangle and rebuilds group metadata from the
|
|
13
|
+
* surviving nodes, so the result is always a self-consistent graph.
|
|
14
|
+
*/
|
|
15
|
+
export interface LensSpec {
|
|
16
|
+
kind: "lexicon" | "stack" | "blast";
|
|
17
|
+
target: string;
|
|
18
|
+
/** blast: include upstream producers (what the node depends on). */
|
|
19
|
+
up: boolean;
|
|
20
|
+
/** blast: include downstream dependents (what depends on the node). */
|
|
21
|
+
down: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Parse a `--lens` spec. Throws a descriptive Error on a malformed spec. */
|
|
24
|
+
export declare function parseLens(spec: string, opts?: {
|
|
25
|
+
up?: boolean;
|
|
26
|
+
down?: boolean;
|
|
27
|
+
}): LensSpec;
|
|
28
|
+
/** Apply a lens to the IR. Throws a descriptive Error when the target matches nothing. */
|
|
29
|
+
export declare function applyLens(ir: GraphIR, lens: LensSpec): GraphIR;
|
|
30
|
+
//# sourceMappingURL=graph-lens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-lens.d.ts","sourceRoot":"","sources":["../src/graph-lens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,EAAE,EAAE,OAAO,CAAC;IACZ,uEAAuE;IACvE,IAAI,EAAE,OAAO,CAAC;CACf;AAID,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,QAAQ,CAkB7F;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAI9D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GraphIR } from "./graph-ir.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render the graph IR as a Mermaid `flowchart`. Mermaid is the zero-install
|
|
4
|
+
* default — it renders in GitHub, docs, and browsers with no native dependency,
|
|
5
|
+
* so `chant graph --format mermaid` gives a diagram out of the box without the
|
|
6
|
+
* standalone painter. Lower fidelity than a custom painter, but portable.
|
|
7
|
+
*
|
|
8
|
+
* Consumes whatever IR it is given, so it honours `--detail` and `--lens` for
|
|
9
|
+
* free (those are IR → IR transforms). See issue #496 / epic #492.
|
|
10
|
+
*
|
|
11
|
+
* Known limits: Mermaid owns layout, so there is little control over node
|
|
12
|
+
* placement, and very large graphs get hard to read — that is the trade-off for
|
|
13
|
+
* zero-install portability. Reach for the graphviz/custom-painter path (#497,
|
|
14
|
+
* pinhole) when fidelity matters.
|
|
15
|
+
*/
|
|
16
|
+
export declare function toMermaid(ir: GraphIR): string;
|
|
17
|
+
//# sourceMappingURL=graph-mermaid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-mermaid.d.ts","sourceRoot":"","sources":["../src/graph-mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAgC7C"}
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,12 @@ export * from "./discovery/graph.js";
|
|
|
24
24
|
export * from "./discovery/index.js";
|
|
25
25
|
export * from "./discovery/cache.js";
|
|
26
26
|
export * from "./build.js";
|
|
27
|
+
export * from "./graph-ir.js";
|
|
28
|
+
export * from "./graph-detail.js";
|
|
29
|
+
export * from "./graph-mermaid.js";
|
|
30
|
+
export * from "./graph-dot.js";
|
|
31
|
+
export * from "./graph-layout.js";
|
|
32
|
+
export * from "./graph-lens.js";
|
|
27
33
|
export * from "./detectLexicon.js";
|
|
28
34
|
export * from "./lint/parser.js";
|
|
29
35
|
export * from "./lint/rule.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,QAAQ,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAClE,cAAc,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5F,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,QAAQ,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAClE,cAAc,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5F,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/provenance.d.ts
CHANGED
|
@@ -12,8 +12,15 @@
|
|
|
12
12
|
export interface EntityProvenance {
|
|
13
13
|
/** Absolute path of the source file that declared (or exported) the entity. */
|
|
14
14
|
sourceFile?: string;
|
|
15
|
-
/** The composite that expanded this entity, when it came from one. */
|
|
15
|
+
/** The composite (type) that expanded this entity, when it came from one. */
|
|
16
16
|
composite?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The composite *instance* this entity belongs to — the export name of the
|
|
19
|
+
* top-level composite, shared by every member it expanded to. Distinguishes
|
|
20
|
+
* two instances of the same composite type, which `composite` cannot. Used to
|
|
21
|
+
* collapse a composite to a single node at coarse diagram detail levels (#494).
|
|
22
|
+
*/
|
|
23
|
+
compositeInstance?: string;
|
|
17
24
|
}
|
|
18
25
|
/**
|
|
19
26
|
* Merge provenance onto an entity. Non-enumerable so it is invisible to
|
package/dist/provenance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAe1E;AAED,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE1E"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-agnostic reconcile primitive.
|
|
3
|
+
*
|
|
4
|
+
* The reusable machinery behind a declarative reconcile loop, with NO knowledge
|
|
5
|
+
* of any specific provider (GitHub, GitLab, a cloud, …): the change-set model,
|
|
6
|
+
* the generic collection diff (selective-by-omission + ownership-gated deletes),
|
|
7
|
+
* the plan renderer, and the guardrail framework (rename resolution + a removal
|
|
8
|
+
* cap + a pluggable check runner).
|
|
9
|
+
*
|
|
10
|
+
* A "warden" (e.g. github-warden) builds its provider-specific resource diffing,
|
|
11
|
+
* live-state types, and domain guardrails on top of this. It complements
|
|
12
|
+
* chant's `ownership.ts` marker contract: ownership markers make a `delete`
|
|
13
|
+
* precise; this module decides *which* entries are creates / updates / deletes
|
|
14
|
+
* in the first place.
|
|
15
|
+
*
|
|
16
|
+
* Consumed as `@intentius/chant/reconcile`. Pure and deterministic: no I/O,
|
|
17
|
+
* no clock.
|
|
18
|
+
*/
|
|
19
|
+
/** A single field-level change: what the old value was and what it will become. */
|
|
20
|
+
export interface FieldChange {
|
|
21
|
+
field: string;
|
|
22
|
+
before: unknown;
|
|
23
|
+
after: unknown;
|
|
24
|
+
}
|
|
25
|
+
/** The kind of operation this change represents. */
|
|
26
|
+
export type ChangeKind = "create" | "update" | "delete";
|
|
27
|
+
/** A single entry in the change set. */
|
|
28
|
+
export interface ChangeSetEntry {
|
|
29
|
+
kind: ChangeKind;
|
|
30
|
+
/** High-level resource category (e.g. "team", "member", "branch-protection"). */
|
|
31
|
+
resourceType: string;
|
|
32
|
+
/**
|
|
33
|
+
* Unique key identifying this resource within its type.
|
|
34
|
+
* - For top-level resources: a single name (team slug, member login, …).
|
|
35
|
+
* - For nested resources: "<parent>/<child>" (e.g. "backend/alice").
|
|
36
|
+
*/
|
|
37
|
+
key: string;
|
|
38
|
+
/** The live value before the change (absent for creates). */
|
|
39
|
+
before?: unknown;
|
|
40
|
+
/** The desired value after the change (absent for deletes). */
|
|
41
|
+
after?: unknown;
|
|
42
|
+
/** Field-level diff, populated for `update` entries. */
|
|
43
|
+
fields?: FieldChange[];
|
|
44
|
+
}
|
|
45
|
+
/** The full set of changes to reconcile for one scope (e.g. one org). */
|
|
46
|
+
export interface ChangeSet {
|
|
47
|
+
/** Scope identifier this change set applies to (e.g. a GitHub org login). */
|
|
48
|
+
org: string;
|
|
49
|
+
/** All proposed changes, in stable order. */
|
|
50
|
+
entries: ChangeSetEntry[];
|
|
51
|
+
}
|
|
52
|
+
/** Options controlling diff behaviour. */
|
|
53
|
+
export interface DiffOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Ownership predicate for collection entries. The diff only emits a `delete`
|
|
56
|
+
* for a live entry absent from desired when this returns `true`. Omitted →
|
|
57
|
+
* deletes are never emitted ("assume nothing is owned").
|
|
58
|
+
*/
|
|
59
|
+
isOwned?: (resourceType: string, key: string) => boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Reference "now" in epoch milliseconds, used by time-based diffs. Callers
|
|
62
|
+
* inject `Date.now()` when unset; tests pass an explicit value.
|
|
63
|
+
*/
|
|
64
|
+
nowMs?: number;
|
|
65
|
+
}
|
|
66
|
+
/** Deep value equality via JSON for plain data (config/live snapshots). */
|
|
67
|
+
export declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Diff fields of `desired` against `live`, returning one `FieldChange` per
|
|
70
|
+
* differing field. When `keys` is given, only those keys are compared (and only
|
|
71
|
+
* when present in `desired`); otherwise every key in `desired` is compared.
|
|
72
|
+
* Selective-by-omission: keys absent from `desired` are never compared.
|
|
73
|
+
*/
|
|
74
|
+
export declare function diffFields(desired: Record<string, unknown>, live: Record<string, unknown>, keys?: string[]): FieldChange[];
|
|
75
|
+
/** Parameters for {@link diffCollection}. */
|
|
76
|
+
export interface DiffCollectionParams<D, L> {
|
|
77
|
+
/** Resource type stamped on emitted entries. */
|
|
78
|
+
resourceType: string;
|
|
79
|
+
/** Prefix prepended to each entry key (e.g. "<parent>/"). Default "". */
|
|
80
|
+
keyPrefix?: string;
|
|
81
|
+
/** Desired entries, keyed by logical key. */
|
|
82
|
+
desired: Map<string, D>;
|
|
83
|
+
/** Live entries, keyed by logical key. */
|
|
84
|
+
live: Map<string, L>;
|
|
85
|
+
/** Fields that differ → an update. Return `[]` for "no change". */
|
|
86
|
+
compareFields: (desired: D, live: L) => FieldChange[];
|
|
87
|
+
/** `after` value for a create entry. Defaults to the desired value. */
|
|
88
|
+
createAfter?: (key: string, desired: D) => unknown;
|
|
89
|
+
/** `after` value for an update entry. Defaults to the desired value. */
|
|
90
|
+
updateAfter?: (key: string, desired: D, live: L) => unknown;
|
|
91
|
+
opts: DiffOptions;
|
|
92
|
+
out: ChangeSetEntry[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The generic managed-collection diff: creates for desired-not-live, updates
|
|
96
|
+
* when `compareFields` reports differences, and ownership-gated deletes for
|
|
97
|
+
* live-not-desired. This is the selective-by-omission + ownership-gated-delete
|
|
98
|
+
* pattern shared by every keyed-collection diff.
|
|
99
|
+
*/
|
|
100
|
+
export declare function diffCollection<D, L>(params: DiffCollectionParams<D, L>): void;
|
|
101
|
+
/** Count entries per change kind. */
|
|
102
|
+
export declare function summarizeChangeSet(cs: ChangeSet): Record<ChangeKind, number>;
|
|
103
|
+
/** Human-readable plan summary for dry-run output. Pure. */
|
|
104
|
+
export declare function renderChangeSet(cs: ChangeSet): string;
|
|
105
|
+
/** A single tripped guardrail with a human-readable message. */
|
|
106
|
+
export interface GuardrailDiagnostic {
|
|
107
|
+
/** Short identifier, e.g. "removalDeltaCap". */
|
|
108
|
+
guardrail: string;
|
|
109
|
+
/** Clear, actionable description of why the apply was refused. */
|
|
110
|
+
message: string;
|
|
111
|
+
}
|
|
112
|
+
/** Aggregated guardrail result. */
|
|
113
|
+
export type GuardrailResult = {
|
|
114
|
+
ok: true;
|
|
115
|
+
} | {
|
|
116
|
+
ok: false;
|
|
117
|
+
diagnostics: GuardrailDiagnostic[];
|
|
118
|
+
};
|
|
119
|
+
/** A guardrail check over a (rename-resolved) change set. Returns null when it passes. */
|
|
120
|
+
export type GuardrailCheck = (resolved: ChangeSet) => GuardrailDiagnostic | null;
|
|
121
|
+
/** Config for `removalDeltaCap`. */
|
|
122
|
+
export interface RemovalDeltaCapOptions {
|
|
123
|
+
/** Max fraction of pre-existing entries that may be deleted. Must be in (0,1]. Default 0.25. */
|
|
124
|
+
maxFraction?: number;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolve rename aliases. A create entry carrying a `previously` key matching a
|
|
128
|
+
* delete entry's key is collapsed into an update, removing the delete. Returns a
|
|
129
|
+
* new ChangeSet with renames resolved. Provider-agnostic — works on any entry
|
|
130
|
+
* whose `after.previously` is a string.
|
|
131
|
+
*/
|
|
132
|
+
export declare function resolveRenames(changeSet: ChangeSet): ChangeSet;
|
|
133
|
+
/**
|
|
134
|
+
* Refuse if deletes exceed `maxFraction` of the pre-existing managed entries
|
|
135
|
+
* (deletes + updates; creates excluded so a flood of new entries can't dilute
|
|
136
|
+
* the delete fraction). Guards against a typo wiping the config in one apply.
|
|
137
|
+
*
|
|
138
|
+
* CONTRACT: pass a RENAME-RESOLVED change set (see {@link resolveRenames}).
|
|
139
|
+
*/
|
|
140
|
+
export declare function removalDeltaCap(changeSet: ChangeSet, opts?: RemovalDeltaCapOptions): GuardrailDiagnostic | null;
|
|
141
|
+
/**
|
|
142
|
+
* Run a set of guardrail checks against a change set. Resolves renames ONCE,
|
|
143
|
+
* then runs every check on the resolved set, aggregating any diagnostics. The
|
|
144
|
+
* caller composes provider-specific checks (e.g. an admin floor) as closures.
|
|
145
|
+
*/
|
|
146
|
+
export declare function runGuardrailChecks(changeSet: ChangeSet, checks: GuardrailCheck[]): GuardrailResult;
|
|
147
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../src/reconcile.ts"],"names":[],"mappings":"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"}
|