@titan-design/code-graph 0.11.0 → 0.13.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 +129 -5
- package/dist/analysis/browser.d.ts +2 -0
- package/dist/analysis/browser.js +84 -0
- package/dist/analysis/browser.js.map +1 -0
- package/dist/browser-BBzShneN.d.ts +936 -0
- package/dist/{change-coupling-CyqHgRsm.d.ts → change-coupling-CT3bcZMD.d.ts} +5 -1
- package/dist/{chunk-PFI5XMUG.js → chunk-GX563F6R.js} +79 -89
- package/dist/chunk-GX563F6R.js.map +1 -0
- package/dist/chunk-HIVVDGWE.js +83 -0
- package/dist/chunk-HIVVDGWE.js.map +1 -0
- package/dist/chunk-L5KU543A.js +1395 -0
- package/dist/chunk-L5KU543A.js.map +1 -0
- package/dist/history/index.d.ts +25 -4
- package/dist/history/index.js +11 -3
- package/dist/index.d.ts +331 -353
- package/dist/index.js +1658 -926
- package/dist/index.js.map +1 -1
- package/package.json +8 -4
- package/dist/chunk-PFI5XMUG.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,63 +1,12 @@
|
|
|
1
|
+
import { N as NodeKind, G as GraphNode, a as GraphEdge, b as GraphMetric, I as IdAlias, F as FileFingerprint, S as SnapshotRow, c as GraphFragment, d as NodeRole, E as EdgeKind, e as IdAliasReason, T as TestSourceLink, f as NodeMetrics, B as BlastRadiusEntry, R as ReferenceEdgeLite, g as SymbolConsumers, h as SymbolCouplingOptions, i as SymbolCouplingPair, C as CheckRule, j as CheckResult, k as CheckViolation, l as Severity, V as ViolationBuckets } from './browser-BBzShneN.js';
|
|
2
|
+
export { A as ArchEdge, m as ArchPackage, n as ArchResult, o as ArchSubNode, p as BucketableViolation, q as BusFactorChange, r as BusFactorRow, s as CentralRow, t as CheckRulesFile, u as ComputeArchInput, v as ComputeDriftInput, w as CouplingClass, x as CouplingDelta, y as CouplingRow, D as DEFAULT_HEALTH_WEIGHTS, z as DEFAULT_MAX_PACKAGE_SIZE, H as DeadModuleRow, J as EXTERNAL_BUCKET, K as ForbidImportRule, L as GraphReportResult, M as GrowthRiskRow, O as HealthComponent, P as HealthComponentKey, Q as HealthInput, U as HealthWeights, W as HotExport, X as HotspotDelta, Y as HotspotRow, Z as LayeredDepsRule, _ as LinkMethod, $ as LinkTestsOptions, a0 as MetricMaxRule, a1 as MetricMinRule, a2 as MetricOutlierRule, a3 as MetricProductMaxRule, a4 as NewHotspot, a5 as NoInternalOnlyBarrelsRule, a6 as PackageFlag, a7 as PackageLayer, a8 as PackageRoot, a9 as PackageStats, aa as PairCoupling, ab as PairFlag, ac as PartitionQualityInput, ad as PartitionQualityResult, ae as PenaltyWeight, af as ReportContext, ag as ReportContextInput, ah as ReportDrift, ai as SnapshotContext, aj as SymbolConsumerGroup, ak as SymbolConsumerRow, al as SymbolCouplingPayload, am as SymbolCouplingRow, an as SymbolUtil, ao as TestCoverageRow, ap as UnchangedViolation, aq as UntestedRiskRow, ar as UnusedExportRow, as as ViolationIdentity, at as aggregateEdges, au as bucketFilesByPackage, av as bucketViolations, aw as buildBlastRadius, ax as buildCentralFiles, ay as buildHotExports, az as buildNodeMetrics, aA as buildReportContext, aB as buildSymbolCouplingPayload, aC as busFactorOf, aD as classifyCoupling, aE as collectNodeMetrics, aF as collectSymbolUtil, aG as computeArch, aH as computeHealth, aI as computePartitionQuality, aJ as computeReportDrift, aK as computeSymbolConsumers, aL as computeSymbolCoupling, aM as filteredFileIds, aN as groupTestsBySource, aO as hotspotScoreOf, aP as invertBuckets, aQ as keepNode, aR as linkTestsToSources, aS as lookupMetric, aT as packagesReferencedByEdges, aU as pairKey, aV as publicApiFiles, aW as rebasedViolationKey, aX as referencedNodes, aY as testCoverageCountMetrics, aZ as toSortedEdges, a_ as topBusFactorRisks, a$ as topCentralFiles, b0 as topDeadModules, b1 as topGrowthRisks, b2 as topHotspots, b3 as topTestCoverageRisks, b4 as topUntestedRisks, b5 as topUnusedExports, b6 as violationKey } from './browser-BBzShneN.js';
|
|
1
3
|
import { Db, Migration } from '@titan-design/store-sqlite';
|
|
4
|
+
import { FileSystemHost, Project } from 'ts-morph';
|
|
2
5
|
import { Extractor, ParsedFile } from '@titan-design/code-parser';
|
|
3
6
|
export { Extractor, ParsedFile, getLanguageFromPath, getSupportedLanguages, parseFile, shouldIncludeFile } from '@titan-design/code-parser';
|
|
4
|
-
import {
|
|
5
|
-
import { c as CoEditPair, C as ChurnEntry, a as ChurnWindow } from './change-coupling-CyqHgRsm.js';
|
|
7
|
+
import { C as ChurnEntry, a as ChurnWindow } from './change-coupling-CT3bcZMD.js';
|
|
6
8
|
import { Embedder } from '@titan-design/embed';
|
|
7
9
|
|
|
8
|
-
type NodeKind = "package" | "module" | "file" | "symbol" | "external";
|
|
9
|
-
type EdgeKind = "imports" | "re-exports" | "calls" | "extends" | "implements" | "references" | "depends-on";
|
|
10
|
-
/** `requalify` maps a bare-name symbol id from before index version 0.14.0 to its scope-qualified successor. */
|
|
11
|
-
type IdAliasReason = "rename" | "move" | "merge" | "requalify";
|
|
12
|
-
type NodeRole = "test" | "fixture" | "barrel" | "types" | "config" | "script" | "entry" | "generated" | "source";
|
|
13
|
-
interface GraphNode {
|
|
14
|
-
id: string;
|
|
15
|
-
kind: NodeKind;
|
|
16
|
-
name: string;
|
|
17
|
-
parentId?: string;
|
|
18
|
-
language?: string;
|
|
19
|
-
role?: NodeRole;
|
|
20
|
-
attrs?: Record<string, unknown>;
|
|
21
|
-
}
|
|
22
|
-
interface GraphEdge {
|
|
23
|
-
srcId: string;
|
|
24
|
-
dstId: string;
|
|
25
|
-
kind: EdgeKind;
|
|
26
|
-
attrs?: Record<string, unknown>;
|
|
27
|
-
}
|
|
28
|
-
interface GraphMetric {
|
|
29
|
-
nodeId: string;
|
|
30
|
-
name: string;
|
|
31
|
-
value: number | null;
|
|
32
|
-
unit?: string;
|
|
33
|
-
}
|
|
34
|
-
interface GraphFragment {
|
|
35
|
-
nodes: GraphNode[];
|
|
36
|
-
edges: GraphEdge[];
|
|
37
|
-
}
|
|
38
|
-
interface SnapshotRow {
|
|
39
|
-
id: number;
|
|
40
|
-
ref: string;
|
|
41
|
-
commitHash: string | null;
|
|
42
|
-
takenAt: string;
|
|
43
|
-
indexVersion: string;
|
|
44
|
-
attrs: Record<string, unknown>;
|
|
45
|
-
}
|
|
46
|
-
interface IdAlias {
|
|
47
|
-
oldId: string;
|
|
48
|
-
newId: string;
|
|
49
|
-
reason: IdAliasReason;
|
|
50
|
-
}
|
|
51
|
-
interface FileFingerprint {
|
|
52
|
-
fileId: string;
|
|
53
|
-
contentHash: string;
|
|
54
|
-
/**
|
|
55
|
-
* Comment/whitespace-insensitive parse-structure hash (C-18). Absent on
|
|
56
|
-
* snapshots written before C-18 (they can only reuse whole unchanged files).
|
|
57
|
-
*/
|
|
58
|
-
structuralHash?: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
10
|
/** One metric's values over the nodes of one kind in one snapshot; `count` excludes null values. */
|
|
62
11
|
interface MetricAggregate {
|
|
63
12
|
name: string;
|
|
@@ -95,6 +44,13 @@ declare class CodeGraphStore {
|
|
|
95
44
|
private readonly targeted;
|
|
96
45
|
constructor(db: Db);
|
|
97
46
|
createSnapshot(input: SnapshotInsert): number;
|
|
47
|
+
/**
|
|
48
|
+
* Run `write` in one transaction so a reader on another connection sees a new
|
|
49
|
+
* snapshot only once every row written for it is committed, never a snapshot
|
|
50
|
+
* row whose nodes or edges are still being inserted. The per-table inserts
|
|
51
|
+
* nest as savepoints inside it.
|
|
52
|
+
*/
|
|
53
|
+
atomically<T>(write: () => T): T;
|
|
98
54
|
insertNodes(snapshotId: number, nodes: readonly GraphNode[]): void;
|
|
99
55
|
insertEdges(snapshotId: number, edges: readonly GraphEdge[]): void;
|
|
100
56
|
insertMetrics(snapshotId: number, metrics: readonly GraphMetric[]): void;
|
|
@@ -185,7 +141,7 @@ declare const FINDING_DDL = "\n CREATE TABLE IF NOT EXISTS finding (\n snaps
|
|
|
185
141
|
declare const SNAPSHOT_SCOPED_TABLES: readonly ["node", "edge", "metric", "id_alias", "file_fingerprint", "finding", "verdict"];
|
|
186
142
|
declare const MIGRATIONS: Migration[];
|
|
187
143
|
/** The top of this package's schema. A code graph database is never shared, so this is the top of one. */
|
|
188
|
-
declare const SCHEMA_VERSION: number;
|
|
144
|
+
declare const SCHEMA_VERSION$1: number;
|
|
189
145
|
|
|
190
146
|
interface PrunePlan {
|
|
191
147
|
keep: SnapshotRow[];
|
|
@@ -206,12 +162,40 @@ declare function runPrune(store: CodeGraphStore, options?: PruneOptions & {
|
|
|
206
162
|
vacuum?: boolean;
|
|
207
163
|
}): PruneResult;
|
|
208
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Where the indexer reads a tree from. Every path is absolute and node ids are
|
|
167
|
+
* derived from it, so a source that is not the working tree (a git commit, say)
|
|
168
|
+
* keeps ids byte-identical by answering for the same absolute paths.
|
|
169
|
+
*/
|
|
170
|
+
interface IndexSource {
|
|
171
|
+
/**
|
|
172
|
+
* Source files under `rootDirs` that pass the ingest filter for `languages`,
|
|
173
|
+
* deduped and sorted, so float metrics summed in file order match across sources.
|
|
174
|
+
*/
|
|
175
|
+
listFiles(rootDirs: readonly string[], languages: readonly string[]): Promise<string[]>;
|
|
176
|
+
/** UTF-8 content of a file; throws when it does not exist. */
|
|
177
|
+
readFile(abs: string): string;
|
|
178
|
+
fileExists(abs: string): boolean;
|
|
179
|
+
/** The host ts-morph resolves imports and reads tsconfig through. */
|
|
180
|
+
readonly fileSystem: FileSystemHost;
|
|
181
|
+
/** Set when the source is a git commit rather than the working tree; undefined for the working tree. */
|
|
182
|
+
readonly revision?: {
|
|
183
|
+
/** The repo's toplevel, canonicalized with realpath. */
|
|
184
|
+
readonly repoRoot: string;
|
|
185
|
+
readonly commit: string;
|
|
186
|
+
/** Committer time, seconds since the epoch. */
|
|
187
|
+
readonly commitEpoch: number;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/** The checked-out working tree, read through `node:fs`. The default source. */
|
|
191
|
+
declare function workingTreeSource(): IndexSource;
|
|
192
|
+
|
|
209
193
|
/**
|
|
210
194
|
* Bumping this invalidates every reuse basis: a snapshot written by a different
|
|
211
195
|
* index version is never reused, so a change to node/edge shape or to a metric's
|
|
212
196
|
* value for the same bytes can never be carried forward from an incompatible graph.
|
|
213
197
|
*/
|
|
214
|
-
declare const INDEX_VERSION = "0.
|
|
198
|
+
declare const INDEX_VERSION = "0.22.0";
|
|
215
199
|
interface IndexOptions {
|
|
216
200
|
/** Roots to walk. Node ids are still rooted at the git toplevel, so importers across roots share an id space. */
|
|
217
201
|
paths: string[];
|
|
@@ -235,6 +219,8 @@ interface IndexOptions {
|
|
|
235
219
|
churnWindows?: number[];
|
|
236
220
|
/** Also store an all-time `lifetime` churn and ownership window over full git history. */
|
|
237
221
|
lifetime?: boolean;
|
|
222
|
+
/** Where files are listed and read from. Defaults to {@link workingTreeSource}. */
|
|
223
|
+
source?: IndexSource;
|
|
238
224
|
}
|
|
239
225
|
interface IndexResult {
|
|
240
226
|
snapshotId: number;
|
|
@@ -260,9 +246,19 @@ interface IndexResult {
|
|
|
260
246
|
*/
|
|
261
247
|
declare function indexPaths(store: CodeGraphStore, options: IndexOptions): Promise<IndexResult>;
|
|
262
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Index `rev`'s tree from git objects, without a checkout and without writing to
|
|
251
|
+
* the repo. Files keep their `<repo root>/<tree path>` absolute paths, so ids
|
|
252
|
+
* match a working-tree index of the same commit. Workspace links into the repo
|
|
253
|
+
* resolve to the commit; installed packages and untracked build output such as
|
|
254
|
+
* a gitignored dist/ resolve against today's disk.
|
|
255
|
+
*/
|
|
256
|
+
declare function gitTreeSource(repoRoot: string, rev: string): IndexSource;
|
|
257
|
+
|
|
263
258
|
interface LanguageExtractorOptions {
|
|
264
259
|
repoRoot: string;
|
|
265
260
|
tsConfigPath?: string;
|
|
261
|
+
source?: IndexSource;
|
|
266
262
|
}
|
|
267
263
|
/**
|
|
268
264
|
* One extractor over every supported language: each delegate already returns an
|
|
@@ -285,8 +281,9 @@ declare class LanguageExtractor implements Extractor<GraphFragment> {
|
|
|
285
281
|
*/
|
|
286
282
|
declare class PythonGraphExtractor implements Extractor<GraphFragment> {
|
|
287
283
|
private readonly repoRoot;
|
|
284
|
+
private readonly source;
|
|
288
285
|
readonly name = "python-graph";
|
|
289
|
-
constructor(repoRoot: string);
|
|
286
|
+
constructor(repoRoot: string, source?: IndexSource);
|
|
290
287
|
extract(file: ParsedFile): GraphFragment[];
|
|
291
288
|
private collectImports;
|
|
292
289
|
/**
|
|
@@ -301,6 +298,7 @@ interface TsMorphGraphExtractorOptions {
|
|
|
301
298
|
repoRoot: string;
|
|
302
299
|
tsConfigPath?: string;
|
|
303
300
|
project?: Project;
|
|
301
|
+
source?: IndexSource;
|
|
304
302
|
}
|
|
305
303
|
declare class TsMorphGraphExtractor implements Extractor<GraphFragment> {
|
|
306
304
|
readonly name = "ts-morph-graph";
|
|
@@ -308,7 +306,9 @@ declare class TsMorphGraphExtractor implements Extractor<GraphFragment> {
|
|
|
308
306
|
private readonly tsConfigPath?;
|
|
309
307
|
private project?;
|
|
310
308
|
private readonly ownsProject;
|
|
309
|
+
private readonly source;
|
|
311
310
|
private readonly retired;
|
|
311
|
+
private readonly fileExists;
|
|
312
312
|
constructor(options: TsMorphGraphExtractorOptions);
|
|
313
313
|
extract(file: ParsedFile): GraphFragment[];
|
|
314
314
|
private retire;
|
|
@@ -415,10 +415,6 @@ interface DeepAstInput {
|
|
|
415
415
|
/** Deep structural facts for one target, or null when the source is unreadable. */
|
|
416
416
|
declare function computeDeepAst(input: DeepAstInput): DeepAst | null;
|
|
417
417
|
|
|
418
|
-
declare function fileId(repoRoot: string, absPath: string): string;
|
|
419
|
-
declare function moduleId(repoRoot: string, absPath: string): string;
|
|
420
|
-
declare function parentModuleId(id: string): string | null;
|
|
421
|
-
declare function packageId(name: string): string;
|
|
422
418
|
declare const SYMBOL_ID_SEP = "#";
|
|
423
419
|
declare function symbolId(fileId: string, qualifiedName: string): string;
|
|
424
420
|
/**
|
|
@@ -431,6 +427,12 @@ declare function parseSymbolId(id: string): {
|
|
|
431
427
|
fileId: string;
|
|
432
428
|
name: string;
|
|
433
429
|
} | null;
|
|
430
|
+
|
|
431
|
+
declare function fileId(repoRoot: string, absPath: string): string;
|
|
432
|
+
declare function moduleId(repoRoot: string, absPath: string): string;
|
|
433
|
+
declare function parentModuleId(id: string): string | null;
|
|
434
|
+
declare function packageId(name: string): string;
|
|
435
|
+
|
|
434
436
|
declare function externalId(specifier: string): string;
|
|
435
437
|
|
|
436
438
|
/** SHA-256 of file content. The fingerprint that gates per-file reuse. */
|
|
@@ -453,7 +455,7 @@ interface ReadFile {
|
|
|
453
455
|
hash: string;
|
|
454
456
|
}
|
|
455
457
|
/** Read + hash every source file. Cheap I/O; the parse/extract it gates is not. */
|
|
456
|
-
declare function readSourceFiles(filePaths: readonly string[]): Promise<ReadFile[]>;
|
|
458
|
+
declare function readSourceFiles(filePaths: readonly string[], source?: IndexSource): Promise<ReadFile[]>;
|
|
457
459
|
/**
|
|
458
460
|
* Everything from a prior snapshot needed to rebuild an unchanged file's
|
|
459
461
|
* contribution to the graph without re-parsing it: its content fingerprint,
|
|
@@ -534,12 +536,22 @@ declare function pruneDanglingReferences(nodes: ReadonlyMap<string, GraphNode>,
|
|
|
534
536
|
*/
|
|
535
537
|
declare function resolveBarrelEdges(nodes: readonly GraphNode[], edges: readonly GraphEdge[]): GraphEdge[];
|
|
536
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Repo-configured role globs, read from `.codewatch/roles.json`. They label
|
|
541
|
+
* paths no filename convention can (a design system's `lab/` playground is
|
|
542
|
+
* too generic a directory name to guess), and they beat the built-in role
|
|
543
|
+
* heuristics. Globs use `.gitattributes` syntax, matched against file ids.
|
|
544
|
+
*/
|
|
545
|
+
type RoleGlobs = Partial<Record<NodeRole, string[]>>;
|
|
546
|
+
|
|
537
547
|
declare const ALL_ROLES: readonly NodeRole[];
|
|
538
548
|
interface RoleHints {
|
|
539
549
|
/** File begins with a `#!` shebang, i.e. it is an executable entry point. */
|
|
540
550
|
hasShebang?: boolean;
|
|
541
551
|
/** File is codegen output (`.gitattributes linguist-generated` or heuristic). */
|
|
542
552
|
isGenerated?: boolean;
|
|
553
|
+
/** Role a `.codewatch/roles.json` glob assigns this file. */
|
|
554
|
+
configuredRole?: NodeRole;
|
|
543
555
|
}
|
|
544
556
|
declare function classifyRole(id: string, hints?: RoleHints): NodeRole;
|
|
545
557
|
interface AnnotateRolesOptions {
|
|
@@ -547,7 +559,11 @@ interface AnnotateRolesOptions {
|
|
|
547
559
|
shebangIds?: ReadonlySet<string>;
|
|
548
560
|
/** Node ids detected as generated (codegen output). */
|
|
549
561
|
generatedIds?: ReadonlySet<string>;
|
|
562
|
+
/** Configured role globs; see {@link loadRoleGlobs}. */
|
|
563
|
+
roleGlobs?: RoleGlobs;
|
|
550
564
|
}
|
|
565
|
+
/** Read `<rootDir>/.codewatch/roles.json`; a repo without one configures no globs. */
|
|
566
|
+
declare function loadRoleGlobs(rootDir: string, source?: IndexSource): RoleGlobs;
|
|
551
567
|
interface ReadFileLike {
|
|
552
568
|
filePath: string;
|
|
553
569
|
content: string;
|
|
@@ -558,9 +574,17 @@ interface ReadFileLike {
|
|
|
558
574
|
* `.gitattributes linguist-generated` under `idRoot` plus filename/path
|
|
559
575
|
* heuristics). Lives here so the indexer stays at its file-size ceiling.
|
|
560
576
|
*/
|
|
561
|
-
declare function computeRoleHints(readFiles: readonly ReadFileLike[], idRoot: string, toId: (root: string, filePath: string) => string): AnnotateRolesOptions;
|
|
577
|
+
declare function computeRoleHints(readFiles: readonly ReadFileLike[], idRoot: string, toId: (root: string, filePath: string) => string, source?: IndexSource): AnnotateRolesOptions;
|
|
562
578
|
declare function annotateRoles(nodes: readonly GraphNode[], options?: AnnotateRolesOptions): GraphNode[];
|
|
563
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Roles of files nothing imports by design, so reachability and dead-export
|
|
582
|
+
* reports treat them as roots. One list, typed by role, so a new role cannot be
|
|
583
|
+
* added to one report and missed in another. It lives apart from `roles.ts`,
|
|
584
|
+
* which reads files, so browser-safe report code can import it.
|
|
585
|
+
*/
|
|
586
|
+
declare const UNIMPORTED_ROLES: ReadonlySet<NodeRole>;
|
|
587
|
+
|
|
564
588
|
/** True when a path looks generated by filename/dir convention alone. */
|
|
565
589
|
declare function isGeneratedByHeuristic(id: string): boolean;
|
|
566
590
|
/**
|
|
@@ -570,7 +594,7 @@ declare function isGeneratedByHeuristic(id: string): boolean;
|
|
|
570
594
|
*/
|
|
571
595
|
declare function isGeneratedFile(id: string, patterns: readonly RegExp[]): boolean;
|
|
572
596
|
/** Read `<rootDir>/.gitattributes` and compile its linguist-generated patterns. */
|
|
573
|
-
declare function loadGeneratedPatterns(rootDir: string): RegExp[];
|
|
597
|
+
declare function loadGeneratedPatterns(rootDir: string, source?: IndexSource): RegExp[];
|
|
574
598
|
|
|
575
599
|
declare function canonicalMetricName(name: string): string;
|
|
576
600
|
declare function canonicalRole(name: string): NodeRole;
|
|
@@ -699,36 +723,6 @@ declare const SYMBOL_METRIC_NAMES: readonly string[];
|
|
|
699
723
|
*/
|
|
700
724
|
declare const EXCEPTION_METRIC_NAMES: readonly string[];
|
|
701
725
|
|
|
702
|
-
/** How a test↔source pairing was inferred. */
|
|
703
|
-
type LinkMethod = "path" | "coedit";
|
|
704
|
-
interface TestSourceLink {
|
|
705
|
-
/** Node id of the test file. */
|
|
706
|
-
testId: string;
|
|
707
|
-
/** Node id of the (non-test) file it covers. */
|
|
708
|
-
sourceId: string;
|
|
709
|
-
method: LinkMethod;
|
|
710
|
-
}
|
|
711
|
-
interface LinkTestsOptions {
|
|
712
|
-
/** Minimum co-edit count for a pass-2 (coedit) link. Default 2. */
|
|
713
|
-
minCoEditCount?: number;
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Two-pass test↔source linker. Pass 1 pairs each test file with non-test files
|
|
717
|
-
* matching its path conventions (high confidence). Pass 2 supplements tests
|
|
718
|
-
* left unpaired by pass 1 with their strongest co-edited non-test partner from
|
|
719
|
-
* change-coupling. Handles orphan tests (no pairing), orphan/untested sources
|
|
720
|
-
* (no incoming link), and one-to-many pairings (a test matching several
|
|
721
|
-
* sources, or a source covered by several tests).
|
|
722
|
-
*/
|
|
723
|
-
declare function linkTestsToSources(nodes: readonly GraphNode[], coEditPairs: readonly CoEditPair[], options?: LinkTestsOptions): TestSourceLink[];
|
|
724
|
-
/**
|
|
725
|
-
* Per-source coverage breadth: how many distinct test files link to each
|
|
726
|
-
* covered source. Emitted only for sources with at least one linked test.
|
|
727
|
-
*/
|
|
728
|
-
declare function testCoverageCountMetrics(links: readonly TestSourceLink[]): GraphMetric[];
|
|
729
|
-
/** Map each covered source to the set of test files that link to it. */
|
|
730
|
-
declare function groupTestsBySource(links: readonly TestSourceLink[]): Map<string, Set<string>>;
|
|
731
|
-
|
|
732
726
|
interface HistoryMetricsOptions {
|
|
733
727
|
/** Primary window: scopes ownership. Default 30. */
|
|
734
728
|
churnWindowDays?: number;
|
|
@@ -738,6 +732,8 @@ interface HistoryMetricsOptions {
|
|
|
738
732
|
includeLifetime?: boolean;
|
|
739
733
|
/** Epoch seconds that windows end at; defaults to the current time. */
|
|
740
734
|
nowEpoch?: number;
|
|
735
|
+
/** Read history up to this rev instead of HEAD; pair it with the rev's commit time as `nowEpoch`. */
|
|
736
|
+
rev?: string;
|
|
741
737
|
}
|
|
742
738
|
/** Windows the dashboard switcher offers; churn is stored for each by default. */
|
|
743
739
|
declare const DEFAULT_CHURN_WINDOWS: number[];
|
|
@@ -870,6 +866,29 @@ interface SymbolSpan {
|
|
|
870
866
|
*/
|
|
871
867
|
declare function attributeCoverage(coverage: IstanbulCoverage, fileIdOf: (absPath: string) => string | null, symbolsByFile: ReadonlyMap<string, readonly SymbolSpan[]>): GraphMetric[];
|
|
872
868
|
|
|
869
|
+
type MinifyLanguage = "typescript" | "tsx" | "python";
|
|
870
|
+
/**
|
|
871
|
+
* Minified source plus its line map. `lineMap[i]` is the 1-based original line
|
|
872
|
+
* of output line `i + 1`; `originalLine` reads it by output line number.
|
|
873
|
+
*/
|
|
874
|
+
interface MinifiedSource {
|
|
875
|
+
text: string;
|
|
876
|
+
lineMap: number[];
|
|
877
|
+
}
|
|
878
|
+
/** The one line that stands in for a leading import block. */
|
|
879
|
+
declare function importMarker(count: number, language: MinifyLanguage): string;
|
|
880
|
+
/** The 1-based original line of a 1-based output line, or undefined past the end. */
|
|
881
|
+
declare function originalLine(minified: MinifiedSource, outputLine: number): number | undefined;
|
|
882
|
+
declare function isMinifyLanguage(language: string): language is MinifyLanguage;
|
|
883
|
+
/**
|
|
884
|
+
* Safe-minify source for LLM context: drops comments and docstrings, strips
|
|
885
|
+
* trailing whitespace, collapses blank-line runs and replaces a leading import
|
|
886
|
+
* block with `importMarker`. It never renames or dedents, so every kept line is
|
|
887
|
+
* its original line minus comments. Any other language comes back unchanged
|
|
888
|
+
* with an identity line map.
|
|
889
|
+
*/
|
|
890
|
+
declare function minifySource(text: string, language: string): Promise<MinifiedSource>;
|
|
891
|
+
|
|
873
892
|
/** Metric-name suffix for a window: `30d`, `180d`, or `lifetime`. */
|
|
874
893
|
declare function windowSuffix(window: ChurnWindow): string;
|
|
875
894
|
/**
|
|
@@ -933,159 +952,237 @@ interface RelevanceOptions {
|
|
|
933
952
|
*/
|
|
934
953
|
declare function computeRelevance(nodes: readonly GraphNode[], edges: readonly GraphEdge[], seedIds: readonly string[], options?: RelevanceOptions): Map<string, number>;
|
|
935
954
|
|
|
955
|
+
/** Marks a gap between two symbols that are not adjacent in their file. */
|
|
956
|
+
declare const ELISION_MARKER = "...";
|
|
957
|
+
/** Ends a line cut at `maxLineChars`; it counts toward the limit. */
|
|
958
|
+
declare const TRUNCATION_SUFFIX = "\u2026";
|
|
959
|
+
declare const DEFAULT_MAX_LINE_CHARS = 120;
|
|
960
|
+
interface SignatureTreeOptions {
|
|
961
|
+
maxLineChars?: number;
|
|
962
|
+
}
|
|
936
963
|
/**
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
*
|
|
940
|
-
* importing file, `dst` is the imported symbol node id (`<fileId>#<name>`).
|
|
941
|
-
*
|
|
942
|
-
* Two slices, both pure functions of the assembled reference edge set (a
|
|
943
|
-
* whole-graph rollup like utilization/PageRank, sound under incremental reuse
|
|
944
|
-
* since it reads the reassembled edges, not a per-file cache):
|
|
964
|
+
* Render symbols as a signatures-only tree for LLM context: per file (sorted by
|
|
965
|
+
* path) a header line, then one line per symbol, with `ELISION_MARKER` between
|
|
966
|
+
* symbols that are not adjacent. Pure; output is independent of input order.
|
|
945
967
|
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
interface
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
+
* A line is the symbol's `attrs.signature`, else `<name> (<kind>)`. Symbols
|
|
969
|
+
* order by `attrs.startLine`, then name, then id. A qualified name
|
|
970
|
+
* (`Job.run`) indents one level per dot. Symbols with no `startLine`
|
|
971
|
+
* (exported types and consts) render after the line-ordered ones, sorted by
|
|
972
|
+
* name then id, and get no elision markers because their position is unknown.
|
|
973
|
+
*/
|
|
974
|
+
declare function renderSignatureTree(nodes: readonly GraphNode[], options?: SignatureTreeOptions): string;
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* C-74 — deterministic per-file / per-symbol **context dossier** (Class A). A
|
|
978
|
+
* pure projection of the already-computed graph: no LLM, no source re-parse. The
|
|
979
|
+
* command layer (graph-context.ts) loads the snapshot and hands the assembled
|
|
980
|
+
* inputs here; this module owns only the shaping + the markdown render, so it is
|
|
981
|
+
* unit-testable on synthetic graphs.
|
|
982
|
+
*/
|
|
983
|
+
/** Bumped when the dossier shape changes, so a RAG store can invalidate records. */
|
|
984
|
+
declare const SCHEMA_VERSION = "2";
|
|
985
|
+
interface Provenance {
|
|
986
|
+
snapshotId: number;
|
|
987
|
+
ref: string;
|
|
988
|
+
commitHash: string | null;
|
|
989
|
+
takenAt: string;
|
|
990
|
+
indexVersion: string;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Consumers split by declaring-file role (C-74/G3): for core exports most inbound
|
|
994
|
+
* references are test files, which is truthful but low-signal for "what production
|
|
995
|
+
* code depends on this" — so source and test consumers are separated, not flattened.
|
|
996
|
+
*/
|
|
997
|
+
interface Consumers {
|
|
998
|
+
source: string[];
|
|
999
|
+
test: string[];
|
|
1000
|
+
counts: {
|
|
1001
|
+
source: number;
|
|
1002
|
+
test: number;
|
|
1003
|
+
total: number;
|
|
1004
|
+
};
|
|
1005
|
+
note: string;
|
|
1006
|
+
}
|
|
1007
|
+
interface FileOwnership {
|
|
1008
|
+
primaryOwner: string;
|
|
1009
|
+
busFactor: number;
|
|
1010
|
+
authorCount: number;
|
|
1011
|
+
}
|
|
1012
|
+
/** One of a file's declared symbols, projected for the dossier. */
|
|
1013
|
+
interface SymbolLine {
|
|
968
1014
|
name: string;
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
bId: string;
|
|
978
|
-
bFile: string;
|
|
979
|
-
bName: string;
|
|
980
|
-
/** Distinct files that import both symbols. */
|
|
981
|
-
coImports: number;
|
|
982
|
-
/** True when the two symbols are declared in different files. */
|
|
983
|
-
crossFile: boolean;
|
|
984
|
-
}
|
|
985
|
-
interface SymbolCouplingOptions {
|
|
986
|
-
/** Skip pairs co-imported by fewer than this many files. Default 2. */
|
|
987
|
-
minCoImports?: number;
|
|
1015
|
+
exported: boolean;
|
|
1016
|
+
/** One-line type signature (C-79), when indexed for this declaration. */
|
|
1017
|
+
signature?: string;
|
|
1018
|
+
cognitive?: number;
|
|
1019
|
+
cyclomatic?: number;
|
|
1020
|
+
utilization: number;
|
|
1021
|
+
/** Distinct files that reference this symbol (inbound `references`). */
|
|
1022
|
+
consumers: number;
|
|
988
1023
|
/**
|
|
989
|
-
*
|
|
990
|
-
*
|
|
991
|
-
*
|
|
1024
|
+
* Symbol-level importance (C-89): the declaring file's PageRank centrality
|
|
1025
|
+
* redistributed across its symbols by utilization share, so a graph-central
|
|
1026
|
+
* file's rank lands on the definitions actually carrying its inbound use.
|
|
992
1027
|
*/
|
|
993
|
-
|
|
1028
|
+
importance?: number;
|
|
994
1029
|
}
|
|
1030
|
+
interface SymbolDossier {
|
|
1031
|
+
exported: boolean;
|
|
1032
|
+
/** G1 slot — the one-line type signature indexed from `attrs.signature` (C-79); null when unannotated or unresolvable. */
|
|
1033
|
+
signature: string | null;
|
|
1034
|
+
/** G2 slot — leading docstring / intent. Null today. */
|
|
1035
|
+
purpose: string | null;
|
|
1036
|
+
complexity: {
|
|
1037
|
+
cognitive?: number;
|
|
1038
|
+
cyclomatic?: number;
|
|
1039
|
+
};
|
|
1040
|
+
utilization: number;
|
|
1041
|
+
consumers: Consumers;
|
|
1042
|
+
blastRadius: number;
|
|
1043
|
+
coupledWith: {
|
|
1044
|
+
symbolId: string;
|
|
1045
|
+
name: string;
|
|
1046
|
+
fileId: string;
|
|
1047
|
+
coImports: number;
|
|
1048
|
+
}[];
|
|
1049
|
+
}
|
|
1050
|
+
interface FileDossier {
|
|
1051
|
+
metrics: NodeMetrics;
|
|
1052
|
+
churn: {
|
|
1053
|
+
windowDays: number;
|
|
1054
|
+
value: number;
|
|
1055
|
+
} | null;
|
|
1056
|
+
centrality: number;
|
|
1057
|
+
ownership: FileOwnership | null;
|
|
1058
|
+
symbols: SymbolLine[];
|
|
1059
|
+
dependsOn: string[];
|
|
1060
|
+
consumers: Consumers;
|
|
1061
|
+
blastRadius: BlastRadiusEntry[];
|
|
1062
|
+
}
|
|
1063
|
+
interface ContextDossier {
|
|
1064
|
+
schemaVersion: string;
|
|
1065
|
+
target: {
|
|
1066
|
+
id: string;
|
|
1067
|
+
kind: "file" | "symbol";
|
|
1068
|
+
name: string;
|
|
1069
|
+
path: string;
|
|
1070
|
+
span?: {
|
|
1071
|
+
startLine: number;
|
|
1072
|
+
endLine: number;
|
|
1073
|
+
};
|
|
1074
|
+
};
|
|
1075
|
+
provenance: Provenance;
|
|
1076
|
+
symbol?: SymbolDossier;
|
|
1077
|
+
file?: FileDossier;
|
|
1078
|
+
notes: string[];
|
|
1079
|
+
}
|
|
1080
|
+
interface ContextBuildInput {
|
|
1081
|
+
target: GraphNode;
|
|
1082
|
+
kind: "file" | "symbol";
|
|
1083
|
+
provenance: Provenance;
|
|
1084
|
+
/** All nodes for the snapshot, symbols INCLUDED. */
|
|
1085
|
+
nodes: readonly GraphNode[];
|
|
1086
|
+
/** `references` edges as {srcId=importing file, dstId=symbol id}. */
|
|
1087
|
+
refEdges: readonly ReferenceEdgeLite[];
|
|
1088
|
+
/** `imports` edges as {srcId, dstId} (file → file/external). */
|
|
1089
|
+
importEdges: readonly {
|
|
1090
|
+
srcId: string;
|
|
1091
|
+
dstId: string;
|
|
1092
|
+
}[];
|
|
1093
|
+
metrics: ReadonlyMap<string, NodeMetrics>;
|
|
1094
|
+
churnByFile: ReadonlyMap<string, number>;
|
|
1095
|
+
churnWindowDays: number;
|
|
1096
|
+
centrality: ReadonlyMap<string, number>;
|
|
1097
|
+
ownership: ReadonlyMap<string, FileOwnership> | null;
|
|
1098
|
+
/** File id → node role, for splitting consumers into source vs test (G3). */
|
|
1099
|
+
roleByFile: ReadonlyMap<string, string>;
|
|
1100
|
+
}
|
|
1101
|
+
declare function buildContextDossier(input: ContextBuildInput): ContextDossier;
|
|
1102
|
+
|
|
995
1103
|
/**
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
*
|
|
999
|
-
*/
|
|
1000
|
-
declare function computeSymbolConsumers(edges: readonly ReferenceEdgeLite[]): SymbolConsumers[];
|
|
1001
|
-
/**
|
|
1002
|
-
* Every pair of symbols co-imported by the same file becomes a coupling pair,
|
|
1003
|
-
* counted by how many distinct files co-import them (Slice B). Wide importers
|
|
1004
|
-
* are dropped to keep the pairing near-linear. Sorted by co-import count desc,
|
|
1005
|
-
* cross-file pairs preferred at a tie (they are the actionable ones — a
|
|
1006
|
-
* same-file pair is just cohesion within one module).
|
|
1104
|
+
* Human/agent-readable markdown projection of a {@link ContextDossier} (C-74).
|
|
1105
|
+
* The JSON form is the RAG-store record; this is the same facts rendered for a
|
|
1106
|
+
* reader (or an agent that prefers prose). Deterministic — no LLM.
|
|
1007
1107
|
*/
|
|
1008
|
-
declare function
|
|
1108
|
+
declare function renderContextMarkdown(d: ContextDossier): string;
|
|
1009
1109
|
|
|
1010
1110
|
/**
|
|
1011
|
-
*
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1015
|
-
*
|
|
1016
|
-
*
|
|
1017
|
-
*
|
|
1018
|
-
*
|
|
1019
|
-
* See C-8 task notes for the design rationale and empirical calibration
|
|
1020
|
-
* data from the 2026-05-21 codewatch dogfood.
|
|
1111
|
+
* C-80 — the **context bundle**: one deterministic pull of the complete paired
|
|
1112
|
+
* context for a symbol/file, the push half of the ingestion API. It wraps the
|
|
1113
|
+
* C-74 dossier with the three things an ingestor needs to embed/answer WITHOUT
|
|
1114
|
+
* opening the file: the raw **source chunk** (source text of the span), the
|
|
1115
|
+
* resolved **graph linkages as explicit edges** (callers / dependencies /
|
|
1116
|
+
* coupled-with — not just counts), and **coverage** (C-63, when the overlay is
|
|
1117
|
+
* ingested). No LLM; a pure projection of the graph + the working-tree source.
|
|
1021
1118
|
*/
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
/**
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
* When true, edges landing on a barrel file are resolved through its
|
|
1035
|
-
* re-export chain to the underlying source files. The cheap implementation
|
|
1036
|
-
* fans each barrel import into N synthetic edges (one per re-export
|
|
1037
|
-
* target), which over-attributes — a single `import { x } from "./pkg"`
|
|
1038
|
-
* becomes N edges as if every re-export were used. Default false until
|
|
1039
|
-
* a weighted or symbol-tracking version is available.
|
|
1040
|
-
*/
|
|
1041
|
-
resolveBarrels?: boolean;
|
|
1042
|
-
}
|
|
1043
|
-
type PackageFlag = "weak-boundary";
|
|
1044
|
-
type PairFlag = "tight" | "moderate" | "none";
|
|
1045
|
-
type PackageLayer = "top" | "middle" | "foundation";
|
|
1046
|
-
interface PackageStats {
|
|
1047
|
-
pkgId: string;
|
|
1048
|
-
fileCount: number;
|
|
1049
|
-
internalEdges: number;
|
|
1050
|
-
outgoingEdges: number;
|
|
1051
|
-
incomingEdges: number;
|
|
1052
|
-
/** internal / (internal + outgoing) — higher = more self-contained. */
|
|
1053
|
-
cohesion: number;
|
|
1054
|
-
/** outgoing / (outgoing + incoming) — Martin's I metric at the package level. */
|
|
1055
|
-
instability: number;
|
|
1056
|
-
/**
|
|
1057
|
-
* Abstractness proxy A ∈ [0,1]: share of the package's files with role
|
|
1058
|
-
* "types" (dedicated type/interface definitions). codewatch has no
|
|
1059
|
-
* symbol-level abstract/concrete counts, so this file-role ratio stands in
|
|
1060
|
-
* for Martin's A. Enables the instability×abstractness main-sequence plot.
|
|
1061
|
-
*/
|
|
1062
|
-
abstractness: number;
|
|
1063
|
-
layer: PackageLayer;
|
|
1064
|
-
flags: PackageFlag[];
|
|
1119
|
+
declare const BUNDLE_SCHEMA_VERSION = "2";
|
|
1120
|
+
interface SourceChunk {
|
|
1121
|
+
/** Repo-relative file id the chunk was read from. */
|
|
1122
|
+
path: string;
|
|
1123
|
+
/** 1-based inclusive line span for a symbol; null for a whole-file target. */
|
|
1124
|
+
span: {
|
|
1125
|
+
startLine: number;
|
|
1126
|
+
endLine: number;
|
|
1127
|
+
} | null;
|
|
1128
|
+
/** The source text, or null when the file could not be read. */
|
|
1129
|
+
text: string | null;
|
|
1130
|
+
note?: string;
|
|
1065
1131
|
}
|
|
1066
|
-
|
|
1132
|
+
/** A resolved graph linkage, deterministic and directional relative to the target. */
|
|
1133
|
+
interface BundleEdge {
|
|
1067
1134
|
from: string;
|
|
1068
1135
|
to: string;
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1136
|
+
kind: string;
|
|
1137
|
+
weight: number;
|
|
1138
|
+
/**
|
|
1139
|
+
* Seeded-PageRank relevance of this edge's neighbour to the target (C-89).
|
|
1140
|
+
* Present only when the target was seeded (the bundle path); the neighbour is
|
|
1141
|
+
* whichever endpoint is not the target's file. Edges are ordered by it, so the
|
|
1142
|
+
* most target-relevant linkages lead, not the globally-famous ones.
|
|
1143
|
+
*/
|
|
1144
|
+
relevance?: number;
|
|
1145
|
+
}
|
|
1146
|
+
interface BundleEdges {
|
|
1147
|
+
/** Inbound — who references/imports the target. */
|
|
1148
|
+
callers: BundleEdge[];
|
|
1149
|
+
/** Outbound — what the target references/imports. */
|
|
1150
|
+
dependencies: BundleEdge[];
|
|
1151
|
+
/** Co-import coupling partners (symbol targets only). */
|
|
1152
|
+
coupledWith: BundleEdge[];
|
|
1153
|
+
note: string;
|
|
1154
|
+
}
|
|
1155
|
+
interface Coverage {
|
|
1156
|
+
pct: number | null;
|
|
1157
|
+
note?: string;
|
|
1073
1158
|
}
|
|
1074
|
-
interface
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
flagsCount: number;
|
|
1159
|
+
interface ContextBundle {
|
|
1160
|
+
schemaVersion: string;
|
|
1161
|
+
dossier: ContextDossier;
|
|
1162
|
+
source: SourceChunk;
|
|
1163
|
+
edges: BundleEdges;
|
|
1164
|
+
coverage: Coverage;
|
|
1081
1165
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1166
|
+
interface BundleBuildInput {
|
|
1167
|
+
dossier: ContextDossier;
|
|
1168
|
+
target: GraphNode;
|
|
1169
|
+
kind: "file" | "symbol";
|
|
1170
|
+
/** Weighted `references` edges (srcId = importing file → dstId = symbol id). */
|
|
1171
|
+
refEdges: readonly GraphEdge[];
|
|
1172
|
+
/** Weighted `imports` edges (file → file/external). */
|
|
1173
|
+
importEdges: readonly GraphEdge[];
|
|
1174
|
+
/** Git toplevel to resolve the source path, or null (read relative to cwd). */
|
|
1175
|
+
repoRoot: string | null;
|
|
1176
|
+
/** `coverage_pct` for the target node, or null when the overlay is absent. */
|
|
1177
|
+
coveragePct: number | null;
|
|
1178
|
+
/** File id → seeded-relevance score (C-89); absent/empty ⇒ weight-ordered cold path. */
|
|
1179
|
+
relevanceByFile?: ReadonlyMap<string, number>;
|
|
1180
|
+
/** The target's declaring file id, for locating each edge's neighbour (C-89). */
|
|
1181
|
+
targetFileId?: string;
|
|
1182
|
+
}
|
|
1183
|
+
declare function buildContextBundle(input: BundleBuildInput): ContextBundle;
|
|
1184
|
+
/** Concatenated text projection — hand this straight to an embedder/LLM. */
|
|
1185
|
+
declare function renderBundleText(bundle: ContextBundle): string;
|
|
1089
1186
|
|
|
1090
1187
|
/**
|
|
1091
1188
|
* PageRank over one snapshot's file-level graph (symbol nodes and `references`
|
|
@@ -1160,111 +1257,6 @@ declare function describeMetrics(names: Iterable<string>): {
|
|
|
1160
1257
|
unknown: string[];
|
|
1161
1258
|
};
|
|
1162
1259
|
|
|
1163
|
-
type Severity = "error" | "warning";
|
|
1164
|
-
interface MetricMaxRule {
|
|
1165
|
-
type: "metric-max";
|
|
1166
|
-
id: string;
|
|
1167
|
-
metric: string;
|
|
1168
|
-
max: number;
|
|
1169
|
-
kind?: NodeKind;
|
|
1170
|
-
severity?: Severity;
|
|
1171
|
-
exclude?: string[];
|
|
1172
|
-
excludeRoles?: NodeRole[];
|
|
1173
|
-
}
|
|
1174
|
-
interface MetricMinRule {
|
|
1175
|
-
type: "metric-min";
|
|
1176
|
-
id: string;
|
|
1177
|
-
metric: string;
|
|
1178
|
-
min: number;
|
|
1179
|
-
kind?: NodeKind;
|
|
1180
|
-
severity?: Severity;
|
|
1181
|
-
exclude?: string[];
|
|
1182
|
-
excludeRoles?: NodeRole[];
|
|
1183
|
-
}
|
|
1184
|
-
interface MetricProductMaxRule {
|
|
1185
|
-
type: "metric-product-max";
|
|
1186
|
-
id: string;
|
|
1187
|
-
metrics: string[];
|
|
1188
|
-
max: number;
|
|
1189
|
-
kind?: NodeKind;
|
|
1190
|
-
severity?: Severity;
|
|
1191
|
-
exclude?: string[];
|
|
1192
|
-
excludeRoles?: NodeRole[];
|
|
1193
|
-
}
|
|
1194
|
-
/** Flags nodes whose value sits strictly above the given percentile of the metric over every node of the kind. */
|
|
1195
|
-
interface MetricOutlierRule {
|
|
1196
|
-
type: "metric-outlier";
|
|
1197
|
-
id: string;
|
|
1198
|
-
metric: string;
|
|
1199
|
-
kind: NodeKind;
|
|
1200
|
-
/** 50 to 100; the threshold interpolates linearly between the two nearest ranked values. */
|
|
1201
|
-
percentile: number;
|
|
1202
|
-
/** Fewest nodes that must carry the metric before any is judged; defaults to 20. */
|
|
1203
|
-
minSample?: number;
|
|
1204
|
-
/** A node is flagged only if its value also exceeds this absolute floor, guarding sparse metrics whose percentile sits at or near zero. */
|
|
1205
|
-
floor?: number;
|
|
1206
|
-
/** When true, rank and gate on the pool of carriers with a non-zero value only; zero-valued nodes are never flagged. */
|
|
1207
|
-
rankNonZero?: boolean;
|
|
1208
|
-
severity?: Severity;
|
|
1209
|
-
}
|
|
1210
|
-
interface ForbidImportRule {
|
|
1211
|
-
type: "forbid-import";
|
|
1212
|
-
id: string;
|
|
1213
|
-
from: string;
|
|
1214
|
-
to: string;
|
|
1215
|
-
severity?: Severity;
|
|
1216
|
-
}
|
|
1217
|
-
interface LayeredDepsRule {
|
|
1218
|
-
type: "layered-deps";
|
|
1219
|
-
id: string;
|
|
1220
|
-
layers: string[][];
|
|
1221
|
-
severity?: Severity;
|
|
1222
|
-
}
|
|
1223
|
-
interface NoInternalOnlyBarrelsRule {
|
|
1224
|
-
type: "no-internal-only-barrels";
|
|
1225
|
-
id: string;
|
|
1226
|
-
/** Path prefixes marking package roots; node ids carry no intrinsic package membership. */
|
|
1227
|
-
packageRoots: string[];
|
|
1228
|
-
severity?: Severity;
|
|
1229
|
-
/** Globs or substrings to skip, such as CLI bin entries the role classifier calls barrels. */
|
|
1230
|
-
exclude?: string[];
|
|
1231
|
-
}
|
|
1232
|
-
type CheckRule = MetricMaxRule | MetricMinRule | MetricProductMaxRule | MetricOutlierRule | ForbidImportRule | LayeredDepsRule | NoInternalOnlyBarrelsRule;
|
|
1233
|
-
interface CheckRulesFile {
|
|
1234
|
-
rules: CheckRule[];
|
|
1235
|
-
}
|
|
1236
|
-
interface CheckViolation {
|
|
1237
|
-
ruleId: string;
|
|
1238
|
-
severity: Severity;
|
|
1239
|
-
nodeId: string;
|
|
1240
|
-
message: string;
|
|
1241
|
-
metric?: string;
|
|
1242
|
-
value?: number;
|
|
1243
|
-
threshold?: number;
|
|
1244
|
-
destinationId?: string;
|
|
1245
|
-
isCarryover?: boolean;
|
|
1246
|
-
/** Repo-relative file the violation sits in; a symbol's parent file. */
|
|
1247
|
-
path?: string;
|
|
1248
|
-
lineStart?: number;
|
|
1249
|
-
lineEnd?: number;
|
|
1250
|
-
symbol?: string;
|
|
1251
|
-
/** One line a reader can check without re-running the rule, such as `loc=412 (max 350)`. */
|
|
1252
|
-
evidence?: string;
|
|
1253
|
-
tool?: string;
|
|
1254
|
-
}
|
|
1255
|
-
interface CheckResult {
|
|
1256
|
-
snapshotId: number;
|
|
1257
|
-
baselineSnapshotId?: number;
|
|
1258
|
-
rulesEvaluated: number;
|
|
1259
|
-
nodesEvaluated: number;
|
|
1260
|
-
violations: CheckViolation[];
|
|
1261
|
-
newErrors: number;
|
|
1262
|
-
newWarnings: number;
|
|
1263
|
-
carryoverErrors: number;
|
|
1264
|
-
carryoverWarnings: number;
|
|
1265
|
-
passed: boolean;
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
1260
|
/** The three whole-snapshot reads rule evaluation needs; any store with them can be checked. */
|
|
1269
1261
|
type RuleStore = Pick<CodeGraphStore, "listNodes" | "listEdges" | "listMetrics">;
|
|
1270
1262
|
|
|
@@ -1276,10 +1268,6 @@ interface RunChecksOptions {
|
|
|
1276
1268
|
declare function runChecks(store: CodeGraphStore, options: RunChecksOptions): CheckResult;
|
|
1277
1269
|
/** Every rule's violations in one snapshot with no baseline; needs only the three whole-snapshot reads. */
|
|
1278
1270
|
declare function snapshotViolations(store: RuleStore, snapshotId: number, rules: readonly CheckRule[]): CheckViolation[];
|
|
1279
|
-
/** Identity of a violation across snapshots: severity, value and message may change, the key does not. */
|
|
1280
|
-
declare function violationKey(v: CheckViolation): string;
|
|
1281
|
-
/** {@link violationKey} with both node ids carried into another snapshot's id space; unmoved ids key as before. */
|
|
1282
|
-
declare function rebasedViolationKey(v: CheckViolation, resolve: (id: string) => string): string;
|
|
1283
1271
|
|
|
1284
1272
|
/** One tool-neutral audit finding; every finding cites a path so a citation checker can verify it. */
|
|
1285
1273
|
interface Finding {
|
|
@@ -1468,20 +1456,10 @@ interface DiffSnapshotsOptions {
|
|
|
1468
1456
|
*/
|
|
1469
1457
|
declare function diffSnapshots(store: CodeGraphStore, options: DiffSnapshotsOptions): GraphDiff;
|
|
1470
1458
|
|
|
1471
|
-
interface
|
|
1472
|
-
from: CheckViolation;
|
|
1473
|
-
to: CheckViolation;
|
|
1474
|
-
delta: number | null;
|
|
1475
|
-
}
|
|
1476
|
-
interface CheckDiff {
|
|
1459
|
+
interface CheckDiff extends ViolationBuckets {
|
|
1477
1460
|
fromSnapshotId: number;
|
|
1478
1461
|
toSnapshotId: number;
|
|
1479
1462
|
rulesEvaluated: number;
|
|
1480
|
-
newViolations: CheckViolation[];
|
|
1481
|
-
resolvedViolations: CheckViolation[];
|
|
1482
|
-
unchanged: UnchangedViolation[];
|
|
1483
|
-
worsened: UnchangedViolation[];
|
|
1484
|
-
improved: UnchangedViolation[];
|
|
1485
1463
|
}
|
|
1486
1464
|
interface DiffCheckResultsOptions {
|
|
1487
1465
|
fromSnapshotId: number;
|
|
@@ -1802,4 +1780,4 @@ declare function getConventionMap(store: CodeGraphStore, snapshotId: number, mod
|
|
|
1802
1780
|
*/
|
|
1803
1781
|
declare function findConventions(store: CodeGraphStore, snapshotId: number, query: string, embedder: Embedder, model: string, opts?: FindConventionsOptions): Promise<ConventionQueryResult>;
|
|
1804
1782
|
|
|
1805
|
-
export { ALIAS_BASE_ATTR, ALL_ROLES, type AliasChain, type AliasChainInput, type AliasChainOptions, type AliasLoader, type AliasResolution, COMMUNITY_SUMMARY_NAMESPACE, COVERAGE_METRIC_NAME, type CachedEmbedResult, type CheckDiff,
|
|
1783
|
+
export { ALIAS_BASE_ATTR, ALL_ROLES, type AliasChain, type AliasChainInput, type AliasChainOptions, type AliasLoader, type AliasResolution, type AnnotateRolesOptions, BUNDLE_SCHEMA_VERSION, BlastRadiusEntry, type BundleBuildInput, type BundleEdge, type BundleEdges, COMMUNITY_SUMMARY_NAMESPACE, SCHEMA_VERSION as CONTEXT_SCHEMA_VERSION, COVERAGE_METRIC_NAME, type CachedEmbedResult, type CheckDiff, CheckResult, CheckRule, type CheckSnapshotOptions, type CheckSnapshotResult, CheckViolation, CodeGraphStore, type Consumers, type ContextBuildInput, type ContextBundle, type ContextDossier, type ConventionArea, type ConventionCorpus, type ConventionCoverage, type ConventionMap, type ConventionMatch, type ConventionOptions, type ConventionQueryResult, type ConventionSymbol, type Coverage, DEAD_CODE_METRIC_NAMES, DEFAULT_CHURN_WINDOWS, DEFAULT_MAX_LINE_CHARS, DEFAULT_OUTLIER_MIN_SAMPLE, DOMAIN_DDL, type DeepAst, type DeepAstInput, type DiffCheckResultsOptions, type DiffFootprintsOptions, type DiffSnapshotsOptions, ELISION_MARKER, EXCEPTION_METRIC_NAMES, EdgeKind, type EmbedAttempt, type EmbedCoverage, type EmbedSnapshotResult, type EmbeddableSymbol, type ExternalDiagnostic, FINDING_DDL, type FileDossier, FileFingerprint, type FileOwnership, type FindConventionsOptions, type FindSimilarOptions, type Finding, type FindingKeyInput, type FootprintChange, type FootprintChangeReason, type FootprintDiff, type FootprintGraph, type FootprintOptions, type FootprintParts, type FootprintUnit, GROWTH_RISK_METRIC_NAMES, type GateResult, type GateUnitsInput, type GraphDiff, type GraphDiffSummary, GraphEdge, GraphFragment, GraphMetric, GraphNode, type HistoryMetricsOptions, INDEX_VERSION, IdAlias, IdAliasReason, type IndexOptions, type IndexResult, type IndexSource, type IstanbulCoverage, KIT, LanguageExtractor, type LanguageExtractorOptions, type LineSpan, type Lineage, type LineageSnapshot, type LineageStep, type LoadedHistory, METRIC_CATALOGUE, MIGRATIONS, type MemberInfo, type MetricAbsence, type MetricAggregate, type MetricDelta, type MetricDescriptor, type MetricDirection, type MetricRollup, type MetricSource, type MetricUnit, type MinifiedSource, type MinifyLanguage, NodeKind, NodeMetrics, type NodeRename, NodeRole, type PageRankOptions, type PageRankResult, type PageRankRow, type ParamInfo, type PriorSnapshotOptions, type Provenance, type PruneOptions, type PrunePlan, type PruneResult, PythonGraphExtractor, type ReadFile, ReferenceEdgeLite, type RegenerateReason, type RelevanceOptions, type ResolveAliasOptions, type ReuseBasis, type RoleGlobs, type RoleHints, type RuleStore, type RunChecksOptions, SCHEMA_VERSION$1 as SCHEMA_VERSION, SNAPSHOT_SCOPED_TABLES, SOURCE_METRIC_NAMES, SYMBOL_EMBEDDING_NAMESPACE, SYMBOL_ID_SEP, SYMBOL_METRIC_NAMES, Severity, type SignatureTreeOptions, type SimilarCandidate, type SimilarResult, type SnapshotInsert, SnapshotRow, type SnapshotSpec, type SourceChunk, type SourceLanguage, type StoredFinding, type StoredVerdict, type SummarizeConventionsResult, type Summarizer, SymbolConsumers, SymbolCouplingOptions, SymbolCouplingPair, type SymbolDossier, type SymbolFootprint, type SymbolLine, type SymbolSpan, TRUNCATION_SUFFIX, type TestCoverageOwnershipOptions, TestSourceLink, type TopMetricRow, TsMorphGraphExtractor, type TsMorphGraphExtractorOptions, UNIMPORTED_ROLES, type UnitProvenance, type UnitProvenanceInput, type UnitRegeneration, type ValidateRulesOptions, type VerdictCitation, type VerdictLabel, ViolationBuckets, aggregateMetrics, aliasChain, annotateRoles, attributeCoverage, buildAliases, buildContextBundle, buildContextDossier, buildConventionAreas, buildEmbedText, buildFileModuleNodes, buildIndexerMetrics, buildLineage, canonicalEdgeKind, canonicalMetricName, canonicalRole, carryForwardVerdicts, checkSnapshot, classifyRole, collectDeclaredNames, collectDeclaredSpans, compilePatterns, computeDeadCodeMetrics, computeDeepAst, computeFootprints, computeGrowthRiskMetrics, computeMetrics, computePageRank, computeRecencyWindows, computeRelevance, computeRoleHints, computeSourceMetrics, computeTestCoverageOwnership, createAliasChain, defaultTargetCount, describeMetric, describeMetrics, detectCommunities, detectGitHead, detectGitToplevel, detectRenames, diffCheckResults, diffFootprints, diffSnapshots, edgeWeight, embedSnapshot, embedTextsCached, externalId, externalToFinding, fileId, findConventions, findSimilarCapability, findingKey, gateUnits, getConventionMap, getEdgeWeight, gitTreeSource, hashContent, hashEmbedText, hashText, importMarker, indexPaths, isGeneratedByHeuristic, isGeneratedFile, isInsideGitRepo, isMinifyLanguage, keyFindings, lineagePath, listEdges, listEdgesTouching, listEmbeddableSymbols, listFindings, listMetrics, listMetricsForNode, listNodes, listVerdicts, loadCheckRules, loadGeneratedPatterns, loadHistoryMetrics, loadLineage, loadRoleGlobs, matchesAny, minifySource, moduleId, normalizeFlaggedText, openCodeGraph, originalLine, packageId, parentModuleId, parseSymbolId, patternToRegex, percentileOf, planPrune, priorSnapshotForRef, pruneDanglingReferences, readSourceFiles, renderBundleText, renderContextMarkdown, renderSignatureTree, resolveAlias, resolveBarrelEdges, resolveChurnWindows, resolveGitRef, resolveSnapshot, runChecks, runPrune, saveFindings, saveVerdicts, snapshotPageRank, snapshotReferenceEdges, snapshotRelevance, snapshotSymbolConsumers, snapshotSymbolCoupling, snapshotViolations, structuralSignature, summarizeConventions, symbolId, symbolSetHash, toFindings, tryEmbedSnapshot, unitProvenance, validateRules, walkSourceFiles, windowSuffix, workingTreeSource };
|